]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
dm: core: Allow uclasses to specify private data for a device's children
authorSimon Glass <sjg@chromium.org>
Sun, 25 Jan 2015 15:27:06 +0000 (08:27 -0700)
committerSimon Glass <sjg@chromium.org>
Fri, 30 Jan 2015 00:09:55 +0000 (17:09 -0700)
In many cases the per-child private data for a device's children is defined
by the uclass rather than the individual driver. For example, a SPI bus
needs to store information about each of its children, but all SPI drivers
store the same information. It makes sense to allow the uclass to define
this data.

If the driver provides a size value for its per-child private data, then use
it. Failng that, fall back to that provided by the uclass.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
drivers/core/device-remove.c
drivers/core/device.c
include/dm/uclass.h
test/dm/bus.c

index 56c358a0ec24cf5d2b8ec8204433cb8f2c6f28a4..3a5f48df7a27511a5bf9231e547360f11facdd7b 100644 (file)
@@ -126,6 +126,10 @@ void device_free(struct udevice *dev)
        }
        if (dev->parent) {
                size = dev->parent->driver->per_child_auto_alloc_size;
+               if (!size) {
+                       size = dev->parent->uclass->uc_drv->
+                                       per_child_auto_alloc_size;
+               }
                if (size) {
                        free(dev->parent_priv);
                        dev->parent_priv = NULL;
index f78b78a299edfdcefb1fe0e2a6f71b2fc9363a60..78bc460d35fb014158f9b2ba88abfdfac3bef5d7 100644 (file)
@@ -201,6 +201,10 @@ int device_probe_child(struct udevice *dev, void *parent_priv)
        /* Ensure all parents are probed */
        if (dev->parent) {
                size = dev->parent->driver->per_child_auto_alloc_size;
+               if (!size) {
+                       size = dev->parent->uclass->uc_drv->
+                                       per_child_auto_alloc_size;
+               }
                if (size) {
                        dev->parent_priv = calloc(1, size);
                        if (!dev->parent_priv) {
index 9000b22c38de9a263646a992932adb61b16e1496..ac6c85072c9517d640ec6c8ceb2e50bac826f243 100644 (file)
@@ -63,6 +63,9 @@ 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_auto_alloc_size: Each child device (of a parent in this
+ * uclass) can hold parent data for the device/uclass. This value is only
+ * used as a falback if this member is 0 in the driver.
  * @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
@@ -82,6 +85,7 @@ struct uclass_driver {
        int (*destroy)(struct uclass *class);
        int priv_auto_alloc_size;
        int per_device_auto_alloc_size;
+       int per_child_auto_alloc_size;
        int per_child_platdata_auto_alloc_size;
        const void *ops;
        uint32_t flags;
index 972c44979084f5e765cc227f1d400f5f8ea2986b..e9096970628e70ec0f0e6ce9f99c4eebef25b902 100644 (file)
@@ -192,7 +192,7 @@ DM_TEST(dm_test_bus_children_iterators,
        DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
 /* Test that the bus can store data about each child */
-static int dm_test_bus_parent_data(struct dm_test_state *dms)
+static int test_bus_parent_data(struct dm_test_state *dms)
 {
        struct dm_test_parent_data *parent_data;
        struct udevice *bus, *dev;
@@ -251,9 +251,36 @@ static int dm_test_bus_parent_data(struct dm_test_state *dms)
 
        return 0;
 }
-
+/* Test that the bus can store data about each child */
+static int dm_test_bus_parent_data(struct dm_test_state *dms)
+{
+       return test_bus_parent_data(dms);
+}
 DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
 
+/* As above but the size is controlled by the uclass */
+static int dm_test_bus_parent_data_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_auto_alloc_size;
+       bus->uclass->uc_drv->per_child_auto_alloc_size = size;
+       bus->driver->per_child_auto_alloc_size = 0;
+       ret = test_bus_parent_data(dms);
+       if (ret)
+               return ret;
+       bus->uclass->uc_drv->per_child_auto_alloc_size = 0;
+       bus->driver->per_child_auto_alloc_size = size;
+
+       return 0;
+}
+DM_TEST(dm_test_bus_parent_data_uclass,
+       DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
 /* Test that the bus ops are called when a child is probed/removed */
 static int dm_test_bus_parent_ops(struct dm_test_state *dms)
 {