2005-04-17 02:20:36 +04:00
/* auxio.c: Probing for the Sparc AUXIO register at boot time.
*
* Copyright ( C ) 1996 David S . Miller ( davem @ caip . rutgers . edu )
*
* Refactoring for unified NCR / PCIO support 2002 Eric Brower ( ebrower @ usa . net )
*/
# include <linux/config.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/ioport.h>
# include <asm/oplib.h>
# include <asm/io.h>
# include <asm/sbus.h>
# include <asm/ebus.h>
# include <asm/auxio.h>
2005-06-28 04:04:45 +04:00
/* This cannot be static, as it is referenced in irq.c */
2005-04-17 02:20:36 +04:00
void __iomem * auxio_register = NULL ;
enum auxio_type {
AUXIO_TYPE_NODEV ,
AUXIO_TYPE_SBUS ,
AUXIO_TYPE_EBUS
} ;
static enum auxio_type auxio_devtype = AUXIO_TYPE_NODEV ;
static DEFINE_SPINLOCK ( auxio_lock ) ;
static void __auxio_sbus_set ( u8 bits_on , u8 bits_off )
{
if ( auxio_register ) {
unsigned char regval ;
unsigned long flags ;
unsigned char newval ;
spin_lock_irqsave ( & auxio_lock , flags ) ;
regval = sbus_readb ( auxio_register ) ;
newval = regval | bits_on ;
newval & = ~ bits_off ;
newval & = ~ AUXIO_AUX1_MASK ;
sbus_writeb ( newval , auxio_register ) ;
spin_unlock_irqrestore ( & auxio_lock , flags ) ;
}
}
static void __auxio_ebus_set ( u8 bits_on , u8 bits_off )
{
if ( auxio_register ) {
unsigned char regval ;
unsigned long flags ;
unsigned char newval ;
spin_lock_irqsave ( & auxio_lock , flags ) ;
regval = ( u8 ) readl ( auxio_register ) ;
newval = regval | bits_on ;
newval & = ~ bits_off ;
writel ( ( u32 ) newval , auxio_register ) ;
spin_unlock_irqrestore ( & auxio_lock , flags ) ;
}
}
static inline void __auxio_ebus_set_led ( int on )
{
( on ) ? __auxio_ebus_set ( AUXIO_PCIO_LED , 0 ) :
__auxio_ebus_set ( 0 , AUXIO_PCIO_LED ) ;
}
static inline void __auxio_sbus_set_led ( int on )
{
( on ) ? __auxio_sbus_set ( AUXIO_AUX1_LED , 0 ) :
__auxio_sbus_set ( 0 , AUXIO_AUX1_LED ) ;
}
void auxio_set_led ( int on )
{
switch ( auxio_devtype ) {
case AUXIO_TYPE_SBUS :
__auxio_sbus_set_led ( on ) ;
break ;
case AUXIO_TYPE_EBUS :
__auxio_ebus_set_led ( on ) ;
break ;
default :
break ;
}
}
static inline void __auxio_sbus_set_lte ( int on )
{
( on ) ? __auxio_sbus_set ( AUXIO_AUX1_LTE , 0 ) :
__auxio_sbus_set ( 0 , AUXIO_AUX1_LTE ) ;
}
void auxio_set_lte ( int on )
{
switch ( auxio_devtype ) {
case AUXIO_TYPE_SBUS :
__auxio_sbus_set_lte ( on ) ;
break ;
case AUXIO_TYPE_EBUS :
/* FALL-THROUGH */
default :
break ;
}
}
void __init auxio_probe ( void )
{
struct sbus_bus * sbus ;
struct sbus_dev * sdev = NULL ;
for_each_sbus ( sbus ) {
for_each_sbusdev ( sdev , sbus ) {
if ( ! strcmp ( sdev - > prom_name , " auxio " ) )
goto found_sdev ;
}
}
found_sdev :
if ( sdev ) {
auxio_devtype = AUXIO_TYPE_SBUS ;
auxio_register = sbus_ioremap ( & sdev - > resource [ 0 ] , 0 ,
sdev - > reg_addrs [ 0 ] . reg_size ,
" auxiliaryIO " ) ;
}
# ifdef CONFIG_PCI
else {
struct linux_ebus * ebus ;
struct linux_ebus_device * edev = NULL ;
for_each_ebus ( ebus ) {
for_each_ebusdev ( edev , ebus ) {
2006-06-23 06:12:03 +04:00
if ( ! strcmp ( edev - > prom_node - > name , " auxio " ) )
2005-04-17 02:20:36 +04:00
goto ebus_done ;
}
}
ebus_done :
if ( edev ) {
auxio_devtype = AUXIO_TYPE_EBUS ;
auxio_register =
ioremap ( edev - > resource [ 0 ] . start , sizeof ( u32 ) ) ;
}
}
auxio_set_led ( AUXIO_LED_ON ) ;
# endif
}