1/* 2 * Interrupt controller driver for Xilinx Virtex FPGAs 3 * 4 * Copyright (C) 2007 Secret Lab Technologies Ltd. 5 * 6 * This file is licensed under the terms of the GNU General Public License 7 * version 2. This program is licensed "as is" without any warranty of any 8 * kind, whether express or implied. 9 * 10 */ 11 12/* 13 * This is a driver for the interrupt controller typically found in 14 * Xilinx Virtex FPGA designs. 15 * 16 * The interrupt sense levels are hard coded into the FPGA design with 17 * typically a 1:1 relationship between irq lines and devices (no shared 18 * irq lines). Therefore, this driver does not attempt to handle edge 19 * and level interrupts differently. 20 */ 21#undef DEBUG 22 23#include <linux/kernel.h> 24#include <linux/irq.h> 25#include <linux/of.h> 26#include <asm/io.h> 27#include <asm/processor.h> 28#include <asm/i8259.h> 29#include <asm/irq.h> 30 31/* 32 * INTC Registers 33 */ 34#define XINTC_ISR 0 /* Interrupt Status */ 35#define XINTC_IPR 4 /* Interrupt Pending */ 36#define XINTC_IER 8 /* Interrupt Enable */ 37#define XINTC_IAR 12 /* Interrupt Acknowledge */ 38#define XINTC_SIE 16 /* Set Interrupt Enable bits */ 39#define XINTC_CIE 20 /* Clear Interrupt Enable bits */ 40#define XINTC_IVR 24 /* Interrupt Vector */ 41#define XINTC_MER 28 /* Master Enable */ 42 43static struct irq_host *master_irqhost; 44 45#define XILINX_INTC_MAXIRQS (32) 46 47/* The following table allows the interrupt type, edge or level, 48 * to be cached after being read from the device tree until the interrupt 49 * is mapped 50 */ 51static int xilinx_intc_typetable[XILINX_INTC_MAXIRQS]; 52 53/* Map the interrupt type from the device tree to the interrupt types 54 * used by the interrupt subsystem 55 */ 56static unsigned char xilinx_intc_map_senses[] = { 57 IRQ_TYPE_EDGE_RISING, 58 IRQ_TYPE_EDGE_FALLING, 59 IRQ_TYPE_LEVEL_HIGH, 60 IRQ_TYPE_LEVEL_LOW, 61}; 62 63/* 64 * The interrupt controller is setup such that it doesn't work well with 65 * the level interrupt handler in the kernel because the handler acks the 66 * interrupt before calling the application interrupt handler. To deal with 67 * that, we use 2 different irq chips so that different functions can be 68 * used for level and edge type interrupts. 69 * 70 * IRQ Chip common (across level and edge) operations 71 */ 72static void xilinx_intc_mask(unsigned int virq) 73{ 74 int irq = virq_to_hw(virq); 75 void * regs = get_irq_chip_data(virq); 76 pr_debug("mask: %d\n", irq); 77 out_be32(regs + XINTC_CIE, 1 << irq); 78} 79 80static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type) 81{ 82 struct irq_desc *desc = irq_to_desc(virq); 83 84 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); 85 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; 86 if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) 87 desc->status |= IRQ_LEVEL; 88 return 0; 89} 90 91/* 92 * IRQ Chip level operations 93 */ 94static void xilinx_intc_level_unmask(unsigned int virq) 95{ 96 int irq = virq_to_hw(virq); 97 void * regs = get_irq_chip_data(virq); 98 pr_debug("unmask: %d\n", irq); 99 out_be32(regs + XINTC_SIE, 1 << irq); 100 101 /* ack level irqs because they can't be acked during 102 * ack function since the handle_level_irq function 103 * acks the irq before calling the inerrupt handler 104 */ 105 out_be32(regs + XINTC_IAR, 1 << irq); 106} 107 108static struct irq_chip xilinx_intc_level_irqchip = { 109 .name = "Xilinx Level INTC", 110 .mask = xilinx_intc_mask, 111 .mask_ack = xilinx_intc_mask, 112 .unmask = xilinx_intc_level_unmask, 113 .set_type = xilinx_intc_set_type, 114}; 115 116/* 117 * IRQ Chip edge operations 118 */ 119static void xilinx_intc_edge_unmask(unsigned int virq) 120{ 121 int irq = virq_to_hw(virq); 122 void *regs = get_irq_chip_data(virq); 123 pr_debug("unmask: %d\n", irq); 124 out_be32(regs + XINTC_SIE, 1 << irq); 125} 126 127static void xilinx_intc_edge_ack(unsigned int virq) 128{ 129 int irq = virq_to_hw(virq); 130 void * regs = get_irq_chip_data(virq); 131 pr_debug("ack: %d\n", irq); 132 out_be32(regs + XINTC_IAR, 1 << irq); 133} 134 135static struct irq_chip xilinx_intc_edge_irqchip = { 136 .name = "Xilinx Edge INTC", 137 .mask = xilinx_intc_mask, 138 .unmask = xilinx_intc_edge_unmask, 139 .ack = xilinx_intc_edge_ack, 140 .set_type = xilinx_intc_set_type, 141}; 142 143/* 144 * IRQ Host operations 145 */ 146 147/** 148 * xilinx_intc_xlate - translate virq# from device tree interrupts property 149 */ 150static int xilinx_intc_xlate(struct irq_host *h, struct device_node *ct, 151 const u32 *intspec, unsigned int intsize, 152 irq_hw_number_t *out_hwirq, 153 unsigned int *out_flags) 154{ 155 if ((intsize < 2) || (intspec[0] >= XILINX_INTC_MAXIRQS)) 156 return -EINVAL; 157 158 /* keep a copy of the interrupt type til the interrupt is mapped 159 */ 160 xilinx_intc_typetable[intspec[0]] = xilinx_intc_map_senses[intspec[1]]; 161 162 /* Xilinx uses 2 interrupt entries, the 1st being the h/w 163 * interrupt number, the 2nd being the interrupt type, edge or level 164 */ 165 *out_hwirq = intspec[0]; 166 *out_flags = xilinx_intc_map_senses[intspec[1]]; 167 168 return 0; 169} 170static int xilinx_intc_map(struct irq_host *h, unsigned int virq, 171 irq_hw_number_t irq) 172{ 173 set_irq_chip_data(virq, h->host_data); 174 175 if (xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_HIGH || 176 xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_LOW) { 177 set_irq_chip_and_handler(virq, &xilinx_intc_level_irqchip, 178 handle_level_irq); 179 } else { 180 set_irq_chip_and_handler(virq, &xilinx_intc_edge_irqchip, 181 handle_edge_irq); 182 } 183 return 0; 184} 185 186static struct irq_host_ops xilinx_intc_ops = { 187 .map = xilinx_intc_map, 188 .xlate = xilinx_intc_xlate, 189}; 190 191struct irq_host * __init 192xilinx_intc_init(struct device_node *np) 193{ 194 struct irq_host * irq; 195 void * regs; 196 197 /* Find and map the intc registers */ 198 regs = of_iomap(np, 0); 199 if (!regs) { 200 pr_err("xilinx_intc: could not map registers\n"); 201 return NULL; 202 } 203 204 /* Setup interrupt controller */ 205 out_be32(regs + XINTC_IER, 0); /* disable all irqs */ 206 out_be32(regs + XINTC_IAR, ~(u32) 0); /* Acknowledge pending irqs */ 207 out_be32(regs + XINTC_MER, 0x3UL); /* Turn on the Master Enable. */ 208 209 /* Allocate and initialize an irq_host structure. */ 210 irq = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, XILINX_INTC_MAXIRQS, 211 &xilinx_intc_ops, -1); 212 if (!irq) 213 panic(__FILE__ ": Cannot allocate IRQ host\n"); 214 irq->host_data = regs; 215 216 return irq; 217} 218 219int xilinx_intc_get_irq(void) 220{ 221 void * regs = master_irqhost->host_data; 222 pr_debug("get_irq:\n"); 223 return irq_linear_revmap(master_irqhost, in_be32(regs + XINTC_IVR)); 224} 225 226#if defined(CONFIG_PPC_I8259) 227/* 228 * Support code for cascading to 8259 interrupt controllers 229 */ 230static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc) 231{ 232 unsigned int cascade_irq = i8259_irq(); 233 if (cascade_irq) 234 generic_handle_irq(cascade_irq); 235 236 /* Let xilinx_intc end the interrupt */ 237 desc->chip->unmask(irq); 238} 239 240static void __init xilinx_i8259_setup_cascade(void) 241{ 242 struct device_node *cascade_node; 243 int cascade_irq; 244 245 /* Initialize i8259 controller */ 246 cascade_node = of_find_compatible_node(NULL, NULL, "chrp,iic"); 247 if (!cascade_node) 248 return; 249 250 cascade_irq = irq_of_parse_and_map(cascade_node, 0); 251 if (!cascade_irq) { 252 pr_err("virtex_ml510: Failed to map cascade interrupt\n"); 253 goto out; 254 } 255 256 i8259_init(cascade_node, 0); 257 set_irq_chained_handler(cascade_irq, xilinx_i8259_cascade); 258 259 /* Program irq 7 (usb/audio), 14/15 (ide) to level sensitive */ 260 /* This looks like a dirty hack to me --gcl */ 261 outb(0xc0, 0x4d0); 262 outb(0xc0, 0x4d1); 263 264 out: 265 of_node_put(cascade_node); 266} 267#else 268static inline void xilinx_i8259_setup_cascade(void) { return; } 269#endif /* defined(CONFIG_PPC_I8259) */ 270 271static struct of_device_id xilinx_intc_match[] __initconst = { 272 { .compatible = "xlnx,opb-intc-1.00.c", }, 273 { .compatible = "xlnx,xps-intc-1.00.a", }, 274 {} 275}; 276 277/* 278 * Initialize master Xilinx interrupt controller 279 */ 280void __init xilinx_intc_init_tree(void) 281{ 282 struct device_node *np; 283 284 /* find top level interrupt controller */ 285 for_each_matching_node(np, xilinx_intc_match) { 286 if (!of_get_property(np, "interrupts", NULL)) 287 break; 288 } 289 BUG_ON(!np); 290 291 master_irqhost = xilinx_intc_init(np); 292 BUG_ON(!master_irqhost); 293 294 irq_set_default_host(master_irqhost); 295 of_node_put(np); 296 297 xilinx_i8259_setup_cascade(); 298} 299