引言

GPIO 接口

本目录中的文档详细介绍了如何在驱动程序中访问 GPIO,以及如何为提供 GPIO 的设备编写驱动程序。

什么是 GPIO?

“通用输入/输出”(GPIO) 是一种灵活的软件控制数字信号。它们由多种芯片提供,并且 Linux 开发人员熟悉在嵌入式和定制硬件上使用它们。每个 GPIO 代表连接到特定引脚的位,或球栅阵列 (BGA) 封装上的“球”。电路板原理图显示哪些外部硬件连接到哪些 GPIO。可以通用地编写驱动程序,以便电路板设置代码将此类引脚配置数据传递给驱动程序。

片上系统 (SOC) 处理器严重依赖 GPIO。在某些情况下,每个非专用引脚都可以配置为 GPIO;大多数芯片至少有几十个。可编程逻辑器件(如 FPGA)可以轻松提供 GPIO;电源管理器和音频编解码器等多功能芯片通常有几个这样的引脚,以帮助解决 SOC 上的引脚稀缺问题;还有使用 I2C 或 SPI 串行总线连接的“GPIO 扩展器”芯片。大多数 PC 南桥都有几十个具有 GPIO 功能的引脚(只有 BIOS 固件知道它们是如何使用的)。

GPIO 的确切功能在不同系统之间有所不同。常用选项

  • 输出值是可写的(高 = 1,低 = 0)。某些芯片还具有关于如何驱动该值的选项,例如,只能驱动一个值,支持“线或”和类似的另一个值的方案(特别是“开漏”信号)。

  • 输入值同样是可读的(1,0)。某些芯片支持读取配置为“输出”的引脚,这在“线或”情况下非常有用(以支持双向信号)。GPIO 控制器可能具有输入去抖/消抖逻辑,有时带有软件控制。

  • 输入通常可以用作 IRQ 信号,通常是边沿触发的,但有时是电平触发的。此类 IRQ 可以配置为系统唤醒事件,以使系统从低功耗状态唤醒。

  • 通常,可以根据不同产品板的需要,将 GPIO 配置为输入或输出;也存在单向的。

  • 大多数 GPIO 可以在持有自旋锁的同时访问,但通过串行总线访问的 GPIO 通常不能。某些系统同时支持这两种类型。

在给定的电路板上,每个 GPIO 都用于一个特定目的,例如监视 MMC/SD 卡的插入/移除、检测卡写保护状态、驱动 LED、配置收发器、位敲击串行总线、轻推硬件看门狗、感应开关等等。

常用 GPIO 属性

这些属性通过 GPIO 接口的所有其他文档来满足,理解它们很有用,尤其是在你需要定义 GPIO 映射时。

高电平有效和低电平有效

自然而然地会认为,当 GPIO 的输出信号为 1(“高”)时,它是“活动的”,当它为 0(“低”)时,它是非活动的。然而,实际上,GPIO 的信号可能会在其到达目的地之前被反转,或者设备可能会决定对“活动”的含义采用不同的约定。这些决定对于设备驱动程序应该是透明的,因此可以将 GPIO 定义为高电平有效(“1”表示“活动”,默认值)或低电平有效(“0”表示“活动”),以便驱动程序只需担心逻辑信号,而不必担心线路电平上发生的情况。

开漏和开路源极

有时,共享信号需要使用“开漏”(仅驱动低信号电平)或“开路源极”(仅驱动高信号电平)信号。该术语适用于 CMOS 晶体管;“集电极开路”用于 TTL。上拉或下拉电阻器会产生高或低信号电平。这有时称为“线与”;或者更实际地说,从负逻辑(低 = 真)的角度来看,这是一个“线或”。

开漏信号的一个常见示例是共享的低电平有效 IRQ 线。此外,双向数据总线信号有时会使用开漏信号。

某些 GPIO 控制器直接支持开漏和开路源极输出;许多不支持。当你需要开漏信号但你的硬件不直接支持它时,你可以使用一个常见的习惯用法来使用可以用作输入或输出的任何 GPIO 引脚来模拟它

低电平gpiod_direction_output(gpio, 0) ... 这会驱动信号并覆盖上拉。

高电平gpiod_direction_input(gpio) ... 这会关闭输出,因此上拉(或某些其他设备)控制信号。

相同的逻辑可以应用于模拟开路源极信号,通过驱动高信号并将 GPIO 配置为低电平的输入。这种开漏/开路源极模拟可以由 GPIO 框架透明地处理。

如果你“驱动”信号为高电平,但 gpiod_get_value(gpio) 报告一个低值(在适当的上升时间过去之后),则你知道某些其他组件正在驱动共享信号为低电平。这不一定是错误。作为一个常见的示例,这就是 I2C 时钟被拉伸的方式:需要较慢时钟的从设备会延迟 SCK 的上升沿,并且 I2C 主设备会相应地调整其信号速率。