summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/core/device.c4
-rw-r--r--include/dm/uclass.h5
-rw-r--r--test/dm/bus.c32
3 files changed, 39 insertions, 2 deletions
diff --git a/drivers/core/device.c b/drivers/core/device.c
index ee97cc84ff..2f33b0e6a3 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -83,6 +83,10 @@ int device_bind(struct udevice *parent, struct driver *drv, const char *name,
if (parent) {
int size = parent->driver->per_child_platdata_auto_alloc_size;
+ if (!size) {
+ size = parent->uclass->uc_drv->
+ per_child_platdata_auto_alloc_size;
+ }
if (size) {
dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
dev->parent_platdata = calloc(1, size);
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 2577ae6489..7d92d34bec 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -60,6 +60,10 @@ struct udevice;
* @per_device_auto_alloc_size: Each device can hold private data owned
* by the uclass. If required this will be automatically allocated if this
* value is non-zero.
+ * @per_child_platdata_auto_alloc_size: A bus likes to store information about
+ * its children. If non-zero this is the size of this data, to be allocated
+ * in the child device's parent_platdata pointer. This value is only used as
+ * a falback if this member is 0 in the driver.
* @ops: Uclass operations, providing the consistent interface to devices
* within the uclass.
*/
@@ -74,6 +78,7 @@ struct uclass_driver {
int (*destroy)(struct uclass *class);
int priv_auto_alloc_size;
int per_device_auto_alloc_size;
+ int per_child_platdata_auto_alloc_size;
const void *ops;
};
diff --git a/test/dm/bus.c b/test/dm/bus.c
index 63c8a9f738..26b8293037 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -279,8 +279,7 @@ static int dm_test_bus_parent_ops(struct dm_test_state *dms)
}
DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
-/* Test that the bus can store platform data about each child */
-static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
+static int test_bus_parent_platdata(struct dm_test_state *dms)
{
struct dm_test_parent_platdata *plat;
struct udevice *bus, *dev;
@@ -351,4 +350,33 @@ static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
return 0;
}
+
+/* Test that the bus can store platform data about each child */
+static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
+{
+ return test_bus_parent_platdata(dms);
+}
DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* As above but the size is controlled by the uclass */
+static int dm_test_bus_parent_platdata_uclass(struct dm_test_state *dms)
+{
+ struct udevice *bus;
+ int size;
+ int ret;
+
+ /* Set the driver size to 0 so that the uclass size is used */
+ ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
+ size = bus->driver->per_child_platdata_auto_alloc_size;
+ bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size;
+ bus->driver->per_child_platdata_auto_alloc_size = 0;
+ ret = test_bus_parent_platdata(dms);
+ if (ret)
+ return ret;
+ bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0;
+ bus->driver->per_child_platdata_auto_alloc_size = size;
+
+ return 0;
+}
+DM_TEST(dm_test_bus_parent_platdata_uclass,
+ DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);