Przeglądaj źródła

[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>
lhxj 3 tygodni temu
rodzic
commit
7641ef6885

+ 9 - 10
components/drivers/core/platform_ofw.c

@@ -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
         {

+ 4 - 0
components/drivers/i2c/dev_i2c_bus.c

@@ -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)

+ 5 - 1
components/drivers/spi/dev_spi_bus.c

@@ -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)