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