Commit 815dece7 authored by Greg Ungerer's avatar Greg Ungerer Committed by Anton Blanchard

[PATCH] rework 68360 interrupt handling code

Rework the interrupt handling code for the m68knommu 68360 sub-architecture.
This is inline with the interrupt changes to the other m68knommu CPU's.
Makes this code be the primary interrupt setup for a 68360 based kernel,
not just a set of support functions.
parent 1b29b46a
...@@ -40,23 +40,21 @@ asmlinkage void inthandler(void); ...@@ -40,23 +40,21 @@ asmlinkage void inthandler(void);
extern void *_ramvec[]; 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 */ /* irq node variables for the 32 (potential) on chip sources */
static irq_node_t *int_irq_list[INTERNAL_IRQS]; static irq_node_t int_irq_list[INTERNAL_IRQS];
static int int_irq_count[INTERNAL_IRQS];
static short int_irq_ablecount[INTERNAL_IRQS]; static short int_irq_ablecount[INTERNAL_IRQS];
static void int_badint(int irq, void *dev_id, struct pt_regs *fp)
{
num_spurious += 1;
}
/* /*
* This function should be called during kernel startup to initialize * This function should be called during kernel startup to initialize
* IRQ handling routines. * IRQ handling routines.
*/ */
void M68360_init_IRQ(void) void init_IRQ(void)
{ {
int i; int i;
int vba = (CPM_VECTOR_BASE<<4); int vba = (CPM_VECTOR_BASE<<4);
...@@ -128,13 +126,14 @@ void M68360_init_IRQ(void) ...@@ -128,13 +126,14 @@ void M68360_init_IRQ(void)
/* initialize handlers */ /* initialize handlers */
for (i = 0; i < INTERNAL_IRQS; i++) { for (i = 0; i < INTERNAL_IRQS; i++) {
int_irq_list[i] = NULL; int_irq_list[i].handler = NULL;
int_irq_list[i].flags = IRQ_FLG_STD;
int_irq_ablecount[i] = 0; int_irq_list[i].dev_id = NULL;
int_irq_count[i] = 0; int_irq_list[i].devname = NULL;
} }
} }
#if 0
void M68360_insert_irq(irq_node_t **list, irq_node_t *node) void M68360_insert_irq(irq_node_t **list, irq_node_t *node)
{ {
unsigned long flags; unsigned long flags;
...@@ -178,9 +177,10 @@ void M68360_delete_irq(irq_node_t **list, void *dev_id) ...@@ -178,9 +177,10 @@ void M68360_delete_irq(irq_node_t **list, void *dev_id)
local_irq_restore(flags); local_irq_restore(flags);
printk ("%s: tried to remove invalid irq\n", __FUNCTION__); printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
} }
#endif
int M68360_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id) unsigned long flags, const char *devname, void *dev_id)
{ {
int mask = (1<<irq); int mask = (1<<irq);
...@@ -191,27 +191,22 @@ int M68360_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_ ...@@ -191,27 +191,22 @@ int M68360_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_
return -ENXIO; return -ENXIO;
} }
if (!int_irq_list[irq]) { if (!(int_irq_list[irq].flags & IRQ_FLG_STD)) {
int_irq_list[irq] = new_irq_node(); if (int_irq_list[irq].flags & IRQ_FLG_LOCK) {
int_irq_list[irq]->flags = IRQ_FLG_STD;
}
if (!(int_irq_list[irq]->flags & IRQ_FLG_STD)) {
if (int_irq_list[irq]->flags & IRQ_FLG_LOCK) {
printk("%s: IRQ %d from %s is not replaceable\n", printk("%s: IRQ %d from %s is not replaceable\n",
__FUNCTION__, irq, int_irq_list[irq]->devname); __FUNCTION__, irq, int_irq_list[irq].devname);
return -EBUSY; return -EBUSY;
} }
if (flags & IRQ_FLG_REPLACE) { if (flags & IRQ_FLG_REPLACE) {
printk("%s: %s can't replace IRQ %d from %s\n", printk("%s: %s can't replace IRQ %d from %s\n",
__FUNCTION__, devname, irq, int_irq_list[irq]->devname); __FUNCTION__, devname, irq, int_irq_list[irq].devname);
return -EBUSY; return -EBUSY;
} }
} }
int_irq_list[irq]->handler = handler; int_irq_list[irq].handler = handler;
int_irq_list[irq]->flags = flags; int_irq_list[irq].flags = flags;
int_irq_list[irq]->dev_id = dev_id; int_irq_list[irq].dev_id = dev_id;
int_irq_list[irq]->devname = devname; int_irq_list[irq].devname = devname;
/* enable in the CIMR */ /* enable in the CIMR */
if (!int_irq_ablecount[irq]) if (!int_irq_ablecount[irq])
...@@ -221,24 +216,25 @@ int M68360_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_ ...@@ -221,24 +216,25 @@ int M68360_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_
return 0; return 0;
} }
void M68360_free_irq(unsigned int irq, void *dev_id) void free_irq(unsigned int irq, void *dev_id)
{ {
if (irq >= INTERNAL_IRQS) { if (irq >= INTERNAL_IRQS) {
printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq); printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
return; return;
} }
if (int_irq_list[irq]->dev_id != dev_id) if (int_irq_list[irq].dev_id != dev_id)
printk("%s: removing probably wrong IRQ %d from %s\n", printk("%s: removing probably wrong IRQ %d from %s\n",
__FUNCTION__, irq, int_irq_list[irq]->devname); __FUNCTION__, irq, int_irq_list[irq].devname);
int_irq_list[irq]->handler = int_badint; int_irq_list[irq].handler = NULL;
int_irq_list[irq]->flags = IRQ_FLG_STD; int_irq_list[irq].flags = IRQ_FLG_STD;
int_irq_list[irq]->dev_id = NULL; int_irq_list[irq].dev_id = NULL;
int_irq_list[irq]->devname = NULL; int_irq_list[irq].devname = NULL;
*(volatile unsigned long *)0xfffff304 |= 1<<irq; *(volatile unsigned long *)0xfffff304 |= 1<<irq;
} }
#if 0
/* /*
* Enable/disable a particular machine specific interrupt source. * Enable/disable a particular machine specific interrupt source.
* Note that this may affect other interrupts in case of a shared interrupt. * Note that this may affect other interrupts in case of a shared interrupt.
...@@ -273,6 +269,27 @@ void M68360_disable_irq(unsigned int irq) ...@@ -273,6 +269,27 @@ void M68360_disable_irq(unsigned int irq)
/* disable the interrupt */ /* disable the interrupt */
*(volatile unsigned long *)0xfffff304 |= 1<<irq; *(volatile unsigned long *)0xfffff304 |= 1<<irq;
} }
#endif
int show_interrupts(struct seq_file *p, void *v)
{
int i;
for (i = 0; i < NR_IRQS; i++) {
if (int_irq_list[i].flags & IRQ_FLG_STD)
continue;
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);
}
seq_printf(p, " : %10u spurious\n", num_spurious);
return 0;
}
/* The 68k family did not have a good way to determine the source /* The 68k family did not have a good way to determine the source
* of interrupts until later in the family. The EC000 core does * of interrupts until later in the family. The EC000 core does
...@@ -280,7 +297,7 @@ void M68360_disable_irq(unsigned int irq) ...@@ -280,7 +297,7 @@ void M68360_disable_irq(unsigned int irq)
* into one vector and look in the blasted mask register... * into one vector and look in the blasted mask register...
* This code is designed to be fast, almost constant time, not clean! * This code is designed to be fast, almost constant time, not clean!
*/ */
void M68360_do_irq(int vec, struct pt_regs *fp) void process_int(int vec, struct pt_regs *fp)
{ {
int irq; int irq;
int mask; int mask;
...@@ -295,25 +312,14 @@ void M68360_do_irq(int vec, struct pt_regs *fp) ...@@ -295,25 +312,14 @@ void M68360_do_irq(int vec, struct pt_regs *fp)
/* Bugger all that weirdness. For the moment, I seem to know where I came from; /* 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. */ * vec is passed from a specific ISR, so I'll use it. */
if (int_irq_list[irq] && int_irq_list[irq]->handler) { if (int_irq_list[irq].handler) {
int_irq_list[irq]->handler(irq , int_irq_list[irq]->dev_id, fp); int_irq_list[irq].handler(irq , int_irq_list[irq].dev_id, fp);
int_irq_count[irq]++; kstat_cpu(0).irqs[irq]++;
pquicc->intr_cisr = (1 << vec); /* indicate that irq has been serviced */ pquicc->intr_cisr = (1 << vec); /* indicate that irq has been serviced */
} else { } else {
printk("unregistered interrupt %d!\nTurning it off in the CIMR...\n", irq); printk("unregistered interrupt %d!\nTurning it off in the CIMR...\n", irq);
/* *(volatile unsigned long *)0xfffff304 |= mask; */ /* *(volatile unsigned long *)0xfffff304 |= mask; */
pquicc->intr_cimr &= ~(1 << vec); pquicc->intr_cimr &= ~(1 << vec);
num_spurious += 1;
} }
} }
void config_M68360_irq(void)
{
mach_default_handler = NULL;
mach_init_IRQ = M68360_init_IRQ;
mach_request_irq = M68360_request_irq;
mach_free_irq = M68360_free_irq;
mach_enable_irq = M68360_enable_irq;
mach_disable_irq = M68360_disable_irq;
mach_process_int = M68360_do_irq;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment