diff --git a/drivers/core/device.c b/drivers/core/device.c
index 6967c3df0f9a777e3958fb6653a38e79a2022150..5bb1d7793dd687a9fed5475409b382e32effab92 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 fc35f4dfd409db345c35ad60233f00d8b4803c12..c825d472366a33d810b8adda8e9d7b88701839a4 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 6f4f00140e5690f404b3169e2dce4e2c0133e735..488b2ab0aea446f524b7edede8cc7ee583b920b5 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 374ad1ca499428c95954d62d743e99beb8f4ec03..ec80abe717d9fadbc5bff665203b8ef7fa248675 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')