platform_ofw.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-06-04 GuEe-GUI the first version
  9. */
  10. #include <rtthread.h>
  11. #define DBG_TAG "drv.platform"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. #include <drivers/platform.h>
  15. #include <drivers/core/dm.h>
  16. static const struct rt_ofw_node_id platform_ofw_ids[] =
  17. {
  18. { .compatible = "simple-bus", },
  19. #ifdef RT_USING_MFD
  20. { .compatible = "simple-mfd", },
  21. #endif
  22. #ifdef RT_USING_ISA
  23. { .compatible = "isa", },
  24. #endif
  25. #ifdef RT_USING_AMBA_BUS
  26. /*
  27. * Maybe ARM has replaced it with compatible: "arm,primecell" and will not
  28. * used anymore in the future.
  29. */
  30. { .compatible = "arm,amba-bus", },
  31. #endif
  32. { /* sentinel */ }
  33. };
  34. static rt_err_t platform_ofw_device_probe_once(struct rt_ofw_node *parent_np)
  35. {
  36. rt_err_t err = RT_EOK;
  37. struct rt_ofw_node *np, *child;
  38. struct rt_platform_device *pdev;
  39. rt_ofw_foreach_available_child_node(parent_np, np)
  40. {
  41. const char *name;
  42. struct rt_ofw_node_id *id;
  43. struct rt_ofw_prop *compat_prop = RT_NULL;
  44. /* Is system node or have driver */
  45. if (rt_ofw_node_test_flag(np, RT_OFW_F_SYSTEM) ||
  46. rt_ofw_node_test_flag(np, RT_OFW_F_READLY))
  47. {
  48. continue;
  49. }
  50. compat_prop = rt_ofw_get_prop(np, "compatible", RT_NULL);
  51. name = rt_ofw_node_name(np);
  52. /* Not have name and compatible */
  53. if (!compat_prop && (name == (const char *)"<NULL>" || !rt_strcmp(name, "<NULL>")))
  54. {
  55. continue;
  56. }
  57. id = rt_ofw_prop_match(compat_prop, platform_ofw_ids);
  58. if (id && (child = rt_ofw_get_next_child(np, RT_NULL)))
  59. {
  60. /* scan next level */
  61. err = platform_ofw_device_probe_once(child);
  62. rt_ofw_node_put(child);
  63. if (err)
  64. {
  65. LOG_E("%s bus probe fail", np->full_name);
  66. break;
  67. }
  68. }
  69. pdev = rt_platform_device_alloc(np->name);
  70. if (!pdev)
  71. {
  72. err = -RT_ENOMEM;
  73. break;
  74. }
  75. /* inc reference of dt-node */
  76. rt_ofw_node_get(np);
  77. rt_ofw_node_set_flag(np, RT_OFW_F_PLATFORM);
  78. pdev->parent.ofw_node = np;
  79. rt_platform_device_register(pdev);
  80. }
  81. return err;
  82. }
  83. static int platform_ofw_device_probe(void)
  84. {
  85. rt_err_t err = RT_EOK;
  86. struct rt_ofw_node *root_np;
  87. root_np = rt_ofw_find_node_by_path("/");
  88. if (root_np)
  89. {
  90. err = platform_ofw_device_probe_once(root_np);
  91. rt_ofw_node_put(root_np);
  92. }
  93. else
  94. {
  95. err = -RT_ENOSYS;
  96. }
  97. return (int)err;
  98. }
  99. INIT_PLATFORM_EXPORT(platform_ofw_device_probe);