Linux驱动开发之【pinctrl和gpio子系统】

这篇具有很好参考价值的文章主要介绍了Linux驱动开发之【pinctrl和gpio子系统】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、 pinctrl和gpio子系统

1.pinctrl子系统

1.1 pinctrl子系统简介

1.2 pinctrl子系统驱动

1.3 设备树中添加pinctrl节点模版

2. gpio子系统

2.1 gpio子系统简介

2.2 gpio子系统驱动

2.3 gpio子系统API函数

2.4 设备树中添加gpio节点模板

2.5 与gpio相关的OF函数

3. 驱动程序编写

3.1 驱动入口函数

3.2 驱动出口函数


一、 pinctrl和gpio子系统

Linux 是一个庞大而完善的系统,尤其是驱动框架,像 GPIO 这种最基本的驱动不可能采用“原始”的裸机驱动开发方式。Linux 内核提供了 pinctrl 和 gpio 子系统用于GPIO 驱动,

Linux 驱动讲究驱动分离与分层,pinctrl 和 gpio 子系统就是驱动分离与分层思想下的产物

要先设置某个 PIN 的复用功能、速度、上下拉等,然后再设置 PIN 所对应的 GPIO。其实对于大多数的 32 位 SOC 而言,引脚的设置基本都是这两方面,因此 Linux 内核针对 PIN 的配置推出了 pinctrl 子系统,对于 GPIO的配置推出了 gpio 子系统。

1.pinctrl子系统

1.1 pinctrl子系统简介

  • pinctrl 子系统主要工作内容如下:

①、获取设备树中 pin 信息。

②、根据获取到的 pin 信息来设置 pin 的复用功能

③、根据获取到的 pin 信息来设置 pin 的电气特性,比如上/下拉、速度、驱动能力等。

1.2 pinctrl子系统驱动

  • PIN配置信息详解

要使用pinctrl子系统,需要在设备树里设置PIN的配置信息,pinctrl子系统会根据提供的信息去配置PIN功能,一般会在设备树里创建一个节点来描述PIN的配置信息

如何向iomuxc(描述IOMUXC设备的节点)追加数据?

不同的外设使用的PIN不同,配置也不同,因此一个萝卜一个坑,将某个外设所使用的的所有PIN都组织在一个子节点里

例如:

iomuxc: iomuxc@020e0000 {
compatible = "fsl,imx6ul-iomuxc";
reg = <0x020e0000 0x4000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog_1>;
imx6ul-evk {
pinctrl_hog_1: hoggrp-1 {
fsl,pins = <
MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 0x17059
MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT 0x17059
MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0x17059
MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID 0x13058
>;
......
};
};
};

"fsl,pins"为pinctrl_hog_1 子节点所使用的 PIN 配置信息,对于一个 PIN 的配置主要包括两方面,一个是设置这个 PIN 的复用功能,另一个就是设置这个 PIN 的电气特性

  • PIN 驱动程序讲解

《正点驱动文档》P1163

pinctrl 配置gpio,Linux驱动框架学习,驱动开发,linux,arm开发,c语言

 

1.3 设备树中添加pinctrl节点模版

1. 创建对应的节点

同一个外设的PIN都放到一个节点里,如在iomuxc节点中的imx6ul-evk子节点下添加"pinctrl_test"节点

pinctrl_test:testgrp
{
    /*具体的PIN信息*/
}

2, 添加"fsl,pins"属性

设备树通过属性来保存信息,对于I.MX系列SOC而言,pinctrl驱动程序是通过读取"fsl,pins"属性值来获取PIN的配置信息

pinctrl_test:testrp
{
    fsl,pins=<
    /*设备所使用的PIN配置信息*/    
    >
}

3. 在“fsl,pins”属性中添加具体的PIN配置信息

pinctrl_test:testrp
{
    fsl,pins=<
    MX6UL_PAD_GPIO1_IO00_GPIO1_IO00 config/*config是具体设置值*/    
    >
}

2. gpio子系统

2.1 gpio子系统简介

pinctrl子系统重点是设置PIN(PAD)的复用和电气属性,若pinctrl子系统将一个PIN复用为GPIO的话,则接下来就要用到gpio子系统

gpio子系统的主要目的就是方便驱动开发者使用gpio,驱动开发者在设备树中添加gpio相关信息

2.2 gpio子系统驱动

  • 设备树中的gpio信息

pinctrl配置好以后就是设置gpio了,驱动程序通过相关GPIO进行判断处理等

  • 如何让驱动程序知道相应引脚连接的是相关的GPIO呢

需要设备树来告诉驱动,在设备树设备节点下添加一个属性来描述设备引脚,设备驱动直接读取这个属性值就知道相应引脚使用哪个GPIO

