一、基础知识
Linux 是一个庞大而完善的系统,尤其是驱动框架,像 GPIO 这种最基本的驱动不可能采用“原始”的裸机驱动开发方式,Linux 内核提供了 pinctrl 和 gpio 子系统用于GPIO 驱动,借助 pinctrl 和 gpio 子系统来简化 GPIO 驱动开发。
传统的配置pin的方式就是直接操作寄存器,但是这种方式比较繁琐,而且容易出现pin的功能冲突,pinctrl子系统就是来解决这个问题的。pinctrl 子系统源码目录为 drivers/pinctrl。
pinctrl 子系统主要工作内容如下:
①、获取设备树中 pin 信息。
②、根据获取到的 pin 信息来设置 pin 的复用功能
③、根据获取到的 pin 信息来设置 pin 的电气特性,比如上/下拉、速度、驱动能力等。
gpio子系统用来配置gpio的输入输出等。
pinctrl配置流程:
在imx6ull.dtsi文件中,aips1节点下面,iomuxc节点定义了I.MX6ULL的外设信息
iomuxc: iomuxc@020e0000 {
compatible = "fsl,imx6ul-iomuxc";
reg = <0x020e0000 0x4000>;
};
我们自己的板子,外设信息肯定不能写在头文件里,要写在imx6ull-alientek-emmc.dts里面。通过&向iomuxc节点追加数据,每个外设都是imx6ul-evk板子的一个子节点,子节点里面包含PIN的复用功能和电气特性。
复用功能MX6UL_PAD_UART1_RTS_B__GPIO1_IO19其实是个宏定义,在#include “imx6ull.dtsi”-> #include "imx6ul-pinfunc.h"中。
二、如何使用pinctrl和gpio子系统
我们就以操作led灯为例,使用这两个子系统初始化led灯的引脚,分为两步,首先配置复用功能,然后在根节点创建设备节点
1.设置引脚复用,在imx6ull-alientek-emmc.dts设备树文件中,iomuxc节点中加入以下节点
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03定义在头文件#include “imx6ull.dtsi” -> #include “imx6ull-pinfunc.h” -> #include “imx6ul-pinfunc.h”
这五个值代表。。。文件的注释做的比较清楚
mux_reg代表复用寄存器地址的偏移
conf_reg代表电气属性寄存器地址的(PAD)偏移 0X10B0就是写这里的
input_reg代表方向寄存器的地址 为0说明 没有输入功能
mux_mode代表复用模式
input_val代表写入Input_reg的值
2.在根节点中创建gpioled子节点
address-cells和size-cells在这里没有用,因为下面没有子节点了
pinctrl-0代表引用之前创建的pinctrl_led节点,表示gpioled设备所使用的PIN信息保存在pinctrl_led中
led-gpio表示设备所使用的gpio