summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/of/base.c4
-rw-r--r--drivers/of/fdt.c137
-rw-r--r--drivers/of/kexec.c40
-rw-r--r--drivers/of/kobj.c2
-rw-r--r--drivers/of/property.c10
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, },