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 <sjg@chromium.org>
master
Simon Glass 10 years ago
parent 02eeb1bbb1
commit 02c07b3741
  1. 2
      drivers/core/device.c
  2. 10
      drivers/core/uclass.c
  3. 1
      include/dm/test.h
  4. 7
      include/dm/uclass-internal.h
  5. 2
      include/dm/uclass.h
  6. 7
      test/dm/core.c
  7. 12
      test/dm/test-uclass.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;

@ -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;

@ -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,

@ -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

@ -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);

@ -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;

@ -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,

Loading…
Cancel
Save