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/device.h>
  22#include <linux/spinlock.h>
  23#include <linux/irq.h>
  24#include <linux/interrupt.h>
  25#include <linux/kernel_stat.h>
  26#include <asm/irq.h>
  27#include <asm/io.h>
  28#include <asm/prom.h>
  29#include <asm/dcr.h>
  30
  31#define NR_UIC_INTS     32
  32
  33#define UIC_SR          0x0
  34#define UIC_ER          0x2
  35#define UIC_CR          0x3
  36#define UIC_PR          0x4
  37#define UIC_TR          0x5
  38#define UIC_MSR         0x6
  39#define UIC_VR          0x7
  40#define UIC_VCR         0x8
  41
  42struct uic *primary_uic;
  43
  44struct uic {
  45        int index;
  46        int dcrbase;
  47
  48        raw_spinlock_t lock;
  49
  50        /* The remapper for this UIC */
  51        struct irq_domain       *irqhost;
  52};
  53
  54static void uic_unmask_irq(struct irq_data *d)
  55{
  56        struct uic *uic = irq_data_get_irq_chip_data(d);
  57        unsigned int src = irqd_to_hwirq(d);
  58        unsigned long flags;
  59        u32 er, sr;
  60
  61        sr = 1 << (31-src);
  62        raw_spin_lock_irqsave(&uic->lock, flags);
  63        /* ack level-triggered interrupts here */
  64        if (irqd_is_level_type(d))
  65                mtdcr(uic->dcrbase + UIC_SR, sr);
  66        er = mfdcr(uic->dcrbase + UIC_ER);
  67        er |= sr;
  68        mtdcr(uic->dcrbase + UIC_ER, er);
  69        raw_spin_unlock_irqrestore(&uic->lock, flags);
  70}
  71
  72static void uic_mask_irq(struct irq_data *d)
  73{
  74        struct uic *uic = irq_data_get_irq_chip_data(d);
  75        unsigned int src = irqd_to_hwirq(d);
  76        unsigned long flags;
  77        u32 er;
  78
  79        raw_spin_lock_irqsave(&uic->lock, flags);
  80        er = mfdcr(uic->dcrbase + UIC_ER);
  81        er &= ~(1 << (31 - src));
  82        mtdcr(uic->dcrbase + UIC_ER, er);
  83        raw_spin_unlock_irqrestore(&uic->lock, flags);
  84}
  85
  86static void uic_ack_irq(struct irq_data *d)
  87{
  88        struct uic *uic = irq_data_get_irq_chip_data(d);
  89        unsigned int src = irqd_to_hwirq(d);
  90        unsigned long flags;
  91
  92        raw_spin_lock_irqsave(&uic->lock, flags);
  93        mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src));
  94        raw_spin_unlock_irqrestore(&uic->lock, flags);
  95}
  96
  97static void uic_mask_ack_irq(struct irq_data *d)
  98{
  99        struct uic *uic = irq_data_get_irq_chip_data(d);
 100        unsigned int src = irqd_to_hwirq(d);
 101        unsigned long flags;
 102        u32 er, sr;
 103
 104        sr = 1 << (31-src);
 105        raw_spin_lock_irqsave(&uic->lock, flags);
 106        er = mfdcr(uic->dcrbase + UIC_ER);
 107        er &= ~sr;
 108        mtdcr(uic->dcrbase + UIC_ER, er);
 109        /* On the UIC, acking (i.e. clearing the SR bit)
 110         * a level irq will have no effect if the interrupt
 111         * is still asserted by the device, even if
 112         * the interrupt is already masked. Therefore
 113         * we only ack the egde interrupts here, while
 114         * level interrupts are ack'ed after the actual
 115         * isr call in the uic_unmask_irq()
 116         */
 117        if (!irqd_is_level_type(d))
 118                mtdcr(uic->dcrbase + UIC_SR, sr);
 119        raw_spin_unlock_irqrestore(&uic->lock, flags);
 120}
 121
 122static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 123{
 124        struct uic *uic = irq_data_get_irq_chip_data(d);
 125        unsigned int src = irqd_to_hwirq(d);
 126        unsigned long flags;
 127        int trigger, polarity;
 128        u32 tr, pr, mask;
 129
 130        switch (flow_type & IRQ_TYPE_SENSE_MASK) {
 131        case IRQ_TYPE_NONE:
 132                uic_mask_irq(d);
 133                return 0;
 134
 135        case IRQ_TYPE_EDGE_RISING:
 136                trigger = 1; polarity = 1;
 137                break;
 138        case IRQ_TYPE_EDGE_FALLING:
 139                trigger = 1; polarity = 0;
 140                break;
 141        case IRQ_TYPE_LEVEL_HIGH:
 142                trigger = 0; polarity = 1;
 143                break;
 144        case IRQ_TYPE_LEVEL_LOW:
 145                trigger = 0; polarity = 0;
 146                break;
 147        default:
 148                return -EINVAL;
 149        }
 150
 151        mask = ~(1 << (31 - src));
 152
 153        raw_spin_lock_irqsave(&uic->lock, flags);
 154        tr = mfdcr(uic->dcrbase + UIC_TR);
 155        pr = mfdcr(uic->dcrbase + UIC_PR);
 156        tr = (tr & mask) | (trigger << (31-src));
 157        pr = (pr & mask) | (polarity << (31-src));
 158
 159        mtdcr(uic->dcrbase + UIC_PR, pr);
 160        mtdcr(uic->dcrbase + UIC_TR, tr);
 161
 162        raw_spin_unlock_irqrestore(&uic->lock, flags);
 163
 164        return 0;
 165}
 166
 167static struct irq_chip uic_irq_chip = {
 168        .name           = "UIC",
 169        .irq_unmask     = uic_unmask_irq,
 170        .irq_mask       = uic_mask_irq,
 171        .irq_mask_ack   = uic_mask_ack_irq,
 172        .irq_ack        = uic_ack_irq,
 173        .irq_set_type   = uic_set_irq_type,
 174};
 175
 176static int uic_host_map(struct irq_domain *h, unsigned int virq,
 177                        irq_hw_number_t hw)
 178{
 179        struct uic *uic = h->host_data;
 180
 181        irq_set_chip_data(virq, uic);
 182        /* Despite the name, handle_level_irq() works for both level
 183         * and edge irqs on UIC.  FIXME: check this is correct */
 184        irq_set_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
 185
 186        /* Set default irq type */
 187        irq_set_irq_type(virq, IRQ_TYPE_NONE);
 188
 189        return 0;
 190}
 191
 192static const struct irq_domain_ops uic_host_ops = {
 193        .map    = uic_host_map,
 194        .xlate  = irq_domain_xlate_twocell,
 195};
 196
 197static void uic_irq_cascade(struct irq_desc *desc)
 198{
 199        struct irq_chip *chip = irq_desc_get_chip(desc);
 200        struct irq_data *idata = irq_desc_get_irq_data(desc);
 201        struct uic *uic = irq_desc_get_handler_data(desc);
 202        u32 msr;
 203        int src;
 204        int subvirq;
 205
 206        raw_spin_lock(&desc->lock);
 207        if (irqd_is_level_type(idata))
 208                chip->irq_mask(idata);
 209        else
 210                chip->irq_mask_ack(idata);
 211        raw_spin_unlock(&desc->lock);
 212
 213        msr = mfdcr(uic->dcrbase + UIC_MSR);
 214        if (!msr) /* spurious interrupt */
 215                goto uic_irq_ret;
 216
 217        src = 32 - ffs(msr);
 218
 219        subvirq = irq_linear_revmap(uic->irqhost, src);
 220        generic_handle_irq(subvirq);
 221
 222uic_irq_ret:
 223        raw_spin_lock(&desc->lock);
 224        if (irqd_is_level_type(idata))
 225                chip->irq_ack(idata);
 226        if (!irqd_irq_disabled(idata) && chip->irq_unmask)
 227                chip->irq_unmask(idata);
 228        raw_spin_unlock(&desc->lock);
 229}
 230
 231static struct uic * __init uic_init_one(struct device_node *node)
 232{
 233        struct uic *uic;
 234        const u32 *indexp, *dcrreg;
 235        int len;
 236
 237        BUG_ON(! of_device_is_compatible(node, "ibm,uic"));
 238
 239        uic = kzalloc(sizeof(*uic), GFP_KERNEL);
 240        if (! uic)
 241                return NULL; /* FIXME: panic? */
 242
 243        raw_spin_lock_init(&uic->lock);
 244        indexp = of_get_property(node, "cell-index", &len);
 245        if (!indexp || (len != sizeof(u32))) {
 246                printk(KERN_ERR "uic: Device node %s has missing or invalid "
 247                       "cell-index property\n", node->full_name);
 248                return NULL;
 249        }
 250        uic->index = *indexp;
 251
 252        dcrreg = of_get_property(node, "dcr-reg", &len);
 253        if (!dcrreg || (len != 2*sizeof(u32))) {
 254                printk(KERN_ERR "uic: Device node %s has missing or invalid "
 255                       "dcr-reg property\n", node->full_name);
 256                return NULL;
 257        }
 258        uic->dcrbase = *dcrreg;
 259
 260        uic->irqhost = irq_domain_add_linear(node, NR_UIC_INTS, &uic_host_ops,
 261                                             uic);
 262        if (! uic->irqhost)
 263                return NULL; /* FIXME: panic? */
 264
 265        /* Start with all interrupts disabled, level and non-critical */
 266        mtdcr(uic->dcrbase + UIC_ER, 0);
 267        mtdcr(uic->dcrbase + UIC_CR, 0);
 268        mtdcr(uic->dcrbase + UIC_TR, 0);
 269        /* Clear any pending interrupts, in case the firmware left some */
 270        mtdcr(uic->dcrbase + UIC_SR, 0xffffffff);
 271
 272        printk ("UIC%d (%d IRQ sources) at DCR 0x%x\n", uic->index,
 273                NR_UIC_INTS, uic->dcrbase);
 274
 275        return uic;
 276}
 277
 278void __init uic_init_tree(void)
 279{
 280        struct device_node *np;
 281        struct uic *uic;
 282        const u32 *interrupts;
 283
 284        /* First locate and initialize the top-level UIC */
 285        for_each_compatible_node(np, NULL, "ibm,uic") {
 286                interrupts = of_get_property(np, "interrupts", NULL);
 287                if (!interrupts)
 288                        break;
 289        }
 290
 291        BUG_ON(!np); /* uic_init_tree() assumes there's a UIC as the
 292                      * top-level interrupt controller */
 293        primary_uic = uic_init_one(np);
 294        if (!primary_uic)
 295                panic("Unable to initialize primary UIC %s\n", np->full_name);
 296
 297        irq_set_default_host(primary_uic->irqhost);
 298        of_node_put(np);
 299
 300        /* The scan again for cascaded UICs */
 301        for_each_compatible_node(np, NULL, "ibm,uic") {
 302                interrupts = of_get_property(np, "interrupts", NULL);
 303                if (interrupts) {
 304                        /* Secondary UIC */
 305                        int cascade_virq;
 306
 307                        uic = uic_init_one(np);
 308                        if (! uic)
 309                                panic("Unable to initialize a secondary UIC %s\n",
 310                                      np->full_name);
 311
 312                        cascade_virq = irq_of_parse_and_map(np, 0);
 313
 314                        irq_set_handler_data(cascade_virq, uic);
 315                        irq_set_chained_handler(cascade_virq, uic_irq_cascade);
 316
 317                        /* FIXME: setup critical cascade?? */
 318                }
 319        }
 320}
 321
 322/* Return an interrupt vector or 0 if no interrupt is pending. */
 323unsigned int uic_get_irq(void)
 324{
 325        u32 msr;
 326        int src;
 327
 328        BUG_ON(! primary_uic);
 329
 330        msr = mfdcr(primary_uic->dcrbase + UIC_MSR);
 331        src = 32 - ffs(msr);
 332
 333        return irq_linear_revmap(primary_uic->irqhost, src);
 334}
 335