dm: core: Allocate platform data when binding a device

When using allocated platform data, allocate it when we bind the device.
This makes it possible to fill in this information before the device is
probed.

This fits with the platform data model (when not using device tree),
since platform data exists at bind-time.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 8fc6b71..2c82577 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -88,6 +88,10 @@
 	if (ret)
 		return ret;
 
+	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+		free(dev->platdata);
+		dev->platdata = NULL;
+	}
 	ret = uclass_unbind_device(dev);
 	if (ret)
 		return ret;
@@ -111,10 +115,6 @@
 		free(dev->priv);
 		dev->priv = NULL;
 	}
-	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
-		free(dev->platdata);
-		dev->platdata = NULL;
-	}
 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
 	if (size) {
 		free(dev->uclass_priv);
diff --git a/drivers/core/device.c b/drivers/core/device.c
index eca8eda..366cffe 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -72,8 +72,14 @@
 #else
 	dev->req_seq = -1;
 #endif
-	if (!dev->platdata && drv->platdata_auto_alloc_size)
+	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;
+		}
+	}
 
 	/* put dev into parent's successor list */
 	if (parent)
@@ -103,6 +109,11 @@
 fail_uclass_bind:
 	if (parent)
 		list_del(&dev->sibling_node);
+	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
+		free(dev->platdata);
+		dev->platdata = NULL;
+	}
+fail_alloc1:
 	free(dev);
 
 	return ret;
@@ -139,7 +150,7 @@
 	drv = dev->driver;
 	assert(drv);
 
-	/* Allocate private data and platdata if requested */
+	/* Allocate private data if requested */
 	if (drv->priv_auto_alloc_size) {
 		dev->priv = calloc(1, drv->priv_auto_alloc_size);
 		if (!dev->priv) {
@@ -148,13 +159,6 @@
 		}
 	}
 	/* Allocate private data if requested */
-	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
-		dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
-		if (!dev->platdata) {
-			ret = -ENOMEM;
-			goto fail;
-		}
-	}
 	size = dev->uclass->uc_drv->per_device_auto_alloc_size;
 	if (size) {
 		dev->uclass_priv = calloc(1, size);
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index cd2c389..dc4ebf9 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -143,12 +143,12 @@
 	/* These are num_devices compatible root-level device tree nodes */
 	ut_asserteq(num_devices, list_count_items(&uc->dev_head));
 
-	/* Each should have no platdata / priv */
+	/* Each should have platform data but no private data */
 	for (i = 0; i < num_devices; i++) {
 		ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev);
 		ut_assert(!ret);
 		ut_assert(!dev_get_priv(dev));
-		ut_assert(!dev->platdata);
+		ut_assert(dev->platdata);
 	}
 
 	ut_assertok(dm_check_devices(dms, num_devices));