diff options
author | Greg Ungerer <gerg@snapgear.com> | 2007-07-19 01:49:12 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 10:04:50 -0700 |
commit | 2502b667ea835ee16685c74b2a0d89ba8afe117a (patch) | |
tree | 31d492fb934df6d83819b679f3aa8d7f6952396d /arch/m68knommu/platform/68360 | |
parent | f8af0bb890d6cdcb09ec042c128e217a7c500355 (diff) |
m68knommu: generic irq handling
Change the m68knommu irq handling to use the generic irq framework.
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/m68knommu/platform/68360')
-rw-r--r-- | arch/m68knommu/platform/68360/entry.S | 6 | ||||
-rw-r--r-- | arch/m68knommu/platform/68360/ints.c | 233 |
2 files changed, 15 insertions, 224 deletions
diff --git a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S index f1af8977f29..55dfefe3864 100644 --- a/arch/m68knommu/platform/68360/entry.S +++ b/arch/m68knommu/platform/68360/entry.S @@ -120,23 +120,21 @@ Lreturn: RESTORE_ALL /* - * This is the main interrupt handler, responsible for calling process_int() + * This is the main interrupt handler, responsible for calling do_IRQ() */ inthandler: SAVE_ALL - addql #1,local_irq_count /* put exception # in d0*/ movew %sp@(PT_VECTOR), %d0 and.l #0x3ff, %d0 lsr.l #0x02, %d0 movel %sp,%sp@- movel %d0,%sp@- /* put vector # on stack*/ - jbsr process_int /* process the IRQ*/ + jbsr do_IRQ /* process the IRQ*/ 3: addql #8,%sp /* pop parameters off stack*/ bra ret_from_interrupt ret_from_interrupt: - subql #1,local_irq_count jeq 1f 2: RESTORE_ALL diff --git a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c index 4df3c146eb7..c36781157e0 100644 --- a/arch/m68knommu/platform/68360/ints.c +++ b/arch/m68knommu/platform/68360/ints.c @@ -10,20 +10,13 @@ * Copyright (c) 1999 D. Jeff Dionne <jeff@uclinux.org> */ -#include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/kernel_stat.h> -#include <linux/errno.h> - -#include <asm/system.h> -#include <asm/irq.h> -#include <asm/irqnode.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> #include <asm/traps.h> -#include <asm/io.h> #include <asm/machdep.h> -#include <asm/setup.h> #include <asm/m68360.h> /* from quicc/commproc.c: */ @@ -36,26 +29,19 @@ extern void cpm_interrupt_init(void); asmlinkage void system_call(void); asmlinkage void buserr(void); asmlinkage void trap(void); -asmlinkage irqreturn_t bad_interrupt(void); -asmlinkage irqreturn_t inthandler(void); +asmlinkage void bad_interrupt(void); +asmlinkage void inthandler(void); extern void *_ramvec[]; /* The number of spurious interrupts */ volatile unsigned int num_spurious; -unsigned int local_irq_count[NR_CPUS]; - -/* irq node variables for the 32 (potential) on chip sources */ -static irq_node_t int_irq_list[INTERNAL_IRQS]; - -static short int_irq_ablecount[INTERNAL_IRQS]; /* * This function should be called during kernel startup to initialize - * IRQ handling routines. + * the vector table. */ - -void init_IRQ(void) +void init_vectors(void) { int i; int vba = (CPM_VECTOR_BASE<<4); @@ -79,7 +65,6 @@ void init_IRQ(void) _ramvec[32] = system_call; _ramvec[33] = trap; - cpm_interrupt_init(); /* set up CICR for vector base address and irq level */ @@ -124,212 +109,20 @@ void init_IRQ(void) /* turn off all CPM interrupts */ pquicc->intr_cimr = 0x00000000; - - /* initialize handlers */ - for (i = 0; i < INTERNAL_IRQS; i++) { - int_irq_list[i].handler = NULL; - int_irq_list[i].flags = IRQ_FLG_STD; - int_irq_list[i].dev_id = NULL; - int_irq_list[i].devname = NULL; - } -} - -#if 0 -void M68360_insert_irq(irq_node_t **list, irq_node_t *node) -{ - unsigned long flags; - irq_node_t *cur; - - if (!node->dev_id) - printk(KERN_INFO "%s: Warning: dev_id of %s is zero\n", - __FUNCTION__, node->devname); - - local_irq_save(flags); - - cur = *list; - - while (cur) { - list = &cur->next; - cur = cur->next; - } - - node->next = cur; - *list = node; - - local_irq_restore(flags); } -void M68360_delete_irq(irq_node_t **list, void *dev_id) +void enable_vector(unsigned int irq) { - unsigned long flags; - irq_node_t *node; - - local_irq_save(flags); - - for (node = *list; node; list = &node->next, node = *list) { - if (node->dev_id == dev_id) { - *list = node->next; - /* Mark it as free. */ - node->handler = NULL; - local_irq_restore(flags); - return; - } - } - local_irq_restore(flags); - printk (KERN_INFO "%s: tried to remove invalid irq\n", __FUNCTION__); + pquicc->intr_cimr |= (1 << irq); } -#endif -int request_irq( - unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, - const char *devname, - void *dev_id) +void disable_vector(unsigned int irq) { - int mask = (1<<irq); - - irq += (CPM_VECTOR_BASE<<4); - - if (irq >= INTERNAL_IRQS) { - printk (KERN_ERR "%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname); - return -ENXIO; - } - - if (!(int_irq_list[irq].flags & IRQ_FLG_STD)) { - if (int_irq_list[irq].flags & IRQ_FLG_LOCK) { - printk(KERN_ERR "%s: IRQ %d from %s is not replaceable\n", - __FUNCTION__, irq, int_irq_list[irq].devname); - return -EBUSY; - } - if (flags & IRQ_FLG_REPLACE) { - printk(KERN_ERR "%s: %s can't replace IRQ %d from %s\n", - __FUNCTION__, devname, irq, int_irq_list[irq].devname); - return -EBUSY; - } - } - int_irq_list[irq].handler = handler; - int_irq_list[irq].flags = flags; - int_irq_list[irq].dev_id = dev_id; - int_irq_list[irq].devname = devname; - - /* enable in the CIMR */ - if (!int_irq_ablecount[irq]) - pquicc->intr_cimr |= mask; - /* *(volatile unsigned long *)0xfffff304 &= ~(1<<irq); */ - - return 0; + pquicc->intr_cimr &= ~(1 << irq); } -EXPORT_SYMBOL(request_irq); - -void free_irq(unsigned int irq, void *dev_id) +void ack_vector(unsigned int irq) { - if (irq >= INTERNAL_IRQS) { - printk (KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq); - return; - } - - if (int_irq_list[irq].dev_id != dev_id) - printk(KERN_INFO "%s: removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, int_irq_list[irq].devname); - int_irq_list[irq].handler = NULL; - int_irq_list[irq].flags = IRQ_FLG_STD; - int_irq_list[irq].dev_id = NULL; - int_irq_list[irq].devname = NULL; - - *(volatile unsigned long *)0xfffff304 |= 1<<irq; + pquicc->intr_cisr = (1 << irq); } -EXPORT_SYMBOL(free_irq); - -#if 0 -/* - * Enable/disable a particular machine specific interrupt source. - * Note that this may affect other interrupts in case of a shared interrupt. - * This function should only be called for a _very_ short time to change some - * internal data, that may not be changed by the interrupt at the same time. - * int_(enable|disable)_irq calls may also be nested. - */ -void M68360_enable_irq(unsigned int irq) -{ - if (irq >= INTERNAL_IRQS) { - printk(KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq); - return; - } - - if (--int_irq_ablecount[irq]) - return; - - /* enable the interrupt */ - *(volatile unsigned long *)0xfffff304 &= ~(1<<irq); -} - -void M68360_disable_irq(unsigned int irq) -{ - if (irq >= INTERNAL_IRQS) { - printk(KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq); - return; - } - - if (int_irq_ablecount[irq]++) - return; - - /* disable the interrupt */ - *(volatile unsigned long *)0xfffff304 |= 1<<irq; -} -#endif - -int show_interrupts(struct seq_file *p, void *v) -{ - int i = *(loff_t *) v; - - if (i < NR_IRQS) { - if (int_irq_list[i].devname) { - seq_printf(p, "%3d: %10u ", i, kstat_cpu(0).irqs[i]); - if (int_irq_list[i].flags & IRQ_FLG_LOCK) - seq_printf(p, "L "); - else - seq_printf(p, " "); - seq_printf(p, "%s\n", int_irq_list[i].devname); - } - } - if (i == NR_IRQS) - seq_printf(p, " : %10u spurious\n", num_spurious); - - return 0; -} - -/* The 68k family did not have a good way to determine the source - * of interrupts until later in the family. The EC000 core does - * not provide the vector number on the stack, we vector everything - * into one vector and look in the blasted mask register... - * This code is designed to be fast, almost constant time, not clean! - */ -void process_int(int vec, struct pt_regs *fp) -{ - int irq; - int mask; - - /* unsigned long pend = *(volatile unsigned long *)0xfffff30c; */ - - /* irq = vec + (CPM_VECTOR_BASE<<4); */ - irq = vec; - - /* unsigned long pend = *(volatile unsigned long *)pquicc->intr_cipr; */ - - /* Bugger all that weirdness. For the moment, I seem to know where I came from; - * vec is passed from a specific ISR, so I'll use it. */ - - if (int_irq_list[irq].handler) { - int_irq_list[irq].handler(irq , int_irq_list[irq].dev_id, fp); - kstat_cpu(0).irqs[irq]++; - pquicc->intr_cisr = (1 << vec); /* indicate that irq has been serviced */ - } else { - printk(KERN_ERR "unregistered interrupt %d!\nTurning it off in the CIMR...\n", irq); - /* *(volatile unsigned long *)0xfffff304 |= mask; */ - pquicc->intr_cimr &= ~(1 << vec); - num_spurious += 1; - } - return(IRQ_HANDLED); -} |