更新:这是一次很好的学习经历,但我发现我的 GPIO 扩展器没有连接中断线,所以我无法实现我希望做的事情。
相反,我将尝试使用串行连接上的一个引脚进行调查,这可能会产生中断。
我正在使用嵌入式 Linux (4.15.0) 单板计算机,它在 I2C 总线上有一个 NXP PCA9535 GPIO 扩展器。我想将每秒脉冲 (PPS) 源连接到其中一个 GPIO 引脚,并让它显示在/sys/class/pps/
.
感谢这个问题和@0andriy 的出色回答,我已经成功让 Linux 枚举 GPIO 引脚。
现在,我正在尝试 (i) 让其中一个引脚在其电平变化时产生中断,并且 (ii) 让pps-gpio
驱动程序将此引脚公开为 PPS 设备。
(关于上面的(i),我已经重建了我的内核,CONFIG_GPIO_PCA953X_IRQ=y
所以我认为理论上应该是可能的。)
当我运行到目前为止的内容时,我得到(使用CONFIG_DEBUG_GPIO=y
):
[ 29.906616] ACPI: Host-directed Dynamic ACPI Table Load:
[ 29.906635] ACPI: SSDT 0xFFFF989EFD4AC400 00037A (v05 GPIO 20210212 INTL 20180105)
[ 29.907108] ACPI: Executed 1 blocks of module-level executable AML code
[ 29.933345] acpi PRP0001:00: GPIO: looking up 0 in _CRS
[ 29.933398] pca953x i2c-PRP0001:00: GPIO lookup for consumer reset
[ 29.933401] pca953x i2c-PRP0001:00: using ACPI for GPIO lookup
[ 29.933405] acpi PRP0001:00: GPIO: looking up reset-gpios
[ 29.933410] acpi PRP0001:00: GPIO: looking up reset-gpio
[ 29.933413] pca953x i2c-PRP0001:00: using lookup tables for GPIO lookup
[ 29.933417] pca953x i2c-PRP0001:00: lookup for GPIO reset failed
[ 29.933424] pca953x i2c-PRP0001:00: i2c-PRP0001:00 supply vcc not found, using dummy regulator
[ 29.936087] gpiochip_find_base: found new base at 322
[ 29.936946] gpio gpiochip3: (pca9535): added GPIO chardev (254:3)
[ 29.937000] gpiochip_setup_dev: registered GPIOs 322 to 337 on device: gpiochip3 (pca9535)
[ 29.944603] pps-gpio PRP0001:01: failed to get GPIO from device tree
[ 29.951505] pps-gpio: probe of PRP0001:01 failed with error -38
任何指导将不胜感激,因为我对 ACPI 完全陌生,不知道如何开始调试它。
DefinitionBlock ("gpio.aml", "SSDT", 5, "", "GPIO", 0x20210212)
{
External (_SB.PCI0.SBUS, DeviceObj)
Scope (\_SB.PCI0.SBUS)
{
Device (GPI0)
{
// This special _HID (Hardware ID) tells Linux to use Device Tree-
// compatible device identification.
Name (_HID, "PRP0001")
Name (_DDN, "NXP PCA9535 GPIO expander")
Name (_CRS, ResourceTemplate () {
I2cSerialBusV2(
0x0020, // I2C address
ControllerInitiated,
400000, // Bus speed (see PCA9535 datasheet)
AddressingMode7Bit,
"\\_SB.PCI0.SBUS", // SMBus controller
0x00,
ResourceConsumer,
/* omitted */,
Exclusive,
/* omitted */
)
})
Name (_DSD, Package () {
// Device Properties
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
// These correspond to Linux Device Tree properties
Package () {"compatible", "nxp,pca9535"},
Package () {"gpio-line-names", Package () {
"GPIOA.0", "GPIOA.1", "GPIOA.2", "GPIOA.3",
"GPIOA.4", "GPIOA.5", "GPIOA.6", "GPIOA.7",
"GPIOB.0", "GPIOB.1", "GPIOB.2", "GPIOB.3",
"GPIOB.4", "GPIOB.5", "GPIOB.6", "GPIOB.7",
}},
}
})
}
}
Device (PPS0)
{
Name (_HID, "PRP0001")
Name (_CRS, ResourceTemplate () {
GpioInt (Edge, ActiveLow, Shared, PullDefault, 0,
"\\_SB.PCI0.SBUS.GPI0", 0, ResourceConsumer, iPPS /* ref */)
{
0 // GPIOA.0 pin
}
})
Name (_DSD, Package() {
// Device Properties
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
// https://github.com/torvalds/linux/blob/v4.15/Documentation/devicetree/bindings/pps/pps-gpio.txt
Package () { "compatible", "pps-gpio" },
Package () {
"gpios", Package () {
^PPS0, iPPS, 0, 0 /* required for GpioInt */
}
},
}
})
}
}
我还尝试按照此示例为其中一个引脚分配一个按钮,我得到:
[ 29.953160] gpio-323 (Button A): gpiod_set_debounce: missing set() or set_config() operations
[ 29.953170] gpio-keys PRP0001:02: Unable to get irq number for GPIO 0, error -6
也许值得注意的是 SMBus 和串行设备共享相同的 IRQ 号?我在这里问过一个关于那个的问题。
gpioinfo
fromlibgpiod
似乎无法检查我的 PCA9535 GPIO 控制器,但我不知道这是否相关。我能够使用 sysfs 导出引脚并检查它们的值。
$ sudo ./gpioinfo 3
gpiochip3 - 16 lines:
gpioinfo: unable to retrieve the line object from chip: Invalid argument
最后,考虑到相关驱动已经看到了一些最近的发展,我构建了 Linux 5.4.0 并尝试了相同的配置。大致相同,但日志稍微详细一些:
[ 63.930115] ACPI: Host-directed Dynamic ACPI Table Load:
[ 63.930140] ACPI: SSDT 0xFFFF8B55770F3800 00037A (v05 GPIO 20210212 INTL 20180105)
[ 63.996036] acpi PRP0001:00: GPIO: looking up 0 in _CRS
[ 63.996136] pca953x i2c-PRP0001:00: GPIO lookup for consumer reset
[ 63.996139] pca953x i2c-PRP0001:00: using ACPI for GPIO lookup
[ 63.996143] acpi PRP0001:00: GPIO: looking up reset-gpios
[ 63.996147] acpi PRP0001:00: GPIO: looking up reset-gpio
[ 63.996150] pca953x i2c-PRP0001:00: using lookup tables for GPIO lookup
[ 63.996159] pca953x i2c-PRP0001:00: No GPIO consumer reset found
[ 63.996168] pca953x i2c-PRP0001:00: i2c-PRP0001:00 supply vcc not found, using dummy regulator
[ 63.996210] pca953x i2c-PRP0001:00: using no AI
[ 63.996875] gpiochip_find_base: found new base at 322
[ 63.998604] gpio gpiochip3: (i2c-PRP0001:00): added GPIO chardev (254:3)
[ 63.998672] gpiochip_setup_dev: registered GPIOs 322 to 337 on device: gpiochip3 (i2c-PRP0001:00)
[ 64.009748] pps-gpio PRP0001:01: GPIO lookup for consumer (null)
[ 64.009753] pps-gpio PRP0001:01: using ACPI for GPIO lookup
[ 64.009756] acpi PRP0001:01: GPIO: looking up gpios
[ 64.009763] acpi PRP0001:01: GPIO: _DSD returned PRP0001:01 0 0 0
[ 64.009800] gpio gpiochip3: Persistence not supported for GPIO 0
[ 64.010245] pps-gpio PRP0001:01: GPIO lookup for consumer echo
[ 64.010248] pps-gpio PRP0001:01: using ACPI for GPIO lookup
[ 64.010251] acpi PRP0001:01: GPIO: looking up echo-gpios
[ 64.010254] acpi PRP0001:01: GPIO: looking up echo-gpio
[ 64.010257] pps-gpio PRP0001:01: using lookup tables for GPIO lookup
[ 64.010260] pps-gpio PRP0001:01: No GPIO consumer echo found
[ 64.010264] pps-gpio PRP0001:01: failed to map GPIO to IRQ: -6
[ 64.016241] pps-gpio: probe of PRP0001:01 failed with error -22
[ 64.016493] gpio gpiochip3: Persistence not supported for GPIO 1
[ 64.017007] gpio-keys PRP0001:02: Unable to get irq number for GPIO 0, error -6