diff options
-rw-r--r-- | arch/arm/include/asm/mach/arch.h | 1 | ||||
-rw-r--r-- | arch/arm/kernel/devtree.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-exynos/exynos.c | 10 | ||||
-rw-r--r-- | drivers/of/fdt.c | 66 | ||||
-rw-r--r-- | include/linux/of_fdt.h | 3 |
5 files changed, 86 insertions, 2 deletions
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 060a75e99263..0406cb3f1af7 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h | |||
@@ -50,6 +50,7 @@ struct machine_desc { | |||
50 | struct smp_operations *smp; /* SMP operations */ | 50 | struct smp_operations *smp; /* SMP operations */ |
51 | bool (*smp_init)(void); | 51 | bool (*smp_init)(void); |
52 | void (*fixup)(struct tag *, char **); | 52 | void (*fixup)(struct tag *, char **); |
53 | void (*dt_fixup)(void); | ||
53 | void (*init_meminfo)(void); | 54 | void (*init_meminfo)(void); |
54 | void (*reserve)(void);/* reserve mem blocks */ | 55 | void (*reserve)(void);/* reserve mem blocks */ |
55 | void (*map_io)(void);/* IO mapping function */ | 56 | void (*map_io)(void);/* IO mapping function */ |
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index e94a157ddff1..11c54de9f8cf 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c | |||
@@ -212,7 +212,7 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) | |||
212 | mdesc_best = &__mach_desc_GENERIC_DT; | 212 | mdesc_best = &__mach_desc_GENERIC_DT; |
213 | #endif | 213 | #endif |
214 | 214 | ||
215 | if (!dt_phys || !early_init_dt_scan(phys_to_virt(dt_phys))) | 215 | if (!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys))) |
216 | return NULL; | 216 | return NULL; |
217 | 217 | ||
218 | mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach); | 218 | mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach); |
@@ -237,6 +237,12 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) | |||
237 | dump_machine_table(); /* does not return */ | 237 | dump_machine_table(); /* does not return */ |
238 | } | 238 | } |
239 | 239 | ||
240 | /* We really don't want to do this, but sometimes firmware provides buggy data */ | ||
241 | if (mdesc->dt_fixup) | ||
242 | mdesc->dt_fixup(); | ||
243 | |||
244 | early_init_dt_scan_nodes(); | ||
245 | |||
240 | /* Change machine number to match the mdesc we're using */ | 246 | /* Change machine number to match the mdesc we're using */ |
241 | __machine_arch_type = mdesc->nr; | 247 | __machine_arch_type = mdesc->nr; |
242 | 248 | ||
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 46d893fcbe85..66c9b9614f3c 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c | |||
@@ -335,6 +335,15 @@ static void __init exynos_reserve(void) | |||
335 | #endif | 335 | #endif |
336 | } | 336 | } |
337 | 337 | ||
338 | static void __init exynos_dt_fixup(void) | ||
339 | { | ||
340 | /* | ||
341 | * Some versions of uboot pass garbage entries in the memory node, | ||
342 | * use the old CONFIG_ARM_NR_BANKS | ||
343 | */ | ||
344 | of_fdt_limit_memory(8); | ||
345 | } | ||
346 | |||
338 | DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)") | 347 | DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)") |
339 | /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */ | 348 | /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */ |
340 | /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ | 349 | /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ |
@@ -348,4 +357,5 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)") | |||
348 | .dt_compat = exynos_dt_compat, | 357 | .dt_compat = exynos_dt_compat, |
349 | .restart = exynos_restart, | 358 | .restart = exynos_restart, |
350 | .reserve = exynos_reserve, | 359 | .reserve = exynos_reserve, |
360 | .dt_fixup = exynos_dt_fixup, | ||
351 | MACHINE_END | 361 | MACHINE_END |
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index b777d8f46bd5..9aa012e6ea0a 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -26,6 +26,54 @@ | |||
26 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ | 26 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ |
27 | #include <asm/page.h> | 27 | #include <asm/page.h> |
28 | 28 | ||
29 | /* | ||
30 | * of_fdt_limit_memory - limit the number of regions in the /memory node | ||
31 | * @limit: maximum entries | ||
32 | * | ||
33 | * Adjust the flattened device tree to have at most 'limit' number of | ||
34 | * memory entries in the /memory node. This function may be called | ||
35 | * any time after initial_boot_param is set. | ||
36 | */ | ||
37 | void of_fdt_limit_memory(int limit) | ||
38 | { | ||
39 | int memory; | ||
40 | int len; | ||
41 | const void *val; | ||
42 | int nr_address_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT; | ||
43 | int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT; | ||
44 | const uint32_t *addr_prop; | ||
45 | const uint32_t *size_prop; | ||
46 | int root_offset; | ||
47 | int cell_size; | ||
48 | |||
49 | root_offset = fdt_path_offset(initial_boot_params, "/"); | ||
50 | if (root_offset < 0) | ||
51 | return; | ||
52 | |||
53 | addr_prop = fdt_getprop(initial_boot_params, root_offset, | ||
54 | "#address-cells", NULL); | ||
55 | if (addr_prop) | ||
56 | nr_address_cells = fdt32_to_cpu(*addr_prop); | ||
57 | |||
58 | size_prop = fdt_getprop(initial_boot_params, root_offset, | ||
59 | "#size-cells", NULL); | ||
60 | if (size_prop) | ||
61 | nr_size_cells = fdt32_to_cpu(*size_prop); | ||
62 | |||
63 | cell_size = sizeof(uint32_t)*(nr_address_cells + nr_size_cells); | ||
64 | |||
65 | memory = fdt_path_offset(initial_boot_params, "/memory"); | ||
66 | if (memory > 0) { | ||
67 | val = fdt_getprop(initial_boot_params, memory, "reg", &len); | ||
68 | if (len > limit*cell_size) { | ||
69 | len = limit*cell_size; | ||
70 | pr_debug("Limiting number of entries to %d\n", limit); | ||
71 | fdt_setprop(initial_boot_params, memory, "reg", val, | ||
72 | len); | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | |||
29 | /** | 77 | /** |
30 | * of_fdt_is_compatible - Return true if given node from the given blob has | 78 | * of_fdt_is_compatible - Return true if given node from the given blob has |
31 | * compat in its compatible list | 79 | * compat in its compatible list |
@@ -937,7 +985,7 @@ int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, | |||
937 | } | 985 | } |
938 | #endif | 986 | #endif |
939 | 987 | ||
940 | bool __init early_init_dt_scan(void *params) | 988 | bool __init early_init_dt_verify(void *params) |
941 | { | 989 | { |
942 | if (!params) | 990 | if (!params) |
943 | return false; | 991 | return false; |
@@ -951,6 +999,12 @@ bool __init early_init_dt_scan(void *params) | |||
951 | return false; | 999 | return false; |
952 | } | 1000 | } |
953 | 1001 | ||
1002 | return true; | ||
1003 | } | ||
1004 | |||
1005 | |||
1006 | void __init early_init_dt_scan_nodes(void) | ||
1007 | { | ||
954 | /* Retrieve various information from the /chosen node */ | 1008 | /* Retrieve various information from the /chosen node */ |
955 | of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); | 1009 | of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); |
956 | 1010 | ||
@@ -959,7 +1013,17 @@ bool __init early_init_dt_scan(void *params) | |||
959 | 1013 | ||
960 | /* Setup memory, calling early_init_dt_add_memory_arch */ | 1014 | /* Setup memory, calling early_init_dt_add_memory_arch */ |
961 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | 1015 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); |
1016 | } | ||
1017 | |||
1018 | bool __init early_init_dt_scan(void *params) | ||
1019 | { | ||
1020 | bool status; | ||
1021 | |||
1022 | status = early_init_dt_verify(params); | ||
1023 | if (!status) | ||
1024 | return false; | ||
962 | 1025 | ||
1026 | early_init_dt_scan_nodes(); | ||
963 | return true; | 1027 | return true; |
964 | } | 1028 | } |
965 | 1029 | ||
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 05117899fcb4..0ff360d5b3b3 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h | |||
@@ -73,6 +73,8 @@ extern int early_init_dt_scan_root(unsigned long node, const char *uname, | |||
73 | int depth, void *data); | 73 | int depth, void *data); |
74 | 74 | ||
75 | extern bool early_init_dt_scan(void *params); | 75 | extern bool early_init_dt_scan(void *params); |
76 | extern bool early_init_dt_verify(void *params); | ||
77 | extern void early_init_dt_scan_nodes(void); | ||
76 | 78 | ||
77 | extern const char *of_flat_dt_get_machine_name(void); | 79 | extern const char *of_flat_dt_get_machine_name(void); |
78 | extern const void *of_flat_dt_match_machine(const void *default_match, | 80 | extern const void *of_flat_dt_match_machine(const void *default_match, |
@@ -84,6 +86,7 @@ extern void unflatten_and_copy_device_tree(void); | |||
84 | extern void early_init_devtree(void *); | 86 | extern void early_init_devtree(void *); |
85 | extern void early_get_first_memblock_info(void *, phys_addr_t *); | 87 | extern void early_get_first_memblock_info(void *, phys_addr_t *); |
86 | extern u64 fdt_translate_address(const void *blob, int node_offset); | 88 | extern u64 fdt_translate_address(const void *blob, int node_offset); |
89 | extern void of_fdt_limit_memory(int limit); | ||
87 | #else /* CONFIG_OF_FLATTREE */ | 90 | #else /* CONFIG_OF_FLATTREE */ |
88 | static inline void early_init_fdt_scan_reserved_mem(void) {} | 91 | static inline void early_init_fdt_scan_reserved_mem(void) {} |
89 | static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } | 92 | static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } |