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