2013-01-22 15:30:52 +04:00
/*
* Copyright ( C ) 2012 Synopsys , Inc . ( www . synopsys . com )
*
* Based on reduced version of METAG
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/init.h>
# include <linux/reboot.h>
# include <linux/memblock.h>
# include <linux/of.h>
# include <linux/of_fdt.h>
# include <asm/prom.h>
2013-01-18 13:42:20 +04:00
# include <asm/clk.h>
2013-01-18 13:42:26 +04:00
# include <asm/mach_desc.h>
2013-01-22 15:30:52 +04:00
/**
* setup_machine_fdt - Machine setup when an dtb was passed to the kernel
* @ dt : virtual address pointer to dt blob
*
* If a dtb was passed to the kernel , then use it to choose the correct
* machine_desc and to setup the system .
*/
2013-01-18 13:42:26 +04:00
struct machine_desc * __init setup_machine_fdt ( void * dt )
2013-01-22 15:30:52 +04:00
{
struct boot_param_header * devtree = dt ;
2013-01-18 13:42:26 +04:00
struct machine_desc * mdesc = NULL , * mdesc_best = NULL ;
unsigned int score , mdesc_score = ~ 1 ;
2013-01-22 15:30:52 +04:00
unsigned long dt_root ;
2013-01-18 13:42:26 +04:00
const char * model , * compat ;
2013-01-18 13:42:20 +04:00
void * clk ;
2013-01-22 15:30:52 +04:00
char manufacturer [ 16 ] ;
2013-01-18 13:42:20 +04:00
unsigned long len ;
2013-01-22 15:30:52 +04:00
/* check device tree validity */
if ( be32_to_cpu ( devtree - > magic ) ! = OF_DT_HEADER )
2013-01-18 13:42:26 +04:00
return NULL ;
2013-01-22 15:30:52 +04:00
initial_boot_params = devtree ;
dt_root = of_get_flat_dt_root ( ) ;
2013-01-18 13:42:26 +04:00
/*
* The kernel could be multi - platform enabled , thus could have many
* " baked-in " machine descriptors . Search thru all for the best
* " compatible " string match .
*/
for_each_machine_desc ( mdesc ) {
score = of_flat_dt_match ( dt_root , mdesc - > dt_compat ) ;
if ( score > 0 & & score < mdesc_score ) {
mdesc_best = mdesc ;
mdesc_score = score ;
}
}
if ( ! mdesc_best ) {
const char * prop ;
long size ;
pr_err ( " \n unrecognized device tree list: \n [ " ) ;
prop = of_get_flat_dt_prop ( dt_root , " compatible " , & size ) ;
if ( prop ) {
while ( size > 0 ) {
printk ( " '%s' " , prop ) ;
size - = strlen ( prop ) + 1 ;
prop + = strlen ( prop ) + 1 ;
}
}
printk ( " ] \n \n " ) ;
machine_halt ( ) ;
}
2013-01-22 15:30:52 +04:00
/* compat = "<manufacturer>,<model>" */
2013-01-18 13:42:26 +04:00
compat = mdesc_best - > dt_compat [ 0 ] ;
2013-01-22 15:30:52 +04:00
model = strchr ( compat , ' , ' ) ;
if ( model )
model + + ;
strlcpy ( manufacturer , compat , model ? model - compat : strlen ( compat ) ) ;
pr_info ( " Board \" %s \" from %s (Manufacturer) \n " , model , manufacturer ) ;
/* Retrieve various information from the /chosen node */
of_scan_flat_dt ( early_init_dt_scan_chosen , boot_command_line ) ;
2013-01-18 13:42:20 +04:00
/* Initialize {size,address}-cells info */
of_scan_flat_dt ( early_init_dt_scan_root , NULL ) ;
/* Setup memory, calling early_init_dt_add_memory_arch */
of_scan_flat_dt ( early_init_dt_scan_memory , NULL ) ;
clk = of_get_flat_dt_prop ( dt_root , " clock-frequency " , & len ) ;
if ( clk )
arc_set_core_freq ( of_read_ulong ( clk , len / 4 ) ) ;
2013-01-18 13:42:26 +04:00
return mdesc_best ;
2013-01-22 15:30:52 +04:00
}