Commit f481178e authored by Matt Porter's avatar Matt Porter Committed by Linus Torvalds

[PATCH] ppc32: PPC4xx PIC rewrite/cleanup

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: default avatarEugene Surovegin <ebs@ebshome.net>
Signed-off-by: default avatarMatt Porter <mporter@kernel.crashing.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ad47c00f
...@@ -55,73 +55,22 @@ ...@@ -55,73 +55,22 @@
static struct ibm44x_clocks clocks __initdata; static struct ibm44x_clocks clocks __initdata;
/* /*
* Ebony IRQ triggering/polarity settings * Ebony external IRQ triggering/polarity settings
*/ */
static u_char ebony_IRQ_initsenses[] __initdata = { unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 0: UART 0 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ0: PCI slot 0 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 1: UART 1 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ1: PCI slot 1 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 2: IIC 0 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ2: PCI slot 2 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 3: IIC 1 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ3: PCI slot 3 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 4: PCI Inb Mess */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ4: IRDA */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 5: PCI Cmd Wrt */ (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ5: SMI pushbutton */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 6: PCI PM */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ6: PHYs */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 7: PCI MSI 0 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ7: AUX */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 8: PCI MSI 1 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ8: EXT */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 9: PCI MSI 2 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ9: EXT */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 10: MAL TX EOB */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ10: EXT */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 11: MAL RX EOB */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ11: EXT */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 12: DMA Chan 0 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ12: EXT */
(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 */
}; };
static void __init static void __init
...@@ -358,9 +307,6 @@ ebony_setup_arch(void) ...@@ -358,9 +307,6 @@ ebony_setup_arch(void)
ebony_early_serial_map(); ebony_early_serial_map();
ibm4xxPIC_InitSenses = ebony_IRQ_initsenses;
ibm4xxPIC_NumInitSenses = sizeof(ebony_IRQ_initsenses);
/* Identify the system */ /* Identify the system */
printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n"); printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n");
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <asm/ibm4xx.h> #include <asm/ibm4xx.h>
#include <asm/ocp.h> #include <asm/ocp.h>
#include <asm/ppc4xx_pic.h>
#include <platforms/4xx/ibm405ep.h> #include <platforms/4xx/ibm405ep.h>
...@@ -132,3 +133,11 @@ struct ocp_def core_ocp[] = { ...@@ -132,3 +133,11 @@ struct ocp_def core_ocp[] = {
{ .vendor = OCP_VENDOR_INVALID { .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 */
}
};
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <platforms/4xx/ibm405gp.h> #include <platforms/4xx/ibm405gp.h>
#include <asm/ibm4xx.h> #include <asm/ibm4xx.h>
#include <asm/ocp.h> #include <asm/ocp.h>
#include <asm/ppc4xx_pic.h>
static struct ocp_func_emac_data ibm405gp_emac0_def = { static struct ocp_func_emac_data ibm405gp_emac0_def = {
.rgmii_idx = -1, /* No RGMII */ .rgmii_idx = -1, /* No RGMII */
...@@ -109,3 +110,11 @@ struct ocp_def core_ocp[] = { ...@@ -109,3 +110,11 @@ struct ocp_def core_ocp[] = {
{ .vendor = OCP_VENDOR_INVALID { .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 */
}
};
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <platforms/4xx/ibm405gpr.h> #include <platforms/4xx/ibm405gpr.h>
#include <asm/ibm4xx.h> #include <asm/ibm4xx.h>
#include <asm/ocp.h> #include <asm/ocp.h>
#include <asm/ppc4xx_pic.h>
static struct ocp_func_emac_data ibm405gpr_emac0_def = { static struct ocp_func_emac_data ibm405gpr_emac0_def = {
.rgmii_idx = -1, /* No RGMII */ .rgmii_idx = -1, /* No RGMII */
...@@ -106,3 +107,11 @@ struct ocp_def core_ocp[] = { ...@@ -106,3 +107,11 @@ struct ocp_def core_ocp[] = {
{ .vendor = OCP_VENDOR_INVALID { .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 */
}
};
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <platforms/4xx/ibm440gp.h> #include <platforms/4xx/ibm440gp.h>
#include <asm/ocp.h> #include <asm/ocp.h>
#include <asm/ppc4xx_pic.h>
static struct ocp_func_emac_data ibm440gp_emac0_def = { static struct ocp_func_emac_data ibm440gp_emac0_def = {
.rgmii_idx = -1, /* No RGMII */ .rgmii_idx = -1, /* No RGMII */
...@@ -149,3 +150,15 @@ struct ocp_def core_ocp[] = { ...@@ -149,3 +150,15 @@ struct ocp_def core_ocp[] = {
{ .vendor = OCP_VENDOR_INVALID { .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 */
},
};
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <platforms/4xx/ibm440gx.h> #include <platforms/4xx/ibm440gx.h>
#include <asm/ocp.h> #include <asm/ocp.h>
#include <asm/ppc4xx_pic.h>
static struct ocp_func_emac_data ibm440gx_emac0_def = { static struct ocp_func_emac_data ibm440gx_emac0_def = {
.rgmii_idx = -1, /* No RGMII */ .rgmii_idx = -1, /* No RGMII */
...@@ -215,3 +216,19 @@ struct ocp_def core_ocp[] = { ...@@ -215,3 +216,19 @@ struct ocp_def core_ocp[] = {
{ .vendor = OCP_VENDOR_INVALID { .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 */
},
};
...@@ -132,8 +132,7 @@ ...@@ -132,8 +132,7 @@
#define DCRN_UIC1_BASE 0x0D0 #define DCRN_UIC1_BASE 0x0D0
#define DCRN_CPC0_EPRCSR 0x0F3 #define DCRN_CPC0_EPRCSR 0x0F3
#define UIC0_UIC1NC 30 /* UIC1 non-critical interrupt */ #define UIC0_UIC1NC 0x00000002
#define UIC0_UIC1CR 31 /* UIC1 critical interrupt */
#define CHR1_CETE 0x00000004 /* CPU external timer enable */ #define CHR1_CETE 0x00000004 /* CPU external timer enable */
#define UIC0 DCRN_UIC0_BASE #define UIC0 DCRN_UIC0_BASE
...@@ -141,7 +140,6 @@ ...@@ -141,7 +140,6 @@
#undef NR_UICS #undef NR_UICS
#define NR_UICS 2 #define NR_UICS 2
#define UIC_CASCADE_MASK 0x0003 /* bits 30 & 31 */
/* EMAC DCRN's FIXME: armin */ /* EMAC DCRN's FIXME: armin */
#define DCRN_MALRXCTP2R(base) ((base) + 0x42) /* Channel Rx 2 Channel Table Pointer */ #define DCRN_MALRXCTP2R(base) ((base) + 0x42) /* Channel Rx 2 Channel Table Pointer */
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/ocp.h> #include <asm/ocp.h>
#include <platforms/4xx/ibmstbx25.h> #include <platforms/4xx/ibmstbx25.h>
#include <asm/ppc4xx_pic.h>
static struct ocp_func_iic_data ibmstbx25_iic0_def = { static struct ocp_func_iic_data ibmstbx25_iic0_def = {
.fast_mode = 0, /* Use standad mode (100Khz) */ .fast_mode = 0, /* Use standad mode (100Khz) */
...@@ -57,3 +58,11 @@ struct ocp_def core_ocp[] __initdata = { ...@@ -57,3 +58,11 @@ struct ocp_def core_ocp[] __initdata = {
{ .vendor = OCP_VENDOR_INVALID { .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 */
}
};
...@@ -101,8 +101,8 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -101,8 +101,8 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.setup_arch = oak_setup_arch; ppc_md.setup_arch = oak_setup_arch;
ppc_md.show_percpuinfo = oak_show_percpuinfo; ppc_md.show_percpuinfo = oak_show_percpuinfo;
ppc_md.irq_canonicalize = NULL; ppc_md.irq_canonicalize = NULL;
ppc_md.init_IRQ = oak_init_IRQ; ppc_md.init_IRQ = ppc4xx_pic_init;
ppc_md.get_irq = oak_get_irq; ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */
ppc_md.init = NULL; ppc_md.init = NULL;
ppc_md.restart = oak_restart; ppc_md.restart = oak_restart;
...@@ -155,32 +155,6 @@ oak_show_percpuinfo(struct seq_file *m, int i) ...@@ -155,32 +155,6 @@ oak_show_percpuinfo(struct seq_file *m, int i)
return 0; return 0;
} }
/*
* 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. * Document me.
*/ */
......
...@@ -347,12 +347,6 @@ void __init platform_init(unsigned long r3, unsigned long r4, ...@@ -347,12 +347,6 @@ void __init platform_init(unsigned long r3, unsigned long r4,
ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
ocp_sys_info.opb_bus_freq = clocks.opb; 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(); ibm44x_platform_init();
ppc_md.setup_arch = ocotea_setup_arch; ppc_md.setup_arch = ocotea_setup_arch;
......
...@@ -19,44 +19,20 @@ ...@@ -19,44 +19,20 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/machdep.h> #include <asm/machdep.h>
/* /*
* Define all of the IRQ senses and polarities. * Define external IRQ senses and polarities.
*/ */
unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
static u_char redwood6_IRQ_initsenses[] __initdata = { (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 7 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 0: RTC/FPC */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 8 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 1: Transport */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 9 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 2: Audio Dec */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 0 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 3: Video Dec */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 1 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 4: DMA Chan 0 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 2 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 5: DMA Chan 1 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 3 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 6: DMA Chan 2 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 4 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 7: DMA Chan 3 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 5 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 8: SmartCard 0 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 6 */
(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 */
}; };
static struct resource smc91x_resources[] = { static struct resource smc91x_resources[] = {
...@@ -144,8 +120,6 @@ redwood6_setup_arch(void) ...@@ -144,8 +120,6 @@ redwood6_setup_arch(void)
printk("\n"); printk("\n");
#endif #endif
ibm4xxPIC_InitSenses = redwood6_IRQ_initsenses;
ibm4xxPIC_NumInitSenses = sizeof(redwood6_IRQ_initsenses);
/* Identify the system */ /* Identify the system */
printk(KERN_INFO "IBM Redwood6 (STBx25XX) Platform\n"); printk(KERN_INFO "IBM Redwood6 (STBx25XX) Platform\n");
......
...@@ -44,42 +44,22 @@ void *kb_data; ...@@ -44,42 +44,22 @@ void *kb_data;
void *sycamore_rtc_base; void *sycamore_rtc_base;
/* /*
* Define all of the IRQ senses and polarities. * Define external IRQ senses and polarities.
*/ */
unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = {
static u_char Sycamore_IRQ_initsenses[] __initdata = { (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 7 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 0: Uart 0*/ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 8 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 1: Uart 1*/ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 9 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 2: IIC */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 10 */
(IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* 3: External Master */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 11 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 4: PCI ext cmd write*/ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 12 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 5: DMA Chan 0 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 0 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 6: DMA Chan 1 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 1 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 7: DMA Chan 2 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 2 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 8: DMA Chan 3 */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 3 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 9: Ethernet wakeup (WOL)*/ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 4 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 10: Mal (SEER) */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 5 */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* 11: Mal TXEOB */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 6 */
(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 */
}; };
...@@ -158,8 +138,6 @@ sycamore_setup_arch(void) ...@@ -158,8 +138,6 @@ sycamore_setup_arch(void)
sycamore_rtc_base = (void *) SYCAMORE_RTC_VADDR; sycamore_rtc_base = (void *) SYCAMORE_RTC_VADDR;
TODC_INIT(TODC_TYPE_DS1743, sycamore_rtc_base, sycamore_rtc_base, TODC_INIT(TODC_TYPE_DS1743, sycamore_rtc_base, sycamore_rtc_base,
sycamore_rtc_base, 8); sycamore_rtc_base, 8);
ibm4xxPIC_InitSenses = Sycamore_IRQ_initsenses;
ibm4xxPIC_NumInitSenses = sizeof(Sycamore_IRQ_initsenses);
/* Identify the system */ /* Identify the system */
printk(KERN_INFO "IBM Sycamore (IBM405GPr) Platform\n"); printk(KERN_INFO "IBM Sycamore (IBM405GPr) Platform\n");
......
...@@ -17,8 +17,12 @@ ifeq ($(CONFIG_4xx),y) ...@@ -17,8 +17,12 @@ ifeq ($(CONFIG_4xx),y)
ifeq ($(CONFIG_VIRTEX_II_PRO),y) ifeq ($(CONFIG_VIRTEX_II_PRO),y)
obj-$(CONFIG_40x) += xilinx_pic.o obj-$(CONFIG_40x) += xilinx_pic.o
else else
ifeq ($(CONFIG_403),y)
obj-$(CONFIG_40x) += ppc403_pic.o
else
obj-$(CONFIG_40x) += ppc4xx_pic.o obj-$(CONFIG_40x) += ppc4xx_pic.o
endif endif
endif
obj-$(CONFIG_44x) += ppc4xx_pic.o obj-$(CONFIG_44x) += ppc4xx_pic.o
obj-$(CONFIG_40x) += ppc4xx_setup.o obj-$(CONFIG_40x) += ppc4xx_setup.o
obj-$(CONFIG_GEN_RTC) += todc_time.o obj-$(CONFIG_GEN_RTC) += todc_time.o
......
...@@ -142,19 +142,9 @@ static unsigned long __init ibm44x_find_end_of_memory(void) ...@@ -142,19 +142,9 @@ static unsigned long __init ibm44x_find_end_of_memory(void)
return mem_size; 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) 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.find_end_of_memory = ibm44x_find_end_of_memory;
ppc_md.restart = ibm44x_restart; ppc_md.restart = ibm44x_restart;
ppc_md.power_off = ibm44x_power_off; ppc_md.power_off = ibm44x_power_off;
......
/*
*
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
*
* 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 <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/stddef.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/ppc4xx_pic.h>
/* 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;
}
/* /*
* arch/ppc/syslib/ppc4xx_pic.c
* *
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> * Interrupt controller driver for PowerPC 4xx-based processors.
*
* 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.
* *
* The PowerPC 405/440 cores' Universal Interrupt Controller (UIC) has * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
* 32 possible interrupts as well. Depending on the core and SoC * Copyright (c) 2004 Zultys Technologies
* 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.
* *
* The PowerNP and 440GP (and most likely future implementations) have * Based on original code by
* cascaded UICs. * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
* Armin Custer <akuster@mvista.com>
* *
*/ * 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 <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/signal.h> #include <linux/signal.h>
...@@ -36,493 +26,212 @@ ...@@ -36,493 +26,212 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/ppc4xx_pic.h> #include <asm/ppc4xx_pic.h>
/* Global Variables */ /* See comment in include/arch-ppc/ppc4xx_pic.h
struct hw_interrupt_type *ppc4xx_pic; * for more info about these two variables
/*
* 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.
*/
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.
*/ */
extern struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[NR_UICS] __attribute__((weak));
#ifdef CONFIG_403 extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__((weak));
/* Function Prototypes */ #define IRQ_MASK_UIC0(irq) (1 << (31 - (irq)))
#define IRQ_MASK_UICx(irq) (1 << (31 - ((irq) & 0x1f)))
static void ppc403_aic_enable(unsigned int irq); #define IRQ_MASK_UIC1(irq) IRQ_MASK_UICx(irq)
static void ppc403_aic_disable(unsigned int irq); #define IRQ_MASK_UIC2(irq) IRQ_MASK_UICx(irq)
static void ppc403_aic_disable_and_ack(unsigned int irq);
#define UIC_HANDLERS(n) \
static struct hw_interrupt_type ppc403_aic = { static void ppc4xx_uic##n##_enable(unsigned int irq) \
"403GC AIC", { \
NULL, ppc_cached_irq_mask[n] |= IRQ_MASK_UIC##n(irq); \
NULL, mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
ppc403_aic_enable, } \
ppc403_aic_disable, \
ppc403_aic_disable_and_ack, static void ppc4xx_uic##n##_disable(unsigned int irq) \
0 { \
}; ppc_cached_irq_mask[n] &= ~IRQ_MASK_UIC##n(irq); \
mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
int } \
ppc403_pic_get_irq(struct pt_regs *regs) \
{ static void ppc4xx_uic##n##_ack(unsigned int irq) \
int irq; { \
unsigned long bits; u32 mask = IRQ_MASK_UIC##n(irq); \
ppc_cached_irq_mask[n] &= ~mask; \
/* mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
* Only report the status of those interrupts that are actually mtdcr(DCRN_UIC_SR(UIC##n), mask); \
* enabled. ACK_UIC##n##_PARENT \
*/ } \
\
bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER); static void ppc4xx_uic##n##_end(unsigned int irq) \
{ \
/* unsigned int status = irq_desc[irq].status; \
* Walk through the interrupts from highest priority to lowest, and u32 mask = IRQ_MASK_UIC##n(irq); \
* report the first pending interrupt found. if (status & IRQ_LEVEL){ \
* We want PPC, not C bit numbering, so just subtract the ffs() mtdcr(DCRN_UIC_SR(UIC##n), mask); \
* result from 32. ACK_UIC##n##_PARENT \
*/ } \
irq = 32 - ffs(bits); if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))){ \
ppc_cached_irq_mask[n] |= mask; \
if (irq == NR_AIC_IRQS) mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
irq = -1; } \
return (irq);
} }
static void #define DECLARE_UIC(n) \
ppc403_aic_enable(unsigned int irq) { \
.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)
{ {
int bit, word; u32 uicb = mfdcr(DCRN_UIC_MSR(UICB));
if (uicb & UICB_UIC0NC)
bit = irq & 0x1f; return 32 - ffs(mfdcr(DCRN_UIC_MSR(UIC0)));
word = irq >> 5; else if (uicb & UICB_UIC1NC)
return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
ppc_cached_irq_mask[word] |= (1 << (31 - bit)); else if (uicb & UICB_UIC2NC)
mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2)));
else
return -1;
} }
static void static void __init ppc4xx_pic_impl_init(void)
ppc403_aic_disable(unsigned int irq)
{ {
int bit, word; /* Configure Base UIC */
mtdcr(DCRN_UIC_CR(UICB), 0);
bit = irq & 0x1f; mtdcr(DCRN_UIC_TR(UICB), 0);
word = irq >> 5; mtdcr(DCRN_UIC_PR(UICB), 0xffffffff);
mtdcr(DCRN_UIC_SR(UICB), 0xffffffff);
ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); mtdcr(DCRN_UIC_ER(UICB), UICB_UIC0NC | UICB_UIC1NC | UICB_UIC2NC);
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)));
} }
#else #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);
#ifndef UIC1 static int ppc4xx_pic_get_irq(struct pt_regs *regs)
#define UIC1 UIC0
#endif
#ifndef UIC2
#define UIC2 UIC1
#endif
static void
ppc4xx_uic_enable(unsigned int irq)
{ {
int bit, word; u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
irq_desc_t *desc = irq_desc + irq; if (uic0 & UIC0_UIC1NC)
return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
bit = irq & 0x1f; else
word = irq >> 5; return uic0 ? 32 - ffs(uic0) : -1;
#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;
}
} }
static void static void __init ppc4xx_pic_impl_init(void)
ppc4xx_uic_disable(unsigned int irq)
{ {
int bit, word; /* Enable cascade interrupt in UIC0 */
ppc_cached_irq_mask[0] |= UIC0_UIC1NC;
bit = irq & 0x1f; mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
word = irq >> 5; mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]);
#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 #elif NR_UICS == 1
ppc4xx_uic_disable_and_ack(unsigned int irq) #define ACK_UIC0_PARENT
{ UIC_HANDLERS(0);
int bit, word;
bit = irq & 0x1f;
word = irq >> 5;
#ifdef UIC_DEBUG static int ppc4xx_pic_get_irq(struct pt_regs *regs)
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;
}
}
static void
ppc4xx_uic_end(unsigned int irq)
{ {
int bit, word; u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
unsigned int tr_bits = 0; return uic0 ? 32 - ffs(uic0) : -1;
}
bit = irq & 0x1f;
word = irq >> 5;
#ifdef UIC_DEBUG static inline void ppc4xx_pic_impl_init(void){}
printk("ppc4xx_uic_end - irq %d word %d bit 0x%x\n", irq, word, bit);
#endif #endif
switch (word) { static struct ppc4xx_uic_impl {
case 0: struct hw_interrupt_type decl;
tr_bits = mfdcr(DCRN_UIC_TR(UIC0)); int base; /* Base DCR number */
break; } __uic[] = {
case 1: { .decl = DECLARE_UIC(0), .base = UIC0 },
tr_bits = mfdcr(DCRN_UIC_TR(UIC1)); #if NR_UICS > 1
break; { .decl = DECLARE_UIC(1), .base = UIC1 },
case 2: #if NR_UICS > 2
tr_bits = mfdcr(DCRN_UIC_TR(UIC2)); { .decl = DECLARE_UIC(2), .base = 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);
#endif
break;
case 2:
mtdcr(DCRN_UIC_SR(UIC2), 1 << (31 - bit));
#if (NR_UICS > 2)
mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
#endif #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 #endif
NULL,
NULL,
ppc4xx_uic_enable,
ppc4xx_uic_disable,
ppc4xx_uic_disable_and_ack,
ppc4xx_uic_end,
0
}; };
int static inline int is_level_sensitive(int irq)
ppc4xx_pic_get_irq(struct pt_regs *regs)
{ {
int irq, cas_irq; u32 tr = mfdcr(DCRN_UIC_TR(__uic[irq >> 5].base));
unsigned long bits; return (tr & IRQ_MASK_UICx(irq)) == 0;
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);
} }
#endif
void __init void __init ppc4xx_pic_init(void)
ppc4xx_extpic_init(void)
{ {
/* set polarity int i;
* 1 = default/pos/rising , 0= neg/falling internal unsigned char* eirqs = ppc4xx_uic_ext_irq_cfg;
* 1 = neg/falling , 0= pos/rising external
* Sense for (i = 0; i < NR_UICS; ++i){
* 0 = default level internal int base = __uic[i].base;
* 0 = level, 1 = edge external
*/ /* Disable everything by default */
ppc_cached_irq_mask[i] = 0;
unsigned int sense, irq; mtdcr(DCRN_UIC_ER(base), 0);
int bit, word;
unsigned long ppc_cached_sense_mask[NR_MASK_WORDS]; /* We don't use critical interrupts */
unsigned long ppc_cached_pol_mask[NR_MASK_WORDS]; mtdcr(DCRN_UIC_CR(base), 0);
ppc_cached_sense_mask[0] = 0;
ppc_cached_sense_mask[1] = 0; /* Configure polarity and triggering */
ppc_cached_sense_mask[2] = 0; if (ppc4xx_core_uic_cfg){
ppc_cached_pol_mask[0] = 0; struct ppc4xx_uic_settings* p = ppc4xx_core_uic_cfg + i;
ppc_cached_pol_mask[1] = 0; u32 mask = p->ext_irq_mask;
ppc_cached_pol_mask[2] = 0; u32 pr = mfdcr(DCRN_UIC_PR(base)) & mask;
u32 tr = mfdcr(DCRN_UIC_TR(base)) & mask;
for (irq = 0; irq < NR_IRQS; irq++) {
/* "Fixed" interrupts (on-chip devices) */
bit = irq & 0x1f; pr |= p->polarity & ~mask;
word = irq >> 5; tr |= p->triggering & ~mask;
sense = /* Merge external IRQs settings if board port
(irq < * provided them
ibm4xxPIC_NumInitSenses) ? ibm4xxPIC_InitSenses[irq] : 3; */
#ifdef PPC4xx_PIC_DEBUG if (eirqs && mask){
printk("PPC4xx_picext %d word:%x bit:%x sense:%x", irq, word, pr &= ~mask;
bit, sense); tr &= ~mask;
#endif while (mask){
ppc_cached_sense_mask[word] |= /* Extract current external IRQ mask */
(~sense & IRQ_SENSE_MASK) << (31 - bit); u32 eirq_mask = 1 << __ilog2(mask);
ppc_cached_pol_mask[word] |=
((sense & IRQ_POLARITY_MASK) >> 1) << (31 - bit); if (!(*eirqs & IRQ_SENSE_LEVEL))
switch (word) { tr |= eirq_mask;
case 0:
#ifdef PPC4xx_PIC_DEBUG if (*eirqs & IRQ_POLARITY_POSITIVE)
printk("Pol %x ", mfdcr(DCRN_UIC_PR(UIC0))); pr |= eirq_mask;
printk("Level %x\n", mfdcr(DCRN_UIC_TR(UIC0)));
#endif mask &= ~eirq_mask;
/* polarity setting */ ++eirqs;
mtdcr(DCRN_UIC_PR(UIC0), ppc_cached_pol_mask[word]); }
}
/* Level setting */ mtdcr(DCRN_UIC_PR(base), pr);
mtdcr(DCRN_UIC_TR(UIC0), ppc_cached_sense_mask[word]); mtdcr(DCRN_UIC_TR(base), tr);
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;
} }
/* ACK any pending interrupts to prevent false
* triggering after first enable
*/
mtdcr(DCRN_UIC_SR(base), 0xffffffff);
} }
} /* Perform optional implementation specific setup
void __init * (e.g. enable cascade interrupts for multi-UIC configurations)
ppc4xx_pic_init(void)
{
/*
* Disable all external interrupts until they are
* explicity requested.
*/ */
ppc_cached_irq_mask[0] = 0; ppc4xx_pic_impl_init();
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; /* Attach low-level handlers */
ppc_md.get_irq = ppc403_pic_get_irq; for (i = 0; i < (NR_UICS << 5); ++i){
#else irq_desc[i].handler = &__uic[i >> 5].decl;
#if (NR_UICS > 2) if (is_level_sensitive(i))
mtdcr(DCRN_UIC_ER(UICB), UICB_UIC0NC | UICB_UIC1NC | UICB_UIC2NC); irq_desc[i].status |= IRQ_LEVEL;
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);
ppc4xx_pic = &ppc4xx_uic;
ppc_md.get_irq = ppc4xx_pic_get_irq; ppc_md.get_irq = ppc4xx_pic_get_irq;
#endif
} }
...@@ -133,12 +133,7 @@ ppc4xx_map_io(void) ...@@ -133,12 +133,7 @@ ppc4xx_map_io(void)
void __init void __init
ppc4xx_init_IRQ(void) ppc4xx_init_IRQ(void)
{ {
int i;
ppc4xx_pic_init(); ppc4xx_pic_init();
for (i = 0; i < NR_IRQS; i++)
irq_desc[i].handler = ppc4xx_pic;
} }
static void static void
......
...@@ -38,9 +38,6 @@ static volatile u32 *intc; ...@@ -38,9 +38,6 @@ static volatile u32 *intc;
#define intc_in_be32(addr) mfdcr((addr)) #define intc_in_be32(addr) mfdcr((addr))
#endif #endif
/* Global Variables */
struct hw_interrupt_type *ppc4xx_pic;
static void static void
xilinx_intc_enable(unsigned int irq) xilinx_intc_enable(unsigned int irq)
{ {
...@@ -115,6 +112,8 @@ xilinx_pic_get_irq(struct pt_regs *regs) ...@@ -115,6 +112,8 @@ xilinx_pic_get_irq(struct pt_regs *regs)
void __init void __init
ppc4xx_pic_init(void) ppc4xx_pic_init(void)
{ {
int i;
#if XPAR_XINTC_USE_DCR == 0 #if XPAR_XINTC_USE_DCR == 0
intc = ioremap(XPAR_INTC_0_BASEADDR, 32); intc = ioremap(XPAR_INTC_0_BASEADDR, 32);
...@@ -137,6 +136,8 @@ ppc4xx_pic_init(void) ...@@ -137,6 +136,8 @@ ppc4xx_pic_init(void)
/* Turn on the Master Enable. */ /* Turn on the Master Enable. */
intc_out_be32(intc + MER, 0x3UL); intc_out_be32(intc + MER, 0x3UL);
ppc4xx_pic = &xilinx_intc;
ppc_md.get_irq = xilinx_pic_get_irq; ppc_md.get_irq = xilinx_pic_get_irq;
for (i = 0; i < NR_IRQS; ++i)
irq_desc[i].handler = &xilinx_intc;
} }
...@@ -162,8 +162,7 @@ ...@@ -162,8 +162,7 @@
#define DCRN_UIC_VR(base) (base + 0x7) #define DCRN_UIC_VR(base) (base + 0x7)
#define DCRN_UIC_VCR(base) (base + 0x8) #define DCRN_UIC_VCR(base) (base + 0x8)
#define UIC0_UIC1NC 30 /* UIC1 non-critical interrupt */ #define UIC0_UIC1NC 0x00000002
#define UIC0_UIC1CR 31 /* UIC1 critical interrupt */
#define UICB_UIC0NC 0x40000000 #define UICB_UIC0NC 0x40000000
#define UICB_UIC1NC 0x10000000 #define UICB_UIC1NC 0x10000000
...@@ -518,7 +517,6 @@ ...@@ -518,7 +517,6 @@
#else #else
#define NR_UICS 2 #define NR_UICS 2
#endif #endif
#define UIC_CASCADE_MASK 0x0003 /* bits 30 & 31 */
#define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i] #define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i]
......
/* /*
* include/asm-ppc/ppc4xx_pic.h
* *
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> * Interrupt controller driver for PowerPC 4xx-based processors.
* *
* Module name: ppc4xx_pic.h * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
* *
* Description: * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
* Interrupt controller driver for PowerPC 4xx-based processors. * 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__ #ifndef __PPC4XX_PIC_H__
#define __PPC4XX_PIC_H__ #define __PPC4XX_PIC_H__
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h>
#include <linux/irq.h> #include <linux/irq.h>
/* External Global Variables */ /* "Fixed" UIC settings (they are chip, not board specific),
* e.g. polarity/triggerring for internal interrupt sources.
extern struct hw_interrupt_type *ppc4xx_pic; *
extern unsigned int ibm4xxPIC_NumInitSenses; * Platform port should provide NR_UICS-sized array named ppc4xx_core_uic_cfg
extern unsigned char *ibm4xxPIC_InitSenses; * with these "fixed" settings: .polarity contains exact value which will
* be written (masked with "ext_irq_mask") into UICx_PR register,
/* Function Prototypes */ * .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 void ppc4xx_pic_init(void);
extern int ppc4xx_pic_get_irq(struct pt_regs *regs);
#endif /* __PPC4XX_PIC_H__ */ #endif /* __PPC4XX_PIC_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment