2007-07-10 17:32:56 +01:00
/*
* Copyright ( C ) 1999 , 2005 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 .
*
*/
# include <linux/init.h>
# include <linux/sched.h>
# include <linux/interrupt.h>
# include <linux/kernel_stat.h>
# include <asm/mips-boards/simint.h>
# include <asm/irq_cpu.h>
static inline int clz ( unsigned long x )
{
2007-10-11 23:46:15 +01:00
__asm__ (
2007-07-10 17:32:56 +01:00
" .set push \n "
" .set mips32 \n "
" clz %0, %1 \n "
" .set pop \n "
: " =r " ( x )
: " r " ( x ) ) ;
return x ;
}
/*
* Version of ffs that only looks at bits 12. .15 .
*/
static inline unsigned int irq_ffs ( unsigned int pending )
{
# if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
return - clz ( pending ) + 31 - CAUSEB_IP ;
# else
unsigned int a0 = 7 ;
unsigned int t0 ;
t0 = s0 & 0xf000 ;
t0 = t0 < 1 ;
t0 = t0 < < 2 ;
a0 = a0 - t0 ;
s0 = s0 < < t0 ;
t0 = s0 & 0xc000 ;
t0 = t0 < 1 ;
t0 = t0 < < 1 ;
a0 = a0 - t0 ;
s0 = s0 < < t0 ;
t0 = s0 & 0x8000 ;
t0 = t0 < 1 ;
/* t0 = t0 << 2; */
a0 = a0 - t0 ;
/* s0 = s0 << t0; */
return a0 ;
# endif
}
asmlinkage void plat_irq_dispatch ( void )
{
unsigned int pending = read_c0_cause ( ) & read_c0_status ( ) & ST0_IM ;
int irq ;
irq = irq_ffs ( pending ) ;
if ( irq > 0 )
2007-07-12 17:41:14 +01:00
do_IRQ ( MIPS_CPU_IRQ_BASE + irq ) ;
2007-07-10 17:32:56 +01:00
else
spurious_interrupt ( ) ;
}
void __init arch_init_irq ( void )
{
mips_cpu_irq_init ( ) ;
}