Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Interrupt request handling routines. On the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Sparc the IRQs are basically 'cast in stone'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * and you are supposed to probe the prom's device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * node trees to find out who's got which IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *  Copyright (C) 1995,2002 Pete A. Zaitcev (zaitcev@yahoo.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *  Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/kernel_stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <asm/cpudata.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <asm/setup.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <asm/pcic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <asm/leon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include "kernel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include "irq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) /* platform specific irq setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) struct sparc_config sparc_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) unsigned long arch_local_irq_save(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	unsigned long retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	__asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		"rd	%%psr, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		"or	%0, %2, %1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		"wr	%1, 0, %%psr\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		"nop; nop; nop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		: "=&r" (retval), "=r" (tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		: "i" (PSR_PIL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		: "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) EXPORT_SYMBOL(arch_local_irq_save);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) void arch_local_irq_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	__asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		"rd	%%psr, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		"andn	%0, %1, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		"wr	%0, 0, %%psr\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		"nop; nop; nop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		: "=&r" (tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		: "i" (PSR_PIL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		: "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) EXPORT_SYMBOL(arch_local_irq_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) void arch_local_irq_restore(unsigned long old_psr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	__asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		"rd	%%psr, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		"and	%2, %1, %2\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		"andn	%0, %1, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		"wr	%0, %2, %%psr\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		"nop; nop; nop\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		: "=&r" (tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		: "i" (PSR_PIL), "r" (old_psr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		: "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) EXPORT_SYMBOL(arch_local_irq_restore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * Dave Redman (djhr@tadpole.co.uk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * IRQ numbers.. These are no longer restricted to 15..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * this is done to enable SBUS cards and onboard IO to be masked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * correctly. using the interrupt level isn't good enough.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * For example:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  *   A device interrupting at sbus level6 and the Floppy both come in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  *   at IRQ11, but enabling and disabling them requires writing to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  *   different bits in the SLAVIO/SEC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  * As a result of these changes sun4m machines could now support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  * directed CPU interrupts using the existing enable/disable irq code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)  * with tweaks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)  * Sun4d complicates things even further.  IRQ numbers are arbitrary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)  * 32-bit values in that case.  Since this is similar to sparc64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)  * we adopt a virtual IRQ numbering scheme as is done there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)  * Virutal interrupt numbers are allocated by build_irq().  So NR_IRQS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)  * just becomes a limit of how many interrupt sources we can handle in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)  * a single system.  Even fully loaded SS2000 machines top off at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)  * about 32 interrupt sources or so, therefore a NR_IRQS value of 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)  * is more than enough.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)   *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)  * We keep a map of per-PIL enable interrupts.  These get wired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  * up via the irq_chip->startup() method which gets invoked by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  * the generic IRQ layer during request_irq().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Table of allocated irqs. Unused entries has irq == 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static struct irq_bucket irq_table[NR_IRQS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Protect access to irq_table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static DEFINE_SPINLOCK(irq_table_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Map between the irq identifier used in hw to the irq_bucket. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct irq_bucket *irq_map[SUN4D_MAX_IRQ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* Protect access to irq_map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static DEFINE_SPINLOCK(irq_map_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* Allocate a new irq from the irq_table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) unsigned int irq_alloc(unsigned int real_irq, unsigned int pil)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	spin_lock_irqsave(&irq_table_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	for (i = 1; i < NR_IRQS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		if (irq_table[i].real_irq == real_irq && irq_table[i].pil == pil)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 			goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	for (i = 1; i < NR_IRQS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		if (!irq_table[i].irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (i < NR_IRQS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		irq_table[i].real_irq = real_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		irq_table[i].irq = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		irq_table[i].pil = pil;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	spin_unlock_irqrestore(&irq_table_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Based on a single pil handler_irq may need to call several
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  * interrupt handlers. Use irq_map as entry to irq_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  * and let each entry in irq_table point to the next entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) void irq_link(unsigned int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	struct irq_bucket *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	unsigned int pil;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	BUG_ON(irq >= NR_IRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	spin_lock_irqsave(&irq_map_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	p = &irq_table[irq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	pil = p->pil;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	BUG_ON(pil >= SUN4D_MAX_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	p->next = irq_map[pil];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	irq_map[pil] = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	spin_unlock_irqrestore(&irq_map_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) void irq_unlink(unsigned int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	struct irq_bucket *p, **pnext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	BUG_ON(irq >= NR_IRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	spin_lock_irqsave(&irq_map_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	p = &irq_table[irq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	BUG_ON(p->pil >= SUN4D_MAX_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	pnext = &irq_map[p->pil];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	while (*pnext != p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		pnext = &(*pnext)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	*pnext = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	spin_unlock_irqrestore(&irq_map_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* /proc/interrupts printing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int arch_show_interrupts(struct seq_file *p, int prec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	seq_printf(p, "RES: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	for_each_online_cpu(j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		seq_printf(p, "%10u ", cpu_data(j).irq_resched_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	seq_printf(p, "     IPI rescheduling interrupts\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	seq_printf(p, "CAL: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	for_each_online_cpu(j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		seq_printf(p, "%10u ", cpu_data(j).irq_call_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	seq_printf(p, "     IPI function call interrupts\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	seq_printf(p, "NMI: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	for_each_online_cpu(j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		seq_printf(p, "%10u ", cpu_data(j).counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	seq_printf(p, "     Non-maskable interrupts\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) void handler_irq(unsigned int pil, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	struct pt_regs *old_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	struct irq_bucket *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	BUG_ON(pil > 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	old_regs = set_irq_regs(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	irq_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	p = irq_map[pil];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		struct irq_bucket *next = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		generic_handle_irq(p->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		p = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	irq_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	set_irq_regs(old_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static unsigned int floppy_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	unsigned int cpu_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	err = request_irq(irq, irq_handler, 0, "floppy", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	/* Save for later use in floppy interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	floppy_irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	cpu_irq = (irq & (NR_IRQS - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	/* Dork with trap table if we get this far. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) #define INSTANTIATE(table) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		SPARC_BRANCH((unsigned long) floppy_hardint, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			     (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	INSTANTIATE(sparc_ttable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #if defined CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	if (sparc_cpu_model != sparc_leon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		struct tt_entry *trap_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		trap_table = &trapbase_cpu1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		INSTANTIATE(trap_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		trap_table = &trapbase_cpu2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		INSTANTIATE(trap_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		trap_table = &trapbase_cpu3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		INSTANTIATE(trap_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #undef INSTANTIATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	 * XXX Correct thing whould be to flush only I- and D-cache lines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	 * which contain the handler in question. But as of time of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	 * writing we have no CPU-neutral interface to fine-grained flushes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	flush_cache_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) EXPORT_SYMBOL(sparc_floppy_request_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)  * These variables are used to access state from the assembler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  * interrupt handler, floppy_hardint, so we cannot put these in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  * the floppy driver image because that would not work in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)  * modular case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) volatile unsigned char *fdc_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) EXPORT_SYMBOL(fdc_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) char *pdma_vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) EXPORT_SYMBOL(pdma_vaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) unsigned long pdma_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) EXPORT_SYMBOL(pdma_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) volatile int doing_pdma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) EXPORT_SYMBOL(doing_pdma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) char *pdma_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) EXPORT_SYMBOL(pdma_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) unsigned long pdma_areasize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) EXPORT_SYMBOL(pdma_areasize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Use the generic irq support to call floppy_interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)  * which was setup using request_irq() in sparc_floppy_request_irq().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)  * We only have one floppy interrupt so we do not need to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)  * for additional handlers being wired up by irq_link()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	struct pt_regs *old_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	old_regs = set_irq_regs(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	irq_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	generic_handle_irq(floppy_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	irq_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	set_irq_regs(old_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /* djhr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  * This could probably be made indirect too and assigned in the CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)  * bits of the code. That would be much nicer I think and would also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)  * fit in with the idea of being able to tune your kernel for your machine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  * by removing unrequired machine and device support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) void __init init_IRQ(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	switch (sparc_cpu_model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	case sun4m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		pcic_probe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		if (pcic_present())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 			sun4m_pci_init_IRQ();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			sun4m_init_IRQ();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	case sun4d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		sun4d_init_IRQ();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	case sparc_leon:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		leon_init_IRQ();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		prom_printf("Cannot initialize IRQs on this Sun machine...");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)