root.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 <malloc.h>
  12. #include <libfdt.h>
  13. #include <dm/device.h>
  14. #include <dm/device-internal.h>
  15. #include <dm/lists.h>
  16. #include <dm/platdata.h>
  17. #include <dm/root.h>
  18. #include <dm/uclass.h>
  19. #include <dm/util.h>
  20. #include <linux/list.h>
  21. DECLARE_GLOBAL_DATA_PTR;
  22. static const struct driver_info root_info = {
  23. .name = "root_driver",
  24. };
  25. struct udevice *dm_root(void)
  26. {
  27. if (!gd->dm_root) {
  28. dm_warn("Virtual root driver does not exist!\n");
  29. return NULL;
  30. }
  31. return gd->dm_root;
  32. }
  33. int dm_init(void)
  34. {
  35. int ret;
  36. if (gd->dm_root) {
  37. dm_warn("Virtual root driver already exists!\n");
  38. return -EINVAL;
  39. }
  40. INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
  41. ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
  42. if (ret)
  43. return ret;
  44. #ifdef CONFIG_OF_CONTROL
  45. DM_ROOT_NON_CONST->of_offset = 0;
  46. #endif
  47. ret = device_probe(DM_ROOT_NON_CONST);
  48. if (ret)
  49. return ret;
  50. return 0;
  51. }
  52. int dm_uninit(void)
  53. {
  54. device_remove(dm_root());
  55. device_unbind(dm_root());
  56. return 0;
  57. }
  58. int dm_scan_platdata(bool pre_reloc_only)
  59. {
  60. int ret;
  61. ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
  62. if (ret == -ENOENT) {
  63. dm_warn("Some drivers were not found\n");
  64. ret = 0;
  65. }
  66. return ret;
  67. }
  68. #ifdef CONFIG_OF_CONTROL
  69. int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
  70. bool pre_reloc_only)
  71. {
  72. int ret = 0, err;
  73. for (offset = fdt_first_subnode(blob, offset);
  74. offset > 0;
  75. offset = fdt_next_subnode(blob, offset)) {
  76. if (pre_reloc_only &&
  77. !fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
  78. continue;
  79. err = lists_bind_fdt(parent, blob, offset, NULL);
  80. if (err && !ret)
  81. ret = err;
  82. }
  83. if (ret)
  84. dm_warn("Some drivers failed to bind\n");
  85. return ret;
  86. }
  87. int dm_scan_fdt(const void *blob, bool pre_reloc_only)
  88. {
  89. return dm_scan_fdt_node(gd->dm_root, blob, 0, pre_reloc_only);
  90. }
  91. #endif
  92. __weak int dm_scan_other(bool pre_reloc_only)
  93. {
  94. return 0;
  95. }
  96. int dm_init_and_scan(bool pre_reloc_only)
  97. {
  98. int ret;
  99. ret = dm_init();
  100. if (ret) {
  101. debug("dm_init() failed: %d\n", ret);
  102. return ret;
  103. }
  104. ret = dm_scan_platdata(pre_reloc_only);
  105. if (ret) {
  106. debug("dm_scan_platdata() failed: %d\n", ret);
  107. return ret;
  108. }
  109. #ifdef CONFIG_OF_CONTROL
  110. ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
  111. if (ret) {
  112. debug("dm_scan_fdt() failed: %d\n", ret);
  113. return ret;
  114. }
  115. #endif
  116. ret = dm_scan_other(pre_reloc_only);
  117. if (ret)
  118. return ret;
  119. return 0;
  120. }
  121. /* This is the root driver - all drivers are children of this */
  122. U_BOOT_DRIVER(root_driver) = {
  123. .name = "root_driver",
  124. .id = UCLASS_ROOT,
  125. };
  126. /* This is the root uclass */
  127. UCLASS_DRIVER(root) = {
  128. .name = "root",
  129. .id = UCLASS_ROOT,
  130. };