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