|
@@ -634,6 +634,29 @@ static void msm_gpio_irq_mask(struct irq_data *d)
|
|
|
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
|
|
|
|
val = readl(pctrl->regs + g->intr_cfg_reg);
|
|
|
+ /*
|
|
|
+ * There are two bits that control interrupt forwarding to the CPU. The
|
|
|
+ * RAW_STATUS_EN bit causes the level or edge sensed on the line to be
|
|
|
+ * latched into the interrupt status register when the hardware detects
|
|
|
+ * an irq that it's configured for (either edge for edge type or level
|
|
|
+ * for level type irq). The 'non-raw' status enable bit causes the
|
|
|
+ * hardware to assert the summary interrupt to the CPU if the latched
|
|
|
+ * status bit is set. There's a bug though, the edge detection logic
|
|
|
+ * seems to have a problem where toggling the RAW_STATUS_EN bit may
|
|
|
+ * cause the status bit to latch spuriously when there isn't any edge
|
|
|
+ * so we can't touch that bit for edge type irqs and we have to keep
|
|
|
+ * the bit set anyway so that edges are latched while the line is masked.
|
|
|
+ *
|
|
|
+ * To make matters more complicated, leaving the RAW_STATUS_EN bit
|
|
|
+ * enabled all the time causes level interrupts to re-latch into the
|
|
|
+ * status register because the level is still present on the line after
|
|
|
+ * we ack it. We clear the raw status enable bit during mask here and
|
|
|
+ * set the bit on unmask so the interrupt can't latch into the hardware
|
|
|
+ * while it's masked.
|
|
|
+ */
|
|
|
+ if (irqd_get_trigger_type(d) & IRQ_TYPE_LEVEL_MASK)
|
|
|
+ val &= ~BIT(g->intr_raw_status_bit);
|
|
|
+
|
|
|
val &= ~BIT(g->intr_enable_bit);
|
|
|
writel(val, pctrl->regs + g->intr_cfg_reg);
|
|
|
|
|
@@ -655,6 +678,7 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
|
|
|
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
|
|
|
|
val = readl(pctrl->regs + g->intr_cfg_reg);
|
|
|
+ val |= BIT(g->intr_raw_status_bit);
|
|
|
val |= BIT(g->intr_enable_bit);
|
|
|
writel(val, pctrl->regs + g->intr_cfg_reg);
|
|
|
|