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