How to access the interrupts in /proc/interrupts in Python from the MCP23s17 kernel driver

67 Views Asked by At

I'm attempting to expand the GPIO on a Beaglebone Black Rev C with a MCP23S17 io expansion chip. I already have the chip set up with the MCP23 family kernel driver via DTO such that I can poll the pins over SPI. However, the chip has two interrupt lines that should be supported by the driver. I configured that per the limited documentation and I can see the interrupt in /proc/interrupts:

`79: 0 481ac000.gpio 3 Level spi1.2` (Note, I also added an extra chip select line)

Ideally, I can now go into python and find a function like bindInterrupt(IRQ=79, callback=myFunc). Obviously it wouldn't be that simple but I can't find anything close after hours of searching.

Here is the DTS that configures the MCP23S17:

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/am33xx.h>
#include <dt-bindings/interrupt-controller/irq.h>

/ {
    compatible = "ti,beaglebone", "ti,beaglebone-black";
    /*
    * Free up the pins used by the cape from the pinmux helpers.
    */
    fragment@1 {
        target = <&ocp>;
        __overlay__ {
            P9_29_pinmux { status = "disabled"; };  /* D0    P9_29 (B13) spi1_d0.spi1_d0 */
            P9_30_pinmux { status = "disabled"; };  /* D1    P9_30 (D12) spi1_d1.spi1_d1 */
            P9_31_pinmux { status = "disabled"; };  /* CLK   P9_31 (A13) spi1_clk.spi1_sclk */
            P9_28_pinmux { status = "disabled"; };  /* CS0   P9_28 (A17) spi1_cs0.spi1_cs0 */
            P9_42_pinmux { status = "disabled"; };  /* CS1   P9_42 (C18) gpio0_7.spi1_cs1*/
            P8_07_pinmux { status = "disabled"; };  /* CS2   P8_07 (R7)  timer4.gpio2_2 */
            P8_08_pinmux { status = "disabled"; };  /* INTA  P8_08 (T7)  timer7.gpio2_3 */
            P8_09_pinmux { status = "disabled"; };  /* INTB  P8_09 (T6)  timer5.gpio2_5 */
            P8_10_pinmux { status = "disabled"; };  /* ~RST  P8_10 (U6)  timer6.gpio2_4 */
        };
    };

    fragment@2 {
        target = <&am33xx_pinmux>;
        __overlay__ {
            bb_spi1_pins: pinmux_bb_spi1_pins {
                pinctrl-single,pins = <
                    AM33XX_PADCONF(0x990, PIN_INPUT, MUX_MODE3) /* CLK   P9_31 (A13) spi1_clk.spi1_sclk */
                    AM33XX_PADCONF(0x994, PIN_INPUT, MUX_MODE3) /* DO    P9_29 (B13) spi1_d0.spi1_d0 */
                    AM33XX_PADCONF(0x998, PIN_INPUT, MUX_MODE3) /* DI    P9_30 (D12) spi1_d1.spi1_d1 */
                    AM33XX_PADCONF(0x99c, PIN_OUTPUT, MUX_MODE3) /* CS0  P9_28 (A17) spi1_cs0.spi1_cs0 */
                    AM33XX_PADCONF(0x964, PIN_OUTPUT, MUX_MODE2) /* CS1  P9_42 (C18) gpio0_7.spi1_cs1*/
                    AM33XX_PADCONF(0x890, PIN_OUTPUT, MUX_MODE7) /* CS2  P8_07 (R7)  timer4.gpio2_2 <- My new custom CS pin*/
                    AM33XX_PADCONF(0x894, PIN_INPUT, MUX_MODE7) /* INTA  P8_08 (T7)  timer7.gpio2_3 */
                    AM33XX_PADCONF(0x89c, PIN_INPUT, MUX_MODE7) /* INTB  P8_09 (T6)  timer5.gpio2_5 */
                    AM33XX_PADCONF(0x898, PIN_OUTPUT, MUX_MODE7)/* ~RST  P8_10 (U6)  timer6.gpio2_4 */
                >;
            };
        };
    };

    fragment@3 {
        target = <&spi1>;
        __overlay__ {
            #address-cells = <1>;
            #size-cells = <0>;

            status = "okay";
            pinctrl-names = "default";
            pinctrl-0 = <&bb_spi1_pins>;
            cs-gpios = <0>, <0>, <&gpio2 2 GPIO_ACTIVE_HIGH>;
            ti,pindir-d0-out-d1-in; //Swap D0 and D1 from their default

            gpiom1: gpio@2 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "microchip,mcp23s17";
                gpio-controller;
                #gpio-cells = <2>;
                microchip,spi-present-mask = <0x01>;
                reg = <0x2>;
                spi-max-frequency = <1000000>;
                //Interrupts
                #interrupt-cells = <2>;
                interrupt-controller;
                interrupt-parent = <&gpio2>; //Both interrupts are on GPIO2
                interrupts = <3 IRQ_TYPE_LEVEL_LOW>,    //P8_8 -> GPIO2_3 INTA
                             <5 IRQ_TYPE_LEVEL_LOW>;    //P8_9 -> GPIO2_5 INTB
                reset-gpios = <&gpio2 4 GPIO_ACTIVE_LOW>; //P9_10 -> GPIO2_4 ~RST
            };
        };
    };
};

From what I can tell, it's impossible to truly handle interrupts in Python, but at this point I could do with a Threading thread that polls the necessary pin rapidly. I tried to use Adafruit_BBIO, but I would still need to configure the interrupt control registers in the MCP23S17.

The hardware connection is straight from the MCP23S17 to P8_8 and P8_9, and I'm not planning to override the deafult active-low behavior. So I do need to make sure the pin gets pulled up inside the BBB.

I use gpiod to poll the expansion now. If there's a way to hook gpiod up to the IRQ, I would love to know about it. Otherwise, any solution would be appreciated.

0

There are 0 best solutions below