diff --git a/drivers/core/device.c b/drivers/core/device.c
index 6bd4b26623d3716930cde9726d3300db374d25dc..748340598a5f1ba4dcb7cfc4c5e8ffdc8c3c07c6 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -227,7 +227,7 @@ int device_probe_child(struct udevice *dev, void *parent_priv)
 	}
 	dev->seq = seq;
 
-	ret = uclass_pre_probe_child(dev);
+	ret = uclass_pre_probe_device(dev);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 289a5d2d53dfc7af75c19cc1dcc21aa88e8cd0cf..98c15e585dfa81d36313899ffacdcaee9ea57ca6 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -391,9 +391,17 @@ int uclass_resolve_seq(struct udevice *dev)
 	return seq;
 }
 
-int uclass_pre_probe_child(struct udevice *dev)
+int uclass_pre_probe_device(struct udevice *dev)
 {
 	struct uclass_driver *uc_drv;
+	int ret;
+
+	uc_drv = dev->uclass->uc_drv;
+	if (uc_drv->pre_probe) {
+		ret = uc_drv->pre_probe(dev);
+		if (ret)
+			return ret;
+	}
 
 	if (!dev->parent)
 		return 0;
diff --git a/include/dm/test.h b/include/dm/test.h
index 707c69e07f02c488f10de559185769829534e689..b310e5f3ff6874884f6a352ab20496ce6e69c45e 100644
--- a/include/dm/test.h
+++ b/include/dm/test.h
@@ -44,6 +44,7 @@ enum {
 	/* For uclass */
 	DM_TEST_OP_POST_BIND,
 	DM_TEST_OP_PRE_UNBIND,
+	DM_TEST_OP_PRE_PROBE,
 	DM_TEST_OP_POST_PROBE,
 	DM_TEST_OP_PRE_REMOVE,
 	DM_TEST_OP_INIT,
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
index f2f254a8259736f9d24ba18ad95ba9e126eb53c2..ae2a93d7d4da7a806826843296d8c2d0d67ce20c 100644
--- a/include/dm/uclass-internal.h
+++ b/include/dm/uclass-internal.h
@@ -44,15 +44,16 @@ int uclass_bind_device(struct udevice *dev);
 int uclass_unbind_device(struct udevice *dev);
 
 /**
- * uclass_pre_probe_child() - Deal with a child that is about to be probed
+ * uclass_pre_probe_device() - Deal with a device that is about to be probed
  *
  * Perform any pre-processing that is needed by the uclass before it can be
- * probed.
+ * probed. This includes the uclass' pre-probe() method and the parent
+ * uclass' child_pre_probe() method.
  *
  * @dev:	Pointer to the device
  * #return 0 on success, -ve on error
  */
-int uclass_pre_probe_child(struct udevice *dev);
+int uclass_pre_probe_device(struct udevice *dev);
 
 /**
  * uclass_post_probe_device() - Deal with a device that has just been probed
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index d6c40c60dda0913c27c46ffb8538176a7d595210..d57d80425986f3c993a42cc8a8cdf35e301b7bf6 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -53,6 +53,7 @@ struct udevice;
  * @id: ID number of this uclass
  * @post_bind: Called after a new device is bound to this uclass
  * @pre_unbind: Called before a device is unbound from this uclass
+ * @pre_probe: Called before a new device is probed
  * @post_probe: Called after a new device is probed
  * @pre_remove: Called before a device is removed
  * @child_post_bind: Called after a child is bound to a device in this uclass
@@ -80,6 +81,7 @@ struct uclass_driver {
 	enum uclass_id id;
 	int (*post_bind)(struct udevice *dev);
 	int (*pre_unbind)(struct udevice *dev);
+	int (*pre_probe)(struct udevice *dev);
 	int (*post_probe)(struct udevice *dev);
 	int (*pre_remove)(struct udevice *dev);
 	int (*child_post_bind)(struct udevice *dev);
diff --git a/test/dm/core.c b/test/dm/core.c
index 7be28e4701124256863fd51f01e80d544c6ba8ad..990d390d0150da5edb8b52a6e5887f1d94e68dc4 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -141,6 +141,7 @@ static int dm_test_autoprobe(struct dm_test_state *dms)
 	ut_assert(uc);
 
 	ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]);
+	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]);
 	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]);
 
 	/* The root device should not be activated until needed */
@@ -167,8 +168,12 @@ static int dm_test_autoprobe(struct dm_test_state *dms)
 			ut_assert(dms->root->flags & DM_FLAG_ACTIVATED);
 	}
 
-	/* Our 3 dm_test_infox children should be passed to post_probe */
+	/*
+	 * Our 3 dm_test_info children should be passed to pre_probe and
+	 * post_probe
+	 */
 	ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]);
+	ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]);
 
 	/* Also we can check the per-device data */
 	expected_base_add = 0;
diff --git a/test/dm/test-uclass.c b/test/dm/test-uclass.c
index 1b9a3fdfa61dcb223465d61cab788d3760ad5efd..be91657347b0df53514ee1ce29718127864f6100 100644
--- a/test/dm/test-uclass.c
+++ b/test/dm/test-uclass.c
@@ -42,6 +42,17 @@ static int test_pre_unbind(struct udevice *dev)
 	return 0;
 }
 
+static int test_pre_probe(struct udevice *dev)
+{
+	struct dm_test_uclass_perdev_priv *priv = dev_get_uclass_priv(dev);
+
+	dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]++;
+	ut_assert(priv);
+	ut_assert(!device_active(dev));
+
+	return 0;
+}
+
 static int test_post_probe(struct udevice *dev)
 {
 	struct udevice *prev = list_entry(dev->uclass_node.prev,
@@ -96,6 +107,7 @@ UCLASS_DRIVER(test) = {
 	.id		= UCLASS_TEST,
 	.post_bind	= test_post_bind,
 	.pre_unbind	= test_pre_unbind,
+	.pre_probe	= test_pre_probe,
 	.post_probe	= test_post_probe,
 	.pre_remove	= test_pre_remove,
 	.init		= test_init,