summaryrefslogtreecommitdiff
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorDaniel Kurtz <djkurtz@chromium.org>2018-03-12 10:45:30 -0600
committerLinus Walleij <linus.walleij@linaro.org>2018-03-26 11:09:49 +0200
commit4c1de0414a134086e9587dc9e7c85cd557c83034 (patch)
tree557a64c93cb81f78c1c07e40f74c213006822709 /drivers/pinctrl
parent44edff1bbc48595a041f65a725203763e3590a73 (diff)
pinctrl/amd: poll InterruptEnable bits in enable_irq
In certain cases interrupt enablement will be delayed relative to when the InterruptEnable bits are written. One example of this is when a GPIO's "debounce" logice is first enabled. After enabling debounce, there is a 900 us "warm up" period during which InterruptEnable[0] (bit 11) will read as 0 despite being written 1. During this time InterruptSts will not be updated, nor will interrupts be delivered, even if the GPIO's interrupt configuration has been written to the register. To work around this delay, poll the InterruptEnable bits after setting them to ensure interrupts have truly been enabled in hardware before returning from the irq_enable handler. Signed-off-by: Daniel Kurtz <djkurtz@chromium.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/pinctrl-amd.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 281b700fe7e9..04ae139671c8 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -348,12 +348,21 @@ static void amd_gpio_irq_enable(struct irq_data *d)
unsigned long flags;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
+ u32 mask = BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
pin_reg |= BIT(INTERRUPT_MASK_OFF);
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
+ /*
+ * When debounce logic is enabled it takes ~900 us before interrupts
+ * can be enabled. During this "debounce warm up" period the
+ * "INTERRUPT_ENABLE" bit will read as 0. Poll the bit here until it
+ * reads back as 1, signaling that interrupts are now enabled.
+ */
+ while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
+ continue;
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
}