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 ( C ) 1992 Linus Torvalds
* Copyright ( C ) 1994 - 2001 , 2003 Ralf Baechle
*/
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/kernel.h>
# include <linux/spinlock.h>
# include <asm/i8259.h>
# include <asm/io.h>
# include <asm/jazz.h>
static DEFINE_SPINLOCK ( r4030_lock ) ;
static void enable_r4030_irq ( unsigned int irq )
{
unsigned int mask = 1 < < ( irq - JAZZ_PARALLEL_IRQ ) ;
unsigned long flags ;
spin_lock_irqsave ( & r4030_lock , flags ) ;
mask | = r4030_read_reg16 ( JAZZ_IO_IRQ_ENABLE ) ;
r4030_write_reg16 ( JAZZ_IO_IRQ_ENABLE , mask ) ;
spin_unlock_irqrestore ( & r4030_lock , flags ) ;
}
void disable_r4030_irq ( unsigned int irq )
{
unsigned int mask = ~ ( 1 < < ( irq - JAZZ_PARALLEL_IRQ ) ) ;
unsigned long flags ;
spin_lock_irqsave ( & r4030_lock , flags ) ;
mask & = r4030_read_reg16 ( JAZZ_IO_IRQ_ENABLE ) ;
r4030_write_reg16 ( JAZZ_IO_IRQ_ENABLE , mask ) ;
spin_unlock_irqrestore ( & r4030_lock , flags ) ;
}
static void end_r4030_irq ( unsigned int irq )
{
if ( ! ( irq_desc [ irq ] . status & ( IRQ_DISABLED | IRQ_INPROGRESS ) ) )
enable_r4030_irq ( irq ) ;
}
2006-07-02 14:41:42 +01:00
static struct irq_chip r4030_irq_type = {
2005-02-28 13:39:57 +00:00
. typename = " R4030 " ,
2006-11-02 02:08:36 +09:00
. ack = disable_r4030_irq ,
. mask = disable_r4030_irq ,
. mask_ack = disable_r4030_irq ,
. unmask = enable_r4030_irq ,
2005-02-28 13:39:57 +00:00
. end = end_r4030_irq ,
2005-04-16 15:20:36 -07:00
} ;
void __init init_r4030_ints ( void )
{
int i ;
2006-11-02 02:08:36 +09:00
for ( i = JAZZ_PARALLEL_IRQ ; i < = JAZZ_TIMER_IRQ ; i + + )
set_irq_chip ( i , & r4030_irq_type ) ;
2005-04-16 15:20:36 -07:00
r4030_write_reg16 ( JAZZ_IO_IRQ_ENABLE , 0 ) ;
r4030_read_reg16 ( JAZZ_IO_IRQ_SOURCE ) ; /* clear pending IRQs */
r4030_read_reg32 ( JAZZ_R4030_INVAL_ADDR ) ; /* clear error bits */
}
/*
* On systems with i8259 - style interrupt controllers we assume for
* driver compatibility reasons interrupts 0 - 15 to be the i8259
* interrupts even if the hardware uses a different interrupt numbering .
*/
void __init arch_init_irq ( void )
{
init_i8259_irqs ( ) ; /* Integrated i8259 */
init_r4030_ints ( ) ;
change_c0_status ( ST0_IM , IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1 ) ;
}
2006-04-03 17:56:36 +01:00
2006-10-07 19:44:33 +01:00
static void loc_call ( unsigned int irq , unsigned int mask )
2006-04-03 17:56:36 +01:00
{
r4030_write_reg16 ( JAZZ_IO_IRQ_ENABLE ,
r4030_read_reg16 ( JAZZ_IO_IRQ_ENABLE ) & mask ) ;
2006-10-07 19:44:33 +01:00
do_IRQ ( irq ) ;
2006-04-03 17:56:36 +01:00
r4030_write_reg16 ( JAZZ_IO_IRQ_ENABLE ,
r4030_read_reg16 ( JAZZ_IO_IRQ_ENABLE ) | mask ) ;
}
2006-10-07 19:44:33 +01:00
static void ll_local_dev ( void )
2006-04-03 17:56:36 +01:00
{
switch ( r4030_read_reg32 ( JAZZ_IO_IRQ_SOURCE ) ) {
case 0 :
panic ( " Unimplemented loc_no_irq handler " ) ;
break ;
case 4 :
2006-10-07 19:44:33 +01:00
loc_call ( JAZZ_PARALLEL_IRQ , JAZZ_IE_PARALLEL ) ;
2006-04-03 17:56:36 +01:00
break ;
case 8 :
2006-10-07 19:44:33 +01:00
loc_call ( JAZZ_PARALLEL_IRQ , JAZZ_IE_FLOPPY ) ;
2006-04-03 17:56:36 +01:00
break ;
case 12 :
panic ( " Unimplemented loc_sound handler " ) ;
break ;
case 16 :
panic ( " Unimplemented loc_video handler " ) ;
break ;
case 20 :
2006-10-07 19:44:33 +01:00
loc_call ( JAZZ_ETHERNET_IRQ , JAZZ_IE_ETHERNET ) ;
2006-04-03 17:56:36 +01:00
break ;
case 24 :
2006-10-07 19:44:33 +01:00
loc_call ( JAZZ_SCSI_IRQ , JAZZ_IE_SCSI ) ;
2006-04-03 17:56:36 +01:00
break ;
case 28 :
2006-10-07 19:44:33 +01:00
loc_call ( JAZZ_KEYBOARD_IRQ , JAZZ_IE_KEYBOARD ) ;
2006-04-03 17:56:36 +01:00
break ;
case 32 :
2006-10-07 19:44:33 +01:00
loc_call ( JAZZ_MOUSE_IRQ , JAZZ_IE_MOUSE ) ;
2006-04-03 17:56:36 +01:00
break ;
case 36 :
2006-10-07 19:44:33 +01:00
loc_call ( JAZZ_SERIAL1_IRQ , JAZZ_IE_SERIAL1 ) ;
2006-04-03 17:56:36 +01:00
break ;
case 40 :
2006-10-07 19:44:33 +01:00
loc_call ( JAZZ_SERIAL2_IRQ , JAZZ_IE_SERIAL2 ) ;
2006-04-03 17:56:36 +01:00
break ;
}
}
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 ;
if ( pending & IE_IRQ5 )
write_c0_compare ( 0 ) ;
else if ( pending & IE_IRQ4 ) {
r4030_read_reg32 ( JAZZ_TIMER_REGISTER ) ;
2006-10-07 19:44:33 +01:00
do_IRQ ( JAZZ_TIMER_IRQ ) ;
2006-04-03 17:56:36 +01:00
} else if ( pending & IE_IRQ3 )
panic ( " Unimplemented ISA NMI handler " ) ;
else if ( pending & IE_IRQ2 )
2006-10-07 19:44:33 +01:00
do_IRQ ( r4030_read_reg32 ( JAZZ_EISA_IRQ_ACK ) ) ;
2006-04-03 17:56:36 +01:00
else if ( pending & IE_IRQ1 ) {
2006-10-07 19:44:33 +01:00
ll_local_dev ( ) ;
2006-04-03 17:56:36 +01:00
} else if ( unlikely ( pending & IE_IRQ0 ) )
panic ( " Unimplemented local_dma handler " ) ;
else if ( pending & IE_SW1 ) {
clear_c0_cause ( IE_SW1 ) ;
panic ( " Unimplemented sw1 handler " ) ;
} else if ( pending & IE_SW0 ) {
clear_c0_cause ( IE_SW0 ) ;
panic ( " Unimplemented sw0 handler " ) ;
}
}