2005-04-16 15:20:36 -07:00
/*
2012-12-04 23:04:49 +00:00
* ints . c - Generic interrupt controller support
2005-04-16 15:20:36 -07:00
*
* 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 < jeff @ rt - control . com >
*/
# include <linux/types.h>
# include <linux/kernel.h>
2007-07-19 01:49:12 -07:00
# include <linux/init.h>
2007-03-07 11:28:13 +10:00
# include <linux/interrupt.h>
2007-07-19 01:49:12 -07:00
# include <linux/irq.h>
2005-04-16 15:20:36 -07:00
# 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 ) ;
2007-03-07 11:28:13 +10:00
asmlinkage irqreturn_t bad_interrupt ( int , void * ) ;
2005-04-16 15:20:36 -07:00
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 + + ;
}
2007-07-19 01:49:12 -07:00
do_IRQ ( irq , fp ) ;
2005-04-16 15:20:36 -07:00
pend & = ~ mask ;
}
}
2007-07-19 01:49:12 -07:00
2011-02-06 23:39:14 +00:00
static void intc_irq_unmask ( struct irq_data * d )
2007-07-19 01:49:12 -07:00
{
2011-02-06 23:39:14 +00:00
IMR & = ~ ( 1 < < d - > irq ) ;
2007-07-19 01:49:12 -07:00
}
2011-02-06 23:39:14 +00:00
static void intc_irq_mask ( struct irq_data * d )
2007-07-19 01:49:12 -07:00
{
2011-02-06 23:39:14 +00:00
IMR | = ( 1 < < d - > irq ) ;
2007-07-19 01:49:12 -07:00
}
2009-05-01 16:54:49 +10:00
static struct irq_chip intc_irq_chip = {
. name = " M68K-INTC " ,
2011-02-06 23:39:14 +00:00
. irq_mask = intc_irq_mask ,
. irq_unmask = intc_irq_unmask ,
2009-05-01 16:54:49 +10:00
} ;
/*
* This function should be called during kernel startup to initialize
* the machine vector table .
*/
2011-06-23 15:52:25 +10:00
void __init trap_init ( void )
2007-07-19 01:49:12 -07:00
{
2009-05-01 16:54:49 +10:00
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 ;
2011-06-23 15:52:25 +10:00
}
void __init init_IRQ ( void )
{
int i ;
2009-05-01 16:54:49 +10:00
IVR = 0x40 ; /* Set DragonBall IVR (interrupt base) to 64 */
/* turn off all interrupts */
IMR = ~ 0 ;
for ( i = 0 ; ( i < NR_IRQS ) ; i + + ) {
2011-03-28 13:31:17 +02:00
irq_set_chip ( i , & intc_irq_chip ) ;
irq_set_handler ( i , handle_level_irq ) ;
2009-05-01 16:54:49 +10:00
}
2007-07-19 01:49:12 -07:00
}