[PATCH v3] powerpc: Add workaround for MPICs with broken register reads
Olof Johansson
olof at lixom.net
Sat Sep 8 05:13:19 EST 2007
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 at lixom.net>
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 041df77..22a8fa9 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -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
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 95cd90f..117d90a 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -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
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 74c64c0..c0fe063 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -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))
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index 262db6b..c877fa7 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -309,6 +309,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;
More information about the Linuxppc-dev
mailing list