如何识别GPIO引脚号? GPIO驱动程序加载了吗?

如何识别GPIO引脚号? GPIO驱动程序加载了吗?

我试图让主板上的 GPIO 引脚正常工作,但我不知道引脚的编号/描述以及是否加载了驱动程序。

我发现指导我应该去哪里回声引脚描述并将输出重定向到/sys/class/gpio/导出

/sys/class/gpio # echo 0 > export

所以我做了。这/系统/类/GPIO/我的系统上存在文件夹,其中包含以下内容:

[user@host ~]$ ls -l /sys/class/gpio/
total 0
--w------- 1 root root 4096 Nov 30 18:12 export
--w------- 1 root root 4096 Nov 30 18:12 unexport
[user@host ~]$ 

(顺便说一句,如果我看到这个文件夹是否意味着驱动程序已加载?)
然后我尝试了主板数据表中的几个引脚名称,但我总是得到以下信息

[root@host gpio]# echo 31 > export 
echo: write error: Invalid argument
[root@host gpio]# 

我在用架构Linux我的内核版本是4.19.2-arch1-1-ARCH。
我使用的主板是超微 X10SBAhttps://www.supermicro.com/products/motherboard/celeron/x10/x10sba.cfm

我能找到的关于主板上 GPIO 的唯一内容是在第 2-25 页X10SBA主板数据表

1 +3.3V
2 SOC_P3V3_GPIO_S5_31
3 SOC_P3V3_GPIO_S5_32
4 SOC_P3V3_GPIO_S5_33
5 SOC_P3V3_GPIO_S5_34
6 SOC_P3V3_GPIO_S5_35
7 SOC_P3V3_GPIO_S5_36
8 SOC_P3V3_GPIO_S5 _37
9 SOC_P3V3_GPIO_S5_38
10 接地

根据我的理解,这意味着该板有 8 个 GPIO。

所以我尝试将各种不同的组合回显/sys/class/gpio/导出喜欢

echo SOC_P3V3_GPIO_S5_31 > export
echo 111 > export
echo 531 > export
echo S531 > export
echo S5_31 > export
...

等等。什么都没起作用。
我在这里做的是根本错误的事情吗?这些GPIO名称的定义在哪里?哪里有出口从哪里获取其信息?我必须先自己做出这些定义吗?也许我必须重新编译我的内核?

我继续尝试找出 GPIO 接头使用的是哪个芯片。

在电路板上的 GPIO 引脚接头 (JP1) 旁边,有一个芯片恩智浦GTL2010数据表)并且引脚从 D1 到 D8 连接到它。我猜这个芯片只是做了一些电压转换,使输出为 3.3V 或 5V。因此信号必定来自 S1-S8 引脚。不幸的是,我无法找到 GTL2010 的这些源极引脚的连接位置,因为走线通向板上的过孔。

但我假设引脚直接连接到CPU。我对此不是 100% 确定。但这是我的假设。

主板上的 CPU 是 Intel Celeron J1900。但不幸的是,我找不到数据表或有关它是否有 GPIO 的任何信息。

是否有可能在 Linux 中列出板上的 GPIO?如何检查我的系统上是否已使用某些 GPIO 驱动程序?

编辑

经过一些研究CPU数据表我发现需要设置 GPIO_BASE_ADDRESS 寄存器(数据表第 1219 页)才能更改 GPIO 设置。该寄存器需要 GPIO 逻辑所在的 I/O 空间中的基地址。现在我不明白我应该把哪个地址放在这里。这可以是 I/O 空间中任意 256 个空闲字节吗?

除此之外,我不明白如何访问 GPIO_BASE_ADDRESS 寄存器。数据表指出该寄存器位于 PCI 配置空间中。总线 0,设备 31(十六进制 1f),功能 0。(数据表第 56 页)

现在 lspci 为我提供了设备 31 的以下输出:

