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; }