fdt_fixup.c 4.2 KB

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