2 * arch/ppc/syslib/xilinx_pic.c
4 * Interrupt controller driver for Xilinx Virtex-II Pro.
6 * Author: MontaVista Software, Inc.
9 * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under
10 * the terms of the GNU General Public License version 2. This program
11 * is licensed "as is" without any warranty of any kind, whether express
15 #include <linux/init.h>
16 #include <linux/irq.h>
18 #include <asm/xparameters.h>
19 #include <asm/ibm4xx.h>
20 #include <asm/machdep.h>
22 /* No one else should require these constants, so define them locally here. */
23 #define ISR 0 /* Interrupt Status Register */
24 #define IPR 1 /* Interrupt Pending Register */
25 #define IER 2 /* Interrupt Enable Register */
26 #define IAR 3 /* Interrupt Acknowledge Register */
27 #define SIE 4 /* Set Interrupt Enable bits */
28 #define CIE 5 /* Clear Interrupt Enable bits */
29 #define IVR 6 /* Interrupt Vector Register */
30 #define MER 7 /* Master Enable Register */
32 #if XPAR_XINTC_USE_DCR == 0
33 static volatile u32
*intc
;
34 #define intc_out_be32(addr, mask) out_be32((addr), (mask))
35 #define intc_in_be32(addr) in_be32((addr))
37 #define intc XPAR_INTC_0_BASEADDR
38 #define intc_out_be32(addr, mask) mtdcr((addr), (mask))
39 #define intc_in_be32(addr) mfdcr((addr))
43 xilinx_intc_enable(unsigned int irq
)
45 unsigned long mask
= (0x00000001 << (irq
& 31));
46 pr_debug("enable: %d\n", irq
);
47 intc_out_be32(intc
+ SIE
, mask
);
51 xilinx_intc_disable(unsigned int irq
)
53 unsigned long mask
= (0x00000001 << (irq
& 31));
54 pr_debug("disable: %d\n", irq
);
55 intc_out_be32(intc
+ CIE
, mask
);
59 xilinx_intc_disable_and_ack(unsigned int irq
)
61 unsigned long mask
= (0x00000001 << (irq
& 31));
62 pr_debug("disable_and_ack: %d\n", irq
);
63 intc_out_be32(intc
+ CIE
, mask
);
64 if (!(irq_desc
[irq
].status
& IRQ_LEVEL
))
65 intc_out_be32(intc
+ IAR
, mask
); /* ack edge triggered intr */
69 xilinx_intc_end(unsigned int irq
)
71 unsigned long mask
= (0x00000001 << (irq
& 31));
73 pr_debug("end: %d\n", irq
);
74 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
| IRQ_INPROGRESS
))) {
75 intc_out_be32(intc
+ SIE
, mask
);
76 /* ack level sensitive intr */
77 if (irq_desc
[irq
].status
& IRQ_LEVEL
)
78 intc_out_be32(intc
+ IAR
, mask
);
82 static struct hw_interrupt_type xilinx_intc
= {
83 .typename
= "Xilinx Interrupt Controller",
84 .enable
= xilinx_intc_enable
,
85 .disable
= xilinx_intc_disable
,
86 .ack
= xilinx_intc_disable_and_ack
,
87 .end
= xilinx_intc_end
,
91 xilinx_pic_get_irq(struct pt_regs
*regs
)
96 * NOTE: This function is the one that needs to be improved in
97 * order to handle multiple interrupt controllers. It currently
98 * is hardcoded to check for interrupts only on the first INTC.
101 irq
= intc_in_be32(intc
+ IVR
);
105 pr_debug("get_irq: %d\n", irq
);
111 ppc4xx_pic_init(void)
116 * NOTE: The assumption here is that NR_IRQS is 32 or less
117 * (NR_IRQS is 32 for PowerPC 405 cores by default).
120 #error NR_IRQS > 32 not supported
123 #if XPAR_XINTC_USE_DCR == 0
124 intc
= ioremap(XPAR_INTC_0_BASEADDR
, 32);
126 printk(KERN_INFO
"Xilinx INTC #0 at 0x%08lX mapped to 0x%08lX\n",
127 (unsigned long) XPAR_INTC_0_BASEADDR
, (unsigned long) intc
);
129 printk(KERN_INFO
"Xilinx INTC #0 at 0x%08lX (DCR)\n",
130 (unsigned long) XPAR_INTC_0_BASEADDR
);
134 * Disable all external interrupts until they are
135 * explicity requested.
137 intc_out_be32(intc
+ IER
, 0);
139 /* Acknowledge any pending interrupts just in case. */
140 intc_out_be32(intc
+ IAR
, ~(u32
) 0);
142 /* Turn on the Master Enable. */
143 intc_out_be32(intc
+ MER
, 0x3UL
);
145 ppc_md
.get_irq
= xilinx_pic_get_irq
;
147 for (i
= 0; i
< NR_IRQS
; ++i
) {
148 irq_desc
[i
].handler
= &xilinx_intc
;
150 if (XPAR_INTC_0_KIND_OF_INTR
& (0x00000001 << i
))
151 irq_desc
[i
].status
&= ~IRQ_LEVEL
;
153 irq_desc
[i
].status
|= IRQ_LEVEL
;