linux-kernel - Linux GPIO 数字如何获取它们的值?

标签 linux-kernel linux-device-driver gpio

我试图了解 Linux GPIO 数字如何获得它们的值。 例如GPIO mapping for Joule .

我尝试阅读有关 Pinctrl 子系统的 linux 文档,还查看了 Intel Joule 中使用的 GPIO 驱动程序的代码: https://elixir.bootlin.com/linux/latest/source/drivers/pinctrl/intel/pinctrl-broxton.c

然而,这种方式看起来非常特定于平台。我正在寻找一些通用的行业标准。请帮助或指导我阅读一些好文章。

最佳答案

首先,必须了解全局系统 GPIO 编号 (GSGN) 与特定 GPIO Controller 的区别。早些时候,在 GPIO 描述符时代之前,已经使用了 GSGN。切换到描述符方案后,编号方案从(半)静态 GSGN 变为动态编号方案,因此对用户来说毫无意义。取而代之的是,引脚的标签(如果有)或一对带有相对编号的 GPIO Controller 句柄开始使用。这是由资源提供者决定的,例如 ACPI 和设备树。如果出于某种原因,用户想要获得 Controller 和相关编号对,则 libgpiod库和工具提供了实现这一目标的可能性。

因此,Joule GPIO 编号方案的链接非常脆弱,用户不应该知道 GSGN。有多种方法可以获取正在运行的系统上的 Controller 和相关编号。但通常它都与驱动程序和 ACPI 表相关,不需要任何用户参与。

示例:

考虑引脚 UART_1_TXD(出于某种原因,它在该文档中被错误命名,应该是 LPSS_UART1_TXD)。根据 pinctrl-broxton.c 这是具有 ACPI _HID INT34D1 和 _UID 1 的 GPIO Controller 上的引脚 43。

列出所有枚举的 GPIO Controller (可选步骤):

# gpiodetect 
gpiochip0 [INT34D1:00] (83 lines)
gpiochip1 [INT34D1:01] (72 lines)
gpiochip2 [INT34D1:02] (42 lines)
gpiochip3 [INT34D1:03] (31 lines)
gpiochip4 [INT34D1:04] (20 lines)

找到一个具有 _UID 1 的:

# grep -w 1 /sys/bus/acpi/devices/INT34D1\:0*/uid
/sys/bus/acpi/devices/INT34D1:00/uid:1

# gpiodetect | grep -w INT34D1:00
gpiochip0 [INT34D1:00] (83 lines)

因此,有趣的一对是:gpiochip0 43

在实际的资源提供者中它看起来像这样(取自 meta-acpi 项目):

...
*   pin name           pin number   led
*   -----------------------------------------
*   ISH_GPIO_0_LS      35           heartbeat
*   ISH_GPIO_1_LS      33           sd-card
*   ISH_GPIO_2_LS      31           wifi
*   ISH_GPIO_3_LS      29           led-3
...
            GpioIo (
...
                "\\_SB.GPO2",               // GPIO controller
                0)                          // Must be 0
            {
                22,                         // ISH_GPIO_0_LS
                23,                         // ISH_GPIO_1_LS
                24,                         // ISH_GPIO_2_LS
                25                          // ISH_GPIO_3_LS
            }
...

在这里您可以看到通过完整路径(即 \_SB.GPO2)对 Device 对象的引用。

您可以在 meta-acpi 中找到更多示例项目。

如果在任何奇怪的情况下用户真的想要一个无意义的数字,就是这样:

# mount -t debugfs none /sys/kernel/debug/

# cat /sys/kernel/debug/pinctrl/INT34D1\:00/gpio-ranges 
GPIO ranges handled:
0: INT34D1:00 GPIOS [429 - 460] PINS [0 - 31]
32: INT34D1:00 GPIOS [461 - 492] PINS [32 - 63]
64: INT34D1:00 GPIOS [493 - 511] PINS [64 - 82]

# echo $((43-32+461))
472

有关 GPIO 库和子系统的更多详细信息,请参阅 GPIO in-kernel documentation .

关于linux-kernel - Linux GPIO 数字如何获取它们的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55532410/

相关文章:

c - Linux内核线程: How to pass the Linux module write function as the function that the thread has to execute?

linux - 我怎样才能创建一个假的设备文件来模仿 dev/mem?

android - 蓝牙低功耗(蓝牙 4.0)与 Android/Linux

linux - 通过 GPIO 信号启用从 sleep 模式唤醒

c - 如何在工作队列(linux,内核)中使用copy_to_user?

linux - 一个线程获取信号量而另一个线程释放信号量的有效用例是什么?

c - 用于将每个 c 源文件编译成 Linux 内核模块的 Makefile

linux-kernel - 如何在 linux 内核设备树中定义时钟多路复用器

java - Odroid N2 "getGpioList()"返回空数组,无法访问 gpio 端口

javascript - 树莓派 PHP GPIO 读取