Sfoglia il codice sorgente

[drivers][core] 完善设备模型 (#8384)

fangjianzhou 1 anno fa
parent
commit
10b16273b8

+ 236 - 126
components/drivers/core/bus.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -10,7 +10,6 @@
  */
 
 #include <rtthread.h>
-#include <rtdevice.h>
 
 #include <string.h>
 #include <stdlib.h>
@@ -19,16 +18,6 @@
 #define DBG_LVL DBG_INFO
 #include <rtdbg.h>
 
-#ifdef RT_USING_DM
-#include <drivers/core/bus.h>
-
-static struct rt_bus bus_root =
-{
-    .name = "root",
-    .children = RT_LIST_OBJECT_INIT(bus_root.children),
-};
-#endif
-
 #ifdef RT_USING_DEV_BUS
 
 #if defined(RT_USING_POSIX_DEVIO)
@@ -95,12 +84,19 @@ rt_err_t rt_device_bus_destroy(rt_device_t dev)
 #endif
 
 #ifdef RT_USING_DM
-/**
- * @brief This function get the root bus
- */
-rt_bus_t rt_bus_root(void)
+#include <drivers/core/bus.h>
+
+static struct rt_spinlock bus_lock = {};
+static rt_list_t bus_nodes = RT_LIST_OBJECT_INIT(bus_nodes);
+
+static void _dm_bus_lock(struct rt_spinlock *spinlock)
+{
+    rt_hw_spin_lock(&spinlock->lock);
+}
+
+static void _dm_bus_unlock(struct rt_spinlock *spinlock)
 {
-    return &bus_root;
+    rt_hw_spin_unlock(&spinlock->lock);
 }
 
 /**
@@ -108,30 +104,43 @@ rt_bus_t rt_bus_root(void)
  *
  *  @param bus the target bus
  *
- *  @param drv the target drv to be matched
+ *  @param data the data push when call fn
  *
  *  @param fn  the function callback in each loop
  *
  *  @return the error code, RT_EOK on added successfully.
  */
-rt_err_t rt_bus_for_each_dev(rt_bus_t bus, rt_driver_t drv, int (*fn)(rt_driver_t drv, rt_device_t dev))
+rt_err_t rt_bus_for_each_dev(rt_bus_t bus, void *data, int (*fn)(rt_device_t dev, void *))
 {
-    rt_base_t level;
     rt_device_t dev;
+    rt_err_t err = -RT_EEMPTY;
+    rt_list_t *dev_list;
+    struct rt_spinlock *dev_lock;
 
     RT_ASSERT(bus != RT_NULL);
-    RT_ASSERT(drv != RT_NULL);
 
-    level = rt_spin_lock_irqsave(&bus->spinlock);
+    dev_list = &bus->dev_list;
+    dev_lock = &bus->dev_lock;
+
+    _dm_bus_lock(dev_lock);
+    dev = rt_list_entry(dev_list->next, struct rt_device, node);
+    _dm_bus_unlock(dev_lock);
 
-    rt_list_for_each_entry(dev, &bus->dev_list, node)
+    while (&dev->node != dev_list)
     {
-        fn(drv, dev);
-    }
+        if (!fn(dev, data))
+        {
+            err = RT_EOK;
 
-    rt_spin_unlock_irqrestore(&bus->spinlock, level);
+            break;
+        }
 
-    return RT_EOK;
+        _dm_bus_lock(dev_lock);
+        dev = rt_list_entry(dev->node.next, struct rt_device, node);
+        _dm_bus_unlock(dev_lock);
+    }
+
+    return err;
 }
 
 /**
@@ -139,104 +148,97 @@ rt_err_t rt_bus_for_each_dev(rt_bus_t bus, rt_driver_t drv, int (*fn)(rt_driver_
  *
  *  @param bus the target bus
  *
- *  @param dev the target dev to be matched
+ *  @param data the data push when call fn
  *
  *  @param fn  the function callback in each loop
  *
  *  @return the error code, RT_EOK on added successfully.
  */
-rt_err_t rt_bus_for_each_drv(rt_bus_t bus, rt_device_t dev, int (*fn)(rt_driver_t drv, rt_device_t dev))
+rt_err_t rt_bus_for_each_drv(rt_bus_t bus, void *data, int (*fn)(rt_driver_t drv, void *))
 {
-    rt_err_t err;
-    rt_base_t level;
     rt_driver_t drv;
+    rt_err_t err = -RT_EEMPTY;
+    rt_list_t *drv_list;
+    struct rt_spinlock *drv_lock;
 
     RT_ASSERT(bus != RT_NULL);
-    RT_ASSERT(dev != RT_NULL);
-
-    if (rt_list_isempty(&bus->drv_list))
-    {
-        return RT_EOK;
-    }
 
-    err = -RT_ERROR;
+    drv_list = &bus->drv_list;
+    drv_lock = &bus->drv_lock;
 
-    level = rt_spin_lock_irqsave(&bus->spinlock);
+    _dm_bus_lock(drv_lock);
+    drv = rt_list_entry(drv_list->next, struct rt_driver, node);
+    _dm_bus_unlock(drv_lock);
 
-    rt_list_for_each_entry(drv, &bus->drv_list, node)
+    while (&drv->node != drv_list)
     {
-        if (fn(drv, dev))
+        if (!fn(drv, data))
         {
-            err = -RT_EOK;
+            err = RT_EOK;
 
             break;
         }
-    }
 
-    rt_spin_unlock_irqrestore(&bus->spinlock, level);
+        _dm_bus_lock(drv_lock);
+        drv = rt_list_entry(drv->node.next, struct rt_driver, node);
+        _dm_bus_unlock(drv_lock);
+    }
 
     return err;
 }
 
-/**
- *  @brief This function add a bus to the root
- *
- *  @param bus_node the bus to be added
- *
- *  @return the error code, RT_EOK on added successfully.
- */
-rt_err_t rt_bus_add(rt_bus_t bus_node)
-{
-    rt_base_t level;
-
-    RT_ASSERT(bus_node != RT_NULL);
-
-    bus_node->bus = &bus_root;
-    rt_list_init(&bus_node->list);
-
-    level = rt_spin_lock_irqsave(&bus_node->spinlock);
-
-    rt_list_insert_before(&bus_root.children, &bus_node->list);
-
-    rt_spin_unlock_irqrestore(&bus_node->spinlock, level);
-
-    return RT_EOK;
-}
-
-/**
- *  @brief This function match the device and driver, probe them if match successed
- *
- *  @param drv the drv to match/probe
- *
- *  @param dev the dev to match/probe
- *
- *  @return the result of probe, 1 on added successfully.
- */
-static int rt_bus_probe(rt_driver_t drv, rt_device_t dev)
+static rt_err_t bus_probe(rt_driver_t drv, rt_device_t dev)
 {
-    int ret = 0;
     rt_bus_t bus = drv->bus;
+    rt_err_t err = -RT_EEMPTY;
 
     if (!bus)
     {
         bus = dev->bus;
     }
 
-    RT_ASSERT(bus != RT_NULL);
-
     if (!dev->drv && bus->match(drv, dev))
     {
         dev->drv = drv;
 
-        ret = bus->probe(dev);
+        err = bus->probe(dev);
 
-        if (ret)
+        if (err)
         {
             dev->drv = RT_NULL;
         }
     }
 
-    return ret;
+    return err;
+}
+
+static int bus_probe_driver(rt_device_t dev, void *drv_ptr)
+{
+    bus_probe(drv_ptr, dev);
+
+    /*
+     * The driver is shared by multiple devices,
+     * so we always return the '1' to enumerate all devices.
+     */
+    return 1;
+}
+
+static int bus_probe_device(rt_driver_t drv, void *dev_ptr)
+{
+    rt_err_t err;
+
+    err = bus_probe(drv, dev_ptr);
+
+    if (!err)
+    {
+        rt_bus_t bus = drv->bus;
+
+        _dm_bus_lock(&bus->drv_lock);
+        ++drv->ref_count;
+        _dm_bus_unlock(&bus->drv_lock);
+    }
+
+    return err;
 }
 
 /**
@@ -250,20 +252,17 @@ static int rt_bus_probe(rt_driver_t drv, rt_device_t dev)
  */
 rt_err_t rt_bus_add_driver(rt_bus_t bus, rt_driver_t drv)
 {
-    rt_base_t level;
-
     RT_ASSERT(bus != RT_NULL);
     RT_ASSERT(drv != RT_NULL);
 
     drv->bus = bus;
+    rt_list_init(&drv->node);
 
-    level = rt_spin_lock_irqsave(&bus->spinlock);
-
+    _dm_bus_lock(&bus->drv_lock);
     rt_list_insert_before(&bus->drv_list, &drv->node);
+    _dm_bus_unlock(&bus->drv_lock);
 
-    rt_spin_unlock_irqrestore(&bus->spinlock, level);
-
-    rt_bus_for_each_dev(drv->bus, drv, rt_bus_probe);
+    rt_bus_for_each_dev(bus, drv, bus_probe_driver);
 
     return RT_EOK;
 }
