一. 简介
 上一章我们编写了基于设备树的  LED  驱动,但是驱动的本质还是没变,都是配置  LED  灯所使用的  GPIO  寄存器,驱动开发方式和裸机基本没啥区别。 Linux  是一个庞大而完善的系统, 尤其是驱动框架,像  GPIO 这种最基本的驱动不可能采用“原始”的裸机驱动开发方式, Linux  内核提供了 pinctrl  和  gpio  子系统用于  GPIO  驱动。 
 
 
接下来,我们就来学习一下如何借助 pinctrl 和 gpio 子系统来简化 GPIO 驱动开发。
本文我们来具体学习 pinctrl 子系统。
二. pinctrl 子系统简介
Linux 驱动讲究驱动分离与分层,pinctrl 和 gpio 子系统就是驱动分离与分层思想下的产物, 驱动分离与分层其实就是按照面向对象编程的设计思想而设计的设备驱动框架,关于驱动的分离与分层我们后面会讲。本来 pinctrl 和 gpio 子系统应该放到驱动分离与分层章节后面讲解,但是不管什么外设驱动,GPIO 驱动基本都是必须的,而 pinctrl 和 gpio 子系统又是 GPIO 驱动必须使用的,所以就将 pintrcl 和 gpio 子系统这一章节提前了。
 我们先来回顾一下上一章是怎么初始化  LED  灯所使用的  GPIO ,步骤如下:  
 
 ①、修改设备树,添加相应的节点,节点里面重点是设置  reg  属性, reg  属性包括了  GPIO  
 
 相关寄存器。  
 
 ② 、 获 取  reg  属 性 中  IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03  和  IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03  这两个寄存器地址,并且初始化这两个寄存器,这  两个寄存器用于设置  GPIO1_IO03  这个  PIN  的复用功能、上下拉、速度等。  
 
 ③、在②里面将  GPIO1_IO03  这个  PIN  复用为了  GPIO  功能,因此需要设置  GPIO1_IO03  这个  GPIO  相关的寄存器,也就是  GPIO1_DR  和  GPIO1_GDIR  这两个寄存器。  
 
 
 Linux  内核针对  PIN  的配置,推出了  pinctrl  子系统。对于  GPIO 的配置,推出了  gpio  子系统。 
 
 大多数  SOC  的  pin  都是支持复用的,比如,  I.MX6ULL  的  GPIO1_IO03  既可以作为普通的 GPIO  使用,也可以作为  I2C1  的  SDA  等等。此外,我们还需要配置  pin  的电气特性,例如,上 / 下 拉、速度、驱动能力等等。 
  传统的配置  pin  的方式,就是直接操作相应的寄存器,但是这种配置 方式比较繁琐、而且容易出问题 ( 比如  pin  功能冲突 ) 。 pinctrl  子系统就是为了解决这个问题而引 入的, pinctrl  子系统主要工作内容如下:  
   ①、获取设备树中  pin  信息。  
  ②、根据获取到的  pin  信息,来设置  pin  的复用功能。 
  ③、根据获取到的  pin  信息,来设置  pin  的电气特性,例如,上 / 下拉、速度、驱动能力等。  
     对于我们使用者来讲,只需要在设备树里面设置好某个  pin  的相关属性即可,其他的初始 化工作,均由  pinctrl  子系统来完成, pinctrl  子系统源码目录为  drivers/pinctrl 。