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 "R4030", 62 startup_r4030_irq, 63 shutdown_r4030_irq, 64 enable_r4030_irq, 65 disable_r4030_irq, 66 mask_and_ack_r4030_irq, 67 end_r4030_irq, 68 NULL 69 }; 70 71 void __init init_r4030_ints(void) 72 { 73 int i; 74 75 for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) { 76 irq_desc[i].status = IRQ_DISABLED; 77 irq_desc[i].action = 0; 78 irq_desc[i].depth = 1; 79 irq_desc[i].handler = &r4030_irq_type; 80 } 81 82 r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0); 83 r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ 84 r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */ 85 } 86 87 /* 88 * On systems with i8259-style interrupt controllers we assume for 89 * driver compatibility reasons interrupts 0 - 15 to be the i8259 90 * interrupts even if the hardware uses a different interrupt numbering. 91 */ 92 void __init arch_init_irq(void) 93 { 94 set_except_vector(0, jazz_handle_int); 95 96 init_i8259_irqs(); /* Integrated i8259 */ 97 init_r4030_ints(); 98 99 change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); 100 } 101