pinctrl/gpio子系统(1)-pinctrl子系统介绍及驱动源码分析

2024-02-01 11:28

本文主要是介绍pinctrl/gpio子系统(1)-pinctrl子系统介绍及驱动源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.简介

在如今的驱动开发工作中,实际上已经很少去对着寄存器手册进行驱动开发了,一般板子拿到手,已经有原厂的驱动开发工程师,在gpio子系统、pinctrl子系统中将自家芯片的引脚适配好了。
我们直接基于设备树已配置好的寄存器值,去使用子系统对应的API函数,就能快速完成驱动开发,不需要再那么关心IO寄存器的值,借助这种驱动分层的思想,快速完成驱动开发。

其中配置一个GPIO最重要的几点就是配置IO的MUX复用属性,PAD电气属性,输入及输出

pinctrl 子系统作用:从设备树中获取PIN 的复用(MUX)和电气属性(PAD),并完成初始化等,PIN 可复用为 I2C、SPI、GPIO,当复用为gpio的时候,就需要用到gpio子系统
gpio 子系统作用:方便开发者使用gpio,负责初始化 GPIO 并且提供相应的 API 函数,比如设置 GPIO 为输入输出,读取 GPIO 的值

1.1 pinctrl和gpio子系统分层思想

在加入gpio子系统和pinctrl系统后,对gpio的操作,将通过pinctrl子系统设置IO复用及电气属性配置,gpio子系统控制输入/输出,读取gpio值等。当原厂bsp工程师适配好设备树后,借助子系统去完成驱动开发将变的十分简单。
image.png
其中gpio子系统和pinctrl子系统的关系如下图,相互依赖密不可分。
image.png

2.pinctrl子系统

2.1驱动源码分析

那么以MX6UL_PAD_UART1_RTS_B__GPIO1_IO19这个引脚为例子,来解析如何使用设备树+设备驱动完成引脚配置。
例如,arch/arm/boot/dts/imx6ull.dtsi中,子节点iomuxc为:

iomuxc: iomuxc@020e0000 {compatible = "fsl,imx6ul-iomuxc";reg = <0x020e0000 0x4000>;
};

而在arch/arm/boot/dts/imx6ull-alientek-emmc.dts中,对iomuxc子节点进行修改

&iomuxc {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 /* SD1 CD */MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT	0x17059 /* SD1 VSELECT */MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID    0x13058 /* USB_OTG1_ID */>;};

其中MX6UL_PAD_UART1_RTS_B__GPIO1_IO19宏定义的具体含义,可以参考下下面的pinctrl配置信息,先不放这个章节

其中的compatible属性为fsl,imx6ul-iomuxc,那么Linux内核就会根据这个字段,查找相应的驱动文件。
全局搜索后找到drivers/pinctrl/freescale/pinctrl-imx6ul.c中的OF表有匹配的属性

static struct of_device_id imx6ul_pinctrl_of_match[] = {{ .compatible = "fsl,imx6ul-iomuxc", .data = &imx6ul_pinctrl_info, },{ .compatible = "fsl,imx6ull-iomuxc-snvs", .data = &imx6ull_snvs_pinctrl_info, },{ /* sentinel */ }
};

当设备和驱动匹配的时候,就会调用对应的probe成员函数,在其中完成PIN配置
image.png
随后调用pinctrl_register向Linux内核注册一个PIN控制器

imx_pinctrl_desc->name = dev_name(&pdev->dev);
imx_pinctrl_desc->pins = info->pins;
imx_pinctrl_desc->npins = info->npins;
imx_pinctrl_desc->pctlops = &imx_pctrl_ops;
imx_pinctrl_desc->pmxops = &imx_pmx_ops;
imx_pinctrl_desc->confops = &imx_pinconf_ops;
imx_pinctrl_desc->owner = THIS_MODULE;ret = imx_pinctrl_probe_dt(pdev, info);
if (ret) {dev_err(&pdev->dev, "fail to probe dt properties\n");return ret;
}ipctl->info = info;
ipctl->dev = info->dev;
platform_set_drvdata(pdev, ipctl);
ipctl->pctl = pinctrl_register(imx_pinctrl_desc, &pdev->dev, ipctl);
if (!ipctl->pctl) {dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");return -EINVAL;
}

在其中的pctlops,pmxops,confops都是PIN的配置函数,借助这些函数来完成PIN 配置,其他的就留着之后再分析啦~

2.2pinctrl配置信息

宏定义MX6UL_PAD_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>

则代表:
mux_reg:IO复用寄存器地址(MUX类) = 0x0090
conf_reg:io配置寄存器地址(PAD类)= 0x031C
input_reg:输入寄存器地址 = 0x0000
mux_mode:mux_reg寄存器值 = 0x5
input_val:input_reg值 = 0x0
0x17059:conf_reg寄存器值

如上面iomuxc节点的reg地址为0x020e0000,则代表MX6UL_PAD_UART1_RTS_B__GPIO1_IO19的复用寄存器地址为0x020e0000+0x0090=0x020e0090
image.png
mux_mode = 0x5 则代表io复用为GPIO1_IO19
image.png
conf_reg = 0x020e031C,寄存器地址为0x020e031C,值为0x17059

2.3添加pinctrl节点过程

多说不如多做,实战添加外设的pin信息。
iomuxc下imx6ul-evk节点添加pinctrl test子节点

pinctrl_test : testgrp {fsl,pins = <MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 config //待结合gpio子系统来添加具体值,这里先不写>;
};

这样就完成了一个gpio的pinctrl子系统配置。这里因为复用为gpio,所以需要用到gpio子系统,gpio子系统中再继续完成这个实战~

3.最后

哈喽~我是徐章鑫,沪漂嵌入式开发工程师一枚,立志成为嵌入式全栈开发工程师,成为优秀博客创作者,共同学习进步。
以上代码全部放在我私人的github地址,其中有许多自己辛苦敲的例程源码,供大家参考、批评指正,有兴趣还可以直接提patch修改我的仓库~:
https://github.com/Xuzhangxin
觉得不错的话可以点个收藏和star~

这篇关于pinctrl/gpio子系统(1)-pinctrl子系统介绍及驱动源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/667136

相关文章

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

Linux之platform平台设备驱动详解

《Linux之platform平台设备驱动详解》Linux设备驱动模型中,Platform总线作为虚拟总线统一管理无物理总线依赖的嵌入式设备,通过platform_driver和platform_de... 目录platform驱动注册platform设备注册设备树Platform驱动和设备的关系总结在 l

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

Olingo分析和实践之ODataImpl详细分析(重要方法详解)

《Olingo分析和实践之ODataImpl详细分析(重要方法详解)》ODataImpl.java是ApacheOlingoOData框架的核心工厂类,负责创建序列化器、反序列化器和处理器等组件,... 目录概述主要职责类结构与继承关系核心功能分析1. 序列化器管理2. 反序列化器管理3. 处理器管理重要方

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种