示例代码 45.2.2.2 设备树中 SD 卡节点
 &usdhc1 {
 pinctrl-names = "default", "state_100mhz", "state_200mhz";
 pinctrl-0 = <&pinctrl_usdhc1>;
 pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
 pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
 /* pinctrl-3 = <&pinctrl_hog_1>; */
 cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
 keep-power-in-suspend;
 enable-sdio-wakeup;
 vmmc-supply = <&reg_sd1_vmmc>;
 status = "okay";
 };
  • "cd-gpios"属性

cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;

描述了SD卡的CD引脚使用的哪个IO,属性值一共有三个:

  1. “&gpio1”:表示CD引脚所使用的的IO属于GPIO1组

  2. “19”:表示GPIO1组的第19号IO

通过这两个值SD卡驱动程序就知道CD引脚使用了GPIO1_IO19这个GPIO

  1. “GPIO_ACTIVE_LOW”:表示低电平有效

  • gpio1节点

描述了GPIO1控制器的所有信息,重点就是GPIO1外设寄存器基地址以及兼容属性

  • GPIO驱动程序简介

《正点驱动文档》P1171

2.3 gpio子系统API函数

对于驱动开发人员,设置好设备树以后就可以使用 gpio 子系统提供的 API 函数来操作指定的 GPIO,gpio 子系统向驱动开发人员屏蔽了具体的读写寄存器过程。这就是驱动分层与分离的好处

  • gpio_request函数

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

int gpio_request(unsigned gpio, const char *label)
  • gpio_free函数

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

void gpio_free(unsigned gpio)
  • gpio_direction_input函数

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

int gpio_direction_input(unsigned gpio)
  • gpio_direction_output函数

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

int gpio_direction_output(unsigned gpio, int value)
  • gpio_get_value函数

此函数用于获取某个GPIO的值

#define gpio_get_value __gpio_get_value
int __gpio_get_value(unsigned gpio)
  • gpio_set_value函数

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

#define gpio_set_value __gpio_set_value
void __gpio_set_value(unsigned gpio, int value)

2.4 设备树中添加gpio节点模板

  1. 创建test设备节点

在根节点“/”下创建test设备子节点

test{
/*节点内容*/
}
  1. 添加pinctrl信息

将描述test设备所使用的的GPIOx_IOxx这个PIN的信息的pinctrl_test节点添加到test设备节点中

test{
pinctrl-names="default";
pinctrl-0=<&pinctrl_test>;
/*其他节点内容*/
};

3.添加GPIO属性信息

最后需要在test节点中添加GPIO属性信息,表明test设备所使用的的GPIO是哪个引脚

test{
pinctrl-names="default";
pinctrl-0=<&pinctrl_test>;
gpio=<&gpio1 0 GPIO_ACTIVE_LOW>;
};

2.5 与gpio相关的OF函数

  • of_gpio_named_count函数

用于获取设备树某个属性里面定义了几个GPIO信息,空的GPIO信息也会被统计到

int of_gpio_named_count(struct device_node *np, const char *propname)
  • of_gpio_count函数

和of_gpio_named_count函数一样,但是不同的地方在于,此函数统计的是"gpios"这个属性的GPIO数量,而of_gpio_named_count函数可以统计任意属性的GPIO信息

int of_gpio_count(struct device_node *np)
  • of_get_named_gpio函数

获取GPIO编号,Linux内核关于GPIO的API函数都需要GPIO编号,此函数会将设备树中类似<&gpio5 7 GPIO_ACTIVE_LOW>的属性信息转换为对应的 GPIO 编号,此函数很重要

int of_get_named_gpio(struct device_node *np,const char *propname, int index)

3. 驱动程序编写

  • test_gpio

int test_gpio; /* test 所使用的 GPIO 编号 */

在设备结构体test_dev中加入test_gpio这个成员变量,保存test设备所使用的的GPIO编号文章来源地址https://www.toymoban.com/news/detail-741269.html

3.1 驱动入口函数

static int __init led_init(void)
{
    /*设置test设备所使用的的GPIO*/
    /*1、获取设备节点:gpiotest (通过设备树中的路径/xxx)*/
    /*2、获取gpio属性内容,得到test要使用的gpio编号*/
​
    /*初始化LED*/
    /*1、设置GPIO引脚的功能*/
    /*2、默认设置*/
    
    /*注册字符设备驱动*/
    /*1、创建设备号*/
    定义了设备号:register_chrdev_region()
    没有定义设备号:alloc_chrdev_region()
    /*2、初始化cdev*/
    /*3、添加一个cdev*/
    /*4、创建类*/
    /*5、创建设备*/
}

3.2 驱动出口函数

static void __exit led_exit(void)
{
    /*注销字符设备驱动*/
    /*1、删除cdev*/
    /*2、取消注册字符设备*/
    /*3、设备销毁*/
    /*4、类销毁*/
}

