2005-04-17 02:20:36 +04:00
/*
* Carsten Langgaard , carstenl @ mips . com
* Copyright ( C ) 1999 , 2000 MIPS Technologies , Inc . All rights reserved .
*
* This program is free software ; you can distribute it and / or modify it
* under the terms of the GNU General Public License ( Version 2 ) as
* published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 59 Temple Place - Suite 330 , Boston MA 02111 - 1307 , USA .
*
2005-09-04 02:56:17 +04:00
* Routines for generic manipulation of the interrupts found on the
2005-04-17 02:20:36 +04:00
* Lasat boards .
*/
# include <linux/init.h>
# include <linux/sched.h>
# include <linux/slab.h>
# include <linux/interrupt.h>
# include <linux/kernel_stat.h>
# include <asm/bootinfo.h>
# include <asm/irq.h>
# include <asm/lasat/lasatint.h>
2006-04-03 20:56:36 +04:00
# include <asm/time.h>
2005-04-17 02:20:36 +04:00
# include <asm/gdb-stub.h>
static volatile int * lasat_int_status = NULL ;
static volatile int * lasat_int_mask = NULL ;
static volatile int lasat_int_mask_shift ;
void disable_lasat_irq ( unsigned int irq_nr )
{
* lasat_int_mask & = ~ ( 1 < < irq_nr ) < < lasat_int_mask_shift ;
}
void enable_lasat_irq ( unsigned int irq_nr )
{
* lasat_int_mask | = ( 1 < < irq_nr ) < < lasat_int_mask_shift ;
}
2006-07-02 17:41:42 +04:00
static struct irq_chip lasat_irq_type = {
2007-01-14 18:07:25 +03:00
. name = " Lasat " ,
2006-11-01 20:08:36 +03:00
. ack = disable_lasat_irq ,
. mask = disable_lasat_irq ,
. mask_ack = disable_lasat_irq ,
. unmask = enable_lasat_irq ,
2005-04-17 02:20:36 +04:00
} ;
static inline int ls1bit32 ( unsigned int x )
{
int b = 31 , s ;
s = 16 ; if ( x < < 16 = = 0 ) s = 0 ; b - = s ; x < < = s ;
s = 8 ; if ( x < < 8 = = 0 ) s = 0 ; b - = s ; x < < = s ;
s = 4 ; if ( x < < 4 = = 0 ) s = 0 ; b - = s ; x < < = s ;
s = 2 ; if ( x < < 2 = = 0 ) s = 0 ; b - = s ; x < < = s ;
s = 1 ; if ( x < < 1 = = 0 ) s = 0 ; b - = s ;
return b ;
}
static unsigned long ( * get_int_status ) ( void ) ;
static unsigned long get_int_status_100 ( void )
{
return * lasat_int_status & * lasat_int_mask ;
}
2005-09-04 02:56:17 +04:00
static unsigned long get_int_status_200 ( void )
2005-04-17 02:20:36 +04:00
{
unsigned long int_status ;
int_status = * lasat_int_status ;
int_status & = ( int_status > > LASATINT_MASK_SHIFT_200 ) & 0xffff ;
return int_status ;
}
2006-10-07 22:44:33 +04:00
asmlinkage void plat_irq_dispatch ( void )
2005-04-17 02:20:36 +04:00
{
unsigned long int_status ;
2006-04-03 20:56:36 +04:00
unsigned int cause = read_c0_cause ( ) ;
2005-04-17 02:20:36 +04:00
int irq ;
2006-04-03 20:56:36 +04:00
if ( cause & CAUSEF_IP7 ) { /* R4000 count / compare IRQ */
2006-10-07 22:44:33 +04:00
ll_timer_interrupt ( 7 ) ;
2006-04-03 20:56:36 +04:00
return ;
}
2005-04-17 02:20:36 +04:00
int_status = get_int_status ( ) ;
/* if int_status == 0, then the interrupt has already been cleared */
if ( int_status ) {
irq = ls1bit32 ( int_status ) ;
2006-10-07 22:44:33 +04:00
do_IRQ ( irq ) ;
2005-04-17 02:20:36 +04:00
}
}
void __init arch_init_irq ( void )
{
int i ;
switch ( mips_machtype ) {
case MACH_LASAT_100 :
lasat_int_status = ( void * ) LASAT_INT_STATUS_REG_100 ;
lasat_int_mask = ( void * ) LASAT_INT_MASK_REG_100 ;
lasat_int_mask_shift = LASATINT_MASK_SHIFT_100 ;
get_int_status = get_int_status_100 ;
* lasat_int_mask = 0 ;
break ;
case MACH_LASAT_200 :
lasat_int_status = ( void * ) LASAT_INT_STATUS_REG_200 ;
lasat_int_mask = ( void * ) LASAT_INT_MASK_REG_200 ;
lasat_int_mask_shift = LASATINT_MASK_SHIFT_200 ;
get_int_status = get_int_status_200 ;
* lasat_int_mask & = 0xffff ;
break ;
default :
panic ( " arch_init_irq: mips_machtype incorrect " ) ;
}
2006-11-01 20:08:36 +03:00
for ( i = 0 ; i < = LASATINT_END ; i + + )
2006-11-13 19:13:18 +03:00
set_irq_chip_and_handler ( i , & lasat_irq_type , handle_level_irq ) ;
2005-04-17 02:20:36 +04:00
}