Merge tag 'dm-3.19-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device...
[firefly-linux-kernel-4.4.55.git] / drivers / pinctrl / pinctrl-rockchip.c
index 3c22dbebc80f202087c9940b05e3887a4c002252..43eacc924b7eb96c0cb0b4fd02d2f91f3c9a2fde 100644 (file)
@@ -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);