|
@@ -1398,10 +1398,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
|
|
{
|
|
|
struct irq_chip *chip = irq_get_chip(irq);
|
|
|
struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
|
|
|
- u32 polarity = 0, data = 0;
|
|
|
u32 pend;
|
|
|
- bool edge_changed = false;
|
|
|
- unsigned long flags;
|
|
|
|
|
|
dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
|
|
|
|
|
@@ -1409,12 +1406,6 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
|
|
|
|
|
pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
|
|
|
|
|
|
- if (bank->toggle_edge_mode) {
|
|
|
- polarity = readl_relaxed(bank->reg_base +
|
|
|
- GPIO_INT_POLARITY);
|
|
|
- data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
|
|
|
- }
|
|
|
-
|
|
|
while (pend) {
|
|
|
unsigned int virq;
|
|
|
|
|
@@ -1434,27 +1425,31 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
|
|
|
* needs manual intervention.
|
|
|
*/
|
|
|
if (bank->toggle_edge_mode & BIT(irq)) {
|
|
|
- if (data & BIT(irq))
|
|
|
- polarity &= ~BIT(irq);
|
|
|
- else
|
|
|
- polarity |= BIT(irq);
|
|
|
+ u32 data, data_old, polarity;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
- edge_changed = true;
|
|
|
- }
|
|
|
+ data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
|
|
|
+ do {
|
|
|
+ spin_lock_irqsave(&bank->slock, flags);
|
|
|
|
|
|
- generic_handle_irq(virq);
|
|
|
- }
|
|
|
+ polarity = readl_relaxed(bank->reg_base +
|
|
|
+ GPIO_INT_POLARITY);
|
|
|
+ if (data & BIT(irq))
|
|
|
+ polarity &= ~BIT(irq);
|
|
|
+ else
|
|
|
+ polarity |= BIT(irq);
|
|
|
+ writel(polarity,
|
|
|
+ bank->reg_base + GPIO_INT_POLARITY);
|
|
|
|
|
|
- if (bank->toggle_edge_mode && edge_changed) {
|
|
|
- /* Interrupt params should only be set with ints disabled */
|
|
|
- spin_lock_irqsave(&bank->slock, flags);
|
|
|
+ spin_unlock_irqrestore(&bank->slock, flags);
|
|
|
|
|
|
- data = readl_relaxed(bank->reg_base + GPIO_INTEN);
|
|
|
- writel_relaxed(0, bank->reg_base + GPIO_INTEN);
|
|
|
- writel(polarity, bank->reg_base + GPIO_INT_POLARITY);
|
|
|
- writel(data, bank->reg_base + GPIO_INTEN);
|
|
|
+ data_old = data;
|
|
|
+ data = readl_relaxed(bank->reg_base +
|
|
|
+ GPIO_EXT_PORT);
|
|
|
+ } while ((data & BIT(irq)) != (data_old & BIT(irq)));
|
|
|
+ }
|
|
|
|
|
|
- spin_unlock_irqrestore(&bank->slock, flags);
|
|
|
+ generic_handle_irq(virq);
|
|
|
}
|
|
|
|
|
|
chained_irq_exit(chip, desc);
|