linux/arch/powerpc/sysdev/uic.c
<<
>>
Prefs
   1/*
   2 * arch/powerpc/sysdev/uic.c
   3 *
   4 * IBM PowerPC 4xx Universal Interrupt Controller
   5 *
   6 * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
   7 *
   8 * This program is free software; you can redistribute  it and/or modify it
   9 * under  the terms of  the GNU General  Public License as published by the
  10 * Free Software Foundation;  either version 2 of the  License, or (at your
  11 * option) any later version.
  12 */
  13#include <linux/kernel.h>
  14#include <linux/init.h>
  15#include <linux/errno.h>
  16#include <linux/reboot.h>
  17#include <linux/slab.h>
  18#include <linux/stddef.h>
  19#include <linux/sched.h>
  20#include <linux/signal.h>
  21#include <linux/sysdev.h>
  22#include <linux/device.h>
  23#include <linux/bootmem.h>
  24#include <linux/spinlock.h>
  25#include <linux/irq.h>
  26#include <linux/interrupt.h>
  27#include <linux/kernel_stat.h>
  28#include <asm/irq.h>
  29#include <asm/io.h>
  30#include <asm/prom.h>
  31#include <asm/dcr.h>
  32
  33#define NR_UIC_INTS     32
  34
  35#define UIC_SR          0x0
  36#define UIC_ER          0x2
  37#define UIC_CR          0x3
  38#define UIC_PR          0x4
  39#define UIC_TR          0x5
  40#define UIC_MSR         0x6
  41#define UIC_VR          0x7
  42#define UIC_VCR         0x8
  43
  44#define uic_irq_to_hw(virq)     (irq_map[virq].hwirq)
  45
  46struct uic *primary_uic;
  47
  48struct uic {
  49        int index;
  50        int dcrbase;
  51
  52        spinlock_t lock;
  53
  54        /* The remapper for this UIC */
  55        struct irq_host *irqhost;
  56};
  57
  58static void uic_unmask_irq(unsigned int virq)
  59{
  60        struct irq_desc *desc = get_irq_desc(virq);
  61        struct uic *uic = get_irq_chip_data(virq);
  62        unsigned int src = uic_irq_to_hw(virq);
  63        unsigned long flags;
  64        u32 er, sr;
  65
  66        sr = 1 << (31-src);
  67        spin_lock_irqsave(&uic->lock, flags);
  68        /* ack level-triggered interrupts here */
  69        if (desc->status & IRQ_LEVEL)
  70                mtdcr(uic->dcrbase + UIC_SR, sr);
  71        er = mfdcr(uic->dcrbase + UIC_ER);
  72        er |= sr;
  73        mtdcr(uic->dcrbase + UIC_ER, er);
  74        spin_unlock_irqrestore(&uic->lock, flags);
  75}
  76
  77static void uic_mask_irq(unsigned int virq)
  78{
  79        struct uic *uic = get_irq_chip_data(virq);
  80        unsigned int src = uic_irq_to_hw(virq);
  81        unsigned long flags;
  82        u32 er;
  83
  84        spin_lock_irqsave(&uic->lock, flags);
  85        er = mfdcr(uic->dcrbase + UIC_ER);
  86        er &= ~(1 << (31 - src));
  87        mtdcr(uic->dcrbase + UIC_ER, er);
  88        spin_unlock_irqrestore(&uic->lock, flags);
  89}
  90
  91static void uic_ack_irq(unsigned int virq)
  92{
  93        struct uic *uic = get_irq_chip_data(virq);
  94        unsigned int src = uic_irq_to_hw(virq);
  95        unsigned long flags;
  96
  97        spin_lock_irqsave(&uic->lock, flags);
  98        mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src));
  99        spin_unlock_irqrestore(&uic->lock, flags);
 100}
 101
 102static void uic_mask_ack_irq(unsigned int virq)
 103{
 104        struct irq_desc *desc = get_irq_desc(virq);
 105        struct uic *uic = get_irq_chip_data(virq);
 106        unsigned int src = uic_irq_to_hw(virq);
 107        unsigned long flags;
 108        u32 er, sr;
 109
 110        sr = 1 << (31-src);
 111        spin_lock_irqsave(&uic->lock, flags);
 112        er = mfdcr(uic->dcrbase + UIC_ER);
 113        er &= ~sr;
 114        mtdcr(uic->dcrbase + UIC_ER, er);
 115        /* On the UIC, acking (i.e. clearing the SR bit)
 116         * a level irq will have no effect if the interrupt
 117         * is still asserted by the device, even if
 118         * the interrupt is already masked. Therefore
 119         * we only ack the egde interrupts here, while
 120         * level interrupts are ack'ed after the actual
 121         * isr call in the uic_unmask_irq()
 122         */
 123        if (!(desc->status & IRQ_LEVEL))
 124                mtdcr(uic->dcrbase + UIC_SR, sr);
 125        spin_unlock_irqrestore(&uic->lock, flags);
 126}
 127
 128static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
 129{
 130        struct uic *uic = get_irq_chip_data(virq);
 131        unsigned int src = uic_irq_to_hw(virq);
 132        struct irq_desc *desc = get_irq_desc(virq);
 133        unsigned long flags;
 134        int trigger, polarity;
 135        u32 tr, pr, mask;
 136
 137        switch (flow_type & IRQ_TYPE_SENSE_MASK) {
 138        case IRQ_TYPE_NONE:
 139                uic_mask_irq(virq);
 140                return 0;
 141
 142        case IRQ_TYPE_EDGE_RISING:
 143                trigger = 1; polarity = 1;
 144                break;
 145        case IRQ_TYPE_EDGE_FALLING:
 146                trigger = 1; polarity = 0;
 147                break;
 148        case IRQ_TYPE_LEVEL_HIGH:
 149                trigger = 0; polarity = 1;
 150                break;
 151        case IRQ_TYPE_LEVEL_LOW:
 152                trigger = 0; polarity = 0;
 153                break;
 154        default:
 155                return -EINVAL;
 156        }
 157
 158        mask = ~(1 << (31 - src));
 159
 160        spin_lock_irqsave(&uic->lock, flags);
 161        tr = mfdcr(uic->dcrbase + UIC_TR);
 162        pr = mfdcr(uic->dcrbase + UIC_PR);
 163        tr = (tr & mask) | (trigger << (31-src));
 164        pr = (pr & mask) | (polarity << (31-src));
 165
 166        mtdcr(uic->dcrbase + UIC_PR, pr);
 167        mtdcr(uic->dcrbase + UIC_TR, tr);
 168
 169        desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
 170        desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
 171        if (!trigger)
 172                desc->status |= IRQ_LEVEL;
 173
 174        spin_unlock_irqrestore(&uic->lock, flags);
 175
 176        return 0;
 177}
 178
 179static struct irq_chip uic_irq_chip = {
 180        .typename       = " UIC  ",
 181        .unmask         = uic_unmask_irq,
 182        .mask           = uic_mask_irq,
 183        .mask_ack       = uic_mask_ack_irq,
 184        .ack            = uic_ack_irq,
 185        .set_type       = uic_set_irq_type,
 186};
 187
 188static int uic_host_map(struct irq_host *h, unsigned int virq,
 189                        irq_hw_number_t hw)
 190{
 191        struct uic *uic = h->host_data;
 192
 193        set_irq_chip_data(virq, uic);
 194        /* Despite the name, handle_level_irq() works for both level
 195         * and edge irqs on UIC.  FIXME: check this is correct */
 196        set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
 197
 198        /* Set default irq type */
 199        set_irq_type(virq, IRQ_TYPE_NONE);
 200
 201        return 0;
 202}
 203
 204static int uic_host_xlate(struct irq_host *h, struct device_node *ct,
 205                          u32 *intspec, unsigned int intsize,
 206                          irq_hw_number_t *out_hwirq, unsigned int *out_type)
 207
 208{
 209        /* UIC intspecs must have 2 cells */
 210        BUG_ON(intsize != 2);
 211        *out_hwirq = intspec[0];
 212        *out_type = intspec[1];
 213        return 0;
 214}
 215
 216static struct irq_host_ops uic_host_ops = {
 217        .map    = uic_host_map,
 218        .xlate  = uic_host_xlate,
 219};
 220
 221void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
 222{
 223        struct uic *uic = get_irq_data(virq);
 224        u32 msr;
 225        int src;
 226        int subvirq;
 227
 228        spin_lock(&desc->lock);
 229        if (desc->status & IRQ_LEVEL)
 230                desc->chip->mask(virq);
 231        else
 232                desc->chip->mask_ack(virq);
 233        spin_unlock(&desc->lock);
 234
 235        msr = mfdcr(uic->dcrbase + UIC_MSR);
 236        if (!msr) /* spurious interrupt */
 237                goto uic_irq_ret;
 238
 239        src = 32 - ffs(msr);
 240
 241        subvirq = irq_linear_revmap(uic->irqhost, src);
 242        generic_handle_irq(subvirq);
 243
 244uic_irq_ret:
 245        spin_lock(&desc->lock);
 246        if (desc->status & IRQ_LEVEL)
 247                desc->chip->ack(virq);
 248        if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
 249                desc->chip->unmask(virq);
 250        spin_unlock(&desc->lock);
 251}
 252
 253static struct uic * __init uic_init_one(struct device_node *node)
 254{
 255        struct uic *uic;
 256        const u32 *indexp, *dcrreg;
 257        int len;
 258
 259        BUG_ON(! of_device_is_compatible(node, "ibm,uic"));
 260
 261        uic = kzalloc(sizeof(*uic), GFP_KERNEL);
 262        if (! uic)
 263                return NULL; /* FIXME: panic? */
 264
 265        spin_lock_init(&uic->lock);
 266        indexp = of_get_property(node, "cell-index", &len);
 267        if (!indexp || (len != sizeof(u32))) {
 268                printk(KERN_ERR "uic: Device node %s has missing or invalid "
 269                       "cell-index property\n", node->full_name);
 270                return NULL;
 271        }
 272        uic->index = *indexp;
 273
 274        dcrreg = of_get_property(node, "dcr-reg", &len);
 275        if (!dcrreg || (len != 2*sizeof(u32))) {
 276                printk(KERN_ERR "uic: Device node %s has missing or invalid "
 277                       "dcr-reg property\n", node->full_name);
 278                return NULL;
 279        }
 280        uic->dcrbase = *dcrreg;
 281
 282        uic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
 283                                      NR_UIC_INTS, &uic_host_ops, -1);
 284        if (! uic->irqhost)
 285                return NULL; /* FIXME: panic? */
 286
 287        uic->irqhost->host_data = uic;
 288
 289        /* Start with all interrupts disabled, level and non-critical */
 290        mtdcr(uic->dcrbase + UIC_ER, 0);
 291        mtdcr(uic->dcrbase + UIC_CR, 0);
 292        mtdcr(uic->dcrbase + UIC_TR, 0);
 293        /* Clear any pending interrupts, in case the firmware left some */
 294        mtdcr(uic->dcrbase + UIC_SR, 0xffffffff);
 295
 296        printk ("UIC%d (%d IRQ sources) at DCR 0x%x\n", uic->index,
 297                NR_UIC_INTS, uic->dcrbase);
 298
 299        return uic;
 300}
 301
 302void __init uic_init_tree(void)
 303{
 304        struct device_node *np;
 305        struct uic *uic;
 306        const u32 *interrupts;
 307
 308        /* First locate and initialize the top-level UIC */
 309        for_each_compatible_node(np, NULL, "ibm,uic") {
 310                interrupts = of_get_property(np, "interrupts", NULL);
 311                if (!interrupts)
 312                        break;
 313        }
 314
 315        BUG_ON(!np); /* uic_init_tree() assumes there's a UIC as the
 316                      * top-level interrupt controller */
 317        primary_uic = uic_init_one(np);
 318        if (!primary_uic)
 319                panic("Unable to initialize primary UIC %s\n", np->full_name);
 320
 321        irq_set_default_host(primary_uic->irqhost);
 322        of_node_put(np);
 323
 324        /* The scan again for cascaded UICs */
 325        for_each_compatible_node(np, NULL, "ibm,uic") {
 326                interrupts = of_get_property(np, "interrupts", NULL);
 327                if (interrupts) {
 328                        /* Secondary UIC */
 329                        int cascade_virq;
 330
 331                        uic = uic_init_one(np);
 332                        if (! uic)
 333                                panic("Unable to initialize a secondary UIC %s\n",
 334                                      np->full_name);
 335
 336                        cascade_virq = irq_of_parse_and_map(np, 0);
 337
 338                        set_irq_data(cascade_virq, uic);
 339                        set_irq_chained_handler(cascade_virq, uic_irq_cascade);
 340
 341                        /* FIXME: setup critical cascade?? */
 342                }
 343        }
 344}
 345
 346/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
 347unsigned int uic_get_irq(void)
 348{
 349        u32 msr;
 350        int src;
 351
 352        BUG_ON(! primary_uic);
 353
 354        msr = mfdcr(primary_uic->dcrbase + UIC_MSR);
 355        src = 32 - ffs(msr);
 356
 357        return irq_linear_revmap(primary_uic->irqhost, src);
 358}
 359