diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index 435cf98ae18fad944b9643040636a3861d3254c8..fd2d4de0c832d6a83006a454c0277c296ccaad99 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -15,4 +15,4 @@ obj-$(CONFIG_OF_LIVE) += of_access.o of_addr.o
 ifndef CONFIG_DM_DEV_READ_INLINE
 obj-$(CONFIG_OF_CONTROL) += read.o
 endif
-obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o
+obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o
diff --git a/drivers/core/read_extra.c b/drivers/core/read_extra.c
new file mode 100644
index 0000000000000000000000000000000000000000..a6d2f342d9da8ff692e41ecfe4f359e110b8b28f
--- /dev/null
+++ b/drivers/core/read_extra.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/of_addr.h>
+#include <dm/read.h>
+#include <linux/ioport.h>
+
+int dev_read_resource(struct udevice *dev, uint index, struct resource *res)
+{
+	ofnode node = dev_ofnode(dev);
+
+#ifdef CONFIG_OF_LIVE
+	if (ofnode_is_np(node)) {
+		return of_address_to_resource(ofnode_to_np(node), index, res);
+	} else
+#endif
+		{
+		struct fdt_resource fres;
+		int ret;
+
+		ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
+				       "reg", index, &fres);
+		if (ret < 0)
+			return -EINVAL;
+		memset(res, '\0', sizeof(*res));
+		res->start = fres.start;
+		res->end = fres.end;
+
+		return 0;
+	}
+}
diff --git a/include/dm/read.h b/include/dm/read.h
index 8c9846eaf26f2fa7dc797e082da0caf15c03f9ab..65d5d1f3577fdb93f58195b60f5d832aea58d673 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -14,6 +14,8 @@
 #include <dm/ofnode.h>
 #include <dm/uclass.h>
 
+struct resource;
+
 #if CONFIG_IS_ENABLED(OF_LIVE)
 static inline const struct device_node *dev_np(struct udevice *dev)
 {
@@ -42,6 +44,16 @@ static inline bool dev_of_valid(struct udevice *dev)
 	return ofnode_valid(dev_ofnode(dev));
 }
 
+/**
+ * dev_read_resource() - obtain an indexed resource from a device.
+ *
+ * @dev: devuce to examine
+ * @index index of the resource to retrieve (0 = first)
+ * @res returns the resource
+ * @return 0 if ok, negative on error
+ */
+int dev_read_resource(struct udevice *dev, uint index, struct resource *res);
+
 #ifndef CONFIG_DM_DEV_READ_INLINE
 /**
  * dev_read_u32_default() - read a 32-bit integer from a device's DT property