Yuhang Zheng

第二十节、pinctl和gpio子系统

N 人看过

本节用于介绍pinctl和gpio子系统

1、什么是pinctrl和gpio子系统?

2、Linux Pinctrl子系统提供的功能是什么?

(1)管理系统中所有的可以控制的pin,在系统初始化的时候,枚举所有可以控制的pin,并标识这些pin。

(2)管理这些pin的复用(Multiplexing)。对于SOC而言,其引脚除了配置成普通的GPIO之外,若干个引脚还可以组成一个pin group,形成特定的功能。

(3)配置这些pin的特性。例如使能或关闭引脚上的pull-up、pull-down电阻,配置引脚的driver strength。

3、不同soc厂家的pin controller的节点这些节点里都是把某些引脚复用成某些功能。

image-20210811120352880

4.不同soc厂家的pin controller的节点里面的属性都是什么意思?

可以通过Linux 源码目录Documentation/devicetree/bindings下的txt文档查看。

如在文件

Documentation/devicetree/bindings/pinctrl/fsl\,imx6q-pinctrl.txt

有对imx6q的pinctrl的使用说明,详细说明了fsl,pins = 中每个字段的含义

5.怎么在代码里面使用pin controller里面定义好的节点?

例1:

pinctrl-names = "default";
//设备的状态,可以有多个状态,default为状态0
pinctrl-0 = <&pinctrl_audmux_1>;
//第0个状态所对应的引脚配置,也就是default状态对应的引脚在pin controller里面定义好的节点pinctrl_audmux_1里面的管脚配置

例2:

pinctrl-names = "default", "wake up";
//设备的状态,可以有多个状态,default为状态0
pinctrl-0 = <&pinctrl_audmux_1>;
//第0个状态所对应的引脚配置,也就是default状态对应的引脚在pin controller里面定义好的节点pinctrl_audmux_1里面的管脚配置
pinctrl-1 = <&pinctrl_audmux_2>;
//第1个状态所对应的引脚配置,也就是default状态对应的引脚在pin controller里面定义好的节点pinctrl_audmux_2里面的管脚配置

例3:

pinctrl-names = "default";
//设备的状态,可以有多个状态,default为状态0
pinctrl-0 = <&pinctrl_audmux_1
            &pinctrl_audmux_2>;
//第0个状态所对应的引脚配置,也就是default状态对应的引脚在pin controller里面定义好的节点pinctrl_audmux_1和pinctrl_audmux_2里面的管脚配置

Linux内核提供了pinctrl 子系统和gpio子系统用于GPIO驱动,当然pinctrl子系统负责的就不仅仅是GPIO的驱动了而是所有pin脚的配置。pinctrl子系统是随着设备树的加入而加入的,依赖于设备树。GPIO子系统在之前的内核中也是存在的,但是pinctrl子系统的加入GPIO子系统也是有很大的改变。

在以前的内核版本中,如果要配置GPIO的话一般要使用SOC厂家实现的配置函数,例如三星的配置函s3c_gpio_cfgpin等,这样带来的问题就是各家有各家的接口函数与实现方式,不但内核的代码复用率低而且开发者很难记住这么多的函数,如果要使用多种平台的话背函数都是很麻烦的,所以在引入设备树后对GPIO子系统进行了大的改造,使用设备树来实现并提供统一的接口。通过GPIO子系统功能主要实现引脚功能的配置,如设置为GPlO,特殊功能,GPIO的方向,设置为中断等。

那么我们先来看一下怎么在设备树中pinctrl和gpio子系统描述一个gpio。

<1>设备树使用pinctrl和gpio子系统描述一个gpio

        test_key {
                #address-cells = <1>;
                #size-cells = <1>;

                status = "okay";
                compatible = "keys";

                pinctrl-name = "default";
                pinctrl-0 = <&pinctrl_key>;
                gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
        };

<2>常用gpio子系统提供的api函数

1、gpio_request 函数

作用:gpio_request 函数用于申请一个GPIO管脚

函数原型:

文件位置路径:include/linux/gpio.h

static inline int gpio_request(unsigned gpio, const char *label)
//参数
//gpio:要申请的gpio标号,使用of_get_named_gpio函数从设备树获取指定GPIO属性信息,此函数会返回这个GPIO的标号。
//label:给gpio设置个名字。
//返回值
//成功,返回0
//失败,返回负值

2、gpio_free 函数

作用:如果不使用某个GPIO了,那么就可以调用gpio_free函数进行释放。

函数原型:

文件位置路径:include/linux/gpio.h

static inline void gpio_free(unsigned gpio)
//参数
//gpio:要释放的gpio标号

3、gpio_direction_input 函数

作用:此函数用于设置某个GPIO为输入

函数原型:

文件位置路径:include/linux/gpio.h

static inline int gpio_direction_input(unsigned gpio)
//参数
//gpio:要设置为输入的GPIO标号。
//返回值
//成功,返回0
//失败,返回负值

4、gpio_direction_output 函数

作用:此函数用于设置某个GPIO为输出

函数原型:

文件位置路径:include/linux/gpio.h

static inline int gpio_direction_output(unsigned gpio, int value)
//参数
//gpio:要设置为输入的GPIO标号。
//value:GPIO默认输出值
//返回值
//成功,返回0
//失败,返回负值

5、gpio_get_value 函数

作用:此函数用于获取某个GPIO的值(0或1)

函数原型:

文件位置路径:include/linux/gpio.h

static inline int gpio_get_value(unsigned gpio)
//参数
//gpio:要获取的GPIO标号
//返回值
//成功,GPIO的值
//失败,返回负值

6、gpio_set_value 函数

作用:此函数用于设置某个GPIO的值(0或1)

函数原型:

文件位置路径:include/linux/gpio.h

static inline void gpio_set_value(unsigned gpio, int value)
//参数
//gpio:要设置的GPIO标号
//value:要设置的值