Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit 53b1bfc

Browse files
dianderslinusw
authored andcommitted
pinctrl: rockchip: Avoid losing interrupts when supporting both edges
I was seeing cases where I was losing interrupts when inserting and removing SD cards. Sometimes the card would get "stuck" in the inserted state. I believe that the problem was related to the code to handle the case where we needed both rising and falling edges. This code would disable the interrupt as the polarity was switched. If an interrupt came at the wrong time it could be lost. We'll match what the gpio-dwapb.c driver does upstream and change the interrupt polarity without disabling things. Signed-off-by: Doug Anderson <[email protected]> Reviewed-by: Heiko Stuebner <[email protected]> Tested-by: Heiko Stuebner <[email protected]> Signed-off-by: Linus Walleij <[email protected]>
1 parent eaa27f3 commit 53b1bfc

File tree

1 file changed

+20
-25
lines changed

1 file changed

+20
-25
lines changed

drivers/pinctrl/pinctrl-rockchip.c

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,23 +1398,14 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
13981398
{
13991399
struct irq_chip *chip = irq_get_chip(irq);
14001400
struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
1401-
u32 polarity = 0, data = 0;
14021401
u32 pend;
1403-
bool edge_changed = false;
1404-
unsigned long flags;
14051402

14061403
dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
14071404

14081405
chained_irq_enter(chip, desc);
14091406

14101407
pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
14111408

1412-
if (bank->toggle_edge_mode) {
1413-
polarity = readl_relaxed(bank->reg_base +
1414-
GPIO_INT_POLARITY);
1415-
data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
1416-
}
1417-
14181409
while (pend) {
14191410
unsigned int virq;
14201411

@@ -1434,27 +1425,31 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
14341425
* needs manual intervention.
14351426
*/
14361427
if (bank->toggle_edge_mode & BIT(irq)) {
1437-
if (data & BIT(irq))
1438-
polarity &= ~BIT(irq);
1439-
else
1440-
polarity |= BIT(irq);
1428+
u32 data, data_old, polarity;
1429+
unsigned long flags;
14411430

1442-
edge_changed = true;
1443-
}
1431+
data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
1432+
do {
1433+
spin_lock_irqsave(&bank->slock, flags);
14441434

1445-
generic_handle_irq(virq);
1446-
}
1435+
polarity = readl_relaxed(bank->reg_base +
1436+
GPIO_INT_POLARITY);
1437+
if (data & BIT(irq))
1438+
polarity &= ~BIT(irq);
1439+
else
1440+
polarity |= BIT(irq);
1441+
writel(polarity,
1442+
bank->reg_base + GPIO_INT_POLARITY);
14471443

1448-
if (bank->toggle_edge_mode && edge_changed) {
1449-
/* Interrupt params should only be set with ints disabled */
1450-
spin_lock_irqsave(&bank->slock, flags);
1444+
spin_unlock_irqrestore(&bank->slock, flags);
14511445

1452-
data = readl_relaxed(bank->reg_base + GPIO_INTEN);
1453-
writel_relaxed(0, bank->reg_base + GPIO_INTEN);
1454-
writel(polarity, bank->reg_base + GPIO_INT_POLARITY);
1455-
writel(data, bank->reg_base + GPIO_INTEN);
1446+
data_old = data;
1447+
data = readl_relaxed(bank->reg_base +
1448+
GPIO_EXT_PORT);
1449+
} while ((data & BIT(irq)) != (data_old & BIT(irq)));
1450+
}
14561451

1457-
spin_unlock_irqrestore(&bank->slock, flags);
1452+
generic_handle_irq(virq);
14581453
}
14591454

14601455
chained_irq_exit(chip, desc);

0 commit comments

Comments
 (0)