Configuring ACPI for PPS on GPIO pin

1.3k views Asked by At

Update: This was a good learning experience but I discovered that my GPIO expander does not have the interrupt line connected, so I cannot achieve what I was hoping to do.

Instead I'm going to try investigating using one of the pins on my serial connection, which can generate interrupts.


I am using an embedded Linux (4.15.0) single-board computer which has a NXP PCA9535 GPIO expander on the I2C bus. I would like to attach a pulse-per-second (PPS) source to one of the GPIO pins and have it show up under /sys/class/pps/.

Thanks to this question and @0andriy's terrific answer, I have successfully gotten Linux to enumerate the GPIO pins.

Now, I am trying to (i) have one of those pins generate a interrupts when its level changes, and (ii) have the pps-gpio driver expose this pin as a PPS device.

(Regarding (i) above, I have rebuilt my kernel with CONFIG_GPIO_PCA953X_IRQ=y so I think theoretically it should be possible.)

When I run what I have so far, I get (with 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

Any guidance would be very appreciated, as I am completely new to ACPI and am not sure how to begin debugging this.


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 */
                    }
                },
            }
        })
    }
}

I've also tried assigning a button to one of the pins, following this example, and I get:

[   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

Maybe it's noteworthy that the SMBus and a serial device share the same IRQ number? I've asked a question about that over here.

gpioinfo from libgpiod doesn't seem to be able to examine my PCA9535 GPIO controller, but I don't know if that is related or not. I am able to export pins with sysfs and inspect their values.

$ sudo ./gpioinfo 3
gpiochip3 - 16 lines:
gpioinfo: unable to retrieve the line object from chip: Invalid argument

Finally, considering the relevant drivers have seen some recent development, I built Linux 5.4.0 and tried with the same configuration. It is largely the same, but the log is slightly more verbose:

[   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
0

There are 0 answers