fdtaddr.c 5.5 KB

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