[U-Boot] [PATCH 10/22] dm: core: Add a uclass pre_probe() method for devices

Simon Glass sjg at chromium.org
Wed Feb 18 22:10:37 CET 2015


Some uclasses want to set up a device before it is probed. Add a method
for this.

An example is with PCI, where a PCI uclass wants to set up its private
data for later use. This allows the device's uclass() method to make calls
whcih use that data (for example, read PCI memory regions from device
tree, set up bus numbers).

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 drivers/core/device.c        |  2 +-
 drivers/core/uclass.c        | 10 +++++++++-
 include/dm/test.h            |  1 +
 include/dm/uclass-internal.h |  7 ++++---
 include/dm/uclass.h          |  2 ++
 test/dm/core.c               |  7 ++++++-
 test/dm/test-uclass.c        | 12 ++++++++++++
 7 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index 6bd4b26..7483405 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 289a5d2..98c15e5 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 707c69e..b310e5f 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 f2f254a..ae2a93d 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 d6c40c6..d57d804 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 7be28e4..990d390 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 1b9a3fd..be91657 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,
-- 
2.2.0.rc0.207.ga3a616c



More information about the U-Boot mailing list