diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 617db226a2480e069286ab462a2c85e1c4473829..3687b9a100081e9c7728c5881b72f7350d2fd300 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -11,6 +11,286 @@
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 
+static const char *if_typename_str[IF_TYPE_COUNT] = {
+	[IF_TYPE_IDE]		= "ide",
+	[IF_TYPE_SCSI]		= "scsi",
+	[IF_TYPE_ATAPI]		= "atapi",
+	[IF_TYPE_USB]		= "usb",
+	[IF_TYPE_DOC]		= "doc",
+	[IF_TYPE_MMC]		= "mmc",
+	[IF_TYPE_SD]		= "sd",
+	[IF_TYPE_SATA]		= "sata",
+	[IF_TYPE_HOST]		= "host",
+	[IF_TYPE_SYSTEMACE]	= "ace",
+};
+
+static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
+	[IF_TYPE_IDE]		= UCLASS_INVALID,
+	[IF_TYPE_SCSI]		= UCLASS_INVALID,
+	[IF_TYPE_ATAPI]		= UCLASS_INVALID,
+	[IF_TYPE_USB]		= UCLASS_MASS_STORAGE,
+	[IF_TYPE_DOC]		= UCLASS_INVALID,
+	[IF_TYPE_MMC]		= UCLASS_MMC,
+	[IF_TYPE_SD]		= UCLASS_INVALID,
+	[IF_TYPE_SATA]		= UCLASS_AHCI,
+	[IF_TYPE_HOST]		= UCLASS_ROOT,
+	[IF_TYPE_SYSTEMACE]	= UCLASS_INVALID,
+};
+
+static enum if_type if_typename_to_iftype(const char *if_typename)
+{
+	int i;
+
+	for (i = 0; i < IF_TYPE_COUNT; i++) {
+		if (if_typename_str[i] &&
+		    !strcmp(if_typename, if_typename_str[i]))
+			return i;
+	}
+
+	return IF_TYPE_UNKNOWN;
+}
+
+static enum uclass_id if_type_to_uclass_id(enum if_type if_type)
+{
+	return if_type_uclass_id[if_type];
+}
+
+struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
+{
+	struct blk_desc *desc;
+	struct udevice *dev;
+	int ret;
+
+	ret = blk_get_device(if_type, devnum, &dev);
+	if (ret)
+		return NULL;
+	desc = dev_get_uclass_platdata(dev);
+
+	return desc;
+}
+
+/*
+ * This function is complicated with driver model. We look up the interface
+ * name in a local table. This gives us an interface type which we can match
+ * against the uclass of the block device's parent.
+ */
+struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
+{
+	enum uclass_id uclass_id;
+	enum if_type if_type;
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	if_type = if_typename_to_iftype(if_typename);
+	if (if_type == IF_TYPE_UNKNOWN) {
+		debug("%s: Unknown interface type '%s'\n", __func__,
+		      if_typename);
+		return NULL;
+	}
+	uclass_id = if_type_to_uclass_id(if_type);
+	if (uclass_id == UCLASS_INVALID) {
+		debug("%s: Unknown uclass for interface type'\n",
+		      if_typename_str[if_type]);
+		return NULL;
+	}
+
+	ret = uclass_get(UCLASS_BLK, &uc);
+	if (ret)
+		return NULL;
+	uclass_foreach_dev(dev, uc) {
+		struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+		debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
+		      if_type, devnum, dev->name, desc->if_type, desc->devnum);
+		if (desc->devnum != devnum)
+			continue;
+
+		/* Find out the parent device uclass */
+		if (device_get_uclass_id(dev->parent) != uclass_id) {
+			debug("%s: parent uclass %d, this dev %d\n", __func__,
+			      device_get_uclass_id(dev->parent), uclass_id);
+			continue;
+		}
+
+		if (device_probe(dev))
+			return NULL;
+
+		debug("%s: Device desc %p\n", __func__, desc);
+		return desc;
+	}
+	debug("%s: No device found\n", __func__);
+
+	return NULL;
+}
+
+/**
+ * get_desc() - Get the block device descriptor for the given device number
+ *
+ * @if_type:	Interface type
+ * @devnum:	Device number (0 = first)
+ * @descp:	Returns block device descriptor on success
+ * @return 0 on success, -ENODEV if there is no such device and no device
+ * with a higher device number, -ENOENT if there is no such device but there
+ * is one with a higher number, or other -ve on other error.
+ */
+static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp)
+{
+	bool found_more = false;
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	*descp = NULL;
+	ret = uclass_get(UCLASS_BLK, &uc);
+	if (ret)
+		return ret;
+	uclass_foreach_dev(dev, uc) {
+		struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+		debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
+		      if_type, devnum, dev->name, desc->if_type, desc->devnum);
+		if (desc->if_type == if_type) {
+			if (desc->devnum == devnum) {
+				ret = device_probe(dev);
+				if (ret)
+					return ret;
+
+			} else if (desc->devnum > devnum) {
+				found_more = true;
+			}
+		}
+	}
+
+	return found_more ? -ENOENT : -ENODEV;
+}
+
+int blk_list_part(enum if_type if_type)
+{
+	struct blk_desc *desc;
+	int devnum, ok;
+	int ret;
+
+	for (ok = 0, devnum = 0;; ++devnum) {
+		ret = get_desc(if_type, devnum, &desc);
+		if (ret == -ENODEV)
+			break;
+		else if (ret)
+			continue;
+		if (desc->part_type != PART_TYPE_UNKNOWN) {
+			++ok;
+			if (devnum)
+				putc('\n');
+			part_print(desc);
+		}
+	}
+	if (!ok)
+		return -ENODEV;
+
+	return 0;
+}
+
+int blk_print_part_devnum(enum if_type if_type, int devnum)
+{
+	struct blk_desc *desc;
+	int ret;
+
+	ret = get_desc(if_type, devnum, &desc);
+	if (ret)
+		return ret;
+	if (desc->type == DEV_TYPE_UNKNOWN)
+		return -ENOENT;
+	part_print(desc);
+
+	return 0;
+}
+
+void blk_list_devices(enum if_type if_type)
+{
+	struct blk_desc *desc;
+	int ret;
+	int i;
+
+	for (i = 0;; ++i) {
+		ret = get_desc(if_type, i, &desc);
+		if (ret == -ENODEV)
+			break;
+		else if (ret)
+			continue;
+		if (desc->type == DEV_TYPE_UNKNOWN)
+			continue;  /* list only known devices */
+		printf("Device %d: ", i);
+		dev_print(desc);
+	}
+}
+
+int blk_print_device_num(enum if_type if_type, int devnum)
+{
+	struct blk_desc *desc;
+	int ret;
+
+	ret = get_desc(if_type, devnum, &desc);
+	if (ret)
+		return ret;
+	printf("\nIDE device %d: ", devnum);
+	dev_print(desc);
+
+	return 0;
+}
+
+int blk_show_device(enum if_type if_type, int devnum)
+{
+	struct blk_desc *desc;
+	int ret;
+
+	printf("\nDevice %d: ", devnum);
+	ret = get_desc(if_type, devnum, &desc);
+	if (ret == -ENODEV || ret == -ENOENT) {
+		printf("unknown device\n");
+		return -ENODEV;
+	}
+	if (ret)
+		return ret;
+	dev_print(desc);
+
+	if (desc->type == DEV_TYPE_UNKNOWN)
+		return -ENOENT;
+
+	return 0;
+}
+
+ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
+		      lbaint_t blkcnt, void *buffer)
+{
+	struct blk_desc *desc;
+	ulong n;
+	int ret;
+
+	ret = get_desc(if_type, devnum, &desc);
+	if (ret)
+		return ret;
+	n = blk_dread(desc, start, blkcnt, buffer);
+	if (IS_ERR_VALUE(n))
+		return n;
+
+	/* flush cache after read */
+	flush_cache((ulong)buffer, blkcnt * desc->blksz);
+
+	return n;
+}
+
+ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
+		       lbaint_t blkcnt, const void *buffer)
+{
+	struct blk_desc *desc;
+	int ret;
+
+	ret = get_desc(if_type, devnum, &desc);
+	if (ret)
+		return ret;
+	return blk_dwrite(desc, start, blkcnt, buffer);
+}
+
 int blk_first_device(int if_type, struct udevice **devp)
 {
 	struct blk_desc *desc;