From: Matt Porter Patch from Eugene to do some cleanup of the PPC4xx PIC code. Separates the interrupts that can have polarity/triggering modified for platform modification if necessary. Between the two of us, it's tested on most of the affected platforms. Signed-off-by: Eugene Surovegin Signed-off-by: Matt Porter Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc/platforms/4xx/ebony.c | 84 --- 25-akpm/arch/ppc/platforms/4xx/ibm405ep.c | 9 25-akpm/arch/ppc/platforms/4xx/ibm405gp.c | 9 25-akpm/arch/ppc/platforms/4xx/ibm405gpr.c | 9 25-akpm/arch/ppc/platforms/4xx/ibm440gp.c | 13 25-akpm/arch/ppc/platforms/4xx/ibm440gx.c | 17 25-akpm/arch/ppc/platforms/4xx/ibmnp405h.h | 4 25-akpm/arch/ppc/platforms/4xx/ibmstbx25.c | 9 25-akpm/arch/ppc/platforms/4xx/oak.c | 30 - 25-akpm/arch/ppc/platforms/4xx/ocotea.c | 6 25-akpm/arch/ppc/platforms/4xx/redwood6.c | 50 -- 25-akpm/arch/ppc/platforms/4xx/sycamore.c | 52 -- 25-akpm/arch/ppc/syslib/Makefile | 4 25-akpm/arch/ppc/syslib/ibm44x_common.c | 12 25-akpm/arch/ppc/syslib/ppc403_pic.c | 127 +++++ 25-akpm/arch/ppc/syslib/ppc4xx_pic.c | 669 ++++++++--------------------- 25-akpm/arch/ppc/syslib/ppc4xx_setup.c | 5 25-akpm/arch/ppc/syslib/xilinx_pic.c | 9 25-akpm/include/asm-ppc/ibm44x.h | 4 25-akpm/include/asm-ppc/ppc4xx_pic.h | 51 +- 20 files changed, 476 insertions(+), 697 deletions(-) diff -puN arch/ppc/platforms/4xx/ebony.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/ebony.c --- 25/arch/ppc/platforms/4xx/ebony.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/ebony.c Tue Nov 23 17:13:13 2004 @@ -55,73 +55,22 @@ static struct ibm44x_clocks clocks __initdata; /* - * Ebony IRQ triggering/polarity settings + * Ebony external IRQ triggering/polarity settings */ -static u_char ebony_IRQ_initsenses[] __initdata = { - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 0: UART 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 1: UART 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 2: IIC 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 3: IIC 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 4: PCI Inb Mess */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 5: PCI Cmd Wrt */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 6: PCI PM */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 7: PCI MSI 0 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 8: PCI MSI 1 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 9: PCI MSI 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 10: MAL TX EOB */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 11: MAL RX EOB */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 12: DMA Chan 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 13: DMA Chan 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 14: DMA Chan 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 15: DMA Chan 3 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 16: Reserved */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 17: Reserved */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 18: GPT Timer 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 19: GPT Timer 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 20: GPT Timer 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 21: GPT Timer 3 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 22: GPT Timer 4 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 23: Ext Int 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 24: Ext Int 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 25: Ext Int 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 26: Ext Int 3 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 27: Ext Int 4 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* 28: Ext Int 5 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 29: Ext Int 6 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 30: UIC1 NC Int */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 31: UIC1 Crit Int */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 32: MAL SERR */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 33: MAL TXDE */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 34: MAL RXDE */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 35: ECC Unc Err */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 36: ECC Corr Err */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 37: Ext Bus Ctrl */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 38: Ext Bus Mstr */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 39: OPB->PLB */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 40: PCI MSI 3 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 41: PCI MSI 4 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 42: PCI MSI 5 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 43: PCI MSI 6 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 44: PCI MSI 7 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 45: PCI MSI 8 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 46: PCI MSI 9 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 47: PCI MSI 10 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 48: PCI MSI 11 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 49: PLB Perf Mon */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 50: Ext Int 7 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 51: Ext Int 8 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 52: Ext Int 9 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 53: Ext Int 10 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 54: Ext Int 11 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 55: Ext Int 12 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 56: Ser ROM Err */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 57: Reserved */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 58: Reserved */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 59: PCI Async Err */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 60: EMAC 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 61: EMAC 0 WOL */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 62: EMAC 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 63: EMAC 1 WOL */ +unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ0: PCI slot 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ1: PCI slot 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ2: PCI slot 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ3: PCI slot 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ4: IRDA */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ5: SMI pushbutton */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ6: PHYs */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ7: AUX */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ8: EXT */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ9: EXT */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ10: EXT */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ11: EXT */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ12: EXT */ }; static void __init @@ -358,9 +307,6 @@ ebony_setup_arch(void) ebony_early_serial_map(); - ibm4xxPIC_InitSenses = ebony_IRQ_initsenses; - ibm4xxPIC_NumInitSenses = sizeof(ebony_IRQ_initsenses); - /* Identify the system */ printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n"); } diff -puN arch/ppc/platforms/4xx/ibm405ep.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/ibm405ep.c --- 25/arch/ppc/platforms/4xx/ibm405ep.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/ibm405ep.c Tue Nov 23 17:13:13 2004 @@ -21,6 +21,7 @@ #include #include +#include #include @@ -132,3 +133,11 @@ struct ocp_def core_ocp[] = { { .vendor = OCP_VENDOR_INVALID } }; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xffff7f80, + .triggering = 0x00000000, + .ext_irq_mask = 0x0000007f, /* IRQ0 - IRQ6 */ + } +}; diff -puN arch/ppc/platforms/4xx/ibm405gp.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/ibm405gp.c --- 25/arch/ppc/platforms/4xx/ibm405gp.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/ibm405gp.c Tue Nov 23 17:13:13 2004 @@ -22,6 +22,7 @@ #include #include #include +#include static struct ocp_func_emac_data ibm405gp_emac0_def = { .rgmii_idx = -1, /* No RGMII */ @@ -109,3 +110,11 @@ struct ocp_def core_ocp[] = { { .vendor = OCP_VENDOR_INVALID } }; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xffffff80, + .triggering = 0x10000000, + .ext_irq_mask = 0x0000007f, /* IRQ0 - IRQ6 */ + } +}; diff -puN arch/ppc/platforms/4xx/ibm405gpr.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/ibm405gpr.c --- 25/arch/ppc/platforms/4xx/ibm405gpr.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/ibm405gpr.c Tue Nov 23 17:13:13 2004 @@ -18,6 +18,7 @@ #include #include #include +#include static struct ocp_func_emac_data ibm405gpr_emac0_def = { .rgmii_idx = -1, /* No RGMII */ @@ -106,3 +107,11 @@ struct ocp_def core_ocp[] = { { .vendor = OCP_VENDOR_INVALID } }; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xffffe000, + .triggering = 0x10000000, + .ext_irq_mask = 0x00001fff, /* IRQ7 - IRQ12, IRQ0 - IRQ6 */ + } +}; diff -puN arch/ppc/platforms/4xx/ibm440gp.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/ibm440gp.c --- 25/arch/ppc/platforms/4xx/ibm440gp.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/ibm440gp.c Tue Nov 23 17:13:13 2004 @@ -19,6 +19,7 @@ #include #include #include +#include static struct ocp_func_emac_data ibm440gp_emac0_def = { .rgmii_idx = -1, /* No RGMII */ @@ -149,3 +150,15 @@ struct ocp_def core_ocp[] = { { .vendor = OCP_VENDOR_INVALID } }; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xfffffe03, + .triggering = 0x01c00000, + .ext_irq_mask = 0x000001fc, /* IRQ0 - IRQ6 */ + }, + { .polarity = 0xffffc0ff, + .triggering = 0x00ff8000, + .ext_irq_mask = 0x00003f00, /* IRQ7 - IRQ12 */ + }, +}; diff -puN arch/ppc/platforms/4xx/ibm440gx.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/ibm440gx.c --- 25/arch/ppc/platforms/4xx/ibm440gx.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/ibm440gx.c Tue Nov 23 17:13:13 2004 @@ -19,6 +19,7 @@ #include #include #include +#include static struct ocp_func_emac_data ibm440gx_emac0_def = { .rgmii_idx = -1, /* No RGMII */ @@ -215,3 +216,19 @@ struct ocp_def core_ocp[] = { { .vendor = OCP_VENDOR_INVALID } }; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xfffffe03, + .triggering = 0x01c00000, + .ext_irq_mask = 0x000001fc, /* IRQ0 - IRQ6 */ + }, + { .polarity = 0xffffc0ff, + .triggering = 0x00ff8000, + .ext_irq_mask = 0x00003f00, /* IRQ7 - IRQ12 */ + }, + { .polarity = 0xffff83ff, + .triggering = 0x000f83c0, + .ext_irq_mask = 0x00007c00, /* IRQ13 - IRQ17 */ + }, +}; diff -puN arch/ppc/platforms/4xx/ibmnp405h.h~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/ibmnp405h.h --- 25/arch/ppc/platforms/4xx/ibmnp405h.h~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/ibmnp405h.h Tue Nov 23 17:13:13 2004 @@ -132,8 +132,7 @@ #define DCRN_UIC1_BASE 0x0D0 #define DCRN_CPC0_EPRCSR 0x0F3 -#define UIC0_UIC1NC 30 /* UIC1 non-critical interrupt */ -#define UIC0_UIC1CR 31 /* UIC1 critical interrupt */ +#define UIC0_UIC1NC 0x00000002 #define CHR1_CETE 0x00000004 /* CPU external timer enable */ #define UIC0 DCRN_UIC0_BASE @@ -141,7 +140,6 @@ #undef NR_UICS #define NR_UICS 2 -#define UIC_CASCADE_MASK 0x0003 /* bits 30 & 31 */ /* EMAC DCRN's FIXME: armin */ #define DCRN_MALRXCTP2R(base) ((base) + 0x42) /* Channel Rx 2 Channel Table Pointer */ diff -puN arch/ppc/platforms/4xx/ibmstbx25.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/ibmstbx25.c --- 25/arch/ppc/platforms/4xx/ibmstbx25.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/ibmstbx25.c Tue Nov 23 17:13:13 2004 @@ -12,6 +12,7 @@ #include #include #include +#include static struct ocp_func_iic_data ibmstbx25_iic0_def = { .fast_mode = 0, /* Use standad mode (100Khz) */ @@ -57,3 +58,11 @@ struct ocp_def core_ocp[] __initdata = { { .vendor = OCP_VENDOR_INVALID } }; + +/* Polarity and triggering settings for internal interrupt sources */ +struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { + { .polarity = 0xffff8f80, + .triggering = 0x00000000, + .ext_irq_mask = 0x0000707f, /* IRQ7 - IRQ9, IRQ0 - IRQ6 */ + } +}; diff -puN arch/ppc/platforms/4xx/oak.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/oak.c --- 25/arch/ppc/platforms/4xx/oak.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/oak.c Tue Nov 23 17:13:13 2004 @@ -101,8 +101,8 @@ platform_init(unsigned long r3, unsigned ppc_md.setup_arch = oak_setup_arch; ppc_md.show_percpuinfo = oak_show_percpuinfo; ppc_md.irq_canonicalize = NULL; - ppc_md.init_IRQ = oak_init_IRQ; - ppc_md.get_irq = oak_get_irq; + ppc_md.init_IRQ = ppc4xx_pic_init; + ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ ppc_md.init = NULL; ppc_md.restart = oak_restart; @@ -156,32 +156,6 @@ oak_show_percpuinfo(struct seq_file *m, } /* - * Document me. - */ -void __init -oak_init_IRQ(void) -{ - int i; - - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].handler = ppc4xx_pic; - } - - return; -} - -/* - * Document me. - */ -int -oak_get_irq(struct pt_regs *regs) -{ - return (ppc4xx_pic_get_irq(regs)); -} - -/* * Document me. */ void diff -puN arch/ppc/platforms/4xx/ocotea.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/ocotea.c --- 25/arch/ppc/platforms/4xx/ocotea.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/ocotea.c Tue Nov 23 17:13:13 2004 @@ -347,12 +347,6 @@ void __init platform_init(unsigned long ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); ocp_sys_info.opb_bus_freq = clocks.opb; - /* XXX Fix L2C IRQ triggerring setting (edge-sensitive). - * Firmware (at least PIBS v1.72 OCT/28/2003) sets it incorrectly - * --ebs - */ - mtdcr(DCRN_UIC_TR(UIC2), mfdcr(DCRN_UIC_TR(UIC2)) | 0x00000100); - ibm44x_platform_init(); ppc_md.setup_arch = ocotea_setup_arch; diff -puN arch/ppc/platforms/4xx/redwood6.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/redwood6.c --- 25/arch/ppc/platforms/4xx/redwood6.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/redwood6.c Tue Nov 23 17:13:13 2004 @@ -19,44 +19,20 @@ #include #include - /* - * Define all of the IRQ senses and polarities. + * Define external IRQ senses and polarities. */ - -static u_char redwood6_IRQ_initsenses[] __initdata = { - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 0: RTC/FPC */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 1: Transport */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 2: Audio Dec */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 3: Video Dec */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 4: DMA Chan 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 5: DMA Chan 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 6: DMA Chan 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 7: DMA Chan 3 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 8: SmartCard 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 9: IIC0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 10: IRR */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 11: Cap Timers */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 12: Cmp Timers */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 13: Serial Port */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 14: Soft Modem */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 15: Down Ctrs */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 16: SmartCard 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 17: Ext Int 7 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 18: Ext Int 8 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 19: Ext Int 9 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 20: Serial 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 21: Serial 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 22: Serial 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 23: XPT_DMA */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 24: DCR timeout */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 25: Ext Int 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 26: Ext Int 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 27: Ext Int 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 28: Ext Int 3 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 29: Ext Int 4 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 30: Ext Int 5 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 31: Ext Int 6 */ +unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 7 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 8 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 9 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 4 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 5 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 6 */ }; static struct resource smc91x_resources[] = { @@ -144,8 +120,6 @@ redwood6_setup_arch(void) printk("\n"); #endif - ibm4xxPIC_InitSenses = redwood6_IRQ_initsenses; - ibm4xxPIC_NumInitSenses = sizeof(redwood6_IRQ_initsenses); /* Identify the system */ printk(KERN_INFO "IBM Redwood6 (STBx25XX) Platform\n"); diff -puN arch/ppc/platforms/4xx/sycamore.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/platforms/4xx/sycamore.c --- 25/arch/ppc/platforms/4xx/sycamore.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/platforms/4xx/sycamore.c Tue Nov 23 17:13:13 2004 @@ -44,42 +44,22 @@ void *kb_data; void *sycamore_rtc_base; /* - * Define all of the IRQ senses and polarities. + * Define external IRQ senses and polarities. */ - -static u_char Sycamore_IRQ_initsenses[] __initdata = { - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 0: Uart 0*/ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 1: Uart 1*/ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 2: IIC */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 3: External Master */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 4: PCI ext cmd write*/ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 5: DMA Chan 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 6: DMA Chan 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 7: DMA Chan 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 8: DMA Chan 3 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 9: Ethernet wakeup (WOL)*/ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 10: Mal (SEER) */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 11: Mal TXEOB */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 12: Mal RXEOB */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 13: Mal TXDE*/ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 14: Mal RXDE*/ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 15: Ethernet */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 16: Ext PCI SERR */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 17: ECC */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 18: PCI PM*/ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 19: Ext Int 7 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 20: Ext Int 8 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 21: Ext Int 9 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 22: Ext Int 10 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 23: Ext Int 11 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 24: Ext Int 12 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 25: Ext Int 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 26: Ext Int 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 27: Ext Int 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 28: Ext Int 3 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 29: Ext Int 4 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 30: Ext Int 5 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 31: Ext Int 6 */ +unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 7 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 8 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 9 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 10 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 11 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 12 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 4 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 5 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 6 */ }; @@ -158,8 +138,6 @@ sycamore_setup_arch(void) sycamore_rtc_base = (void *) SYCAMORE_RTC_VADDR; TODC_INIT(TODC_TYPE_DS1743, sycamore_rtc_base, sycamore_rtc_base, sycamore_rtc_base, 8); - ibm4xxPIC_InitSenses = Sycamore_IRQ_initsenses; - ibm4xxPIC_NumInitSenses = sizeof(Sycamore_IRQ_initsenses); /* Identify the system */ printk(KERN_INFO "IBM Sycamore (IBM405GPr) Platform\n"); diff -puN arch/ppc/syslib/ibm44x_common.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/syslib/ibm44x_common.c --- 25/arch/ppc/syslib/ibm44x_common.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/syslib/ibm44x_common.c Tue Nov 23 17:13:13 2004 @@ -142,19 +142,9 @@ static unsigned long __init ibm44x_find_ return mem_size; } -static void __init ibm44x_init_irq(void) -{ - int i; - - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) - irq_desc[i].handler = ppc4xx_pic; -} - void __init ibm44x_platform_init(void) { - ppc_md.init_IRQ = ibm44x_init_irq; + ppc_md.init_IRQ = ppc4xx_pic_init; ppc_md.find_end_of_memory = ibm44x_find_end_of_memory; ppc_md.restart = ibm44x_restart; ppc_md.power_off = ibm44x_power_off; diff -puN arch/ppc/syslib/Makefile~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/syslib/Makefile --- 25/arch/ppc/syslib/Makefile~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/syslib/Makefile Tue Nov 23 17:13:13 2004 @@ -17,8 +17,12 @@ ifeq ($(CONFIG_4xx),y) ifeq ($(CONFIG_VIRTEX_II_PRO),y) obj-$(CONFIG_40x) += xilinx_pic.o else +ifeq ($(CONFIG_403),y) +obj-$(CONFIG_40x) += ppc403_pic.o +else obj-$(CONFIG_40x) += ppc4xx_pic.o endif +endif obj-$(CONFIG_44x) += ppc4xx_pic.o obj-$(CONFIG_40x) += ppc4xx_setup.o obj-$(CONFIG_GEN_RTC) += todc_time.o diff -puN /dev/null arch/ppc/syslib/ppc403_pic.c --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/arch/ppc/syslib/ppc403_pic.c Tue Nov 23 17:13:13 2004 @@ -0,0 +1,127 @@ +/* + * + * Copyright (c) 1999 Grant Erickson + * + * Module name: ppc403_pic.c + * + * Description: + * Interrupt controller driver for PowerPC 403-based processors. + */ + +/* + * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has + * 32 possible interrupts, a majority of which are not implemented on + * all cores. There are six configurable, external interrupt pins and + * there are eight internal interrupts for the on-chip serial port + * (SPU), DMA controller, and JTAG controller. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Function Prototypes */ + +static void ppc403_aic_enable(unsigned int irq); +static void ppc403_aic_disable(unsigned int irq); +static void ppc403_aic_disable_and_ack(unsigned int irq); + +static struct hw_interrupt_type ppc403_aic = { + "403GC AIC", + NULL, + NULL, + ppc403_aic_enable, + ppc403_aic_disable, + ppc403_aic_disable_and_ack, + 0 +}; + +int +ppc403_pic_get_irq(struct pt_regs *regs) +{ + int irq; + unsigned long bits; + + /* + * Only report the status of those interrupts that are actually + * enabled. + */ + + bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER); + + /* + * Walk through the interrupts from highest priority to lowest, and + * report the first pending interrupt found. + * We want PPC, not C bit numbering, so just subtract the ffs() + * result from 32. + */ + irq = 32 - ffs(bits); + + if (irq == NR_AIC_IRQS) + irq = -1; + + return (irq); +} + +static void +ppc403_aic_enable(unsigned int irq) +{ + int bit, word; + + bit = irq & 0x1f; + word = irq >> 5; + + ppc_cached_irq_mask[word] |= (1 << (31 - bit)); + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); +} + +static void +ppc403_aic_disable(unsigned int irq) +{ + int bit, word; + + bit = irq & 0x1f; + word = irq >> 5; + + ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); +} + +static void +ppc403_aic_disable_and_ack(unsigned int irq) +{ + int bit, word; + + bit = irq & 0x1f; + word = irq >> 5; + + ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); + mtdcr(DCRN_EXISR, (1 << (31 - bit))); +} + +void __init +ppc4xx_pic_init(void) +{ + int i; + + /* + * Disable all external interrupts until they are + * explicity requested. + */ + ppc_cached_irq_mask[0] = 0; + + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]); + + ppc_md.get_irq = ppc403_pic_get_irq; + + for (i = 0; i < NR_IRQS; i++) + irq_desc[i].handler = &ppc403_aic; +} diff -puN arch/ppc/syslib/ppc4xx_pic.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/syslib/ppc4xx_pic.c --- 25/arch/ppc/syslib/ppc4xx_pic.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/syslib/ppc4xx_pic.c Tue Nov 23 17:13:13 2004 @@ -1,31 +1,21 @@ /* + * arch/ppc/syslib/ppc4xx_pic.c * - * Copyright (c) 1999 Grant Erickson - * - * Module name: ppc4xx_pic.c - * - * Description: - * Interrupt controller driver for PowerPC 4xx-based processors. - */ - -/* - * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has - * 32 possible interrupts, a majority of which are not implemented on - * all cores. There are six configurable, external interrupt pins and - * there are eight internal interrupts for the on-chip serial port - * (SPU), DMA controller, and JTAG controller. + * Interrupt controller driver for PowerPC 4xx-based processors. * - * The PowerPC 405/440 cores' Universal Interrupt Controller (UIC) has - * 32 possible interrupts as well. Depending on the core and SoC - * implementation, a portion of the interrrupts are used for on-chip - * peripherals and a portion of the interrupts are available to be - * configured for external devices generating interrupts. + * Eugene Surovegin or + * Copyright (c) 2004 Zultys Technologies * - * The PowerNP and 440GP (and most likely future implementations) have - * cascaded UICs. + * Based on original code by + * Copyright (c) 1999 Grant Erickson + * Armin Custer * - */ - + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. +*/ +#include #include #include #include @@ -36,493 +26,212 @@ #include #include -/* Global Variables */ -struct hw_interrupt_type *ppc4xx_pic; -/* - * We define 4xxIRQ_InitSenses table thusly: - * bit 0x1: sense, 1 for edge and 0 for level. - * bit 0x2: polarity, 0 for negative, 1 for positive. +/* See comment in include/arch-ppc/ppc4xx_pic.h + * for more info about these two variables */ -unsigned int ibm4xxPIC_NumInitSenses __initdata = 0; -unsigned char *ibm4xxPIC_InitSenses __initdata = NULL; - -/* Six of one, half dozen of the other....#ifdefs, separate files, - * other tricks..... - * - * There are basically two types of interrupt controllers, the 403 AIC - * and the "others" with UIC. I just kept them both here separated - * with #ifdefs, but it seems to change depending upon how supporting - * files (like ppc4xx.h) change. -- Dan. - */ - -#ifdef CONFIG_403 - -/* Function Prototypes */ +extern struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[NR_UICS] __attribute__((weak)); +extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__((weak)); -static void ppc403_aic_enable(unsigned int irq); -static void ppc403_aic_disable(unsigned int irq); -static void ppc403_aic_disable_and_ack(unsigned int irq); - -static struct hw_interrupt_type ppc403_aic = { - "403GC AIC", - NULL, - NULL, - ppc403_aic_enable, - ppc403_aic_disable, - ppc403_aic_disable_and_ack, - 0 -}; - -int -ppc403_pic_get_irq(struct pt_regs *regs) -{ - int irq; - unsigned long bits; - - /* - * Only report the status of those interrupts that are actually - * enabled. - */ - - bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER); - - /* - * Walk through the interrupts from highest priority to lowest, and - * report the first pending interrupt found. - * We want PPC, not C bit numbering, so just subtract the ffs() - * result from 32. - */ - irq = 32 - ffs(bits); - - if (irq == NR_AIC_IRQS) - irq = -1; - - return (irq); +#define IRQ_MASK_UIC0(irq) (1 << (31 - (irq))) +#define IRQ_MASK_UICx(irq) (1 << (31 - ((irq) & 0x1f))) +#define IRQ_MASK_UIC1(irq) IRQ_MASK_UICx(irq) +#define IRQ_MASK_UIC2(irq) IRQ_MASK_UICx(irq) + +#define UIC_HANDLERS(n) \ +static void ppc4xx_uic##n##_enable(unsigned int irq) \ +{ \ + ppc_cached_irq_mask[n] |= IRQ_MASK_UIC##n(irq); \ + mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \ +} \ + \ +static void ppc4xx_uic##n##_disable(unsigned int irq) \ +{ \ + ppc_cached_irq_mask[n] &= ~IRQ_MASK_UIC##n(irq); \ + mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \ +} \ + \ +static void ppc4xx_uic##n##_ack(unsigned int irq) \ +{ \ + u32 mask = IRQ_MASK_UIC##n(irq); \ + ppc_cached_irq_mask[n] &= ~mask; \ + mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \ + mtdcr(DCRN_UIC_SR(UIC##n), mask); \ + ACK_UIC##n##_PARENT \ +} \ + \ +static void ppc4xx_uic##n##_end(unsigned int irq) \ +{ \ + unsigned int status = irq_desc[irq].status; \ + u32 mask = IRQ_MASK_UIC##n(irq); \ + if (status & IRQ_LEVEL){ \ + mtdcr(DCRN_UIC_SR(UIC##n), mask); \ + ACK_UIC##n##_PARENT \ + } \ + if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))){ \ + ppc_cached_irq_mask[n] |= mask; \ + mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \ + } \ +} + +#define DECLARE_UIC(n) \ +{ \ + .typename = "UIC"#n, \ + .enable = ppc4xx_uic##n##_enable, \ + .disable = ppc4xx_uic##n##_disable, \ + .ack = ppc4xx_uic##n##_ack, \ + .end = ppc4xx_uic##n##_end, \ +} \ + +#if NR_UICS == 3 +#define ACK_UIC0_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC); +#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC); +#define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC); +UIC_HANDLERS(0); UIC_HANDLERS(1); UIC_HANDLERS(2); + +static int ppc4xx_pic_get_irq(struct pt_regs *regs) +{ + u32 uicb = mfdcr(DCRN_UIC_MSR(UICB)); + if (uicb & UICB_UIC0NC) + return 32 - ffs(mfdcr(DCRN_UIC_MSR(UIC0))); + else if (uicb & UICB_UIC1NC) + return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1))); + else if (uicb & UICB_UIC2NC) + return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2))); + else + return -1; } -static void -ppc403_aic_enable(unsigned int irq) +static void __init ppc4xx_pic_impl_init(void) { - int bit, word; - - bit = irq & 0x1f; - word = irq >> 5; - - ppc_cached_irq_mask[word] |= (1 << (31 - bit)); - mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); + /* Configure Base UIC */ + mtdcr(DCRN_UIC_CR(UICB), 0); + mtdcr(DCRN_UIC_TR(UICB), 0); + mtdcr(DCRN_UIC_PR(UICB), 0xffffffff); + mtdcr(DCRN_UIC_SR(UICB), 0xffffffff); + mtdcr(DCRN_UIC_ER(UICB), UICB_UIC0NC | UICB_UIC1NC | UICB_UIC2NC); } -static void -ppc403_aic_disable(unsigned int irq) -{ - int bit, word; - - bit = irq & 0x1f; - word = irq >> 5; - - ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); - mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); -} +#elif NR_UICS == 2 +#define ACK_UIC0_PARENT +#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC); +UIC_HANDLERS(0); UIC_HANDLERS(1); -static void -ppc403_aic_disable_and_ack(unsigned int irq) +static int ppc4xx_pic_get_irq(struct pt_regs *regs) { - int bit, word; - - bit = irq & 0x1f; - word = irq >> 5; - - ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); - mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); - mtdcr(DCRN_EXISR, (1 << (31 - bit))); + u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0)); + if (uic0 & UIC0_UIC1NC) + return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1))); + else + return uic0 ? 32 - ffs(uic0) : -1; } -#else - -#ifndef UIC1 -#define UIC1 UIC0 -#endif -#ifndef UIC2 -#define UIC2 UIC1 -#endif - -static void -ppc4xx_uic_enable(unsigned int irq) +static void __init ppc4xx_pic_impl_init(void) { - int bit, word; - irq_desc_t *desc = irq_desc + irq; - - bit = irq & 0x1f; - word = irq >> 5; - -#ifdef UIC_DEBUG - printk("ppc4xx_uic_enable - irq %d word %d bit 0x%x\n", irq, word, bit); -#endif - ppc_cached_irq_mask[word] |= 1 << (31 - bit); - switch (word) { - case 0: - mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]); - if ((mfdcr(DCRN_UIC_TR(UIC0)) & (1 << (31 - bit))) == 0) - desc->status |= IRQ_LEVEL; - else - desc->status = desc->status & ~IRQ_LEVEL; - break; - case 1: - mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]); - if ((mfdcr(DCRN_UIC_TR(UIC1)) & (1 << (31 - bit))) == 0) - desc->status |= IRQ_LEVEL; - else - desc->status = desc->status & ~IRQ_LEVEL; - break; - case 2: - mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]); - if ((mfdcr(DCRN_UIC_TR(UIC2)) & (1 << (31 - bit))) == 0) - desc->status |= IRQ_LEVEL; - else - desc->status = desc->status & ~IRQ_LEVEL; - break; - } - + /* Enable cascade interrupt in UIC0 */ + ppc_cached_irq_mask[0] |= UIC0_UIC1NC; + mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC); + mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]); } -static void -ppc4xx_uic_disable(unsigned int irq) -{ - int bit, word; +#elif NR_UICS == 1 +#define ACK_UIC0_PARENT +UIC_HANDLERS(0); - bit = irq & 0x1f; - word = irq >> 5; -#ifdef UIC_DEBUG - printk("ppc4xx_uic_disable - irq %d word %d bit 0x%x\n", irq, word, - bit); -#endif - ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); - switch (word) { - case 0: - mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]); - break; - case 1: - mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]); - break; - case 2: - mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]); - break; - } -} - -static void -ppc4xx_uic_disable_and_ack(unsigned int irq) +static int ppc4xx_pic_get_irq(struct pt_regs *regs) { - int bit, word; - - bit = irq & 0x1f; - word = irq >> 5; - -#ifdef UIC_DEBUG - printk("ppc4xx_uic_disable_and_ack - irq %d word %d bit 0x%x\n", irq, - word, bit); -#endif - ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); - switch (word) { - case 0: - mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]); - mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - bit))); -#if (NR_UICS > 2) - mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC); -#endif - break; - case 1: - mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]); - mtdcr(DCRN_UIC_SR(UIC1), (1 << (31 - bit))); -#if (NR_UICS == 2) - mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - UIC0_UIC1NC))); -#endif -#if (NR_UICS > 2) - mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC); -#endif - break; - case 2: - mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]); - mtdcr(DCRN_UIC_SR(UIC2), (1 << (31 - bit))); -#if (NR_UICS > 2) - mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC); -#endif - break; - } - + u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0)); + return uic0 ? 32 - ffs(uic0) : -1; } -static void -ppc4xx_uic_end(unsigned int irq) -{ - int bit, word; - unsigned int tr_bits = 0; - - bit = irq & 0x1f; - word = irq >> 5; - -#ifdef UIC_DEBUG - printk("ppc4xx_uic_end - irq %d word %d bit 0x%x\n", irq, word, bit); +static inline void ppc4xx_pic_impl_init(void){} #endif - switch (word) { - case 0: - tr_bits = mfdcr(DCRN_UIC_TR(UIC0)); - break; - case 1: - tr_bits = mfdcr(DCRN_UIC_TR(UIC1)); - break; - case 2: - tr_bits = mfdcr(DCRN_UIC_TR(UIC2)); - break; - } - - if ((tr_bits & (1 << (31 - bit))) == 0) { - /* level trigger */ - switch (word) { - case 0: - mtdcr(DCRN_UIC_SR(UIC0), 1 << (31 - bit)); -#if (NR_UICS > 2) - mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC); -#endif - break; - case 1: - mtdcr(DCRN_UIC_SR(UIC1), 1 << (31 - bit)); -#if (NR_UICS == 2) - mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - UIC0_UIC1NC))); -#endif -#if (NR_UICS > 2) - mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC); +static struct ppc4xx_uic_impl { + struct hw_interrupt_type decl; + int base; /* Base DCR number */ +} __uic[] = { + { .decl = DECLARE_UIC(0), .base = UIC0 }, +#if NR_UICS > 1 + { .decl = DECLARE_UIC(1), .base = UIC1 }, +#if NR_UICS > 2 + { .decl = DECLARE_UIC(2), .base = UIC2 }, #endif - break; - case 2: - mtdcr(DCRN_UIC_SR(UIC2), 1 << (31 - bit)); -#if (NR_UICS > 2) - mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC); #endif - break; - } - } - - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - ppc_cached_irq_mask[word] |= 1 << (31 - bit); - switch (word) { - case 0: - mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]); - break; - case 1: - mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]); - break; - case 2: - mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]); - break; - } - } -} - -static struct hw_interrupt_type ppc4xx_uic = { -#if (NR_UICS == 1) - "IBM UIC", -#else - "IBM UIC Cascade", -#endif - NULL, - NULL, - ppc4xx_uic_enable, - ppc4xx_uic_disable, - ppc4xx_uic_disable_and_ack, - ppc4xx_uic_end, - 0 }; -int -ppc4xx_pic_get_irq(struct pt_regs *regs) +static inline int is_level_sensitive(int irq) { - int irq, cas_irq; - unsigned long bits; - cas_irq = 0; - /* - * Only report the status of those interrupts that are actually - * enabled. - */ - -#if (NR_UICS > 2) - bits = mfdcr(DCRN_UIC_MSR(UICB)); -#else - bits = mfdcr(DCRN_UIC_MSR(UIC0)); -#endif -#if (NR_UICS > 2) - if (bits & UICB_UIC0NC) { - bits = mfdcr(DCRN_UIC_MSR(UIC0)); - irq = 32 - ffs(bits); - } else if (bits & UICB_UIC1NC) { - bits = mfdcr(DCRN_UIC_MSR(UIC1)); - irq = 64 - ffs(bits); - } else if (bits & UICB_UIC2NC) { - bits = mfdcr(DCRN_UIC_MSR(UIC2)); - irq = 96 - ffs(bits); - } else { - irq = -1; - } -#elif (NR_UICS > 1) - if (bits & UIC_CASCADE_MASK) { - bits = mfdcr(DCRN_UIC_MSR(UIC1)); - cas_irq = 32 - ffs(bits); - irq = 32 + cas_irq; - } else { - irq = 32 - ffs(bits); - if (irq == 32) - irq = -1; - } -#else - /* - * Walk through the interrupts from highest priority to lowest, and - * report the first pending interrupt found. - * We want PPC, not C bit numbering, so just subtract the ffs() - * result from 32. - */ - irq = 32 - ffs(bits); -#endif - if (irq == (NR_UIC_IRQS * NR_UICS)) - irq = -1; - -#ifdef UIC_DEBUG - printk("ppc4xx_pic_get_irq - irq %d bit 0x%x\n", irq, bits); -#endif - - return (irq); + u32 tr = mfdcr(DCRN_UIC_TR(__uic[irq >> 5].base)); + return (tr & IRQ_MASK_UICx(irq)) == 0; } -#endif -void __init -ppc4xx_extpic_init(void) +void __init ppc4xx_pic_init(void) { - /* set polarity - * 1 = default/pos/rising , 0= neg/falling internal - * 1 = neg/falling , 0= pos/rising external - * Sense - * 0 = default level internal - * 0 = level, 1 = edge external - */ - - unsigned int sense, irq; - int bit, word; - unsigned long ppc_cached_sense_mask[NR_MASK_WORDS]; - unsigned long ppc_cached_pol_mask[NR_MASK_WORDS]; - ppc_cached_sense_mask[0] = 0; - ppc_cached_sense_mask[1] = 0; - ppc_cached_sense_mask[2] = 0; - ppc_cached_pol_mask[0] = 0; - ppc_cached_pol_mask[1] = 0; - ppc_cached_pol_mask[2] = 0; - - for (irq = 0; irq < NR_IRQS; irq++) { - - bit = irq & 0x1f; - word = irq >> 5; - - sense = - (irq < - ibm4xxPIC_NumInitSenses) ? ibm4xxPIC_InitSenses[irq] : 3; -#ifdef PPC4xx_PIC_DEBUG - printk("PPC4xx_picext %d word:%x bit:%x sense:%x", irq, word, - bit, sense); -#endif - ppc_cached_sense_mask[word] |= - (~sense & IRQ_SENSE_MASK) << (31 - bit); - ppc_cached_pol_mask[word] |= - ((sense & IRQ_POLARITY_MASK) >> 1) << (31 - bit); - switch (word) { - case 0: -#ifdef PPC4xx_PIC_DEBUG - printk("Pol %x ", mfdcr(DCRN_UIC_PR(UIC0))); - printk("Level %x\n", mfdcr(DCRN_UIC_TR(UIC0))); -#endif - /* polarity setting */ - mtdcr(DCRN_UIC_PR(UIC0), ppc_cached_pol_mask[word]); - - /* Level setting */ - mtdcr(DCRN_UIC_TR(UIC0), ppc_cached_sense_mask[word]); - - break; - case 1: -#ifdef PPC4xx_PIC_DEBUG - printk("Pol %x ", mfdcr(DCRN_UIC_PR(UIC1))); - printk("Level %x\n", mfdcr(DCRN_UIC_TR(UIC1))); -#endif - /* polarity setting */ - mtdcr(DCRN_UIC_PR(UIC1), ppc_cached_pol_mask[word]); - - /* Level setting */ - mtdcr(DCRN_UIC_TR(UIC1), ppc_cached_sense_mask[word]); - - break; - case 2: -#ifdef PPC4xx_PIC_DEBUG - printk("Pol %x ", mfdcr(DCRN_UIC_PR(UIC2))); - printk("Level %x\n", mfdcr(DCRN_UIC_TR(UIC2))); -#endif - /* polarity setting */ - mtdcr(DCRN_UIC_PR(UIC2), ppc_cached_pol_mask[word]); - - /* Level setting */ - mtdcr(DCRN_UIC_TR(UIC2), ppc_cached_sense_mask[word]); - - break; + int i; + unsigned char* eirqs = ppc4xx_uic_ext_irq_cfg; + + for (i = 0; i < NR_UICS; ++i){ + int base = __uic[i].base; + + /* Disable everything by default */ + ppc_cached_irq_mask[i] = 0; + mtdcr(DCRN_UIC_ER(base), 0); + + /* We don't use critical interrupts */ + mtdcr(DCRN_UIC_CR(base), 0); + + /* Configure polarity and triggering */ + if (ppc4xx_core_uic_cfg){ + struct ppc4xx_uic_settings* p = ppc4xx_core_uic_cfg + i; + u32 mask = p->ext_irq_mask; + u32 pr = mfdcr(DCRN_UIC_PR(base)) & mask; + u32 tr = mfdcr(DCRN_UIC_TR(base)) & mask; + + /* "Fixed" interrupts (on-chip devices) */ + pr |= p->polarity & ~mask; + tr |= p->triggering & ~mask; + + /* Merge external IRQs settings if board port + * provided them + */ + if (eirqs && mask){ + pr &= ~mask; + tr &= ~mask; + while (mask){ + /* Extract current external IRQ mask */ + u32 eirq_mask = 1 << __ilog2(mask); + + if (!(*eirqs & IRQ_SENSE_LEVEL)) + tr |= eirq_mask; + + if (*eirqs & IRQ_POLARITY_POSITIVE) + pr |= eirq_mask; + + mask &= ~eirq_mask; + ++eirqs; + } + } + mtdcr(DCRN_UIC_PR(base), pr); + mtdcr(DCRN_UIC_TR(base), tr); } - } -} -void __init -ppc4xx_pic_init(void) -{ - /* - * Disable all external interrupts until they are - * explicity requested. - */ - ppc_cached_irq_mask[0] = 0; - ppc_cached_irq_mask[1] = 0; - ppc_cached_irq_mask[2] = 0; - -#if defined CONFIG_403 - mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]); - - ppc4xx_pic = &ppc403_aic; - ppc_md.get_irq = ppc403_pic_get_irq; -#else -#if (NR_UICS > 2) - mtdcr(DCRN_UIC_ER(UICB), UICB_UIC0NC | UICB_UIC1NC | UICB_UIC2NC); - mtdcr(DCRN_UIC_CR(UICB), 0); - - mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[2]); - mtdcr(DCRN_UIC_CR(UIC2), 0); - -#endif -#if (NR_UICS > 1) -#if (NR_UICS == 2) - /* enable cascading interrupt */ - ppc_cached_irq_mask[0] |= 1 << (31 - UIC0_UIC1NC); -#endif - mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[1]); - mtdcr(DCRN_UIC_CR(UIC1), 0); -#endif - mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]); - mtdcr(DCRN_UIC_CR(UIC0), 0); - - if (ibm4xxPIC_InitSenses != NULL) - ppc4xx_extpic_init(); - - /* Clear any pending interrupts */ -#if (NR_UICS > 2) - mtdcr(DCRN_UIC_SR(UICB), 0xffffffff); - mtdcr(DCRN_UIC_SR(UIC2), 0xffffffff); -#endif -#if (NR_UICS > 1) - mtdcr(DCRN_UIC_SR(UIC1), 0xffffffff); -#endif - mtdcr(DCRN_UIC_SR(UIC0), 0xffffffff); + /* ACK any pending interrupts to prevent false + * triggering after first enable + */ + mtdcr(DCRN_UIC_SR(base), 0xffffffff); + } + + /* Perform optional implementation specific setup + * (e.g. enable cascade interrupts for multi-UIC configurations) + */ + ppc4xx_pic_impl_init(); + + /* Attach low-level handlers */ + for (i = 0; i < (NR_UICS << 5); ++i){ + irq_desc[i].handler = &__uic[i >> 5].decl; + if (is_level_sensitive(i)) + irq_desc[i].status |= IRQ_LEVEL; + } - ppc4xx_pic = &ppc4xx_uic; ppc_md.get_irq = ppc4xx_pic_get_irq; -#endif } diff -puN arch/ppc/syslib/ppc4xx_setup.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/syslib/ppc4xx_setup.c --- 25/arch/ppc/syslib/ppc4xx_setup.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/syslib/ppc4xx_setup.c Tue Nov 23 17:13:13 2004 @@ -133,12 +133,7 @@ ppc4xx_map_io(void) void __init ppc4xx_init_IRQ(void) { - int i; - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) - irq_desc[i].handler = ppc4xx_pic; } static void diff -puN arch/ppc/syslib/xilinx_pic.c~ppc32-ppc4xx-pic-rewrite-cleanup arch/ppc/syslib/xilinx_pic.c --- 25/arch/ppc/syslib/xilinx_pic.c~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/arch/ppc/syslib/xilinx_pic.c Tue Nov 23 17:13:13 2004 @@ -38,9 +38,6 @@ static volatile u32 *intc; #define intc_in_be32(addr) mfdcr((addr)) #endif -/* Global Variables */ -struct hw_interrupt_type *ppc4xx_pic; - static void xilinx_intc_enable(unsigned int irq) { @@ -115,6 +112,8 @@ xilinx_pic_get_irq(struct pt_regs *regs) void __init ppc4xx_pic_init(void) { + int i; + #if XPAR_XINTC_USE_DCR == 0 intc = ioremap(XPAR_INTC_0_BASEADDR, 32); @@ -137,6 +136,8 @@ ppc4xx_pic_init(void) /* Turn on the Master Enable. */ intc_out_be32(intc + MER, 0x3UL); - ppc4xx_pic = &xilinx_intc; ppc_md.get_irq = xilinx_pic_get_irq; + + for (i = 0; i < NR_IRQS; ++i) + irq_desc[i].handler = &xilinx_intc; } diff -puN include/asm-ppc/ibm44x.h~ppc32-ppc4xx-pic-rewrite-cleanup include/asm-ppc/ibm44x.h --- 25/include/asm-ppc/ibm44x.h~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/include/asm-ppc/ibm44x.h Tue Nov 23 17:13:13 2004 @@ -162,8 +162,7 @@ #define DCRN_UIC_VR(base) (base + 0x7) #define DCRN_UIC_VCR(base) (base + 0x8) -#define UIC0_UIC1NC 30 /* UIC1 non-critical interrupt */ -#define UIC0_UIC1CR 31 /* UIC1 critical interrupt */ +#define UIC0_UIC1NC 0x00000002 #define UICB_UIC0NC 0x40000000 #define UICB_UIC1NC 0x10000000 @@ -518,7 +517,6 @@ #else #define NR_UICS 2 #endif -#define UIC_CASCADE_MASK 0x0003 /* bits 30 & 31 */ #define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i] diff -puN include/asm-ppc/ppc4xx_pic.h~ppc32-ppc4xx-pic-rewrite-cleanup include/asm-ppc/ppc4xx_pic.h --- 25/include/asm-ppc/ppc4xx_pic.h~ppc32-ppc4xx-pic-rewrite-cleanup Tue Nov 23 17:13:13 2004 +++ 25-akpm/include/asm-ppc/ppc4xx_pic.h Tue Nov 23 17:13:13 2004 @@ -1,28 +1,53 @@ /* + * include/asm-ppc/ppc4xx_pic.h * - * Copyright (c) 1999 Grant Erickson + * Interrupt controller driver for PowerPC 4xx-based processors. * - * Module name: ppc4xx_pic.h + * Copyright (c) 1999 Grant Erickson * - * Description: - * Interrupt controller driver for PowerPC 4xx-based processors. + * Eugene Surovegin or + * Copyright (c) 2004 Zultys Technologies + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. */ #ifndef __PPC4XX_PIC_H__ #define __PPC4XX_PIC_H__ #include +#include #include -/* External Global Variables */ - -extern struct hw_interrupt_type *ppc4xx_pic; -extern unsigned int ibm4xxPIC_NumInitSenses; -extern unsigned char *ibm4xxPIC_InitSenses; - -/* Function Prototypes */ +/* "Fixed" UIC settings (they are chip, not board specific), + * e.g. polarity/triggerring for internal interrupt sources. + * + * Platform port should provide NR_UICS-sized array named ppc4xx_core_uic_cfg + * with these "fixed" settings: .polarity contains exact value which will + * be written (masked with "ext_irq_mask") into UICx_PR register, + * .triggering - to UICx_TR. + * + * Settings for external IRQs can be specified separately by the + * board support code. In this case properly sized array of unsigned + * char named ppc4xx_uic_ext_irq_cfg should be filled with correct + * values using IRQ_SENSE_XXXXX and IRQ_POLARITY_XXXXXXX defines. + * + * If these arrays aren't provided, UIC initialization code keeps firmware + * configuration. Also, ppc4xx_uic_ext_irq_cfg implies ppc4xx_core_uic_cfg + * is defined. + * + * Both ppc4xx_core_uic_cfg and ppc4xx_uic_ext_irq_cfg are declared as + * "weak" symbols in ppc4xx_pic.c + * + */ +struct ppc4xx_uic_settings { + u32 polarity; + u32 triggering; + u32 ext_irq_mask; +}; extern void ppc4xx_pic_init(void); -extern int ppc4xx_pic_get_irq(struct pt_regs *regs); -#endif /* __PPC4XX_PIC_H__ */ +#endif /* __PPC4XX_PIC_H__ */ _