root.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. static const struct driver_info root_info = {
  24. .name = "root_driver",
  25. };
  26. struct udevice *dm_root(void)
  27. {
  28. if (!gd->dm_root) {
  29. dm_warn("Virtual root driver does not exist!\n");
  30. return NULL;
  31. }
  32. return gd->dm_root;
  33. }
  34. #if defined(CONFIG_NEEDS_MANUAL_RELOC)
  35. void fix_drivers(void)
  36. {
  37. struct driver *drv =
  38. ll_entry_start(struct driver, driver);
  39. const int n_ents = ll_entry_count(struct driver, driver);
  40. struct driver *entry;
  41. for (entry = drv; entry != drv + n_ents; entry++) {
  42. if (entry->of_match)
  43. entry->of_match = (const struct udevice_id *)
  44. ((u32)entry->of_match + gd->reloc_off);
  45. if (entry->bind)
  46. entry->bind += gd->reloc_off;
  47. if (entry->probe)
  48. entry->probe += gd->reloc_off;
  49. if (entry->remove)
  50. entry->remove += gd->reloc_off;
  51. if (entry->unbind)
  52. entry->unbind += gd->reloc_off;
  53. if (entry->ofdata_to_platdata)
  54. entry->ofdata_to_platdata += gd->reloc_off;
  55. if (entry->child_pre_probe)
  56. entry->child_pre_probe += gd->reloc_off;
  57. if (entry->child_post_remove)
  58. entry->child_post_remove += gd->reloc_off;
  59. /* OPS are fixed in every uclass post_probe function */
  60. if (entry->ops)
  61. entry->ops += gd->reloc_off;
  62. }
  63. }
  64. void fix_uclass(void)
  65. {
  66. struct uclass_driver *uclass =
  67. ll_entry_start(struct uclass_driver, uclass);
  68. const int n_ents = ll_entry_count(struct uclass_driver, uclass);
  69. struct uclass_driver *entry;
  70. for (entry = uclass; entry != uclass + n_ents; entry++) {
  71. if (entry->post_bind)
  72. entry->post_bind += gd->reloc_off;
  73. if (entry->pre_unbind)
  74. entry->pre_unbind += gd->reloc_off;
  75. if (entry->post_probe)
  76. entry->post_probe += gd->reloc_off;
  77. if (entry->pre_remove)
  78. entry->pre_remove += gd->reloc_off;
  79. if (entry->init)
  80. entry->init += gd->reloc_off;
  81. if (entry->destroy)
  82. entry->destroy += gd->reloc_off;
  83. /* FIXME maybe also need to fix these ops */
  84. if (entry->ops)
  85. entry->ops += gd->reloc_off;
  86. }
  87. }
  88. #endif
  89. int dm_init(void)
  90. {
  91. int ret;
  92. if (gd->dm_root) {
  93. dm_warn("Virtual root driver already exists!\n");
  94. return -EINVAL;
  95. }
  96. INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
  97. #if defined(CONFIG_NEEDS_MANUAL_RELOC)
  98. fix_drivers();
  99. fix_uclass();
  100. #endif
  101. ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
  102. if (ret)
  103. return ret;
  104. #ifdef CONFIG_OF_CONTROL
  105. DM_ROOT_NON_CONST->of_offset = 0;
  106. #endif
  107. ret = device_probe(DM_ROOT_NON_CONST);
  108. if (ret)
  109. return ret;
  110. return 0;
  111. }
  112. int dm_uninit(void)
  113. {
  114. device_remove(dm_root());
  115. device_unbind(dm_root());
  116. return 0;
  117. }
  118. int dm_scan_platdata(bool pre_reloc_only)
  119. {
  120. int ret;
  121. ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
  122. if (ret == -ENOENT) {
  123. dm_warn("Some drivers were not found\n");
  124. ret = 0;
  125. }
  126. return ret;
  127. }
  128. #ifdef CONFIG_OF_CONTROL
  129. int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
  130. bool pre_reloc_only)
  131. {
  132. int ret = 0, err;
  133. for (offset = fdt_first_subnode(blob, offset);
  134. offset > 0;
  135. offset = fdt_next_subnode(blob, offset)) {
  136. if (pre_reloc_only &&
  137. !fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
  138. continue;
  139. if (!fdtdec_get_is_enabled(blob, offset)) {
  140. dm_dbg(" - ignoring disabled device\n");
  141. continue;
  142. }
  143. err = lists_bind_fdt(parent, blob, offset, NULL);
  144. if (err && !ret)
  145. ret = err;
  146. }
  147. if (ret)
  148. dm_warn("Some drivers failed to bind\n");
  149. return ret;
  150. }
  151. int dm_scan_fdt(const void *blob, bool pre_reloc_only)
  152. {
  153. return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
  154. }
  155. #endif
  156. __weak int dm_scan_other(bool pre_reloc_only)
  157. {
  158. return 0;
  159. }
  160. int dm_init_and_scan(bool pre_reloc_only)
  161. {
  162. int ret;
  163. ret = dm_init();
  164. if (ret) {
  165. debug("dm_init() failed: %d\n", ret);
  166. return ret;
  167. }
  168. ret = dm_scan_platdata(pre_reloc_only);
  169. if (ret) {
  170. debug("dm_scan_platdata() failed: %d\n", ret);
  171. return ret;
  172. }
  173. #ifdef CONFIG_OF_CONTROL
  174. ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
  175. if (ret) {
  176. debug("dm_scan_fdt() failed: %d\n", ret);
  177. return ret;
  178. }
  179. #endif
  180. ret = dm_scan_other(pre_reloc_only);
  181. if (ret)
  182. return ret;
  183. return 0;
  184. }
  185. /* This is the root driver - all drivers are children of this */
  186. U_BOOT_DRIVER(root_driver) = {
  187. .name = "root_driver",
  188. .id = UCLASS_ROOT,
  189. };
  190. /* This is the root uclass */
  191. UCLASS_DRIVER(root) = {
  192. .name = "root",
  193. .id = UCLASS_ROOT,
  194. };