blob: a9ea60eb2c10f21e01cf007143e47942b6a768ad [file] [log] [blame]
Adrian Bunk88278ca2008-05-19 16:53:02 -07001/*
Sam Ravnborge54f8542011-01-28 22:08:21 +00002 * SS1000/SC2000 interrupt handling.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 * Heavily based on arch/sparc/kernel/irq.c.
6 */
7
Linus Torvalds1da177e2005-04-16 15:20:36 -07008#include <linux/kernel_stat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/seq_file.h>
10
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <asm/timer.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <asm/traps.h>
13#include <asm/irq.h>
14#include <asm/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <asm/sbi.h>
16#include <asm/cacheflush.h>
Daniel Hellstrom5fcafb72011-04-21 04:20:23 +000017#include <asm/setup.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Sam Ravnborg81265fd2008-12-08 01:08:24 -080019#include "kernel.h"
Al Viro32231a62007-07-21 19:18:57 -070020#include "irq.h"
21
Sam Ravnborge54f8542011-01-28 22:08:21 +000022/* 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.
Sam Ravnborg6baa9b22011-04-18 11:25:44 +000026 * SBUS interrupts are encodes as a combination of board, level and slot.
Sam Ravnborge54f8542011-01-28 22:08:21 +000027 */
28
Sam Ravnborg6baa9b22011-04-18 11:25:44 +000029struct 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
David S. Millerf5f10852008-09-13 22:04:55 -070040struct 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
Sam Ravnborg6baa9b22011-04-18 11:25:44 +000050#define SUN4D_TIMER_IRQ 10
Sam Ravnborgdb1cdd12011-04-18 11:25:42 +000051
52/* Specify which cpu handle interrupts from which board.
53 * Index is board - value is cpu.
54 */
55static unsigned char board_to_cpu[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
Linus Torvalds1da177e2005-04-16 15:20:36 -070057static int pil_to_sbus[] = {
Sam Ravnborge54f8542011-01-28 22:08:21 +000058 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,
Linus Torvalds1da177e2005-04-16 15:20:36 -070074};
75
David S. Millerf8376e92008-09-13 22:05:25 -070076/* Exported for sun4d_smp.c */
Linus Torvalds1da177e2005-04-16 15:20:36 -070077DEFINE_SPINLOCK(sun4d_imsk_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Sam Ravnborg6baa9b22011-04-18 11:25:44 +000079/* 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)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096{
Sam Ravnborg6baa9b22011-04-18 11:25:44 +000097 unsigned int bus_mask;
98 unsigned int sbino, slot;
99 unsigned int sbil;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000101 bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff;
102 bw_clear_intr_mask(sbusl, bus_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000104 sbil = (sbusl << 2);
105 /* Loop for each pending SBI */
106 for (sbino = 0; bus_mask; sbino++) {
107 unsigned int idx, mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000109 bus_mask >>= 1;
110 if (!(bus_mask & 1))
111 continue;
112 /* XXX This seems to ACK the irq twice. acquire_sbi()
113 * XXX uses swap, therefore this writes 0xf << sbil,
114 * XXX then later release_sbi() will write the individual
115 * XXX bits which were set again.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 */
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000117 mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil);
118 mask &= (0xf << sbil);
119
120 /* Loop for each pending SBI slot */
121 idx = 0;
122 slot = (1 << sbil);
123 while (mask != 0) {
124 unsigned int pil;
125 struct irq_bucket *p;
126
127 idx++;
128 slot <<= 1;
129 if (!(mask & slot))
130 continue;
131
132 mask &= ~slot;
133 pil = sun4d_encode_irq(sbino, sbil, idx);
134
135 p = irq_map[pil];
136 while (p) {
137 struct irq_bucket *next;
138
139 next = p->next;
140 generic_handle_irq(p->irq);
141 p = next;
142 }
143 release_sbi(SBI2DEVID(sbino), slot);
144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146}
147
Sam Ravnborge54f8542011-01-28 22:08:21 +0000148void sun4d_handler_irq(int pil, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149{
Al Viro0d844382006-10-08 14:30:44 +0100150 struct pt_regs *old_regs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 /* SBUS IRQ level (1 - 7) */
Sam Ravnborgd4d1ec42011-01-22 11:32:15 +0000152 int sbusl = pil_to_sbus[pil];
Sam Ravnborge54f8542011-01-28 22:08:21 +0000153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 /* FIXME: Is this necessary?? */
155 cc_get_ipen();
Sam Ravnborge54f8542011-01-28 22:08:21 +0000156
Sam Ravnborgd4d1ec42011-01-22 11:32:15 +0000157 cc_set_iclr(1 << pil);
Sam Ravnborge54f8542011-01-28 22:08:21 +0000158
Daniel Hellstrom55dd23e2011-05-02 00:08:54 +0000159#ifdef CONFIG_SMP
160 /*
161 * Check IPI data structures after IRQ has been cleared. Hard and Soft
162 * IRQ can happen at the same time, so both cases are always handled.
163 */
164 if (pil == SUN4D_IPI_IRQ)
165 sun4d_ipi_interrupt();
166#endif
167
Al Viro0d844382006-10-08 14:30:44 +0100168 old_regs = set_irq_regs(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 irq_enter();
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000170 if (sbusl == 0) {
171 /* cpu interrupt */
172 struct irq_bucket *p;
173
174 p = irq_map[pil];
175 while (p) {
176 struct irq_bucket *next;
177
178 next = p->next;
179 generic_handle_irq(p->irq);
180 p = next;
181 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 } else {
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000183 /* SBUS interrupt */
184 sun4d_sbus_handler_irq(sbusl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 }
186 irq_exit();
Al Viro0d844382006-10-08 14:30:44 +0100187 set_irq_regs(old_regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188}
189
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000190
191static void sun4d_mask_irq(struct irq_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192{
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000193 struct sun4d_handler_data *handler_data = data->handler_data;
194 unsigned int real_irq;
195#ifdef CONFIG_SMP
196 int cpuid = handler_data->cpuid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 unsigned long flags;
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000198#endif
199 real_irq = handler_data->real_irq;
200#ifdef CONFIG_SMP
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 spin_lock_irqsave(&sun4d_imsk_lock, flags);
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000202 cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | (1 << real_irq));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000204#else
205 cc_set_imsk(cc_get_imsk() | (1 << real_irq));
206#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207}
208
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000209static void sun4d_unmask_irq(struct irq_data *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210{
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000211 struct sun4d_handler_data *handler_data = data->handler_data;
212 unsigned int real_irq;
213#ifdef CONFIG_SMP
214 int cpuid = handler_data->cpuid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 unsigned long flags;
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000216#endif
217 real_irq = handler_data->real_irq;
Sam Ravnborge54f8542011-01-28 22:08:21 +0000218
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000219#ifdef CONFIG_SMP
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 spin_lock_irqsave(&sun4d_imsk_lock, flags);
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000221 cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | ~(1 << real_irq));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000223#else
224 cc_set_imsk(cc_get_imsk() | ~(1 << real_irq));
225#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226}
227
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000228static unsigned int sun4d_startup_irq(struct irq_data *data)
229{
230 irq_link(data->irq);
231 sun4d_unmask_irq(data);
232 return 0;
233}
234
235static void sun4d_shutdown_irq(struct irq_data *data)
236{
237 sun4d_mask_irq(data);
238 irq_unlink(data->irq);
239}
240
241struct irq_chip sun4d_irq = {
242 .name = "sun4d",
243 .irq_startup = sun4d_startup_irq,
244 .irq_shutdown = sun4d_shutdown_irq,
245 .irq_unmask = sun4d_unmask_irq,
246 .irq_mask = sun4d_mask_irq,
247};
248
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249#ifdef CONFIG_SMP
250static void sun4d_set_cpu_int(int cpu, int level)
251{
252 sun4d_send_ipi(cpu, level);
253}
254
255static void sun4d_clear_ipi(int cpu, int level)
256{
257}
258
259static void sun4d_set_udt(int cpu)
260{
261}
262
263/* Setup IRQ distribution scheme. */
264void __init sun4d_distribute_irqs(void)
265{
David S. Miller71d37212008-08-27 02:50:57 -0700266 struct device_node *dp;
267
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 int cpuid = cpu_logical_map(1);
269
270 if (cpuid == -1)
271 cpuid = cpu_logical_map(0);
David S. Miller71d37212008-08-27 02:50:57 -0700272 for_each_node_by_name(dp, "sbi") {
273 int devid = of_getintprop_default(dp, "device-id", 0);
274 int board = of_getintprop_default(dp, "board#", 0);
Sam Ravnborgdb1cdd12011-04-18 11:25:42 +0000275 board_to_cpu[board] = cpuid;
David S. Miller71d37212008-08-27 02:50:57 -0700276 set_sbi_tid(devid, cpuid << 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 }
Sam Ravnborge54f8542011-01-28 22:08:21 +0000278 printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279}
280#endif
Sam Ravnborge54f8542011-01-28 22:08:21 +0000281
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282static void sun4d_clear_clock_irq(void)
283{
David S. Millerf5f10852008-09-13 22:04:55 -0700284 sbus_readl(&sun4d_timers->l10_timer_limit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285}
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287static void sun4d_load_profile_irq(int cpu, unsigned int limit)
288{
289 bw_set_prof_limit(cpu, limit);
290}
291
David S. Millerf5f10852008-09-13 22:04:55 -0700292static void __init sun4d_load_profile_irqs(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293{
David S. Millerf5f10852008-09-13 22:04:55 -0700294 int cpu = 0, mid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 while (!cpu_find_by_instance(cpu, NULL, &mid)) {
297 sun4d_load_profile_irq(mid >> 3, 0);
298 cpu++;
299 }
David S. Millerf5f10852008-09-13 22:04:55 -0700300}
301
Sam Ravnborg1d059952011-02-25 23:01:19 -0800302unsigned int sun4d_build_device_irq(struct platform_device *op,
303 unsigned int real_irq)
304{
Sam Ravnborg1d059952011-02-25 23:01:19 -0800305 struct device_node *dp = op->dev.of_node;
306 struct device_node *io_unit, *sbi = dp->parent;
307 const struct linux_prom_registers *regs;
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000308 struct sun4d_handler_data *handler_data;
309 unsigned int pil;
310 unsigned int irq;
Sam Ravnborg1d059952011-02-25 23:01:19 -0800311 int board, slot;
312 int sbusl;
313
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000314 irq = 0;
Sam Ravnborg1d059952011-02-25 23:01:19 -0800315 while (sbi) {
316 if (!strcmp(sbi->name, "sbi"))
317 break;
318
319 sbi = sbi->parent;
320 }
321 if (!sbi)
322 goto err_out;
323
324 regs = of_get_property(dp, "reg", NULL);
325 if (!regs)
326 goto err_out;
327
328 slot = regs->which_io;
329
330 /*
331 * If SBI's parent is not io-unit or the io-unit lacks
332 * a "board#" property, something is very wrong.
333 */
334 if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
335 printk("%s: Error, parent is not io-unit.\n", sbi->full_name);
336 goto err_out;
337 }
338 io_unit = sbi->parent;
339 board = of_getintprop_default(io_unit, "board#", -1);
340 if (board == -1) {
341 printk("%s: Error, lacks board# property.\n", io_unit->full_name);
342 goto err_out;
343 }
344
345 sbusl = pil_to_sbus[real_irq];
346 if (sbusl)
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000347 pil = sun4d_encode_irq(board, sbusl, slot);
348 else
349 pil = real_irq;
350
351 irq = irq_alloc(real_irq, pil);
352 if (irq == 0)
353 goto err_out;
354
355 handler_data = irq_get_handler_data(irq);
356 if (unlikely(handler_data))
357 goto err_out;
358
359 handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC);
360 if (unlikely(!handler_data)) {
361 prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n");
362 prom_halt();
363 }
364 handler_data->cpuid = board_to_cpu[board];
365 handler_data->real_irq = real_irq;
366 irq_set_chip_and_handler_name(irq, &sun4d_irq,
367 handle_level_irq, "level");
368 irq_set_handler_data(irq, handler_data);
Sam Ravnborg1d059952011-02-25 23:01:19 -0800369
370err_out:
371 return real_irq;
372}
373
David S. Millerf5f10852008-09-13 22:04:55 -0700374static void __init sun4d_fixup_trap_table(void)
375{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376#ifdef CONFIG_SMP
David S. Millerf5f10852008-09-13 22:04:55 -0700377 unsigned long flags;
David S. Millerf5f10852008-09-13 22:04:55 -0700378 struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
David S. Millerf5f10852008-09-13 22:04:55 -0700380 /* Adjust so that we jump directly to smp4d_ticker */
381 lvl14_save[2] += smp4d_ticker - real_irq_entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
David S. Millerf5f10852008-09-13 22:04:55 -0700383 /* For SMP we use the level 14 ticker, however the bootup code
384 * has copied the firmware's level 14 vector into the boot cpu's
385 * trap table, we must fix this now or we get squashed.
386 */
387 local_irq_save(flags);
388 patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
389 trap_table->inst_one = lvl14_save[0];
390 trap_table->inst_two = lvl14_save[1];
391 trap_table->inst_three = lvl14_save[2];
392 trap_table->inst_four = lvl14_save[3];
393 local_flush_cache_all();
394 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395#endif
396}
397
David S. Millerf5f10852008-09-13 22:04:55 -0700398static void __init sun4d_init_timers(irq_handler_t counter_fn)
399{
400 struct device_node *dp;
401 struct resource res;
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000402 unsigned int irq;
David S. Millerf5f10852008-09-13 22:04:55 -0700403 const u32 *reg;
404 int err;
405
406 dp = of_find_node_by_name(NULL, "cpu-unit");
407 if (!dp) {
408 prom_printf("sun4d_init_timers: Unable to find cpu-unit\n");
409 prom_halt();
410 }
411
412 /* Which cpu-unit we use is arbitrary, we can view the bootbus timer
413 * registers via any cpu's mapping. The first 'reg' property is the
414 * bootbus.
415 */
416 reg = of_get_property(dp, "reg", NULL);
Nicolas Palixc2e27c32008-12-03 21:10:57 -0800417 of_node_put(dp);
David S. Millerf5f10852008-09-13 22:04:55 -0700418 if (!reg) {
419 prom_printf("sun4d_init_timers: No reg property\n");
420 prom_halt();
421 }
422
423 res.start = reg[1];
424 res.end = reg[2] - 1;
425 res.flags = reg[0] & 0xff;
426 sun4d_timers = of_ioremap(&res, BW_TIMER_LIMIT,
427 sizeof(struct sun4d_timer_regs), "user timer");
428 if (!sun4d_timers) {
429 prom_printf("sun4d_init_timers: Can't map timer regs\n");
430 prom_halt();
431 }
432
433 sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit);
434
435 master_l10_counter = &sun4d_timers->l10_cur_count;
David S. Millerf5f10852008-09-13 22:04:55 -0700436
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000437 irq = sun4d_build_device_irq(NULL, SUN4D_TIMER_IRQ);
438 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
David S. Millerf5f10852008-09-13 22:04:55 -0700439 if (err) {
Sam Ravnborge54f8542011-01-28 22:08:21 +0000440 prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
441 err);
David S. Millerf5f10852008-09-13 22:04:55 -0700442 prom_halt();
443 }
444 sun4d_load_profile_irqs();
445 sun4d_fixup_trap_table();
446}
447
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448void __init sun4d_init_sbi_irq(void)
449{
David S. Miller71d37212008-08-27 02:50:57 -0700450 struct device_node *dp;
Daniel Hellstrom5fcafb72011-04-21 04:20:23 +0000451 int target_cpu;
David S. Millerf8376e92008-09-13 22:05:25 -0700452
David S. Millerf8376e92008-09-13 22:05:25 -0700453 target_cpu = boot_cpu_id;
David S. Miller71d37212008-08-27 02:50:57 -0700454 for_each_node_by_name(dp, "sbi") {
455 int devid = of_getintprop_default(dp, "device-id", 0);
456 int board = of_getintprop_default(dp, "board#", 0);
457 unsigned int mask;
458
David S. Millerf8376e92008-09-13 22:05:25 -0700459 set_sbi_tid(devid, target_cpu << 3);
Sam Ravnborgdb1cdd12011-04-18 11:25:42 +0000460 board_to_cpu[board] = target_cpu;
David S. Millerf8376e92008-09-13 22:05:25 -0700461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 /* Get rid of pending irqs from PROM */
David S. Miller71d37212008-08-27 02:50:57 -0700463 mask = acquire_sbi(devid, 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 if (mask) {
Sam Ravnborge54f8542011-01-28 22:08:21 +0000465 printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n",
466 mask, board);
David S. Miller71d37212008-08-27 02:50:57 -0700467 release_sbi(devid, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 }
469 }
470}
471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472void __init sun4d_init_IRQ(void)
473{
474 local_irq_disable();
475
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
Sam Ravnborgbbdc2662011-02-25 23:00:19 -0800478
Sam Ravnborg6baa9b22011-04-18 11:25:44 +0000479 sparc_irq_config.init_timers = sun4d_init_timers;
Sam Ravnborg1d059952011-02-25 23:01:19 -0800480 sparc_irq_config.build_device_irq = sun4d_build_device_irq;
Sam Ravnborgbbdc2662011-02-25 23:00:19 -0800481
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482#ifdef CONFIG_SMP
483 BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
484 BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP);
485 BTFIXUPSET_CALL(set_irq_udt, sun4d_set_udt, BTFIXUPCALL_NOP);
486#endif
487 /* Cannot enable interrupts until OBP ticker is disabled. */
488}