📄 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 <platforms/4xx/xparameters/xparameters.h>#include <asm/ibm4xx.h>#include <asm/machdep.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 == 0static 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))#endifstatic voidxilinx_intc_enable(unsigned int irq){ unsigned long mask = (0x00000001 << (irq & 31)); pr_debug("enable: %d\n", irq); intc_out_be32(intc + SIE, mask);}static voidxilinx_intc_disable(unsigned int irq){ unsigned long mask = (0x00000001 << (irq & 31)); pr_debug("disable: %d\n", irq); intc_out_be32(intc + CIE, mask);}static voidxilinx_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 voidxilinx_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 = { .typename = "Xilinx Interrupt Controller", .enable = xilinx_intc_enable, .disable = xilinx_intc_disable, .ack = xilinx_intc_disable_and_ack, .end = xilinx_intc_end,};intxilinx_pic_get_irq(void){ 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 __initppc4xx_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 * explicitly 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].chip = &xilinx_intc; if (XPAR_INTC_0_KIND_OF_INTR & (0x00000001 << i)) irq_desc[i].status &= ~IRQ_LEVEL; else irq_desc[i].status |= IRQ_LEVEL; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -