linux/arch/powerpc/sysdev/xilinx_intc.c
<<
>>
Prefs
   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_domain *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(struct irq_data *d)
  73{
  74        int irq = irqd_to_hwirq(d);
  75        void * regs = irq_data_get_irq_chip_data(d);
  76        pr_debug("mask: %d\n", irq);
  77        out_be32(regs + XINTC_CIE, 1 << irq);
  78}
  79
  80static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
  81{
  82        return 0;
  83}
  84
  85/*
  86 * IRQ Chip level operations
  87 */
  88static void xilinx_intc_level_unmask(struct irq_data *d)
  89{
  90        int irq = irqd_to_hwirq(d);
  91        void * regs = irq_data_get_irq_chip_data(d);
  92        pr_debug("unmask: %d\n", irq);
  93        out_be32(regs + XINTC_SIE, 1 << irq);
  94
  95        /* ack level irqs because they can't be acked during
  96         * ack function since the handle_level_irq function
  97         * acks the irq before calling the inerrupt handler
  98         */
  99        out_be32(regs + XINTC_IAR, 1 << irq);
 100}
 101
 102static struct irq_chip xilinx_intc_level_irqchip = {
 103        .name = "Xilinx Level INTC",
 104        .irq_mask = xilinx_intc_mask,
 105        .irq_mask_ack = xilinx_intc_mask,
 106        .irq_unmask = xilinx_intc_level_unmask,
 107        .irq_set_type = xilinx_intc_set_type,
 108};
 109
 110/*
 111 * IRQ Chip edge operations
 112 */
 113static void xilinx_intc_edge_unmask(struct irq_data *d)
 114{
 115        int irq = irqd_to_hwirq(d);
 116        void *regs = irq_data_get_irq_chip_data(d);
 117        pr_debug("unmask: %d\n", irq);
 118        out_be32(regs + XINTC_SIE, 1 << irq);
 119}
 120
 121static void xilinx_intc_edge_ack(struct irq_data *d)
 122{
 123        int irq = irqd_to_hwirq(d);
 124        void * regs = irq_data_get_irq_chip_data(d);
 125        pr_debug("ack: %d\n", irq);
 126        out_be32(regs + XINTC_IAR, 1 << irq);
 127}
 128
 129static struct irq_chip xilinx_intc_edge_irqchip = {
 130        .name = "Xilinx Edge  INTC",
 131        .irq_mask = xilinx_intc_mask,
 132        .irq_unmask = xilinx_intc_edge_unmask,
 133        .irq_ack = xilinx_intc_edge_ack,
 134        .irq_set_type = xilinx_intc_set_type,
 135};
 136
 137/*
 138 * IRQ Host operations
 139 */
 140
 141/**
 142 * xilinx_intc_xlate - translate virq# from device tree interrupts property
 143 */
 144static int xilinx_intc_xlate(struct irq_domain *h, struct device_node *ct,
 145                                const u32 *intspec, unsigned int intsize,
 146                                irq_hw_number_t *out_hwirq,
 147                                unsigned int *out_flags)
 148{
 149        if ((intsize < 2) || (intspec[0] >= XILINX_INTC_MAXIRQS))
 150                return -EINVAL;
 151
 152        /* keep a copy of the interrupt type til the interrupt is mapped
 153         */
 154        xilinx_intc_typetable[intspec[0]] = xilinx_intc_map_senses[intspec[1]];
 155
 156        /* Xilinx uses 2 interrupt entries, the 1st being the h/w
 157         * interrupt number, the 2nd being the interrupt type, edge or level
 158         */
 159        *out_hwirq = intspec[0];
 160        *out_flags = xilinx_intc_map_senses[intspec[1]];
 161
 162        return 0;
 163}
 164static int xilinx_intc_map(struct irq_domain *h, unsigned int virq,
 165                                  irq_hw_number_t irq)
 166{
 167        irq_set_chip_data(virq, h->host_data);
 168
 169        if (xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_HIGH ||
 170            xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_LOW) {
 171                irq_set_chip_and_handler(virq, &xilinx_intc_level_irqchip,
 172                                         handle_level_irq);
 173        } else {
 174                irq_set_chip_and_handler(virq, &xilinx_intc_edge_irqchip,
 175                                         handle_edge_irq);
 176        }
 177        return 0;
 178}
 179
 180static struct irq_domain_ops xilinx_intc_ops = {
 181        .map = xilinx_intc_map,
 182        .xlate = xilinx_intc_xlate,
 183};
 184
 185struct irq_domain * __init
 186xilinx_intc_init(struct device_node *np)
 187{
 188        struct irq_domain * irq;
 189        void * regs;
 190
 191        /* Find and map the intc registers */
 192        regs = of_iomap(np, 0);
 193        if (!regs) {
 194                pr_err("xilinx_intc: could not map registers\n");
 195                return NULL;
 196        }
 197
 198        /* Setup interrupt controller */
 199        out_be32(regs + XINTC_IER, 0); /* disable all irqs */
 200        out_be32(regs + XINTC_IAR, ~(u32) 0); /* Acknowledge pending irqs */
 201        out_be32(regs + XINTC_MER, 0x3UL); /* Turn on the Master Enable. */
 202
 203        /* Allocate and initialize an irq_domain structure. */
 204        irq = irq_domain_add_linear(np, XILINX_INTC_MAXIRQS, &xilinx_intc_ops,
 205                                    regs);
 206        if (!irq)
 207                panic(__FILE__ ": Cannot allocate IRQ host\n");
 208
 209        return irq;
 210}
 211
 212int xilinx_intc_get_irq(void)
 213{
 214        void * regs = master_irqhost->host_data;
 215        pr_debug("get_irq:\n");
 216        return irq_linear_revmap(master_irqhost, in_be32(regs + XINTC_IVR));
 217}
 218
 219#if defined(CONFIG_PPC_I8259)
 220/*
 221 * Support code for cascading to 8259 interrupt controllers
 222 */
 223static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
 224{
 225        struct irq_chip *chip = irq_desc_get_chip(desc);
 226        unsigned int cascade_irq = i8259_irq();
 227
 228        if (cascade_irq)
 229                generic_handle_irq(cascade_irq);
 230
 231        /* Let xilinx_intc end the interrupt */
 232        chip->irq_unmask(&desc->irq_data);
 233}
 234
 235static void __init xilinx_i8259_setup_cascade(void)
 236{
 237        struct device_node *cascade_node;
 238        int cascade_irq;
 239
 240        /* Initialize i8259 controller */
 241        cascade_node = of_find_compatible_node(NULL, NULL, "chrp,iic");
 242        if (!cascade_node)
 243                return;
 244
 245        cascade_irq = irq_of_parse_and_map(cascade_node, 0);
 246        if (!cascade_irq) {
 247                pr_err("virtex_ml510: Failed to map cascade interrupt\n");
 248                goto out;
 249        }
 250
 251        i8259_init(cascade_node, 0);
 252        irq_set_chained_handler(cascade_irq, xilinx_i8259_cascade);
 253
 254        /* Program irq 7 (usb/audio), 14/15 (ide) to level sensitive */
 255        /* This looks like a dirty hack to me --gcl */
 256        outb(0xc0, 0x4d0);
 257        outb(0xc0, 0x4d1);
 258
 259 out:
 260        of_node_put(cascade_node);
 261}
 262#else
 263static inline void xilinx_i8259_setup_cascade(void) { return; }
 264#endif /* defined(CONFIG_PPC_I8259) */
 265
 266static struct of_device_id xilinx_intc_match[] __initconst = {
 267        { .compatible = "xlnx,opb-intc-1.00.c", },
 268        { .compatible = "xlnx,xps-intc-1.00.a", },
 269        {}
 270};
 271
 272/*
 273 * Initialize master Xilinx interrupt controller
 274 */
 275void __init xilinx_intc_init_tree(void)
 276{
 277        struct device_node *np;
 278
 279        /* find top level interrupt controller */
 280        for_each_matching_node(np, xilinx_intc_match) {
 281                if (!of_get_property(np, "interrupts", NULL))
 282                        break;
 283        }
 284        BUG_ON(!np);
 285
 286        master_irqhost = xilinx_intc_init(np);
 287        BUG_ON(!master_irqhost);
 288
 289        irq_set_default_host(master_irqhost);
 290        of_node_put(np);
 291
 292        xilinx_i8259_setup_cascade();
 293}
 294