summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzu-Hao Wei <twei@axiado.com>2026-01-09 12:26:07 +0300
committerBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>2026-01-12 13:41:02 +0300
commit43f37d44f2b8a75a896e218bac1e43d75063f8d3 (patch)
tree2c4aaf00e11827c01d87216710115d165ac6a102
parentea5b4c68e097412f2d3ca13314b672837718a446 (diff)
downloadlinux-43f37d44f2b8a75a896e218bac1e43d75063f8d3.tar.xz
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>
-rw-r--r--drivers/gpio/gpio-cadence.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/gpio/gpio-cadence.c b/drivers/gpio/gpio-cadence.c
index 85aef54d0aec..d7790fc35c22 100644
--- a/drivers/gpio/gpio-cadence.c
+++ b/drivers/gpio/gpio-cadence.c
@@ -98,6 +98,7 @@ static int cdns_gpio_irq_set_type(struct irq_data *d, unsigned int type)
struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
u32 int_value;
u32 int_type;
+ u32 int_any;
u32 mask = BIT(d->hwirq);
int ret = 0;
@@ -105,24 +106,35 @@ static int cdns_gpio_irq_set_type(struct irq_data *d, unsigned int type)
int_value = ioread32(cgpio->regs + CDNS_GPIO_IRQ_VALUE) & ~mask;
int_type = ioread32(cgpio->regs + CDNS_GPIO_IRQ_TYPE) & ~mask;
-
/*
- * The GPIO controller doesn't have an ACK register.
- * All interrupt statuses are cleared on a status register read.
- * Don't support edge interrupts for now.
+ * Interrupt polarity and trigger behaviour is configured like this:
+ *
+ * (type, value)
+ * (0, 0) = Falling edge triggered
+ * (0, 1) = Rising edge triggered
+ * (1, 0) = Low level triggered
+ * (1, 1) = High level triggered
*/
+ int_any = ioread32(cgpio->regs + CDNS_GPIO_IRQ_ANY_EDGE) & ~mask;
if (type == IRQ_TYPE_LEVEL_HIGH) {
int_type |= mask;
int_value |= mask;
} else if (type == IRQ_TYPE_LEVEL_LOW) {
int_type |= mask;
+ } else if (type == IRQ_TYPE_EDGE_RISING) {
+ int_value |= mask;
+ } else if (type == IRQ_TYPE_EDGE_FALLING) {
+ /* edge trigger, int_value remains cleared for falling */
+ } else if (type == IRQ_TYPE_EDGE_BOTH) {
+ int_any |= mask;
} else {
return -EINVAL;
}
iowrite32(int_value, cgpio->regs + CDNS_GPIO_IRQ_VALUE);
iowrite32(int_type, cgpio->regs + CDNS_GPIO_IRQ_TYPE);
+ iowrite32(int_any, cgpio->regs + CDNS_GPIO_IRQ_ANY_EDGE);
return ret;
}