X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=arch%2Fmips%2Fjazz%2Firq.c;h=d7f8a782aae4d9a3200c307f383be28ed83b2b18;hb=39d4e58d36321b3c3b4025d9bf28bf026c2a5bb1;hp=015cf4bb51ddb4ab3fd92928e460df07d9509aff;hpb=18062a91d2ddc40e19fc674afeb7cad58cfa23ab;p=linux-2.6-omap-h63xx.git diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index 015cf4bb51d..d7f8a782aae 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -4,22 +4,26 @@ * for more details. * * Copyright (C) 1992 Linus Torvalds - * Copyright (C) 1994 - 2001, 2003 Ralf Baechle + * Copyright (C) 1994 - 2001, 2003, 07 Ralf Baechle */ +#include #include #include #include #include +#include +#include #include #include #include +#include static DEFINE_SPINLOCK(r4030_lock); static void enable_r4030_irq(unsigned int irq) { - unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ); + unsigned int mask = 1 << (irq - JAZZ_IRQ_START); unsigned long flags; spin_lock_irqsave(&r4030_lock, flags); @@ -30,7 +34,7 @@ static void enable_r4030_irq(unsigned int irq) void disable_r4030_irq(unsigned int irq) { - unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ)); + unsigned int mask = ~(1 << (irq - JAZZ_IRQ_START)); unsigned long flags; spin_lock_irqsave(&r4030_lock, flags); @@ -51,7 +55,7 @@ void __init init_r4030_ints(void) { int i; - for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) + for (i = JAZZ_IRQ_START; i <= JAZZ_IRQ_END; i++) set_irq_chip_and_handler(i, &r4030_irq_type, handle_level_irq); r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0); @@ -66,82 +70,93 @@ void __init init_r4030_ints(void) */ void __init arch_init_irq(void) { + /* + * this is a hack to get back the still needed wired mapping + * killed by init_mm() + */ + + /* Map 0xe0000000 -> 0x0:800005C0, 0xe0010000 -> 0x1:30000580 */ + add_wired_entry(0x02000017, 0x03c00017, 0xe0000000, PM_64K); + /* Map 0xe2000000 -> 0x0:900005C0, 0xe3010000 -> 0x0:910005C0 */ + add_wired_entry(0x02400017, 0x02440017, 0xe2000000, PM_16M); + /* Map 0xe4000000 -> 0x0:600005C0, 0xe4100000 -> 400005C0 */ + add_wired_entry(0x01800017, 0x01000017, 0xe4000000, PM_4M); + init_i8259_irqs(); /* Integrated i8259 */ + mips_cpu_irq_init(); init_r4030_ints(); - change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); + change_c0_status(ST0_IM, IE_IRQ2 | IE_IRQ1); } -static void loc_call(unsigned int irq, unsigned int mask) +asmlinkage void plat_irq_dispatch(void) { - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask); - do_IRQ(irq); - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask); + unsigned int pending = read_c0_cause() & read_c0_status(); + unsigned int irq; + + if (pending & IE_IRQ4) { + r4030_read_reg32(JAZZ_TIMER_REGISTER); + do_IRQ(JAZZ_TIMER_IRQ); + } else if (pending & IE_IRQ2) { + irq = *(volatile u8 *)JAZZ_EISA_IRQ_ACK; + do_IRQ(irq); + } else if (pending & IE_IRQ1) { + irq = *(volatile u8 *)JAZZ_IO_IRQ_SOURCE >> 2; + if (likely(irq > 0)) + do_IRQ(irq + JAZZ_IRQ_START - 1); + else + panic("Unimplemented loc_no_irq handler"); + } } -static void ll_local_dev(void) +static void r4030_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) { - switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) { - case 0: - panic("Unimplemented loc_no_irq handler"); - break; - case 4: - loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_PARALLEL); - break; - case 8: - loc_call(JAZZ_PARALLEL_IRQ, JAZZ_IE_FLOPPY); - break; - case 12: - panic("Unimplemented loc_sound handler"); - break; - case 16: - panic("Unimplemented loc_video handler"); - break; - case 20: - loc_call(JAZZ_ETHERNET_IRQ, JAZZ_IE_ETHERNET); - break; - case 24: - loc_call(JAZZ_SCSI_IRQ, JAZZ_IE_SCSI); - break; - case 28: - loc_call(JAZZ_KEYBOARD_IRQ, JAZZ_IE_KEYBOARD); - break; - case 32: - loc_call(JAZZ_MOUSE_IRQ, JAZZ_IE_MOUSE); - break; - case 36: - loc_call(JAZZ_SERIAL1_IRQ, JAZZ_IE_SERIAL1); - break; - case 40: - loc_call(JAZZ_SERIAL2_IRQ, JAZZ_IE_SERIAL2); - break; - } + /* Nothing to do ... */ } -asmlinkage void plat_irq_dispatch(void) +struct clock_event_device r4030_clockevent = { + .name = "r4030", + .features = CLOCK_EVT_FEAT_PERIODIC, + .rating = 300, + .irq = JAZZ_TIMER_IRQ, + .set_mode = r4030_set_mode, +}; + +static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id) { - unsigned int pending = read_c0_cause() & read_c0_status(); + struct clock_event_device *cd = dev_id; - if (pending & IE_IRQ5) - write_c0_compare(0); - else if (pending & IE_IRQ4) { - r4030_read_reg32(JAZZ_TIMER_REGISTER); - do_IRQ(JAZZ_TIMER_IRQ); - } else if (pending & IE_IRQ3) - panic("Unimplemented ISA NMI handler"); - else if (pending & IE_IRQ2) - do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK)); - else if (pending & IE_IRQ1) { - ll_local_dev(); - } else if (unlikely(pending & IE_IRQ0)) - panic("Unimplemented local_dma handler"); - else if (pending & IE_SW1) { - clear_c0_cause(IE_SW1); - panic("Unimplemented sw1 handler"); - } else if (pending & IE_SW0) { - clear_c0_cause(IE_SW0); - panic("Unimplemented sw0 handler"); - } + cd->event_handler(cd); + return IRQ_HANDLED; +} + +static struct irqaction r4030_timer_irqaction = { + .handler = r4030_timer_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_CPU0, + .name = "R4030 timer", +}; + +void __init plat_time_init(void) +{ + struct clock_event_device *cd = &r4030_clockevent; + struct irqaction *action = &r4030_timer_irqaction; + unsigned int cpu = smp_processor_id(); + + BUG_ON(HZ != 100); + + cd->cpumask = cpumask_of_cpu(cpu); + clockevents_register_device(cd); + action->dev_id = cd; + setup_irq(JAZZ_TIMER_IRQ, action); + + /* + * Set clock to 100Hz. + * + * The R4030 timer receives an input clock of 1kHz which is divieded by + * a programmable 4-bit divider. This makes it fairly inflexible. + */ + r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); + setup_pit_timer(); }