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

相关文章

Java中HashMap的用法详细介绍

《Java中HashMap的用法详细介绍》JavaHashMap是一种高效的数据结构,用于存储键值对,它是基于哈希表实现的,提供快速的插入、删除和查找操作,:本文主要介绍Java中HashMap... 目录一.HashMap1.基本概念2.底层数据结构:3.HashCode和equals方法为什么重写Has

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

Springboot项目构建时各种依赖详细介绍与依赖关系说明详解

《Springboot项目构建时各种依赖详细介绍与依赖关系说明详解》SpringBoot通过spring-boot-dependencies统一依赖版本管理,spring-boot-starter-w... 目录一、spring-boot-dependencies1.简介2. 内容概览3.核心内容结构4.

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

MySQL中读写分离方案对比分析与选型建议

《MySQL中读写分离方案对比分析与选型建议》MySQL读写分离是提升数据库可用性和性能的常见手段,本文将围绕现实生产环境中常见的几种读写分离模式进行系统对比,希望对大家有所帮助... 目录一、问题背景介绍二、多种解决方案对比2.1 原生mysql主从复制2.2 Proxy层中间件:ProxySQL2.3

setsid 命令工作原理和使用案例介绍

《setsid命令工作原理和使用案例介绍》setsid命令在Linux中创建独立会话,使进程脱离终端运行,适用于守护进程和后台任务,通过重定向输出和确保权限,可有效管理长时间运行的进程,本文给大家介... 目录setsid 命令介绍和使用案例基本介绍基本语法主要特点命令参数使用案例1. 在后台运行命令2.

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

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 的选择策略三、性能对比