sparc32: rename sparc_irq_config to sparc_config
[linux-2.6-block.git] / arch / sparc / kernel / sun4d_irq.c
CommitLineData
88278ca2 1/*
e54f8548 2 * SS1000/SC2000 interrupt handling.
1da177e4
LT
3 *
4 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 * Heavily based on arch/sparc/kernel/irq.c.
6 */
7
1da177e4 8#include <linux/kernel_stat.h>
1da177e4 9#include <linux/seq_file.h>
e54f8548 10
1da177e4 11#include <asm/timer.h>
1da177e4
LT
12#include <asm/traps.h>
13#include <asm/irq.h>
14#include <asm/io.h>
1da177e4
LT
15#include <asm/sbi.h>
16#include <asm/cacheflush.h>
5fcafb7a 17#include <asm/setup.h>
1da177e4 18
81265fd9 19#include "kernel.h"
32231a66
AV
20#include "irq.h"
21
e54f8548
SR
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.
6baa9b20 26 * SBUS interrupts are encodes as a combination of board, level and slot.
e54f8548
SR
27 */
28
6baa9b20
SR
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
f5f10857
DM
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
6baa9b20 50#define SUN4D_TIMER_IRQ 10
db1cdd14
SR
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];
1da177e4 56
1da177e4 57static int pil_to_sbus[] = {
e54f8548
SR
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,
1da177e4
LT
74};
75
f8376e93 76/* Exported for sun4d_smp.c */
1da177e4 77DEFINE_SPINLOCK(sun4d_imsk_lock);
1da177e4 78
6baa9b20
SR
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)
1da177e4 96{
6baa9b20
SR
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 */
ea160584 106 for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) {
6baa9b20
SR
107 unsigned int idx, mask;
108
6baa9b20
SR
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 */
6baa9b20 120 slot = (1 << sbil);
ea160584 121 for (idx = 0; mask != 0; idx++, slot <<= 1) {
6baa9b20
SR
122 unsigned int pil;
123 struct irq_bucket *p;
124
6baa9b20
SR
125 if (!(mask & slot))
126 continue;
127
128 mask &= ~slot;
ea160584 129 pil = sun4d_encode_irq(sbino, sbusl, idx);
6baa9b20
SR
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;
1da177e4 138 }
6baa9b20 139 release_sbi(SBI2DEVID(sbino), slot);
1da177e4 140 }
1da177e4 141 }
1da177e4
LT
142}
143
e54f8548 144void sun4d_handler_irq(int pil, struct pt_regs *regs)
1da177e4 145{
0d84438d 146 struct pt_regs *old_regs;
1da177e4 147 /* SBUS IRQ level (1 - 7) */
d4d1ec48 148 int sbusl = pil_to_sbus[pil];
e54f8548 149
1da177e4
LT
150 /* FIXME: Is this necessary?? */
151 cc_get_ipen();
e54f8548 152
d4d1ec48 153 cc_set_iclr(1 << pil);
e54f8548 154
55dd23ec
DH
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
0d84438d 164 old_regs = set_irq_regs(regs);
1da177e4 165 irq_enter();
6baa9b20
SR
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 }
1da177e4 178 } else {
6baa9b20
SR
179 /* SBUS interrupt */
180 sun4d_sbus_handler_irq(sbusl);
1da177e4
LT
181 }
182 irq_exit();
0d84438d 183 set_irq_regs(old_regs);
1da177e4
LT
184}
185
6baa9b20
SR
186
187static void sun4d_mask_irq(struct irq_data *data)
1da177e4 188{
6baa9b20
SR
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;
1da177e4 193 unsigned long flags;
6baa9b20
SR
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
1da177e4
LT
203}
204
6baa9b20 205static void sun4d_unmask_irq(struct irq_data *data)
1da177e4 206{
6baa9b20
SR
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;
1da177e4 211 unsigned long flags;
6baa9b20
SR
212#endif
213 real_irq = handler_data->real_irq;
e54f8548 214
6baa9b20 215#ifdef CONFIG_SMP
1da177e4 216 spin_lock_irqsave(&sun4d_imsk_lock, flags);
ea160584 217 cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) & ~(1 << real_irq));
1da177e4 218 spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
6baa9b20 219#else
ea160584 220 cc_set_imsk(cc_get_imsk() & ~(1 << real_irq));
6baa9b20 221#endif
1da177e4
LT
222}
223
6baa9b20 224static unsigned int sun4d_startup_irq(struct irq_data *data)
1da177e4 225{
6baa9b20
SR
226 irq_link(data->irq);
227 sun4d_unmask_irq(data);
228 return 0;
229}
f8376e93 230
6baa9b20
SR
231static void sun4d_shutdown_irq(struct irq_data *data)
232{
233 sun4d_mask_irq(data);
234 irq_unlink(data->irq);
1da177e4
LT
235}
236
6baa9b20
SR
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
1da177e4
LT
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{
71d37211
DM
262 struct device_node *dp;
263
1da177e4
LT
264 int cpuid = cpu_logical_map(1);
265
266 if (cpuid == -1)
267 cpuid = cpu_logical_map(0);
71d37211
DM
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);
db1cdd14 271 board_to_cpu[board] = cpuid;
71d37211 272 set_sbi_tid(devid, cpuid << 3);
1da177e4 273 }
e54f8548 274 printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid);
1da177e4
LT
275}
276#endif
e54f8548 277
1da177e4
LT
278static void sun4d_clear_clock_irq(void)
279{
f5f10857 280 sbus_readl(&sun4d_timers->l10_timer_limit);
1da177e4
LT
281}
282
1da177e4
LT
283static void sun4d_load_profile_irq(int cpu, unsigned int limit)
284{
285 bw_set_prof_limit(cpu, limit);
286}
287
f5f10857 288static void __init sun4d_load_profile_irqs(void)
1da177e4 289{
f5f10857 290 int cpu = 0, mid;
1da177e4 291
f5f10857
DM
292 while (!cpu_find_by_instance(cpu, NULL, &mid)) {
293 sun4d_load_profile_irq(mid >> 3, 0);
294 cpu++;
295 }
296}
297
5fba1708 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
1d05995b
SR
333unsigned int sun4d_build_device_irq(struct platform_device *op,
334 unsigned int real_irq)
335{
1d05995b 336 struct device_node *dp = op->dev.of_node;
9eeb0898 337 struct device_node *board_parent, *bus = dp->parent;
338 char *bus_connection;
1d05995b 339 const struct linux_prom_registers *regs;
6baa9b20
SR
340 unsigned int pil;
341 unsigned int irq;
1d05995b
SR
342 int board, slot;
343 int sbusl;
344
5fba1708 345 irq = real_irq;
9eeb0898 346 while (bus) {
347 if (!strcmp(bus->name, "sbi")) {
348 bus_connection = "io-unit";
1d05995b 349 break;
9eeb0898 350 }
351
352 if (!strcmp(bus->name, "bootbus")) {
353 bus_connection = "cpu-unit";
354 break;
355 }
1d05995b 356
9eeb0898 357 bus = bus->parent;
1d05995b 358 }
9eeb0898 359 if (!bus)
1d05995b
SR
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 /*
9eeb0898 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.
1d05995b 371 */
9eeb0898 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);
1d05995b
SR
375 goto err_out;
376 }
9eeb0898 377 board_parent = bus->parent;
378 board = of_getintprop_default(board_parent, "board#", -1);
1d05995b 379 if (board == -1) {
9eeb0898 380 printk(KERN_ERR "%s: Error, lacks board# property.\n",
381 board_parent->full_name);
1d05995b
SR
382 goto err_out;
383 }
384
385 sbusl = pil_to_sbus[real_irq];
386 if (sbusl)
6baa9b20
SR
387 pil = sun4d_encode_irq(board, sbusl, slot);
388 else
389 pil = real_irq;
390
5fba1708 391 irq = _sun4d_build_device_irq(real_irq, pil, board);
1d05995b 392err_out:
5fba1708 393 return irq;
1d05995b
SR
394}
395
5fba1708 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
f5f10857
DM
402static void __init sun4d_fixup_trap_table(void)
403{
1da177e4 404#ifdef CONFIG_SMP
f5f10857 405 unsigned long flags;
f5f10857 406 struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
f5f10857
DM
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);
1da177e4 423#endif
f5f10857
DM
424}
425
426static void __init sun4d_init_timers(irq_handler_t counter_fn)
427{
428 struct device_node *dp;
429 struct resource res;
6baa9b20 430 unsigned int irq;
f5f10857
DM
431 const u32 *reg;
432 int err;
5fba1708 433 int board;
f5f10857
DM
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
5fba1708 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
f5f10857
DM
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);
1da177e4 470
1da177e4 471 master_l10_counter = &sun4d_timers->l10_cur_count;
1da177e4 472
5fba1708 473 irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ);
6baa9b20 474 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
f5f10857 475 if (err) {
e54f8548
SR
476 prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
477 err);
1da177e4
LT
478 prom_halt();
479 }
f5f10857
DM
480 sun4d_load_profile_irqs();
481 sun4d_fixup_trap_table();
1da177e4
LT
482}
483
484void __init sun4d_init_sbi_irq(void)
485{
71d37211 486 struct device_node *dp;
5fcafb7a 487 int target_cpu;
f8376e93 488
f8376e93 489 target_cpu = boot_cpu_id;
71d37211
DM
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
f8376e93 495 set_sbi_tid(devid, target_cpu << 3);
db1cdd14 496 board_to_cpu[board] = target_cpu;
f8376e93 497
1da177e4 498 /* Get rid of pending irqs from PROM */
71d37211 499 mask = acquire_sbi(devid, 0xffffffff);
1da177e4 500 if (mask) {
e54f8548
SR
501 printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n",
502 mask, board);
71d37211 503 release_sbi(devid, mask);
1da177e4
LT
504 }
505 }
506}
507
1da177e4
LT
508void __init sun4d_init_IRQ(void)
509{
510 local_irq_disable();
511
1da177e4 512 BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
1da177e4 513 BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
bbdc2661 514
472bc4f2
SR
515 sparc_config.init_timers = sun4d_init_timers;
516 sparc_config.build_device_irq = sun4d_build_device_irq;
bbdc2661 517
1da177e4
LT
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}