123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /*
- * arch/ppc/syslib/xilinx_pic.c
- *
- * Interrupt controller driver for Xilinx Virtex-II Pro.
- *
- * Author: MontaVista Software, Inc.
- * source@mvista.com
- *
- * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
- #include <linux/init.h>
- #include <linux/irq.h>
- #include <asm/io.h>
- #include <asm/xparameters.h>
- #include <asm/ibm4xx.h>
- /* No one else should require these constants, so define them locally here. */
- #define ISR 0 /* Interrupt Status Register */
- #define IPR 1 /* Interrupt Pending Register */
- #define IER 2 /* Interrupt Enable Register */
- #define IAR 3 /* Interrupt Acknowledge Register */
- #define SIE 4 /* Set Interrupt Enable bits */
- #define CIE 5 /* Clear Interrupt Enable bits */
- #define IVR 6 /* Interrupt Vector Register */
- #define MER 7 /* Master Enable Register */
- #if XPAR_XINTC_USE_DCR == 0
- static volatile u32 *intc;
- #define intc_out_be32(addr, mask) out_be32((addr), (mask))
- #define intc_in_be32(addr) in_be32((addr))
- #else
- #define intc XPAR_INTC_0_BASEADDR
- #define intc_out_be32(addr, mask) mtdcr((addr), (mask))
- #define intc_in_be32(addr) mfdcr((addr))
- #endif
- static void
- xilinx_intc_enable(unsigned int irq)
- {
- unsigned long mask = (0x00000001 << (irq & 31));
- pr_debug("enable: %d\n", irq);
- intc_out_be32(intc + SIE, mask);
- }
- static void
- xilinx_intc_disable(unsigned int irq)
- {
- unsigned long mask = (0x00000001 << (irq & 31));
- pr_debug("disable: %d\n", irq);
- intc_out_be32(intc + CIE, mask);
- }
- static void
- xilinx_intc_disable_and_ack(unsigned int irq)
- {
- unsigned long mask = (0x00000001 << (irq & 31));
- pr_debug("disable_and_ack: %d\n", irq);
- intc_out_be32(intc + CIE, mask);
- if (!(irq_desc[irq].status & IRQ_LEVEL))
- intc_out_be32(intc + IAR, mask); /* ack edge triggered intr */
- }
- static void
- xilinx_intc_end(unsigned int irq)
- {
- unsigned long mask = (0x00000001 << (irq & 31));
- pr_debug("end: %d\n", irq);
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
- intc_out_be32(intc + SIE, mask);
- /* ack level sensitive intr */
- if (irq_desc[irq].status & IRQ_LEVEL)
- intc_out_be32(intc + IAR, mask);
- }
- }
- static struct hw_interrupt_type xilinx_intc = {
- "Xilinx Interrupt Controller",
- NULL,
- NULL,
- xilinx_intc_enable,
- xilinx_intc_disable,
- xilinx_intc_disable_and_ack,
- xilinx_intc_end,
- 0
- };
- int
- xilinx_pic_get_irq(struct pt_regs *regs)
- {
- int irq;
- /*
- * NOTE: This function is the one that needs to be improved in
- * order to handle multiple interrupt controllers. It currently
- * is hardcoded to check for interrupts only on the first INTC.
- */
- irq = intc_in_be32(intc + IVR);
- if (irq != -1)
- irq = irq;
- pr_debug("get_irq: %d\n", irq);
- return (irq);
- }
- void __init
- ppc4xx_pic_init(void)
- {
- int i;
- /*
- * NOTE: The assumption here is that NR_IRQS is 32 or less
- * (NR_IRQS is 32 for PowerPC 405 cores by default).
- */
- #if (NR_IRQS > 32)
- #error NR_IRQS > 32 not supported
- #endif
- #if XPAR_XINTC_USE_DCR == 0
- intc = ioremap(XPAR_INTC_0_BASEADDR, 32);
- printk(KERN_INFO "Xilinx INTC #0 at 0x%08lX mapped to 0x%08lX\n",
- (unsigned long) XPAR_INTC_0_BASEADDR, (unsigned long) intc);
- #else
- printk(KERN_INFO "Xilinx INTC #0 at 0x%08lX (DCR)\n",
- (unsigned long) XPAR_INTC_0_BASEADDR);
- #endif
- /*
- * Disable all external interrupts until they are
- * explicity requested.
- */
- intc_out_be32(intc + IER, 0);
- /* Acknowledge any pending interrupts just in case. */
- intc_out_be32(intc + IAR, ~(u32) 0);
- /* Turn on the Master Enable. */
- intc_out_be32(intc + MER, 0x3UL);
- ppc_md.get_irq = xilinx_pic_get_irq;
- for (i = 0; i < NR_IRQS; ++i) {
- irq_desc[i].handler = &xilinx_intc;
- if (XPAR_INTC_0_KIND_OF_INTR & (0x00000001 << i))
- irq_desc[i].status &= ~IRQ_LEVEL;
- else
- irq_desc[i].status |= IRQ_LEVEL;
- }
- }
|