[POWERPC] Add workaround for MPICs with broken register reads
authorOlof Johansson <olof@lixom.net>
Fri, 7 Sep 2007 19:13:19 +0000 (05:13 +1000)
committerPaul Mackerras <paulus@samba.org>
Thu, 13 Sep 2007 15:33:25 +0000 (01:33 +1000)
Some versions of PWRficient 1682M have an interrupt controller in which
the first register in each pair for interrupt sources doesn't always
read with the right polarity/sense values.

To work around this, keep a software copy of the register instead.  Since
it's not modified from the mpic itself, it's a feasible solution.  Still,
keep it under a config option to avoid wasting memory on other platforms.

Signed-off-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/pasemi/Kconfig
arch/powerpc/sysdev/mpic.c
include/asm-powerpc/mpic.h

index 065f3b19d6c749ea902700601482afaed8b0f59b..78a7edac577f355845bf7835aef0f6094bb6c4a7 100644 (file)
@@ -137,6 +137,16 @@ config MPIC_U3_HT_IRQS
        depends on PPC_MAPLE
        default y
 
+config MPIC_BROKEN_REGREAD
+       bool
+       depends on MPIC
+       help
+         This option enables a MPIC driver workaround for some chips
+         that have a bug that causes some interrupt source information
+         to not read back properly. It is safe to use on other chips as
+         well, but enabling it uses about 8KB of memory to keep copies
+         of the register contents in software.
+
 config IBMVIO
        depends on PPC_PSERIES || PPC_ISERIES
        bool
index 95cd90fd81c74f3ed38dd61766787afb0987965b..117d90aa500840336f1bca64827b3e3c2049e7e4 100644 (file)
@@ -5,6 +5,7 @@ config PPC_PASEMI
        select MPIC
        select PPC_UDBG_16550
        select PPC_NATIVE
+       select MPIC_BROKEN_REGREAD
        help
          This option enables support for PA Semi's PWRficient line
          of SoC processors, including PA6T-1682M
index 25a81f73cecf021ea8d3a6bc470a0ef6c769005f..8de29f28b4c7a6da03f749760b7777dc7356977b 100644 (file)
@@ -228,8 +228,13 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne
        unsigned int    isu = src_no >> mpic->isu_shift;
        unsigned int    idx = src_no & mpic->isu_mask;
 
-       return _mpic_read(mpic->reg_type, &mpic->isus[isu],
-                         reg + (idx * MPIC_INFO(IRQ_STRIDE)));
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+       if (reg == 0)
+               return mpic->isu_reg0_shadow[idx];
+       else
+#endif
+               return _mpic_read(mpic->reg_type, &mpic->isus[isu],
+                                 reg + (idx * MPIC_INFO(IRQ_STRIDE)));
 }
 
 static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
@@ -240,6 +245,11 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
 
        _mpic_write(mpic->reg_type, &mpic->isus[isu],
                    reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
+
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+       if (reg == 0)
+               mpic->isu_reg0_shadow[idx] = value;
+#endif
 }
 
 #define mpic_read(b,r)         _mpic_read(mpic->reg_type,&(b),(r))
index 0eb3ab9ec2bbf5b559907ead942610591269bacd..edb4a7c8450626009f1585096cbd783525f3fda4 100644 (file)
@@ -306,6 +306,10 @@ struct mpic
        unsigned long           *hwirq_bitmap;
 #endif
 
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+       u32                     isu_reg0_shadow[MPIC_MAX_IRQ_SOURCES];
+#endif
+
        /* link */
        struct mpic             *next;