[user@host ~]$ sudo lspci -vvvvvv
...
00:1f.0 ISA bridge: Intel Corporation Atom Processor Z36xxx/Z37xxx Series Power Control Unit (rev 0e)
Subsystem: Super Micro Computer Inc Atom Processor Z36xxx/Z37xxx Series Power Control Unit
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0
Capabilities: [e0] Vendor Specific Information: Len=0c <?>
Kernel driver in use: lpc_ich
Kernel modules: lpc_ich

00:1f.3 SMBus: Intel Corporation Atom Processor E3800 Series SMBus Controller (rev 0e)
Subsystem: Super Micro Computer Inc Atom Processor E3800 Series SMBus Controller
Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Interrupt: pin B routed to IRQ 18
Region 0: Memory at 90a04000 (32-bit, non-prefetchable) [size=32]
Region 4: I/O ports at e000 [size=32]
Capabilities: [50] Power Management version 3
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
Kernel driver in use: i801_smbus
Kernel modules: i2c_i801

我不知道如何访问该区域以将基地址写入寄存器,并且我不知道应该将寄存器放在 IO 空间中的何处。我如何在 C 中实现这一点?我可以利用现有的Linux功能来实现这个功能吗?

编辑

配置空间的十六进制转储输出以下内容:

[user@host ~]$ sudo lspci -xxx -s 00:1f.0
[sudo] password for user: 
00:1f.0 ISA bridge: Intel Corporation Atom Processor Z36xxx/Z37xxx Series Power Control Unit (rev 0e)
00: 86 80 1c 0f 07 00 10 02 0e 00 01 06 00 00 80 00
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 d9 15 16 08
30: 00 00 00 00 e0 00 00 00 00 00 00 00 00 00 00 00
40: 03 04 00 00 02 30 d0 fe 03 05 00 00 02 c0 d0 fe
50: 02 80 d0 fe 02 10 d0 fe 02 00 f0 fe 02 50 d0 fe
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 00 00 00 00 cf ff 00 00 00 00 00 00
e0: 09 00 0c 10 00 00 00 00 00 00 00 00 00 00 00 00
f0: 01 c0 d1 fe 00 00 00 00 1a 0f 0e 01 03 03 00 00

[user@host ~]$

根据我的解释,ACPI_BASE_ADDRESS 寄存器(手册第 1217 页)包含“03 04 00 00”。

GPIO_BASE_ADDRESS 寄存器(手册第 1219 页)包含“03 05 00 00”。

在 dmesg 中查找 acpi 会返回几个条目(太多,无法在此处发布)。

/proc/ioports 输出以下内容:

[user@host ~]$ sudo cat /proc/ioports 
[sudo] password for user: 
0000-006f : PCI Bus 0000:00
  0000-001f : dma1
  0020-0021 : pic1
  0040-0043 : timer0
  0050-0053 : timer1
  0060-0060 : keyboard
  0064-0064 : keyboard
0070-0077 : PCI Bus 0000:00
  0070-0077 : rtc0
0078-0cf7 : PCI Bus 0000:00
  0080-008f : dma page reg
  00a0-00a1 : pic2
  00c0-00df : dma2
  00f0-00ff : fpu
  02e0-02e7 : serial
  02f8-02ff : serial
  03e0-03e7 : serial
  03f8-03ff : serial
  0400-047f : pnp 00:01
    0400-0403 : ACPI PM1a_EVT_BLK
    0404-0405 : ACPI PM1a_CNT_BLK
    0408-040b : ACPI PM_TMR
    0420-042f : ACPI GPE0_BLK
    0430-0433 : iTCO_wdt.0.auto
      0430-0433 : iTCO_wdt
    0450-0450 : ACPI PM2_CNT_BLK
    0460-047f : iTCO_wdt.0.auto
      0460-047f : iTCO_wdt
  0500-05fe : pnp 00:01
  0600-061f : pnp 00:01
  0680-069f : pnp 00:01
  0a30-0a3f : pnp 00:07
