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