diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 065f3b19d6c7..78a7edac577f 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 95cd90fd81c7..117d90aa5008 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 25a81f73cecf..8de29f28b4c7 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 0eb3ab9ec2bb..edb4a7c84506 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h @@ -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;