From 02c07b3741f1b825934b1a6eb8f23530532dc426 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 5 Mar 2015 12:25:22 -0700 Subject: [PATCH] dm: core: Add a uclass pre_probe() method for devices 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 --- 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 6bd4b26623..748340598a 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 289a5d2d53..98c15e585d 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 707c69e07f..b310e5f3ff 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 f2f254a825..ae2a93d7d4 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 d6c40c60dd..d57d804259 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 7be28e4701..990d390d01 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 1b9a3fdfa6..be91657347 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.30.2