root.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. #endif
  112. int dm_init(void)
  113. {
  114. int ret;
  115. if (gd->dm_root) {
  116. dm_warn("Virtual root driver already exists!\n");
  117. return -EINVAL;
  118. }
  119. INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
  120. #if defined(CONFIG_NEEDS_MANUAL_RELOC)
  121. fix_drivers();
  122. fix_uclass();
  123. #endif
  124. ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
  125. if (ret)
  126. return ret;
  127. #if CONFIG_IS_ENABLED(OF_CONTROL)
  128. DM_ROOT_NON_CONST->of_offset = 0;
  129. #endif
  130. ret = device_probe(DM_ROOT_NON_CONST);
  131. if (ret)
  132. return ret;
  133. return 0;
  134. }
  135. int dm_uninit(void)
  136. {
  137. device_remove(dm_root());
  138. device_unbind(dm_root());
  139. return 0;
  140. }
  141. int dm_scan_platdata(bool pre_reloc_only)
  142. {
  143. int ret;
  144. ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
  145. if (ret == -ENOENT) {
  146. dm_warn("Some drivers were not found\n");
  147. ret = 0;
  148. }
  149. return ret;
  150. }
  151. #if CONFIG_IS_ENABLED(OF_CONTROL)
  152. int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
  153. bool pre_reloc_only)
  154. {
  155. int ret = 0, err;
  156. for (offset = fdt_first_subnode(blob, offset);
  157. offset > 0;
  158. offset = fdt_next_subnode(blob, offset)) {
  159. if (pre_reloc_only &&
  160. !fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
  161. continue;
  162. if (!fdtdec_get_is_enabled(blob, offset)) {
  163. dm_dbg(" - ignoring disabled device\n");
  164. continue;
  165. }
  166. err = lists_bind_fdt(parent, blob, offset, NULL);
  167. if (err && !ret) {
  168. ret = err;
  169. debug("%s: ret=%d\n", fdt_get_name(blob, offset, NULL),
  170. ret);
  171. }
  172. }
  173. if (ret)
  174. dm_warn("Some drivers failed to bind\n");
  175. return ret;
  176. }
  177. int dm_scan_fdt(const void *blob, bool pre_reloc_only)
  178. {
  179. return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
  180. }
  181. #endif
  182. __weak int dm_scan_other(bool pre_reloc_only)
  183. {
  184. return 0;
  185. }
  186. int dm_init_and_scan(bool pre_reloc_only)
  187. {
  188. int ret;
  189. ret = dm_init();
  190. if (ret) {
  191. debug("dm_init() failed: %d\n", ret);
  192. return ret;
  193. }
  194. ret = dm_scan_platdata(pre_reloc_only);
  195. if (ret) {
  196. debug("dm_scan_platdata() failed: %d\n", ret);
  197. return ret;
  198. }
  199. if (CONFIG_IS_ENABLED(OF_CONTROL)) {
  200. ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
  201. if (ret) {
  202. debug("dm_scan_fdt() failed: %d\n", ret);
  203. return ret;
  204. }
  205. }
  206. ret = dm_scan_other(pre_reloc_only);
  207. if (ret)
  208. return ret;
  209. return 0;
  210. }
  211. /* This is the root driver - all drivers are children of this */
  212. U_BOOT_DRIVER(root_driver) = {
  213. .name = "root_driver",
  214. .id = UCLASS_ROOT,
  215. .priv_auto_alloc_size = sizeof(struct root_priv),
  216. };
  217. /* This is the root uclass */
  218. UCLASS_DRIVER(root) = {
  219. .name = "root",
  220. .id = UCLASS_ROOT,
  221. };