diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/of/base.c | 4 | ||||
-rw-r--r-- | drivers/of/fdt.c | 137 | ||||
-rw-r--r-- | drivers/of/kexec.c | 40 | ||||
-rw-r--r-- | drivers/of/kobj.c | 2 | ||||
-rw-r--r-- | drivers/of/property.c | 10 |
5 files changed, 131 insertions, 62 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 5883d63c7714..f720c0d246f2 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -708,9 +708,7 @@ static struct device_node *__of_get_next_child(const struct device_node *node, return NULL; next = prev ? prev->sibling : node->child; - for (; next; next = next->sibling) - if (of_node_get(next)) - break; + of_node_get(next); of_node_put(prev); return next; } diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index e0f96e3ef1da..4546572af24b 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) "OF: fdt: " fmt +#include <linux/crash_dump.h> #include <linux/crc32.h> #include <linux/kernel.h> #include <linux/initrd.h> @@ -193,16 +194,12 @@ static void populate_properties(const void *blob, pp->length = len; pp->value = pp + 1; *pprev = pp; - pprev = &pp->next; memcpy(pp->value, ps, len - 1); ((char *)pp->value)[len - 1] = 0; pr_debug("fixed up name for %s -> %s\n", nodename, (char *)pp->value); } } - - if (!dryrun) - *pprev = NULL; } static int populate_node(const void *blob, @@ -479,6 +476,22 @@ void *initial_boot_params __ro_after_init; static u32 of_fdt_crc32; +static int __init early_init_dt_reserve_memory_arch(phys_addr_t base, + phys_addr_t size, bool nomap) +{ + if (nomap) { + /* + * If the memory is already reserved (by another region), we + * should not allow it to be marked nomap. + */ + if (memblock_is_region_reserved(base, size)) + return -EBUSY; + + return memblock_mark_nomap(base, size); + } + return memblock_reserve(base, size); +} + /* * __reserved_mem_reserve_reg() - reserve all memory described in 'reg' property */ @@ -585,6 +598,30 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, return 0; } +/* + * fdt_reserve_elfcorehdr() - reserves memory for elf core header + * + * This function reserves the memory occupied by an elf core header + * described in the device tree. This region contains all the + * information about primary kernel's core image and is used by a dump + * capture kernel to access the system memory on primary kernel. + */ +static void __init fdt_reserve_elfcorehdr(void) +{ + if (!IS_ENABLED(CONFIG_CRASH_DUMP) || !elfcorehdr_size) + return; + + if (memblock_is_region_reserved(elfcorehdr_addr, elfcorehdr_size)) { + pr_warn("elfcorehdr is overlapped\n"); + return; + } + + memblock_reserve(elfcorehdr_addr, elfcorehdr_size); + + pr_info("Reserving %llu KiB of memory at 0x%llx for elfcorehdr\n", + elfcorehdr_size >> 10, elfcorehdr_addr); +} + /** * early_init_fdt_scan_reserved_mem() - create reserved memory regions * @@ -610,6 +647,7 @@ void __init early_init_fdt_scan_reserved_mem(void) of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); fdt_init_reserved_mem(); + fdt_reserve_elfcorehdr(); } /** @@ -858,7 +896,6 @@ const void * __init of_flat_dt_match_machine(const void *default_match, return best_data; } -#ifdef CONFIG_BLK_DEV_INITRD static void __early_init_dt_declare_initrd(unsigned long start, unsigned long end) { @@ -884,6 +921,9 @@ static void __init early_init_dt_check_for_initrd(unsigned long node) int len; const __be32 *prop; + if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD)) + return; + pr_debug("Looking for initrd properties... "); prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len); @@ -902,11 +942,58 @@ static void __init early_init_dt_check_for_initrd(unsigned long node) pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", start, end); } -#else -static inline void early_init_dt_check_for_initrd(unsigned long node) + +/** + * early_init_dt_check_for_elfcorehdr - Decode elfcorehdr location from flat + * tree + * @node: reference to node containing elfcorehdr location ('chosen') + */ +static void __init early_init_dt_check_for_elfcorehdr(unsigned long node) +{ + const __be32 *prop; + int len; + + if (!IS_ENABLED(CONFIG_CRASH_DUMP)) + return; + + pr_debug("Looking for elfcorehdr property... "); + + prop = of_get_flat_dt_prop(node, "linux,elfcorehdr", &len); + if (!prop || (len < (dt_root_addr_cells + dt_root_size_cells))) + return; + + elfcorehdr_addr = dt_mem_next_cell(dt_root_addr_cells, &prop); + elfcorehdr_size = dt_mem_next_cell(dt_root_size_cells, &prop); + + pr_debug("elfcorehdr_start=0x%llx elfcorehdr_size=0x%llx\n", + elfcorehdr_addr, elfcorehdr_size); +} + +static phys_addr_t cap_mem_addr; +static phys_addr_t cap_mem_size; + +/** + * early_init_dt_check_for_usable_mem_range - Decode usable memory range + * location from flat tree + * @node: reference to node containing usable memory range location ('chosen') + */ +static void __init early_init_dt_check_for_usable_mem_range(unsigned long node) { + const __be32 *prop; + int len; + + pr_debug("Looking for usable-memory-range property... "); + + prop = of_get_flat_dt_prop(node, "linux,usable-memory-range", &len); + if (!prop || (len < (dt_root_addr_cells + dt_root_size_cells))) + return; + + cap_mem_addr = dt_mem_next_cell(dt_root_addr_cells, &prop); + cap_mem_size = dt_mem_next_cell(dt_root_size_cells, &prop); + + pr_debug("cap_mem_start=%pa cap_mem_size=%pa\n", &cap_mem_addr, + &cap_mem_size); } -#endif /* CONFIG_BLK_DEV_INITRD */ #ifdef CONFIG_SERIAL_EARLYCON @@ -1033,7 +1120,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname, if (!hotpluggable) continue; - if (early_init_dt_mark_hotplug_memory_arch(base, size)) + if (memblock_mark_hotplug(base, size)) pr_warn("failed to mark hotplug range 0x%llx - 0x%llx\n", base, base + size); } @@ -1055,6 +1142,8 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, return 0; early_init_dt_check_for_initrd(node); + early_init_dt_check_for_elfcorehdr(node); + early_init_dt_check_for_usable_mem_range(node); /* Retrieve command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); @@ -1146,27 +1235,6 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) memblock_add(base, size); } -int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size) -{ - return memblock_mark_hotplug(base, size); -} - -int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, - phys_addr_t size, bool nomap) -{ - if (nomap) { - /* - * If the memory is already reserved (by another region), we - * should not allow it to be marked nomap. - */ - if (memblock_is_region_reserved(base, size)) - return -EBUSY; - - return memblock_mark_nomap(base, size); - } - return memblock_reserve(base, size); -} - static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) { void *ptr = memblock_alloc(size, align); @@ -1199,16 +1267,19 @@ void __init early_init_dt_scan_nodes(void) { int rc = 0; + /* Initialize {size,address}-cells info */ + of_scan_flat_dt(early_init_dt_scan_root, NULL); + /* Retrieve various information from the /chosen node */ rc = of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); if (!rc) pr_warn("No chosen node found, continuing without\n"); - /* Initialize {size,address}-cells info */ - of_scan_flat_dt(early_init_dt_scan_root, NULL); - /* Setup memory, calling early_init_dt_add_memory_arch */ of_scan_flat_dt(early_init_dt_scan_memory, NULL); + + /* Handle linux,usable-memory-range property */ + memblock_cap_memory_range(cap_mem_addr, cap_mem_size); } bool __init early_init_dt_scan(void *params) diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c index f335d941a716..761fd870d1db 100644 --- a/drivers/of/kexec.c +++ b/drivers/of/kexec.c @@ -18,14 +18,6 @@ #include <linux/random.h> #include <linux/types.h> -/* relevant device tree properties */ -#define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr" -#define FDT_PROP_MEM_RANGE "linux,usable-memory-range" -#define FDT_PROP_INITRD_START "linux,initrd-start" -#define FDT_PROP_INITRD_END "linux,initrd-end" -#define FDT_PROP_BOOTARGS "bootargs" -#define FDT_PROP_KASLR_SEED "kaslr-seed" -#define FDT_PROP_RNG_SEED "rng-seed" #define RNG_SEED_SIZE 128 /* @@ -310,10 +302,10 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, goto out; } - ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KEXEC_ELFHDR); + ret = fdt_delprop(fdt, chosen_node, "linux,elfcorehdr"); if (ret && ret != -FDT_ERR_NOTFOUND) goto out; - ret = fdt_delprop(fdt, chosen_node, FDT_PROP_MEM_RANGE); + ret = fdt_delprop(fdt, chosen_node, "linux,usable-memory-range"); if (ret && ret != -FDT_ERR_NOTFOUND) goto out; @@ -347,12 +339,12 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, /* add initrd-* */ if (initrd_load_addr) { - ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_START, + ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-start", initrd_load_addr); if (ret) goto out; - ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_END, + ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-end", initrd_load_addr + initrd_len); if (ret) goto out; @@ -362,11 +354,11 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, goto out; } else { - ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_START); + ret = fdt_delprop(fdt, chosen_node, "linux,initrd-start"); if (ret && (ret != -FDT_ERR_NOTFOUND)) goto out; - ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_END); + ret = fdt_delprop(fdt, chosen_node, "linux,initrd-end"); if (ret && (ret != -FDT_ERR_NOTFOUND)) goto out; } @@ -374,8 +366,7 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, if (image->type == KEXEC_TYPE_CRASH) { /* add linux,elfcorehdr */ ret = fdt_appendprop_addrrange(fdt, 0, chosen_node, - FDT_PROP_KEXEC_ELFHDR, - image->elf_load_addr, + "linux,elfcorehdr", image->elf_load_addr, image->elf_headers_sz); if (ret) goto out; @@ -391,8 +382,7 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, /* add linux,usable-memory-range */ ret = fdt_appendprop_addrrange(fdt, 0, chosen_node, - FDT_PROP_MEM_RANGE, - crashk_res.start, + "linux,usable-memory-range", crashk_res.start, crashk_res.end - crashk_res.start + 1); if (ret) goto out; @@ -400,17 +390,17 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, /* add bootargs */ if (cmdline) { - ret = fdt_setprop_string(fdt, chosen_node, FDT_PROP_BOOTARGS, cmdline); + ret = fdt_setprop_string(fdt, chosen_node, "bootargs", cmdline); if (ret) goto out; } else { - ret = fdt_delprop(fdt, chosen_node, FDT_PROP_BOOTARGS); + ret = fdt_delprop(fdt, chosen_node, "bootargs"); if (ret && (ret != -FDT_ERR_NOTFOUND)) goto out; } /* add kaslr-seed */ - ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KASLR_SEED); + ret = fdt_delprop(fdt, chosen_node, "kaslr-seed"); if (ret == -FDT_ERR_NOTFOUND) ret = 0; else if (ret) @@ -419,26 +409,26 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, if (rng_is_initialized()) { u64 seed = get_random_u64(); - ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_KASLR_SEED, seed); + ret = fdt_setprop_u64(fdt, chosen_node, "kaslr-seed", seed); if (ret) goto out; } else { pr_notice("RNG is not initialised: omitting \"%s\" property\n", - FDT_PROP_KASLR_SEED); + "kaslr-seed"); } /* add rng-seed */ if (rng_is_initialized()) { void *rng_seed; - ret = fdt_setprop_placeholder(fdt, chosen_node, FDT_PROP_RNG_SEED, + ret = fdt_setprop_placeholder(fdt, chosen_node, "rng-seed", RNG_SEED_SIZE, &rng_seed); if (ret) goto out; get_random_bytes(rng_seed, RNG_SEED_SIZE); } else { pr_notice("RNG is not initialised: omitting \"%s\" property\n", - FDT_PROP_RNG_SEED); + "rng-seed"); } ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0); diff --git a/drivers/of/kobj.c b/drivers/of/kobj.c index a32e60b024b8..6675b5e56960 100644 --- a/drivers/of/kobj.c +++ b/drivers/of/kobj.c @@ -119,7 +119,7 @@ int __of_attach_node_sysfs(struct device_node *np) struct property *pp; int rc; - if (!of_kset) + if (!IS_ENABLED(CONFIG_SYSFS) || !of_kset) return 0; np->kobj.kset = of_kset; diff --git a/drivers/of/property.c b/drivers/of/property.c index 6c028632f425..0c0dc2e369c0 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1287,6 +1287,11 @@ DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL) DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) DEFINE_SIMPLE_PROP(remote_endpoint, "remote-endpoint", NULL) +DEFINE_SIMPLE_PROP(pwms, "pwms", "#pwm-cells") +DEFINE_SIMPLE_PROP(resets, "resets", "#reset-cells") +DEFINE_SIMPLE_PROP(leds, "leds", NULL) +DEFINE_SIMPLE_PROP(backlight, "backlight", NULL) +DEFINE_SIMPLE_PROP(phy_handle, "phy-handle", NULL) DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") @@ -1371,6 +1376,11 @@ static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_pinctrl7, }, { .parse_prop = parse_pinctrl8, }, { .parse_prop = parse_remote_endpoint, .node_not_dev = true, }, + { .parse_prop = parse_pwms, }, + { .parse_prop = parse_resets, }, + { .parse_prop = parse_leds, }, + { .parse_prop = parse_backlight, }, + { .parse_prop = parse_phy_handle, }, { .parse_prop = parse_gpio_compat, }, { .parse_prop = parse_interrupts, }, { .parse_prop = parse_regulators, }, |