File: /usr/src/linux/arch/sparc/kernel/sun4d_irq.c

1     /*  $Id: sun4d_irq.c,v 1.28 2001/07/17 16:17:33 anton Exp $
2      *  arch/sparc/kernel/sun4d_irq.c:
3      *			SS1000/SC2000 interrupt handling.
4      *
5      *  Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6      *  Heavily based on arch/sparc/kernel/irq.c.
7      */
8     
9     #include <linux/config.h>
10     #include <linux/ptrace.h>
11     #include <linux/errno.h>
12     #include <linux/linkage.h>
13     #include <linux/kernel_stat.h>
14     #include <linux/signal.h>
15     #include <linux/sched.h>
16     #include <linux/interrupt.h>
17     #include <linux/slab.h>
18     #include <linux/random.h>
19     #include <linux/init.h>
20     #include <linux/smp.h>
21     #include <linux/smp_lock.h>
22     #include <linux/spinlock.h>
23     
24     #include <asm/ptrace.h>
25     #include <asm/processor.h>
26     #include <asm/system.h>
27     #include <asm/psr.h>
28     #include <asm/smp.h>
29     #include <asm/vaddrs.h>
30     #include <asm/timer.h>
31     #include <asm/openprom.h>
32     #include <asm/oplib.h>
33     #include <asm/traps.h>
34     #include <asm/irq.h>
35     #include <asm/io.h>
36     #include <asm/pgalloc.h>
37     #include <asm/pgtable.h>
38     #include <asm/sbus.h>
39     #include <asm/sbi.h>
40     
41     /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */
42     /* #define DISTRIBUTE_IRQS */
43     
44     struct sun4d_timer_regs *sun4d_timers;
45     #define TIMER_IRQ	10
46     
47     #define MAX_STATIC_ALLOC	4
48     extern struct irqaction static_irqaction[MAX_STATIC_ALLOC];
49     extern int static_irq_count;
50     unsigned char cpu_leds[32];
51     #ifdef CONFIG_SMP
52     unsigned char sbus_tid[32];
53     #endif
54     
55     extern struct irqaction *irq_action[];
56     
57     struct sbus_action {
58     	struct irqaction *action;
59     	/* For SMP this needs to be extended */
60     } *sbus_actions;
61     
62     static int pil_to_sbus[] = {
63     	0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
64     };
65     
66     static int sbus_to_pil[] = {
67     	0, 2, 3, 5, 7, 9, 11, 13,
68     };
69     
70     static int nsbi;
71     #ifdef CONFIG_SMP
72     spinlock_t sun4d_imsk_lock = SPIN_LOCK_UNLOCKED;
73     #endif
74     
75     int sun4d_get_irq_list(char *buf)
76     {
77     	int i, j = 0, k = 0, len = 0, sbusl;
78     	struct irqaction * action;
79     #ifdef CONFIG_SMP
80     	int x;
81     #endif
82     
83     	for (i = 0 ; i < NR_IRQS ; i++) {
84     		sbusl = pil_to_sbus[i];
85     		if (!sbusl) {
86     	 		action = *(i + irq_action);
87     			if (!action) 
88     		        	continue;
89     		} else {
90     			for (j = 0; j < nsbi; j++) {
91     				for (k = 0; k < 4; k++)
92     					if ((action = sbus_actions [(j << 5) + (sbusl << 2) + k].action))
93     						goto found_it;
94     			}
95     			continue;
96     		}
97     found_it:	len += sprintf(buf+len, "%3d: ", i);
98     #ifndef CONFIG_SMP
99     		len += sprintf(buf+len, "%10u ", kstat_irqs(i));
100     #else
101     		for (x = 0; x < smp_num_cpus; x++)
102     			len += sprintf(buf+len, "%10u ",
103     				       kstat.irqs[cpu_logical_map(x)][i]);
104     #endif
105     		len += sprintf(buf+len, "%c %s",
106     			(action->flags & SA_INTERRUPT) ? '+' : ' ',
107     			action->name);
108     		action = action->next;
109     		for (;;) {
110     			for (; action; action = action->next) {
111     				len += sprintf(buf+len, ",%s %s",
112     					(action->flags & SA_INTERRUPT) ? " +" : "",
113     					action->name);
114     			}
115     			if (!sbusl) break;
116     			k++;
117     			if (k < 4)
118     				action = sbus_actions [(j << 5) + (sbusl << 2) + k].action;
119     			else {
120     				j++;
121     				if (j == nsbi) break;
122     				k = 0;
123     				action = sbus_actions [(j << 5) + (sbusl << 2)].action;
124     			}
125     		}
126     		len += sprintf(buf+len, "\n");
127     	}
128     	return len;
129     }
130     
131     void sun4d_free_irq(unsigned int irq, void *dev_id)
132     {
133     	struct irqaction *action, **actionp;
134     	struct irqaction *tmp = NULL;
135             unsigned long flags;
136     	
137     	if (irq < 15)
138     		actionp = irq + irq_action;
139     	else
140     		actionp = &(sbus_actions[irq - (1 << 5)].action);
141     	action = *actionp;
142     	if (!action) {
143     		printk("Trying to free free IRQ%d\n",irq);
144     		return;
145     	}
146     	if (dev_id) {
147     		for (; action; action = action->next) {
148     			if (action->dev_id == dev_id)
149     				break;
150     			tmp = action;
151     		}
152     		if (!action) {
153     			printk("Trying to free free shared IRQ%d\n",irq);
154     			return;
155     		}
156     	} else if (action->flags & SA_SHIRQ) {
157     		printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
158     		return;
159     	}
160     	if (action->flags & SA_STATIC_ALLOC)
161     	{
162     	    /* This interrupt is marked as specially allocated
163     	     * so it is a bad idea to free it.
164     	     */
165     	    printk("Attempt to free statically allocated IRQ%d (%s)\n",
166     		   irq, action->name);
167     	    return;
168     	}
169     	
170             save_and_cli(flags);
171     	if (action && tmp)
172     		tmp->next = action->next;
173     	else
174     		*actionp = action->next;
175     
176     	kfree(action);
177     
178     	if (!(*actionp))
179     		disable_irq(irq);
180     
181     	restore_flags(flags);
182     }
183     
184     extern void unexpected_irq(int, void *, struct pt_regs *);
185     
186     void sun4d_handler_irq(int irq, struct pt_regs * regs)
187     {
188     	struct irqaction * action;
189     	int cpu = smp_processor_id();
190     	/* SBUS IRQ level (1 - 7) */
191     	int sbusl = pil_to_sbus[irq];
192     	
193     	/* FIXME: Is this necessary?? */
194     	cc_get_ipen();
195     	
196     	cc_set_iclr(1 << irq);
197     	
198     	irq_enter(cpu, irq);
199     	kstat.irqs[cpu][irq]++;
200     	if (!sbusl) {
201     		action = *(irq + irq_action);
202     		if (!action)
203     			unexpected_irq(irq, 0, regs);
204     		do {
205     			action->handler(irq, action->dev_id, regs);
206     			action = action->next;
207     		} while (action);
208     	} else {
209     		int bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff;
210     		int sbino;
211     		struct sbus_action *actionp;
212     		unsigned mask, slot;
213     		int sbil = (sbusl << 2);
214     		
215     		bw_clear_intr_mask(sbusl, bus_mask);
216     		
217     		/* Loop for each pending SBI */
218     		for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1)
219     			if (bus_mask & 1) {
220     				mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil);
221     				mask &= (0xf << sbil);
222     				actionp = sbus_actions + (sbino << 5) + (sbil);
223     				/* Loop for each pending SBI slot */
224     				for (slot = (1 << sbil); mask; slot <<= 1, actionp++)
225     					if (mask & slot) {
226     						mask &= ~slot;
227     						action = actionp->action;
228     						
229     						if (!action)
230     							unexpected_irq(irq, 0, regs);
231     						do {
232     							action->handler(irq, action->dev_id, regs);
233     							action = action->next;
234     						} while (action);
235     						release_sbi(SBI2DEVID(sbino), slot);
236     					}
237     			}
238     	}
239     	irq_exit(cpu, irq);
240     	if (softirq_pending(cpu))
241     		do_softirq();
242     }
243     
244     unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq)
245     {
246     	int sbusl = pil_to_sbus[irq];
247     
248     	if (sbusl)
249     		return ((sdev->bus->board + 1) << 5) + (sbusl << 2) + sdev->slot;
250     	else
251     		return irq;
252     }
253     
254     int sun4d_request_irq(unsigned int irq,
255     		void (*handler)(int, void *, struct pt_regs *),
256     		unsigned long irqflags, const char * devname, void *dev_id)
257     {
258     	struct irqaction *action, *tmp = NULL, **actionp;
259     	unsigned long flags;
260     	
261     	if(irq > 14 && irq < (1 << 5))
262     		return -EINVAL;
263     
264     	if (!handler)
265     	    return -EINVAL;
266     
267     	if (irq >= (1 << 5))
268     		actionp = &(sbus_actions[irq - (1 << 5)].action);
269     	else
270     		actionp = irq + irq_action;
271     	action = *actionp;
272     	
273     	if (action) {
274     		if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
275     			for (tmp = action; tmp->next; tmp = tmp->next);
276     		} else {
277     			return -EBUSY;
278     		}
279     		if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
280     			printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
281     			return -EBUSY;
282     		}   
283     		action = NULL;		/* Or else! */
284     	}
285     
286     	save_and_cli(flags);
287     
288     	/* If this is flagged as statically allocated then we use our
289     	 * private struct which is never freed.
290     	 */
291     	if (irqflags & SA_STATIC_ALLOC) {
292     	    if (static_irq_count < MAX_STATIC_ALLOC)
293     		action = &static_irqaction[static_irq_count++];
294     	    else
295     		printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",irq, devname);
296     	}
297     	
298     	if (action == NULL)
299     	    action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
300     						 GFP_KERNEL);
301     	
302     	if (!action) { 
303     		restore_flags(flags);
304     		return -ENOMEM;
305     	}
306     
307     	action->handler = handler;
308     	action->flags = irqflags;
309     	action->mask = 0;
310     	action->name = devname;
311     	action->next = NULL;
312     	action->dev_id = dev_id;
313     
314     	if (tmp)
315     		tmp->next = action;
316     	else
317     		*actionp = action;
318     		
319     	enable_irq(irq);
320     	restore_flags(flags);
321     	return 0;
322     }
323     
324     static void sun4d_disable_irq(unsigned int irq)
325     {
326     #ifdef CONFIG_SMP
327     	int tid = sbus_tid[(irq >> 5) - 1];
328     	unsigned long flags;
329     #endif	
330     	
331     	if (irq < NR_IRQS) return;
332     #ifdef CONFIG_SMP
333     	spin_lock_irqsave(&sun4d_imsk_lock, flags);
334     	cc_set_imsk_other(tid, cc_get_imsk_other(tid) | (1 << sbus_to_pil[(irq >> 2) & 7]));
335     	spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
336     #else		
337     	cc_set_imsk(cc_get_imsk() | (1 << sbus_to_pil[(irq >> 2) & 7]));
338     #endif
339     }
340     
341     static void sun4d_enable_irq(unsigned int irq)
342     {
343     #ifdef CONFIG_SMP
344     	int tid = sbus_tid[(irq >> 5) - 1];
345     	unsigned long flags;
346     #endif	
347     	
348     	if (irq < NR_IRQS) return;
349     #ifdef CONFIG_SMP
350     	spin_lock_irqsave(&sun4d_imsk_lock, flags);
351     	cc_set_imsk_other(tid, cc_get_imsk_other(tid) & ~(1 << sbus_to_pil[(irq >> 2) & 7]));
352     	spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
353     #else		
354     	cc_set_imsk(cc_get_imsk() & ~(1 << sbus_to_pil[(irq >> 2) & 7]));
355     #endif
356     }
357     
358     #ifdef CONFIG_SMP
359     static void sun4d_set_cpu_int(int cpu, int level)
360     {
361     	sun4d_send_ipi(cpu, level);
362     }
363     
364     static void sun4d_clear_ipi(int cpu, int level)
365     {
366     }
367     
368     static void sun4d_set_udt(int cpu)
369     {
370     }
371     
372     /* Setup IRQ distribution scheme. */
373     void __init sun4d_distribute_irqs(void)
374     {
375     #ifdef DISTRIBUTE_IRQS
376     	struct sbus_bus *sbus;
377     	unsigned long sbus_serving_map;
378     
379     	sbus_serving_map = cpu_present_map;
380     	for_each_sbus(sbus) {
381     		if ((sbus->board * 2) == boot_cpu_id && (cpu_present_map & (1 << (sbus->board * 2 + 1))))
382     			sbus_tid[sbus->board] = (sbus->board * 2 + 1);
383     		else if (cpu_present_map & (1 << (sbus->board * 2)))
384     			sbus_tid[sbus->board] = (sbus->board * 2);
385     		else if (cpu_present_map & (1 << (sbus->board * 2 + 1)))
386     			sbus_tid[sbus->board] = (sbus->board * 2 + 1);
387     		else
388     			sbus_tid[sbus->board] = 0xff;
389     		if (sbus_tid[sbus->board] != 0xff)
390     			sbus_serving_map &= ~(1 << sbus_tid[sbus->board]);
391     	}
392     	for_each_sbus(sbus)
393     		if (sbus_tid[sbus->board] == 0xff) {
394     			int i = 31;
395     				
396     			if (!sbus_serving_map)
397     				sbus_serving_map = cpu_present_map;
398     			while (!(sbus_serving_map & (1 << i)))
399     				i--;
400     			sbus_tid[sbus->board] = i;
401     			sbus_serving_map &= ~(1 << i);
402     		}
403     	for_each_sbus(sbus) {
404     		printk("sbus%d IRQs directed to CPU%d\n", sbus->board, sbus_tid[sbus->board]);
405     		set_sbi_tid(sbus->devid, sbus_tid[sbus->board] << 3);
406     	}
407     #else
408     	struct sbus_bus *sbus;
409     	int cpuid = cpu_logical_map(1);
410     
411     	if (cpuid == -1)
412     		cpuid = cpu_logical_map(0);
413     	for_each_sbus(sbus) {
414     		sbus_tid[sbus->board] = cpuid;
415     		set_sbi_tid(sbus->devid, cpuid << 3);
416     	}
417     	printk("All sbus IRQs directed to CPU%d\n", cpuid);
418     #endif
419     }
420     #endif
421      
422     static void sun4d_clear_clock_irq(void)
423     {
424     	volatile unsigned int clear_intr;
425     	clear_intr = sun4d_timers->l10_timer_limit;
426     }
427     
428     static void sun4d_clear_profile_irq(int cpu)
429     {
430     	bw_get_prof_limit(cpu);
431     }
432     
433     static void sun4d_load_profile_irq(int cpu, unsigned int limit)
434     {
435     	bw_set_prof_limit(cpu, limit);
436     }
437     
438     static void __init sun4d_init_timers(void (*counter_fn)(int, void *, struct pt_regs *))
439     {
440     	int irq;
441     	extern struct prom_cpuinfo linux_cpus[NR_CPUS];
442     	int cpu;
443     	struct resource r;
444     
445     	/* Map the User Timer registers. */
446     	memset(&r, 0, sizeof(r));
447     #ifdef CONFIG_SMP
448     	r.start = CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT;
449     #else
450     	r.start = CSR_BASE(0)+BW_TIMER_LIMIT;
451     #endif
452     	r.flags = 0xf;
453     	sun4d_timers = (struct sun4d_timer_regs *) sbus_ioremap(&r, 0,
454     	    PAGE_SIZE, "user timer");
455     
456     	sun4d_timers->l10_timer_limit =  (((1000000/HZ) + 1) << 10);
457     	master_l10_counter = &sun4d_timers->l10_cur_count;
458     	master_l10_limit = &sun4d_timers->l10_timer_limit;
459     
460     	irq = request_irq(TIMER_IRQ,
461     			  counter_fn,
462     			  (SA_INTERRUPT | SA_STATIC_ALLOC),
463     			  "timer", NULL);
464     	if (irq) {
465     		prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ);
466     		prom_halt();
467     	}
468     	
469     	/* Enable user timer free run for CPU 0 in BW */
470     	/* bw_set_ctrl(0, bw_get_ctrl(0) | BW_CTRL_USER_TIMER); */
471         
472     	for(cpu = 0; cpu < linux_num_cpus; cpu++)
473     		sun4d_load_profile_irq((linux_cpus[cpu].mid >> 3), 0);
474     		
475     #ifdef CONFIG_SMP
476     	{
477     		unsigned long flags;
478     		extern unsigned long lvl14_save[4];
479     		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
480     		extern unsigned int real_irq_entry[], smp4d_ticker[];
481     		extern unsigned int patchme_maybe_smp_msg[];
482     
483     		/* Adjust so that we jump directly to smp4d_ticker */
484     		lvl14_save[2] += smp4d_ticker - real_irq_entry;
485     
486     		/* For SMP we use the level 14 ticker, however the bootup code
487     		 * has copied the firmwares level 14 vector into boot cpu's
488     		 * trap table, we must fix this now or we get squashed.
489     		 */
490     		__save_and_cli(flags);
491     		patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
492     		trap_table->inst_one = lvl14_save[0];
493     		trap_table->inst_two = lvl14_save[1];
494     		trap_table->inst_three = lvl14_save[2];
495     		trap_table->inst_four = lvl14_save[3];
496     		local_flush_cache_all();
497     		__restore_flags(flags);
498     	}
499     #endif
500     }
501     
502     void __init sun4d_init_sbi_irq(void)
503     {
504     	struct sbus_bus *sbus;
505     	unsigned mask;
506     
507     	nsbi = 0;
508     	for_each_sbus(sbus)
509     		nsbi++;
510     	sbus_actions = (struct sbus_action *)kmalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
511     	memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action)));
512     	for_each_sbus(sbus) {
513     #ifdef CONFIG_SMP	
514     		extern unsigned char boot_cpu_id;
515     		
516     		set_sbi_tid(sbus->devid, boot_cpu_id << 3);
517     		sbus_tid[sbus->board] = boot_cpu_id;
518     #endif
519     		/* Get rid of pending irqs from PROM */
520     		mask = acquire_sbi(sbus->devid, 0xffffffff);
521     		if (mask) {
522     			printk ("Clearing pending IRQs %08x on SBI %d\n", mask, sbus->board);
523     			release_sbi(sbus->devid, mask);
524     		}
525     	}
526     }
527     
528     static char *sun4d_irq_itoa(unsigned int irq)
529     {
530     	static char buff[16];
531     	
532     	if (irq < (1 << 5))
533     		sprintf(buff, "%d", irq);
534     	else
535     		sprintf(buff, "%d,%x", sbus_to_pil[(irq >> 2) & 7], irq);
536     	return buff;
537     }
538     
539     void __init sun4d_init_IRQ(void)
540     {
541     	__cli();
542     
543     	BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM);
544     	BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM);
545     	BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
546     	BTFIXUPSET_CALL(clear_profile_irq, sun4d_clear_profile_irq, BTFIXUPCALL_NORM);
547     	BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
548     	BTFIXUPSET_CALL(__irq_itoa, sun4d_irq_itoa, BTFIXUPCALL_NORM);
549     	init_timers = sun4d_init_timers;
550     #ifdef CONFIG_SMP
551     	BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
552     	BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP);
553     	BTFIXUPSET_CALL(set_irq_udt, sun4d_set_udt, BTFIXUPCALL_NOP);
554     #endif
555     	/* Cannot enable interrupts until OBP ticker is disabled. */
556     }
557