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.