0cf8-0cff : PCI conf1
0d00-ffff : PCI Bus 0000:00
  1000-1fff : PCI Bus 0000:01
  b000-cfff : PCI Bus 0000:03
    b000-cfff : PCI Bus 0000:04
      b000-bfff : PCI Bus 0000:07
        b000-b01f : 0000:07:00.0
          b000-b01f : ahci
        b020-b023 : 0000:07:00.0
          b020-b023 : ahci
        b030-b037 : 0000:07:00.0
          b030-b037 : ahci
        b040-b043 : 0000:07:00.0
          b040-b043 : ahci
        b050-b057 : 0000:07:00.0
          b050-b057 : ahci
      c000-cfff : PCI Bus 0000:05
        c000-c01f : 0000:05:00.0
  d000-dfff : PCI Bus 0000:02
    d000-d01f : 0000:02:00.0
  e000-e01f : 0000:00:1f.3
    e000-e01f : i801_smbus
  e020-e027 : 0000:00:02.0

答案1

一般来说,GPIO 引脚是高度硬件特定的。没有系统名称,没有系统驱动程序,没有系统寄存器。

你唯一能做的就是阅读你拥有的信息,谷歌,然后猜测。

正如您的主板手册所说,有一个 GPIO 接头,我们可以假设 GPIO 引脚实际上是物理布线的(这不是给定的;GPIO 引脚可能被 BIOS 用于其他用途,或者它们可能只是处于开放状态)。 “SOC”表示“片上系统”,“3V3”表示 3.3 伏(TTL 电平)。

首先,一个警告:如果此接头直接连接到 SoC,则很容易因错误操作而损坏您的 SoC。静电放电、错误的电压水平、混淆输入与输出等可能会损坏您的 SoC 及其主 CPU。总是如果要使用,请先连接缓冲芯片。即使您在它旁边找到的缓冲芯片实际上保护了这个标头,而不是其他东西。

所以现在我们需要一个数据表。谷歌搜索出现,看起来不错。

它告诉我们,SoC 有 101 个用于 S0 的 GPIO 引脚,以及 43 个用于 S5 的 GPIO 引脚。其中只有 10 个最终出现在主板接头上,但幸运的是我们知道是哪些。其他的可能连接到主板上的其他东西,所以不要管它们很重要。

第 56 页告诉我们 GPIO (PCU) 是一个 256 字节长的可移动 I/O 范围,由 I/O 结构上的 PCI 设备解码。我不知道如何解释GBA: PCI[B:0,D:31,F:0] + 48h。无论如何,这意味着下一步是lspci根据需要尽可能详细地使用,找出可能意味着哪些 PCI 设备,并寻找看起来有希望的 256 字节区域。

从第 1262 页开始,它进一步向我们介绍了 PCU(平台单元控制器),特别是 GPIO 寄存器。

因此,下一步是阅读所有这些内容,理解它,为其编写一个使用正确 PCI 卡和区域的内核驱动程序。该驱动程序将使 I/O 引脚出现在 下/sys/class/gpio。写一篇不应该困难,谷歌搜索现有的 GPIO 驱动程序并针对该硬件修改它们应该足够了。您需要知道如何用 C 语言编程,并且需要能够自学如何编写内核模块。

也有可能已经存在针对该特定硬件的驱动程序,但至少它不在您的内核中(或者您已经看到一些引脚)。

编辑

好的,B、D 和 F 似乎与 PCI 设备的总线、设备和功能相匹配,并且 SMBus 控制器有两个 32 字节区域,因此至少有一个与手册中描述的区域相匹配。

但是, 上没有区域00:1f.0,只有供应商特定的块。数据表中提到了+40ACPI 电源管理、+48hGPIO 和+f0hRCBA,还说“它们是使用基址寄存器 (BAR) 或其他类似方式设置的”,所以也许它不是 BAR/区域,而只是字节在 PCI 配置中。