到了这里,关于Linux驱动开发之【pinctrl和gpio子系统】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux驱动开发】011 gpio子系统

    前面我们编写了基于设备树的 LED 驱动,但是驱动的本质还是没变,都是配置 LED 灯所使用的 GPIO 寄存器,驱动开发方式和裸机基本没啥区别。本章我们就来学习一下如何借助 pinctrl 和 gpio 子系统来简化 GPIO 驱动开发。   Linux 内核针对 PIN 的配置推出了 pinctrl 子系统,对于

    2024年02月03日
    浏览(49)
  • 【Linux驱动开发】012 gpio子系统API函数

    设置好设备树以后, 在驱动程序中就可以使用 gpio 子系统提供的 API 函数来操作指定的 GPIO, gpio 子系统向驱动开发人员屏蔽了具体的读写寄存器过程。这就是驱动分层与分离的好处,大家各司其职,做好自己的本职工作即可。 gpio 子系统提供的常用的 API 函数有下面几个:

    2023年04月18日
    浏览(43)
  • 【IMX6ULL驱动开发学习】14.Linux驱动开发 - GPIO中断(设备树 + GPIO子系统)

    代码自取 【14.key_tree_pinctrl_gpios_interrupt】: https://gitee.com/chenshao777/imx6-ull_-drivers 主要接口函数: 1. of_gpio_count (获得GPIO的数量) 2. kzalloc (向内核申请空间) 3. of_get_gpio (获取GPIO子系统标号) 4. gpio_to_irq (根据GPIO子系统标号得到软件中断号) 5. request_irq (根据软件中断号

    2024年02月12日
    浏览(51)
  • 驱动开发作业3——GPIO子系统

    作业1:在内核模块中启用定时器,定时1s,让LED1以1s为周期实现流水灯  myled.c(驱动文件)    作业2:基于GPIO子系统完成LED灯驱动的注册,并利用应用程序测试  chrdevled.c(驱动文件) test.c(测试文件)

    2024年02月16日
    浏览(38)
  • RK3588 设备树pinctrl gpio子系统解析,解决GPIO无法正确拉高拉低的问题,RK3588设备树详解

    firefly的官方说明文档RK3588gpio系统说明 其中,bank是所属的组,Core-3588J 有 5 组 GPIO bank:GPIO0-GPIO4,每组又以 A0-A7, B0-B7, C0-C7, D0-D7 作为编号区分。 首先,对于firefly的rk3588j的开发板,其设备树有几个比较重要的文件, 分别是 /kernel/arch/arm64/boot/dts/rockchip/rk3588s-pinctrl.dtsi ; /ker

    2024年02月06日
    浏览(43)
  • [驱动开发]gpio子系统及中断实现led亮灭

    编写LED灯的驱动,使用GPIO子系统,里面添加按键的中断处理 1.应用程序发送指令控制发光二极管亮灭 2.按键1按下,led1电位反转;按键2按下,led2电位反转;按键3按下,led3电位反转   

    2024年02月14日
    浏览(77)
  • 【Linux】Pinctrl子系统简介

    我们工作开发中非常常用的就是GPIO,在Linux开发中,是有必要去熟悉并理解的。在Linux内核中也有提供相应的子系统pinctrl子系统, 本文从大的面上去了解它 。 参考学习:Linux笔记老师课程(Pinctrl子系统) https://live.csdn.net/v/219059?spm=1001.2014.3001.5501 https://xuesong.blog.csdn.net/arti

    2024年02月07日
    浏览(48)
  • Linux驱动开发:SPI子系统

    MISO:主设备数据输入,从设备数据输出。 MOSI:主设备数据输出,从设备数据输入。 SCLK:时钟信号,由主设备产生。 CS:    从设备片选信号,由主设备控制。 CPOL(时钟极性) :   0:时钟起始位低电平      1:时钟起始为高电平   CPHA(时钟相位) :0:第一个时钟周期采样   1

    2024年02月06日
    浏览(53)
  • 【IMX6ULL驱动开发学习】08.IMX6ULL通过GPIO子系统函数点亮LED

    通过GPIO子系统函数点亮LED 1、GPIO子系统函数 1.1 确定 led 的GPIO标号,查看内核中的gpiochip 查看 gpiochip ,以正点原子的IMX6ULL阿尔法开发板为例 查看原理图,发现led接的引脚是 GPIO1_IO3,对应 /sys/kernel/debug/gpio 中的 gpiochip0 组,gpiochip0 组从0开始算起, 所以 GPIO1_IO3 对应的标号就

    2024年02月10日
    浏览(78)
  • <Linux开发>驱动开发 -之-Linux INPUT 子系统

    <Linux开发>驱动开发 -之-Linux INPUT 子系统 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: <Linux开发> -之-系统移植 uboot移植过程详细记录(第一部分) <Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分) <Linux开发

    2024年02月09日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包