2005-04-17 02:20:36 +04:00
/* devices.c: Initial scan of the prom device tree for important
* Sparc device nodes which we need to find .
*
* This is based on the sparc64 version , but sun4m doesn ' t always use
* the hardware MIDs , so be careful .
*
* Copyright ( C ) 1996 David S . Miller ( davem @ caip . rutgers . edu )
*/
# include <linux/kernel.h>
# include <linux/threads.h>
# include <linux/string.h>
# include <linux/init.h>
# include <linux/errno.h>
# include <asm/page.h>
# include <asm/oplib.h>
2006-07-18 08:49:58 +04:00
# include <asm/prom.h>
2005-04-17 02:20:36 +04:00
# include <asm/smp.h>
# include <asm/cpudata.h>
2012-03-28 21:30:03 +04:00
# include <asm/cpu_type.h>
2005-04-17 02:20:36 +04:00
extern void clock_stop_probe ( void ) ; /* tadpole.c */
static char * cpu_mid_prop ( void )
{
if ( sparc_cpu_model = = sun4d )
return " cpu-id " ;
return " mid " ;
}
2010-10-09 01:18:11 +04:00
static int check_cpu_node ( phandle nd , int * cur_inst ,
int ( * compare ) ( phandle , int , void * ) , void * compare_arg ,
phandle * prom_node , int * mid )
2005-04-17 02:20:36 +04:00
{
if ( ! compare ( nd , * cur_inst , compare_arg ) ) {
if ( prom_node )
* prom_node = nd ;
if ( mid ) {
* mid = prom_getintdefault ( nd , cpu_mid_prop ( ) , 0 ) ;
if ( sparc_cpu_model = = sun4m )
* mid & = 3 ;
}
return 0 ;
}
( * cur_inst ) + + ;
return - ENODEV ;
}
2010-10-09 01:18:11 +04:00
static int __cpu_find_by ( int ( * compare ) ( phandle , int , void * ) ,
void * compare_arg , phandle * prom_node , int * mid )
2005-04-17 02:20:36 +04:00
{
2006-07-18 08:49:58 +04:00
struct device_node * dp ;
int cur_inst ;
2005-04-17 02:20:36 +04:00
cur_inst = 0 ;
2006-07-18 08:49:58 +04:00
for_each_node_by_type ( dp , " cpu " ) {
2010-01-29 00:06:53 +03:00
int err = check_cpu_node ( dp - > phandle , & cur_inst ,
2006-07-18 08:49:58 +04:00
compare , compare_arg ,
prom_node , mid ) ;
2007-12-04 11:33:07 +03:00
if ( ! err ) {
of_node_put ( dp ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-12-04 11:33:07 +03:00
}
2005-04-17 02:20:36 +04:00
}
return - ENODEV ;
}
2010-10-09 01:18:11 +04:00
static int cpu_instance_compare ( phandle nd , int instance , void * _arg )
2005-04-17 02:20:36 +04:00
{
int desired_instance = ( int ) _arg ;
if ( instance = = desired_instance )
return 0 ;
return - ENODEV ;
}
2010-10-09 01:18:11 +04:00
int cpu_find_by_instance ( int instance , phandle * prom_node , int * mid )
2005-04-17 02:20:36 +04:00
{
return __cpu_find_by ( cpu_instance_compare , ( void * ) instance ,
prom_node , mid ) ;
}
2010-10-09 01:18:11 +04:00
static int cpu_mid_compare ( phandle nd , int instance , void * _arg )
2005-04-17 02:20:36 +04:00
{
int desired_mid = ( int ) _arg ;
int this_mid ;
this_mid = prom_getintdefault ( nd , cpu_mid_prop ( ) , 0 ) ;
if ( this_mid = = desired_mid
| | ( sparc_cpu_model = = sun4m & & ( this_mid & 3 ) = = desired_mid ) )
return 0 ;
return - ENODEV ;
}
2010-10-09 01:18:11 +04:00
int cpu_find_by_mid ( int mid , phandle * prom_node )
2005-04-17 02:20:36 +04:00
{
return __cpu_find_by ( cpu_mid_compare , ( void * ) mid ,
prom_node , NULL ) ;
}
/* sun4m uses truncated mids since we base the cpuid on the ttable/irqset
* address ( 0 - 3 ) . This gives us the true hardware mid , which might have
* some other bits set . On 4 d hardware and software mids are the same .
*/
2010-10-09 01:18:11 +04:00
int cpu_get_hwmid ( phandle prom_node )
2005-04-17 02:20:36 +04:00
{
return prom_getintdefault ( prom_node , cpu_mid_prop ( ) , - ENODEV ) ;
}
void __init device_scan ( void )
{
2011-04-22 02:47:35 +04:00
printk ( KERN_NOTICE " Booting Linux... \n " ) ;
2005-04-17 02:20:36 +04:00
# ifndef CONFIG_SMP
{
2010-10-09 01:18:11 +04:00
phandle cpu_node ;
int err ;
2005-04-17 02:20:36 +04:00
err = cpu_find_by_instance ( 0 , & cpu_node , NULL ) ;
if ( err ) {
/* Probably a sun4e, Sun is trying to trick us ;-) */
prom_printf ( " No cpu nodes, cannot continue \n " ) ;
prom_halt ( ) ;
}
cpu_data ( 0 ) . clock_tick = prom_getintdefault ( cpu_node ,
" clock-frequency " ,
0 ) ;
}
# endif /* !CONFIG_SMP */
{
extern void auxio_probe ( void ) ;
extern void auxio_power_probe ( void ) ;
auxio_probe ( ) ;
auxio_power_probe ( ) ;
}
clock_stop_probe ( ) ;
}