Skip to content

Commit 43f37d4

Browse files
twei-axiadoBartosz Golaszewski
authored andcommitted
gpio: cadence: Add support for edge-triggered interrupts
The Cadence GPIO controller (CDNS IP6508) supports edge-triggered interrupts (rising, falling, and both) via IRQ_TYPE, IRQ_VALUE, and IRQ_ANY_EDGE registers. This commit enables support for these modes in cdns_gpio_irq_set_type(). Although the interrupt status register is cleared on read and lacks per-pin acknowledgment, the driver already handles this safely by reading the ISR once and dispatching all pending interrupts immediately. This allows edge IRQs to be used reliably in controlled environments. Signed-off-by: Tzu-Hao Wei <twei@axiado.com> Reviewed-by: Linus Walleij <linusw@kernel.org> Signed-off-by: Swark Yang <syang@axiado.com> Link: https://lore.kernel.org/r/20260109-axiado-ax3000-cadence-gpio-support-v2-2-fc1e28edf68a@axiado.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
1 parent ea5b4c6 commit 43f37d4

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

drivers/gpio/gpio-cadence.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,31 +98,43 @@ static int cdns_gpio_irq_set_type(struct irq_data *d, unsigned int type)
9898
struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
9999
u32 int_value;
100100
u32 int_type;
101+
u32 int_any;
101102
u32 mask = BIT(d->hwirq);
102103
int ret = 0;
103104

104105
guard(gpio_generic_lock)(&cgpio->gen_gc);
105106

106107
int_value = ioread32(cgpio->regs + CDNS_GPIO_IRQ_VALUE) & ~mask;
107108
int_type = ioread32(cgpio->regs + CDNS_GPIO_IRQ_TYPE) & ~mask;
108-
109109
/*
110-
* The GPIO controller doesn't have an ACK register.
111-
* All interrupt statuses are cleared on a status register read.
112-
* Don't support edge interrupts for now.
110+
* Interrupt polarity and trigger behaviour is configured like this:
111+
*
112+
* (type, value)
113+
* (0, 0) = Falling edge triggered
114+
* (0, 1) = Rising edge triggered
115+
* (1, 0) = Low level triggered
116+
* (1, 1) = High level triggered
113117
*/
118+
int_any = ioread32(cgpio->regs + CDNS_GPIO_IRQ_ANY_EDGE) & ~mask;
114119

115120
if (type == IRQ_TYPE_LEVEL_HIGH) {
116121
int_type |= mask;
117122
int_value |= mask;
118123
} else if (type == IRQ_TYPE_LEVEL_LOW) {
119124
int_type |= mask;
125+
} else if (type == IRQ_TYPE_EDGE_RISING) {
126+
int_value |= mask;
127+
} else if (type == IRQ_TYPE_EDGE_FALLING) {
128+
/* edge trigger, int_value remains cleared for falling */
129+
} else if (type == IRQ_TYPE_EDGE_BOTH) {
130+
int_any |= mask;
120131
} else {
121132
return -EINVAL;
122133
}
123134

124135
iowrite32(int_value, cgpio->regs + CDNS_GPIO_IRQ_VALUE);
125136
iowrite32(int_type, cgpio->regs + CDNS_GPIO_IRQ_TYPE);
137+
iowrite32(int_any, cgpio->regs + CDNS_GPIO_IRQ_ANY_EDGE);
126138

127139
return ret;
128140
}

0 commit comments

Comments
 (0)