@@ -279,20 +278,17 @@ rt_err_t rt_bus_add_driver(rt_bus_t bus, rt_driver_t drv)
  */
 rt_err_t rt_bus_add_device(rt_bus_t bus, rt_device_t dev)
 {
-    rt_base_t level;
-
     RT_ASSERT(bus != RT_NULL);
     RT_ASSERT(dev != RT_NULL);
 
     dev->bus = bus;
+    rt_list_init(&dev->node);
 
-    level = rt_spin_lock_irqsave(&bus->spinlock);
-
+    _dm_bus_lock(&bus->dev_lock);
     rt_list_insert_before(&bus->dev_list, &dev->node);
+    _dm_bus_unlock(&bus->dev_lock);
 
-    rt_spin_unlock_irqrestore(&bus->spinlock, level);
-
-    rt_bus_for_each_drv(dev->bus, dev, rt_bus_probe);
+    rt_bus_for_each_drv(bus, dev, bus_probe_device);
 
     return RT_EOK;
 }
@@ -306,13 +302,31 @@ rt_err_t rt_bus_add_device(rt_bus_t bus, rt_device_t dev)
  */
 rt_err_t rt_bus_remove_driver(rt_driver_t drv)
 {
+    rt_err_t err;
+    rt_bus_t bus;
+
+    RT_ASSERT(drv != RT_NULL);
     RT_ASSERT(drv->bus != RT_NULL);
 
-    LOG_D("Bus(%s) remove driver %s", drv->bus->name, drv->name);
+    bus = drv->bus;
 
-    rt_list_remove(&drv->node);
+    LOG_D("Bus(%s) remove driver %s", bus->name, drv->parent.name);
 
-    return RT_EOK;
+    _dm_bus_lock(&bus->drv_lock);
+
+    if (drv->ref_count)
+    {
+        err = -RT_EBUSY;
+    }
+    else
+    {
+        rt_list_remove(&drv->node);
+        err = RT_EOK;
+    }
+
+    _dm_bus_unlock(&bus->drv_lock);
+
+    return err;
 }
 
 /**
@@ -324,13 +338,104 @@ rt_err_t rt_bus_remove_driver(rt_driver_t drv)
  */
 rt_err_t rt_bus_remove_device(rt_device_t dev)
 {
+    rt_bus_t bus;
+    rt_driver_t drv;
+    rt_err_t err = RT_EOK;
+
+    RT_ASSERT(dev != RT_NULL);
     RT_ASSERT(dev->bus != RT_NULL);
 
-    LOG_D("Bus(%s) remove device %s", dev->bus->name, dev->name);
+    bus = dev->bus;
+    drv = dev->drv;
 
+    LOG_D("Bus(%s) remove device %s", bus->name, dev->parent.name);
+
+    _dm_bus_lock(&bus->dev_lock);
     rt_list_remove(&dev->node);
+    _dm_bus_unlock(&bus->dev_lock);
 
-    return RT_EOK;
+    if (dev->bus->remove)
+    {
+        err = dev->bus->remove(dev);
+    }
+    else if (drv)
+    {
+        if (drv->shutdown)
+        {
+            err = drv->shutdown(dev);
+        }
+
+        /* device and driver are in the same bus */
+        _dm_bus_lock(&bus->drv_lock);
+        --drv->ref_count;
+        _dm_bus_unlock(&bus->drv_lock);
+    }
+
+    return err;
+}
+
+struct bus_shutdown_info
+{
+    rt_bus_t bus;
+
+    rt_err_t err;
+};
+
+static int device_shutdown(rt_device_t dev, void *info_ptr)
+{
+    rt_bus_t bus;
+    rt_err_t err = RT_EOK;
+    struct bus_shutdown_info *info = info_ptr;
+
+    bus = info->bus;
+
+    if (bus->shutdown)
+    {
+        LOG_D("Device(%s) shutdown", dev->parent.name);
+        err = bus->shutdown(dev);
+        LOG_D("  Result: %s", rt_strerror(err));
+    }
+    else if (dev->drv && dev->drv->shutdown)
+    {
+        LOG_D("Device(%s) shutdown", dev->parent.name);
+        err = dev->drv->shutdown(dev);
+        LOG_D("  Result: %s", rt_strerror(err));
+    }
+
+    if (err)
+    {
+        /* Only get the last one while system not crash */
+        info->err = err;
+    }
+
+    /* Go on, we want to ask all devices to shutdown */
+    return 1;
+}
+
+/**
+ *  @brief This function call all buses' shutdown
+ *
+ *  @return the error code, RT_EOK on shutdown successfully.
+ */
+rt_err_t rt_bus_shutdown(void)
+{
+    rt_bus_t bus = RT_NULL;
+    struct bus_shutdown_info info =
+    {
+        .err = RT_EOK,
+    };
+
+    _dm_bus_lock(&bus_lock);
+
+    rt_list_for_each_entry(bus, &bus_nodes, list)
+    {
+        info.bus = bus;
+        rt_bus_for_each_dev(bus, &info, device_shutdown);
+    }
+
+    _dm_bus_unlock(&bus_lock);
+
+    return info.err;
 }
 
 /**
@@ -339,24 +444,24 @@ rt_err_t rt_bus_remove_device(rt_device_t dev)
  *
  *  @return the bus finded by name.
  */
-rt_bus_t rt_bus_find_by_name(char *name)
+rt_bus_t rt_bus_find_by_name(const char *name)
 {
     rt_bus_t bus = RT_NULL;
-    struct rt_list_node *node = RT_NULL;
 
-    if (!rt_list_isempty(&bus_root.children))
+    RT_ASSERT(name != RT_NULL);
+
+    _dm_bus_lock(&bus_lock);
+
+    rt_list_for_each_entry(bus, &bus_nodes, list)
     {
-        rt_list_for_each(node, &bus_root.children)
+        if (!rt_strncmp(bus->name, name, RT_NAME_MAX))
         {
-            bus = rt_list_entry(node, struct rt_bus, list);
-
-            if (!rt_strncmp(bus->name, name, RT_NAME_MAX))
-            {
-                return bus;
-            }
+            break;
         }
     }
 
+    _dm_bus_unlock(&bus_lock);
+
     return bus;
 }
 
@@ -371,22 +476,20 @@ rt_bus_t rt_bus_find_by_name(char *name)
  */
 rt_err_t rt_bus_reload_driver_device(rt_bus_t new_bus, rt_device_t dev)
 {
-    rt_base_t level;
+    rt_bus_t old_bus;
 
     RT_ASSERT(new_bus != RT_NULL);
     RT_ASSERT(dev != RT_NULL);
+    RT_ASSERT(dev->bus != RT_NULL);
+    RT_ASSERT(dev->bus != new_bus);
 
-    level = rt_spin_lock_irqsave(&new_bus->spinlock);
+    old_bus = dev->bus;
 
+    _dm_bus_lock(&old_bus->dev_lock);
     rt_list_remove(&dev->node);
-    rt_list_insert_before(&new_bus->dev_list, &dev->node);
-
-    rt_list_remove(&dev->drv->node);
-    rt_list_insert_before(&new_bus->drv_list, &dev->drv->node);
+    _dm_bus_unlock(&old_bus->dev_lock);
 
-    rt_spin_unlock_irqrestore(&new_bus->spinlock, level);
-
-    return RT_EOK;
+    return rt_bus_add_device(new_bus, dev);
 }
 
 /**
@@ -397,13 +500,20 @@ rt_err_t rt_bus_reload_driver_device(rt_bus_t new_bus, rt_device_t dev)
  */
 rt_err_t rt_bus_register(rt_bus_t bus)
 {
-    rt_list_init(&bus->children);
+    RT_ASSERT(bus != RT_NULL);
+
+    rt_list_init(&bus->list);
     rt_list_init(&bus->dev_list);
     rt_list_init(&bus->drv_list);
 
-    rt_spin_lock_init(&bus->spinlock);
+    rt_spin_lock_init(&bus->dev_lock);
+    rt_spin_lock_init(&bus->drv_lock);
+
+    _dm_bus_lock(&bus_lock);
+
+    rt_list_insert_before(&bus_nodes, &bus->list);
 
-    rt_bus_add(bus);
+    _dm_bus_unlock(&bus_lock);
 
     return RT_EOK;
 }

+ 317 - 8
components/drivers/core/dm.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -10,6 +10,10 @@
 
 #include <rtthread.h>
 
+#ifdef RT_USING_OFW
+#include <drivers/ofw_io.h>
+#include <drivers/ofw_irq.h>
+#endif
 #include <drivers/core/dm.h>
 
 #ifdef RT_USING_SMP
@@ -56,10 +60,10 @@ struct prefix_track
     int uid;
     const char *prefix;
 };
