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 extern asmlinkage void jazz_handle_int(void); 19 20 static DEFINE_SPINLOCK(r4030_lock); 21 22 static void enable_r4030_irq(unsigned int irq) 23 { 24 unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ); 25 unsigned long flags; 26 27 spin_lock_irqsave(&r4030_lock, flags); 28 mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); 29 r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); 30 spin_unlock_irqrestore(&r4030_lock, flags); 31 } 32 33 static unsigned int startup_r4030_irq(unsigned int irq) 34 { 35 enable_r4030_irq(irq); 36 return 0; /* never anything pending */ 37 } 38 39 #define shutdown_r4030_irq disable_r4030_irq 40 41 void disable_r4030_irq(unsigned int irq) 42 { 43 unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ)); 44 unsigned long flags; 45 46 spin_lock_irqsave(&r4030_lock, flags); 47 mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); 48 r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); 49 spin_unlock_irqrestore(&r4030_lock, flags); 50 } 51 52 #define mask_and_ack_r4030_irq disable_r4030_irq 53 54 static void end_r4030_irq(unsigned int irq) 55 { 56 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 57 enable_r4030_irq(irq); 58 } 59 60 static struct hw_interrupt_type r4030_irq_type = { 61 .typename = "R4030", 62 .startup = startup_r4030_irq, 63 .shutdown = shutdown_r4030_irq, 64 .enable = enable_r4030_irq, 65 .disable = disable_r4030_irq, 66 .ack = mask_and_ack_r4030_irq, 67 .end = end_r4030_irq, 68 }; 69 70 void __init init_r4030_ints(void) 71 { 72 int i; 73 74 for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) { 75 irq_desc[i].status = IRQ_DISABLED; 76 irq_desc[i].action = 0; 77 irq_desc[i].depth = 1; 78 irq_desc[i].handler = &r4030_irq_type; 79 } 80 81 r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0); 82 r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ 83 r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */ 84 } 85 86 /* 87 * On systems with i8259-style interrupt controllers we assume for 88 * driver compatibility reasons interrupts 0 - 15 to be the i8259 89 * interrupts even if the hardware uses a different interrupt numbering. 90 */ 91 void __init arch_init_irq(void) 92 { 93 set_except_vector(0, jazz_handle_int); 94 95 init_i8259_irqs(); /* Integrated i8259 */ 96 init_r4030_ints(); 97 98 change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); 99 } 100