Hello, I've recently purchased a sifive unmatched board, and have tried to complete its devicetree using the schematics. Doing so, I enabled some sub-functions of its PMIC chip (DA9063). Those which matter for this email are: - power button, notified by interrupt - hwmon, based on an ADC which signals conversion completion with an interrupt The PMIC has an interrupt line, active low, connected to line 1 of the GPIO controller embedded in the board's SoC (fu740). Internally to the SoC, the GPIO has one interrupt line per GPIO line, connected to the PLIC. The issue I originally had was, which I noticed with the ADC but could equally reproduce with the power button, I could only ever get a single IRQ to be processed. Reading the corresponding registers (with the script attached), enabling IRQ and regmap tracing, I saw the output at the end of this email. Here is how I read the register states: - initial state: The PMIC interrupt line is in its idle state (high). The GPIO controller noticed the high state, and armed the corresponding interrupt-pending bit - this an important first piece of information. As the corresponding interrupt-enable is cleared, no interrupt is signalled and the PLIC does not see an interrupt pending. This is all good. - after one button press: The PMIC interrupt line is again in its idle state, so the interrupt source was cleared. I know it triggered as the power button input event does fire as intended. This time, the GPIO controller noticed 3 interrupt conditions on this line: low, rising edge, and high. This means it was cleared *before* the PMIC line went high: - if it was cleared after, only "high" should be visible - if is was never cleared, all low/rise/high/fall interrupt conditions would be present As the "low" interrupt is enabled, I believe (but cannot check) that it notified the PLIC of the interrupt. But like before, the PLIC does not see this interrupt being signalled. As a result, the hart assigned to this interrupt (here, hart4) does not get interrupted even after it gets re-assigned to the corresponding PLIC line, so the GPIO interrupt pending bits are never cleared, and it cannot signal any further interrupt to the PLIC. Pressing the key a second time, the only difference is that the GPIO controller noticed the falling edge interrupt condition, which is masked so nothing happens. The kernel/debug/tracing/trace buffer tells a similar story: - the GPIO regmap clear writes happen first - later, the PMIC interrupt source register is cleared (the write to register 6) Checking gpio-sifive.c and irq-sifive-plic.c, I see: - the GPIO propagates irq_mask and irq_unmask to the PLIC - the PLIC implements irq masking by making the interrupt line handled by no hart Reading the PLIC documentation, I cannot tell if this behaviour of the PLIC ("losing" an interrupt if there is no hart servicing it) is intended or not. If it is intended, then what is the proper way of masking an interrupt ? Is it to lower that interrupt priority ? (which I did not try) Is it to mask it outside the PLIC (so on the GPIO controller here) ? I did try the latter as a quick hack, and it allows repeated interrupts, fixing both the power button and the hwmon subsystems. But I am not sure it is possible to do this while being certain to never lose an interrupt - but I am very new to interrupt handling in Linux. Traces: # ./unmatched_gpio_irq_debug.py 1 gpio_pin=1 gpio_mask=0b10 plic_irq=24 plic_mask=0b1000000000000000000000000 GPIO 1: dir=in in=1 out=0 irq_en=low irq_pending=high PLIC 24: priority=1 irq_en=hart4 irq_pending=False hart min prio: 1=0, 2=0, 3=0, 4=0 # echo 1 > /sys/kernel/debug/tracing/events/regmap/enable; echo 1 > /sys/kernel/debug/tracing/events/irq/enable button pressed once here # echo 0 > /sys/kernel/debug/tracing/events/regmap/enable; echo 0 > /sys/kernel/debug/tracing/events/irq/enable # ./unmatched_gpio_irq_debug.py 1 gpio_pin=1 gpio_mask=0b10 plic_irq=24 plic_mask=0b1000000000000000000000000 GPIO 1: dir=in in=1 out=0 irq_en=low irq_pending=rise,high,low PLIC 24: priority=1 irq_en=hart4 irq_pending=False hart min prio: 1=0, 2=0, 3=0, 4=0 Trace output with i2c interrupts trimmed for brevity: -0 [000] d.h2 102.707972: irq_handler_entry: irq=53 name=da9063-irq -0 [000] d.h2 102.707976: irq_handler_exit: irq=53 ret=handled -0 [000] d.h4 102.708019: regmap_reg_write: 10060000.gpio reg=1c val=2 -0 [000] d.h4 102.708022: regmap_reg_write: 10060000.gpio reg=24 val=2 -0 [000] d.h4 102.708024: regmap_reg_write: 10060000.gpio reg=2c val=2 -0 [000] d.h4 102.708026: regmap_reg_write: 10060000.gpio reg=34 val=2 irq/53-da9063-i-140 [002] ...1 102.708072: regmap_hw_read_start: 0-0058 reg=0 count=1 irq/53-da9063-i-140 [002] d.h2 102.708121: irq_handler_entry: irq=5 name=riscv-timer irq/53-da9063-i-140 [002] dnh2 102.708159: irq_handler_exit: irq=5 ret=handled (snip) irq/53-da9063-i-140 [002] ...1 102.709089: regmap_hw_read_done: 0-0058 reg=0 count=1 irq/53-da9063-i-140 [002] ...1 102.709095: regmap_reg_read: 0-0058 reg=0 val=0 irq/53-da9063-i-140 [002] ...1 102.709099: regmap_hw_read_start: 0-0058 reg=6 count=4 (snip) irq/53-da9063-i-140 [002] ...1 102.709879: regmap_hw_read_done: 0-0058 reg=6 count=4 irq/53-da9063-i-140 [002] ...1 102.709893: regmap_hw_read_start: 0-0058 reg=0 count=1 (snip) irq/53-da9063-i-140 [002] ...1 102.710371: regmap_hw_read_done: 0-0058 reg=0 count=1 irq/53-da9063-i-140 [002] ...1 102.710374: regmap_reg_read: 0-0058 reg=0 val=0 irq/53-da9063-i-140 [002] ...1 102.710378: regmap_hw_write_start: 0-0058 reg=6 count=1 (snip) irq/53-da9063-i-140 [002] ...1 102.710763: regmap_hw_write_done: 0-0058 reg=6 count=1 irq/53-da9063-i-140 [002] ...1 102.710767: regmap_reg_write: 0-0058 reg=6 val=1 irq/53-da9063-i-140 [002] ...1 102.710783: regmap_hw_read_start: 0-0058 reg=0 count=1 (snip) irq/53-da9063-i-140 [002] ...1 102.711268: regmap_hw_read_done: 0-0058 reg=0 count=1 irq/53-da9063-i-140 [002] ...1 102.711271: regmap_reg_read: 0-0058 reg=0 val=0 irq/53-da9063-i-140 [002] ...1 102.711274: regmap_hw_read_start: 0-0058 reg=1 count=1 (snip) irq/53-da9063-i-140 [002] ...1 102.711770: regmap_hw_read_done: 0-0058 reg=1 count=1 irq/53-da9063-i-140 [002] ...1 102.711773: regmap_reg_read: 0-0058 reg=1 val=0 irq/53-da9063-i-140 [002] d..3 102.712183: softirq_raise: vec=6 [action=TASKLET] ksoftirqd/2-23 [002] ..s1 102.714162: softirq_entry: vec=6 [action=TASKLET] ksoftirqd/2-23 [002] ..s1 102.714173: softirq_exit: vec=6 [action=TASKLET] Regards, -- Vincent Pelletier GPG fingerprint 983A E8B7 3B91 1598 7A92 3845 CAC9 3691 4257 B0C1