因此,尝试类似的操作lspci -xxx -s 00:1f.0(以 root 身份),这应该将整个配置空间显示为 hexdump。还要在dmesg启动后查看cat /proc/ioports一下 ACPI 电源管理是否显示在某处(即,是否有与其关联的任何 I/O 端口范围)。我们可以将其与 进行比较+40h。请使用信息编辑问题。

如果 GPIO 范围不在 BAR/区域中,则启用它会变得非常困难;此时您可能应该开始编写内核驱动程序。

编辑

Coreboot 项目还具有访问 Intel 上的 GPIO 内容的代码,例如GPIO.cGPIO.hBaytrail 架构。不确定 Celeron J1900 属于哪种架构,但即使不匹配,它也可能会提示 GPIO 区域是否正常工作。

编辑

好吧,BAR 确实是空的。假设+40h和+48h像条一样工作,它们都是I/O空间(最低位是1),其中

+40h (ACPI) = 0400h
+48h (GPIO) = 0500h 

与 相比/proc/ioports,这是有道理的:ACPI 是 0400-047f,而 0500-05fe 已为同一设备保留pnp 00:01

这就是 I/O 范围,并且它已经被映射。您可以通过/dev/port在正确的偏移处读取和写入来访问它,或者在 C 程序中使用ioperm。尽管我依稀记得 Linux 内核开发人员威胁要禁用其中一个或两个功能,所以我不知道它是否仍然有效。在这种情况下,您需要一个内核驱动程序。

无论如何,在使用 I/O 空间时要非常小心:即使读取错误的地址也可能导致硬件操作,如果您在随机地址上执行此操作,则任何事情都可能发生。所以不行hexdump -C /dev/port。此外,访问大小也很重要。

我在数据表中找不到任何具体的 GPIO I/O 空间如何工作的内容,因此要么您需要在 google 上搜索更好的数据表,要么 Coreboot 文件的工作方式可能足够相似。

答案2

我购买了类似的硬件并遇到了类似的问题。起初我尝试探索别人描述的路线,但后来我解决如下:

我的系统: CPU 版本: Intel(R) Celeron(R) CPU J1900 @ 1.99GHz

在某些时候我认为这实现了 IT8786 芯片。

如果您检查内核配置,您可能会发现对 IT87x 系列驱动程序的支持(当然在 GPIO 驱动程序下)。就我而言,这仅作为模块启用。

然后,我加载了该模块:

sudo insmod /lib/modules/5.8.0-55-generic/kernel/drivers/gpio/gpio-it87.ko

dmesg 返回以下项目:

gpio_it87: Found Chip IT8786 rev 2. 64 GPIO lines starting at 0a00h

通过检查 /dev,gpiochip0 出现,从那里开始,如果您愿意,您可以使用已经提到的 sysfs 方法(尽管已经退休)。

如果您不知道如何将物理引脚与硬件相关联,请尝试以下操作:

apt-get install gpiod

在我的例子中,运行 gpioinfo 返回以下内容:

