Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2020 Western Digital Corporation or its affiliates * */ #define LOG_CATEGORY LOGC_ARCH #include <fdt_support.h> #include <log.h> #include <mapmem.h> #include <asm/global_data.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; 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) { log_debug("No reserved memory region found in source FDT\n"); return 0; } /* * Extend the FDT by the following estimated size: * * Each PMP memory region entry occupies 64 bytes. * With 16 PMP memory regions we need 64 * 16 = 1024 bytes. */ err = fdt_open_into(dst, dst, fdt_totalsize(dst) + 1024); if (err < 0) { printf("Device Tree can't be expanded to accommodate new node"); return err; } fdt_for_each_subnode(node, src, offset) { name = fdt_get_name(src, node, NULL); addr = fdtdec_get_addr_size_auto_parent(src, offset, node, "reg", 0, &size, false); if (addr == FDT_ADDR_T_NONE) { log_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, NULL, 0, &phandle, 0); if (err < 0 && err != -FDT_ERR_EXISTS) { log_err("failed to add reserved memory: %d\n", err); return err; } if (fdt_getprop(src, node, "no-map", NULL)) { 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 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); /* avoid the copy if we are using the same device tree */ if (src_fdt_addr == fdt) return 0; err = riscv_fdt_copy_resv_mem_node(src_fdt_addr, fdt); if (err < 0) return err; return 0; } #ifdef CONFIG_OF_BOARD_FIXUP int board_fix_fdt(void *fdt) { int err; err = riscv_board_reserved_mem_fixup(fdt); if (err < 0) { log_err("failed to fixup DT for reserved memory: %d\n", err); return err; } return 0; } #endif int arch_fixup_fdt(void *blob) { int err; #ifdef CONFIG_EFI_LOADER u32 size; int chosen_offset; size = fdt_totalsize(blob); err = fdt_open_into(blob, blob, size + 32); if (err < 0) { log_err("Device-tree can't be expanded to accommodate new node\n"); return err; } chosen_offset = fdt_path_offset(blob, "/chosen"); if (chosen_offset < 0) { chosen_offset = fdt_add_subnode(blob, 0, "chosen"); if (chosen_offset < 0) { log_err("chosen node cannot be added\n"); return chosen_offset; } } /* Overwrite the boot-hartid as U-Boot is the last stage BL */ err = fdt_setprop_u32(blob, chosen_offset, "boot-hartid", gd->arch.boot_hart); if (err < 0) return log_msg_ret("could not set boot-hartid", err); #endif /* Copy the reserved-memory node to the DT used by OS */ err = riscv_fdt_copy_resv_mem_node(gd->fdt_blob, blob); if (err < 0) return err; return 0; } |