fdt_fixup.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2020 Western Digital Corporation or its affiliates
  4. *
  5. */
  6. #include <common.h>
  7. #include <fdt_support.h>
  8. #include <mapmem.h>
  9. DECLARE_GLOBAL_DATA_PTR;
  10. /**
  11. * riscv_fdt_copy_resv_mem_node() - Copy reserve memory node entry
  12. * @src: Pointer to the source device tree from which reserved memory node
  13. * needs to be copied.
  14. * @dst: Pointer to the destination device tree to which reserved memory node
  15. * needs to be copied.
  16. *
  17. * Return: 0 on success or if source doesn't have reserved memory node.
  18. * Error if copy process failed.
  19. */
  20. int riscv_fdt_copy_resv_mem_node(const void *src, void *dst)
  21. {
  22. u32 phandle;
  23. struct fdt_memory pmp_mem;
  24. fdt_addr_t addr;
  25. fdt_size_t size;
  26. int offset, node, err, rmem_offset;
  27. bool nomap = true;
  28. char basename[32] = {0};
  29. int bname_len;
  30. int max_len = sizeof(basename);
  31. const char *name;
  32. char *temp;
  33. offset = fdt_path_offset(src, "/reserved-memory");
  34. if (offset < 0) {
  35. printf("No reserved memory region found in source FDT\n");
  36. return 0;
  37. }
  38. fdt_for_each_subnode(node, src, offset) {
  39. name = fdt_get_name(src, node, NULL);
  40. addr = fdtdec_get_addr_size_auto_noparent(src, node,
  41. "reg", 0, &size,
  42. false);
  43. if (addr == FDT_ADDR_T_NONE) {
  44. debug("failed to read address/size for %s\n", name);
  45. continue;
  46. }
  47. strncpy(basename, name, max_len);
  48. temp = strchr(basename, '@');
  49. if (temp) {
  50. bname_len = strnlen(basename, max_len) - strnlen(temp,
  51. max_len);
  52. *(basename + bname_len) = '\0';
  53. }
  54. pmp_mem.start = addr;
  55. pmp_mem.end = addr + size - 1;
  56. err = fdtdec_add_reserved_memory(dst, basename, &pmp_mem,
  57. &phandle);
  58. if (err < 0) {
  59. printf("failed to add reserved memory: %d\n", err);
  60. return err;
  61. }
  62. if (!fdt_getprop(src, node, "no-map", NULL))
  63. nomap = false;
  64. if (nomap) {
  65. rmem_offset = fdt_node_offset_by_phandle(dst, phandle);
  66. fdt_setprop_empty(dst, rmem_offset, "no-map");
  67. }
  68. }
  69. return 0;
  70. }
  71. /**
  72. * riscv_board_reserved_mem_fixup() - Fix up reserved memory node for a board
  73. * @fdt: Pointer to the device tree in which reserved memory node needs to be
  74. * added.
  75. *
  76. * In RISC-V, any board compiled with OF_SEPARATE needs to copy the reserved
  77. * memory node from the device tree provided by the firmware to the device tree
  78. * used by U-Boot. This is a common function that individual board fixup
  79. * functions can invoke.
  80. *
  81. * Return: 0 on success or error otherwise.
  82. */
  83. int riscv_board_reserved_mem_fixup(void *fdt)
  84. {
  85. int err;
  86. void *src_fdt_addr;
  87. src_fdt_addr = map_sysmem(gd->arch.firmware_fdt_addr, 0);
  88. err = riscv_fdt_copy_resv_mem_node(src_fdt_addr, fdt);
  89. if (err < 0)
  90. return err;
  91. return 0;
  92. }
  93. #ifdef CONFIG_OF_BOARD_FIXUP
  94. int board_fix_fdt(void *fdt)
  95. {
  96. int err;
  97. err = riscv_board_reserved_mem_fixup(fdt);
  98. if (err < 0) {
  99. printf("failed to fixup DT for reserved memory: %d\n", err);
  100. return err;
  101. }
  102. return 0;
  103. }
  104. #endif