summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components/drivers/core/bus.c362
-rw-r--r--components/drivers/core/dm.c325
-rw-r--r--components/drivers/core/platform.c36
-rw-r--r--components/drivers/core/platform_ofw.c145
-rw-r--r--components/drivers/include/drivers/core/bus.h20
-rw-r--r--components/drivers/include/drivers/core/dm.h138
-rw-r--r--components/drivers/include/drivers/core/driver.h13
-rw-r--r--components/drivers/include/drivers/ofw.h4
-rwxr-xr-xcomponents/drivers/include/drivers/ofw_fdt.h3
-rwxr-xr-xcomponents/drivers/include/drivers/ofw_io.h1
-rw-r--r--components/drivers/include/drivers/platform.h6
-rw-r--r--components/drivers/ofw/base.c346
-rw-r--r--[-rwxr-xr-x]components/drivers/ofw/fdt.c50
-rwxr-xr-xcomponents/drivers/ofw/io.c23
-rw-r--r--[-rwxr-xr-x]components/drivers/ofw/ofw.c73
-rwxr-xr-xcomponents/drivers/ofw/ofw_internal.h1
-rw-r--r--include/rtdef.h1
17 files changed, 1301 insertions, 246 deletions
diff --git a/components/drivers/core/bus.c b/components/drivers/core/bus.c
index 0717d48649..13e154f40c 100644
--- a/components/drivers/core/bus.c
+++ b/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;
}
diff --git a/components/drivers/core/dm.c b/components/drivers/core/dm.c
index c8a7792d64..ecae24945c 100644
--- a/components/drivers/core/dm.c
+++ b/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;
+}
+
diff --git a/components/drivers/core/platform.c b/components/drivers/core/platform.c
index e6d62817ab..18c044f6c4 100644
--- a/components/drivers/core/platform.c
+++ b/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;
}
diff --git a/components/drivers/core/platform_ofw.c b/components/drivers/core/platform_ofw.c
index 4496f2370e..408dec9dc7 100644
--- a/components/drivers/core/platform_ofw.c
+++ b/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
{
diff --git a/components/drivers/include/drivers/core/bus.h b/components/drivers/include/drivers/core/bus.h
index 4a010d797d..ab821240bb 100644
--- a/components/drivers/include/drivers/core/bus.h
+++ b/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);
diff --git a/components/drivers/include/drivers/core/dm.h b/components/drivers/include/drivers/core/dm.h
index f016906499..94821fe395 100644
--- a/components/drivers/include/drivers/core/dm.h
+++ b/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__ */
diff --git a/components/drivers/include/drivers/core/driver.h b/components/drivers/include/drivers/core/driver.h
index 75608e2732..f576c812af 100644
--- a/components/drivers/include/drivers/core/driver.h
+++ b/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);
diff --git a/components/drivers/include/drivers/ofw.h b/components/drivers/include/drivers/ofw.h
index c760cf7e83..4ee2049e8f 100644
--- a/components/drivers/include/drivers/ofw.h
+++ b/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)
diff --git a/components/drivers/include/drivers/ofw_fdt.h b/components/drivers/include/drivers/ofw_fdt.h
index a9c951ca40..4db4ecef6b 100755
--- a/components/drivers/include/drivers/ofw_fdt.h
+++ b/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, _) = \
diff --git a/components/drivers/include/drivers/ofw_io.h b/components/drivers/include/drivers/ofw_io.h
index 5fdfe8f5e6..4ebfbe2c82 100755
--- a/components/drivers/include/drivers/ofw_io.h
+++ b/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);
diff --git a/components/drivers/include/drivers/platform.h b/components/drivers/include/drivers/platform.h
index 9ea1c9803a..d63980fc65 100644
--- a/components/drivers/include/drivers/platform.h
+++ b/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__ */
diff --git a/components/drivers/ofw/base.c b/components/drivers/ofw/base.c
index d8c33033a3..8b081bc9d4 100644
--- a/components/drivers/ofw/base.c
+++ b/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;
diff --git a/components/drivers/ofw/fdt.c b/components/drivers/ofw/fdt.c
index 8745fbc993..9f65436d7d 100755..100644
--- a/components/drivers/ofw/fdt.c
+++ b/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;
diff --git a/components/drivers/ofw/io.c b/components/drivers/ofw/io.c
index b5d6b58425..5f4892c148 100755
--- a/components/drivers/ofw/io.c
+++ b/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]);
}
}
diff --git a/components/drivers/ofw/ofw.c b/components/drivers/ofw/ofw.c
index cd9532349d..c66724c7b7 100755..100644
--- a/components/drivers/ofw/ofw.c
+++ b/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;
diff --git a/components/drivers/ofw/ofw_internal.h b/components/drivers/ofw/ofw_internal.h
index b8bffe41c4..f536b382ca 100755
--- a/components/drivers/ofw/ofw_internal.h
+++ b/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__ */
diff --git a/include/rtdef.h b/include/rtdef.h
index 0e3601090a..7599e73983 100644
--- a/include/rtdef.h
+++ b/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