diff options
author | Atish Patra <atish.patra@wdc.com> | 2020-04-21 11:15:01 -0700 |
---|---|---|
committer | Andes <uboot@andestech.com> | 2020-04-23 10:14:16 +0800 |
commit | d4ea649f179a69edd2cf2dd96efb9337205eb015 (patch) | |
tree | 42bd3450a19f02aafa85e7c4fff2d3fdadcc903c /arch/riscv/lib/fdt_fixup.c | |
parent | f614753c4b91bc3b56809773aeb17da10f1231a5 (diff) |
riscv: Provide a mechanism to fix DT for reserved memory
In RISC-V, M-mode software can reserve physical memory regions
by setting appropriate physical memory protection (PMP) csr. As the
PMP csr are accessible only in M-mode, S-mode U-Boot can not read
this configuration directly. However, M-mode software can pass this
information via reserved-memory node in device tree so that S-mode
software can access this information.
This patch provides a framework to copy to the reserved-memory node
from one DT to another. This will be used to update the DT used by
U-Boot and the DT passed to the next stage OS.
Signed-off-by: Atish Patra <atish.patra@wdc.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'arch/riscv/lib/fdt_fixup.c')
-rw-r--r-- | arch/riscv/lib/fdt_fixup.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/arch/riscv/lib/fdt_fixup.c b/arch/riscv/lib/fdt_fixup.c new file mode 100644 index 0000000000..1fce414909 --- /dev/null +++ b/arch/riscv/lib/fdt_fixup.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020 Western Digital Corporation or its affiliates + * + */ + +#include <common.h> +#include <fdt_support.h> +#include <mapmem.h> + +DECLARE_GLOBAL_DATA_PTR; + +/** + * riscv_fdt_copy_resv_mem_node() - Copy reserve memory node entry + * @src: Pointer to the source device tree from which reserved memory node + * needs to be copied. + * @dst: Pointer to the destination device tree to which reserved memory node + * needs to be copied. + * + * Return: 0 on success or if source doesn't have reserved memory node. + * Error if copy process failed. + */ +int riscv_fdt_copy_resv_mem_node(const void *src, void *dst) +{ + u32 phandle; + struct fdt_memory pmp_mem; + fdt_addr_t addr; + fdt_size_t size; + int offset, node, err, rmem_offset; + bool nomap = true; + char basename[32] = {0}; + int bname_len; + int max_len = sizeof(basename); + const char *name; + char *temp; + + offset = fdt_path_offset(src, "/reserved-memory"); + if (offset < 0) { + printf("No reserved memory region found in source FDT\n"); + return 0; + } + + fdt_for_each_subnode(node, src, offset) { + name = fdt_get_name(src, node, NULL); + + addr = fdtdec_get_addr_size_auto_noparent(src, node, + "reg", 0, &size, + false); + if (addr == FDT_ADDR_T_NONE) { + debug("failed to read address/size for %s\n", name); + continue; + } + strncpy(basename, name, max_len); + temp = strchr(basename, '@'); + if (temp) { + bname_len = strnlen(basename, max_len) - strnlen(temp, + max_len); + *(basename + bname_len) = '\0'; + } + pmp_mem.start = addr; + pmp_mem.end = addr + size - 1; + err = fdtdec_add_reserved_memory(dst, basename, &pmp_mem, + &phandle); + if (err < 0) { + printf("failed to add reserved memory: %d\n", err); + return err; + } + if (!fdt_getprop(src, node, "no-map", NULL)) + nomap = false; + if (nomap) { + rmem_offset = fdt_node_offset_by_phandle(dst, phandle); + fdt_setprop_empty(dst, rmem_offset, "no-map"); + } + } + + return 0; +} + +/** + * riscv_board_reserved_mem_fixup() - Fix up reserved memory node for a board + * @fdt: Pointer to the device tree in which reserved memory node needs to be + * added. + * + * In RISC-V, any board compiled with OF_SEPARATE needs to copy the reserved + * memory node from the device tree provided by the firmware to the device tree + * used by U-Boot. This is a common function that individual board fixup + * functions can invoke. + * + * Return: 0 on success or error otherwise. + */ +int riscv_board_reserved_mem_fixup(void *fdt) +{ + int err; + void *src_fdt_addr; + + src_fdt_addr = map_sysmem(gd->arch.firmware_fdt_addr, 0); + err = riscv_fdt_copy_resv_mem_node(src_fdt_addr, fdt); + if (err < 0) + return err; + + return 0; +} |