Search code examples
linux-kerneldevice-treeirq

STM32MP1 linux IRQs & EXTI controller config in DTS file


I'm running a buildroot linux environment on a STM32MP157 dev board. I have a button with an internal pullup on pin B12. I want to fire an interrupt once the line goes low. On other linux boards like the RPi, I've been able to call gpio_to_irq(<gpio#>) and get the IRQ for that pin. Done, simple. However, on this board, there are only 16 external interrupts connected to the EXTI peripheral; they are configurable in a sense that any port may be connected to the EXTI, but the pin numbers cannot overlap. For example GPIO A12 and B12 may NOT be connected to the EXTI at the same time. I have ensured that no other devices are using and GPIO port pin 12.

I have edited my DTS file to reflect that I want my GPIO B12 connected to the EXTI controller. But so far I have had no luck in making that happen. Here is the documentation for the interrupts provided by ST. If someone can explain how to fix the device tree such that I can request the B12 interrupt from my driver I would really appreciate it.

Here's my DTS file:

    /dts-v1/;
 
#include "stm32mp157.dtsi"
#include "stm32mp15xa.dtsi"
#include "stm32mp15-pinctrl.dtsi"
#include "stm32mp15xxac-pinctrl.dtsi"
#include "stm32mp15xx-dkx.dtsi"
 
/ {
    model = "STMicroelectronics STM32MP157A-DK1 Discovery Board";
    compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
 
    chosen {
        stdout-path = "serial0:115200n8";
    };
 
 
    button {
        compatible = "test,button";
        input-gpios = <&gpiob 12 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; //Works with pull-up once the driver is loaded. 
        interrupts-extended = <&gpiob 12 IRQ_TYPE_EDGE_FALLING>;
        interrupt-names = "qwerty";
        status = "okay";        
    };
 
    led {
        extern-led {
            compatible = "test,led";
            gpios = <&gpiob 10 GPIO_ACTIVE_HIGH>;
            linux,default-trigger = "cpu";
        };
    };
};

I have tried the following:

  • interrupts-extended = <&exti 28 IRQ_TYPE_EDGE_FALLING>; (This SOC only has 16 pins per GPIO bank, so B12 is global GPIO 28)

  • interrupts-extended = <&gpiob 12 IRQ_TYPE_EDGE_FALLING>;

  • interrupt-parent = <&gpiob>;
    interrupts = <12 IRQ_TYPE_EDGE_FALLING>;

Lastly, my stretch goal is to be able to request the IRQ by name, from the interrupt-name property in the device tree. Something like request_irq("qwerty"). Is that possible?

EDIT: I have temporarily connected my pushbutton to GPIO A12, and it successfully fires the interrupt, confirming that the EXTI #12 interrupt is connected to GPIO bank A. How can I go about changing this from within the device tree? Thank you in advance.


Solution

  • Okay I have solved this. Apparently iterating through your GPIO pins with the gpio*_to_irq() functions was the problem. When the function was called, the kernel would immediately configure the EXTI interface for that pin. I thought it was defaulting to Port A, but that was actually caused by iterating through all the GPIO pins looking for the interrupt number starting at GPIO 0, aka Port A Pin 0. So by only calling the gpio_to_irq or gpiod_to_irq function for the pins you need, the kernel will properly configure the EXTI interface for the requested pins.