]> git.sur5r.net Git - u-boot/commitdiff
dm: core: Expand platdata for of-platdata devices
authorSimon Glass <sjg@chromium.org>
Mon, 4 Jul 2016 17:58:18 +0000 (11:58 -0600)
committerSimon Glass <sjg@chromium.org>
Fri, 15 Jul 2016 02:40:24 +0000 (20:40 -0600)
Devices which use of-platdata have their own platdata. However, in many
cases the driver will have its own auto-alloced platdata, for use with the
device tree. The ofdata_to_platdata() method converts the device tree
settings to platdata.

With of-platdata we would not normally allocate the platdata since it is
provided by the U_BOOT_DEVICE() declaration. However this is inconvenient
since the of-platdata struct is closely tied to the device tree properties.
It is unlikely to exactly match the platdata needed by the driver.

In fact a useful approach is to declare platdata in the driver like this:

struct r3288_mmc_platdata {
struct dtd_rockchip_rk3288_dw_mshc of_platdata;
/* the 'normal' fields go here */
};

In this case we have dt_platadata available, but the normal fields are not
present, since ofdata_to_platdata() is never called. In fact driver model
doesn't allocate any space for the 'normal' fields, since it sees that there
is already platform data attached to the device.

To make this easier, adjust driver model to allocate the full size of the
struct (i.e. platdata_auto_alloc_size from the driver) and copy in the
of-platdata. This means that when the driver's bind() method is called,
the of-platdata will be present, followed by zero bytes for the empty
'normal field' portion.

A new DM_FLAG_OF_PLATDATA flag is available that indicates that the platdata
came from of-platdata. When the allocation/copy happens, the
DM_FLAG_ALLOC_PDATA flag will be set as well. The dtoc tool is updated to
output the platdata_size field, since U-Boot has no other way of knowing
the size of the of-platdata struct.

Signed-off-by: Simon Glass <sjg@chromium.org>
drivers/core/device.c
include/dm/device.h
include/dm/platdata.h
tools/dtoc/dtoc.py

index 6967c3df0f9a777e3958fb6653a38e79a2022150..5bb1d7793dd687a9fed5475409b382e32effab92 100644 (file)
@@ -30,7 +30,7 @@ DECLARE_GLOBAL_DATA_PTR;
 static int device_bind_common(struct udevice *parent, const struct driver *drv,
                              const char *name, void *platdata,
                              ulong driver_data, int of_offset,
-                             struct udevice **devp)
+                             uint of_platdata_size, struct udevice **devp)
 {
        struct udevice *dev;
        struct uclass *uc;
@@ -84,12 +84,29 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
                }
        }
 
-       if (!dev->platdata && drv->platdata_auto_alloc_size) {
-               dev->flags |= DM_FLAG_ALLOC_PDATA;
-               dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
-               if (!dev->platdata) {
-                       ret = -ENOMEM;
-                       goto fail_alloc1;
+       if (drv->platdata_auto_alloc_size) {
+               bool alloc = !platdata;
+
+               if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+                       if (of_platdata_size) {
+                               dev->flags |= DM_FLAG_OF_PLATDATA;
+                               if (of_platdata_size <
+                                               drv->platdata_auto_alloc_size)
+                                       alloc = true;
+                       }
+               }
+               if (alloc) {
+                       dev->flags |= DM_FLAG_ALLOC_PDATA;
+                       dev->platdata = calloc(1,
+                                              drv->platdata_auto_alloc_size);
+                       if (!dev->platdata) {
+                               ret = -ENOMEM;
+                               goto fail_alloc1;
+                       }
+                       if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
+                               memcpy(dev->platdata, platdata,
+                                      of_platdata_size);
+                       }
                }
        }
 
@@ -202,14 +219,14 @@ int device_bind_with_driver_data(struct udevice *parent,
                                 struct udevice **devp)
 {
        return device_bind_common(parent, drv, name, NULL, driver_data,
-                                 of_offset, devp);
+                                 of_offset, 0, devp);
 }
 
 int device_bind(struct udevice *parent, const struct driver *drv,
                const char *name, void *platdata, int of_offset,
                struct udevice **devp)
 {
-       return device_bind_common(parent, drv, name, platdata, 0, of_offset,
+       return device_bind_common(parent, drv, name, platdata, 0, of_offset, 0,
                                  devp);
 }
 
@@ -217,6 +234,7 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
                        const struct driver_info *info, struct udevice **devp)
 {
        struct driver *drv;
+       uint platdata_size = 0;
 
        drv = lists_driver_lookup_name(info->name);
        if (!drv)
@@ -224,8 +242,11 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
        if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
                return -EPERM;
 
-       return device_bind(parent, drv, info->name, (void *)info->platdata,
-                          -1, devp);
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+       platdata_size = info->platdata_size;
+#endif
+       return device_bind_common(parent, drv, info->name,
+                       (void *)info->platdata, 0, -1, platdata_size, devp);
 }
 
 static void *alloc_priv(int size, uint flags)
index fc35f4dfd409db345c35ad60233f00d8b4803c12..c825d472366a33d810b8adda8e9d7b88701839a4 100644 (file)
@@ -44,6 +44,8 @@ struct driver_info;
 /* Device name is allocated and should be freed on unbind() */
 #define DM_FLAG_NAME_ALLOCED           (1 << 7)
 
+#define DM_FLAG_OF_PLATDATA            (1 << 8)
+
 /**
  * struct udevice - An instance of a driver
  *
index 6f4f00140e5690f404b3169e2dce4e2c0133e735..488b2ab0aea446f524b7edede8cc7ee583b920b5 100644 (file)
  *
  * @name:      Driver name
  * @platdata:  Driver-specific platform data
+ * @platdata_size: Size of platform data structure
+ * @flags:     Platform data flags (DM_FLAG_...)
  */
 struct driver_info {
        const char *name;
        const void *platdata;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+       uint platdata_size;
+#endif
 };
 
 /**
index 374ad1ca499428c95954d62d743e99beb8f4ec03..ec80abe717d9fadbc5bff665203b8ef7fa248675 100755 (executable)
@@ -346,6 +346,8 @@ class DtbPlatdata:
             self.Buf('U_BOOT_DEVICE(%s) = {\n' % var_name)
             self.Buf('\t.name\t\t= "%s",\n' % struct_name)
             self.Buf('\t.platdata\t= &%s%s,\n' % (VAL_PREFIX, var_name))
+            self.Buf('\t.platdata_size\t= sizeof(%s%s),\n' %
+                     (VAL_PREFIX, var_name))
             self.Buf('};\n')
             self.Buf('\n')