Linux驱动开发pinctrl子系统和gpio子系统

Posted XXX_UUU_XXX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux驱动开发pinctrl子系统和gpio子系统相关的知识,希望对你有一定的参考价值。

Linux驱动分离与分层的产物:pinctrl子系统和gpio子系统

pinctrl子系统

设置pin引脚的复用和电气属性

主要工作内容:

  1. 获取设备树中 pin 信息
  2. 根据获取到的 pin 信息来设置 pin 的复用功能
  3. 根据获取到的 pin 信息来设置 pin 的电气特性,比如上/下拉、速度、驱动能力等

pinctrl设备树绑定信息可以参考Linux内核路径/Documentation/devicetree/bindings/pinctrl/xxx-pinctrl.txt

设备树中添加pinctrl节点

在设备中检查PIN是否被多个外设使用

  • 检查pinctrl的设置
  • 如果PIN被设置为GPIO,检查gpio是否被别的外设使用

示例:I.MX SOC,在iomuxc节点下,

节点前缀一定要为pinctrl_

// 创建节点
pinctrl_test: testgrp
    // 创建属性
    fsl,pins = <
        // MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0X17059   复用功能 电气特性
        MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0X17059
    >;
;

MX6UL_PAD_UART1_RTS_B__GPIO1_IO19,UART1_RTS_B 做为 SD 卡的检测引脚,UART1_RTS_B 复用为 GPIO1_IO19。查看芯片手册可知。

# define MX6UL_PAD_UART1_RTS_B__GPIO1_IO19         0x0090 0x031C 0x0000 0x5 0x0

<mux_reg     conf_reg     input_reg     mux_mode     input_val>

0x0090         0x031C      0x0000          0x5                 0x0

  • 和根据芯片手册中数据对应
  • mux_reg 寄存器偏移地址,iomuxc节点首地址0x020e0000,因此UART1_RTS_B这个PIN的mux寄存器地址 就是:0x020e0000+0x0090=0x020e 0090
  • conf_reg 寄存器偏移地址0x020e0000+0x031c=0x020e031c,这个寄存器就是UART1_RTS_B的电气属性配置寄存器0x17059:为电气属性配置寄存器的值
  • input_reg 寄存器偏移地址,有些外设有 input_reg 寄存器,有 input_reg 寄存器的 外设需要配置 input_reg 寄存器。没有的话就不需要设置
  • mux_mode  复用值寄存器值,0x5表示复用为GPIO1_IO19,将其写入0x020e 0090
  • input_reg 寄存器值,在这里无效,为0

gpio子系统

pinctrl子系统将一个PIN复用为GPIO后,需要使用gpio子系统。gpio子系统主要用来初始化GPIO并提供响应的API函数。设置GPIO输入输出、读取GPIO值等。

pinctrl设备树绑定信息可以参考Linux内核路径/Documentation/devicetree/bindings/gpio/xxx-gpio.txt

使用函数of_find_node_by_path获取GPIO所处设备节点,使用函数of_get_named_gpio获取GPIO编号,使用API函数gpio_request请求编号对应的GPIO,设置GPIO的输入gpio_direction_input或输出gpio_direction_output,如果GPIO为输入,使用gpio_get_vaule读取GPIO值,如果GPIO为输出,使用gpio_set_value设置GPIO值,不使用GPIO时,使用gpio_free释放。

OF函数

of_gpio_named_count

  • 获取设备树某个属性里面定义了几个 GPIO 信息,空的GPIO信息也会获取到
  • int of_gpio_named_count(struct device_node *np, const char *propname)
  • np:设备节点。 propname:GPIO 属性
  • 返回值:正值,GPIO 数量;负值,失败

of_gpio_count

获取gpios属性的GPIO数量,而 of_gpio_named_count 函数可以获取任意属性的GPIO信息

  • int of_gpio_count(struct device_node *np)
  • np:设备节点
  • 返回值:正值,GPIO数量;负值,失败

of_get_named_gpio

获取GPIO编号,将设备树中<&gpio1 19 GPIO_ACTIVE_LOW>的属性信息转换为对应的GPIO编 号。of_get_named_gpio函数在驱动中使用频繁

  • int of_get_named_gpio(struct device_node *np, const char *propname, int index)
  • np:设备节点。 propname:包含要获取GPIO信息的属性名
  • index:GPIO索引,一个属性里面可能包含多个 GPIO,此参数指定要获取哪个GPIO的编号,如果只有一个 GPIO 信息的话此参数为 0。
  • 返回值:正值,获取到的 GPIO 编号;负值,失败。

API函数

gpio_request 

用于申请一个 GPIO 管脚,在使用一个 GPIO 之前一定要使用 gpio_request 进行申请。

申请GPIO可以检测是否被其他设备使用,如果IO被分配给了其他设备,申请失败,需要重新分配IO。申请IO失败,通常是该IO被其他外设占用,需要检查设备树文件中使用相同IO的设备,修改(注释)pinctrl和gpio节点中相同的IO设置,重新编译设备树。

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

gpio_free

如果不使用某个 GPIO ,进行释放

  • void gpio_free(unsigned gpio)
  • gpio:要释放的 gpio 标号。
  • 返回值:无。

gpio_direction_input

用于设置某个 GPIO 为输入

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

gpio_direction_output

函数用于设置某个 GPIO 为输出,并且设置默认输出值

  • int gpio_direction_output(unsigned gpio, int value)
  • gpio:要设置为输出的 GPIO 标号。 value:GPIO 默认输出值

gpio_get_value

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

  • #define gpio_get_value __gpio_get_value
  • int __gpio_get_value(unsigned gpio)
  • gpio:要获取的 GPIO 标号
  • 返回值:非负值,得到的 GPIO 值;负值,获取失败

gpio_set_value

用于设置某个 GPIO 的值,此函数是个

  • #define gpio_set_value __gpio_set_value
  • void __gpio_set_value(unsigned gpio, int value)
  • gpio:要设置的 GPIO 标号。 value:要设置的值
  • 返回值:无

设备树中添加gpio节点

test 
    pinctrl-names = "default";             // pinctrl-names属性
    pinctrl-0 = <&pinctrl_test>;           // pinctrl-0节点,引用pinctrl_test节点
    gpio = <&gpio1 19 GPIO_ACTIVE_LOW>;    // GPIO属性,test节点使用GPIO1_IO19,低电平有效

以上是关于Linux驱动开发pinctrl子系统和gpio子系统的主要内容,如果未能解决你的问题,请参考以下文章

使用pinctrl和gpio子系统开发GPIO驱动正点原子IMX6ULL阿尔法板的LED灯

pinctl和gpio子系统-22

pinctrl 和 gpio 子系统

Linux——Linux驱动之设备树中pinctrl和gpio子系统应用实践(如何使用其在设备树中配置GPIO,驱动中如何调用?)

Linux——Linux驱动之设备树中pinctrl和gpio子系统应用实践(如何使用其在设备树中配置GPIO,驱动中如何调用?)

嵌入式Linux开发21——pinctrl 和 gpio 子系统