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 )
*/
# include <linux/stddef.h>
# include <linux/init.h>
# include <linux/spinlock.h>
2008-08-27 15:05:35 +04:00
# include <linux/of.h>
# include <linux/of_device.h>
2011-07-18 23:57:46 +04:00
# include <linux/export.h>
2005-04-17 02:20:36 +04:00
# include <asm/oplib.h>
# include <asm/io.h>
# include <asm/auxio.h>
# include <asm/string.h> /* memset(), Linux has no bzero() */
2012-03-28 21:30:03 +04:00
# include <asm/cpu_type.h>
2005-04-17 02:20:36 +04:00
/* Probe and map in the Auxiliary I/O register */
/* auxio_register is not static because it is referenced
* in entry . S : : floppy_tdone
*/
void __iomem * auxio_register = NULL ;
static DEFINE_SPINLOCK ( auxio_lock ) ;
void __init auxio_probe ( void )
{
2010-10-09 01:18:11 +04:00
phandle node , auxio_nd ;
2005-04-17 02:20:36 +04:00
struct linux_prom_registers auxregs [ 1 ] ;
struct resource r ;
switch ( sparc_cpu_model ) {
2009-11-13 08:21:22 +03:00
case sparc_leon :
2005-04-17 02:20:36 +04:00
case sun4d :
return ;
default :
break ;
}
node = prom_getchild ( prom_root_node ) ;
auxio_nd = prom_searchsiblings ( node , " auxiliary-io " ) ;
if ( ! auxio_nd ) {
node = prom_searchsiblings ( node , " obio " ) ;
node = prom_getchild ( node ) ;
auxio_nd = prom_searchsiblings ( node , " auxio " ) ;
if ( ! auxio_nd ) {
# ifdef CONFIG_PCI
/* There may be auxio on Ebus */
return ;
# else
if ( prom_searchsiblings ( node , " leds " ) ) {
/* VME chassis sun4m machine, no auxio exists. */
return ;
}
prom_printf ( " Cannot find auxio node, cannot continue... \n " ) ;
prom_halt ( ) ;
# endif
}
}
if ( prom_getproperty ( auxio_nd , " reg " , ( char * ) auxregs , sizeof ( auxregs ) ) < = 0 )
return ;
prom_apply_obio_ranges ( auxregs , 0x1 ) ;
/* Map the register both read and write */
r . flags = auxregs [ 0 ] . which_io & 0xF ;
r . start = auxregs [ 0 ] . phys_addr ;
r . end = auxregs [ 0 ] . phys_addr + auxregs [ 0 ] . reg_size - 1 ;
2008-08-27 15:05:35 +04:00
auxio_register = of_ioremap ( & r , 0 , auxregs [ 0 ] . reg_size , " auxio " ) ;
2012-05-12 11:23:23 +04:00
/* Fix the address on sun4m. */
if ( ( ( ( unsigned long ) auxregs [ 0 ] . phys_addr ) & 3 ) = = 3 )
2005-04-17 02:20:36 +04:00
auxio_register + = ( 3 - ( ( unsigned long ) auxio_register & 3 ) ) ;
set_auxio ( AUXIO_LED , 0 ) ;
}
unsigned char get_auxio ( void )
{
if ( auxio_register )
return sbus_readb ( auxio_register ) ;
return 0 ;
}
2009-01-09 03:58:05 +03:00
EXPORT_SYMBOL ( get_auxio ) ;
2005-04-17 02:20:36 +04:00
void set_auxio ( unsigned char bits_on , unsigned char bits_off )
{
unsigned char regval ;
unsigned long flags ;
spin_lock_irqsave ( & auxio_lock , flags ) ;
2012-05-12 11:23:23 +04:00
switch ( sparc_cpu_model ) {
2005-04-17 02:20:36 +04:00
case sun4m :
if ( ! auxio_register )
2007-05-12 00:51:23 +04:00
break ; /* VME chassis sun4m, no auxio. */
2005-04-17 02:20:36 +04:00
regval = sbus_readb ( auxio_register ) ;
sbus_writeb ( ( ( regval | bits_on ) & ~ bits_off ) | AUXIO_ORMEIN4M ,
auxio_register ) ;
break ;
case sun4d :
break ;
default :
panic ( " Can't set AUXIO register on this machine. " ) ;
2011-06-03 18:45:23 +04:00
}
2005-04-17 02:20:36 +04:00
spin_unlock_irqrestore ( & auxio_lock , flags ) ;
}
2009-01-09 03:58:05 +03:00
EXPORT_SYMBOL ( set_auxio ) ;
2005-04-17 02:20:36 +04:00
/* sun4m power control register (AUXIO2) */
volatile unsigned char * auxio_power_register = NULL ;
void __init auxio_power_probe ( void )
{
struct linux_prom_registers regs ;
2010-10-09 01:18:11 +04:00
phandle node ;
2005-04-17 02:20:36 +04:00
struct resource r ;
/* Attempt to find the sun4m power control node. */
node = prom_getchild ( prom_root_node ) ;
node = prom_searchsiblings ( node , " obio " ) ;
node = prom_getchild ( node ) ;
node = prom_searchsiblings ( node , " power " ) ;
2010-11-12 09:42:06 +03:00
if ( node = = 0 | | ( s32 ) node = = - 1 )
2005-04-17 02:20:36 +04:00
return ;
/* Map the power control register. */
if ( prom_getproperty ( node , " reg " , ( char * ) & regs , sizeof ( regs ) ) < = 0 )
return ;
prom_apply_obio_ranges ( & regs , 1 ) ;
memset ( & r , 0 , sizeof ( r ) ) ;
r . flags = regs . which_io & 0xF ;
r . start = regs . phys_addr ;
r . end = regs . phys_addr + regs . reg_size - 1 ;
2008-08-27 15:05:35 +04:00
auxio_power_register = ( unsigned char * ) of_ioremap ( & r , 0 ,
2005-04-17 02:20:36 +04:00
regs . reg_size , " auxpower " ) ;
/* Display a quick message on the console. */
if ( auxio_power_register )
printk ( KERN_INFO " Power off control detected. \n " ) ;
}