2005-04-17 02:20:36 +04:00
/*
* linux / arch / alpha / kernel / irq_pyxis . c
*
* Based on code written by David A Rusling ( david . rusling @ reo . mts . dec . com ) .
*
* IRQ Code common to all PYXIS core logic chips .
*/
# include <linux/init.h>
# include <linux/sched.h>
# include <linux/irq.h>
# include <asm/io.h>
# include <asm/core_cia.h>
# include "proto.h"
# include "irq_impl.h"
/* Note mask bit is true for ENABLED irqs. */
static unsigned long cached_irq_mask ;
static inline void
pyxis_update_irq_hw ( unsigned long mask )
{
* ( vulp ) PYXIS_INT_MASK = mask ;
mb ( ) ;
* ( vulp ) PYXIS_INT_MASK ;
}
static inline void
2011-02-06 17:32:23 +03:00
pyxis_enable_irq ( struct irq_data * d )
2005-04-17 02:20:36 +04:00
{
2011-02-06 17:32:23 +03:00
pyxis_update_irq_hw ( cached_irq_mask | = 1UL < < ( d - > irq - 16 ) ) ;
2005-04-17 02:20:36 +04:00
}
static void
2011-02-06 17:32:23 +03:00
pyxis_disable_irq ( struct irq_data * d )
2005-04-17 02:20:36 +04:00
{
2011-02-06 17:32:23 +03:00
pyxis_update_irq_hw ( cached_irq_mask & = ~ ( 1UL < < ( d - > irq - 16 ) ) ) ;
2005-04-17 02:20:36 +04:00
}
static void
2011-02-06 17:32:23 +03:00
pyxis_mask_and_ack_irq ( struct irq_data * d )
2005-04-17 02:20:36 +04:00
{
2011-02-06 17:32:23 +03:00
unsigned long bit = 1UL < < ( d - > irq - 16 ) ;
2005-04-17 02:20:36 +04:00
unsigned long mask = cached_irq_mask & = ~ bit ;
/* Disable the interrupt. */
* ( vulp ) PYXIS_INT_MASK = mask ;
wmb ( ) ;
/* Ack PYXIS PCI interrupt. */
* ( vulp ) PYXIS_INT_REQ = bit ;
mb ( ) ;
/* Re-read to force both writes. */
* ( vulp ) PYXIS_INT_MASK ;
}
2009-06-17 02:33:25 +04:00
static struct irq_chip pyxis_irq_type = {
2009-12-01 06:51:31 +03:00
. name = " PYXIS " ,
2011-02-06 17:32:23 +03:00
. irq_mask_ack = pyxis_mask_and_ack_irq ,
. irq_mask = pyxis_disable_irq ,
. irq_unmask = pyxis_enable_irq ,
2005-04-17 02:20:36 +04:00
} ;
void
2006-10-08 17:36:08 +04:00
pyxis_device_interrupt ( unsigned long vector )
2005-04-17 02:20:36 +04:00
{
unsigned long pld ;
unsigned int i ;
/* Read the interrupt summary register of PYXIS */
pld = * ( vulp ) PYXIS_INT_REQ ;
pld & = cached_irq_mask ;
/*
* Now for every possible bit set , work through them and call
* the appropriate interrupt handler .
*/
while ( pld ) {
i = ffz ( ~ pld ) ;
pld & = pld - 1 ; /* clear least bit set */
if ( i = = 7 )
2006-10-08 17:36:08 +04:00
isa_device_interrupt ( vector ) ;
2005-04-17 02:20:36 +04:00
else
2006-10-08 17:37:32 +04:00
handle_irq ( 16 + i ) ;
2005-04-17 02:20:36 +04:00
}
}
void __init
init_pyxis_irqs ( unsigned long ignore_mask )
{
long i ;
* ( vulp ) PYXIS_INT_MASK = 0 ; /* disable all */
* ( vulp ) PYXIS_INT_REQ = - 1 ; /* flush all */
mb ( ) ;
/* Send -INTA pulses to clear any pending interrupts ...*/
* ( vuip ) CIA_IACK_SC ;
for ( i = 16 ; i < 48 ; + + i ) {
if ( ( ignore_mask > > i ) & 1 )
continue ;
2011-03-26 00:17:31 +03:00
irq_set_chip_and_handler ( i , & pyxis_irq_type , handle_level_irq ) ;
2011-02-06 17:32:23 +03:00
irq_set_status_flags ( i , IRQ_LEVEL ) ;
2005-04-17 02:20:36 +04:00
}
setup_irq ( 16 + 7 , & isa_cascade_irqaction ) ;
}