linux内核中的GPIO系统之(5):gpio subsysem和pinctrl subsystem之间的耦合
作者:wowo 发布于:2017-8-10 22:17 分类:GPIO子系统
1. 前言
按理说,kernel中gpio subsystem和pinctrl subsystem的关系应该非常清楚:
pinctrl subsystem管理系统的所有管脚,GPIO是这些管脚的用途之一,因此gpio subsystem应该是pinctrl subsystem的client(也可叫做backend、consumer),基于pinctrl subsystem提供的功能,处理GPIO有关的逻辑。
不过,实际情况却不是这么简单,它们之间有着较为紧密的耦合(看一看kernel中pinctrl和gpio相关的实现就知道了)。本文将对这种耦合进行一个简单的分析,解释为什么要这样设计。
2. Why
首先,无论硬件的架构如何(可参考[2]中“五、和GPIO subsystem交互”),从逻辑上讲,有一点是很明确的(这一点和linuxer同学在[2]中的说明有出入,待讨论):
gpio subsystem永远是pinctrl的backend(或client,或consumer)。
基于这一点,规范的做法,任何一个gpio chip(相关的概念可参考本站GPIO子系统的文章[5]),在使用GPIO的时候(通常是gpio subsystem的consumer申请GPIO资源的时候),都需要向系统的pinctrl subsystem申请管脚,并将管脚配置为GPIO功能。
思路是简单、直接的,但实际操作起来,却有点棘手,下面以一个最简单的例子说明:
假设某一个gpio chip只包括2个gpio,这两个gpio分别和uart进行功能复用。
如果这两个管脚是同时控制的,要么是gpio,要么是uart,就很好处理了,按照pinctrl subsystem的精神,抽象出两个function:gpio和uart,gpio chip在使用gpio功能的时候,调用pinctrl set state,将它们切换为gpio即可。
但是,如果这两个gpio可以分开控制(很多硬件都是这样的设计的),麻烦就出现了,每个gpio要单独抽象为一个function,因此我们可以抽象出3个function:gpio1、gpio2和uart。
然后考虑一下一个包含32个gpio的chip(一般硬件的gpio bank都是32个),如果它们都可以单独控制,则会出现32个function。而系统又不止有一个chip,灾难就发生了,我们的device tree文件将会被一坨坨的gpio functions撑爆!
规范是我们追求的目标,但有限度,不能让上面的事情发生,怎么办呢?在pinctrl subsystem的标准框架上打个洞,只要碰到这种情况,直接就走后门就是了。
3. pinctrl中和gpio有关的后门
后门是什么呢?其实很简单,参考下面的API:
static inline int pinctrl_request_gpio(unsigned gpio) ; static inline void pinctrl_free_gpio(unsigned gpio) ; static inline int pinctrl_gpio_direction_input(unsigned gpio); static inline int pinctrl_gpio_direction_output(unsigned gpio); |
当gpio driver需要使用某个管脚的时候,直接调用pinctrl_request_gpio,向pinctrl subsystem申请。
pinctrl subsystem会维护一个gpio number到pin number的map,将gpio subsystem传来的gpio number转换为pin number之后,调用struct pinmux_ops中有关的回调函数即可:
struct pinmux_ops {
...
int (*gpio_request_enable) (struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset);
void (*gpio_disable_free) (struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset);
int (*gpio_set_direction) (struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset,
bool input);
};对gpio driver来说,要做的事情就是提供gpio number到pin number的map。
而pinctrl subsystem呢,做自己分内的事情即可:管理系统的pin资源,并根据gpio subsystem的请求,将某些pin设置为GPIO功能。
4. gpio range----gpio number到pin number的map
那么,怎么提供gpio number和pin number的map呢?是通过一个名称为gpio range的数据结构(pinctrl subsystem提供的),如下:
/* include/linux/pinctrl/pinctrl.h */ |
该数据结构很容易理解,总结来说,就是:gpio controller(gc)中的gpio(base)到gpio(base + npins - 1),和pin controller中的pin(pin_base)到pin(pin_base + npins - 1)是一一对应的。
有了这个对应关系之后,pinctrl subsystem就可以将任意一个gpio controller中的gpio number转换为相应的pin controller中的pin number。
最后,gpio subsystem为了方便gpio driver的开发,提供了一种简单的、可以通过device tree提供gpio range信息的方法,总结如下:
1)gpio range的dts格式示例(可参考[6]中的介绍)
qe_pio_e: gpio-controller@1460 {
#gpio-cells = <2>;
compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
reg = <0x1460 0x18="">;
gpio-controller;
gpio-ranges = <&pinctrl1 0 20 10>, <&pinctrl2 10 50 20>;
};
上面dts节点中的gpio-ranges关键字指定了两个gpio range:gpio controller(qe_pio_e)中的gpio0~9和pinctrl1中的pin20~29对应;gpio controller(qe_pio_e)中的gpio10~29和pinctrl2中的pin50~69对应。
2)gpio range dts node的解析
解析的过程如下(具体不再详细介绍了,大家可参考相应的代码):
devm_gpiochip_add_data(drivers/gpio/gpiolib.c)
gpiochip_add_data
of_gpiochip_add(drivers/gpio/gpiolib-of.c)
of_gpiochip_add_pin_range
gpiochip_add_pin_range(drivers/gpio/gpiolib.c)
pinctrl_find_and_add_gpio_range(drivers/pinctrl/core.c)
pinctrl_add_gpio_range
以上过程的结果,就是在相应的pin controller device的数据结构中生成了一个gpio range的链表,如下:
struct pinctrl_dev {
struct list_head node;
struct pinctrl_desc *desc;
struct radix_tree_root pin_desc_tree;
struct list_head gpio_ranges;
...
};
3)gpio range的使用
当gpio driver需要使用某一个gpio的时候,可以在gpiochip的request函数中,调用pinctrl core提供的pinctrl_request_gpio接口(参数是gpio编号),然后pinctrl core会查寻gpio ranges链表,将gpio编号转换成pin编号,然后调用pinctrl的相应接口(参数是pin编号),申请该pin的使用。
至此,gpio subsystem和pinctrl subsystem的耦合,就真相大白了。
5. 参考文档
[1] https://github.com/wowotechX/linux/blob/x_integration/Documentation/pinctrl.txt
[2] linux内核中的GPIO系统之(2):pin control subsystem
[3] linux内核中的GPIO系统之(4):pinctrl驱动的理解和总结
[4] X-023-KERNEL-Linux pinctrl driver的移植
[5] http://www.wowotech.net/sort/gpio_subsystem
[6] Documentation/devicetree/bindings/gpio/gpio.txt
原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。
标签: GPIO subsystem pinctrl range
评论:
2019-05-19 16:42
功能
最新评论
- bngvwzdlzj
天上碑仙境RO诛仙服务端出售www.81uv.com9155... - 北葵依旧菜
感谢博主,博主多年前的文章在今天依旧熠熠生辉,解答了很多疑惑 - jqdeng
@新手:curr的确是从rb tree拿下来了,但是on_r... - leelockhey
@入行真的好难:遇到写得好的技术博客真滴少啊,遇到写得好的一... - 飞翔的蜗牛2024
请问怎么在head.S中bl __enable_mmu后使用... - Jam
2024.9.1来考古
文章分类
随机文章
文章存档
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
2023-08-28 17:41