fdtaddr.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Device addresses
  4. *
  5. * Copyright (c) 2017 Google, Inc
  6. *
  7. * (C) Copyright 2012
  8. * Pavel Herrmann <morpheus.ibis@gmail.com>
  9. */
  10. #include <common.h>
  11. #include <dm.h>
  12. #include <fdt_support.h>
  13. #include <log.h>
  14. #include <asm/io.h>
  15. #include <dm/device-internal.h>
  16. DECLARE_GLOBAL_DATA_PTR;
  17. fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index)
  18. {
  19. #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
  20. fdt_addr_t addr;
  21. if (CONFIG_IS_ENABLED(OF_TRANSLATE)) {
  22. const fdt32_t *reg;
  23. int len = 0;
  24. int na, ns;
  25. na = fdt_address_cells(gd->fdt_blob,
  26. dev_of_offset(dev->parent));
  27. if (na < 1) {
  28. debug("bad #address-cells\n");
  29. return FDT_ADDR_T_NONE;
  30. }
  31. ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent));
  32. if (ns < 0) {
  33. debug("bad #size-cells\n");
  34. return FDT_ADDR_T_NONE;
  35. }
  36. reg = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "reg",
  37. &len);
  38. if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) {
  39. debug("Req index out of range\n");
  40. return FDT_ADDR_T_NONE;
  41. }
  42. reg += index * (na + ns);
  43. if (ns) {
  44. /*
  45. * Use the full-fledged translate function for complex
  46. * bus setups.
  47. */
  48. addr = fdt_translate_address((void *)gd->fdt_blob,
  49. dev_of_offset(dev), reg);
  50. } else {
  51. /* Non translatable if #size-cells == 0 */
  52. addr = fdt_read_number(reg, na);
  53. }
  54. } else {
  55. /*
  56. * Use the "simple" translate function for less complex
  57. * bus setups.
  58. */
  59. addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob,
  60. dev_of_offset(dev->parent), dev_of_offset(dev),
  61. "reg", index, NULL, false);
  62. if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) {
  63. if (device_get_uclass_id(dev->parent) ==
  64. UCLASS_SIMPLE_BUS)
  65. addr = simple_bus_translate(dev->parent, addr);
  66. }
  67. }
  68. #if defined(CONFIG_TRANSLATION_OFFSET)
  69. /*
  70. * Some platforms need a special address translation. Those
  71. * platforms (e.g. mvebu in SPL) can configure a translation
  72. * offset by setting this value in the GD and enaling this
  73. * feature via CONFIG_TRANSLATION_OFFSET. This value will
  74. * get added to all addresses returned by devfdt_get_addr().
  75. */
  76. addr += gd->translation_offset;
  77. #endif
  78. return addr;
  79. #else
  80. return FDT_ADDR_T_NONE;
  81. #endif
  82. }
  83. fdt_addr_t devfdt_get_addr_size_index(const struct udevice *dev, int index,
  84. fdt_size_t *size)
  85. {
  86. #if CONFIG_IS_ENABLED(OF_CONTROL)
  87. /*
  88. * Only get the size in this first call. We'll get the addr in the
  89. * next call to the exisiting dev_get_xxx function which handles
  90. * all config options.
  91. */
  92. fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev_of_offset(dev),
  93. "reg", index, size, false);
  94. /*
  95. * Get the base address via the existing function which handles
  96. * all Kconfig cases
  97. */
  98. return devfdt_get_addr_index(dev, index);
  99. #else
  100. return FDT_ADDR_T_NONE;
  101. #endif
  102. }
  103. fdt_addr_t devfdt_get_addr_name(const struct udevice *dev, const char *name)
  104. {
  105. #if CONFIG_IS_ENABLED(OF_CONTROL)
  106. int index;
  107. index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
  108. "reg-names", name);
  109. if (index < 0)
  110. return index;
  111. return devfdt_get_addr_index(dev, index);
  112. #else
  113. return FDT_ADDR_T_NONE;
  114. #endif
  115. }
  116. fdt_addr_t devfdt_get_addr_size_name(const struct udevice *dev,
  117. const char *name, fdt_size_t *size)
  118. {
  119. #if CONFIG_IS_ENABLED(OF_CONTROL)
  120. int index;
  121. index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
  122. "reg-names", name);
  123. if (index < 0)
  124. return index;
  125. return devfdt_get_addr_size_index(dev, index, size);
  126. #else
  127. return FDT_ADDR_T_NONE;
  128. #endif
  129. }
  130. fdt_addr_t devfdt_get_addr(const struct udevice *dev)
  131. {
  132. return devfdt_get_addr_index(dev, 0);
  133. }
  134. void *devfdt_get_addr_ptr(const struct udevice *dev)
  135. {
  136. fdt_addr_t addr = devfdt_get_addr_index(dev, 0);
  137. return (addr == FDT_ADDR_T_NONE) ? NULL : (void *)(uintptr_t)addr;
  138. }
  139. void *devfdt_remap_addr_index(const struct udevice *dev, int index)
  140. {
  141. fdt_addr_t addr = devfdt_get_addr_index(dev, index);
  142. if (addr == FDT_ADDR_T_NONE)
  143. return NULL;
  144. return map_physmem(addr, 0, MAP_NOCACHE);
  145. }
  146. void *devfdt_remap_addr_name(const struct udevice *dev, const char *name)
  147. {
  148. fdt_addr_t addr = devfdt_get_addr_name(dev, name);
  149. if (addr == FDT_ADDR_T_NONE)
  150. return NULL;
  151. return map_physmem(addr, 0, MAP_NOCACHE);
  152. }
  153. void *devfdt_remap_addr(const struct udevice *dev)
  154. {
  155. return devfdt_remap_addr_index(dev, 0);
  156. }
  157. void *devfdt_map_physmem(const struct udevice *dev, unsigned long size)
  158. {
  159. fdt_addr_t addr = devfdt_get_addr(dev);
  160. if (addr == FDT_ADDR_T_NONE)
  161. return NULL;
  162. return map_physmem(addr, size, MAP_NOCACHE);
  163. }
  164. fdt_addr_t devfdt_get_addr_pci(const struct udevice *dev)
  165. {
  166. ulong addr;
  167. addr = devfdt_get_addr(dev);
  168. if (CONFIG_IS_ENABLED(PCI) && IS_ENABLED(CONFIG_DM_PCI) &&
  169. addr == FDT_ADDR_T_NONE) {
  170. struct fdt_pci_addr pci_addr;
  171. u32 bar;
  172. int ret;
  173. ret = ofnode_read_pci_addr(dev_ofnode(dev), FDT_PCI_SPACE_MEM32,
  174. "reg", &pci_addr);
  175. if (ret) {
  176. /* try if there is any i/o-mapped register */
  177. ret = ofnode_read_pci_addr(dev_ofnode(dev),
  178. FDT_PCI_SPACE_IO, "reg",
  179. &pci_addr);
  180. if (ret)
  181. return FDT_ADDR_T_NONE;
  182. }
  183. ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar);
  184. if (ret)
  185. return FDT_ADDR_T_NONE;
  186. addr = bar;
  187. }
  188. return addr;
  189. }