Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[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>
0d01ff25 9#include <linux/slab.h>
1da177e4 10#include <linux/seq_file.h>
e54f8548 11
1da177e4 12#include <asm/timer.h>
1da177e4
LT
13#include <asm/traps.h>
14#include <asm/irq.h>
15#include <asm/io.h>
1da177e4
LT
16#include <asm/sbi.h>
17#include <asm/cacheflush.h>
5fcafb7a 18#include <asm/setup.h>
5d83d666 19#include <asm/oplib.h>
1da177e4 20
81265fd9 21#include "kernel.h"
32231a66
AV
22#include "irq.h"
23
e54f8548
SR
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.
6baa9b20 28 * SBUS interrupts are encodes as a combination of board, level and slot.
e54f8548
SR
29 */
30
6baa9b20
SR
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
f5f10857
DM
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
6baa9b20 52#define SUN4D_TIMER_IRQ 10
db1cdd14
SR
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];
1da177e4 58
1da177e4 59static int pil_to_sbus[] = {
e54f8548
SR
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,
1da177e4
LT
76};
77
f8376e93 78/* Exported for sun4d_smp.c */
1da177e4 79DEFINE_SPINLOCK(sun4d_imsk_lock);
1da177e4 80
6baa9b20
SR
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)
1da177e4 98{
6baa9b20
SR
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 */
ea160584 108 for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) {
6baa9b20
SR
109 unsigned int idx, mask;
110
6baa9b20
SR
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 */
6baa9b20 122 slot = (1 << sbil);
ea160584 123 for (idx = 0; mask != 0; idx++, slot <<= 1) {
6baa9b20
SR
124 unsigned int pil;
125 struct irq_bucket *p;
126
6baa9b20
SR
127 if (!(mask & slot))
128 continue;
129
130 mask &= ~slot;
ea160584 131 pil = sun4d_encode_irq(sbino, sbusl, idx);
6baa9b20
SR
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;
1da177e4 140 }
6baa9b20 141 release_sbi(SBI2DEVID(sbino), slot);
1da177e4 142 }
1da177e4 143 }
1da177e4
LT
144}
145
5ac75688 146void sun4d_handler_irq(unsigned int pil, struct pt_regs *regs)
1da177e4 147{
0d84438d 148 struct pt_regs *old_regs;
1da177e4 149 /* SBUS IRQ level (1 - 7) */
d4d1ec48 150 int sbusl = pil_to_sbus[pil];
e54f8548 151
1da177e4
LT
152 /* FIXME: Is this necessary?? */
153 cc_get_ipen();
e54f8548 154
d4d1ec48 155 cc_set_iclr(1 << pil);
e54f8548 156
55dd23ec
DH
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
0d84438d 166 old_regs = set_irq_regs(regs);
1da177e4 167 irq_enter();
6baa9b20
SR
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 }
1da177e4 180 } else {
6baa9b20
SR
181 /* SBUS interrupt */
182 sun4d_sbus_handler_irq(sbusl);
1da177e4
LT
183 }
184 irq_exit();
0d84438d 185 set_irq_regs(old_regs);
1da177e4
LT
186}
187
6baa9b20
SR
188
189static void sun4d_mask_irq(struct irq_data *data)
1da177e4 190{
6baa9b20
SR
191 struct sun4d_handler_data *handler_data = data->handler_data;
192 unsigned int real_irq;
193#ifdef CONFIG_SMP
194 int cpuid = handler_data->cpuid;
1da177e4 195 unsigned long flags;
6baa9b20
SR
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
1da177e4
LT
205}
206
6baa9b20 207static void sun4d_unmask_irq(struct irq_data *data)
1da177e4 208{
6baa9b20
SR
209 struct sun4d_handler_data *handler_data = data->handler_data;
210 unsigned int real_irq;
211#ifdef CONFIG_SMP
212 int cpuid = handler_data->cpuid;
1da177e4 213 unsigned long flags;
6baa9b20
SR
214#endif
215 real_irq = handler_data->real_irq;
e54f8548 216
6baa9b20 217#ifdef CONFIG_SMP
1da177e4 218 spin_lock_irqsave(&sun4d_imsk_lock, flags);
ea160584 219 cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) & ~(1 << real_irq));
1da177e4 220 spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
6baa9b20 221#else
ea160584 222 cc_set_imsk(cc_get_imsk() & ~(1 << real_irq));
6baa9b20 223#endif
1da177e4
LT
224}
225
6baa9b20 226static unsigned int sun4d_startup_irq(struct irq_data *data)
1da177e4 227{
6baa9b20
SR
228 irq_link(data->irq);
229 sun4d_unmask_irq(data);
230 return 0;
231}
f8376e93 232
6baa9b20
SR
233static void sun4d_shutdown_irq(struct irq_data *data)
234{
235 sun4d_mask_irq(data);
236 irq_unlink(data->irq);
1da177e4
LT
237}
238
5ac75688 239static struct irq_chip sun4d_irq = {
6baa9b20
SR
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
1da177e4 247#ifdef CONFIG_SMP
1da177e4
LT
248/* Setup IRQ distribution scheme. */
249void __init sun4d_distribute_irqs(void)
250{
71d37211
DM
251 struct device_node *dp;
252
1da177e4
LT
253 int cpuid = cpu_logical_map(1);
254
255 if (cpuid == -1)
256 cpuid = cpu_logical_map(0);
71d37211
DM
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);
db1cdd14 260 board_to_cpu[board] = cpuid;
71d37211 261 set_sbi_tid(devid, cpuid << 3);
1da177e4 262 }
e54f8548 263 printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid);
1da177e4
LT
264}
265#endif
e54f8548 266
1da177e4
LT
267static void sun4d_clear_clock_irq(void)
268{
f5f10857 269 sbus_readl(&sun4d_timers->l10_timer_limit);
1da177e4
LT
270}
271
1da177e4
LT
272static void sun4d_load_profile_irq(int cpu, unsigned int limit)
273{
62f08283
TK
274 unsigned int value = limit ? timer_value(limit) : 0;
275 bw_set_prof_limit(cpu, value);
1da177e4
LT
276}
277
f5f10857 278static void __init sun4d_load_profile_irqs(void)
1da177e4 279{
f5f10857 280 int cpu = 0, mid;
1da177e4 281
f5f10857
DM
282 while (!cpu_find_by_instance(cpu, NULL, &mid)) {
283 sun4d_load_profile_irq(mid >> 3, 0);
284 cpu++;
285 }
286}
287
5ac75688
SR
288static unsigned int _sun4d_build_device_irq(unsigned int real_irq,
289 unsigned int pil,
290 unsigned int board)
5fba1708 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
5ac75688
SR
323static unsigned int sun4d_build_device_irq(struct platform_device *op,
324 unsigned int real_irq)
1d05995b 325{
1d05995b 326 struct device_node *dp = op->dev.of_node;
9eeb0898 327 struct device_node *board_parent, *bus = dp->parent;
328 char *bus_connection;
1d05995b 329 const struct linux_prom_registers *regs;
6baa9b20
SR
330 unsigned int pil;
331 unsigned int irq;
1d05995b
SR
332 int board, slot;
333 int sbusl;
334
5fba1708 335 irq = real_irq;
9eeb0898 336 while (bus) {
337 if (!strcmp(bus->name, "sbi")) {
338 bus_connection = "io-unit";
1d05995b 339 break;
9eeb0898 340 }
341
342 if (!strcmp(bus->name, "bootbus")) {
343 bus_connection = "cpu-unit";
344 break;
345 }
1d05995b 346
9eeb0898 347 bus = bus->parent;
1d05995b 348 }
9eeb0898 349 if (!bus)
1d05995b
SR
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 /*
9eeb0898 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.
1d05995b 361 */
9eeb0898 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);
1d05995b
SR
365 goto err_out;
366 }
9eeb0898 367 board_parent = bus->parent;
368 board = of_getintprop_default(board_parent, "board#", -1);
1d05995b 369 if (board == -1) {
9eeb0898 370 printk(KERN_ERR "%s: Error, lacks board# property.\n",
371 board_parent->full_name);
1d05995b
SR
372 goto err_out;
373 }
374
375 sbusl = pil_to_sbus[real_irq];
376 if (sbusl)
6baa9b20
SR
377 pil = sun4d_encode_irq(board, sbusl, slot);
378 else
379 pil = real_irq;
380
5fba1708 381 irq = _sun4d_build_device_irq(real_irq, pil, board);
1d05995b 382err_out:
5fba1708 383 return irq;
1d05995b
SR
384}
385
5ac75688
SR
386static unsigned int sun4d_build_timer_irq(unsigned int board,
387 unsigned int real_irq)
5fba1708 388{
389 return _sun4d_build_device_irq(real_irq, real_irq, board);
390}
391
392
f5f10857
DM
393static void __init sun4d_fixup_trap_table(void)
394{
1da177e4 395#ifdef CONFIG_SMP
f5f10857 396 unsigned long flags;
f5f10857 397 struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
f5f10857
DM
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];
5d83d666 412 local_ops->cache_all();
f5f10857 413 local_irq_restore(flags);
1da177e4 414#endif
f5f10857
DM
415}
416
62f08283 417static void __init sun4d_init_timers(void)
f5f10857
DM
418{
419 struct device_node *dp;
420 struct resource res;
6baa9b20 421 unsigned int irq;
f5f10857
DM
422 const u32 *reg;
423 int err;
5fba1708 424 int board;
f5f10857
DM
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
5fba1708 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
f5f10857
DM
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
62f08283
TK
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);
1da177e4 469
1da177e4 470 master_l10_counter = &sun4d_timers->l10_cur_count;
1da177e4 471
5fba1708 472 irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ);
62f08283 473 err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
f5f10857 474 if (err) {
e54f8548
SR
475 prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
476 err);
1da177e4
LT
477 prom_halt();
478 }
f5f10857
DM
479 sun4d_load_profile_irqs();
480 sun4d_fixup_trap_table();
1da177e4
LT
481}
482
483void __init sun4d_init_sbi_irq(void)
484{
71d37211 485 struct device_node *dp;
5fcafb7a 486 int target_cpu;
f8376e93 487
f8376e93 488 target_cpu = boot_cpu_id;
71d37211
DM
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
f8376e93 494 set_sbi_tid(devid, target_cpu << 3);
db1cdd14 495 board_to_cpu[board] = target_cpu;
f8376e93 496
1da177e4 497 /* Get rid of pending irqs from PROM */
71d37211 498 mask = acquire_sbi(devid, 0xffffffff);
1da177e4 499 if (mask) {
e54f8548
SR
500 printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n",
501 mask, board);
71d37211 502 release_sbi(devid, mask);
1da177e4
LT
503 }
504 }
505}
506
1da177e4
LT
507void __init sun4d_init_IRQ(void)
508{
509 local_irq_disable();
510
472bc4f2
SR
511 sparc_config.init_timers = sun4d_init_timers;
512 sparc_config.build_device_irq = sun4d_build_device_irq;
62f08283 513 sparc_config.clock_rate = SBUS_CLOCK_RATE;
08c9388f
SR
514 sparc_config.clear_clock_irq = sun4d_clear_clock_irq;
515 sparc_config.load_profile_irq = sun4d_load_profile_irq;
bbdc2661 516
1da177e4
LT
517 /* Cannot enable interrupts until OBP ticker is disabled. */
518}