GPIO子系统源码研究

GPIO驱动相关文件

首先查看设备树文件

其中对gpio-controller节点的定义如下

该节点会作为一个platform_device注册到系统中

因为imx6ull的pin和gpio编号的顺序是一一对应的,所以省略了一个gpio-ranges属性

对应该设备的驱动文件为gpio-mxc.c

匹配到了compatible的第二条fsl,imx35-gpio

重点看看其probe函数

probe函数

第一段

472行,调用了如下函数,其根据of_device_id携带的硬件类型信息,给mxc_gpio_data选择硬编码的gpio硬件信息

选择的硬件信息如下:

按照其命名,其中应该保存的是gpio的一些寄存器和特定位的偏移量

由如下的宏进行精简

474行,申请一个名为port的mxc_gpio_port变量,该变量是IMX自定义的变量

其可以理解为对gpio_chip变量的再扩展,变为驱动的私有结构体,记录一些申请到的资源信息,比如内存remap,中断号等

478行,479行,获取寄存器地址并且remap给port->base

483,484行,申请两个硬件中断号

489行,获取gpio的时钟,并在493行开启 ----(但是很显然,imx6ull的gpio-controller设备树节点里面没有clk)

第二段

499行,500行,501行负责开启自动电源管理,并且强制不关闭当前设备一次,直到probe结束

506行,给gpio的中断掩码寄存器写0,即关闭该gpio所有pin的中断

507行,给gpio的中断状态寄存器写1,从而清除中断标志位

517,518,给中断设置handler,低16个和高16个pin分为两个handler

527行,按照传入的寄存器偏移量初始化gpio_chip,并且设置gpio_chip中操作寄存器的函数,同时这里传入的4规定了一个GPIO中引脚的数量(即ngpio)=4x8=32

第三段

535行,判断设备树节点是否有gpio_ranges属性,imx6ull没有,因为其pin的编号和gpio的编号是一一对应的

540-541,设置对应函数

543行,设置按照gpio找对应中断号的函数

544行,设置当前gpio对应的base编号,比如GPIO1就是0,GPIO2就是32,GPIO3就是64

547行,将当前的gpio_chip注册到gpio子系统中,port作为私有变量

同时会在gpio总线上添加一个gpio_device的设备

该设备结构体如下:

该结构体中最重要的是descs数组和base

通过descs数组和base+offset的形式,就可以准确定位到某个gpio pin的gpio_desc结构体

gpio_desc结构体是对一个gpio的pin的描述结构体

551行-557行,为给当前gpio申请连续的32个中断号,并且建立硬件中断和全局中断号的映射关系

565行,初始化 generic irq chip,让所有中断走通用框架

569行,将port添加到全局的mxc_gpio_ports链表中

571行,设置port指针为当前pdev的私有数据

572行,解除电源管理的引用,正常交给系统的电源管理框架操作

使用gpiod系列函数的流程

整个流程如下:

比如使用如下的gpio5的第7个引脚,设置其值为1

需要先用gpio_desc *cs_gpio=gpiod_get(dev,"cs",0)

该函数会根据GPIO的编号和第多少个引脚((5-1)x32+7=135,GPIO5的base是128),在系统中已经注册过的gpio_device(gpio-controller)中找到其descs数组中的对应项,并且返回该desc的指针

然后调用gpiod_set_value(cs_gpio,1)

该函数会使用cs_gpio->gpio_device->gpio_chip中的设置寄存器的函数,对对应的GPIO的DR寄存器进行写入,然后完成输出任务

和pinctrl的关系

gpio和pinctrl的关系是息息相关的

大部分的芯片默认pin复用的就是goio模块

其核心的复用pin到GPIO的功能在pinctrl子系统的代码中实现,为pinmux_ops.request()

大概流程是调用gpiod_get的时候,内部会调用gpiod_get_index,内部会调用gpiod_request,内部会调用__gpiod_request

然后内部会调用request(chip,gpio_chip_hwgpio(desc))

gpio_chip_hwgpio(desc)函数会返回gpio pin在其对应gpio_device的偏移量offset,即申请某个chip的第offset个引脚的复用

对应gpio_chip的request函数在gpio的probe函数中被设置

该mxc_gpio_request函数使用的是通用的gpio复用框架

最终会调用到pinmux_ops中的request函数,复用一个对应编号的pin作为gpio的pin

这里的gpio_range结构体是负责映射gpio的pin到pad的编号的,由于imx6ull的gpio 的pin编号和pad的编号一一对应,所以不需要这个变量,直接走else if分支

前面提到的gpio的设备树节点中的gpio_ranges属性就是负责控制从哪里映射多少个pad到gpio(负责gpio pin和pad编号不一一对应的情况)

由于imx6ull的gpio pin的编号和物理pad的编号一模一样,所以不需要这个属性

相关推荐
AlfredZhao15 小时前
生产环境里,为什么不建议把普通端口直接暴露到公网?
linux·https·443·80
戴为沐2 天前
Linux内存扩容指南
linux
zylyehuo2 天前
Linux 彻底且安全地删除文件
linux
用户805533698033 天前
主线 U-Boot 上 RK3506:和闭源 rkbin 拔河的三个隐性契约
linux·嵌入式
用户034095297913 天前
linux fcitx 5 雾凇拼音 设置在中文输入法下仍然输入英文标点
linux
Web3探索者4 天前
可视化服务器管理和传统命令行区别是什么?新手教程:Linux 运维到底该用图形界面还是 SSH 命令行?
linux·ssh
zylyehuo5 天前
Linux系统中网线与USB网络共享冲突
linux
Sokach10156 天前
Linux Shell 脚本从零到能用:一个新手的一天学习总结
linux
AlfredZhao6 天前
Docker 容器时区不对,`timedatectl` 不存在怎么办?
linux·timezone
zzzzzz3108 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql