11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4SLinus Torvalds * for more details. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (C) 1992 Linus Torvalds 71da177e4SLinus Torvalds * Copyright (C) 1994 - 2001, 2003 Ralf Baechle 81da177e4SLinus Torvalds */ 91da177e4SLinus Torvalds #include <linux/init.h> 101da177e4SLinus Torvalds #include <linux/interrupt.h> 111da177e4SLinus Torvalds #include <linux/kernel.h> 121da177e4SLinus Torvalds #include <linux/spinlock.h> 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds #include <asm/i8259.h> 151da177e4SLinus Torvalds #include <asm/io.h> 161da177e4SLinus Torvalds #include <asm/jazz.h> 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds static DEFINE_SPINLOCK(r4030_lock); 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds static void enable_r4030_irq(unsigned int irq) 211da177e4SLinus Torvalds { 221da177e4SLinus Torvalds unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ); 231da177e4SLinus Torvalds unsigned long flags; 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds spin_lock_irqsave(&r4030_lock, flags); 261da177e4SLinus Torvalds mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); 271da177e4SLinus Torvalds r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); 281da177e4SLinus Torvalds spin_unlock_irqrestore(&r4030_lock, flags); 291da177e4SLinus Torvalds } 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds static unsigned int startup_r4030_irq(unsigned int irq) 321da177e4SLinus Torvalds { 331da177e4SLinus Torvalds enable_r4030_irq(irq); 341da177e4SLinus Torvalds return 0; /* never anything pending */ 351da177e4SLinus Torvalds } 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds #define shutdown_r4030_irq disable_r4030_irq 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds void disable_r4030_irq(unsigned int irq) 401da177e4SLinus Torvalds { 411da177e4SLinus Torvalds unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ)); 421da177e4SLinus Torvalds unsigned long flags; 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds spin_lock_irqsave(&r4030_lock, flags); 451da177e4SLinus Torvalds mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); 461da177e4SLinus Torvalds r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); 471da177e4SLinus Torvalds spin_unlock_irqrestore(&r4030_lock, flags); 481da177e4SLinus Torvalds } 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds #define mask_and_ack_r4030_irq disable_r4030_irq 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds static void end_r4030_irq(unsigned int irq) 531da177e4SLinus Torvalds { 541da177e4SLinus Torvalds if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 551da177e4SLinus Torvalds enable_r4030_irq(irq); 561da177e4SLinus Torvalds } 571da177e4SLinus Torvalds 58*94dee171SRalf Baechle static struct irq_chip r4030_irq_type = { 598ab00b9aSRalf Baechle .typename = "R4030", 608ab00b9aSRalf Baechle .startup = startup_r4030_irq, 618ab00b9aSRalf Baechle .shutdown = shutdown_r4030_irq, 628ab00b9aSRalf Baechle .enable = enable_r4030_irq, 638ab00b9aSRalf Baechle .disable = disable_r4030_irq, 648ab00b9aSRalf Baechle .ack = mask_and_ack_r4030_irq, 658ab00b9aSRalf Baechle .end = end_r4030_irq, 661da177e4SLinus Torvalds }; 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds void __init init_r4030_ints(void) 691da177e4SLinus Torvalds { 701da177e4SLinus Torvalds int i; 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) { 731da177e4SLinus Torvalds irq_desc[i].status = IRQ_DISABLED; 741da177e4SLinus Torvalds irq_desc[i].action = 0; 751da177e4SLinus Torvalds irq_desc[i].depth = 1; 76d1bef4edSIngo Molnar irq_desc[i].chip = &r4030_irq_type; 771da177e4SLinus Torvalds } 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0); 801da177e4SLinus Torvalds r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ 811da177e4SLinus Torvalds r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */ 821da177e4SLinus Torvalds } 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds /* 851da177e4SLinus Torvalds * On systems with i8259-style interrupt controllers we assume for 861da177e4SLinus Torvalds * driver compatibility reasons interrupts 0 - 15 to be the i8259 871da177e4SLinus Torvalds * interrupts even if the hardware uses a different interrupt numbering. 881da177e4SLinus Torvalds */ 891da177e4SLinus Torvalds void __init arch_init_irq(void) 901da177e4SLinus Torvalds { 911da177e4SLinus Torvalds init_i8259_irqs(); /* Integrated i8259 */ 921da177e4SLinus Torvalds init_r4030_ints(); 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); 951da177e4SLinus Torvalds } 96e4ac58afSRalf Baechle 97e4ac58afSRalf Baechle static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask) 98e4ac58afSRalf Baechle { 99e4ac58afSRalf Baechle r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 100e4ac58afSRalf Baechle r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask); 101e4ac58afSRalf Baechle do_IRQ(irq, regs); 102e4ac58afSRalf Baechle r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 103e4ac58afSRalf Baechle r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask); 104e4ac58afSRalf Baechle } 105e4ac58afSRalf Baechle 106e4ac58afSRalf Baechle static void ll_local_dev(struct pt_regs *regs) 107e4ac58afSRalf Baechle { 108e4ac58afSRalf Baechle switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) { 109e4ac58afSRalf Baechle case 0: 110e4ac58afSRalf Baechle panic("Unimplemented loc_no_irq handler"); 111e4ac58afSRalf Baechle break; 112e4ac58afSRalf Baechle case 4: 113e4ac58afSRalf Baechle loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL); 114e4ac58afSRalf Baechle break; 115e4ac58afSRalf Baechle case 8: 116e4ac58afSRalf Baechle loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY); 117e4ac58afSRalf Baechle break; 118e4ac58afSRalf Baechle case 12: 119e4ac58afSRalf Baechle panic("Unimplemented loc_sound handler"); 120e4ac58afSRalf Baechle break; 121e4ac58afSRalf Baechle case 16: 122e4ac58afSRalf Baechle panic("Unimplemented loc_video handler"); 123e4ac58afSRalf Baechle break; 124e4ac58afSRalf Baechle case 20: 125e4ac58afSRalf Baechle loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET); 126e4ac58afSRalf Baechle break; 127e4ac58afSRalf Baechle case 24: 128e4ac58afSRalf Baechle loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI); 129e4ac58afSRalf Baechle break; 130e4ac58afSRalf Baechle case 28: 131e4ac58afSRalf Baechle loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD); 132e4ac58afSRalf Baechle break; 133e4ac58afSRalf Baechle case 32: 134e4ac58afSRalf Baechle loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE); 135e4ac58afSRalf Baechle break; 136e4ac58afSRalf Baechle case 36: 137e4ac58afSRalf Baechle loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1); 138e4ac58afSRalf Baechle break; 139e4ac58afSRalf Baechle case 40: 140e4ac58afSRalf Baechle loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2); 141e4ac58afSRalf Baechle break; 142e4ac58afSRalf Baechle } 143e4ac58afSRalf Baechle } 144e4ac58afSRalf Baechle 145e4ac58afSRalf Baechle asmlinkage void plat_irq_dispatch(struct pt_regs *regs) 146e4ac58afSRalf Baechle { 147e4ac58afSRalf Baechle unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; 148e4ac58afSRalf Baechle 149e4ac58afSRalf Baechle if (pending & IE_IRQ5) 150e4ac58afSRalf Baechle write_c0_compare(0); 151e4ac58afSRalf Baechle else if (pending & IE_IRQ4) { 152e4ac58afSRalf Baechle r4030_read_reg32(JAZZ_TIMER_REGISTER); 153e4ac58afSRalf Baechle do_IRQ(JAZZ_TIMER_IRQ, regs); 154e4ac58afSRalf Baechle } else if (pending & IE_IRQ3) 155e4ac58afSRalf Baechle panic("Unimplemented ISA NMI handler"); 156e4ac58afSRalf Baechle else if (pending & IE_IRQ2) 157e4ac58afSRalf Baechle do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs); 158e4ac58afSRalf Baechle else if (pending & IE_IRQ1) { 159e4ac58afSRalf Baechle ll_local_dev(regs); 160e4ac58afSRalf Baechle } else if (unlikely(pending & IE_IRQ0)) 161e4ac58afSRalf Baechle panic("Unimplemented local_dma handler"); 162e4ac58afSRalf Baechle else if (pending & IE_SW1) { 163e4ac58afSRalf Baechle clear_c0_cause(IE_SW1); 164e4ac58afSRalf Baechle panic("Unimplemented sw1 handler"); 165e4ac58afSRalf Baechle } else if (pending & IE_SW0) { 166e4ac58afSRalf Baechle clear_c0_cause(IE_SW0); 167e4ac58afSRalf Baechle panic("Unimplemented sw0 handler"); 168e4ac58afSRalf Baechle } 169e4ac58afSRalf Baechle } 170