-static struct rt_spinlock _prefix_nodes_lock;
+static struct rt_spinlock _prefix_nodes_lock = { 0 };
 static rt_list_t _prefix_nodes = RT_LIST_OBJECT_INIT(_prefix_nodes);
 
-int rt_dm_set_dev_name_auto(rt_device_t dev, const char *prefix)
+int rt_dm_dev_set_name_auto(rt_device_t dev, const char *prefix)
 {
     int uid = -1;
     struct prefix_track *pt = RT_NULL;
@@ -104,17 +108,17 @@ int rt_dm_set_dev_name_auto(rt_device_t dev, const char *prefix)
         rt_spin_unlock(&_prefix_nodes_lock);
     }
 
-    return rt_dm_set_dev_name(dev, "%s%u", prefix, uid);
+    return rt_dm_dev_set_name(dev, "%s%u", prefix, uid);
 }
 
-int rt_dm_get_dev_name_id(rt_device_t dev)
+int rt_dm_dev_get_name_id(rt_device_t dev)
 {
     int id = 0, len;
     const char *name;
 
     RT_ASSERT(dev != RT_NULL);
 
-    name = rt_dm_get_dev_name(dev);
+    name = rt_dm_dev_get_name(dev);
     len = rt_strlen(name) - 1;
     name += len;
 
@@ -137,7 +141,7 @@ int rt_dm_get_dev_name_id(rt_device_t dev)
     return id;
 }
 
-int rt_dm_set_dev_name(rt_device_t dev, const char *format, ...)
+int rt_dm_dev_set_name(rt_device_t dev, const char *format, ...)
 {
     int n;
     va_list arg_ptr;
@@ -152,9 +156,314 @@ int rt_dm_set_dev_name(rt_device_t dev, const char *format, ...)
     return n;
 }
 
-const char *rt_dm_get_dev_name(rt_device_t dev)
+const char *rt_dm_dev_get_name(rt_device_t dev)
 {
     RT_ASSERT(dev != RT_NULL);
 
     return dev->parent.name;
 }
+
+#ifdef RT_USING_OFW
+#define ofw_api_call(name, ...)    rt_ofw_##name(__VA_ARGS__)
+#define ofw_api_call_ptr(name, ...) ofw_api_call(name, __VA_ARGS__)
+#else
+#define ofw_api_call(name, ...)   (-RT_ENOSYS)
+#define ofw_api_call_ptr(name, ...) RT_NULL
+#endif
+
+int rt_dm_dev_get_address_count(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(get_address_count, dev->ofw_node);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+rt_err_t rt_dm_dev_get_address(rt_device_t dev, int index,
+        rt_uint64_t *out_address, rt_uint64_t *out_size)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(get_address, dev->ofw_node, index,
+                out_address, out_size);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+rt_err_t rt_dm_dev_get_address_by_name(rt_device_t dev, const char *name,
+        rt_uint64_t *out_address, rt_uint64_t *out_size)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(get_address_by_name, dev->ofw_node, name,
+                out_address, out_size);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+int rt_dm_dev_get_address_array(rt_device_t dev, int nr, rt_uint64_t *out_regs)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(get_address_array, dev->ofw_node, nr, out_regs);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+void *rt_dm_dev_iomap(rt_device_t dev, int index)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call_ptr(iomap, dev->ofw_node, index);
+    }
+#endif
+
+    return RT_NULL;
+}
+
+void *rt_dm_dev_iomap_by_name(rt_device_t dev, const char *name)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call_ptr(iomap_by_name, dev->ofw_node, name);
+    }
+#endif
+
+    return RT_NULL;
+}
+
+int rt_dm_dev_get_irq_count(rt_device_t dev)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(get_irq_count, dev->ofw_node);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+int rt_dm_dev_get_irq(rt_device_t dev, int index)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(get_irq, dev->ofw_node, index);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+int rt_dm_dev_get_irq_by_name(rt_device_t dev, const char *name)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(get_irq_by_name, dev->ofw_node, name);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+void rt_dm_dev_bind_fwdata(rt_device_t dev, void *fw_np, void *data)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (!dev->ofw_node && fw_np)
+    {
+        dev->ofw_node = fw_np;
+        rt_ofw_data(fw_np) = data;
+    }
+
+    if (dev->ofw_node == RT_NULL)
+    {
+        rt_kprintf("[%s:%s] line=%d ofw_node is NULL\r\n", __FILE__, __func__, __LINE__);
+        return;
+    }
+
+    rt_ofw_data(dev->ofw_node) = data;
+#endif
+}
+
+void rt_dm_dev_unbind_fwdata(rt_device_t dev, void *fw_np)
+{
+    RT_ASSERT(dev!= RT_NULL);
+
+#ifdef RT_USING_OFW
+    void *dev_fw_np;
+
+    if (!dev->ofw_node && fw_np)
+    {
+        dev_fw_np = fw_np;
+        rt_ofw_data(fw_np) = RT_NULL;
+    }
+
+    if (dev_fw_np == RT_NULL)
+    {
+        rt_kprintf("[%s:%s] line=%d dev_fw_np is NULL\r\n", __FILE__, __func__, __LINE__);
+        return;
+    }
+
+    rt_ofw_data(dev_fw_np) = RT_NULL;
+#endif
+}
+
+int rt_dm_dev_prop_read_u8_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, rt_uint8_t *out_values)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_UISNG_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(prop_read_u8_array_index, dev->ofw_node, propname,
+                index, nr, out_value);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+int rt_dm_dev_prop_read_u16_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, rt_uint16_t *out_values)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(prop_read_u16_array_index, dev->ofw_node, propname,
+                index, nr, out_values);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+int rt_dm_dev_prop_read_u32_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, rt_uint32_t *out_values)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(prop_read_u32_array_index, dev->ofw_node, propname,
+                index, nr, out_values);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+int rt_dm_dev_prop_read_u64_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, rt_uint64_t *out_values)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(prop_read_u64_array_index, dev->ofw_node, propname,
+                index, nr, out_values);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+int rt_dm_dev_prop_read_string_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, const char **out_strings)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(prop_read_string_array_index, dev->ofw_node, propname,
+                index, nr, out_strings);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+int rt_dm_dev_prop_count_of_size(rt_device_t dev, const char *propname, int size)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(prop_count_of_size, dev->ofw_node, propname, size);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+int rt_dm_dev_prop_index_of_string(rt_device_t dev, const char *propname, const char *string)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(prop_index_of_string, dev->ofw_node, propname, string);
+    }
+#endif
+
+    return -RT_ENOSYS;
+}
+
+rt_bool_t rt_dm_dev_prop_read_bool(rt_device_t dev, const char *propname)
+{
+    RT_ASSERT(dev != RT_NULL);
+
+#ifdef RT_USING_OFW
+    if (dev->ofw_node)
+    {
+        return ofw_api_call(prop_read_bool, dev->ofw_node, propname);
+    }
+#endif
+
+    return RT_FALSE;
+}
+

+ 25 - 11
components/drivers/core/platform.c

@@ -11,6 +11,10 @@
 
 #include <rtthread.h>
 
+#define DBG_TAG "rtdm.pltaform"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
 #include <drivers/platform.h>
 #include <drivers/core/bus.h>
 #include <drivers/core/dm.h>
@@ -28,6 +32,11 @@ struct rt_platform_device *rt_platform_device_alloc(const char *name)
 {
     struct rt_platform_device *pdev = rt_calloc(1, sizeof(*pdev));
 
+    if (!pdev)
+    {
+        return RT_NULL;
+    }
+
     pdev->parent.bus = &platform_bus;
     pdev->name = name;
 
@@ -44,7 +53,11 @@ rt_err_t rt_platform_driver_register(struct rt_platform_driver *pdrv)
     RT_ASSERT(pdrv != RT_NULL);
 
     pdrv->parent.bus = &platform_bus;
-
+#if RT_NAME_MAX > 0
+    rt_strcpy(pdrv->parent.parent.name, pdrv->name);
+#else
+    pdrv->parent.parent.name = pdrv->name;
+#endif
     return rt_driver_register(&pdrv->parent);
 }
 
@@ -67,20 +80,22 @@ static rt_bool_t platform_match(rt_driver_t drv, rt_device_t dev)
 
 #ifdef RT_USING_OFW
     struct rt_ofw_node *np = dev->ofw_node;
-#endif
 
-#ifdef RT_USING_OFW
+    /* 1、match with ofw node */
     if (np)
     {
-        /* 1、match with ofw node */
         pdev->id = rt_ofw_node_match(np, pdrv->ids);
 
-        return !!pdev->id;
+        if (pdev->id)
+        {
+            return RT_TRUE;
+        }
     }
 #endif
