linux/arch/sparc/kernel/sun4d_irq.c
<<
>>
Prefs
   1/*
   2 * SS1000/SC2000 interrupt handling.
   3 *
   4 *  Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   5 *  Heavily based on arch/sparc/kernel/irq.c.
   6 */
   7
   8#include <linux/kernel_stat.h>
   9#include <linux/slab.h>
  10#include <linux/seq_file.h>
  11
  12#include <asm/timer.h>
  13#include <asm/traps.h>
  14#include <asm/irq.h>
  15#include <asm/io.h>
  16#include <asm/sbi.h>
  17#include <asm/cacheflush.h>
  18#include <asm/setup.h>
  19#include <asm/oplib.h>
  20
  21#include "kernel.h"
  22#include "irq.h"
  23
  24/* Sun4d interrupts fall roughly into two categories.  SBUS and
  25 * cpu local.  CPU local interrupts cover the timer interrupts
  26 * and whatnot, and we encode those as normal PILs between
  27 * 0 and 15.
  28 * SBUS interrupts are encodes as a combination of board, level and slot.
  29 */
  30
  31struct sun4d_handler_data {
  32        unsigned int cpuid;    /* target cpu */
  33        unsigned int real_irq; /* interrupt level */
  34};
  35
  36
  37static unsigned int sun4d_encode_irq(int board, int lvl, int slot)
  38{
  39        return (board + 1) << 5 | (lvl << 2) | slot;
  40}
  41
  42struct sun4d_timer_regs {
  43        u32     l10_timer_limit;
  44        u32     l10_cur_countx;
  45        u32     l10_limit_noclear;
  46        u32     ctrl;
  47        u32     l10_cur_count;
  48};
  49
  50static struct sun4d_timer_regs __iomem *sun4d_timers;
  51
  52#define SUN4D_TIMER_IRQ        10
  53
  54/* Specify which cpu handle interrupts from which board.
  55 * Index is board - value is cpu.
  56 */
  57static unsigned char board_to_cpu[32];
  58
  59static int pil_to_sbus[] = {
  60        0,
  61        0,
  62        1,
  63        2,
  64        0,
  65        3,
  66        0,
  67        4,
  68        0,
  69        5,
  70        0,
  71        6,
  72        0,
  73        7,
  74        0,
  75        0,
  76};
  77
  78/* Exported for sun4d_smp.c */
  79DEFINE_SPINLOCK(sun4d_imsk_lock);
  80
  81/* SBUS interrupts are encoded integers including the board number
  82 * (plus one), the SBUS level, and the SBUS slot number.  Sun4D
  83 * IRQ dispatch is done by:
  84 *
  85 * 1) Reading the BW local interrupt table in order to get the bus
  86 *    interrupt mask.
  87 *
  88 *    This table is indexed by SBUS interrupt level which can be
  89 *    derived from the PIL we got interrupted on.
  90 *
  91 * 2) For each bus showing interrupt pending from #1, read the
  92 *    SBI interrupt state register.  This will indicate which slots
  93 *    have interrupts pending for that SBUS interrupt level.
  94 *
  95 * 3) Call the genreric IRQ support.
  96 */
  97static void sun4d_sbus_handler_irq(int sbusl)
  98{
  99        unsigned int bus_mask;
 100        unsigned int sbino, slot;
 101        unsigned int sbil;
 102
 103        bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff;
 104        bw_clear_intr_mask(sbusl, bus_mask);
 105
 106        sbil = (sbusl << 2);
 107        /* Loop for each pending SBI */
 108        for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) {
 109                unsigned int idx, mask;
 110
 111                if (!(bus_mask & 1))
 112                        continue;
 113                /* XXX This seems to ACK the irq twice.  acquire_sbi()
 114                 * XXX uses swap, therefore this writes 0xf << sbil,
 115                 * XXX then later release_sbi() will write the individual
 116                 * XXX bits which were set again.
 117                 */
 118                mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil);
 119                mask &= (0xf << sbil);
 120
 121                /* Loop for each pending SBI slot */
 122                slot = (1 << sbil);
 123                for (idx = 0; mask != 0; idx++, slot <<= 1) {
 124                        unsigned int pil;
 125                        struct irq_bucket *p;
 126
 127                        if (!(mask & slot))
 128                                continue;
 129
 130                        mask &= ~slot;
 131                        pil = sun4d_encode_irq(sbino, sbusl, idx);
 132
 133                        p = irq_map[pil];
 134                        while (p) {
 135                                struct irq_bucket *next;
 136
 137                                next = p->next;
 138                                generic_handle_irq(p->irq);
 139                                p = next;
 140                        }
 141                        release_sbi(SBI2DEVID(sbino), slot);
 142                }
 143        }
 144}
 145
 146void sun4d_handler_irq(unsigned int pil, struct pt_regs *regs)
 147{
 148        struct pt_regs *old_regs;
 149        /* SBUS IRQ level (1 - 7) */
 150        int sbusl = pil_to_sbus[pil];
 151
 152        /* FIXME: Is this necessary?? */
 153        cc_get_ipen();
 154
 155        cc_set_iclr(1 << pil);
 156
 157#ifdef CONFIG_SMP
 158        /*
 159         * Check IPI data structures after IRQ has been cleared. Hard and Soft
 160         * IRQ can happen at the same time, so both cases are always handled.
 161         */
 162        if (pil == SUN4D_IPI_IRQ)
 163                sun4d_ipi_interrupt();
 164#endif
 165
 166        old_regs = set_irq_regs(regs);
 167        irq_enter();
 168        if (sbusl == 0) {
 169                /* cpu interrupt */
 170                struct irq_bucket *p;
 171
 172                p = irq_map[pil];
 173                while (p) {
 174                        struct irq_bucket *next;
 175
 176                        next = p->next;
 177                        generic_handle_irq(p->irq);
 178                        p = next;
 179                }
 180        } else {
 181                /* SBUS interrupt */
 182                sun4d_sbus_handler_irq(sbusl);
 183        }
 184        irq_exit();
 185        set_irq_regs(old_regs);
 186}
 187
 188
 189static void sun4d_mask_irq(struct irq_data *data)
 190{
 191        struct sun4d_handler_data *handler_data = irq_data_get_irq_handler_data(data);
 192        unsigned int real_irq;
 193#ifdef CONFIG_SMP
 194        int cpuid = handler_data->cpuid;
 195        unsigned long flags;
 196#endif
 197        real_irq = handler_data->real_irq;
 198#ifdef CONFIG_SMP
 199        spin_lock_irqsave(&sun4d_imsk_lock, flags);
 200        cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | (1 << real_irq));
 201        spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
 202#else
 203        cc_set_imsk(cc_get_imsk() | (1 << real_irq));
 204#endif
 205}
 206
 207static void sun4d_unmask_irq(struct irq_data *data)
 208{
 209        struct sun4d_handler_data *handler_data = irq_data_get_irq_handler_data(data);
 210        unsigned int real_irq;
 211#ifdef CONFIG_SMP
 212        int cpuid = handler_data->cpuid;
 213        unsigned long flags;
 214#endif
 215        real_irq = handler_data->real_irq;
 216
 217#ifdef CONFIG_SMP
 218        spin_lock_irqsave(&sun4d_imsk_lock, flags);
 219        cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) & ~(1 << real_irq));
 220        spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
 221#else
 222        cc_set_imsk(cc_get_imsk() & ~(1 << real_irq));
 223#endif
 224}
 225
 226static unsigned int sun4d_startup_irq(struct irq_data *data)
 227{
 228        irq_link(data->irq);
 229        sun4d_unmask_irq(data);
 230        return 0;
 231}
 232
 233static void sun4d_shutdown_irq(struct irq_data *data)
 234{
 235        sun4d_mask_irq(data);
 236        irq_unlink(data->irq);
 237}
 238
 239static struct irq_chip sun4d_irq = {
 240        .name           = "sun4d",
 241        .irq_startup    = sun4d_startup_irq,
 242        .irq_shutdown   = sun4d_shutdown_irq,
 243        .irq_unmask     = sun4d_unmask_irq,
 244        .irq_mask       = sun4d_mask_irq,
 245};
 246
 247#ifdef CONFIG_SMP
 248/* Setup IRQ distribution scheme. */
 249void __init sun4d_distribute_irqs(void)
 250{
 251        struct device_node *dp;
 252
 253        int cpuid = cpu_logical_map(1);
 254
 255        if (cpuid == -1)
 256                cpuid = cpu_logical_map(0);
 257        for_each_node_by_name(dp, "sbi") {
 258                int devid = of_getintprop_default(dp, "device-id", 0);
 259                int board = of_getintprop_default(dp, "board#", 0);
 260                board_to_cpu[board] = cpuid;
 261                set_sbi_tid(devid, cpuid << 3);
 262        }
 263        printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid);
 264}
 265#endif
 266
 267static void sun4d_clear_clock_irq(void)
 268{
 269        sbus_readl(&sun4d_timers->l10_timer_limit);
 270}
 271
 272static void sun4d_load_profile_irq(int cpu, unsigned int limit)
 273{
 274        unsigned int value = limit ? timer_value(limit) : 0;
 275        bw_set_prof_limit(cpu, value);
 276}
 277
 278static void __init sun4d_load_profile_irqs(void)
 279{
 280        int cpu = 0, mid;
 281
 282        while (!cpu_find_by_instance(cpu, NULL, &mid)) {
 283                sun4d_load_profile_irq(mid >> 3, 0);
 284                cpu++;
 285        }
 286}
 287
 288static unsigned int _sun4d_build_device_irq(unsigned int real_irq,
 289                                            unsigned int pil,
 290                                            unsigned int board)
 291{
 292        struct sun4d_handler_data *handler_data;
 293        unsigned int irq;
 294
 295        irq = irq_alloc(real_irq, pil);
 296        if (irq == 0) {
 297                prom_printf("IRQ: allocate for %d %d %d failed\n",
 298                        real_irq, pil, board);
 299                goto err_out;
 300        }
 301
 302        handler_data = irq_get_handler_data(irq);
 303        if (unlikely(handler_data))
 304                goto err_out;
 305
 306        handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC);
 307        if (unlikely(!handler_data)) {
 308                prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n");
 309                prom_halt();
 310        }
 311        handler_data->cpuid    = board_to_cpu[board];
 312        handler_data->real_irq = real_irq;
 313        irq_set_chip_and_handler_name(irq, &sun4d_irq,
 314                                      handle_level_irq, "level");
 315        irq_set_handler_data(irq, handler_data);
 316
 317err_out:
 318        return irq;
 319}
 320
 321
 322
 323static unsigned int sun4d_build_device_irq(struct platform_device *op,
 324                                           unsigned int real_irq)
 325{
 326        struct device_node *dp = op->dev.of_node;
 327        struct device_node *board_parent, *bus = dp->parent;
 328        char *bus_connection;
 329        const struct linux_prom_registers *regs;
 330        unsigned int pil;
 331        unsigned int irq;
 332        int board, slot;
 333        int sbusl;
 334
 335        irq = real_irq;
 336        while (bus) {
 337                if (!strcmp(bus->name, "sbi")) {
 338                        bus_connection = "io-unit";
 339                        break;
 340                }
 341
 342                if (!strcmp(bus->name, "bootbus")) {
 343                        bus_connection = "cpu-unit";
 344                        break;
 345                }
 346
 347                bus = bus->parent;
 348        }
 349        if (!bus)
 350                goto err_out;
 351
 352        regs = of_get_property(dp, "reg", NULL);
 353        if (!regs)
 354                goto err_out;
 355
 356        slot = regs->which_io;
 357
 358        /*
 359         * If Bus nodes parent is not io-unit/cpu-unit or the io-unit/cpu-unit
 360         * lacks a "board#" property, something is very wrong.
 361         */
 362        if (!bus->parent || strcmp(bus->parent->name, bus_connection)) {
 363                printk(KERN_ERR "%s: Error, parent is not %s.\n",
 364                        bus->full_name, bus_connection);
 365                goto err_out;
 366        }
 367        board_parent = bus->parent;
 368        board = of_getintprop_default(board_parent, "board#", -1);
 369        if (board == -1) {
 370                printk(KERN_ERR "%s: Error, lacks board# property.\n",
 371                        board_parent->full_name);
 372                goto err_out;
 373        }
 374
 375        sbusl = pil_to_sbus[real_irq];
 376        if (sbusl)
 377                pil = sun4d_encode_irq(board, sbusl, slot);
 378        else
 379                pil = real_irq;
 380
 381        irq = _sun4d_build_device_irq(real_irq, pil, board);
 382err_out:
 383        return irq;
 384}
 385
 386static unsigned int sun4d_build_timer_irq(unsigned int board,
 387                                          unsigned int real_irq)
 388{
 389        return _sun4d_build_device_irq(real_irq, real_irq, board);
 390}
 391
 392
 393static void __init sun4d_fixup_trap_table(void)
 394{
 395#ifdef CONFIG_SMP
 396        unsigned long flags;
 397        struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
 398
 399        /* Adjust so that we jump directly to smp4d_ticker */
 400        lvl14_save[2] += smp4d_ticker - real_irq_entry;
 401
 402        /* For SMP we use the level 14 ticker, however the bootup code
 403         * has copied the firmware's level 14 vector into the boot cpu's
 404         * trap table, we must fix this now or we get squashed.
 405         */
 406        local_irq_save(flags);
 407        patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
 408        trap_table->inst_one = lvl14_save[0];
 409        trap_table->inst_two = lvl14_save[1];
 410        trap_table->inst_three = lvl14_save[2];
 411        trap_table->inst_four = lvl14_save[3];
 412        local_ops->cache_all();
 413        local_irq_restore(flags);
 414#endif
 415}
 416
 417static void __init sun4d_init_timers(void)
 418{
 419        struct device_node *dp;
 420        struct resource res;
 421        unsigned int irq;
 422        const u32 *reg;
 423        int err;
 424        int board;
 425
 426        dp = of_find_node_by_name(NULL, "cpu-unit");
 427        if (!dp) {
 428                prom_printf("sun4d_init_timers: Unable to find cpu-unit\n");
 429                prom_halt();
 430        }
 431
 432        /* Which cpu-unit we use is arbitrary, we can view the bootbus timer
 433         * registers via any cpu's mapping.  The first 'reg' property is the
 434         * bootbus.
 435         */
 436        reg = of_get_property(dp, "reg", NULL);
 437        if (!reg) {
 438                prom_printf("sun4d_init_timers: No reg property\n");
 439                prom_halt();
 440        }
 441
 442        board = of_getintprop_default(dp, "board#", -1);
 443        if (board == -1) {
 444                prom_printf("sun4d_init_timers: No board# property on cpu-unit\n");
 445                prom_halt();
 446        }
 447
 448        of_node_put(dp);
 449
 450        res.start = reg[1];
 451        res.end = reg[2] - 1;
 452        res.flags = reg[0] & 0xff;
 453        sun4d_timers = of_ioremap(&res, BW_TIMER_LIMIT,
 454                                  sizeof(struct sun4d_timer_regs), "user timer");
 455        if (!sun4d_timers) {
 456                prom_printf("sun4d_init_timers: Can't map timer regs\n");
 457                prom_halt();
 458        }
 459
 460#ifdef CONFIG_SMP
 461        sparc_config.cs_period = SBUS_CLOCK_RATE * 2;  /* 2 seconds */
 462#else
 463        sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec  */
 464        sparc_config.features |= FEAT_L10_CLOCKEVENT;
 465#endif
 466        sparc_config.features |= FEAT_L10_CLOCKSOURCE;
 467        sbus_writel(timer_value(sparc_config.cs_period),
 468                    &sun4d_timers->l10_timer_limit);
 469
 470        master_l10_counter = &sun4d_timers->l10_cur_count;
 471
 472        irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ);
 473        err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
 474        if (err) {
 475                prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
 476                             err);
 477                prom_halt();
 478        }
 479        sun4d_load_profile_irqs();
 480        sun4d_fixup_trap_table();
 481}
 482
 483void __init sun4d_init_sbi_irq(void)
 484{
 485        struct device_node *dp;
 486        int target_cpu;
 487
 488        target_cpu = boot_cpu_id;
 489        for_each_node_by_name(dp, "sbi") {
 490                int devid = of_getintprop_default(dp, "device-id", 0);
 491                int board = of_getintprop_default(dp, "board#", 0);
 492                unsigned int mask;
 493
 494                set_sbi_tid(devid, target_cpu << 3);
 495                board_to_cpu[board] = target_cpu;
 496
 497                /* Get rid of pending irqs from PROM */
 498                mask = acquire_sbi(devid, 0xffffffff);
 499                if (mask) {
 500                        printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n",
 501                               mask, board);
 502                        release_sbi(devid, mask);
 503                }
 504        }
 505}
 506
 507void __init sun4d_init_IRQ(void)
 508{
 509        local_irq_disable();
 510
 511        sparc_config.init_timers      = sun4d_init_timers;
 512        sparc_config.build_device_irq = sun4d_build_device_irq;
 513        sparc_config.clock_rate       = SBUS_CLOCK_RATE;
 514        sparc_config.clear_clock_irq  = sun4d_clear_clock_irq;
 515        sparc_config.load_profile_irq = sun4d_load_profile_irq;
 516
 517        /* Cannot enable interrupts until OBP ticker is disabled. */
 518}
 519