• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * sun4m irq support
3   *
4   *  djhr: Hacked out of irq.c into a CPU dependent version.
5   *
6   *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
7   *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
8   *  Copyright (C) 1995 Pete A. Zaitcev (zaitcev@yahoo.com)
9   *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
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  /* Sample sun4m IRQ layout:
24   *
25   * 0x22 - Power
26   * 0x24 - ESP SCSI
27   * 0x26 - Lance ethernet
28   * 0x2b - Floppy
29   * 0x2c - Zilog uart
30   * 0x32 - SBUS level 0
31   * 0x33 - Parallel port, SBUS level 1
32   * 0x35 - SBUS level 2
33   * 0x37 - SBUS level 3
34   * 0x39 - Audio, Graphics card, SBUS level 4
35   * 0x3b - SBUS level 5
36   * 0x3d - SBUS level 6
37   *
38   * Each interrupt source has a mask bit in the interrupt registers.
39   * When the mask bit is set, this blocks interrupt deliver.  So you
40   * clear the bit to enable the interrupt.
41   *
42   * Interrupts numbered less than 0x10 are software triggered interrupts
43   * and unused by Linux.
44   *
45   * Interrupt level assignment on sun4m:
46   *
47   *	level		source
48   * ------------------------------------------------------------
49   *	  1		softint-1
50   *	  2		softint-2, VME/SBUS level 1
51   *	  3		softint-3, VME/SBUS level 2
52   *	  4		softint-4, onboard SCSI
53   *	  5		softint-5, VME/SBUS level 3
54   *	  6		softint-6, onboard ETHERNET
55   *	  7		softint-7, VME/SBUS level 4
56   *	  8		softint-8, onboard VIDEO
57   *	  9		softint-9, VME/SBUS level 5, Module Interrupt
58   *	 10		softint-10, system counter/timer
59   *	 11		softint-11, VME/SBUS level 6, Floppy
60   *	 12		softint-12, Keyboard/Mouse, Serial
61   *	 13		softint-13, VME/SBUS level 7, ISDN Audio
62   *	 14		softint-14, per-processor counter/timer
63   *	 15		softint-15, Asynchronous Errors (broadcast)
64   *
65   * Each interrupt source is masked distinctly in the sun4m interrupt
66   * registers.  The PIL level alone is therefore ambiguous, since multiple
67   * interrupt sources map to a single PIL.
68   *
69   * This ambiguity is resolved in the 'intr' property for device nodes
70   * in the OF device tree.  Each 'intr' property entry is composed of
71   * two 32-bit words.  The first word is the IRQ priority value, which
72   * is what we're intersted in.  The second word is the IRQ vector, which
73   * is unused.
74   *
75   * The low 4 bits of the IRQ priority indicate the PIL, and the upper
76   * 4 bits indicate onboard vs. SBUS leveled vs. VME leveled.  0x20
77   * means onboard, 0x30 means SBUS leveled, and 0x40 means VME leveled.
78   *
79   * For example, an 'intr' IRQ priority value of 0x24 is onboard SCSI
80   * whereas a value of 0x33 is SBUS level 2.  Here are some sample
81   * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and
82   * Tadpole S3 GX systems.
83   *
84   * esp:		0x24	onboard ESP SCSI
85   * le:		0x26	onboard Lance ETHERNET
86   * p9100:	0x32	SBUS level 1 P9100 video
87   * bpp:		0x33	SBUS level 2 BPP parallel port device
88   * DBRI:	0x39	SBUS level 5 DBRI ISDN audio
89   * SUNW,leo:	0x39	SBUS level 5 LEO video
90   * pcmcia:	0x3b	SBUS level 6 PCMCIA controller
91   * uctrl:	0x3b	SBUS level 6 UCTRL device
92   * modem:	0x3d	SBUS level 7 MODEM
93   * zs:		0x2c	onboard keyboard/mouse/serial
94   * floppy:	0x2b	onboard Floppy
95   * power:	0x22	onboard power device (XXX unknown mask bit XXX)
96   */
97  
98  
99  /* Code in entry.S needs to get at these register mappings.  */
100  struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
101  struct sun4m_irq_global __iomem *sun4m_irq_global;
102  
103  struct sun4m_handler_data {
104  	bool    percpu;
105  	long    mask;
106  };
107  
108  /* Dave Redman (djhr@tadpole.co.uk)
109   * The sun4m interrupt registers.
110   */
111  #define SUN4M_INT_ENABLE	0x80000000
112  #define SUN4M_INT_E14		0x00000080
113  #define SUN4M_INT_E10		0x00080000
114  
115  #define SUN4M_HARD_INT(x)	(0x000000001 << (x))
116  #define SUN4M_SOFT_INT(x)	(0x000010000 << (x))
117  
118  #define	SUN4M_INT_MASKALL	0x80000000	  /* mask all interrupts */
119  #define	SUN4M_INT_MODULE_ERR	0x40000000	  /* module error */
120  #define	SUN4M_INT_M2S_WRITE_ERR	0x20000000	  /* write buffer error */
121  #define	SUN4M_INT_ECC_ERR	0x10000000	  /* ecc memory error */
122  #define	SUN4M_INT_VME_ERR	0x08000000	  /* vme async error */
123  #define	SUN4M_INT_FLOPPY	0x00400000	  /* floppy disk */
124  #define	SUN4M_INT_MODULE	0x00200000	  /* module interrupt */
125  #define	SUN4M_INT_VIDEO		0x00100000	  /* onboard video */
126  #define	SUN4M_INT_REALTIME	0x00080000	  /* system timer */
127  #define	SUN4M_INT_SCSI		0x00040000	  /* onboard scsi */
128  #define	SUN4M_INT_AUDIO		0x00020000	  /* audio/isdn */
129  #define	SUN4M_INT_ETHERNET	0x00010000	  /* onboard ethernet */
130  #define	SUN4M_INT_SERIAL	0x00008000	  /* serial ports */
131  #define	SUN4M_INT_KBDMS		0x00004000	  /* keyboard/mouse */
132  #define	SUN4M_INT_SBUSBITS	0x00003F80	  /* sbus int bits */
133  #define	SUN4M_INT_VMEBITS	0x0000007F	  /* vme int bits */
134  
135  #define	SUN4M_INT_ERROR		(SUN4M_INT_MODULE_ERR |    \
136  				 SUN4M_INT_M2S_WRITE_ERR | \
137  				 SUN4M_INT_ECC_ERR |       \
138  				 SUN4M_INT_VME_ERR)
139  
140  #define SUN4M_INT_SBUS(x)	(1 << (x+7))
141  #define SUN4M_INT_VME(x)	(1 << (x))
142  
143  /* Interrupt levels used by OBP */
144  #define	OBP_INT_LEVEL_SOFT	0x10
145  #define	OBP_INT_LEVEL_ONBOARD	0x20
146  #define	OBP_INT_LEVEL_SBUS	0x30
147  #define	OBP_INT_LEVEL_VME	0x40
148  
149  #define SUN4M_TIMER_IRQ         (OBP_INT_LEVEL_ONBOARD | 10)
150  #define SUN4M_PROFILE_IRQ       (OBP_INT_LEVEL_ONBOARD | 14)
151  
152  static unsigned long sun4m_imask[0x50] = {
153  	/* 0x00 - SMP */
154  	0,  SUN4M_SOFT_INT(1),
155  	SUN4M_SOFT_INT(2),  SUN4M_SOFT_INT(3),
156  	SUN4M_SOFT_INT(4),  SUN4M_SOFT_INT(5),
157  	SUN4M_SOFT_INT(6),  SUN4M_SOFT_INT(7),
158  	SUN4M_SOFT_INT(8),  SUN4M_SOFT_INT(9),
159  	SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
160  	SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
161  	SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
162  	/* 0x10 - soft */
163  	0,  SUN4M_SOFT_INT(1),
164  	SUN4M_SOFT_INT(2),  SUN4M_SOFT_INT(3),
165  	SUN4M_SOFT_INT(4),  SUN4M_SOFT_INT(5),
166  	SUN4M_SOFT_INT(6),  SUN4M_SOFT_INT(7),
167  	SUN4M_SOFT_INT(8),  SUN4M_SOFT_INT(9),
168  	SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
169  	SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
170  	SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
171  	/* 0x20 - onboard */
172  	0, 0, 0, 0,
173  	SUN4M_INT_SCSI,  0, SUN4M_INT_ETHERNET, 0,
174  	SUN4M_INT_VIDEO, SUN4M_INT_MODULE,
175  	SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY,
176  	(SUN4M_INT_SERIAL | SUN4M_INT_KBDMS),
177  	SUN4M_INT_AUDIO, SUN4M_INT_E14, SUN4M_INT_MODULE_ERR,
178  	/* 0x30 - sbus */
179  	0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1),
180  	0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3),
181  	0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5),
182  	0, SUN4M_INT_SBUS(6), 0, 0,
183  	/* 0x40 - vme */
184  	0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1),
185  	0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3),
186  	0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5),
187  	0, SUN4M_INT_VME(6), 0, 0
188  };
189  
sun4m_mask_irq(struct irq_data * data)190  static void sun4m_mask_irq(struct irq_data *data)
191  {
192  	struct sun4m_handler_data *handler_data = data->handler_data;
193  	int cpu = smp_processor_id();
194  
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  
sun4m_unmask_irq(struct irq_data * data)208  static void sun4m_unmask_irq(struct irq_data *data)
209  {
210  	struct sun4m_handler_data *handler_data = data->handler_data;
211  	int cpu = smp_processor_id();
212  
213  	if (handler_data->mask) {
214  		unsigned long flags;
215  
216  		local_irq_save(flags);
217  		if (handler_data->percpu) {
218  			sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->clear);
219  		} else {
220  			sbus_writel(handler_data->mask, &sun4m_irq_global->mask_clear);
221  		}
222  		local_irq_restore(flags);
223  	}
224  }
225  
sun4m_startup_irq(struct irq_data * data)226  static unsigned int sun4m_startup_irq(struct irq_data *data)
227  {
228  	irq_link(data->irq);
229  	sun4m_unmask_irq(data);
230  	return 0;
231  }
232  
sun4m_shutdown_irq(struct irq_data * data)233  static void sun4m_shutdown_irq(struct irq_data *data)
234  {
235  	sun4m_mask_irq(data);
236  	irq_unlink(data->irq);
237  }
238  
239  static struct irq_chip sun4m_irq = {
240  	.name		= "sun4m",
241  	.irq_startup	= sun4m_startup_irq,
242  	.irq_shutdown	= sun4m_shutdown_irq,
243  	.irq_mask	= sun4m_mask_irq,
244  	.irq_unmask	= sun4m_unmask_irq,
245  };
246  
247  
sun4m_build_device_irq(struct platform_device * op,unsigned int real_irq)248  static unsigned int sun4m_build_device_irq(struct platform_device *op,
249  					   unsigned int real_irq)
250  {
251  	struct sun4m_handler_data *handler_data;
252  	unsigned int irq;
253  	unsigned int pil;
254  
255  	if (real_irq >= OBP_INT_LEVEL_VME) {
256  		prom_printf("Bogus sun4m IRQ %u\n", real_irq);
257  		prom_halt();
258  	}
259  	pil = (real_irq & 0xf);
260  	irq = irq_alloc(real_irq, pil);
261  
262  	if (irq == 0)
263  		goto out;
264  
265  	handler_data = irq_get_handler_data(irq);
266  	if (unlikely(handler_data))
267  		goto out;
268  
269  	handler_data = kzalloc(sizeof(struct sun4m_handler_data), GFP_ATOMIC);
270  	if (unlikely(!handler_data)) {
271  		prom_printf("IRQ: kzalloc(sun4m_handler_data) failed.\n");
272  		prom_halt();
273  	}
274  
275  	handler_data->mask = sun4m_imask[real_irq];
276  	handler_data->percpu = real_irq < OBP_INT_LEVEL_ONBOARD;
277  	irq_set_chip_and_handler_name(irq, &sun4m_irq,
278  	                              handle_level_irq, "level");
279  	irq_set_handler_data(irq, handler_data);
280  
281  out:
282  	return irq;
283  }
284  
285  #ifdef CONFIG_SMP
sun4m_send_ipi(int cpu,int level)286  static void sun4m_send_ipi(int cpu, int level)
287  {
288  	sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
289  }
290  
sun4m_clear_ipi(int cpu,int level)291  static void sun4m_clear_ipi(int cpu, int level)
292  {
293  	sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->clear);
294  }
295  
sun4m_set_udt(int cpu)296  static void sun4m_set_udt(int cpu)
297  {
298  	sbus_writel(cpu, &sun4m_irq_global->interrupt_target);
299  }
300  #endif
301  
302  struct sun4m_timer_percpu {
303  	u32		l14_limit;
304  	u32		l14_count;
305  	u32		l14_limit_noclear;
306  	u32		user_timer_start_stop;
307  };
308  
309  static struct sun4m_timer_percpu __iomem *timers_percpu[SUN4M_NCPUS];
310  
311  struct sun4m_timer_global {
312  	u32		l10_limit;
313  	u32		l10_count;
314  	u32		l10_limit_noclear;
315  	u32		reserved;
316  	u32		timer_config;
317  };
318  
319  static struct sun4m_timer_global __iomem *timers_global;
320  
321  
322  unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10);
323  
sun4m_clear_clock_irq(void)324  static void sun4m_clear_clock_irq(void)
325  {
326  	sbus_readl(&timers_global->l10_limit);
327  }
328  
sun4m_nmi(struct pt_regs * regs)329  void sun4m_nmi(struct pt_regs *regs)
330  {
331  	unsigned long afsr, afar, si;
332  
333  	printk(KERN_ERR "Aieee: sun4m NMI received!\n");
334  	/* XXX HyperSparc hack XXX */
335  	__asm__ __volatile__("mov 0x500, %%g1\n\t"
336  			     "lda [%%g1] 0x4, %0\n\t"
337  			     "mov 0x600, %%g1\n\t"
338  			     "lda [%%g1] 0x4, %1\n\t" :
339  			     "=r" (afsr), "=r" (afar));
340  	printk(KERN_ERR "afsr=%08lx afar=%08lx\n", afsr, afar);
341  	si = sbus_readl(&sun4m_irq_global->pending);
342  	printk(KERN_ERR "si=%08lx\n", si);
343  	if (si & SUN4M_INT_MODULE_ERR)
344  		printk(KERN_ERR "Module async error\n");
345  	if (si & SUN4M_INT_M2S_WRITE_ERR)
346  		printk(KERN_ERR "MBus/SBus async error\n");
347  	if (si & SUN4M_INT_ECC_ERR)
348  		printk(KERN_ERR "ECC memory error\n");
349  	if (si & SUN4M_INT_VME_ERR)
350  		printk(KERN_ERR "VME async error\n");
351  	printk(KERN_ERR "you lose buddy boy...\n");
352  	show_regs(regs);
353  	prom_halt();
354  }
355  
sun4m_unmask_profile_irq(void)356  void sun4m_unmask_profile_irq(void)
357  {
358  	unsigned long flags;
359  
360  	local_irq_save(flags);
361  	sbus_writel(sun4m_imask[SUN4M_PROFILE_IRQ], &sun4m_irq_global->mask_clear);
362  	local_irq_restore(flags);
363  }
364  
sun4m_clear_profile_irq(int cpu)365  void sun4m_clear_profile_irq(int cpu)
366  {
367  	sbus_readl(&timers_percpu[cpu]->l14_limit);
368  }
369  
sun4m_load_profile_irq(int cpu,unsigned int limit)370  static void sun4m_load_profile_irq(int cpu, unsigned int limit)
371  {
372  	sbus_writel(limit, &timers_percpu[cpu]->l14_limit);
373  }
374  
sun4m_init_timers(irq_handler_t counter_fn)375  static void __init sun4m_init_timers(irq_handler_t counter_fn)
376  {
377  	struct device_node *dp = of_find_node_by_name(NULL, "counter");
378  	int i, err, len, num_cpu_timers;
379  	unsigned int irq;
380  	const u32 *addr;
381  
382  	if (!dp) {
383  		printk(KERN_ERR "sun4m_init_timers: No 'counter' node.\n");
384  		return;
385  	}
386  
387  	addr = of_get_property(dp, "address", &len);
388  	of_node_put(dp);
389  	if (!addr) {
390  		printk(KERN_ERR "sun4m_init_timers: No 'address' prop.\n");
391  		return;
392  	}
393  
394  	num_cpu_timers = (len / sizeof(u32)) - 1;
395  	for (i = 0; i < num_cpu_timers; i++) {
396  		timers_percpu[i] = (void __iomem *)
397  			(unsigned long) addr[i];
398  	}
399  	timers_global = (void __iomem *)
400  		(unsigned long) addr[num_cpu_timers];
401  
402  	/* Every per-cpu timer works in timer mode */
403  	sbus_writel(0x00000000, &timers_global->timer_config);
404  
405  	sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit);
406  
407  	master_l10_counter = &timers_global->l10_count;
408  
409  	irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ);
410  
411  	err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
412  	if (err) {
413  		printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
414  			err);
415  		return;
416  	}
417  
418  	for (i = 0; i < num_cpu_timers; i++)
419  		sbus_writel(0, &timers_percpu[i]->l14_limit);
420  	if (num_cpu_timers == 4)
421  		sbus_writel(SUN4M_INT_E14, &sun4m_irq_global->mask_set);
422  
423  #ifdef CONFIG_SMP
424  	{
425  		unsigned long flags;
426  		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
427  
428  		/* For SMP we use the level 14 ticker, however the bootup code
429  		 * has copied the firmware's level 14 vector into the boot cpu's
430  		 * trap table, we must fix this now or we get squashed.
431  		 */
432  		local_irq_save(flags);
433  		trap_table->inst_one = lvl14_save[0];
434  		trap_table->inst_two = lvl14_save[1];
435  		trap_table->inst_three = lvl14_save[2];
436  		trap_table->inst_four = lvl14_save[3];
437  		local_flush_cache_all();
438  		local_irq_restore(flags);
439  	}
440  #endif
441  }
442  
sun4m_init_IRQ(void)443  void __init sun4m_init_IRQ(void)
444  {
445  	struct device_node *dp = of_find_node_by_name(NULL, "interrupt");
446  	int len, i, mid, num_cpu_iregs;
447  	const u32 *addr;
448  
449  	if (!dp) {
450  		printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n");
451  		return;
452  	}
453  
454  	addr = of_get_property(dp, "address", &len);
455  	of_node_put(dp);
456  	if (!addr) {
457  		printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n");
458  		return;
459  	}
460  
461  	num_cpu_iregs = (len / sizeof(u32)) - 1;
462  	for (i = 0; i < num_cpu_iregs; i++) {
463  		sun4m_irq_percpu[i] = (void __iomem *)
464  			(unsigned long) addr[i];
465  	}
466  	sun4m_irq_global = (void __iomem *)
467  		(unsigned long) addr[num_cpu_iregs];
468  
469  	local_irq_disable();
470  
471  	sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set);
472  	for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
473  		sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear);
474  
475  	if (num_cpu_iregs == 4)
476  		sbus_writel(0, &sun4m_irq_global->interrupt_target);
477  
478  	BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
479  	BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
480  
481  	sparc_irq_config.init_timers = sun4m_init_timers;
482  	sparc_irq_config.build_device_irq = sun4m_build_device_irq;
483  
484  #ifdef CONFIG_SMP
485  	BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
486  	BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
487  	BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM);
488  #endif
489  
490  	/* Cannot enable interrupts until OBP ticker is disabled. */
491  }
492