diff --git a/drivers/i2c/i2c-uclass-compat.c b/drivers/i2c/i2c-uclass-compat.c
index d8de46a..223f238 100644
--- a/drivers/i2c/i2c-uclass-compat.c
+++ b/drivers/i2c/i2c-uclass-compat.c
@@ -20,7 +20,7 @@ static int i2c_compat_get_device(uint chip_addr, int alen,
 	ret = i2c_get_chip_for_busnum(cur_busnum, chip_addr, alen, devp);
 	if (ret)
 		return ret;
-	chip = dev_get_parentdata(*devp);
+	chip = dev_get_parent_platdata(*devp);
 	if (chip->offset_len != alen) {
 		printf("I2C chip %x: requested alen %d does not match chip offset_len %d\n",
 		       chip_addr, alen, chip->offset_len);
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index 94b49df..83c7a04 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -50,7 +50,7 @@ static int i2c_setup_offset(struct dm_i2c_chip *chip, uint offset,
 static int i2c_read_bytewise(struct udevice *dev, uint offset,
 			     uint8_t *buffer, int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[2], *ptr;
@@ -79,7 +79,7 @@ static int i2c_read_bytewise(struct udevice *dev, uint offset,
 static int i2c_write_bytewise(struct udevice *dev, uint offset,
 			     const uint8_t *buffer, int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[1];
@@ -102,7 +102,7 @@ static int i2c_write_bytewise(struct udevice *dev, uint offset,
 
 int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[2], *ptr;
@@ -133,7 +133,7 @@ int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
 int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
 		 int len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct udevice *bus = dev_get_parent(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	struct i2c_msg msg[1];
@@ -223,7 +223,7 @@ static int i2c_probe_chip(struct udevice *bus, uint chip_addr,
 static int i2c_bind_driver(struct udevice *bus, uint chip_addr, uint offset_len,
 			   struct udevice **devp)
 {
-	struct dm_i2c_chip chip;
+	struct dm_i2c_chip *chip;
 	char name[30], *str;
 	struct udevice *dev;
 	int ret;
@@ -236,11 +236,11 @@ static int i2c_bind_driver(struct udevice *bus, uint chip_addr, uint offset_len,
 		goto err_bind;
 
 	/* Tell the device what we know about it */
-	memset(&chip, '\0', sizeof(chip));
-	chip.chip_addr = chip_addr;
-	chip.offset_len = offset_len;
-	ret = device_probe_child(dev, &chip);
-	debug("%s:  device_probe_child: ret=%d\n", __func__, ret);
+	chip = dev_get_parent_platdata(dev);
+	chip->chip_addr = chip_addr;
+	chip->offset_len = offset_len;
+	ret = device_probe(dev);
+	debug("%s:  device_probe: ret=%d\n", __func__, ret);
 	if (ret)
 		goto err_probe;
 
@@ -248,6 +248,10 @@ static int i2c_bind_driver(struct udevice *bus, uint chip_addr, uint offset_len,
 	return 0;
 
 err_probe:
+	/*
+	 * If the device failed to probe, unbind it. There is nothing there
+	 * on the bus so we don't want to leave it lying around
+	 */
 	device_unbind(dev);
 err_bind:
 	free(str);
@@ -263,15 +267,9 @@ int i2c_get_chip(struct udevice *bus, uint chip_addr, uint offset_len,
 	      bus->name, chip_addr);
 	for (device_find_first_child(bus, &dev); dev;
 			device_find_next_child(&dev)) {
-		struct dm_i2c_chip store;
-		struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+		struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 		int ret;
 
-		if (!chip) {
-			chip = &store;
-			i2c_chip_ofdata_to_platdata(gd->fdt_blob,
-						    dev->of_offset, chip);
-		}
 		if (chip->chip_addr == chip_addr) {
 			ret = device_probe(dev);
 			debug("found, ret=%d\n", ret);
@@ -367,7 +365,7 @@ int i2c_get_bus_speed(struct udevice *bus)
 int i2c_set_chip_flags(struct udevice *dev, uint flags)
 {
 	struct udevice *bus = dev->parent;
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 	struct dm_i2c_ops *ops = i2c_get_ops(bus);
 	int ret;
 
@@ -383,7 +381,7 @@ int i2c_set_chip_flags(struct udevice *dev, uint flags)
 
 int i2c_get_chip_flags(struct udevice *dev, uint *flagsp)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 
 	*flagsp = chip->flags;
 
@@ -392,7 +390,7 @@ int i2c_get_chip_flags(struct udevice *dev, uint *flagsp)
 
 int i2c_set_chip_offset_len(struct udevice *dev, uint offset_len)
 {
-	struct dm_i2c_chip *chip = dev_get_parentdata(dev);
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
 
 	if (offset_len > I2C_MAX_OFFSET_LEN)
 		return -EINVAL;
@@ -450,13 +448,26 @@ int i2c_post_bind(struct udevice *dev)
 	return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 
+int i2c_child_post_bind(struct udevice *dev)
+{
+	struct dm_i2c_chip *plat = dev_get_parent_platdata(dev);
+
+	if (dev->of_offset == -1)
+		return 0;
+
+	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
+}
+
 UCLASS_DRIVER(i2c) = {
 	.id		= UCLASS_I2C,
 	.name		= "i2c",
 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
-	.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
 	.post_bind	= i2c_post_bind,
 	.post_probe	= i2c_post_probe,
+	.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
+	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
+	.per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip),
+	.child_post_bind = i2c_child_post_bind,
 };
 
 UCLASS_DRIVER(i2c_generic) = {
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index b0d30f7..6707edd 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -145,16 +145,6 @@ static int uniphier_fi2c_remove(struct udevice *dev)
 	return 0;
 }
 
-static int uniphier_fi2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	if (dev->of_offset == -1)
-		return 0;
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
 static int wait_for_irq(struct uniphier_fi2c_dev *dev, u32 flags,
 			bool *stop)
 {
@@ -372,8 +362,6 @@ U_BOOT_DRIVER(uniphier_fi2c) = {
 	.of_match = uniphier_fi2c_of_match,
 	.probe = uniphier_fi2c_probe,
 	.remove = uniphier_fi2c_remove,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = uniphier_fi2c_child_pre_probe,
 	.priv_auto_alloc_size = sizeof(struct uniphier_fi2c_dev),
 	.ops = &uniphier_fi2c_ops,
 };
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
index bdac1f9..64a9ed8 100644
--- a/drivers/i2c/i2c-uniphier.c
+++ b/drivers/i2c/i2c-uniphier.c
@@ -75,16 +75,6 @@ static int uniphier_i2c_remove(struct udevice *dev)
 	return 0;
 }
 
-static int uniphier_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	if (dev->of_offset == -1)
-		return 0;
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
 static int send_and_recv_byte(struct uniphier_i2c_dev *dev, u32 dtrm)
 {
 	writel(dtrm, &dev->regs->dtrm);
@@ -232,8 +222,6 @@ U_BOOT_DRIVER(uniphier_i2c) = {
 	.of_match = uniphier_i2c_of_match,
 	.probe = uniphier_i2c_probe,
 	.remove = uniphier_i2c_remove,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = uniphier_i2c_child_pre_probe,
 	.priv_auto_alloc_size = sizeof(struct uniphier_i2c_dev),
 	.ops = &uniphier_i2c_ops,
 };
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index c21d479..4002972 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -1404,16 +1404,6 @@ static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)
 	return 0;
 }
 
-static int s3c_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	if (dev->of_offset == -1)
-		return 0;
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
 static const struct dm_i2c_ops s3c_i2c_ops = {
 	.xfer		= s3c24x0_i2c_xfer,
 	.probe_chip	= s3c24x0_i2c_probe,
@@ -1431,8 +1421,6 @@ U_BOOT_DRIVER(i2c_s3c) = {
 	.id	= UCLASS_I2C,
 	.of_match = s3c_i2c_ids,
 	.ofdata_to_platdata = s3c_i2c_ofdata_to_platdata,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = s3c_i2c_child_pre_probe,
 	.priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
 	.ops	= &s3c_i2c_ops,
 };
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c
index e2f6c3b..a943aa6 100644
--- a/drivers/i2c/sandbox_i2c.c
+++ b/drivers/i2c/sandbox_i2c.c
@@ -25,24 +25,24 @@ struct dm_sandbox_i2c_emul_priv {
 static int get_emul(struct udevice *dev, struct udevice **devp,
 		    struct dm_i2c_ops **opsp)
 {
-	struct dm_i2c_chip *priv;
+	struct dm_i2c_chip *plat;
 	int ret;
 
 	*devp = NULL;
 	*opsp = NULL;
-	priv = dev_get_parentdata(dev);
-	if (!priv->emul) {
+	plat = dev_get_parent_platdata(dev);
+	if (!plat->emul) {
 		ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset,
 				       false);
 		if (ret)
 			return ret;
 
-		ret = device_get_child(dev, 0, &priv->emul);
+		ret = device_get_child(dev, 0, &plat->emul);
 		if (ret)
 			return ret;
 	}
-	*devp = priv->emul;
-	*opsp = i2c_get_ops(priv->emul);
+	*devp = plat->emul;
+	*opsp = i2c_get_ops(plat->emul);
 
 	return 0;
 }
@@ -82,20 +82,6 @@ static const struct dm_i2c_ops sandbox_i2c_ops = {
 	.xfer		= sandbox_i2c_xfer,
 };
 
-static int sandbox_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	/* Ignore our test address */
-	if (i2c_chip->chip_addr == SANDBOX_I2C_TEST_ADDR)
-		return 0;
-	if (dev->of_offset == -1)
-		return 0;
-
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
 static const struct udevice_id sandbox_i2c_ids[] = {
 	{ .compatible = "sandbox,i2c" },
 	{ }
@@ -105,7 +91,5 @@ U_BOOT_DRIVER(i2c_sandbox) = {
 	.name	= "i2c_sandbox",
 	.id	= UCLASS_I2C,
 	.of_match = sandbox_i2c_ids,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = sandbox_i2c_child_pre_probe,
 	.ops	= &sandbox_i2c_ops,
 };
diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c
index 87290c3..f414287 100644
--- a/drivers/i2c/tegra_i2c.c
+++ b/drivers/i2c/tegra_i2c.c
@@ -484,21 +484,6 @@ static const struct dm_i2c_ops tegra_i2c_ops = {
 	.set_bus_speed	= tegra_i2c_set_bus_speed,
 };
 
-static int tegra_i2c_child_pre_probe(struct udevice *dev)
-{
-	struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-	if (dev->of_offset == -1)
-		return 0;
-	return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-					   i2c_chip);
-}
-
-static int tegra_i2c_ofdata_to_platdata(struct udevice *dev)
-{
-	return 0;
-}
-
 static const struct udevice_id tegra_i2c_ids[] = {
 	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
 	{ .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD },
@@ -510,10 +495,7 @@ U_BOOT_DRIVER(i2c_tegra) = {
 	.name	= "i2c_tegra",
 	.id	= UCLASS_I2C,
 	.of_match = tegra_i2c_ids,
-	.ofdata_to_platdata = tegra_i2c_ofdata_to_platdata,
 	.probe	= tegra_i2c_probe,
-	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-	.child_pre_probe = tegra_i2c_child_pre_probe,
 	.priv_auto_alloc_size = sizeof(struct i2c_bus),
 	.ops	= &tegra_i2c_ops,
 };
diff --git a/include/i2c.h b/include/i2c.h
index 616c974..27fe00f 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -39,8 +39,8 @@ enum dm_i2c_chip_flags {
  * An I2C chip is a device on the I2C bus. It sits at a particular address
  * and normally supports 7-bit or 10-bit addressing.
  *
- * To obtain this structure, use dev_get_parentdata(dev) where dev is the
- * chip to examine.
+ * To obtain this structure, use dev_get_parent_platdata(dev) where dev is
+ * the chip to examine.
  *
  * @chip_addr:	Chip address on bus
  * @offset_len: Length of offset in bytes. A single byte offset can
