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