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; } |
