一.? 简介
上一章我们编写了基于设备树的
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
。