summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSandrine Bailleux <sandrine.bailleux@arm.com>2019-09-16 14:21:04 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2019-09-16 14:21:04 +0000
commitf65423cd3cdc4b8c9606b285248844e55981db61 (patch)
tree6d44917b11085f9c95a42087974f64204304da36
parentc011d7d5fa64ed352f94825d67d183a7d9d2934e (diff)
parent3ef45dda88c83413c2c554212956d7966fab2807 (diff)
Merge changes from topic "raspberry-pi-4-support" into integration
* changes: Add fdt_add_reserved_memory() helper function qemu: Move and generalise FDT PSCI fixup
-rw-r--r--common/fdt_fixup.c156
-rw-r--r--include/common/fdt_fixup.h15
-rw-r--r--plat/qemu/dt.c99
-rw-r--r--plat/qemu/platform.mk2
-rw-r--r--plat/qemu/qemu_bl2_setup.c3
-rw-r--r--plat/qemu/qemu_private.h3
6 files changed, 174 insertions, 104 deletions
diff --git a/common/fdt_fixup.c b/common/fdt_fixup.c
new file mode 100644
index 00000000..8843404d
--- /dev/null
+++ b/common/fdt_fixup.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Contains generic routines to fix up the device tree blob passed on to
+ * payloads like BL32 and BL33 (and further down the boot chain).
+ * This allows to easily add PSCI nodes, when the original DT does not have
+ * it or advertises another method.
+ * Also it supports to add reserved memory nodes to describe memory that
+ * is used by the secure world, so that non-secure software avoids using
+ * that.
+ */
+
+#include <string.h>
+
+#include <libfdt.h>
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/psci/psci.h>
+
+#include <common/fdt_fixup.h>
+
+static int append_psci_compatible(void *fdt, int offs, const char *str)
+{
+ return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1);
+}
+
+int dt_add_psci_node(void *fdt)
+{
+ int offs;
+
+ if (fdt_path_offset(fdt, "/psci") >= 0) {
+ WARN("PSCI Device Tree node already exists!\n");
+ return 0;
+ }
+
+ offs = fdt_path_offset(fdt, "/");
+ if (offs < 0)
+ return -1;
+ offs = fdt_add_subnode(fdt, offs, "psci");
+ if (offs < 0)
+ return -1;
+ if (append_psci_compatible(fdt, offs, "arm,psci-1.0"))
+ return -1;
+ if (append_psci_compatible(fdt, offs, "arm,psci-0.2"))
+ return -1;
+ if (append_psci_compatible(fdt, offs, "arm,psci"))
+ return -1;
+ if (fdt_setprop_string(fdt, offs, "method", "smc"))
+ return -1;
+ if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND_AARCH64))
+ return -1;
+ if (fdt_setprop_u32(fdt, offs, "cpu_off", PSCI_CPU_OFF))
+ return -1;
+ if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON_AARCH64))
+ return -1;
+ if (fdt_setprop_u32(fdt, offs, "sys_poweroff", PSCI_SYSTEM_OFF))
+ return -1;
+ if (fdt_setprop_u32(fdt, offs, "sys_reset", PSCI_SYSTEM_RESET))
+ return -1;
+ return 0;
+}
+
+/*
+ * Find the first subnode that has a "device_type" property with the value
+ * "cpu" and which's enable-method is not "psci" (yet).
+ * Returns 0 if no such subnode is found, so all have already been patched
+ * or none have to be patched in the first place.
+ * Returns 1 if *one* such subnode has been found and successfully changed
+ * to "psci".
+ * Returns -1 on error.
+ *
+ * Call in a loop until it returns 0. Recalculate the node offset after
+ * it has returned 1.
+ */
+static int dt_update_one_cpu_node(void *fdt, int offset)
+{
+ int offs;
+
+ /* Iterate over all subnodes to find those with device_type = "cpu". */
+ for (offs = fdt_first_subnode(fdt, offset); offs >= 0;
+ offs = fdt_next_subnode(fdt, offs)) {
+ const char *prop;
+ int len;
+
+ prop = fdt_getprop(fdt, offs, "device_type", &len);
+ if (!prop)
+ continue;
+ if (memcmp(prop, "cpu", 4) != 0 || len != 4)
+ continue;
+
+ /* Ignore any nodes which already use "psci". */
+ prop = fdt_getprop(fdt, offs, "enable-method", &len);
+ if (prop && memcmp(prop, "psci", 5) == 0 && len == 5)
+ continue;
+
+ if (fdt_setprop_string(fdt, offs, "enable-method", "psci"))
+ return -1;
+ /*
+ * Subnode found and patched.
+ * Restart to accommodate potentially changed offsets.
+ */
+ return 1;
+ }
+
+ if (offs == -FDT_ERR_NOTFOUND)
+ return 0;
+
+ return offs;
+}
+
+int dt_add_psci_cpu_enable_methods(void *fdt)
+{
+ int offs, ret;
+
+ do {
+ offs = fdt_path_offset(fdt, "/cpus");
+ if (offs < 0)
+ return offs;
+
+ ret = dt_update_one_cpu_node(fdt, offs);
+ } while (ret > 0);
+
+ return ret;
+}
+
+#define HIGH_BITS(x) ((sizeof(x) > 4) ? ((x) >> 32) : (typeof(x))0)
+
+int fdt_add_reserved_memory(void *dtb, const char *node_name,
+ uintptr_t base, size_t size)
+{
+ int offs = fdt_path_offset(dtb, "/reserved-memory");
+ uint32_t addresses[3];
+
+ if (offs < 0) { /* create if not existing yet */
+ offs = fdt_add_subnode(dtb, 0, "reserved-memory");
+ if (offs < 0)
+ return offs;
+ fdt_setprop_u32(dtb, offs, "#address-cells", 2);
+ fdt_setprop_u32(dtb, offs, "#size-cells", 1);
+ fdt_setprop(dtb, offs, "ranges", NULL, 0);
+ }
+
+ addresses[0] = cpu_to_fdt32(HIGH_BITS(base));
+ addresses[1] = cpu_to_fdt32(base & 0xffffffff);
+ addresses[2] = cpu_to_fdt32(size & 0xffffffff);
+ offs = fdt_add_subnode(dtb, offs, node_name);
+ fdt_setprop(dtb, offs, "no-map", NULL, 0);
+ fdt_setprop(dtb, offs, "reg", addresses, 12);
+
+ return 0;
+}
diff --git a/include/common/fdt_fixup.h b/include/common/fdt_fixup.h
new file mode 100644
index 00000000..0248de9c
--- /dev/null
+++ b/include/common/fdt_fixup.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FDT_FIXUP_H
+#define FDT_FIXUP_H
+
+int dt_add_psci_node(void *fdt);
+int dt_add_psci_cpu_enable_methods(void *fdt);
+int fdt_add_reserved_memory(void *dtb, const char *node_name,
+ uintptr_t base, size_t size);
+
+#endif /* FDT_FIXUP_H */
diff --git a/plat/qemu/dt.c b/plat/qemu/dt.c
deleted file mode 100644
index b1cd368c..00000000
--- a/plat/qemu/dt.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <string.h>
-
-#include <libfdt.h>
-
-#include <common/debug.h>
-#include <drivers/console.h>
-#include <lib/psci/psci.h>
-
-#include "qemu_private.h"
-
-static int append_psci_compatible(void *fdt, int offs, const char *str)
-{
- return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1);
-}
-
-int dt_add_psci_node(void *fdt)
-{
- int offs;
-
- if (fdt_path_offset(fdt, "/psci") >= 0) {
- WARN("PSCI Device Tree node already exists!\n");
- return 0;
- }
-
- offs = fdt_path_offset(fdt, "/");
- if (offs < 0)
- return -1;
- offs = fdt_add_subnode(fdt, offs, "psci");
- if (offs < 0)
- return -1;
- if (append_psci_compatible(fdt, offs, "arm,psci-1.0"))
- return -1;
- if (append_psci_compatible(fdt, offs, "arm,psci-0.2"))
- return -1;
- if (append_psci_compatible(fdt, offs, "arm,psci"))
- return -1;
- if (fdt_setprop_string(fdt, offs, "method", "smc"))
- return -1;
- if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND_AARCH64))
- return -1;
- if (fdt_setprop_u32(fdt, offs, "cpu_off", PSCI_CPU_OFF))
- return -1;
- if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON_AARCH64))
- return -1;
- if (fdt_setprop_u32(fdt, offs, "sys_poweroff", PSCI_SYSTEM_OFF))
- return -1;
- if (fdt_setprop_u32(fdt, offs, "sys_reset", PSCI_SYSTEM_RESET))
- return -1;
- return 0;
-}
-
-static int check_node_compat_prefix(void *fdt, int offs, const char *prefix)
-{
- const size_t prefix_len = strlen(prefix);
- size_t l;
- int plen;
- const char *prop;
-
- prop = fdt_getprop(fdt, offs, "compatible", &plen);
- if (!prop)
- return -1;
-
- while (plen > 0) {
- if (memcmp(prop, prefix, prefix_len) == 0)
- return 0; /* match */
-
- l = strlen(prop) + 1;
- prop += l;
- plen -= l;
- }
-
- return -1;
-}
-
-int dt_add_psci_cpu_enable_methods(void *fdt)
-{
- int offs = 0;
-
- while (1) {
- offs = fdt_next_node(fdt, offs, NULL);
- if (offs < 0)
- break;
- if (fdt_getprop(fdt, offs, "enable-method", NULL))
- continue; /* already set */
- if (check_node_compat_prefix(fdt, offs, "arm,cortex-a"))
- continue; /* no compatible */
- if (fdt_setprop_string(fdt, offs, "enable-method", "psci"))
- return -1;
- /* Need to restart scanning as offsets may have changed */
- offs = 0;
- }
- return 0;
-}
diff --git a/plat/qemu/platform.mk b/plat/qemu/platform.mk
index 6b9749c7..bc4a21bc 100644
--- a/plat/qemu/platform.mk
+++ b/plat/qemu/platform.mk
@@ -114,7 +114,7 @@ BL2_SOURCES += drivers/io/io_semihosting.c \
plat/qemu/qemu_io_storage.c \
plat/qemu/${ARCH}/plat_helpers.S \
plat/qemu/qemu_bl2_setup.c \
- plat/qemu/dt.c \
+ common/fdt_fixup.c \
plat/qemu/qemu_bl2_mem_params_desc.c \
plat/qemu/qemu_image_load.c \
common/desc_image_load.c
diff --git a/plat/qemu/qemu_bl2_setup.c b/plat/qemu/qemu_bl2_setup.c
index 4c97c8dd..166d2454 100644
--- a/plat/qemu/qemu_bl2_setup.c
+++ b/plat/qemu/qemu_bl2_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,6 +15,7 @@
#include <common/bl_common.h>
#include <common/debug.h>
#include <common/desc_image_load.h>
+#include <common/fdt_fixup.h>
#include <lib/optee_utils.h>
#include <lib/utils.h>
#include <plat/common/platform.h>
diff --git a/plat/qemu/qemu_private.h b/plat/qemu/qemu_private.h
index 46b1ca1e..71ea4de1 100644
--- a/plat/qemu/qemu_private.h
+++ b/plat/qemu/qemu_private.h
@@ -28,9 +28,6 @@ void qemu_configure_mmu_el3(unsigned long total_base, unsigned long total_size,
void plat_qemu_io_setup(void);
unsigned int plat_qemu_calc_core_pos(u_register_t mpidr);
-int dt_add_psci_node(void *fdt);
-int dt_add_psci_cpu_enable_methods(void *fdt);
-
void qemu_console_init(void);
void plat_qemu_gic_init(void);