root.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright (c) 2013 Google, Inc
  3. *
  4. * (C) Copyright 2012
  5. * Pavel Herrmann <morpheus.ibis@gmail.com>
  6. *
  7. * SPDX-License-Identifier: GPL-2.0+
  8. */
  9. #include <common.h>
  10. #include <errno.h>
  11. #include <fdtdec.h>
  12. #include <malloc.h>
  13. #include <libfdt.h>
  14. #include <dm/device.h>
  15. #include <dm/device-internal.h>
  16. #include <dm/lists.h>
  17. #include <dm/platdata.h>
  18. #include <dm/root.h>
  19. #include <dm/uclass.h>
  20. #include <dm/util.h>
  21. #include <linux/list.h>
  22. DECLARE_GLOBAL_DATA_PTR;
  23. struct root_priv {
  24. fdt_addr_t translation_offset; /* optional translation offset */
  25. };
  26. static const struct driver_info root_info = {
  27. .name = "root_driver",
  28. };
  29. struct udevice *dm_root(void)
  30. {
  31. if (!gd->dm_root) {
  32. dm_warn("Virtual root driver does not exist!\n");
  33. return NULL;
  34. }
  35. return gd->dm_root;
  36. }
  37. fdt_addr_t dm_get_translation_offset(void)
  38. {
  39. struct udevice *root = dm_root();
  40. struct root_priv *priv = dev_get_priv(root);
  41. return priv->translation_offset;
  42. }
  43. void dm_set_translation_offset(fdt_addr_t offs)
  44. {
  45. struct udevice *root = dm_root();
  46. struct root_priv *priv = dev_get_priv(root);
  47. priv->translation_offset = offs;
  48. }
  49. #if defined(CONFIG_NEEDS_MANUAL_RELOC)
  50. void fix_drivers(void)
  51. {
  52. struct driver *drv =
  53. ll_entry_start(struct driver, driver);
  54. const int n_ents = ll_entry_count(struct driver, driver);
  55. struct driver *entry;
  56. for (entry = drv; entry != drv + n_ents; entry++) {
  57. if (entry->of_match)
  58. entry->of_match = (const struct udevice_id *)
  59. ((u32)entry->of_match + gd->reloc_off);
  60. if (entry->bind)
  61. entry->bind += gd->reloc_off;
  62. if (entry->probe)
  63. entry->probe += gd->reloc_off;
  64. if (entry->remove)
  65. entry->remove += gd->reloc_off;
  66. if (entry->unbind)
  67. entry->unbind += gd->reloc_off;
  68. if (entry->ofdata_to_platdata)
  69. entry->ofdata_to_platdata += gd->reloc_off;
  70. if (entry->child_post_bind)
  71. entry->child_post_bind += gd->reloc_off;
  72. if (entry->child_pre_probe)
  73. entry->child_pre_probe += gd->reloc_off;
  74. if (entry->child_post_remove)
  75. entry->child_post_remove += gd->reloc_off;
  76. /* OPS are fixed in every uclass post_probe function */
  77. if (entry->ops)
  78. entry->ops += gd->reloc_off;
  79. }
  80. }
  81. void fix_uclass(void)
  82. {
  83. struct uclass_driver *uclass =
  84. ll_entry_start(struct uclass_driver, uclass);
  85. const int n_ents = ll_entry_count(struct uclass_driver, uclass);
  86. struct uclass_driver *entry;
  87. for (entry = uclass; entry != uclass + n_ents; entry++) {
  88. if (entry->post_bind)
  89. entry->post_bind += gd->reloc_off;
  90. if (entry->pre_unbind)
  91. entry->pre_unbind += gd->reloc_off;
  92. if (entry->pre_probe)
  93. entry->pre_probe += gd->reloc_off;
  94. if (entry->post_probe)
  95. entry->post_probe += gd->reloc_off;
  96. if (entry->pre_remove)
  97. entry->pre_remove += gd->reloc_off;
  98. if (entry->child_post_bind)
  99. entry->child_post_bind += gd->reloc_off;
  100. if (entry->child_pre_probe)
  101. entry->child_pre_probe += gd->reloc_off;
  102. if (entry->init)
  103. entry->init += gd->reloc_off;
  104. if (entry->destroy)
  105. entry->destroy += gd->reloc_off;
  106. /* FIXME maybe also need to fix these ops */
  107. if (entry->ops)
  108. entry->ops += gd->reloc_off;
  109. }
  110. }
  111. void fix_devices(void)
  112. {
  113. struct driver_info *dev =
  114. ll_entry_start(struct driver_info, driver_info);
  115. const int n_ents = ll_entry_count(struct driver_info, driver_info);
  116. struct driver_info *entry;
  117. for (entry = dev; entry != dev + n_ents; entry++) {
  118. if (entry->platdata)
  119. entry->platdata += gd->reloc_off;
  120. }
  121. }
  122. #endif
  123. int dm_init(void)
  124. {
  125. int ret;
  126. if (gd->dm_root) {
  127. dm_warn("Virtual root driver already exists!\n");
  128. return -EINVAL;
  129. }
  130. INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
  131. #if defined(CONFIG_NEEDS_MANUAL_RELOC)
  132. fix_drivers();
  133. fix_uclass();
  134. fix_devices();
  135. #endif
  136. ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
  137. if (ret)
  138. return ret;
  139. #if CONFIG_IS_ENABLED(OF_CONTROL)
  140. DM_ROOT_NON_CONST->of_offset = 0;
  141. #endif
  142. ret = device_probe(DM_ROOT_NON_CONST);
  143. if (ret)
  144. return ret;
  145. return 0;
  146. }
  147. int dm_uninit(void)
  148. {
  149. device_remove(dm_root());
  150. device_unbind(dm_root());
  151. return 0;
  152. }
  153. int dm_scan_platdata(bool pre_reloc_only)
  154. {
  155. int ret;
  156. ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
  157. if (ret == -ENOENT) {
  158. dm_warn("Some drivers were not found\n");
  159. ret = 0;
  160. }
  161. return ret;
  162. }
  163. #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
  164. int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
  165. bool pre_reloc_only)
  166. {
  167. int ret = 0, err;
  168. for (offset = fdt_first_subnode(blob, offset);
  169. offset > 0;
  170. offset = fdt_next_subnode(blob, offset)) {
  171. if (pre_reloc_only &&
  172. !fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
  173. continue;
  174. if (!fdtdec_get_is_enabled(blob, offset)) {
  175. dm_dbg(" - ignoring disabled device\n");
  176. continue;
  177. }
  178. err = lists_bind_fdt(parent, blob, offset, NULL);
  179. if (err && !ret) {
  180. ret = err;
  181. debug("%s: ret=%d\n", fdt_get_name(blob, offset, NULL),
  182. ret);
  183. }
  184. }
  185. if (ret)
  186. dm_warn("Some drivers failed to bind\n");
  187. return ret;
  188. }
  189. int dm_scan_fdt(const void *blob, bool pre_reloc_only)
  190. {
  191. return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
  192. }
  193. #endif
  194. __weak int dm_scan_other(bool pre_reloc_only)
  195. {
  196. return 0;
  197. }
  198. int dm_init_and_scan(bool pre_reloc_only)
  199. {
  200. int ret;
  201. ret = dm_init();
  202. if (ret) {
  203. debug("dm_init() failed: %d\n", ret);
  204. return ret;
  205. }
  206. ret = dm_scan_platdata(pre_reloc_only);
  207. if (ret) {
  208. debug("dm_scan_platdata() failed: %d\n", ret);
  209. return ret;
  210. }
  211. if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
  212. ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
  213. if (ret) {
  214. debug("dm_scan_fdt() failed: %d\n", ret);
  215. return ret;
  216. }
  217. }
  218. ret = dm_scan_other(pre_reloc_only);
  219. if (ret)
  220. return ret;
  221. return 0;
  222. }
  223. /* This is the root driver - all drivers are children of this */
  224. U_BOOT_DRIVER(root_driver) = {
  225. .name = "root_driver",
  226. .id = UCLASS_ROOT,
  227. .priv_auto_alloc_size = sizeof(struct root_priv),
  228. };
  229. /* This is the root uclass */
  230. UCLASS_DRIVER(root) = {
  231. .name = "root",
  232. .id = UCLASS_ROOT,
  233. };