dm: core: Add a uclass pre_probe() method for devices
authorSimon Glass <sjg@chromium.org>
Thu, 5 Mar 2015 19:25:22 +0000 (12:25 -0700)
committerSimon Glass <sjg@chromium.org>
Fri, 17 Apr 2015 01:27:42 +0000 (19:27 -0600)
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>
drivers/core/device.c
drivers/core/uclass.c
include/dm/test.h
include/dm/uclass-internal.h
include/dm/uclass.h
test/dm/core.c
test/dm/test-uclass.c

index 6bd4b26623d3716930cde9726d3300db374d25dc..748340598a5f1ba4dcb7cfc4c5e8ffdc8c3c07c6 100644 (file)
@@ -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;
 
index 289a5d2d53dfc7af75c19cc1dcc21aa88e8cd0cf..98c15e585dfa81d36313899ffacdcaee9ea57ca6 100644 (file)
@@ -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;
index 707c69e07f02c488f10de559185769829534e689..b310e5f3ff6874884f6a352ab20496ce6e69c45e 100644 (file)
@@ -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,
index f2f254a8259736f9d24ba18ad95ba9e126eb53c2..ae2a93d7d4da7a806826843296d8c2d0d67ce20c 100644 (file)
@@ -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
index d6c40c60dda0913c27c46ffb8538176a7d595210..d57d80425986f3c993a42cc8a8cdf35e301b7bf6 100644 (file)
@@ -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);
index 7be28e4701124256863fd51f01e80d544c6ba8ad..990d390d0150da5edb8b52a6e5887f1d94e68dc4 100644 (file)
@@ -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;
index 1b9a3fdfa61dcb223465d61cab788d3760ad5efd..be91657347b0df53514ee1ce29718127864f6100 100644 (file)
@@ -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,