+
+    /* 2、match with name */
     if (pdev->name && pdrv->name)
     {
-        /* 2、match with name */
         if (pdev->name == pdrv->name)
         {
             return RT_TRUE;
@@ -97,7 +112,6 @@ static rt_bool_t platform_match(rt_driver_t drv, rt_device_t dev)
 static rt_err_t platform_probe(rt_device_t dev)
 {
     rt_err_t err;
-
     struct rt_platform_driver *pdrv = rt_container_of(dev->drv, struct rt_platform_driver, parent);
     struct rt_platform_device *pdev = rt_container_of(dev, struct rt_platform_device, parent);
 #ifdef RT_USING_OFW
@@ -106,22 +120,22 @@ static rt_err_t platform_probe(rt_device_t dev)
 
     err = pdrv->probe(pdev);
 
-#ifdef RT_USING_OFW
     if (!err)
     {
+#ifdef RT_USING_OFW
         if (np)
         {
             rt_ofw_node_set_flag(np, RT_OFW_F_READLY);
         }
+#endif
     }
     else
     {
-        if (np)
+        if (err == -RT_ENOMEM)
         {
-            rt_ofw_data(np) = &pdev->parent;
+            LOG_W("System not memory in driver %s", pdrv->name);
         }
     }
-#endif
 
     return err;
 }

+ 127 - 18
components/drivers/core/platform_ofw.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -14,9 +14,13 @@
 #define DBG_LVL DBG_INFO
 #include <rtdbg.h>
 
+#include <drivers/ofw_io.h>
+#include <drivers/ofw_fdt.h>
 #include <drivers/platform.h>
 #include <drivers/core/dm.h>
 
+#include "../ofw/ofw_internal.h"
+
 static const struct rt_ofw_node_id platform_ofw_ids[] =
 {
     { .compatible = "simple-bus", },
@@ -36,10 +40,76 @@ static const struct rt_ofw_node_id platform_ofw_ids[] =
     { /* sentinel */ }
 };
 
+static void ofw_device_rename(struct rt_device *dev)
+{
+    rt_uint32_t mask;
+    rt_uint64_t addr;
+    const char *dev_name = dev->parent.name;
+    struct rt_ofw_node *np = dev->ofw_node;
+
+#if RT_NAME_MAX > 0
+    if (dev_name[0] == '\0')
+    {
+        dev_name = RT_NULL;
+    }
+#endif
+
+    while (np->parent)
+    {
+        if (!rt_ofw_get_address(np, 0, &addr, RT_NULL))
+        {
+            const char *node_name = rt_fdt_node_name(np->full_name);
+            rt_size_t tag_len = strchrnul(node_name, '@') - node_name;
+
+            if (!rt_ofw_prop_read_u32(np, "mask", &mask))
+            {
+                rt_dm_dev_set_name(dev, dev_name ? "%lx.%x.%.*s:%s" : "%lx.%x.%.*s",
+                    addr, __rt_ffs(mask) - 1, tag_len, node_name, dev_name);
+            }
+            else
+            {
+                rt_dm_dev_set_name(dev, dev_name ? "%lx.%.*s:%s" : "%lx.%.*s",
+                    addr, tag_len, node_name, dev_name);
+            }
+
+            return;
+        }
+
+        rt_dm_dev_set_name(dev, dev_name ? "%s:%s" : "%s",
+                rt_fdt_node_name(np->full_name), dev_name);
+
+        np = np->parent;
+    }
+}
+
+static struct rt_platform_device *alloc_ofw_platform_device(struct rt_ofw_node *np)
+{
+    struct rt_platform_device *pdev = rt_platform_device_alloc("");
+
+    if (pdev)
+    {
+        /* inc reference of dt-node */
+        rt_ofw_node_get(np);
+        rt_ofw_node_set_flag(np, RT_OFW_F_PLATFORM);
+
+#ifdef RT_USING_OFW
+        pdev->parent.ofw_node = np;
+#endif
+
+        ofw_device_rename(&pdev->parent);
+    }
+    else
+    {
+        LOG_E("Alloc device fail for %s", rt_ofw_node_full_name(np));
+    }
+
+    return pdev;
+}
+
 static rt_err_t platform_ofw_device_probe_once(struct rt_ofw_node *parent_np)
 {
     rt_err_t err = RT_EOK;
-    struct rt_ofw_node *np, *child;
+    struct rt_ofw_node *np;
     struct rt_platform_device *pdev;
 
     rt_ofw_foreach_available_child_node(parent_np, np)
@@ -48,6 +118,8 @@ static rt_err_t platform_ofw_device_probe_once(struct rt_ofw_node *parent_np)
         struct rt_ofw_node_id *id;
         struct rt_ofw_prop *compat_prop = RT_NULL;
 
+        LOG_D("%s found in %s", np->full_name, parent_np->full_name);
+
         /* Is system node or have driver */
         if (rt_ofw_node_test_flag(np, RT_OFW_F_SYSTEM) ||
             rt_ofw_node_test_flag(np, RT_OFW_F_READLY))
@@ -66,35 +138,32 @@ static rt_err_t platform_ofw_device_probe_once(struct rt_ofw_node *parent_np)
 
         id = rt_ofw_prop_match(compat_prop, platform_ofw_ids);
 
-        if (id && (child = rt_ofw_get_next_child(np, RT_NULL)))
+        if (id && np->child)
         {
             /* scan next level */
-            err = platform_ofw_device_probe_once(child);
-
-            rt_ofw_node_put(child);
+            err = platform_ofw_device_probe_once(np);
 
             if (err)
             {
+                rt_ofw_node_put(np);
                 LOG_E("%s bus probe fail", np->full_name);
 
                 break;
             }
         }
 
-        pdev = rt_platform_device_alloc(np->name);
+        pdev = alloc_ofw_platform_device(np);
 
         if (!pdev)
         {
+            rt_ofw_node_put(np);
             err = -RT_ENOMEM;
 
             break;
         }
 
-        /* inc reference of dt-node */
-        rt_ofw_node_get(np);
-        rt_ofw_node_set_flag(np, RT_OFW_F_PLATFORM);
-
-        pdev->parent.ofw_node = np;
+        pdev->dev_id = ofw_alias_node_id(np);
+        LOG_D("%s register to bus", np->full_name);
 
         rt_platform_device_register(pdev);
     }
@@ -102,18 +171,58 @@ static rt_err_t platform_ofw_device_probe_once(struct rt_ofw_node *parent_np)
     return err;
 }
 
+rt_err_t rt_platform_ofw_device_probe_child(struct rt_ofw_node *np)
+{
+    rt_err_t err;
+    struct rt_ofw_node *parent = rt_ofw_get_parent(np);
+
+    if (parent && rt_strcmp(parent->name, "/") &&
+        rt_ofw_get_prop(np, "compatible", RT_NULL) &&
+        !rt_ofw_node_test_flag(np, RT_OFW_F_PLATFORM))
+    {
+        struct rt_platform_device *pdev = alloc_ofw_platform_device(np);
+
+        if (pdev)
+        {
+            err = rt_platform_device_register(pdev);
+        }
+        else
+        {
+            err = -RT_ENOMEM;
+        }
+    }
+    else
+    {
+        err = -RT_EINVAL;
+    }
+
+    rt_ofw_node_put(parent);
+
+    return err;
+}
+
 static int platform_ofw_device_probe(void)
 {
     rt_err_t err = RT_EOK;
-    struct rt_ofw_node *root_np;
-
-    root_np = rt_ofw_find_node_by_path("/");
+    struct rt_ofw_node *node;
 
-    if (root_np)
+    if (ofw_node_root)
     {
-        err = platform_ofw_device_probe_once(root_np);
+        err = platform_ofw_device_probe_once(ofw_node_root);
+
+        rt_ofw_node_put(ofw_node_root);
+
+        if ((node = rt_ofw_find_node_by_path("/firmware")))
+        {
+            platform_ofw_device_probe_once(node);
+            rt_ofw_node_put(node);
+        }
 
-        rt_ofw_node_put(root_np);
+        if ((node = rt_ofw_get_child_by_compatible(ofw_node_chosen, "simple-framebuffer")))
+        {
+            platform_ofw_device_probe_once(node);
+            rt_ofw_node_put(node);
+        }
     }
     else
     {

+ 10 - 10
components/drivers/include/drivers/core/bus.h

@@ -21,32 +21,32 @@ struct rt_bus
 {
     struct rt_object parent;    /**< inherit from rt_object */
 
-    char *name;
-    struct rt_bus *bus;
+    const char *name;
 
     rt_list_t list;
-    rt_list_t children;
     rt_list_t dev_list;
     rt_list_t drv_list;
 
-    struct rt_spinlock spinlock;
+    struct rt_spinlock dev_lock;
+    struct rt_spinlock drv_lock;
 
     rt_bool_t (*match)(rt_driver_t drv, rt_device_t dev);
     rt_err_t  (*probe)(rt_device_t dev);
+    rt_err_t  (*remove)(rt_device_t dev);
+    rt_err_t  (*shutdown)(rt_device_t dev);
 };
 
-rt_bus_t rt_bus_root(void);
+rt_err_t rt_bus_for_each_dev(rt_bus_t bus, void *data, int (*fn)(rt_device_t dev, void *));
+rt_err_t rt_bus_for_each_drv(rt_bus_t bus, void *data, int (*fn)(rt_driver_t drv, void *));
 
-rt_err_t rt_bus_for_each_dev(rt_bus_t bus, rt_driver_t drv, int (*fn)(rt_driver_t drv, rt_device_t dev));
-rt_err_t rt_bus_for_each_drv(rt_bus_t bus, rt_device_t dev, int (*fn)(rt_driver_t drv, rt_device_t dev));
-
-rt_err_t rt_bus_add(rt_bus_t bus);
 rt_err_t rt_bus_add_driver(rt_bus_t bus, rt_driver_t drv);
 rt_err_t rt_bus_add_device(rt_bus_t bus, rt_device_t dev);
 rt_err_t rt_bus_remove_driver(rt_driver_t drv);
 rt_err_t rt_bus_remove_device(rt_device_t dev);
 
-rt_bus_t rt_bus_find_by_name(char *name);
+rt_err_t rt_bus_shutdown(void);
+
+rt_bus_t rt_bus_find_by_name(const char *name);
 rt_err_t rt_bus_reload_driver_device(rt_bus_t new_bus, rt_device_t dev);
 
 rt_err_t rt_bus_register(rt_bus_t bus);

+ 134 - 4
components/drivers/include/drivers/core/dm.h

@@ -13,6 +13,7 @@
 
 #include <rthw.h>
 #include <rtdef.h>
+#include <ioremap.h>
 #include <drivers/misc.h>
 #include <drivers/byteorder.h>
 
@@ -26,10 +27,139 @@ extern int rt_hw_cpu_id(void);
 
 void rt_dm_secondary_cpu_init(void);
 
-int rt_dm_set_dev_name_auto(rt_device_t dev, const char *prefix);
-int rt_dm_get_dev_name_id(rt_device_t dev);
+int rt_dm_dev_set_name_auto(rt_device_t dev, const char *prefix);
+int rt_dm_dev_get_name_id(rt_device_t dev);
 
-int rt_dm_set_dev_name(rt_device_t dev, const char *format, ...);
-const char *rt_dm_get_dev_name(rt_device_t dev);
+int rt_dm_dev_set_name(rt_device_t dev, const char *format, ...);
+const char *rt_dm_dev_get_name(rt_device_t dev);
+
+int rt_dm_dev_get_address_count(rt_device_t dev);
+rt_err_t rt_dm_dev_get_address(rt_device_t dev, int index,
+        rt_uint64_t *out_address, rt_uint64_t *out_size);
+rt_err_t rt_dm_dev_get_address_by_name(rt_device_t dev, const char *name,
+        rt_uint64_t *out_address, rt_uint64_t *out_size);
+int rt_dm_dev_get_address_array(rt_device_t dev, int nr, rt_uint64_t *out_regs);
+
+void *rt_dm_dev_iomap(rt_device_t dev, int index);
+void *rt_dm_dev_iomap_by_name(rt_device_t dev, const char *name);
+
+int rt_dm_dev_get_irq_count(rt_device_t dev);
+int rt_dm_dev_get_irq(rt_device_t dev, int index);
+int rt_dm_dev_get_irq_by_name(rt_device_t dev, const char *name);
+
+void rt_dm_dev_bind_fwdata(rt_device_t dev, void *fw_np, void *data);
+void rt_dm_dev_unbind_fwdata(rt_device_t dev, void *fw_np);
+
+int rt_dm_dev_prop_read_u8_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, rt_uint8_t *out_values);
+int rt_dm_dev_prop_read_u16_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, rt_uint16_t *out_values);
+int rt_dm_dev_prop_read_u32_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, rt_uint32_t *out_values);
+int rt_dm_dev_prop_read_u64_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, rt_uint64_t *out_values);
+int rt_dm_dev_prop_read_string_array_index(rt_device_t dev, const char *propname,
+        int index, int nr, const char **out_strings);
+
+int rt_dm_dev_prop_count_of_size(rt_device_t dev, const char *propname, int size);
+int rt_dm_dev_prop_index_of_string(rt_device_t dev, const char *propname, const char *string);
+
+rt_bool_t rt_dm_dev_prop_read_bool(rt_device_t dev, const char *propname);
+
+rt_inline rt_err_t rt_dm_dev_prop_read_u8_index(rt_device_t dev, const char *propname,
+        int index, rt_uint8_t *out_value)
+{
+    int nr = rt_dm_dev_prop_read_u8_array_index(dev, propname, index, 1, out_value);
+
+    return nr > 0 ? RT_EOK : (rt_err_t)nr;
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_u16_index(rt_device_t dev, const char *propname,
+        int index, rt_uint16_t *out_value)
+{
+    int nr = rt_dm_dev_prop_read_u16_array_index(dev, propname, index, 1, out_value);
+
+    return nr > 0 ? RT_EOK : (rt_err_t)nr;
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_u32_index(rt_device_t dev, const char *propname,
+        int index, rt_uint32_t *out_value)
+{
+    int nr = rt_dm_dev_prop_read_u32_array_index(dev, propname, index, 1, out_value);
+
+    return nr > 0 ? RT_EOK : (rt_err_t)nr;
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_u64_index(rt_device_t dev, const char *propname,
+        int index, rt_uint64_t *out_value)
+{
+    int nr = rt_dm_dev_prop_read_u64_array_index(dev, propname, index, 1, out_value);
+
+    return nr > 0 ? RT_EOK : (rt_err_t)nr;
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_string_index(rt_device_t dev, const char *propname,
+        int index, const char **out_string)
+{
+    int nr = rt_dm_dev_prop_read_string_array_index(dev, propname, index, 1, out_string);
+
+    return nr > 0 ? RT_EOK : (rt_err_t)nr;
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_u8(rt_device_t dev, const char *propname,
+        rt_uint8_t *out_value)
+{
+    return rt_dm_dev_prop_read_u8_index(dev, propname, 0, out_value);
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_u16(rt_device_t dev, const char *propname,
+        rt_uint16_t *out_value)
+{
+    return rt_dm_dev_prop_read_u16_index(dev, propname, 0, out_value);
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_u32(rt_device_t dev, const char *propname,
+        rt_uint32_t *out_value)
+{
+    return rt_dm_dev_prop_read_u32_index(dev, propname, 0, out_value);
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_s32(rt_device_t dev, const char *propname,
+        rt_int32_t *out_value)
+{
+    return rt_dm_dev_prop_read_u32_index(dev, propname, 0, (rt_uint32_t *)out_value);
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_u64(rt_device_t dev, const char *propname,
+        rt_uint64_t *out_value)
+{
+    return rt_dm_dev_prop_read_u64_index(dev, propname, 0, out_value);
+}
+
+rt_inline rt_err_t rt_dm_dev_prop_read_string(rt_device_t dev, const char *propname,
+        const char **out_string)
+{
+    return rt_dm_dev_prop_read_string_index(dev, propname, 0, out_string);
+}
+
+rt_inline int rt_dm_dev_prop_count_of_u8(rt_device_t dev, const char *propname)
+{
+    return rt_dm_dev_prop_count_of_size(dev, propname, sizeof(rt_uint8_t));
+}
+
+rt_inline int rt_dm_dev_prop_count_of_u16(rt_device_t dev, const char *propname)
+{
+    return rt_dm_dev_prop_count_of_size(dev, propname, sizeof(rt_uint16_t));
+}
+
+rt_inline int rt_dm_dev_prop_count_of_u32(rt_device_t dev, const char *propname)
+{
+    return rt_dm_dev_prop_count_of_size(dev, propname, sizeof(rt_uint32_t));
+}
+
+rt_inline int rt_dm_dev_prop_count_of_u64(rt_device_t dev, const char *propname)
+{
+    return rt_dm_dev_prop_count_of_size(dev, propname, sizeof(rt_uint64_t));
+}
 
 #endif /* __RT_DM_H__ */

+ 4 - 9
components/drivers/include/drivers/core/driver.h

@@ -13,13 +13,14 @@
 
 #include <rtdef.h>
 
-struct rt_bus;
-
 struct rt_driver
 {
+    struct rt_object parent;
     struct rt_bus *bus;
     rt_list_t node;
 
+    rt_uint32_t ref_count;
+
 #ifdef RT_USING_DEVICE_OPS
     const struct rt_device_ops *dev_ops;
 #else
@@ -34,16 +35,10 @@ struct rt_driver
 
     const struct filesystem_ops *fops;
 
-    const char *name;
-
     int (*probe)(struct rt_device *dev);
     int (*remove)(struct rt_device *dev);
-
-    void *priv;
+    int (*shutdown)(struct rt_device *dev);
 };
-typedef struct rt_driver* rt_driver_t;
-
-int rt_driver_probe_device(struct rt_driver *drv, struct rt_device *dev);
 
 rt_err_t rt_driver_register(rt_driver_t drv);
 rt_err_t rt_driver_unregister(rt_driver_t drv);

+ 4 - 0
components/drivers/include/drivers/ofw.h

@@ -205,11 +205,15 @@ struct rt_ofw_node *rt_ofw_get_alias_node(const char *tag, int id);
 int rt_ofw_get_alias_id(struct rt_ofw_node *np, const char *tag);
 int rt_ofw_get_alias_last_id(const char *tag);
 
+struct rt_ofw_node *rt_ofw_append_child(struct rt_ofw_node *parent, const char *full_name);
+rt_err_t rt_ofw_append_prop(struct rt_ofw_node *np, const char *name, int length, void *value);
+
 struct rt_ofw_node *rt_ofw_parse_phandle(const struct rt_ofw_node *np, const char *phandle_name, int index);
 rt_err_t rt_ofw_parse_phandle_cells(const struct rt_ofw_node *np, const char *list_name, const char *cells_name,
         int index, struct rt_ofw_cell_args *out_args);
 int rt_ofw_count_phandle_cells(const struct rt_ofw_node *np, const char *list_name, const char *cells_name);
 
+const char *rt_ofw_get_prop_fuzzy_name(const struct rt_ofw_node *np, const char *name);
 struct rt_ofw_prop *rt_ofw_get_prop(const struct rt_ofw_node *np, const char *name, rt_ssize_t *out_length);
 
 rt_inline const void *rt_ofw_prop_read_raw(const struct rt_ofw_node *np, const char *name, rt_ssize_t *out_length)

+ 1 - 2
components/drivers/include/drivers/ofw_fdt.h

@@ -20,6 +20,7 @@ struct rt_fdt_earlycon
     union { rt_ubase_t size, width; };
 
     void *fdt;
+    char options[32];
     long nodeoffset;
 
     void *data;
@@ -41,8 +42,6 @@ struct rt_fdt_earlycon_id
     rt_err_t (*setup)(struct rt_fdt_earlycon *earlycon, const char *options);
 };
 
-#define RT_FDT_EARLYCON_OPTION_SIGNATURE    '\n'
-
 #define RT_FDT_EARLYCON_EXPORT(_name, _type, _compatible, _setup)   \
 static const struct rt_fdt_earlycon_id __rt_fdt_##_name##_earlycon  \
 rt_used RT_OFW_SYMBOL(earlycon, _) =                                \

+ 1 - 0
components/drivers/include/drivers/ofw_io.h

@@ -11,6 +11,7 @@
 #ifndef __OFW_IO_H__
 #define __OFW_IO_H__
 
+#include <ioremap.h>
 #include <drivers/ofw.h>
 
 int rt_ofw_bus_addr_cells(struct rt_ofw_node *np);

+ 6 - 0
components/drivers/include/drivers/platform.h

@@ -22,6 +22,8 @@ struct rt_platform_device
 {
     struct rt_device parent;
 
+    int dev_id;
+
     const char *name;
 
 #ifdef RT_USING_OFW
@@ -42,6 +44,8 @@ struct rt_platform_driver
 #endif
 
     rt_err_t (*probe)(struct rt_platform_device *pdev);
+    rt_err_t (*remove)(struct rt_platform_device *pdev);
+    rt_err_t (*shutdown)(struct rt_platform_device *pdev);
 };
 
 struct rt_platform_device *rt_platform_device_alloc(const char *name);
@@ -49,6 +53,8 @@ struct rt_platform_device *rt_platform_device_alloc(const char *name);
 rt_err_t rt_platform_driver_register(struct rt_platform_driver *pdrv);
 rt_err_t rt_platform_device_register(struct rt_platform_device *pdev);
 
+rt_err_t rt_platform_ofw_device_probe_child(struct rt_ofw_node *np);
+
 #define RT_PLATFORM_DRIVER_EXPORT(driver)  RT_DRIVER_EXPORT(driver, platform, BUILIN)
 
 #endif /* __PLATFORM_H__ */

+ 337 - 9
components/drivers/ofw/base.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -8,7 +8,7 @@
  * 2022-08-25     GuEe-GUI     first version
  */
 
-
+#include <rthw.h>
 #include <rtthread.h>
 
 #include <drivers/ofw.h>
@@ -28,7 +28,7 @@ struct rt_ofw_node *ofw_node_chosen = RT_NULL;
 struct rt_ofw_node *ofw_node_aliases = RT_NULL;
 struct rt_ofw_node *ofw_node_reserved_memory = RT_NULL;
 
-static rt_phandle _phandle_range[2] = { 1, 1 };
+static rt_phandle _phandle_range[2] = { 1, 1 }, _phandle_next = 1;
 static struct rt_ofw_node **_phandle_hash = RT_NULL;
 
 static rt_list_t _aliases_nodes = RT_LIST_OBJECT_INIT(_aliases_nodes);
@@ -36,6 +36,7 @@ static rt_list_t _aliases_nodes = RT_LIST_OBJECT_INIT(_aliases_nodes);
 rt_err_t ofw_phandle_hash_reset(rt_phandle min, rt_phandle max)
 {
     rt_err_t err = RT_EOK;
+    rt_phandle next = max;
     struct rt_ofw_node **hash_ptr = RT_NULL;
 
     max = RT_ALIGN(max, OFW_NODE_MIN_HASH);
@@ -69,7 +70,7 @@ rt_err_t ofw_phandle_hash_reset(rt_phandle min, rt_phandle max)
             _phandle_range[0] = min;
         }
         _phandle_range[1] = max;
-
+        _phandle_next = next + 1;
         _phandle_hash = hash_ptr;
     }
     else
@@ -80,6 +81,39 @@ rt_err_t ofw_phandle_hash_reset(rt_phandle min, rt_phandle max)
     return err;
 }
 
+static rt_phandle ofw_phandle_next(void)
+{
+    rt_phandle next;
+    static struct rt_spinlock op_lock = {};
+
+    rt_hw_spin_lock(&op_lock.lock);
+
+    RT_ASSERT(_phandle_next != OFW_PHANDLE_MAX);
+
+    if (_phandle_next <= _phandle_range[1])
+    {
+        next = _phandle_next++;
+    }
+    else
+    {
+        rt_err_t err = ofw_phandle_hash_reset(_phandle_range[0], _phandle_next);
+
+        if (!err)
+        {
+            next = _phandle_next++;
+        }
+        else
+        {
+            next = 0;
+            LOG_E("Expanded phandle hash[%u, %u] fail error = %s",
+                    _phandle_range[0], _phandle_next + 1, rt_strerror(err));
+        }
+    }
+
+    rt_hw_spin_unlock(&op_lock.lock);
+
+    return next;
+}
 static void ofw_prop_destroy(struct rt_ofw_prop *prop)
 {
     struct rt_ofw_prop *next;
@@ -230,6 +264,7 @@ static void ofw_node_release(struct rt_ref *r)
     struct rt_ofw_node *np = rt_container_of(r, struct rt_ofw_node, ref);
 
     LOG_E("%s is release", np->full_name);
+    (void)np;
 
     RT_ASSERT(0);
 }
@@ -610,7 +645,7 @@ struct rt_ofw_node *rt_ofw_find_node_by_path(const char *path)
                     break;
                 }
 
-                path += len;
+                path += len + !!*next;
             }
 
             np = tmp;
@@ -1031,9 +1066,9 @@ rt_err_t ofw_alias_scan(void)
             continue;
         }
 
-        end = name + rt_strlen(name);
+        end = name + rt_strlen(name) - 1;
 
-        while (*end && !(*end >= '0' && *end <= '9'))
+        while (*end && !(*end >= '0' && *end <= '9') && end > name)
         {
             --end;
         }
@@ -1043,7 +1078,7 @@ rt_err_t ofw_alias_scan(void)
             id += (*end - '0') * rate;
             rate *= 10;
 
-            --end;
+            ++end;
         }
 
         info = rt_malloc(sizeof(*info));
@@ -1058,7 +1093,7 @@ rt_err_t ofw_alias_scan(void)
 
         info->id = id;
         info->tag = name;
-        info->tag_len = end - name;
+        info->tag_len = end - name - 1;
         info->np = tmp;
 
         rt_list_insert_after(&_aliases_nodes, &info->list);
@@ -1092,6 +1127,32 @@ struct rt_ofw_node *rt_ofw_get_alias_node(const char *tag, int id)
     return np;
 }
 
+int ofw_alias_node_id(struct rt_ofw_node *np)
+{
+    int id;
+    struct alias_info *info;
+
+    if (np)
+    {
+        id = -1;
+
+        rt_list_for_each_entry(info, &_aliases_nodes, list)
+        {
+            if (info->np == np)
+            {
+                id = info->id;
+                break;
+            }
+        }
+    }
+    else
+    {
+        id = -RT_EINVAL;
+    }
+
+    return id;
+}
+
 int rt_ofw_get_alias_id(struct rt_ofw_node *np, const char *tag)
 {
     int id;
@@ -1153,6 +1214,109 @@ int rt_ofw_get_alias_last_id(const char *tag)
     return id;
 }
 
+struct rt_ofw_node *rt_ofw_append_child(struct rt_ofw_node *parent, const char *full_name)
+{
+    rt_phandle phandle;
+    rt_err_t err = RT_EOK;
+    fdt32_t *phandle_value;
+    struct rt_ofw_node *np = RT_NULL, *child;
+
+    if (full_name)
+    {
+        if ((phandle = ofw_phandle_next()))
+        {
+            np = rt_calloc(1, sizeof(*np) + sizeof(*phandle_value));
+        }
+    }
+
+    if (np)
+    {
+        parent = parent ? : ofw_node_root;
+
+        np->full_name = full_name;
+        np->phandle = phandle;
+        np->parent = parent;
+
+        rt_ref_init(&np->ref);
+
+        phandle_value = (void *)np + sizeof(*np);
+        *phandle_value = cpu_to_fdt32(phandle);
+
+        err = rt_ofw_append_prop(np, "phandle", sizeof(*phandle_value), phandle_value);
+
+        if (!err)
+        {
+            if (parent->child)
+            {
+                rt_ofw_foreach_child_node(parent, child)
+                {
+                    if (!child->sibling)
+                    {
+                        child->sibling = np;
+                        rt_ofw_node_put(child);
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                parent->child = np;
+            }
+        }
+        else
+        {
+            rt_free(np);
+            np = RT_NULL;
+        }
+    }
+
+    return np;
+}
+
+rt_err_t rt_ofw_append_prop(struct rt_ofw_node *np, const char *name, int length, void *value)
+{
+    rt_err_t err = RT_EOK;
+
+    if (np && name && ((length && value) || (!length && !value)))
+    {
+        struct rt_ofw_prop *prop = rt_malloc(sizeof(*prop)), *last_prop;
+
+        if (prop)
+        {
+            prop->name = name;
+            prop->length = length;
+            prop->value = value;
+            prop->next = RT_NULL;
+
+            if (np->props)
+            {
+                rt_ofw_foreach_prop(np, last_prop)
+                {
+                    if (!last_prop->next)
+                    {
+                        last_prop->next = prop;
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                np->props = prop;
+            }
+        }
+        else
+        {
+            err = -RT_ENOMEM;
+        }
+    }
+    else
+    {
+        err = -RT_EINVAL;
+    }
+
+    return err;
+}
+
 struct rt_ofw_node *rt_ofw_parse_phandle(const struct rt_ofw_node *np, const char *phandle_name, int index)
 {
     struct rt_ofw_cell_args args;
@@ -1296,6 +1460,170 @@ int rt_ofw_count_phandle_cells(const struct rt_ofw_node *np, const char *list_na
     return count;
 }
 
+static const char *ofw_get_prop_fuzzy_name(const struct rt_ofw_node *np, const char *name)
+{
+    char *sf, split_field[64];
+    rt_size_t len = 0, max_ak = 0;
+    const char *str, *result = RT_NULL;
+    RT_DECLARE_BITMAP(ak, sizeof(split_field));
+    struct rt_ofw_prop *prop;
+
+    /*
+     * List:
+     *
+     *      node {
+     *          property;
+     *          front-prop-rear;
+     *          front-prop;
+     *          prop-rear;
+     *      };
+     *
+     * if call:
+     *  ofw_get_prop_fuzzy_name(node, name):
+     *      ["prop"] => property
+     *      ["-prop"] => front-prop-rear
+     *      ["prop-"] => front-prop-rear
+     *      ["-prop$"] => front-prop
+     *      ["^prop-"] => prop-rear
+     *      ["-prop-"] => front-prop-rear
+     *      ["front-*-rear"] => front-prop-rear
+     */
+
+    str = name;
+    sf = split_field;
+
+    if (str[0] != '^')
+    {
+        /* As '*' */
+        *sf++ = '\0';
+        rt_bitmap_set_bit(ak, len++);
+    }
+    else
+    {
+        ++str;
+    }
+
+    for (; *str && len < sizeof(split_field); ++str, ++sf, ++len)
+    {
+        if (*str != '*')
+        {
+            *sf = *str;
+            rt_bitmap_clear_bit(ak, len);
+        }
+        else
+        {
+            max_ak = len;
+            *sf = '\0';
+            rt_bitmap_set_bit(ak, len);
+        }
+    }
+    *sf = '\0';
+
+    if (str[-1] != '$')
+    {
+        /* As '*' */
+        max_ak = len;
+        rt_bitmap_set_bit(ak, len++);
+    }
+    else
+    {
+        sf[-1] = '\0';
+        --len;
+    }
+
+    sf = split_field;
+
+    if (len >= sizeof(split_field))
+    {
+        LOG_W("%s fuzzy name = %s len is %d out of %d", np->full_name, name, rt_strlen(name), sizeof(split_field));
+    }
+
+    rt_ofw_foreach_prop(np, prop)
+    {
+        int prep_ak = 0, next_ak, field;
+        rt_bool_t match = RT_TRUE;
+        const char *propname = prop->name, *fuzzy_name = sf;
+
+        if (!rt_bitmap_test_bit(ak, prep_ak))
+        {
+            next_ak = rt_bitmap_next_set_bit(ak, prep_ak + 1, max_ak) ? : len;
+            field = next_ak - prep_ak;
+
+            if (rt_strncmp(propname, fuzzy_name, field))
+            {
+                continue;
+            }
+
+            propname += field;
+            fuzzy_name += field;
+            prep_ak = next_ak;
+        }
+
+        rt_bitmap_for_each_set_bit_from(ak, prep_ak, next_ak, max_ak)
+        {
+            /* Skip the '*' */
+            if (prep_ak == next_ak)
+            {
+                ++fuzzy_name;
+
+                next_ak = rt_bitmap_next_set_bit(ak, prep_ak + 1, max_ak);
+            }
+
+            if (!(str = rt_strstr(propname, fuzzy_name)))
+            {
+                match = RT_FALSE;
+                break;
+            }
+
+            field = next_ak - prep_ak;
+            propname = str + field - 1;
+            fuzzy_name += field;
+            prep_ak = next_ak;
+        }
+
+        if (match)
+        {
+            if ((max_ak || !split_field[0]) && next_ak >= max_ak && len - max_ak > 1)
+            {
+                if (next_ak == max_ak)
+                {
+                    /* Skip the last '*' */
+                    ++fuzzy_name;
+                }
+
+                if (!(propname = rt_strstr(propname, fuzzy_name)))
+                {
+                    continue;
+                }
+
+                /* Check end flag */
+                if (propname[len - max_ak - 1] != '\0')
+                {
+                    continue;
+                }
+            }
+
+            result = prop->name;
+            break;
+        }
+    }
+
+    return result;
+}
+
+const char *rt_ofw_get_prop_fuzzy_name(const struct rt_ofw_node *np, const char *name)
+{
+    const char *propname = RT_NULL;
+
+    if (np && name)
+    {
+        propname = ofw_get_prop_fuzzy_name(np, name);
+    }
+
+    return propname;
+}
+
+
 struct rt_ofw_prop *rt_ofw_get_prop(const struct rt_ofw_node *np, const char *name, rt_ssize_t *out_length)
 {
     struct rt_ofw_prop *prop = RT_NULL;

+ 29 - 21
components/drivers/ofw/fdt.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -321,7 +321,7 @@ static rt_err_t fdt_reserved_memory_reg(int nodeoffset, const char *uname)
         }
         else
         {
-            while (len >= t_len)
+            for (; len >= t_len; len -= t_len)
             {
                 base = rt_fdt_next_cell(&prop, _root_addr_cells);
                 size = rt_fdt_next_cell(&prop, _root_size_cells);
@@ -664,12 +664,17 @@ void rt_fdt_earlycon_kick(int why)
         fdt_earlycon.console_kick(&fdt_earlycon, why);
     }
 
-    if (why == FDT_EARLYCON_KICK_COMPLETED && fdt_earlycon.msg_idx)
+    if (why == FDT_EARLYCON_KICK_COMPLETED)
     {
-        fdt_earlycon.msg_idx = 0;
+        fdt_earlycon.console_putc = RT_NULL;
 
-        /* Dump old messages */
-        rt_kputs(fdt_earlycon.msg);
+        if (fdt_earlycon.msg_idx)
+        {
+            fdt_earlycon.msg_idx = 0;
+
+            /* Dump old messages */
+            rt_kputs(fdt_earlycon.msg);
+        }
     }
 }
 
@@ -787,6 +792,8 @@ rt_err_t rt_fdt_scan_chosen_stdout(void)
                 if (options && *options && *options != ' ')
                 {
                     options_len = strchrnul(options, ' ') - options;
+
+                    rt_strncpy(fdt_earlycon.options, options, options_len);
                 }
 
                 /* console > stdout-path */
@@ -824,7 +831,7 @@ rt_err_t rt_fdt_scan_chosen_stdout(void)
 
                 if (best_earlycon_id && best_earlycon_id->setup)
                 {
-                    rt_bool_t used_options = RT_FALSE;
+                    const char earlycon_magic[] = { 'O', 'F', 'W', '\0' };
 
                     if (!con_type)
                     {
@@ -833,24 +840,25 @@ rt_err_t rt_fdt_scan_chosen_stdout(void)
                     fdt_earlycon.fdt = _fdt;
                     fdt_earlycon.nodeoffset = offset;
 
-                    err = best_earlycon_id->setup(&fdt_earlycon, options);
+                    options = &fdt_earlycon.options[options_len + 1];
+                    rt_strncpy((void *)options, earlycon_magic, RT_ARRAY_SIZE(earlycon_magic));
+
+                    err = best_earlycon_id->setup(&fdt_earlycon, fdt_earlycon.options);
 
-                    for (int i = 0; i < options_len; ++i)
+                    if (rt_strncmp(options, earlycon_magic, RT_ARRAY_SIZE(earlycon_magic)))
                     {
-                        if (options[i] == RT_FDT_EARLYCON_OPTION_SIGNATURE)
+                        const char *option_start = options - 1;
+
+                        while (option_start[-1] != '\0')
                         {
-                            /* Restore ',' */
-                            ((char *)options)[i++] = ',';
-                            options = &options[i];
-                            options_len -= i;
-                            used_options = RT_TRUE;
-                            break;
+                            --option_start;
                         }
+
+                        rt_memmove(fdt_earlycon.options, option_start, options - option_start);
                     }
-                    if (!used_options)
+                    else
                     {
-                        options = RT_NULL;
-                        options_len = 0;
+                        fdt_earlycon.options[0] = '\0';
                     }
                 }
             }
@@ -877,8 +885,8 @@ rt_err_t rt_fdt_scan_chosen_stdout(void)
 
     if (fdt_earlycon.mmio)
     {
-        LOG_I("Earlycon: %s at MMIO/PIO %p (options '%.*s')",
-                con_type, fdt_earlycon.mmio, options_len, options ? options : "");
+        LOG_I("Earlycon: %s at MMIO/PIO %p (options '%s')",
+                con_type, fdt_earlycon.mmio, fdt_earlycon.options);
     }
 
     return err;

+ 19 - 4
components/drivers/ofw/io.c

@@ -10,7 +10,6 @@
 
 #include <rtthread.h>
 
-#include <ioremap.h>
 #include <drivers/ofw.h>
 #include <drivers/ofw_io.h>
 #include <drivers/ofw_fdt.h>
@@ -155,7 +154,7 @@ static rt_err_t ofw_get_address_by_name(struct rt_ofw_node *np, const char *name
 
 {
     int index = 0;
-    rt_err_t err = RT_EOK;
+    rt_err_t err = -RT_EEMPTY;
     const char *reg_name;
     struct rt_ofw_prop *prop;
 
@@ -386,6 +385,22 @@ rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_t
     return cpu_addr;
 }
 
+#ifdef ARCH_CPU_64BIT
+#define ofw_address_cpu_cast(np, address) (void *)(address)
+#else
+#define ofw_address_cpu_cast(np, address)                       \
+({                                                              \
+    if (((address) >> 32))                                      \
+    {                                                           \
+        LOG_W("%s find 64 bits address = %x%x",                 \
+                rt_ofw_node_full_name(np),                      \
+                ofw_static_cast(rt_ubase_t, (address) >> 32),   \
+                ofw_static_cast(rt_ubase_t, (address)));        \
+    }                                                           \
+    (void *)ofw_static_cast(rt_ubase_t, (address));             \
+})
+#endif
+
 void *rt_ofw_iomap(struct rt_ofw_node *np, int index)
 {
     void *iomem = RT_NULL;
@@ -396,7 +411,7 @@ void *rt_ofw_iomap(struct rt_ofw_node *np, int index)
 
         if (!ofw_get_address(np, index, &regs[0], &regs[1]))
         {
-            iomem = rt_ioremap((void *)regs[0], (size_t)regs[1]);
+            iomem = rt_ioremap(ofw_address_cpu_cast(np, regs[0]), (size_t)regs[1]);
         }
     }
 
@@ -413,7 +428,7 @@ void *rt_ofw_iomap_by_name(struct rt_ofw_node *np, const char *name)
 
         if (!ofw_get_address_by_name(np, name, &regs[0], &regs[1]))
         {
-            iomem = rt_ioremap((void *)regs[0], (size_t)regs[1]);
+            iomem = rt_ioremap(ofw_address_cpu_cast(np, regs[0]), (size_t)regs[1]);
         }
     }
 

+ 49 - 24
components/drivers/ofw/ofw.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -85,6 +85,41 @@ static const char *ofw_console_serial_find(char *dst_con, struct rt_ofw_node *np
     return ofw_name;
 }
 
+static int tty_device_compare(rt_device_t dev, void *data)
+{
+    rt_ubase_t *args_list;
+    char *dst_con;
+    const char *console, **ofw_name;
+    const struct rt_ofw_node_id *id;
+    struct rt_platform_device *pdev;
+    int *tty_idx, tty_id, tty_name_len;
+
+    pdev = rt_container_of(dev, struct rt_platform_device, parent);
+    id = pdev->id;
+
+    args_list = data;
+    tty_idx = (int *)args_list[0];
+    tty_id = args_list[1];
+    console = (const char *)args_list[2];
+    tty_name_len = args_list[3];
+    dst_con = (char *)args_list[4];
+    ofw_name = (const char **)args_list[5];
+
+    if (id && id->type[0] && !strncmp(id->type, console, tty_name_len))
+    {
+        if (*tty_idx == tty_id)
+        {
+            *ofw_name = ofw_console_serial_find(dst_con, pdev->parent.ofw_node);
+
+            return RT_EOK;
+        }
+
+        ++*tty_idx;
+    }
+
+    return -RT_EEMPTY;
+}
+
 static const char *ofw_console_tty_find(char *dst_con, const char *con)
 {
     const char *ofw_name = RT_NULL;
@@ -97,8 +132,7 @@ static const char *ofw_console_tty_find(char *dst_con, const char *con)
 
     if (platform_bus)
     {
-        rt_device_t dev;
-        rt_ubase_t level;
+        rt_ubase_t args_list[6];
         const char *console = con;
         int tty_idx = 0, tty_id = 0, tty_name_len;
 
@@ -119,27 +153,13 @@ static const char *ofw_console_tty_find(char *dst_con, const char *con)
             ++con;
         }
 
-        level = rt_spin_lock_irqsave(&platform_bus->spinlock);
-
-        rt_list_for_each_entry(dev, &platform_bus->dev_list, node)
-        {
-            struct rt_platform_device *pdev = rt_container_of(dev, struct rt_platform_device, parent);
-            const struct rt_ofw_node_id *id = pdev->id;
-
-            if (id && id->type[0] && !rt_strncmp(id->type, console, tty_name_len))
-            {
-                if (tty_idx == tty_id)
-                {
-                    ofw_name = ofw_console_serial_find(dst_con, pdev->parent.ofw_node);
-
-                    break;
-                }
-
-                ++tty_idx;
-            }
-        }
-
-        rt_spin_unlock_irqrestore(&platform_bus->spinlock, level);
+        args_list[0] = (rt_ubase_t)&tty_idx;
+        args_list[1] = tty_id;
+        args_list[2] = (rt_ubase_t)console;
+        args_list[3] = tty_name_len;
+        args_list[4] = (rt_ubase_t)dst_con;
+        args_list[5] = (rt_ubase_t)&ofw_name;
+        rt_bus_for_each_dev(platform_bus, &args_list, tty_device_compare);
     }
 
     return ofw_name;
@@ -463,6 +483,11 @@ static void ofw_node_dump_dts(struct rt_ofw_node *np, rt_bool_t sibling_too)
             dts_put_depth(depth);
             rt_kputs("};\n");
 
+            if (!sibling_too && org_np == np)
+            {
+                break;
+            }
+
             while (np->parent && !np->sibling)
             {
                 np = np->parent;

+ 1 - 0
components/drivers/ofw/ofw_internal.h

@@ -68,6 +68,7 @@ extern struct rt_fdt_earlycon fdt_earlycon;
     (to_type)(((value) >> ((sizeof(value) - sizeof(to_type)) * 8)))
 
 rt_err_t ofw_alias_scan(void);
+int ofw_alias_node_id(struct rt_ofw_node *np);
 rt_err_t ofw_phandle_hash_reset(rt_phandle min, rt_phandle max);
 
 #endif /* __OFW_INTERNAL_H__ */

+ 1 - 0
include/rtdef.h

@@ -1470,6 +1470,7 @@ enum rt_device_class_type
  */
 #define RT_DEVICE_CTRL_BASE(Type)        ((RT_Device_Class_##Type + 1) * 0x100)
 
+typedef struct rt_driver *rt_driver_t;
 typedef struct rt_device *rt_device_t;
 
 #ifdef RT_USING_DEVICE_OPS