diff options
Diffstat (limited to 'arch/arm/mach-dove/irq.c')
| -rw-r--r-- | arch/arm/mach-dove/irq.c | 14 | 
1 files changed, 13 insertions, 1 deletions
diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c index 087711524e8..bc4344aa100 100644 --- a/arch/arm/mach-dove/irq.c +++ b/arch/arm/mach-dove/irq.c @@ -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 = {  |