diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
index a2b6122ebcb3ac7be8285a218d5ad61dd83c6798..59ef05cf2b5405f36de05c8e50f1e90ea34d7426 100644
--- a/doc/driver-model/README.txt
+++ b/doc/driver-model/README.txt
@@ -95,13 +95,14 @@ are provided in test/dm. To run them, try:
 You should see something like this:
 
     <...U-Boot banner...>
-    Running 18 driver model tests
+    Running 19 driver model tests
     Test: dm_test_autobind
     Test: dm_test_autoprobe
     Test: dm_test_bus_children
     Device 'd-test': seq 3 is in use by 'b-test'
     Device 'c-test@0': seq 0 is in use by 'a-test'
     Device 'c-test@1': seq 1 is in use by 'd-test'
+    Test: dm_test_bus_children_funcs
     Test: dm_test_children
     Test: dm_test_fdt
     Device 'd-test': seq 3 is in use by 'b-test'
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 848ce3b675efc72c2b9ea953c78bd8f81862f810..74bb5f0f8efb8b568885a2a10ba09f118f052a9f 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -376,3 +376,96 @@ void *dev_get_priv(struct udevice *dev)
 
 	return dev->priv;
 }
+
+static int device_get_device_tail(struct udevice *dev, int ret,
+				  struct udevice **devp)
+{
+	if (ret)
+		return ret;
+
+	ret = device_probe(dev);
+	if (ret)
+		return ret;
+
+	*devp = dev;
+
+	return 0;
+}
+
+int device_get_child(struct udevice *parent, int index, struct udevice **devp)
+{
+	struct udevice *dev;
+
+	list_for_each_entry(dev, &parent->child_head, sibling_node) {
+		if (!index--)
+			return device_get_device_tail(dev, 0, devp);
+	}
+
+	return -ENODEV;
+}
+
+int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
+			     bool find_req_seq, struct udevice **devp)
+{
+	struct udevice *dev;
+
+	*devp = NULL;
+	if (seq_or_req_seq == -1)
+		return -ENODEV;
+
+	list_for_each_entry(dev, &parent->child_head, sibling_node) {
+		if ((find_req_seq ? dev->req_seq : dev->seq) ==
+				seq_or_req_seq) {
+			*devp = dev;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+int device_get_child_by_seq(struct udevice *parent, int seq,
+			    struct udevice **devp)
+{
+	struct udevice *dev;
+	int ret;
+
+	*devp = NULL;
+	ret = device_find_child_by_seq(parent, seq, false, &dev);
+	if (ret == -ENODEV) {
+		/*
+		 * We didn't find it in probed devices. See if there is one
+		 * that will request this seq if probed.
+		 */
+		ret = device_find_child_by_seq(parent, seq, true, &dev);
+	}
+	return device_get_device_tail(dev, ret, devp);
+}
+
+int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
+				   struct udevice **devp)
+{
+	struct udevice *dev;
+
+	*devp = NULL;
+
+	list_for_each_entry(dev, &parent->child_head, sibling_node) {
+		if (dev->of_offset == of_offset) {
+			*devp = dev;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+int device_get_child_by_of_offset(struct udevice *parent, int seq,
+				  struct udevice **devp)
+{
+	struct udevice *dev;
+	int ret;
+
+	*devp = NULL;
+	ret = device_find_child_by_of_offset(parent, seq, &dev);
+	return device_get_device_tail(dev, ret, devp);
+}
diff --git a/include/dm/device.h b/include/dm/device.h
index 9077490901e6dffd745c5e964dde1c625457fb48..3f0f7111f7cd136b3b54527a334bfafe2a3229ed 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -168,6 +168,18 @@ void *dev_get_platdata(struct udevice *dev);
  */
 void *dev_get_priv(struct udevice *dev);
 
+/**
+ * device_get_child() - Get the child of a device by index
+ *
+ * Returns the numbered child, 0 being the first. This does not use
+ * sequence numbers, only the natural order.
+ *
+ * @dev:	Parent device to check
+ * @index:	Child index
+ * @devp:	Returns pointer to device
+ */
+int device_get_child(struct udevice *parent, int index, struct udevice **devp);
+
 /**
  * device_find_child_by_seq() - Find a child device based on a sequence
  *
@@ -190,4 +202,50 @@ void *dev_get_priv(struct udevice *dev);
 int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
 			     bool find_req_seq, struct udevice **devp);
 
+/**
+ * device_get_child_by_seq() - Get a child device based on a sequence
+ *
+ * If an active device has this sequence it will be returned. If there is no
+ * such device then this will check for a device that is requesting this
+ * sequence.
+ *
+ * The device is probed to activate it ready for use.
+ *
+ * @parent: Parent device
+ * @seq: Sequence number to find (0=first)
+ * @devp: Returns pointer to device (there is only one per for each seq)
+ * Set to NULL if none is found
+ * @return 0 if OK, -ve on error
+ */
+int device_get_child_by_seq(struct udevice *parent, int seq,
+			    struct udevice **devp);
+
+/**
+ * device_find_child_by_of_offset() - Find a child device based on FDT offset
+ *
+ * Locates a child device by its device tree offset.
+ *
+ * @parent: Parent device
+ * @of_offset: Device tree offset to find
+ * @devp: Returns pointer to device if found, otherwise this is set to NULL
+ * @return 0 if OK, -ve on error
+ */
+int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
+				   struct udevice **devp);
+
+/**
+ * device_get_child_by_of_offset() - Get a child device based on FDT offset
+ *
+ * Locates a child device by its device tree offset.
+ *
+ * The device is probed to activate it ready for use.
+ *
+ * @parent: Parent device
+ * @of_offset: Device tree offset to find
+ * @devp: Returns pointer to device if found, otherwise this is set to NULL
+ * @return 0 if OK, -ve on error
+ */
+int device_get_child_by_of_offset(struct udevice *parent, int seq,
+				  struct udevice **devp);
+
 #endif
diff --git a/test/dm/bus.c b/test/dm/bus.c
index cfb993440c73eaacd40e90262c737dca9801e218..08a4725648e1da7f3c2bf0d4f690652fb125f622 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -61,3 +61,49 @@ static int dm_test_bus_children(struct dm_test_state *dms)
 	return 0;
 }
 DM_TEST(dm_test_bus_children, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test our functions for accessing children */
+static int dm_test_bus_children_funcs(struct dm_test_state *dms)
+{
+	const void *blob = gd->fdt_blob;
+	struct udevice *bus, *dev;
+	int node;
+
+	ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
+
+	/* device_get_child() */
+	ut_assertok(device_get_child(bus, 0, &dev));
+	ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev));
+	ut_assertok(device_get_child_by_seq(bus, 5, &dev));
+	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
+	ut_asserteq_str("c-test@5", dev->name);
+
+	/* Device with sequence number 0 should be accessible */
+	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, true, &dev));
+	ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
+	ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
+	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 0, false, &dev));
+	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
+	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
+
+	/* There is no device with sequence number 2 */
+	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, false, &dev));
+	ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, true, &dev));
+	ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev));
+
+	/* Looking for something that is not a child */
+	node = fdt_path_offset(blob, "/junk");
+	ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
+	node = fdt_path_offset(blob, "/d-test");
+	ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
+
+	/* Find a valid child */
+	node = fdt_path_offset(blob, "/some-bus/c-test@1");
+	ut_assertok(device_find_child_by_of_offset(bus, node, &dev));
+	ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
+	ut_assertok(device_get_child_by_of_offset(bus, node, &dev));
+	ut_assert(dev->flags & DM_FLAG_ACTIVATED);
+
+	return 0;
+}
+DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);