mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-08 19:11:53 +00:00
dm: core: Allow uclass to set up a device's child before it is probed
Some buses need to set up their devices before they can be used. This setup may well be common to all buses in a particular uclass. Support a common pre-probe method for the uclass, called before any bus devices are probed. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
This commit is contained in:
parent
1603bf3cc1
commit
83c7e434c9
7 changed files with 85 additions and 0 deletions
|
@ -227,6 +227,10 @@ int device_probe_child(struct udevice *dev, void *parent_priv)
|
||||||
}
|
}
|
||||||
dev->seq = seq;
|
dev->seq = seq;
|
||||||
|
|
||||||
|
ret = uclass_pre_probe_child(dev);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (dev->parent && dev->parent->driver->child_pre_probe) {
|
if (dev->parent && dev->parent->driver->child_pre_probe) {
|
||||||
ret = dev->parent->driver->child_pre_probe(dev);
|
ret = dev->parent->driver->child_pre_probe(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -391,6 +391,19 @@ int uclass_resolve_seq(struct udevice *dev)
|
||||||
return seq;
|
return seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uclass_pre_probe_child(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct uclass_driver *uc_drv;
|
||||||
|
|
||||||
|
if (!dev->parent)
|
||||||
|
return 0;
|
||||||
|
uc_drv = dev->parent->uclass->uc_drv;
|
||||||
|
if (uc_drv->child_pre_probe)
|
||||||
|
return uc_drv->child_pre_probe(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int uclass_post_probe_device(struct udevice *dev)
|
int uclass_post_probe_device(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct uclass_driver *uc_drv = dev->uclass->uc_drv;
|
struct uclass_driver *uc_drv = dev->uclass->uc_drv;
|
||||||
|
|
|
@ -67,6 +67,8 @@ enum {
|
||||||
struct dm_test_priv {
|
struct dm_test_priv {
|
||||||
int ping_total;
|
int ping_total;
|
||||||
int op_count[DM_TEST_OP_COUNT];
|
int op_count[DM_TEST_OP_COUNT];
|
||||||
|
int uclass_flag;
|
||||||
|
int uclass_total;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,6 +90,7 @@ struct dm_test_uclass_priv {
|
||||||
*
|
*
|
||||||
* @sum: Test value used to check parent data works correctly
|
* @sum: Test value used to check parent data works correctly
|
||||||
* @flag: Used to track calling of parent operations
|
* @flag: Used to track calling of parent operations
|
||||||
|
* @uclass_flag: Used to track calling of parent operations by uclass
|
||||||
*/
|
*/
|
||||||
struct dm_test_parent_data {
|
struct dm_test_parent_data {
|
||||||
int sum;
|
int sum;
|
||||||
|
|
|
@ -43,6 +43,17 @@ int uclass_bind_device(struct udevice *dev);
|
||||||
*/
|
*/
|
||||||
int uclass_unbind_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
|
||||||
|
*
|
||||||
|
* Perform any pre-processing that is needed by the uclass before it can be
|
||||||
|
* probed.
|
||||||
|
*
|
||||||
|
* @dev: Pointer to the device
|
||||||
|
* #return 0 on success, -ve on error
|
||||||
|
*/
|
||||||
|
int uclass_pre_probe_child(struct udevice *dev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* uclass_post_probe_device() - Deal with a device that has just been probed
|
* uclass_post_probe_device() - Deal with a device that has just been probed
|
||||||
*
|
*
|
||||||
|
|
|
@ -83,6 +83,7 @@ struct uclass_driver {
|
||||||
int (*post_probe)(struct udevice *dev);
|
int (*post_probe)(struct udevice *dev);
|
||||||
int (*pre_remove)(struct udevice *dev);
|
int (*pre_remove)(struct udevice *dev);
|
||||||
int (*child_post_bind)(struct udevice *dev);
|
int (*child_post_bind)(struct udevice *dev);
|
||||||
|
int (*child_pre_probe)(struct udevice *dev);
|
||||||
int (*init)(struct uclass *class);
|
int (*init)(struct uclass *class);
|
||||||
int (*destroy)(struct uclass *class);
|
int (*destroy)(struct uclass *class);
|
||||||
int priv_auto_alloc_size;
|
int priv_auto_alloc_size;
|
||||||
|
|
|
@ -53,6 +53,15 @@ static int testbus_child_pre_probe(struct udevice *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int testbus_child_pre_probe_uclass(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct dm_test_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
priv->uclass_flag++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int testbus_child_post_remove(struct udevice *dev)
|
static int testbus_child_post_remove(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
|
struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
|
||||||
|
@ -91,6 +100,7 @@ UCLASS_DRIVER(testbus) = {
|
||||||
.name = "testbus",
|
.name = "testbus",
|
||||||
.id = UCLASS_TEST_BUS,
|
.id = UCLASS_TEST_BUS,
|
||||||
.flags = DM_UC_FLAG_SEQ_ALIAS,
|
.flags = DM_UC_FLAG_SEQ_ALIAS,
|
||||||
|
.child_pre_probe = testbus_child_pre_probe_uclass,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Test that we can probe for children */
|
/* Test that we can probe for children */
|
||||||
|
@ -469,3 +479,39 @@ static int dm_test_bus_child_post_bind_uclass(struct dm_test_state *dms)
|
||||||
}
|
}
|
||||||
DM_TEST(dm_test_bus_child_post_bind_uclass,
|
DM_TEST(dm_test_bus_child_post_bind_uclass,
|
||||||
DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test that the bus' uclass' child_pre_probe() is called before the
|
||||||
|
* device's probe() method
|
||||||
|
*/
|
||||||
|
static int dm_test_bus_child_pre_probe_uclass(struct dm_test_state *dms)
|
||||||
|
{
|
||||||
|
struct udevice *bus, *dev;
|
||||||
|
int child_count;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See testfdt_drv_probe() which effectively checks that the uclass
|
||||||
|
* flag is set before that method is called
|
||||||
|
*/
|
||||||
|
ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
|
||||||
|
for (device_find_first_child(bus, &dev), child_count = 0;
|
||||||
|
dev;
|
||||||
|
device_find_next_child(&dev)) {
|
||||||
|
struct dm_test_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
/* Check that things happened in the right order */
|
||||||
|
ut_asserteq_ptr(NULL, priv);
|
||||||
|
ut_assertok(device_probe(dev));
|
||||||
|
|
||||||
|
priv = dev_get_priv(dev);
|
||||||
|
ut_assert(priv != NULL);
|
||||||
|
ut_asserteq(1, priv->uclass_flag);
|
||||||
|
ut_asserteq(1, priv->uclass_total);
|
||||||
|
child_count++;
|
||||||
|
}
|
||||||
|
ut_asserteq(3, child_count);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DM_TEST(dm_test_bus_child_pre_probe_uclass,
|
||||||
|
DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
|
||||||
|
|
|
@ -51,6 +51,13 @@ static int testfdt_drv_probe(struct udevice *dev)
|
||||||
|
|
||||||
priv->ping_total += DM_TEST_START_TOTAL;
|
priv->ping_total += DM_TEST_START_TOTAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this device is on a bus, the uclass_flag will be set before
|
||||||
|
* calling this function. This is used by
|
||||||
|
* dm_test_bus_child_pre_probe_uclass().
|
||||||
|
*/
|
||||||
|
priv->uclass_total += priv->uclass_flag;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue