^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)