前言
pinctrl子系统用来控制每个端口的复用功能和电气属性,这篇博客来介绍一下pinctrl子系统。
嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关注本博主并订阅本专栏,一起讨论一起学习。现在关注就是老粉啦!
目录
- 前言
- pinctrl介绍
- pinctrl 设备树
- 服务端
- 客户端
- pinctrl添加
- 参考资料
pinctrl介绍
pinctrl顾名思义就是控制pin引脚的。如下图所示,pinA可以通过IOMUX连接到GPIO,也可以连接到I2C,同时每个引脚的状态例如上拉、下拉、开漏开源等都可以交由pinctrl来控制。
因此pinctrl
的作用如下所示:
引脚枚举与命名
引脚复用:如GPIO、I2C或其他功能
引脚配置:如上拉、下拉、 开漏开源、驱动强度等
一般Pinctrl驱动由芯片厂家的BSP工程师提供,一般的驱动工程师只需要在设备树里之名使用哪些引脚、复用为哪些功能、配置为哪些状态。
pinctrl 设备树
pinctrl分为两部分,客户端和服务端:
客户端可以指定引脚描述、引脚组描述和配置描述,以满足其特定的功能和需求,不同厂商在客户端的编写格式相同
服务端是提供GPIO引脚配置的pinctrl设备树节点,描述GPIO引脚配置和使用规则的节点,定义了一组GPIO引脚的配置选项、引脚功能、电气特性等。
服务端
打开设备树文件,我们以一个gpio为例:
pinctrl_led: ledgrp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0
>;
};
如上所示,我们配置GPIO1_IO3复用为GPIO功能,其他属性配置综合下来为:0x10B0
,这个0x10b0就是之后会写入寄存器的值,实现复用为GPIO的功能。
客户端
有了以上服务端的配置,接下来来看看如何使用,依旧是在设备树文件中,可以看到gpioled节点:
gpioled {
#address-cells = <1>;
#size-cells = <1>;
compatible = "atkmini-gpioled";
pinctrl-names = "default"; /* 用于pinctrl */
pinctrl-0 = <&pinctrl_led>; /* 用于pinctrl */
led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
status = "okay";
};
上面的设备树中,pinctrl-names
代表状态名,pinctrl-0
代表“default”状态下对应的配置方案,即我们上一步设置的服务端的设备数代码,需要用&
来引用。
既然有pinctrl-0
,那就肯定也有pinctrl-1
等等,现在来看多个状态怎么配置
假设现在服务端有pinctrl_led
节点,pinctrl_led2
节点, pinctrl_led3
节点,然后我们配置的时候对应不同的速度,默认,100M,200M。
gpioled {
...
pinctrl-names = "default", "state_100mhz", "state_200mhz"; /* 用于pinctrl */
pinctrl-0 = <&pinctrl_led>; /* 用于pinctrl */
pinctrl-1 = <&pinctrl_led2>; /* 用于pinctrl */
pinctrl-2 = <&pinctrl_led3>; /* 用于pinctrl */
...
};
这样就可以根据不同的状态选择不同的引脚电气属性的配置,即state_100mhz
时对应节点pinctrl_led2
中的配置,state_200mhz
时对应节点pinctrl_led3
中的配置。
pinctrl添加
由于服务端的写法不同的芯片也不同,因此如果要添加pinctrl
,一般有三种方式:
第三方的辅助工具:如果芯片是stm32,可以选择用STM32CubeMX,如果芯片是IMX可以使用i.MX Pins Tool v6进行配置
厂家给出的例程
看源码写
参考资料
[1] 【正点原子】I.MX6U嵌入式Linux驱区动开发指南 第四十五章
[2] 【Linux驱动】pinctrl 和 gpio子系统(一)—— pinctrl 节点解析,引入gpio子系统