forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
4.2 KiB
186 lines
4.2 KiB
/* |
|
* ints.c - Generic interrupt controller support |
|
* |
|
* This file is subject to the terms and conditions of the GNU General Public |
|
* License. See the file COPYING in the main directory of this archive |
|
* for more details. |
|
* |
|
* Copyright 1996 Roman Zippel |
|
* Copyright 1999 D. Jeff Dionne <[email protected]> |
|
*/ |
|
|
|
#include <linux/types.h> |
|
#include <linux/kernel.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> |
|
|
|
#if defined(CONFIG_M68328) |
|
#include <asm/MC68328.h> |
|
#elif defined(CONFIG_M68EZ328) |
|
#include <asm/MC68EZ328.h> |
|
#elif defined(CONFIG_M68VZ328) |
|
#include <asm/MC68VZ328.h> |
|
#endif |
|
|
|
/* assembler routines */ |
|
asmlinkage void system_call(void); |
|
asmlinkage void buserr(void); |
|
asmlinkage void trap(void); |
|
asmlinkage void trap3(void); |
|
asmlinkage void trap4(void); |
|
asmlinkage void trap5(void); |
|
asmlinkage void trap6(void); |
|
asmlinkage void trap7(void); |
|
asmlinkage void trap8(void); |
|
asmlinkage void trap9(void); |
|
asmlinkage void trap10(void); |
|
asmlinkage void trap11(void); |
|
asmlinkage void trap12(void); |
|
asmlinkage void trap13(void); |
|
asmlinkage void trap14(void); |
|
asmlinkage void trap15(void); |
|
asmlinkage void trap33(void); |
|
asmlinkage void trap34(void); |
|
asmlinkage void trap35(void); |
|
asmlinkage void trap36(void); |
|
asmlinkage void trap37(void); |
|
asmlinkage void trap38(void); |
|
asmlinkage void trap39(void); |
|
asmlinkage void trap40(void); |
|
asmlinkage void trap41(void); |
|
asmlinkage void trap42(void); |
|
asmlinkage void trap43(void); |
|
asmlinkage void trap44(void); |
|
asmlinkage void trap45(void); |
|
asmlinkage void trap46(void); |
|
asmlinkage void trap47(void); |
|
asmlinkage irqreturn_t bad_interrupt(int, void *); |
|
asmlinkage irqreturn_t inthandler(void); |
|
asmlinkage irqreturn_t inthandler1(void); |
|
asmlinkage irqreturn_t inthandler2(void); |
|
asmlinkage irqreturn_t inthandler3(void); |
|
asmlinkage irqreturn_t inthandler4(void); |
|
asmlinkage irqreturn_t inthandler5(void); |
|
asmlinkage irqreturn_t inthandler6(void); |
|
asmlinkage irqreturn_t inthandler7(void); |
|
|
|
/* 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 = ISR; |
|
|
|
while (pend) { |
|
if (pend & 0x0000ffff) { |
|
if (pend & 0x000000ff) { |
|
if (pend & 0x0000000f) { |
|
mask = 0x00000001; |
|
irq = 0; |
|
} else { |
|
mask = 0x00000010; |
|
irq = 4; |
|
} |
|
} else { |
|
if (pend & 0x00000f00) { |
|
mask = 0x00000100; |
|
irq = 8; |
|
} else { |
|
mask = 0x00001000; |
|
irq = 12; |
|
} |
|
} |
|
} else { |
|
if (pend & 0x00ff0000) { |
|
if (pend & 0x000f0000) { |
|
mask = 0x00010000; |
|
irq = 16; |
|
} else { |
|
mask = 0x00100000; |
|
irq = 20; |
|
} |
|
} else { |
|
if (pend & 0x0f000000) { |
|
mask = 0x01000000; |
|
irq = 24; |
|
} else { |
|
mask = 0x10000000; |
|
irq = 28; |
|
} |
|
} |
|
} |
|
|
|
while (! (mask & pend)) { |
|
mask <<=1; |
|
irq++; |
|
} |
|
|
|
do_IRQ(irq, fp); |
|
pend &= ~mask; |
|
} |
|
} |
|
|
|
static void intc_irq_unmask(struct irq_data *d) |
|
{ |
|
IMR &= ~(1 << d->irq); |
|
} |
|
|
|
static void intc_irq_mask(struct irq_data *d) |
|
{ |
|
IMR |= (1 << d->irq); |
|
} |
|
|
|
static struct irq_chip intc_irq_chip = { |
|
.name = "M68K-INTC", |
|
.irq_mask = intc_irq_mask, |
|
.irq_unmask = intc_irq_unmask, |
|
}; |
|
|
|
/* |
|
* This function should be called during kernel startup to initialize |
|
* the machine vector table. |
|
*/ |
|
void __init trap_init(void) |
|
{ |
|
int i; |
|
|
|
/* set up the vectors */ |
|
for (i = 72; i < 256; ++i) |
|
_ramvec[i] = (e_vector) bad_interrupt; |
|
|
|
_ramvec[32] = system_call; |
|
|
|
_ramvec[65] = (e_vector) inthandler1; |
|
_ramvec[66] = (e_vector) inthandler2; |
|
_ramvec[67] = (e_vector) inthandler3; |
|
_ramvec[68] = (e_vector) inthandler4; |
|
_ramvec[69] = (e_vector) inthandler5; |
|
_ramvec[70] = (e_vector) inthandler6; |
|
_ramvec[71] = (e_vector) inthandler7; |
|
} |
|
|
|
void __init init_IRQ(void) |
|
{ |
|
int i; |
|
|
|
IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */ |
|
|
|
/* turn off all interrupts */ |
|
IMR = ~0; |
|
|
|
for (i = 0; (i < NR_IRQS); i++) { |
|
irq_set_chip(i, &intc_irq_chip); |
|
irq_set_handler(i, handle_level_irq); |
|
} |
|
} |
|
|
|
|