|
@@ -46,8 +46,20 @@ static void pmu_irq_ack(struct irq_data *d)
|
|
|
int pin = irq_to_pmu(d->irq);
|
|
|
u32 u;
|
|
|
|
|
|
+ /*
|
|
|
+ * The PMU mask register is not RW0C: it is RW. This means that
|
|
|
+ * the bits take whatever value is written to them; if you write
|
|
|
+ * a '1', you will set the interrupt.
|
|
|
+ *
|
|
|
+ * Unfortunately this means there is NO race free way to clear
|
|
|
+ * these interrupts.
|
|
|
+ *
|
|
|
+ * So, let's structure the code so that the window is as small as
|
|
|
+ * possible.
|
|
|
+ */
|
|
|
u = ~(1 << (pin & 31));
|
|
|
- writel(u, PMU_INTERRUPT_CAUSE);
|
|
|
+ u &= readl_relaxed(PMU_INTERRUPT_CAUSE);
|
|
|
+ writel_relaxed(u, PMU_INTERRUPT_CAUSE);
|
|
|
}
|
|
|
|
|
|
static struct irq_chip pmu_irq_chip = {
|