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