Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | /* * IRQ vector handles * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv) * */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/ioport.h> #include <asm/bootinfo.h> #include <asm/i8259.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/mipsregs.h> #include <asm/system.h> #include <asm/cobalt/cobalt.h> /* Cobalt Exception handler */ extern void cobalt_handle_int(void); /* Via masking routines */ extern void unmask_irq(unsigned int irqr); extern void mask_irq(unsigned int irq); /* * We have two types of interrupts that we handle, ones that come * in through the CPU interrupt lines, and ones that come in on * the via chip. The CPU mappings are: * 0,1 - S/W (ignored) * 2 - Galileo chip (timer) * 3 - Tulip 0 + NCR SCSI * 4 - Tulip 1 * 5 - 16550 UART * 6 - VIA southbridge PIC * 7 - unused * * The VIA chip is a master/slave 8259 setup and has the * following interrupts * 8 - RTC * 9 - PCI * 14 - IDE0 * 15 - IDE1 * * In the table we use a 1 to indicate that we use a VIA interrupt * line, and IE_IRQx to indicate that we use a CPU interrupt line * * We map all of these onto linux IRQ #s 0-15 and forget the rest */ #define NOINT_LINE 0 #define CPUINT_LINE(x) IE_IRQ##x #define VIAINT_LINE 1 #define COBALT_IRQS 16 static unsigned short irqnr_to_type[COBALT_IRQS] = { CPUINT_LINE(0), NOINT_LINE, VIAINT_LINE, NOINT_LINE, CPUINT_LINE(1), NOINT_LINE, NOINT_LINE, CPUINT_LINE(3), VIAINT_LINE, VIAINT_LINE, NOINT_LINE, NOINT_LINE, NOINT_LINE, CPUINT_LINE(2), VIAINT_LINE, VIAINT_LINE }; /* * Cobalt CPU irq */ static void enable_cpu_irq(unsigned int irq) { unsigned long flags; local_irq_save(flags); change_c0_status(irqnr_to_type[irq], irqnr_to_type[irq]); local_irq_restore(flags); } static unsigned startup_cpu_irq(unsigned int irq) { enable_cpu_irq(irq); return 0; } static void disable_cpu_irq(unsigned int irq) { unsigned long flags; local_irq_save(flags); change_c0_status(irqnr_to_type[irq], ~(irqnr_to_type[irq])); local_irq_restore(flags); } #define shutdown_cpu_irq disable_cpu_irq #define mask_and_ack_cpu_irq disable_cpu_irq static void end_cpu_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) enable_cpu_irq(irq); } static struct hw_interrupt_type cobalt_cpu_irq_type = { "Cobalt CPU", startup_cpu_irq, shutdown_cpu_irq, enable_cpu_irq, disable_cpu_irq, mask_and_ack_cpu_irq, end_cpu_irq, NULL }; void __init init_IRQ(void) { int i; /* Initialise all of the IRQ descriptors */ init_i8259_irqs(); /* Map the irqnr to the type int we have */ for (i=0; i < COBALT_IRQS; i++) { if (irqnr_to_type[i] >= CPUINT_LINE(0)) /* cobalt_cpu_irq_type */ irq_desc[i].handler = &cobalt_cpu_irq_type; } /* Mask all cpu interrupts (except IE4, we already masked those at VIA level) */ clear_c0_status(ST0_IM); set_c0_status(IE_IRQ4); cli(); set_except_vector(0, cobalt_handle_int); } |