diff options
-rw-r--r-- | drivers/core/device.c | 43 | ||||
-rw-r--r-- | include/dm/device.h | 2 | ||||
-rw-r--r-- | include/dm/platdata.h | 5 | ||||
-rwxr-xr-x | tools/dtoc/dtoc.py | 2 |
4 files changed, 41 insertions, 11 deletions
diff --git a/drivers/core/device.c b/drivers/core/device.c index 6967c3df0f..5bb1d7793d 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -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) diff --git a/include/dm/device.h b/include/dm/device.h index fc35f4dfd4..c825d47236 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -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 * diff --git a/include/dm/platdata.h b/include/dm/platdata.h index 6f4f00140e..488b2ab0ae 100644 --- a/include/dm/platdata.h +++ b/include/dm/platdata.h @@ -22,10 +22,15 @@ * * @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 }; /** diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py index 374ad1ca49..ec80abe717 100755 --- a/tools/dtoc/dtoc.py +++ b/tools/dtoc/dtoc.py @@ -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') |