Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16 155 lines 4.0 kB view raw
1/* 2 * arch/ppc/syslib/xilinx_pic.c 3 * 4 * Interrupt controller driver for Xilinx Virtex-II Pro. 5 * 6 * Author: MontaVista Software, Inc. 7 * source@mvista.com 8 * 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 12 * or implied. 13 */ 14 15#include <linux/init.h> 16#include <linux/irq.h> 17#include <asm/io.h> 18#include <asm/xparameters.h> 19#include <asm/ibm4xx.h> 20#include <asm/machdep.h> 21 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 */ 31 32#if XPAR_XINTC_USE_DCR == 0 33static volatile u32 *intc; 34#define intc_out_be32(addr, mask) out_be32((addr), (mask)) 35#define intc_in_be32(addr) in_be32((addr)) 36#else 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)) 40#endif 41 42static void 43xilinx_intc_enable(unsigned int irq) 44{ 45 unsigned long mask = (0x00000001 << (irq & 31)); 46 pr_debug("enable: %d\n", irq); 47 intc_out_be32(intc + SIE, mask); 48} 49 50static void 51xilinx_intc_disable(unsigned int irq) 52{ 53 unsigned long mask = (0x00000001 << (irq & 31)); 54 pr_debug("disable: %d\n", irq); 55 intc_out_be32(intc + CIE, mask); 56} 57 58static void 59xilinx_intc_disable_and_ack(unsigned int irq) 60{ 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 */ 66} 67 68static void 69xilinx_intc_end(unsigned int irq) 70{ 71 unsigned long mask = (0x00000001 << (irq & 31)); 72 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); 79 } 80} 81 82static 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, 88}; 89 90int 91xilinx_pic_get_irq(struct pt_regs *regs) 92{ 93 int irq; 94 95 /* 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. 99 */ 100 101 irq = intc_in_be32(intc + IVR); 102 if (irq != -1) 103 irq = irq; 104 105 pr_debug("get_irq: %d\n", irq); 106 107 return (irq); 108} 109 110void __init 111ppc4xx_pic_init(void) 112{ 113 int i; 114 115 /* 116 * NOTE: The assumption here is that NR_IRQS is 32 or less 117 * (NR_IRQS is 32 for PowerPC 405 cores by default). 118 */ 119#if (NR_IRQS > 32) 120#error NR_IRQS > 32 not supported 121#endif 122 123#if XPAR_XINTC_USE_DCR == 0 124 intc = ioremap(XPAR_INTC_0_BASEADDR, 32); 125 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); 128#else 129 printk(KERN_INFO "Xilinx INTC #0 at 0x%08lX (DCR)\n", 130 (unsigned long) XPAR_INTC_0_BASEADDR); 131#endif 132 133 /* 134 * Disable all external interrupts until they are 135 * explicity requested. 136 */ 137 intc_out_be32(intc + IER, 0); 138 139 /* Acknowledge any pending interrupts just in case. */ 140 intc_out_be32(intc + IAR, ~(u32) 0); 141 142 /* Turn on the Master Enable. */ 143 intc_out_be32(intc + MER, 0x3UL); 144 145 ppc_md.get_irq = xilinx_pic_get_irq; 146 147 for (i = 0; i < NR_IRQS; ++i) { 148 irq_desc[i].handler = &xilinx_intc; 149 150 if (XPAR_INTC_0_KIND_OF_INTR & (0x00000001 << i)) 151 irq_desc[i].status &= ~IRQ_LEVEL; 152 else 153 irq_desc[i].status |= IRQ_LEVEL; 154 } 155}