aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/mach/arch.h1
-rw-r--r--arch/arm/kernel/devtree.c8
-rw-r--r--arch/arm/mach-exynos/exynos.c10
-rw-r--r--drivers/of/fdt.c66
-rw-r--r--include/linux/of_fdt.h3
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
338static 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
338DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)") 347DT_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,
351MACHINE_END 361MACHINE_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 */
37void 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
940bool __init early_init_dt_scan(void *params) 988bool __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
1006void __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
1018bool __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
75extern bool early_init_dt_scan(void *params); 75extern bool early_init_dt_scan(void *params);
76extern bool early_init_dt_verify(void *params);
77extern void early_init_dt_scan_nodes(void);
76 78
77extern const char *of_flat_dt_get_machine_name(void); 79extern const char *of_flat_dt_get_machine_name(void);
78extern const void *of_flat_dt_match_machine(const void *default_match, 80extern const void *of_flat_dt_match_machine(const void *default_match,
@@ -84,6 +86,7 @@ extern void unflatten_and_copy_device_tree(void);
84extern void early_init_devtree(void *); 86extern void early_init_devtree(void *);
85extern void early_get_first_memblock_info(void *, phys_addr_t *); 87extern void early_get_first_memblock_info(void *, phys_addr_t *);
86extern u64 fdt_translate_address(const void *blob, int node_offset); 88extern u64 fdt_translate_address(const void *blob, int node_offset);
89extern void of_fdt_limit_memory(int limit);
87#else /* CONFIG_OF_FLATTREE */ 90#else /* CONFIG_OF_FLATTREE */
88static inline void early_init_fdt_scan_reserved_mem(void) {} 91static inline void early_init_fdt_scan_reserved_mem(void) {}
89static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } 92static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }