fdtaddr.c 5.1 KB

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