[drivers] Fix OFW bus conflict and prevent duplicate device creation

Problem:
When enumerating device tree nodes, platform bus and native buses (I2C/SPI)
may create duplicate devices for the same OFW node, causing cross-bus conflicts.
This triggers assertion failure '(dev->bus != new_bus)' in
rt_bus_reload_driver_device() during boot on minimal DM-enabled systems.

Root Cause:
1. Platform bus tries to reload devices that already belong to other buses
   by calling rt_bus_reload_driver_device(dev->bus, dev), which violates
   the API contract (requires dev->bus != new_bus).
2. Native buses (I2C/SPI) do not mark OFW nodes as occupied, so platform
   bus creates duplicate platform devices for I2C/SPI client nodes.

Solution:
1. components/drivers/core/platform_ofw.c: Return RT_EOK when np->dev exists,
   letting the native bus handle device lifecycle instead of cross-bus reload.
2. components/drivers/i2c/dev_i2c_bus.c: Mark i2c_client_np->dev during scan
   to prevent platform bus from duplicating I2C client devices.
3. components/drivers/spi/dev_spi_bus.c: Mark spi_dev_np->dev during scan
   to prevent platform bus from duplicating SPI devices.

Tested on Spacemit K1 RISC-V platform with minimal DM configuration.

Signed-off-by: lhxj <2743257167@qq.com>
This commit is contained in:
lhxj
2025-12-25 17:56:52 +08:00
committed by R b b666
parent 306505ea24
commit 7641ef6885
3 changed files with 18 additions and 11 deletions

View File

@@ -6,6 +6,7 @@
* Change Logs:
* Date Author Notes
* 2023-06-04 GuEe-GUI the first version
* 2025-12-25 lhxj fix OFW bus conflict and prevent duplicate device creation
*/
#include <rtthread.h>
@@ -223,16 +224,14 @@ rt_err_t rt_platform_ofw_request(struct rt_ofw_node *np)
if (dev)
{
/* Was create */
if (dev->drv)
{
/* Was probe OK */
err = RT_EOK;
}
else
{
err = rt_bus_reload_driver_device(dev->bus, dev);
}
/*
* Device was already created (np->dev != NULL).
* - If it's already probed (dev->drv != NULL), nothing to do.
* - If not yet probed (dev->drv == NULL), it belongs to its native bus
* (e.g. I2C/SPI) which will handle probing; platform bus should not reload
* or transfer it, to avoid cross-bus conflicts.
*/
err = RT_EOK;
}
else
{

View File

@@ -6,6 +6,7 @@
* Change Logs:
* Date Author Notes
* 2022-12-06 GuEe-GUI first version
* 2025-12-25 lhxj mark OFW node as taken to prevent platform bus duplication
*/
#include <rtdevice.h>
@@ -63,6 +64,9 @@ void i2c_bus_scan_clients(struct rt_i2c_bus_device *bus)
rt_dm_dev_set_name(&client->parent, "%s", client->name);
/* Mark this OFW node as taken to prevent platform bus from creating duplicate device */
i2c_client_np->dev = &client->parent;
rt_i2c_device_register(client);
if (i2c_client_np != child_np)

View File

@@ -6,6 +6,7 @@
* Change Logs:
* Date Author Notes
* 2022-12-06 GuEe-GUI first version
* 2025-12-25 lhxj mark OFW node as taken to prevent platform bus duplication; fix cppcheck warning
*/
#include "dev_spi_dm.h"
@@ -69,6 +70,9 @@ void spi_bus_scan_devices(struct rt_spi_bus *bus)
continue;
}
/* Mark this OFW node as taken to prevent platform bus from creating duplicate device */
spi_dev_np->dev = &spi_dev->parent;
rt_spi_device_register(spi_dev);
}
}
@@ -163,7 +167,7 @@ static rt_err_t spi_probe(rt_device_t dev)
rt_spidev_device_init(device, rt_dm_dev_get_name(&device->parent));
}
return err;
return RT_EOK;
}
static rt_err_t spi_remove(rt_device_t dev)