diff options
Diffstat (limited to 'arch/arc/kernel/devtree.c')
-rw-r--r-- | arch/arc/kernel/devtree.c | 97 |
1 files changed, 20 insertions, 77 deletions
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index 2340af0e1d6f..b6dc4e21fd32 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c | |||
@@ -14,10 +14,22 @@ | |||
14 | #include <linux/memblock.h> | 14 | #include <linux/memblock.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/of_fdt.h> | 16 | #include <linux/of_fdt.h> |
17 | #include <asm/prom.h> | ||
18 | #include <asm/clk.h> | 17 | #include <asm/clk.h> |
19 | #include <asm/mach_desc.h> | 18 | #include <asm/mach_desc.h> |
20 | 19 | ||
20 | static const void * __init arch_get_next_mach(const char *const **match) | ||
21 | { | ||
22 | static const struct machine_desc *mdesc = __arch_info_begin; | ||
23 | const struct machine_desc *m = mdesc; | ||
24 | |||
25 | if (m >= __arch_info_end) | ||
26 | return NULL; | ||
27 | |||
28 | mdesc++; | ||
29 | *match = m->dt_compat; | ||
30 | return m; | ||
31 | } | ||
32 | |||
21 | /** | 33 | /** |
22 | * setup_machine_fdt - Machine setup when an dtb was passed to the kernel | 34 | * setup_machine_fdt - Machine setup when an dtb was passed to the kernel |
23 | * @dt: virtual address pointer to dt blob | 35 | * @dt: virtual address pointer to dt blob |
@@ -25,93 +37,24 @@ | |||
25 | * If a dtb was passed to the kernel, then use it to choose the correct | 37 | * If a dtb was passed to the kernel, then use it to choose the correct |
26 | * machine_desc and to setup the system. | 38 | * machine_desc and to setup the system. |
27 | */ | 39 | */ |
28 | struct machine_desc * __init setup_machine_fdt(void *dt) | 40 | const struct machine_desc * __init setup_machine_fdt(void *dt) |
29 | { | 41 | { |
30 | struct boot_param_header *devtree = dt; | 42 | const struct machine_desc *mdesc; |
31 | struct machine_desc *mdesc = NULL, *mdesc_best = NULL; | ||
32 | unsigned int score, mdesc_score = ~1; | ||
33 | unsigned long dt_root; | 43 | unsigned long dt_root; |
34 | const char *model, *compat; | ||
35 | void *clk; | 44 | void *clk; |
36 | char manufacturer[16]; | ||
37 | unsigned long len; | 45 | unsigned long len; |
38 | 46 | ||
39 | /* check device tree validity */ | 47 | if (!early_init_dt_scan(dt)) |
40 | if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) | ||
41 | return NULL; | 48 | return NULL; |
42 | 49 | ||
43 | initial_boot_params = devtree; | 50 | mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach); |
44 | dt_root = of_get_flat_dt_root(); | 51 | if (!mdesc) |
45 | |||
46 | /* | ||
47 | * The kernel could be multi-platform enabled, thus could have many | ||
48 | * "baked-in" machine descriptors. Search thru all for the best | ||
49 | * "compatible" string match. | ||
50 | */ | ||
51 | for_each_machine_desc(mdesc) { | ||
52 | score = of_flat_dt_match(dt_root, mdesc->dt_compat); | ||
53 | if (score > 0 && score < mdesc_score) { | ||
54 | mdesc_best = mdesc; | ||
55 | mdesc_score = score; | ||
56 | } | ||
57 | } | ||
58 | if (!mdesc_best) { | ||
59 | const char *prop; | ||
60 | long size; | ||
61 | |||
62 | pr_err("\n unrecognized device tree list:\n[ "); | ||
63 | |||
64 | prop = of_get_flat_dt_prop(dt_root, "compatible", &size); | ||
65 | if (prop) { | ||
66 | while (size > 0) { | ||
67 | printk("'%s' ", prop); | ||
68 | size -= strlen(prop) + 1; | ||
69 | prop += strlen(prop) + 1; | ||
70 | } | ||
71 | } | ||
72 | printk("]\n\n"); | ||
73 | |||
74 | machine_halt(); | 52 | machine_halt(); |
75 | } | ||
76 | |||
77 | /* compat = "<manufacturer>,<model>" */ | ||
78 | compat = mdesc_best->dt_compat[0]; | ||
79 | |||
80 | model = strchr(compat, ','); | ||
81 | if (model) | ||
82 | model++; | ||
83 | |||
84 | strlcpy(manufacturer, compat, model ? model - compat : strlen(compat)); | ||
85 | |||
86 | pr_info("Board \"%s\" from %s (Manufacturer)\n", model, manufacturer); | ||
87 | |||
88 | /* Retrieve various information from the /chosen node */ | ||
89 | of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); | ||
90 | |||
91 | /* Initialize {size,address}-cells info */ | ||
92 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | ||
93 | |||
94 | /* Setup memory, calling early_init_dt_add_memory_arch */ | ||
95 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | ||
96 | 53 | ||
54 | dt_root = of_get_flat_dt_root(); | ||
97 | clk = of_get_flat_dt_prop(dt_root, "clock-frequency", &len); | 55 | clk = of_get_flat_dt_prop(dt_root, "clock-frequency", &len); |
98 | if (clk) | 56 | if (clk) |
99 | arc_set_core_freq(of_read_ulong(clk, len/4)); | 57 | arc_set_core_freq(of_read_ulong(clk, len/4)); |
100 | 58 | ||
101 | return mdesc_best; | 59 | return mdesc; |
102 | } | ||
103 | |||
104 | /* | ||
105 | * Copy the flattened DT out of .init since unflattening doesn't copy strings | ||
106 | * and the normal DT APIs refs them from orig flat DT | ||
107 | */ | ||
108 | void __init copy_devtree(void) | ||
109 | { | ||
110 | void *alloc = early_init_dt_alloc_memory_arch( | ||
111 | be32_to_cpu(initial_boot_params->totalsize), 64); | ||
112 | if (alloc) { | ||
113 | memcpy(alloc, initial_boot_params, | ||
114 | be32_to_cpu(initial_boot_params->totalsize)); | ||
115 | initial_boot_params = alloc; | ||
116 | } | ||
117 | } | 60 | } |