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功能。

其它具体的实现,这里不再详细描述了,可参考其它的文章[5]

4. 参考文档  

[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

原创文章,转发请注明出处。蜗窝科技,www.wowotech.net

标签: GPIO subsystem pinctrl range

发表评论:

Copyright @ 2013-2015 蜗窝科技 All rights reserved. Powered by emlog