GPIO子系统
1 GPIO子系统简介
上一节讲的pinctrl子系统,核心是配置引脚复用功能与电气属性。当引脚被pinctrl配置为gpio模式后,就需要GPIO子系统来接管。
GPIO子系统负责GPIO初始化,并且提供一套统一的内核操作接口,可快速配置引脚为输入/输出模式、读取引脚电平、控制引脚高低电平。
开发人员只需在设备树中写明GPIO硬件信息,驱动里直接调用GPIO子系统API即可操作引脚。内核屏蔽了底层寄存器差异,大幅简化驱动开发。
I.MX6ULL 的GPIO子系统驱动
- 设备树中的GPIO关键信息
以开发板SD卡检测引脚为例,SD卡检测脚复用为 GPIO1_IO19 ,依靠读取该引脚电平判断SD卡是否插入。
首先依靠pinctrl节点,完成引脚复用与电气配置。
在SD卡总节点 usdhc1 中,通过 cd-gpios 属性定义检测引脚,属性包含三个关键信息:GPIO组、引脚编号、有效电平。
比如低电平有效,就可通过该属性告知驱动,识别SD卡插入状态。
设备树中还存在独立的 gpio1 控制器节点,这是GPIO硬件的核心描述:
- reg :写明GPIO控制器物理寄存器基地址;
- compatible :匹配内核对应的驱动文件;
- gpio-controller :标记该节点为GPIO控制器;
- gpio-cells :固定为2,分别代表引脚编号、电平有效极性。
- GPIO底层驱动原理
I.MX6ULL的GPIO专属驱动文件为 gpio-mxc.c ,依靠设备树 compatible 属性完成驱动匹配,属于标准的平台设备驱动。
驱动核心入口为 mxc_gpio_probe 函数,整套初始化流程简单易懂:
- 绑定硬件参数
通过硬件匹配,加载 imx35_gpio_hwdata 硬件结构体,这个结构体提前定义了GPIO所有寄存器的偏移地址,和芯片手册寄存器地址一一对应,统一管理数据寄存器、方向寄存器、中断寄存器等,方便驱动统一访问硬件。
- 申请并映射寄存器内存
从设备树读取GPIO物理寄存器地址,进行内核虚拟地址映射,内核只能通过虚拟地址操作硬件寄存器。
- 配置中断资源
获取GPIO分组对应的中断号,初始化中断寄存器,默认关闭所有GPIO中断、清除中断标志,统一绑定同一个中断处理函数,管理所有GPIO中断事件。
- 初始化通用GPIO核心框架
调用内核通用函数 bgpio_init ,绑定芯片实际的GPIO寄存器,自动填充GPIO基础操作方法,包括引脚方向配置、电平读取、电平输出等底层函数。
- 注册GPIO控制器
将初始化完成的GPIO控制器结构体注册到内核,注册成功后,内核通用GPIO接口全部生效,其他外设驱动就能直接调用标准GPIO接口操作引脚。
- 绑定中断域
为每个GPIO分配独立中断号,支持引脚中断触发功能,满足按键、检测等中断开发场景。
核心架构逻辑
Linux采用分层设计管理GPIO:
- 设备树层:描述硬件硬件引脚、寄存器地址、外设GPIO绑定关系;
- 芯片驱动层: gpio-mxc.c 适配I.MX6ULL芯片,操作底层寄存器;
- 内核通用框架层:gpiolib核心文件,提供统一通用API;
- 上层驱动层:LED、SD卡、按键等驱动,直接调用API,无需操作寄存器。
简单来说,pinctrl负责引脚模式切换,GPIO子系统负责引脚功能控制,两者配合,完成Linux下引脚的完整配置与使用。