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;
192 int cpu = smp_processor_id();
193
194 handler_data = irq_data_get_irq_handler_data(data);
195 if (handler_data->mask) {
196 unsigned long flags;
197
198 local_irq_save(flags);
199 if (handler_data->percpu) {
200 sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->set);
201 } else {
202 sbus_writel(handler_data->mask, &sun4m_irq_global->mask_set);
203 }
204 local_irq_restore(flags);
205 }
206}
207
208static void sun4m_unmask_irq(struct irq_data *data)
209{
210 struct sun4m_handler_data *handler_data;
211 int cpu = smp_processor_id();
212
213 handler_data = irq_data_get_irq_handler_data(data);
214 if (handler_data->mask) {
215 unsigned long flags;
216
217 local_irq_save(flags);
218 if (handler_data->percpu) {
219 sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->clear);
220 } else {
221 sbus_writel(handler_data->mask, &sun4m_irq_global->mask_clear);
222 }
223 local_irq_restore(flags);
224 }
225}
226
227static unsigned int sun4m_startup_irq(struct irq_data *data)
228{
229 irq_link(data->irq);
230 sun4m_unmask_irq(data);
231 return 0;
232}
233
234static void sun4m_shutdown_irq(struct irq_data *data)
235{
236 sun4m_mask_irq(data);
237 irq_unlink(data->irq);
238}
239
240static struct irq_chip sun4m_irq = {
241 .name = "sun4m",
242 .irq_startup = sun4m_startup_irq,
243 .irq_shutdown = sun4m_shutdown_irq,
244 .irq_mask = sun4m_mask_irq,
245 .irq_unmask = sun4m_unmask_irq,
246};
247
248
249static unsigned int sun4m_build_device_irq(struct platform_device *op,
250 unsigned int real_irq)
251{
252 struct sun4m_handler_data *handler_data;
253 unsigned int irq;
254 unsigned int pil;
255
256 if (real_irq >= OBP_INT_LEVEL_VME) {
257 prom_printf("Bogus sun4m IRQ %u\n", real_irq);
258 prom_halt();
259 }
260 pil = (real_irq & 0xf);
261 irq = irq_alloc(real_irq, pil);
262
263 if (irq == 0)
264 goto out;
265
266 handler_data = irq_get_handler_data(irq);
267 if (unlikely(handler_data))
268 goto out;
269
270 handler_data = kzalloc(sizeof(struct sun4m_handler_data), GFP_ATOMIC);
271 if (unlikely(!handler_data)) {
272 prom_printf("IRQ: kzalloc(sun4m_handler_data) failed.\n");
273 prom_halt();
274 }
275
276 handler_data->mask = sun4m_imask[real_irq];
277 handler_data->percpu = real_irq < OBP_INT_LEVEL_ONBOARD;
278 irq_set_chip_and_handler_name(irq, &sun4m_irq,
279 handle_level_irq, "level");
280 irq_set_handler_data(irq, handler_data);
281
282out:
283 return irq;
284}
285
286struct sun4m_timer_percpu {
287 u32 l14_limit;
288 u32 l14_count;
289 u32 l14_limit_noclear;
290 u32 user_timer_start_stop;
291};
292
293static struct sun4m_timer_percpu __iomem *timers_percpu[SUN4M_NCPUS];
294
295struct sun4m_timer_global {
296 u32 l10_limit;
297 u32 l10_count;
298 u32 l10_limit_noclear;
299 u32 reserved;
300 u32 timer_config;
301};
302
303static struct sun4m_timer_global __iomem *timers_global;
304
305static void sun4m_clear_clock_irq(void)
306{
307 sbus_readl(&timers_global->l10_limit);
308}
309
310void sun4m_nmi(struct pt_regs *regs)
311{
312 unsigned long afsr, afar, si;
313
314 printk(KERN_ERR "Aieee: sun4m NMI received!\n");
315
316 __asm__ __volatile__("mov 0x500, %%g1\n\t"
317 "lda [%%g1] 0x4, %0\n\t"
318 "mov 0x600, %%g1\n\t"
319 "lda [%%g1] 0x4, %1\n\t" :
320 "=r" (afsr), "=r" (afar));
321 printk(KERN_ERR "afsr=%08lx afar=%08lx\n", afsr, afar);
322 si = sbus_readl(&sun4m_irq_global->pending);
323 printk(KERN_ERR "si=%08lx\n", si);
324 if (si & SUN4M_INT_MODULE_ERR)
325 printk(KERN_ERR "Module async error\n");
326 if (si & SUN4M_INT_M2S_WRITE_ERR)
327 printk(KERN_ERR "MBus/SBus async error\n");
328 if (si & SUN4M_INT_ECC_ERR)
329 printk(KERN_ERR "ECC memory error\n");
330 if (si & SUN4M_INT_VME_ERR)
331 printk(KERN_ERR "VME async error\n");
332 printk(KERN_ERR "you lose buddy boy...\n");
333 show_regs(regs);
334 prom_halt();
335}
336
337void sun4m_unmask_profile_irq(void)
338{
339 unsigned long flags;
340
341 local_irq_save(flags);
342 sbus_writel(sun4m_imask[SUN4M_PROFILE_IRQ], &sun4m_irq_global->mask_clear);
343 local_irq_restore(flags);
344}
345
346void sun4m_clear_profile_irq(int cpu)
347{
348 sbus_readl(&timers_percpu[cpu]->l14_limit);
349}
350
351static void sun4m_load_profile_irq(int cpu, unsigned int limit)
352{
353 unsigned int value = limit ? timer_value(limit) : 0;
354 sbus_writel(value, &timers_percpu[cpu]->l14_limit);
355}
356
357static void __init sun4m_init_timers(void)
358{
359 struct device_node *dp = of_find_node_by_name(NULL, "counter");
360 int i, err, len, num_cpu_timers;
361 unsigned int irq;
362 const u32 *addr;
363
364 if (!dp) {
365 printk(KERN_ERR "sun4m_init_timers: No 'counter' node.\n");
366 return;
367 }
368
369 addr = of_get_property(dp, "address", &len);
370 of_node_put(dp);
371 if (!addr) {
372 printk(KERN_ERR "sun4m_init_timers: No 'address' prop.\n");
373 return;
374 }
375
376 num_cpu_timers = (len / sizeof(u32)) - 1;
377 for (i = 0; i < num_cpu_timers; i++) {
378 timers_percpu[i] = (void __iomem *)
379 (unsigned long) addr[i];
380 }
381 timers_global = (void __iomem *)
382 (unsigned long) addr[num_cpu_timers];
383
384
385 sbus_writel(0x00000000, &timers_global->timer_config);
386
387#ifdef CONFIG_SMP
388 sparc_config.cs_period = SBUS_CLOCK_RATE * 2;
389 sparc_config.features |= FEAT_L14_ONESHOT;
390#else
391 sparc_config.cs_period = SBUS_CLOCK_RATE / HZ;
392 sparc_config.features |= FEAT_L10_CLOCKEVENT;
393#endif
394 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
395 sbus_writel(timer_value(sparc_config.cs_period),
396 &timers_global->l10_limit);
397
398 master_l10_counter = &timers_global->l10_count;
399
400 irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ);
401
402 err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
403 if (err) {
404 printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
405 err);
406 return;
407 }
408
409 for (i = 0; i < num_cpu_timers; i++)
410 sbus_writel(0, &timers_percpu[i]->l14_limit);
411 if (num_cpu_timers == 4)
412 sbus_writel(SUN4M_INT_E14, &sun4m_irq_global->mask_set);
413
414#ifdef CONFIG_SMP
415 {
416 unsigned long flags;
417 struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
418
419
420
421
422
423 local_irq_save(flags);
424 trap_table->inst_one = lvl14_save[0];
425 trap_table->inst_two = lvl14_save[1];
426 trap_table->inst_three = lvl14_save[2];
427 trap_table->inst_four = lvl14_save[3];
428 local_ops->cache_all();
429 local_irq_restore(flags);
430 }
431#endif
432}
433
434void __init sun4m_init_IRQ(void)
435{
436 struct device_node *dp = of_find_node_by_name(NULL, "interrupt");
437 int len, i, mid, num_cpu_iregs;
438 const u32 *addr;
439
440 if (!dp) {
441 printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n");
442 return;
443 }
444
445 addr = of_get_property(dp, "address", &len);
446 of_node_put(dp);
447 if (!addr) {
448 printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n");
449 return;
450 }
451
452 num_cpu_iregs = (len / sizeof(u32)) - 1;
453 for (i = 0; i < num_cpu_iregs; i++) {
454 sun4m_irq_percpu[i] = (void __iomem *)
455 (unsigned long) addr[i];
456 }
457 sun4m_irq_global = (void __iomem *)
458 (unsigned long) addr[num_cpu_iregs];
459
460 local_irq_disable();
461
462 sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set);
463 for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
464 sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear);
465
466 if (num_cpu_iregs == 4)
467 sbus_writel(0, &sun4m_irq_global->interrupt_target);
468
469 sparc_config.init_timers = sun4m_init_timers;
470 sparc_config.build_device_irq = sun4m_build_device_irq;
471 sparc_config.clock_rate = SBUS_CLOCK_RATE;
472 sparc_config.clear_clock_irq = sun4m_clear_clock_irq;
473 sparc_config.load_profile_irq = sun4m_load_profile_irq;
474
475
476
477}
478