Skip to content

Commit b85bfa2

Browse files
djkurtzlinusw
authored andcommitted
pinctrl/amd: poll InterruptEnable bits in amd_gpio_irq_set_type
From the AMD BKDG, if WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the debounce registers of *any* gpio will block wake/interrupt status generation for *all* gpios for a length of time that depends on WAKE_INT_MASTER_REG.MaskStsLength[11:0]. During this period the Interrupt Delivery bit (INTERRUPT_ENABLE) will read as 0. In commit 4c1de04 ("pinctrl/amd: poll InterruptEnable bits in enable_irq") we tried to fix this same "gpio Interrupts are blocked immediately after writing debounce registers" problem, but incorrectly assumed it only affected the gpio whose debounce was being configured and not ALL gpios. To solve this for all gpios, we move the polling loop from amd_gpio_irq_enable() to amd_gpio_irq_set_type(), while holding the gpio spinlock. This ensures that another gpio operation (e.g. amd_gpio_irq_unmask()) can read a temporarily disabled IRQ and incorrectly disable it while trying to modify some other register bits. Fixes: 4c1de04 pinctrl/amd: poll InterruptEnable bits in enable_irq Signed-off-by: Daniel Kurtz <djkurtz@chromium.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent 6bf4ca7 commit b85bfa2

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

drivers/pinctrl/pinctrl-amd.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -348,21 +348,12 @@ static void amd_gpio_irq_enable(struct irq_data *d)
348348
unsigned long flags;
349349
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
350350
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
351-
u32 mask = BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
352351

353352
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
354353
pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
355354
pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
356355
pin_reg |= BIT(INTERRUPT_MASK_OFF);
357356
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
358-
/*
359-
* When debounce logic is enabled it takes ~900 us before interrupts
360-
* can be enabled. During this "debounce warm up" period the
361-
* "INTERRUPT_ENABLE" bit will read as 0. Poll the bit here until it
362-
* reads back as 1, signaling that interrupts are now enabled.
363-
*/
364-
while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
365-
continue;
366357
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
367358
}
368359

@@ -426,7 +417,7 @@ static void amd_gpio_irq_eoi(struct irq_data *d)
426417
static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
427418
{
428419
int ret = 0;
429-
u32 pin_reg;
420+
u32 pin_reg, pin_reg_irq_en, mask;
430421
unsigned long flags, irq_flags;
431422
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
432423
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
@@ -495,6 +486,28 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
495486
}
496487

497488
pin_reg |= CLR_INTR_STAT << INTERRUPT_STS_OFF;
489+
/*
490+
* If WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the
491+
* debounce registers of any GPIO will block wake/interrupt status
492+
* generation for *all* GPIOs for a lenght of time that depends on
493+
* WAKE_INT_MASTER_REG.MaskStsLength[11:0]. During this period the
494+
* INTERRUPT_ENABLE bit will read as 0.
495+
*
496+
* We temporarily enable irq for the GPIO whose configuration is
497+
* changing, and then wait for it to read back as 1 to know when
498+
* debounce has settled and then disable the irq again.
499+
* We do this polling with the spinlock held to ensure other GPIO
500+
* access routines do not read an incorrect value for the irq enable
501+
* bit of other GPIOs. We keep the GPIO masked while polling to avoid
502+
* spurious irqs, and disable the irq again after polling.
503+
*/
504+
mask = BIT(INTERRUPT_ENABLE_OFF);
505+
pin_reg_irq_en = pin_reg;
506+
pin_reg_irq_en |= mask;
507+
pin_reg_irq_en &= ~BIT(INTERRUPT_MASK_OFF);
508+
writel(pin_reg_irq_en, gpio_dev->base + (d->hwirq)*4);
509+
while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
510+
continue;
498511
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
499512
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
500513

0 commit comments

Comments
 (0)