1 /* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 1992 Linus Torvalds 7 * Copyright (C) 1994 - 2001, 2003 Ralf Baechle 8 */ 9 #include <linux/init.h> 10 #include <linux/interrupt.h> 11 #include <linux/kernel.h> 12 #include <linux/spinlock.h> 13 14 #include <asm/i8259.h> 15 #include <asm/io.h> 16 #include <asm/jazz.h> 17 18 static DEFINE_SPINLOCK(r4030_lock); 19 20 static void enable_r4030_irq(unsigned int irq) 21 { 22 unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ); 23 unsigned long flags; 24 25 spin_lock_irqsave(&r4030_lock, flags); 26 mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); 27 r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); 28 spin_unlock_irqrestore(&r4030_lock, flags); 29 } 30 31 static unsigned int startup_r4030_irq(unsigned int irq) 32 { 33 enable_r4030_irq(irq); 34 return 0; /* never anything pending */ 35 } 36 37 #define shutdown_r4030_irq disable_r4030_irq 38 39 void disable_r4030_irq(unsigned int irq) 40 { 41 unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ)); 42 unsigned long flags; 43 44 spin_lock_irqsave(&r4030_lock, flags); 45 mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); 46 r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); 47 spin_unlock_irqrestore(&r4030_lock, flags); 48 } 49 50 #define mask_and_ack_r4030_irq disable_r4030_irq 51 52 static void end_r4030_irq(unsigned int irq) 53 { 54 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 55 enable_r4030_irq(irq); 56 } 57 58 static struct hw_interrupt_type r4030_irq_type = { 59 .typename = "R4030", 60 .startup = startup_r4030_irq, 61 .shutdown = shutdown_r4030_irq, 62 .enable = enable_r4030_irq, 63 .disable = disable_r4030_irq, 64 .ack = mask_and_ack_r4030_irq, 65 .end = end_r4030_irq, 66 }; 67 68 void __init init_r4030_ints(void) 69 { 70 int i; 71 72 for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) { 73 irq_desc[i].status = IRQ_DISABLED; 74 irq_desc[i].action = 0; 75 irq_desc[i].depth = 1; 76 irq_desc[i].handler = &r4030_irq_type; 77 } 78 79 r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0); 80 r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ 81 r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */ 82 } 83 84 /* 85 * On systems with i8259-style interrupt controllers we assume for 86 * driver compatibility reasons interrupts 0 - 15 to be the i8259 87 * interrupts even if the hardware uses a different interrupt numbering. 88 */ 89 void __init arch_init_irq(void) 90 { 91 init_i8259_irqs(); /* Integrated i8259 */ 92 init_r4030_ints(); 93 94 change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); 95 } 96 97 static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask) 98 { 99 r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 100 r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask); 101 do_IRQ(irq, regs); 102 r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 103 r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask); 104 } 105 106 static void ll_local_dev(struct pt_regs *regs) 107 { 108 switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) { 109 case 0: 110 panic("Unimplemented loc_no_irq handler"); 111 break; 112 case 4: 113 loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL); 114 break; 115 case 8: 116 loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY); 117 break; 118 case 12: 119 panic("Unimplemented loc_sound handler"); 120 break; 121 case 16: 122 panic("Unimplemented loc_video handler"); 123 break; 124 case 20: 125 loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET); 126 break; 127 case 24: 128 loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI); 129 break; 130 case 28: 131 loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD); 132 break; 133 case 32: 134 loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE); 135 break; 136 case 36: 137 loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1); 138 break; 139 case 40: 140 loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2); 141 break; 142 } 143 } 144 145 asmlinkage void plat_irq_dispatch(struct pt_regs *regs) 146 { 147 unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; 148 149 if (pending & IE_IRQ5) 150 write_c0_compare(0); 151 else if (pending & IE_IRQ4) { 152 r4030_read_reg32(JAZZ_TIMER_REGISTER); 153 do_IRQ(JAZZ_TIMER_IRQ, regs); 154 } else if (pending & IE_IRQ3) 155 panic("Unimplemented ISA NMI handler"); 156 else if (pending & IE_IRQ2) 157 do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs); 158 else if (pending & IE_IRQ1) { 159 ll_local_dev(regs); 160 } else if (unlikely(pending & IE_IRQ0)) 161 panic("Unimplemented local_dma handler"); 162 else if (pending & IE_SW1) { 163 clear_c0_cause(IE_SW1); 164 panic("Unimplemented sw1 handler"); 165 } else if (pending & IE_SW0) { 166 clear_c0_cause(IE_SW0); 167 panic("Unimplemented sw0 handler"); 168 } 169 } 170