2005-04-16 15:20:36 -07:00
/*
* Carsten Langgaard , carstenl @ mips . com
* Copyright ( C ) 2002 MIPS Technologies , Inc . All rights reserved .
* Copyright ( C ) 2003 Ralf Baechle ( ralf @ linux - mips . org )
2005-02-04 01:34:52 +00:00
* Copyright ( C ) 2004 Maciej W . Rozycki
2005-04-16 15:20:36 -07:00
*
* 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 .
*
* Routines for generic manipulation of the interrupts found on the MIPS
* Sead board .
*/
# include <linux/init.h>
2007-01-08 01:27:40 +09:00
# include <linux/interrupt.h>
2005-02-04 01:34:52 +00:00
# include <asm/irq_cpu.h>
2006-04-03 17:56:36 +01:00
# include <asm/mipsregs.h>
2005-02-04 01:34:52 +00:00
# include <asm/system.h>
2005-04-16 15:20:36 -07:00
# include <asm/mips-boards/seadint.h>
2006-04-03 17:56:36 +01:00
static inline int clz ( unsigned long x )
{
2007-10-11 23:46:15 +01:00
__asm__ (
2006-04-03 17:56:36 +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
}
/*
* IRQs on the SEAD board look basically are combined together on hardware
* interrupt 0 ( MIPS IRQ 2 ) ) like :
*
* MIPS IRQ Source
* - - - - - - - - - - - - - -
* 0 Software ( ignored )
* 1 Software ( ignored )
* 2 UART0 ( hw0 )
* 3 UART1 ( hw1 )
* 4 Hardware ( ignored )
* 5 Hardware ( ignored )
* 6 Hardware ( ignored )
* 7 R4k timer ( what we use )
*
* We handle the IRQ according to _our_ priority which is :
*
* Highest - - - - R4k Timer
* Lowest - - - - Combined hardware interrupt
*
* then we just return , if multiple IRQs are pending then we will just take
* another exception , big deal .
*/
2006-10-07 19:44:33 +01:00
asmlinkage void plat_irq_dispatch ( void )
2006-04-03 17:56:36 +01:00
{
unsigned int pending = read_c0_cause ( ) & read_c0_status ( ) & ST0_IM ;
int irq ;
irq = irq_ffs ( pending ) ;
if ( irq > = 0 )
2007-06-20 22:27:10 +01:00
do_IRQ ( MIPS_CPU_IRQ_BASE + irq ) ;
2006-04-03 17:56:36 +01:00
else
2007-01-08 01:27:40 +09:00
spurious_interrupt ( ) ;
2006-04-03 17:56:36 +01:00
}
2005-04-16 15:20:36 -07:00
void __init arch_init_irq ( void )
{
2007-01-08 02:14:29 +09:00
mips_cpu_irq_init ( ) ;
2005-04-16 15:20:36 -07:00
}