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 14*ea202c63SThomas Bogendoerfer #include <asm/irq_cpu.h> 151da177e4SLinus Torvalds #include <asm/i8259.h> 161da177e4SLinus Torvalds #include <asm/io.h> 171da177e4SLinus Torvalds #include <asm/jazz.h> 18*ea202c63SThomas Bogendoerfer #include <asm/pgtable.h> 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds static DEFINE_SPINLOCK(r4030_lock); 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds static void enable_r4030_irq(unsigned int irq) 231da177e4SLinus Torvalds { 24*ea202c63SThomas Bogendoerfer unsigned int mask = 1 << (irq - JAZZ_IRQ_START); 251da177e4SLinus Torvalds unsigned long flags; 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds spin_lock_irqsave(&r4030_lock, flags); 281da177e4SLinus Torvalds mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); 291da177e4SLinus Torvalds r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); 301da177e4SLinus Torvalds spin_unlock_irqrestore(&r4030_lock, flags); 311da177e4SLinus Torvalds } 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds void disable_r4030_irq(unsigned int irq) 341da177e4SLinus Torvalds { 35*ea202c63SThomas Bogendoerfer unsigned int mask = ~(1 << (irq - JAZZ_IRQ_START)); 361da177e4SLinus Torvalds unsigned long flags; 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds spin_lock_irqsave(&r4030_lock, flags); 391da177e4SLinus Torvalds mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); 401da177e4SLinus Torvalds r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); 411da177e4SLinus Torvalds spin_unlock_irqrestore(&r4030_lock, flags); 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds 4494dee171SRalf Baechle static struct irq_chip r4030_irq_type = { 4570d21cdeSAtsushi Nemoto .name = "R4030", 461603b5acSAtsushi Nemoto .ack = disable_r4030_irq, 471603b5acSAtsushi Nemoto .mask = disable_r4030_irq, 481603b5acSAtsushi Nemoto .mask_ack = disable_r4030_irq, 491603b5acSAtsushi Nemoto .unmask = enable_r4030_irq, 501da177e4SLinus Torvalds }; 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds void __init init_r4030_ints(void) 531da177e4SLinus Torvalds { 541da177e4SLinus Torvalds int i; 551da177e4SLinus Torvalds 56*ea202c63SThomas Bogendoerfer for (i = JAZZ_IRQ_START; i <= JAZZ_IRQ_END; i++) 571417836eSAtsushi Nemoto set_irq_chip_and_handler(i, &r4030_irq_type, handle_level_irq); 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0); 601da177e4SLinus Torvalds r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ 611da177e4SLinus Torvalds r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */ 621da177e4SLinus Torvalds } 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds /* 651da177e4SLinus Torvalds * On systems with i8259-style interrupt controllers we assume for 661da177e4SLinus Torvalds * driver compatibility reasons interrupts 0 - 15 to be the i8259 671da177e4SLinus Torvalds * interrupts even if the hardware uses a different interrupt numbering. 681da177e4SLinus Torvalds */ 691da177e4SLinus Torvalds void __init arch_init_irq(void) 701da177e4SLinus Torvalds { 71*ea202c63SThomas Bogendoerfer /* 72*ea202c63SThomas Bogendoerfer * this is a hack to get back the still needed wired mapping 73*ea202c63SThomas Bogendoerfer * killed by init_mm() 74*ea202c63SThomas Bogendoerfer */ 75*ea202c63SThomas Bogendoerfer 76*ea202c63SThomas Bogendoerfer /* Map 0xe0000000 -> 0x0:800005C0, 0xe0010000 -> 0x1:30000580 */ 77*ea202c63SThomas Bogendoerfer add_wired_entry(0x02000017, 0x03c00017, 0xe0000000, PM_64K); 78*ea202c63SThomas Bogendoerfer /* Map 0xe2000000 -> 0x0:900005C0, 0xe3010000 -> 0x0:910005C0 */ 79*ea202c63SThomas Bogendoerfer add_wired_entry(0x02400017, 0x02440017, 0xe2000000, PM_16M); 80*ea202c63SThomas Bogendoerfer /* Map 0xe4000000 -> 0x0:600005C0, 0xe4100000 -> 400005C0 */ 81*ea202c63SThomas Bogendoerfer add_wired_entry(0x01800017, 0x01000017, 0xe4000000, PM_4M); 82*ea202c63SThomas Bogendoerfer 831da177e4SLinus Torvalds init_i8259_irqs(); /* Integrated i8259 */ 84*ea202c63SThomas Bogendoerfer mips_cpu_irq_init(); 851da177e4SLinus Torvalds init_r4030_ints(); 861da177e4SLinus Torvalds 87*ea202c63SThomas Bogendoerfer change_c0_status(ST0_IM, IE_IRQ2 | IE_IRQ1); 88e4ac58afSRalf Baechle } 89e4ac58afSRalf Baechle 90937a8015SRalf Baechle asmlinkage void plat_irq_dispatch(void) 91e4ac58afSRalf Baechle { 92119537c0SThiemo Seufer unsigned int pending = read_c0_cause() & read_c0_status(); 93*ea202c63SThomas Bogendoerfer unsigned int irq; 94e4ac58afSRalf Baechle 95*ea202c63SThomas Bogendoerfer if (pending & IE_IRQ4) { 96e4ac58afSRalf Baechle r4030_read_reg32(JAZZ_TIMER_REGISTER); 97937a8015SRalf Baechle do_IRQ(JAZZ_TIMER_IRQ); 98*ea202c63SThomas Bogendoerfer } else if (pending & IE_IRQ2) 99937a8015SRalf Baechle do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK)); 100e4ac58afSRalf Baechle else if (pending & IE_IRQ1) { 101*ea202c63SThomas Bogendoerfer irq = *(volatile u8 *)JAZZ_IO_IRQ_SOURCE >> 2; 102*ea202c63SThomas Bogendoerfer if (likely(irq > 0)) 103*ea202c63SThomas Bogendoerfer do_IRQ(irq + JAZZ_IRQ_START - 1); 104*ea202c63SThomas Bogendoerfer else 105*ea202c63SThomas Bogendoerfer panic("Unimplemented loc_no_irq handler"); 106e4ac58afSRalf Baechle } 107e4ac58afSRalf Baechle } 108