gpiochip0 - 64 lines:
        line   0:  "it87_gp10"       unused   input  active-high
        line   1:  "it87_gp11"       unused   input  active-high
        line   2:  "it87_gp12"      "sysfs"   input  active-high [used]
        line   3:  "it87_gp13"       unused   input  active-high
        line   4:  "it87_gp14"       unused   input  active-high
        line   5:  "it87_gp15"       unused   input  active-high
        line   6:  "it87_gp16"       unused   input  active-high
        line   7:  "it87_gp17"       unused   input  active-high
        line   8:  "it87_gp20"       unused   input  active-high
        line   9:  "it87_gp21"       unused   input  active-high
        line  10:  "it87_gp22"       unused   input  active-high
        line  11:  "it87_gp23"       unused   input  active-high
        line  12:  "it87_gp24"      "sysfs"   input  active-high [used]
        line  13:  "it87_gp25"       unused   input  active-high
        line  14:  "it87_gp26"       unused   input  active-high
        line  15:  "it87_gp27"       unused   input  active-high
        line  16:  "it87_gp30"       unused   input  active-high
        line  17:  "it87_gp31"       unused   input  active-high
        line  18:  "it87_gp32"       unused   input  active-high
        line  19:  "it87_gp33"       unused   input  active-high
        line  20:  "it87_gp34"       unused   input  active-high
        line  21:  "it87_gp35"       unused   input  active-high
        line  22:  "it87_gp36"      "sysfs"  output  active-high [used]
        line  23:  "it87_gp37"       unused   input  active-high
        line  24:  "it87_gp40"       unused   input  active-high
        line  25:  "it87_gp41"       unused   input  active-high
        line  26:  "it87_gp42"       unused   input  active-high
        line  27:  "it87_gp43"       unused   input  active-high
        line  28:  "it87_gp44"       unused   input  active-high
        line  29:  "it87_gp45"       unused   input  active-high
        line  30:  "it87_gp46"       unused   input  active-high
        line  31:  "it87_gp47"       unused   input  active-high
        line  32:  "it87_gp50"       unused   input  active-high
        line  33:  "it87_gp51"       unused   input  active-high
        line  34:  "it87_gp52"       unused   input  active-high
        line  35:  "it87_gp53"       unused   input  active-high
        line  36:  "it87_gp54"       unused   input  active-high
        line  37:  "it87_gp55"       unused   input  active-high
        line  38:  "it87_gp56"       unused   input  active-high
        line  39:  "it87_gp57"       unused   input  active-high
        line  40:  "it87_gp60"       unused   input  active-high
        line  41:  "it87_gp61"       unused   input  active-high
        line  42:  "it87_gp62"       unused   input  active-high
        line  43:  "it87_gp63"       unused   input  active-high
        line  44:  "it87_gp64"       unused   input  active-high
        line  45:  "it87_gp65"       unused   input  active-high
        line  46:  "it87_gp66"       unused   input  active-high
        line  47:  "it87_gp67"       unused   input  active-high
        line  48:  "it87_gp70"       unused   input  active-high
        line  49:  "it87_gp71"       unused   input  active-high
        line  50:  "it87_gp72"       unused   input  active-high
        line  51:  "it87_gp73"      "sysfs"   input  active-high [used]
        line  52:  "it87_gp74"      "sysfs"  output  active-high [used]
        line  53:  "it87_gp75"      "sysfs"   input  active-high [used]
        line  54:  "it87_gp76"      "sysfs"   input  active-high [used]
        line  55:  "it87_gp77"       unused   input  active-high
        line  56:  "it87_gp80"       unused   input  active-high
        line  57:  "it87_gp81"       unused  output  active-high
        line  58:  "it87_gp82"       unused   input  active-high
        line  59:  "it87_gp83"       unused   input  active-high
        line  60:  "it87_gp84"       unused   input  active-high
        line  61:  "it87_gp85"       unused   input  active-high
        line  62:  "it87_gp86"       unused   input  active-high
        line  63:  "it87_gp87"       unused   input  active-high

您可以使用 gpiod 实用程序来处理不同的引脚。如果您的制造商以某种方式指示您可以使用哪个 GPI/O,那么您可以将“线路”与 it87_gpXX”部分相关联,即 XX 可能由制造商提供的引脚。

可以按照旧方式进行快速检查。

转到 /sys/class/gpio 并查看找到的 gpiochip。 gpiochip 内部的基数是起始位置,gpioinfo 返回的线点是偏移量。

就我而言,我以 448 作为基础。如果我想到达 GP81,即第 57 行,所以我会这样做:

echo 505 > /sys/class/gpio/export

我希望这有帮助!它使我免于编写驱动程序(顺便说一句,制造商给我发送了驱动程序,但它不起作用)

相关内容