diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-01-18 15:12:26 +0530 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-02-15 23:16:13 +0530 |
commit | 03a6d28cdddfbd11b338c23e7fe51d0816b9bdef (patch) | |
tree | 740383bea378fd680c35ff9b8c074ac36e2781ee /arch/arc/kernel/devtree.c | |
parent | 93ad700de2abc111c50bb961c150a9968d5b3982 (diff) | |
download | linux-03a6d28cdddfbd11b338c23e7fe51d0816b9bdef.tar.gz linux-03a6d28cdddfbd11b338c23e7fe51d0816b9bdef.tar.bz2 linux-03a6d28cdddfbd11b338c23e7fe51d0816b9bdef.zip |
ARC: [Review] Multi-platform image #2: Board callback Infrastructure
The orig platform code orgnaization was singleton design pattern - only
one platform (and board thereof) would build at a time.
Thus any platform/board specific code (e.g. irq init, early init ...)
expected by ARC common code was exported as well defined set of APIs,
with only ONE instance building ever.
Now with multiple-platform build requirement, that design of code no
longer holds - multiple board specific calls need to build at the same
time - so ARC common code can't use the API approach, it needs a
callback based design where each board registers it's specific set of
functions, and at runtime, depending on board detection, the callbacks
are used from the registry.
This commit adds all the infrastructure, where board specific callbacks
are specified as a "maThine description".
All the hooks are placed in right spots, no board callbacks registered
yet (with MACHINE_STARt/END constructs) so the hooks will not run.
Next commit will actually convert the platform to this infrastructure.
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arc/kernel/devtree.c')
-rw-r--r-- | arch/arc/kernel/devtree.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index c8166dc02c38..a7d98b30358b 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -16,6 +16,7 @@ #include <linux/of_fdt.h> #include <asm/prom.h> #include <asm/clk.h> +#include <asm/mach_desc.h> /* called from unflatten_device_tree() to bootstrap devicetree itself */ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) @@ -30,27 +31,57 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) * If a dtb was passed to the kernel, then use it to choose the correct * machine_desc and to setup the system. */ -int __init setup_machine_fdt(void *dt) +struct machine_desc * __init setup_machine_fdt(void *dt) { struct boot_param_header *devtree = dt; + struct machine_desc *mdesc = NULL, *mdesc_best = NULL; + unsigned int score, mdesc_score = ~1; unsigned long dt_root; - char *model, *compat; + const char *model, *compat; void *clk; char manufacturer[16]; unsigned long len; /* check device tree validity */ if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) - return 1; + return NULL; - /* Search the mdescs for the 'best' compatible value match */ initial_boot_params = devtree; dt_root = of_get_flat_dt_root(); + /* + * 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(); + } + /* compat = "<manufacturer>,<model>" */ - compat = of_get_flat_dt_prop(dt_root, "compatible", NULL); - if (!compat) - compat = "<unknown>"; + compat = mdesc_best->dt_compat[0]; model = strchr(compat, ','); if (model) @@ -73,5 +104,5 @@ int __init setup_machine_fdt(void *dt) if (clk) arc_set_core_freq(of_read_ulong(clk, len/4)); - return 0; + return mdesc_best; } |