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的编号一模一样,所以不需要这个属性

相关推荐
Doro再努力1 小时前
【Linux操作系统13】GDB调试进阶技巧与冯诺依曼体系结构深度解析
linux·运维·服务器
8125035331 小时前
计算机网络全栈连载计划
linux·网络·网络协议·计算机网络
袁袁袁袁满1 小时前
Linux如何保留当前目录本身并清空删除目录内的所有内容(文件+文件夹)?
linux·运维·服务器·清空删除目录内的所有内容
CHANG_THE_WORLD1 小时前
深入理解C语言指针运算与数据搜索
c语言·开发语言
济6171 小时前
ARM Linux 驱动开发篇---Linux设备树实战-- Ubuntu20.04
linux·嵌入式·嵌入式linux驱动开发
Chasing Aurora1 小时前
vscode连接 服务器进行 深度学习
linux·ide·vscode·深度学习·研究生·解压缩·连接服务器
未名编程1 小时前
Linux / macOS / Windows 一条命令安装 Node.js + npm(极限一行版大全)
linux·macos·node.js
哈哈浩丶3 小时前
LK(little kernel)-3:LK的启动流程-作为Android的bootloarder
android·linux·服务器
圥忈&&丅佽&&扗虖4 小时前
linux 安装docker和docker-compose
linux·运维·docker