From 04a4a0b7c6ab2c36e0cf645a42dca0cce0fa281e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 18 May 2001 22:13:23 +0000 Subject: Move Alchemy board to the new interrupt handling plus various other cleanup. Patch from Pete Popov. --- arch/mips/au1000/common/int-handler.S | 11 +- arch/mips/au1000/common/irq.c | 399 ++++++++++------------------------ 2 files changed, 119 insertions(+), 291 deletions(-) (limited to 'arch/mips/au1000') diff --git a/arch/mips/au1000/common/int-handler.S b/arch/mips/au1000/common/int-handler.S index c7c933036..7cb017784 100644 --- a/arch/mips/au1000/common/int-handler.S +++ b/arch/mips/au1000/common/int-handler.S @@ -40,27 +40,28 @@ NESTED(au1000_IRQ, PT_SIZE, sp) 1: andi a0, t0, CAUSEF_IP2 # Interrupt Controller 0, Request 0 -/* beq a0, zero, 2f */ + beq a0, zero, 2f move a0,sp jal intc0_req0_irqdispatch - j done + j ret_from_irq 2: andi a0, t0, CAUSEF_IP3 # Interrupt Controller 0, Request 1 beq a0, zero, 3f move a0,sp jal intc0_req1_irqdispatch - j done + j ret_from_irq 3: andi a0, t0, CAUSEF_IP4 # Interrupt Controller 1, Request 0 beq a0, zero, 4f move a0,sp - jal intc1_req1_irqdispatch - j done + jal intc1_req0_irqdispatch + j ret_from_irq 4: andi a0, t0, CAUSEF_IP5 # Interrupt Controller 1, Request 1 beq a0, zero, 5f move a0, sp jal intc1_req1_irqdispatch + j ret_from_irq 5: move a0, sp diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index 7dececa07..fa1bab576 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -71,20 +72,26 @@ extern void set_debug_traps(void); irq_cpustat_t irq_stat [NR_CPUS]; unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; -unsigned long spurious_count = 0; irq_desc_t irq_desc[NR_IRQS]; -static void setup_au1000_irq(unsigned int irq, int type, int int_req); -static unsigned int startup_au1000_irq(unsigned int irq); -static void enable_au1000_irq(unsigned int irq_nr); -static void disable_au1000_irq(unsigned int irq_nr); -static void end_au1000_irq(unsigned int irq_nr); +static void setup_local_irq(unsigned int irq, int type, int int_req); +static unsigned int startup_irq(unsigned int irq); +static void end_irq(unsigned int irq_nr); +static inline void mask_and_ack_level_irq(unsigned int irq_nr); +static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr); +static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr); +static inline void local_enable_irq(unsigned int irq_nr); +static inline void local_disable_irq(unsigned int irq_nr); -static void ack_level_irq(unsigned int irq_nr); -static void ack_rise_edge_irq(unsigned int irq_nr); -static void ack_fall_edge_irq(unsigned int irq_nr); +extern unsigned long spurious_interrupts; +extern unsigned int do_IRQ(int irq, struct pt_regs *regs); +extern void __init init_generic_irq(void); + +static inline void sync(void) +{ + __asm volatile ("sync"); +} -void disable_ack_irq(int irq); /* Function for careful CP0 interrupt mask access */ static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) @@ -95,16 +102,19 @@ static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) write_32bit_cp0_register(CP0_STATUS, status); } + static inline void mask_cpu_irq_input(unsigned int irq_nr) { modify_cp0_intmask(irq_nr, 0); } + static inline void unmask_cpu_irq_input(unsigned int irq_nr) { modify_cp0_intmask(0, irq_nr); } + static void disable_cpu_irq_input(unsigned int irq_nr) { unsigned long flags; @@ -114,6 +124,7 @@ static void disable_cpu_irq_input(unsigned int irq_nr) restore_flags(flags); } + static void enable_cpu_irq_input(unsigned int irq_nr) { unsigned long flags; @@ -124,7 +135,7 @@ static void enable_cpu_irq_input(unsigned int irq_nr) } -static void setup_au1000_irq(unsigned int irq_nr, int type, int int_req) +static void setup_local_irq(unsigned int irq_nr, int type, int int_req) { /* Config2[n], Config1[n], Config0[n] */ if (irq_nr > AU1000_LAST_INTC0_INT) { @@ -171,7 +182,6 @@ static void setup_au1000_irq(unsigned int irq_nr, int type, int int_req) else { switch (type) { case INTC_INT_RISE_EDGE: /* 0:0:1 */ - printk("irq %d: rise edge\n", irq_nr); outl(1< AU1000_LAST_INTC0_INT) { - outl(1< AU1000_LAST_INTC0_INT) { outl(1< AU1000_LAST_INTC0_INT) { - outl(1< AU1000_LAST_INTC0_INT) { outl(1< AU1000_LAST_INTC0_INT) { outl(1< AU1000_LAST_INTC0_INT) { - outl(1<handler ) - continue; - len += sprintf(buf+len, "%3d: ", i); - len += sprintf(buf+len, "%10u ", kstat_irqs(i)); - if ( irq_desc[i].handler ) - len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename ); - else - len += sprintf(buf+len, " None "); - len += sprintf(buf+len, " %s",action->name); - for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ", %s", action->name); - } - len += sprintf(buf+len, "\n"); - } - len += sprintf(buf+len, "BAD: %10lu\n", spurious_count); - return len; -} - -asmlinkage void do_IRQ(int irq, struct pt_regs *regs) -{ - struct irqaction *action; - irq_desc_t *desc = irq_desc + irq; - int cpu; - - cpu = smp_processor_id(); - irq_enter(cpu, irq); - - kstat.irqs[cpu][irq]++; - desc->handler->ack(irq); - - action = irq_desc[irq].action; - - if (action && action->handler) - { - //desc->handler->disable(irq); - //if (!(action->flags & SA_INTERRUPT)) __sti(); /* reenable ints */ - do { - action->handler(irq, action->dev_id, regs); - action = action->next; - } while ( action ); - //__cli(); /* disable ints */ - //desc->handler->ack(irq); - //desc->handler->enable(irq); - } - else - { - spurious_count++; - printk("Unhandled interrupt %d, cause %x, disabled\n", - (unsigned)irq, (unsigned)regs->cp0_cause); - desc->handler->disable(irq); - } - irq_exit(cpu, irq); -#if 0 - if (softirq_active(cpu) & softirq_mask(cpu)) - do_softirq(); -#endif -} - -int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) -{ - struct irqaction *old, **p, *action; - unsigned long flags, shared=0; - irq_desc_t *desc = irq_desc + irq; - unsigned long cp0_status; - - cp0_status = read_32bit_cp0_register(CP0_STATUS); - - if (irq >= NR_IRQS) - return -EINVAL; - - if (!handler) - { - /* Free */ - for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) - { - /* Found it - now free it */ - save_flags(flags); - cli(); - *p = action->next; - desc->handler->disable(irq); - desc->handler->ack(irq); - restore_flags(flags); - kfree(action); - return 0; - } - return -ENOENT; - } - - action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - memset(action, 0, sizeof(struct irqaction)); - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->dev_id = dev_id; - action->next = NULL; - - p = &irq_desc[irq].action; - - spin_lock_irqsave(&desc->lock,flags); - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & action->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&desc->lock,flags); - return -EBUSY; - } - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - *p = action; - if (!shared) { - desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); - desc->handler->startup(irq); - desc->handler->ack(irq); - desc->handler->enable(irq); - } - else { - printk("irq %d is shared\n", irq); - } - spin_unlock_irqrestore(&desc->lock,flags); - return 0; -} - -void free_irq(unsigned int irq, void *dev_id) -{ - request_irq(irq, NULL, 0, NULL, dev_id); -} - void enable_cpu_timer(void) { enable_cpu_irq_input(1<handler->disable(irq); - desc->handler->ack(irq); -} - void mips_spurious_interrupt(struct pt_regs *regs) { -#if 0 - return; -#else - unsigned cause; - - cause = read_32bit_cp0_register(CP0_CAUSE); - printk("spurious int (epc %x) (cause %x) (badvaddr %x)\n", - (unsigned)regs->cp0_epc, cause, (unsigned)regs->cp0_badvaddr); -#endif + spurious_interrupts++; } + void intc0_req0_irqdispatch(struct pt_regs *regs) { - int irq = 0; + int irq = 0, i; unsigned long int_request; int_request = inl(INTC0_REQ0_INT); if (!int_request) return; - for (;;) { - if (!(int_request & 0x1)) { - irq++; - int_request >>= 1; + for (i=0; i<32; i++) { + if ((int_request & 0x1)) { + do_IRQ(irq, regs); } - else break; + irq++; + int_request >>= 1; } - do_IRQ(irq, regs); } + void intc0_req1_irqdispatch(struct pt_regs *regs) { - int irq = 0; + int irq = 0, i; unsigned long int_request; int_request = inl(INTC0_REQ1_INT); if (!int_request) return; - for (;;) { - if (!(int_request & 0x1)) { - irq++; - int_request >>= 1; + for (i=0; i<32; i++) { + if ((int_request & 0x1)) { + do_IRQ(irq, regs); } - else break; + irq++; + int_request >>= 1; } - do_IRQ(irq, regs); } + void intc1_req0_irqdispatch(struct pt_regs *regs) { - int irq = 0; + int irq = 0, i; unsigned long int_request; int_request = inl(INTC1_REQ0_INT); if (!int_request) return; - for (;;) { - if (!(int_request & 0x1)) { - irq++; - int_request >>= 1; + for (i=0; i<32; i++) { + if ((int_request & 0x1)) { + do_IRQ(irq, regs); } - else break; + irq++; + int_request >>= 1; } - do_IRQ(irq, regs); } + void intc1_req1_irqdispatch(struct pt_regs *regs) { - int irq = 0; + int irq = 0, i; unsigned long int_request; int_request = inl(INTC1_REQ1_INT); if (!int_request) return; - for (;;) { - if (!(int_request & 0x1)) { - irq++; - int_request >>= 1; + for (i=0; i<32; i++) { + if ((int_request & 0x1)) { + do_IRQ(irq, regs); } - else break; + irq++; + int_request >>= 1; } - do_IRQ(irq, regs); -} - -void show_pending_irqs(void) -{ } -- cgit v1.2.3