dm: core: Add a function to find a device by drvdata
authorSimon Glass <sjg@chromium.org>
Thu, 6 Feb 2020 16:54:50 +0000 (09:54 -0700)
committerBin Meng <bmeng.cn@gmail.com>
Fri, 7 Feb 2020 14:41:24 +0000 (22:41 +0800)
It is sometimes useful to find a device in a uclass using only its driver
data. The driver data often indicates the 'subtype' of the device, e,g,
via its compatible string.

Add a function to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
drivers/core/uclass.c
include/dm/test.h
include/dm/uclass.h
test/dm/test-fdt.c

index c520ef113a2a3fbc8f155e19a763d579e601dbd5..61192d8a9ff03c9c9afb3335abc6ff50320b01b3 100644 (file)
@@ -629,6 +629,23 @@ int uclass_next_device_check(struct udevice **devp)
        return device_probe(*devp);
 }
 
+int uclass_first_device_drvdata(enum uclass_id id, ulong driver_data,
+                               struct udevice **devp)
+{
+       struct udevice *dev;
+       struct uclass *uc;
+
+       uclass_id_foreach_dev(id, dev, uc) {
+               if (dev_get_driver_data(dev) == driver_data) {
+                       *devp = dev;
+
+                       return device_probe(dev);
+               }
+       }
+
+       return -ENODEV;
+}
+
 int uclass_bind_device(struct udevice *dev)
 {
        struct uclass *uc;
index 07385cd531fa2c9af660010ad4a439aab0ec75e0..f0f36624ce3b68906c3f3f692b0b8dda43d65bc0 100644 (file)
@@ -56,6 +56,8 @@ enum {
 enum {
        DM_TEST_TYPE_FIRST = 0,
        DM_TEST_TYPE_SECOND,
+
+       DM_TEST_TYPE_COUNT,
 };
 
 /* The number added to the ping total on each probe */
index 74b8e2ecb5e57c0de3028cf72e6dc5d7b1b838f7..70fca79b449824a1d49549458d72b8ea52cf592e 100644 (file)
@@ -350,6 +350,20 @@ int uclass_first_device_check(enum uclass_id id, struct udevice **devp);
  */
 int uclass_next_device_check(struct udevice **devp);
 
+/**
+ * uclass_first_device_drvdata() - Find the first device with given driver data
+ *
+ * This searches through the devices for a particular uclass looking for one
+ * that has the given driver data.
+ *
+ * @id: Uclass ID to check
+ * @driver_data: Driver data to search for
+ * @devp: Returns pointer to the first matching device in that uclass, if found
+ * @return 0 if found, -ENODEV if not found, other -ve on error
+ */
+int uclass_first_device_drvdata(enum uclass_id id, ulong driver_data,
+                               struct udevice **devp);
+
 /**
  * uclass_resolve_seq() - Resolve a device's sequence number
  *
index 8ea536c309337ea970743e7cd2dbaa730d059098..698ca0e7cf86cf47fcb474dcaa61daab5696bd6b 100644 (file)
@@ -893,3 +893,24 @@ static int dm_test_read_int(struct unit_test_state *uts)
        return 0;
 }
 DM_TEST(dm_test_read_int, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test iteration through devices by drvdata */
+static int dm_test_uclass_drvdata(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+
+       ut_assertok(uclass_first_device_drvdata(UCLASS_TEST_FDT,
+                                               DM_TEST_TYPE_FIRST, &dev));
+       ut_asserteq_str("a-test", dev->name);
+
+       ut_assertok(uclass_first_device_drvdata(UCLASS_TEST_FDT,
+                                               DM_TEST_TYPE_SECOND, &dev));
+       ut_asserteq_str("d-test", dev->name);
+
+       ut_asserteq(-ENODEV, uclass_first_device_drvdata(UCLASS_TEST_FDT,
+                                                        DM_TEST_TYPE_COUNT,
+                                                        &dev));
+
+       return 0;
+}
+DM_TEST(dm_test_uclass_drvdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);