1
2
3
4
5
6
7
8
9
10
11
12#include <linux/errno.h>
13#include <linux/linkage.h>
14#include <linux/kernel_stat.h>
15#include <linux/signal.h>
16#include <linux/sched.h>
17#include <linux/ptrace.h>
18#include <linux/smp.h>
19#include <linux/interrupt.h>
20#include <linux/slab.h>
21#include <linux/init.h>
22#include <linux/ioport.h>
23#include <linux/of.h>
24#include <linux/of_device.h>
25
26#include <asm/ptrace.h>
27#include <asm/processor.h>
28#include <asm/system.h>
29#include <asm/psr.h>
30#include <asm/vaddrs.h>
31#include <asm/timer.h>
32#include <asm/openprom.h>
33#include <asm/oplib.h>
34#include <asm/traps.h>
35#include <asm/pgalloc.h>
36#include <asm/pgtable.h>
37#include <asm/smp.h>
38#include <asm/irq.h>
39#include <asm/io.h>
40#include <asm/cacheflush.h>
41
42#include "irq.h"
43
44struct sun4m_irq_percpu {
45 u32 pending;
46 u32 clear;
47 u32 set;
48};
49
50struct sun4m_irq_global {
51 u32 pending;
52 u32 mask;
53 u32 mask_clear;
54 u32 mask_set;
55 u32 interrupt_target;
56};
57
58
59struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
60struct sun4m_irq_global __iomem *sun4m_irq_global;
61
62
63
64
65#define SUN4M_INT_ENABLE 0x80000000
66#define SUN4M_INT_E14 0x00000080
67#define SUN4M_INT_E10 0x00080000
68
69#define SUN4M_HARD_INT(x) (0x000000001 << (x))
70#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
71
72#define SUN4M_INT_MASKALL 0x80000000
73#define SUN4M_INT_MODULE_ERR 0x40000000
74#define SUN4M_INT_M2S_WRITE_ERR 0x20000000
75#define SUN4M_INT_ECC_ERR 0x10000000
76#define SUN4M_INT_VME_ERR 0x08000000
77#define SUN4M_INT_FLOPPY 0x00400000
78#define SUN4M_INT_MODULE 0x00200000
79#define SUN4M_INT_VIDEO 0x00100000
80#define SUN4M_INT_REALTIME 0x00080000
81#define SUN4M_INT_SCSI 0x00040000
82#define SUN4M_INT_AUDIO 0x00020000
83#define SUN4M_INT_ETHERNET 0x00010000
84#define SUN4M_INT_SERIAL 0x00008000
85#define SUN4M_INT_KBDMS 0x00004000
86#define SUN4M_INT_SBUSBITS 0x00003F80
87#define SUN4M_INT_VMEBITS 0x0000007F
88
89#define SUN4M_INT_ERROR (SUN4M_INT_MODULE_ERR | \
90 SUN4M_INT_M2S_WRITE_ERR | \
91 SUN4M_INT_ECC_ERR | \
92 SUN4M_INT_VME_ERR)
93
94#define SUN4M_INT_SBUS(x) (1 << (x+7))
95#define SUN4M_INT_VME(x) (1 << (x))
96
97
98#define OBP_INT_LEVEL_SOFT 0x10
99#define OBP_INT_LEVEL_ONBOARD 0x20
100#define OBP_INT_LEVEL_SBUS 0x30
101#define OBP_INT_LEVEL_VME 0x40
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156static unsigned long irq_mask[0x50] = {
157
158 0, SUN4M_SOFT_INT(1),
159 SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3),
160 SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5),
161 SUN4M_SOFT_INT(6), SUN4M_SOFT_INT(7),
162 SUN4M_SOFT_INT(8), SUN4M_SOFT_INT(9),
163 SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
164 SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
165 SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
166
167 0, SUN4M_SOFT_INT(1),
168 SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3),
169 SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5),
170 SUN4M_SOFT_INT(6), SUN4M_SOFT_INT(7),
171 SUN4M_SOFT_INT(8), SUN4M_SOFT_INT(9),
172 SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
173 SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
174 SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
175
176 0, 0, 0, 0,
177 SUN4M_INT_SCSI, 0, SUN4M_INT_ETHERNET, 0,
178 SUN4M_INT_VIDEO, SUN4M_INT_MODULE,
179 SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY,
180 (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS),
181 SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR,
182
183 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1),
184 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3),
185 0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5),
186 0, SUN4M_INT_SBUS(6), 0, 0,
187
188 0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1),
189 0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3),
190 0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5),
191 0, SUN4M_INT_VME(6), 0, 0
192};
193
194static unsigned long sun4m_get_irqmask(unsigned int irq)
195{
196 unsigned long mask;
197
198 if (irq < 0x50)
199 mask = irq_mask[irq];
200 else
201 mask = 0;
202
203 if (!mask)
204 printk(KERN_ERR "sun4m_get_irqmask: IRQ%d has no valid mask!\n",
205 irq);
206
207 return mask;
208}
209
210static void sun4m_disable_irq(unsigned int irq_nr)
211{
212 unsigned long mask, flags;
213 int cpu = smp_processor_id();
214
215 mask = sun4m_get_irqmask(irq_nr);
216 local_irq_save(flags);
217 if (irq_nr > 15)
218 sbus_writel(mask, &sun4m_irq_global->mask_set);
219 else
220 sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
221 local_irq_restore(flags);
222}
223
224static void sun4m_enable_irq(unsigned int irq_nr)
225{
226 unsigned long mask, flags;
227 int cpu = smp_processor_id();
228
229
230
231
232
233 if (irq_nr != 0x0b) {
234 mask = sun4m_get_irqmask(irq_nr);
235 local_irq_save(flags);
236 if (irq_nr > 15)
237 sbus_writel(mask, &sun4m_irq_global->mask_clear);
238 else
239 sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
240 local_irq_restore(flags);
241 } else {
242 local_irq_save(flags);
243 sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear);
244 local_irq_restore(flags);
245 }
246}
247
248static unsigned long cpu_pil_to_imask[16] = {
249 0x00000000,
250 0x00000000,
251 SUN4M_INT_SBUS(0) | SUN4M_INT_VME(0),
252 SUN4M_INT_SBUS(1) | SUN4M_INT_VME(1),
253 SUN4M_INT_SCSI,
254 SUN4M_INT_SBUS(2) | SUN4M_INT_VME(2),
255 SUN4M_INT_ETHERNET,
256 SUN4M_INT_SBUS(3) | SUN4M_INT_VME(3),
257 SUN4M_INT_VIDEO,
258 SUN4M_INT_SBUS(4) | SUN4M_INT_VME(4) | SUN4M_INT_MODULE_ERR,
259 SUN4M_INT_REALTIME,
260 SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY,
261 SUN4M_INT_SERIAL | SUN4M_INT_KBDMS,
262 SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO,
263 SUN4M_INT_E14,
264 SUN4M_INT_ERROR
265};
266
267
268
269
270static void sun4m_disable_pil_irq(unsigned int pil)
271{
272 sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_set);
273}
274
275static void sun4m_enable_pil_irq(unsigned int pil)
276{
277 sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_clear);
278}
279
280#ifdef CONFIG_SMP
281static void sun4m_send_ipi(int cpu, int level)
282{
283 unsigned long mask = sun4m_get_irqmask(level);
284 sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
285}
286
287static void sun4m_clear_ipi(int cpu, int level)
288{
289 unsigned long mask = sun4m_get_irqmask(level);
290 sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
291}
292
293static void sun4m_set_udt(int cpu)
294{
295 sbus_writel(cpu, &sun4m_irq_global->interrupt_target);
296}
297#endif
298
299struct sun4m_timer_percpu {
300 u32 l14_limit;
301 u32 l14_count;
302 u32 l14_limit_noclear;
303 u32 user_timer_start_stop;
304};
305
306static struct sun4m_timer_percpu __iomem *timers_percpu[SUN4M_NCPUS];
307
308struct sun4m_timer_global {
309 u32 l10_limit;
310 u32 l10_count;
311 u32 l10_limit_noclear;
312 u32 reserved;
313 u32 timer_config;
314};
315
316static struct sun4m_timer_global __iomem *timers_global;
317
318#define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10)
319
320unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10);
321
322static void sun4m_clear_clock_irq(void)
323{
324 sbus_readl(&timers_global->l10_limit);
325}
326
327void sun4m_nmi(struct pt_regs *regs)
328{
329 unsigned long afsr, afar, si;
330
331 printk(KERN_ERR "Aieee: sun4m NMI received!\n");
332
333 __asm__ __volatile__("mov 0x500, %%g1\n\t"
334 "lda [%%g1] 0x4, %0\n\t"
335 "mov 0x600, %%g1\n\t"
336 "lda [%%g1] 0x4, %1\n\t" :
337 "=r" (afsr), "=r" (afar));
338 printk(KERN_ERR "afsr=%08lx afar=%08lx\n", afsr, afar);
339 si = sbus_readl(&sun4m_irq_global->pending);
340 printk(KERN_ERR "si=%08lx\n", si);
341 if (si & SUN4M_INT_MODULE_ERR)
342 printk(KERN_ERR "Module async error\n");
343 if (si & SUN4M_INT_M2S_WRITE_ERR)
344 printk(KERN_ERR "MBus/SBus async error\n");
345 if (si & SUN4M_INT_ECC_ERR)
346 printk(KERN_ERR "ECC memory error\n");
347 if (si & SUN4M_INT_VME_ERR)
348 printk(KERN_ERR "VME async error\n");
349 printk(KERN_ERR "you lose buddy boy...\n");
350 show_regs(regs);
351 prom_halt();
352}
353
354
355void sun4m_clear_profile_irq(int cpu)
356{
357 sbus_readl(&timers_percpu[cpu]->l14_limit);
358}
359
360static void sun4m_load_profile_irq(int cpu, unsigned int limit)
361{
362 sbus_writel(limit, &timers_percpu[cpu]->l14_limit);
363}
364
365static void __init sun4m_init_timers(irq_handler_t counter_fn)
366{
367 struct device_node *dp = of_find_node_by_name(NULL, "counter");
368 int i, err, len, num_cpu_timers;
369 const u32 *addr;
370
371 if (!dp) {
372 printk(KERN_ERR "sun4m_init_timers: No 'counter' node.\n");
373 return;
374 }
375
376 addr = of_get_property(dp, "address", &len);
377 of_node_put(dp);
378 if (!addr) {
379 printk(KERN_ERR "sun4m_init_timers: No 'address' prop.\n");
380 return;
381 }
382
383 num_cpu_timers = (len / sizeof(u32)) - 1;
384 for (i = 0; i < num_cpu_timers; i++) {
385 timers_percpu[i] = (void __iomem *)
386 (unsigned long) addr[i];
387 }
388 timers_global = (void __iomem *)
389 (unsigned long) addr[num_cpu_timers];
390
391 sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit);
392
393 master_l10_counter = &timers_global->l10_count;
394
395 err = request_irq(TIMER_IRQ, counter_fn,
396 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
397 if (err) {
398 printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
399 err);
400 return;
401 }
402
403 for (i = 0; i < num_cpu_timers; i++)
404 sbus_writel(0, &timers_percpu[i]->l14_limit);
405 if (num_cpu_timers == 4)
406 sbus_writel(SUN4M_INT_E14, &sun4m_irq_global->mask_set);
407
408#ifdef CONFIG_SMP
409 {
410 unsigned long flags;
411 extern unsigned long lvl14_save[4];
412 struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
413
414
415
416
417
418 local_irq_save(flags);
419 trap_table->inst_one = lvl14_save[0];
420 trap_table->inst_two = lvl14_save[1];
421 trap_table->inst_three = lvl14_save[2];
422 trap_table->inst_four = lvl14_save[3];
423 local_flush_cache_all();
424 local_irq_restore(flags);
425 }
426#endif
427}
428
429void __init sun4m_init_IRQ(void)
430{
431 struct device_node *dp = of_find_node_by_name(NULL, "interrupt");
432 int len, i, mid, num_cpu_iregs;
433 const u32 *addr;
434
435 if (!dp) {
436 printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n");
437 return;
438 }
439
440 addr = of_get_property(dp, "address", &len);
441 of_node_put(dp);
442 if (!addr) {
443 printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n");
444 return;
445 }
446
447 num_cpu_iregs = (len / sizeof(u32)) - 1;
448 for (i = 0; i < num_cpu_iregs; i++) {
449 sun4m_irq_percpu[i] = (void __iomem *)
450 (unsigned long) addr[i];
451 }
452 sun4m_irq_global = (void __iomem *)
453 (unsigned long) addr[num_cpu_iregs];
454
455 local_irq_disable();
456
457 sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set);
458 for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
459 sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear);
460
461 if (num_cpu_iregs == 4)
462 sbus_writel(0, &sun4m_irq_global->interrupt_target);
463
464 BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM);
465 BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM);
466 BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM);
467 BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM);
468 BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
469 BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
470 sparc_init_timers = sun4m_init_timers;
471#ifdef CONFIG_SMP
472 BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
473 BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
474 BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM);
475#endif
476
477
478}
479