pinctrl和gpio子系统

简介: pinctrl和gpio子系统

前言

原始字符设备驱动,patform框架,设备树这三种方法来点亮led灯的原理都是配置gpio寄存器。但在实际开发中,需要用到的引脚非常多。都是用前面讲到的方法不显示,麻烦。实际开发中我们常用pinctrl和gpio子系统来进行GPIO驱动开发。


一、pinctrl子系统

传统的配置 pin 的方式就是直接操作相应的寄存器,但是这种配置方式比较繁琐、而且容易出问题(比如 pin 功能冲突)。而pinctrl子系统就是为了解决这种问题而引入的,pinctrl子系统的主要工作内容:

1.获取设备树中pin的信息

2.依据获取到的pin信息设置pin的复用功能

3.依据获取到的pin信息设置pin的电气属性。

使用时我们只需要在设备树里面设置好某个 pin 的相关属性即可,其他的初始化工作均由 pinctrl 子系统来完成。例如:

&iomuxc {
  pinctrl-names = "default";
  pinctrl-0 = <&pinctrl_hog_1>;
  imx6ul-evk {
     pinctrl_led: ledgrp {
       fsl,pins = <
         MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0 /* LED0 */
       >;
     };

搜索“pinctrl_led”就会找到 pin引脚的gpio设置:

gpioled {
     #address-cells = <1>;
     #size-cells = <1>;
     compatible = "atkalpha-gpioled";
     pinctrl-names = "default";
     pinctrl-0 = <&pinctrl_led>;
     led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
     status = "okay";
   };

注意:pinctrl_led节点和gpioled 节点是我自己添加上去的,不是原来就有的。

我们先说明pinctrl子系统。gpio1_3在这里我们用来点亮led灯:

MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 

这是一个宏定义,在arch/arm/boot/dts/imx6ul-pinfunc.h中可以找到:

#define MX6UL_PAD_GPIO1_IO03__GPIO1_IO03                          0x0068 0x02F4 0x0000 0x5 0x0

后面跟着5个数字,为该宏定义的具体值。

<mux_reg conf_reg input_reg mux_mode input_val>

0x0068 :mux_reg 寄存器偏移地址,设备树中的 iomuxc 节点就是 IOMUXC 外设对应的节点 , 根 据 其 reg 属 性 可 知 IOMUXC 外 设 寄 存 器 起 始 地 址 为 0x020e0000 。 因 此0x020e0000+0x0068 =0x020e0068, MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 寄存器地址正 好 是 0x020e0068,

0x020e0000+mux_reg 就是 PIN 的复用寄存器地址。

0x02F4 : conf_reg 寄存器偏移地址,和 mux_reg 一样, 0x020e0000+0x02F4 =0x020e02F4c,这个就是寄存器 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03的地址。

0x0000: input_reg 寄存器偏移地址,有些外设有 input_reg 寄存器,有 input_reg 寄存器的外设需要配置 input_reg 寄存器。没有的话就不需要设置, GPIO1_IO03这个 PIN 在做GPIO1_IO03的时候是没有 input_reg 寄存器,因此这里 intput_reg 是无效的。

0x5 : mux_reg 寄 存 器 值 , 在 这 里 就 相 当 于 设 置MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 寄存器为 0x5,也即是设置 GPIO1_IO03这个 PIN 复用为 GPIO1_IO03。

0x0: input_reg 寄存器值,在这里无效。至于pin引脚的电气属性,由我们自行设置:

MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0 /* LED0 */

0x10B0 设置的就是 conf_reg 寄存器值,在这里就相当于设置寄存器MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 的值为 0x10B0 。

二、gpio子系统

pinctrl 子系统重点是设置 PIN(有的 SOC 叫做 PAD)的复用和电气属性,如果 pinctrl 子系统将一个 PIN 复用为 GPIO 的话,那么接下来就要用到 gpio 子系统,gpio 子系统就是用于初始化 GPIO 并且提供相应的 API 函数,比如设置 GPIO为输入输出,读取 GPIO 的值等。

gpioled {
     #address-cells = <1>;
     #size-cells = <1>;
     compatible = "atkalpha-gpioled";
     pinctrl-names = "default";
     pinctrl-0 = <&pinctrl_led>;
     led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
     status = "okay";
   };

pinctrl-0 属性设置 LED 灯所使用的 PIN 对应的 pinctrl 节点。led-gpio 属性指定了 LED 灯所使用的 GPIO,在这里就是 GPIO1 的 IO03,低电平有效。稍后编写驱动程序的时候会获取 led-gpio 属性的内容来得到 GPIO 编号,因为 gpio 子系统的 API 操作函数需要 GPIO 编号。

三、pinctrl与gpio子系统的使用

pinctrl使用模板

1、创建对应的节点

同一个外设的 PIN 都放到一个节点里面,打开 imx6ull-alientek-emmc.dts,在 iomuxc 节点中的“imx6ul-evk”子节点下添加“pinctrl_test”节点,注意!节点前缀一定要为“pinctrl_”。添加完成以后如下所示:

pinctrl_test: testgrp {
 /* 具体的 PIN 信息 */
 };

2、添加“fsl,pins”属性

设备树是通过属性来保存信息的,因此我们需要添加一个属性,属性名字一定要为“fsl,pins”,因为对于 I.MX 系列 SOC 而言, pinctrl 驱动程序是通过读取“fsl,pins”属性值来获取 PIN 的配置信息,完成以后如下所示:

pinctrl_test: testgrp {
 fsl,pins = <
 /* 设备所使用的 PIN 配置信息 */
 >;
 };

3、在“fsl,pins”属性中添加 PIN 配置信息

最后在“fsl,pins”属性中添加具体的 PIN 配置信息,完成以后如下所示:

pinctrl_test: testgrp {
 fsl,pins = <
 MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 config /*config 是具体设置值*/
 >;

gpio模板

1、创建 test 设备节点

在根节点“/”下创建 test 设备子节点,如下所示:

test {
 /*节点内容*/
 };

2、添加 pinctrl 信息

在 前面中我们创建了 pinctrl_test 节点,此节点描述了 test 设备所使用的 GPIO1_IO00 这个 PIN 的信息,我们要将这节点添加到 test 设备节点中,如下所示:

test {
 pinctrl-names = "default";
 pinctrl-0 = <&pinctrl_test>;
 /* 其他节点内容 */
 };

添加 pinctrl-names 属性,此属性描述 pinctrl 名字为“default”。

添加 pinctrl-0 节点,此节点引用 前面中创建的 pinctrl_test 节点,表示 tset 设备的所使用的 PIN 信息保存在 pinctrl_test 节点中。

3、添加 GPIO 属性信息

我们最后需要在 test 节点中添加 GPIO 属性信息,表明 test 所使用的 GPIO 是哪个引脚,添加完成以后如下所示:

test {
 pinctrl-names = "default";
 pinctrl-0 = <&pinctrl_test>;
 gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
 };

pinctrl与gpio子系统内核实现





目录
相关文章
|
6月前
|
Java Android开发
Rockchip系列之客制化GPIO接口应用部分(5)
Rockchip系列之客制化GPIO接口应用部分(5)
61 0
|
6月前
|
Linux API Android开发
Rockchip系列之客制化GPIO接口Hardware部分(3)
Rockchip系列之客制化GPIO接口Hardware部分(3)
94 0
|
3月前
|
编解码 数据格式
IMX6ULL开发板spi OLED驱动
【8月更文挑战第24天】本文档介绍在IMX6ULL开发板上实现SPI接口OLED显示器驱动的步骤。首先需正确连接OLED至开发板的SPI接口,包括时钟(SCLK)、数据(MOSI)及片选(CS)等线路。理解SPI协议与OLED规格也很关键:SPI为同步串行通信,涉及主从设备交互;OLED参数如分辨率、颜色深度等须明确。接下来配置IMX6ULL的SPI控制器,通过设备树设定时钟频率、数据宽度等参数,并加载内核驱动。最后编写驱动程序,初始化SPI设备、发送控制命令与数据以完成OLED初始化,并实现文本或图像的显示功能。
|
6月前
|
传感器 存储 缓存
STM32--MPU6050与I2C外设
STM32--MPU6050与I2C外设
158 1
|
6月前
|
传感器
gpio设备
GPIO设备是一种数字输入/输出设备,用于连接计算机和外部电子设备。
50 0
|
6月前
|
Linux API 芯片
嵌入式Linux中pinctrl 子系统和 gpio 子系统分析
嵌入式Linux中pinctrl 子系统和 gpio 子系统分析
163 0
|
Linux 芯片
GPIO和Pinctrl子系统的使用
GPIO和Pinctrl子系统的使用
97 0
|
Linux API 芯片
pinctrl子系统和gpio子系统
pinctrl子系统和gpio子系统
76 0
|
Ubuntu Linux Shell
UART子系统(三) UART属于TTY体系之一
UART子系统(三) UART属于TTY体系之一
238 1
UART子系统(三) UART属于TTY体系之一
|
缓存 开发工具 芯片
ZYNQ-AXI GPIO使用(一)
ZYNQ-AXI GPIO使用
1191 1
ZYNQ-AXI GPIO使用(一)