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>
21 /* No one else should require these constants, so define them locally here. */
22 #define ISR 0 /* Interrupt Status Register */
23 #define IPR 1 /* Interrupt Pending Register */
24 #define IER 2 /* Interrupt Enable Register */
25 #define IAR 3 /* Interrupt Acknowledge Register */
26 #define SIE 4 /* Set Interrupt Enable bits */
27 #define CIE 5 /* Clear Interrupt Enable bits */
28 #define IVR 6 /* Interrupt Vector Register */
29 #define MER 7 /* Master Enable Register */
31 #if XPAR_XINTC_USE_DCR == 0
32 static volatile u32 *intc;
33 #define intc_out_be32(addr, mask) out_be32((addr), (mask))
34 #define intc_in_be32(addr) in_be32((addr))
36 #define intc XPAR_INTC_0_BASEADDR
37 #define intc_out_be32(addr, mask) mtdcr((addr), (mask))
38 #define intc_in_be32(addr) mfdcr((addr))
41 /* Global Variables */
42 struct hw_interrupt_type *ppc4xx_pic;
45 xilinx_intc_enable(unsigned int irq)
47 unsigned long mask = (0x00000001 << (irq & 31));
48 pr_debug("enable: %d\n", irq);
49 intc_out_be32(intc + SIE, mask);
53 xilinx_intc_disable(unsigned int irq)
55 unsigned long mask = (0x00000001 << (irq & 31));
56 pr_debug("disable: %d\n", irq);
57 intc_out_be32(intc + CIE, mask);
61 xilinx_intc_disable_and_ack(unsigned int irq)
63 unsigned long mask = (0x00000001 << (irq & 31));
64 pr_debug("disable_and_ack: %d\n", irq);
65 intc_out_be32(intc + CIE, mask);
66 if (!(irq_desc[irq].status & IRQ_LEVEL))
67 intc_out_be32(intc + IAR, mask); /* ack edge triggered intr */
71 xilinx_intc_end(unsigned int irq)
73 unsigned long mask = (0x00000001 << (irq & 31));
75 pr_debug("end: %d\n", irq);
76 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
77 intc_out_be32(intc + SIE, mask);
78 /* ack level sensitive intr */
79 if (irq_desc[irq].status & IRQ_LEVEL)
80 intc_out_be32(intc + IAR, mask);
84 static struct hw_interrupt_type xilinx_intc = {
85 "Xilinx Interrupt Controller",
90 xilinx_intc_disable_and_ack,
96 xilinx_pic_get_irq(struct pt_regs *regs)
101 * NOTE: This function is the one that needs to be improved in
102 * order to handle multiple interrupt controllers. It currently
103 * is hardcoded to check for interrupts only on the first INTC.
106 irq = intc_in_be32(intc + IVR);
110 pr_debug("get_irq: %d\n", irq);
116 ppc4xx_pic_init(void)
118 #if XPAR_XINTC_USE_DCR == 0
119 intc = ioremap(XPAR_INTC_0_BASEADDR, 32);
121 printk(KERN_INFO "Xilinx INTC #0 at 0x%08lX mapped to 0x%08lX\n",
122 (unsigned long) XPAR_INTC_0_BASEADDR, (unsigned long) intc);
124 printk(KERN_INFO "Xilinx INTC #0 at 0x%08lX (DCR)\n",
125 (unsigned long) XPAR_INTC_0_BASEADDR);
129 * Disable all external interrupts until they are
130 * explicity requested.
132 intc_out_be32(intc + IER, 0);
134 /* Acknowledge any pending interrupts just in case. */
135 intc_out_be32(intc + IAR, ~(u32) 0);
137 /* Turn on the Master Enable. */
138 intc_out_be32(intc + MER, 0x3UL);
140 ppc4xx_pic = &xilinx_intc;
141 ppc_md.get_irq = xilinx_pic_get_irq;