diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index da9324b43caeee237e2120191b37ab15aced7132..0e8dc0179bf069202afad62c8131abf485264415 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -728,7 +728,6 @@ config ARCH_ZYNQ
 	select DM_GPIO
 	select SPL_DM if SPL
 	select DM_MMC
-	select DM_MMC_OPS
 	select DM_SPI
 	select DM_SERIAL
 	select DM_SPI_FLASH
@@ -1076,7 +1075,6 @@ config ARCH_ROCKCHIP
 	select DM_GPIO
 	select DM_I2C
 	select DM_MMC
-	select DM_MMC_OPS
 	select DM_SERIAL
 	select DM_SPI
 	select DM_SPI_FLASH
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index f94c2471b4e88b4275f2ad4231bc3d7ee63aed9e..d07715fc4f12da5f775c07ab97f8cdcb58f88b41 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -359,6 +359,7 @@ dtb-$(CONFIG_MX6) += imx6ull-14x14-evk.dtb \
 	imx6sll-evk.dtb \
 	imx6dl-icore.dtb \
 	imx6dl-icore-rqs.dtb \
+	imx6q-cm-fx6.dtb \
 	imx6q-icore.dtb \
 	imx6q-icore-rqs.dtb \
 	imx6q-logicpd.dtb \
diff --git a/arch/arm/dts/imx6q-cm-fx6.dts b/arch/arm/dts/imx6q-cm-fx6.dts
new file mode 100644
index 0000000000000000000000000000000000000000..4f1fced40eacd582f143ba406f35b6d6d3bcb765
--- /dev/null
+++ b/arch/arm/dts/imx6q-cm-fx6.dts
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2013 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6";
+	compatible = "compulab,cm-fx6", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		heartbeat-led {
+			label = "Heartbeat";
+			gpios = <&gpio2 31 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+};
+
+&iomuxc {
+	imx6q-cm-fx6 {
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b0b0
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b0b0
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			>;
+		};
+
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
+				MX6QDL_PAD_SD4_DAT0__NAND_DQS		0x00b1
+			>;
+		};
+
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+			>;
+		};
+	};
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&sata {
+	status = "okay";
+};
+
+&usdhc3 {
+	status = "okay";
+};
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index 9e83b4221e025e1a8004fc4fba6ff3ea1e26394f..1017eb84f95ad028acd7bab274ec226ae7452267 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -279,7 +279,7 @@ void arch_preboot_os(void)
 	imx_pcie_remove();
 #endif
 #if defined(CONFIG_SATA)
-	sata_stop();
+	sata_remove(0);
 #if defined(CONFIG_MX6)
 	disable_sata_clock();
 #endif
diff --git a/arch/arm/mach-rmobile/include/mach/sh_sdhi.h b/arch/arm/mach-rmobile/include/mach/sh_sdhi.h
index 1fb0648b126036f251c14576258b0db80c8151ea..00a135faa145c10194158dd8384e05fc941e36fc 100644
--- a/arch/arm/mach-rmobile/include/mach/sh_sdhi.h
+++ b/arch/arm/mach-rmobile/include/mach/sh_sdhi.h
@@ -49,11 +49,6 @@
 
 /* SDHI CMD VALUE */
 #define CMD_MASK			0x0000ffff
-#define SDHI_APP			0x0040
-#define SDHI_MMC_SEND_OP_COND		0x0701
-#define SDHI_SD_APP_SEND_SCR		0x0073
-#define SDHI_SD_SWITCH			0x1C06
-#define SDHI_MMC_SEND_EXT_CSD		0x1C08
 
 /* SDHI_PORTSEL */
 #define USE_1PORT			(1 << 8) /* 1 port */
diff --git a/board/compulab/cm_fx6/cm_fx6.c b/board/compulab/cm_fx6/cm_fx6.c
index a1da2780aa444b5799d002dee8773ff76ccaffa1..638e9f393b9cb6dda10156319a4ccae9f5ab4318 100644
--- a/board/compulab/cm_fx6/cm_fx6.c
+++ b/board/compulab/cm_fx6/cm_fx6.c
@@ -9,7 +9,9 @@
  */
 
 #include <common.h>
+#include <ahci.h>
 #include <dm.h>
+#include <dwc_ahsata.h>
 #include <fsl_esdhc.h>
 #include <miiphy.h>
 #include <mtd_node.h>
@@ -29,6 +31,7 @@
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <dm/platform_data/serial_mxc.h>
+#include <dm/device-internal.h>
 #include <jffs2/load_kernel.h>
 #include "common.h"
 #include "../common/eeprom.h"
@@ -206,6 +209,8 @@ static int cm_fx6_setup_issd(void)
 }
 
 #define CM_FX6_SATA_INIT_RETRIES	10
+
+# if !CONFIG_IS_ENABLED(AHCI)
 int sata_initialize(void)
 {
 	int err, i;
@@ -246,6 +251,7 @@ int sata_stop(void)
 
 	return 0;
 }
+# endif
 #else
 static int cm_fx6_setup_issd(void) { return 0; }
 #endif
@@ -672,6 +678,17 @@ int board_init(void)
 
 	cm_fx6_setup_display();
 
+	/* This should be done in the MMC driver when MX6 has a clock driver */
+#ifdef CONFIG_FSL_ESDHC
+	if (IS_ENABLED(CONFIG_BLK)) {
+		int i;
+
+		cm_fx6_set_usdhc_iomux();
+		for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++)
+			enable_usdhc_clk(1, i);
+	}
+#endif
+
 	return 0;
 }
 
@@ -757,3 +774,66 @@ U_BOOT_DEVICE(cm_fx6_serial) = {
 	.name	= "serial_mxc",
 	.platdata = &cm_fx6_mxc_serial_plat,
 };
+
+#if CONFIG_IS_ENABLED(AHCI)
+static int sata_imx_probe(struct udevice *dev)
+{
+	int i, err;
+
+	/* Make sure this gpio has logical 0 value */
+	gpio_direction_output(CM_FX6_SATA_PWLOSS_INT, 0);
+	udelay(100);
+	cm_fx6_sata_power(1);
+
+	for (i = 0; i < CM_FX6_SATA_INIT_RETRIES; i++) {
+		err = setup_sata();
+		if (err) {
+			printf("SATA setup failed: %d\n", err);
+			return err;
+		}
+
+		udelay(100);
+
+		err = dwc_ahsata_probe(dev);
+		if (!err)
+			break;
+
+		/* There is no device on the SATA port */
+		if (sata_dm_port_status(0, 0) == 0)
+			break;
+
+		/* There's a device, but link not established. Retry */
+		device_remove(dev, DM_REMOVE_NORMAL);
+	}
+
+	return 0;
+}
+
+static int sata_imx_remove(struct udevice *dev)
+{
+	cm_fx6_sata_power(0);
+	mdelay(250);
+
+	return 0;
+}
+
+struct ahci_ops sata_imx_ops = {
+	.port_status = dwc_ahsata_port_status,
+	.reset	= dwc_ahsata_bus_reset,
+	.scan	= dwc_ahsata_scan,
+};
+
+static const struct udevice_id sata_imx_ids[] = {
+	{ .compatible = "fsl,imx6q-ahci" },
+	{ }
+};
+
+U_BOOT_DRIVER(sata_imx) = {
+	.name		= "dwc_ahci",
+	.id		= UCLASS_AHCI,
+	.of_match	= sata_imx_ids,
+	.ops		= &sata_imx_ops,
+	.probe		= sata_imx_probe,
+	.remove		= sata_imx_remove,  /* reset bus to stop it */
+};
+#endif /* AHCI */
diff --git a/cmd/Makefile b/cmd/Makefile
index 13c86f8fccc2dadc24ad9fa0cdc65e46280530c0..4a865bd7d7540e6769d7c287071a6b062c8b2f85 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -15,6 +15,7 @@ obj-y += version.o
 # command
 obj-$(CONFIG_CMD_AES) += aes.o
 obj-$(CONFIG_CMD_ARMFLASH) += armflash.o
+obj-y += blk_common.o
 obj-$(CONFIG_SOURCE) += source.o
 obj-$(CONFIG_CMD_SOURCE) += source.o
 obj-$(CONFIG_CMD_BDI) += bdinfo.o
diff --git a/cmd/blk_common.c b/cmd/blk_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..86c75e78d8892a3a1f6ea45728307f61ae86b593
--- /dev/null
+++ b/cmd/blk_common.c
@@ -0,0 +1,104 @@
+/*
+ * Handling of common block commands
+ *
+ * Copyright (c) 2017 Google, Inc
+ *
+ * (C) Copyright 2000-2011
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <blk.h>
+
+#ifdef HAVE_BLOCK_DEVICE
+int blk_common_cmd(int argc, char * const argv[], enum if_type if_type,
+		   int *cur_devnump)
+{
+	const char *if_name = blk_get_if_type_name(if_type);
+
+	switch (argc) {
+	case 0:
+	case 1:
+		return CMD_RET_USAGE;
+	case 2:
+		if (strncmp(argv[1], "inf", 3) == 0) {
+			blk_list_devices(if_type);
+			return 0;
+		} else if (strncmp(argv[1], "dev", 3) == 0) {
+			if (blk_print_device_num(if_type, *cur_devnump)) {
+				printf("\nno %s devices available\n", if_name);
+				return CMD_RET_FAILURE;
+			}
+			return 0;
+		} else if (strncmp(argv[1], "part", 4) == 0) {
+			if (blk_list_part(if_type))
+				printf("\nno %s devices available\n", if_name);
+			return 0;
+		}
+		return CMD_RET_USAGE;
+	case 3:
+		if (strncmp(argv[1], "dev", 3) == 0) {
+			int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+			if (!blk_show_device(if_type, dev)) {
+				*cur_devnump = dev;
+				printf("... is now current device\n");
+			} else {
+				return CMD_RET_FAILURE;
+			}
+			return 0;
+		} else if (strncmp(argv[1], "part", 4) == 0) {
+			int dev = (int)simple_strtoul(argv[2], NULL, 10);
+
+			if (blk_print_part_devnum(if_type, dev)) {
+				printf("\n%s device %d not available\n",
+				       if_name, dev);
+				return CMD_RET_FAILURE;
+			}
+			return 0;
+		}
+		return CMD_RET_USAGE;
+
+	default: /* at least 4 args */
+		if (strcmp(argv[1], "read") == 0) {
+			ulong addr = simple_strtoul(argv[2], NULL, 16);
+			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
+			ulong cnt = simple_strtoul(argv[4], NULL, 16);
+			ulong n;
+
+			printf("\n%s read: device %d block # %lld, count %ld ... ",
+			       if_name, *cur_devnump, (unsigned long long)blk,
+			       cnt);
+
+			n = blk_read_devnum(if_type, *cur_devnump, blk, cnt,
+					    (ulong *)addr);
+
+			printf("%ld blocks read: %s\n", n,
+			       n == cnt ? "OK" : "ERROR");
+			return n == cnt ? 0 : 1;
+		} else if (strcmp(argv[1], "write") == 0) {
+			ulong addr = simple_strtoul(argv[2], NULL, 16);
+			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
+			ulong cnt = simple_strtoul(argv[4], NULL, 16);
+			ulong n;
+
+			printf("\n%s write: device %d block # %lld, count %ld ... ",
+			       if_name, *cur_devnump, (unsigned long long)blk,
+			       cnt);
+
+			n = blk_write_devnum(if_type, *cur_devnump, blk, cnt,
+					     (ulong *)addr);
+
+			printf("%ld blocks written: %s\n", n,
+			       n == cnt ? "OK" : "ERROR");
+			return n == cnt ? 0 : 1;
+		} else {
+			return CMD_RET_USAGE;
+		}
+
+		return 0;
+	}
+}
+#endif
diff --git a/cmd/ide.c b/cmd/ide.c
index 10fb2f95a7f371154cf3e52a72defc0384d311fa..e3c32420cfe8886590dcee5478f41fa21140343d 100644
--- a/cmd/ide.c
+++ b/cmd/ide.c
@@ -34,116 +34,15 @@ static int curr_device = -1;
 
 int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
-	int rcode = 0;
-
-	switch (argc) {
-	case 0:
-	case 1:
-		return CMD_RET_USAGE;
-	case 2:
+	if (argc == 2) {
 		if (strncmp(argv[1], "res", 3) == 0) {
 			puts("\nReset IDE: ");
 			ide_init();
 			return 0;
-		} else if (strncmp(argv[1], "inf", 3) == 0) {
-			blk_list_devices(IF_TYPE_IDE);
-			return 0;
-
-		} else if (strncmp(argv[1], "dev", 3) == 0) {
-			if (blk_print_device_num(IF_TYPE_IDE, curr_device)) {
-				printf("\nno IDE devices available\n");
-				return CMD_RET_FAILURE;
-			}
-
-			return 0;
-		} else if (strncmp(argv[1], "part", 4) == 0) {
-			if (blk_list_part(IF_TYPE_IDE))
-				printf("\nno IDE devices available\n");
-			return 1;
 		}
-		return CMD_RET_USAGE;
-	case 3:
-		if (strncmp(argv[1], "dev", 3) == 0) {
-			int dev = (int)simple_strtoul(argv[2], NULL, 10);
-
-			if (!blk_show_device(IF_TYPE_IDE, dev)) {
-				curr_device = dev;
-				printf("... is now current device\n");
-			} else {
-				return CMD_RET_FAILURE;
-			}
-			return 0;
-		} else if (strncmp(argv[1], "part", 4) == 0) {
-			int dev = (int)simple_strtoul(argv[2], NULL, 10);
-
-			if (blk_print_part_devnum(IF_TYPE_IDE, dev)) {
-				printf("\nIDE device %d not available\n", dev);
-				return CMD_RET_FAILURE;
-			}
-			return 1;
-		}
-
-		return CMD_RET_USAGE;
-	default:
-		/* at least 4 args */
-
-		if (strcmp(argv[1], "read") == 0) {
-			ulong addr = simple_strtoul(argv[2], NULL, 16);
-			ulong cnt = simple_strtoul(argv[4], NULL, 16);
-			ulong n;
-
-#ifdef CONFIG_SYS_64BIT_LBA
-			lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
-
-			printf("\nIDE read: device %d block # %lld, count %ld...",
-			       curr_device, blk, cnt);
-#else
-			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
-
-			printf("\nIDE read: device %d block # %ld, count %ld...",
-			       curr_device, blk, cnt);
-#endif
-
-			n = blk_read_devnum(IF_TYPE_IDE, curr_device, blk, cnt,
-					    (ulong *)addr);
-
-			printf("%ld blocks read: %s\n",
-			       n, (n == cnt) ? "OK" : "ERROR");
-			if (n == cnt)
-				return 0;
-			else
-				return 1;
-		} else if (strcmp(argv[1], "write") == 0) {
-			ulong addr = simple_strtoul(argv[2], NULL, 16);
-			ulong cnt = simple_strtoul(argv[4], NULL, 16);
-			ulong n;
-
-#ifdef CONFIG_SYS_64BIT_LBA
-			lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
-
-			printf("\nIDE write: device %d block # %lld, count %ld...",
-			       curr_device, blk, cnt);
-#else
-			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
-
-			printf("\nIDE write: device %d block # %ld, count %ld...",
-			       curr_device, blk, cnt);
-#endif
-			n = blk_write_devnum(IF_TYPE_IDE, curr_device, blk, cnt,
-					     (ulong *)addr);
-
-			printf("%ld blocks written: %s\n", n,
-			       n == cnt ? "OK" : "ERROR");
-			if (n == cnt)
-				return 0;
-			else
-				return 1;
-		} else {
-			return CMD_RET_USAGE;
-		}
-
-		return rcode;
 	}
+
+	return blk_common_cmd(argc, argv, IF_TYPE_IDE, &curr_device);
 }
 
 int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
diff --git a/cmd/mmc.c b/cmd/mmc.c
index f7b75684adedc0673f03664aee63c1f71275bdc6..00697fc1f2b7bd8323ca0c0fb723685c1949595d 100644
--- a/cmd/mmc.c
+++ b/cmd/mmc.c
@@ -643,6 +643,28 @@ static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag,
 	printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
 	return CMD_RET_SUCCESS;
 }
+
+static int mmc_partconf_print(struct mmc *mmc)
+{
+	u8 ack, access, part;
+
+	if (mmc->part_config == MMCPART_NOAVAILABLE) {
+		printf("No part_config info for ver. 0x%x\n", mmc->version);
+		return CMD_RET_FAILURE;
+	}
+
+	access = EXT_CSD_EXTRACT_PARTITION_ACCESS(mmc->part_config);
+	ack = EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config);
+	part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
+
+	printf("EXT_CSD[179], PARTITION_CONFIG:\n"
+		"BOOT_ACK: 0x%x\n"
+		"BOOT_PARTITION_ENABLE: 0x%x\n"
+		"PARTITION_ACCESS: 0x%x\n", ack, part, access);
+
+	return CMD_RET_SUCCESS;
+}
+
 static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
 			   int argc, char * const argv[])
 {
@@ -650,13 +672,10 @@ static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
 	struct mmc *mmc;
 	u8 ack, part_num, access;
 
-	if (argc != 5)
+	if (argc != 2 && argc != 5)
 		return CMD_RET_USAGE;
 
 	dev = simple_strtoul(argv[1], NULL, 10);
-	ack = simple_strtoul(argv[2], NULL, 10);
-	part_num = simple_strtoul(argv[3], NULL, 10);
-	access = simple_strtoul(argv[4], NULL, 10);
 
 	mmc = init_mmc_device(dev, false);
 	if (!mmc)
@@ -667,6 +686,13 @@ static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
 		return CMD_RET_FAILURE;
 	}
 
+	if (argc == 2)
+		return mmc_partconf_print(mmc);
+
+	ack = simple_strtoul(argv[2], NULL, 10);
+	part_num = simple_strtoul(argv[3], NULL, 10);
+	access = simple_strtoul(argv[4], NULL, 10);
+
 	/* acknowledge to be sent during boot operation */
 	return mmc_set_part_conf(mmc, ack, part_num, access);
 }
@@ -832,8 +858,8 @@ U_BOOT_CMD(
 	" - Set the BOOT_BUS_WIDTH field of the specified device\n"
 	"mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
 	" - Change sizes of boot and RPMB partitions of specified device\n"
-	"mmc partconf dev boot_ack boot_partition partition_access\n"
-	" - Change the bits of the PARTITION_CONFIG field of the specified device\n"
+	"mmc partconf dev [boot_ack boot_partition partition_access]\n"
+	" - Show or change the bits of the PARTITION_CONFIG field of the specified device\n"
 	"mmc rst-function dev value\n"
 	" - Change the RST_n_FUNCTION field of the specified device\n"
 	"   WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
diff --git a/cmd/sata.c b/cmd/sata.c
index 4c53022ff60a365ea030e80c3e9b112d55f9b50f..7817442532a490398d0affeeb1fc7e5ed35c1a7e 100644
--- a/cmd/sata.c
+++ b/cmd/sata.c
@@ -11,124 +11,116 @@
  */
 
 #include <common.h>
+#include <ahci.h>
+#include <dm.h>
 #include <command.h>
 #include <part.h>
 #include <sata.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
 
 static int sata_curr_device = -1;
 
+int sata_remove(int devnum)
+{
+#ifdef CONFIG_AHCI
+	struct udevice *dev;
+	int rc;
+
+	rc = uclass_find_device(UCLASS_AHCI, devnum, &dev);
+	if (!rc && !dev)
+		rc = uclass_find_first_device(UCLASS_AHCI, &dev);
+	if (rc || !dev) {
+		printf("Cannot find SATA device %d (err=%d)\n", devnum, rc);
+		return CMD_RET_FAILURE;
+	}
+
+	rc = device_remove(dev, DM_REMOVE_NORMAL);
+	if (rc) {
+		printf("Cannot remove SATA device '%s' (err=%d)\n", dev->name,
+		       rc);
+		return CMD_RET_FAILURE;
+	}
+
+	return 0;
+#else
+	return sata_stop();
+#endif
+}
+
+int sata_probe(int devnum)
+{
+#ifdef CONFIG_AHCI
+	struct udevice *dev;
+	struct udevice *blk;
+	int rc;
+
+	rc = uclass_get_device(UCLASS_AHCI, devnum, &dev);
+	if (rc)
+		rc = uclass_find_first_device(UCLASS_AHCI, &dev);
+	if (rc) {
+		printf("Cannot probe SATA device %d (err=%d)\n", devnum, rc);
+		return CMD_RET_FAILURE;
+	}
+	rc = sata_scan(dev);
+	if (rc) {
+		printf("Cannot scan SATA device %d (err=%d)\n", devnum, rc);
+		return CMD_RET_FAILURE;
+	}
+
+	rc = blk_get_from_parent(dev, &blk);
+	if (!rc) {
+		struct blk_desc *desc = dev_get_uclass_platdata(blk);
+
+		if (desc->lba > 0 && desc->blksz > 0)
+			part_init(desc);
+	}
+
+	return 0;
+#else
+	return sata_initialize() < 0 ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+#endif
+}
+
 static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	int rc = 0;
 
-	if (argc == 2 && strcmp(argv[1], "stop") == 0)
-		return sata_stop();
+	if (argc >= 2) {
+		int devnum = 0;
 
-	if (argc == 2 && strcmp(argv[1], "init") == 0) {
-		if (sata_curr_device != -1)
-			sata_stop();
+		if (argc == 3)
+			devnum = (int)simple_strtoul(argv[2], NULL, 10);
+		if (!strcmp(argv[1], "stop"))
+			return sata_remove(devnum);
+
+		if (!strcmp(argv[1], "init")) {
+			if (sata_curr_device != -1) {
+				rc = sata_remove(devnum);
+				if (rc)
+					return rc;
+			}
 
-		return (sata_initialize() < 0) ?
-			CMD_RET_FAILURE : CMD_RET_SUCCESS;
+			return sata_probe(devnum);
+		}
 	}
 
 	/* If the user has not yet run `sata init`, do it now */
 	if (sata_curr_device == -1) {
-		rc = sata_initialize();
-		if (rc == -1)
+		rc = sata_probe(0);
+		if (rc < 0)
 			return CMD_RET_FAILURE;
-		sata_curr_device = rc;
+		sata_curr_device = 0;
 	}
 
-	switch (argc) {
-	case 0:
-	case 1:
-		return CMD_RET_USAGE;
-	case 2:
-		if (strncmp(argv[1], "inf", 3) == 0) {
-			blk_list_devices(IF_TYPE_SATA);
-			return 0;
-		} else if (strncmp(argv[1], "dev", 3) == 0) {
-			if (blk_print_device_num(IF_TYPE_SATA,
-						 sata_curr_device)) {
-				printf("\nno SATA devices available\n");
-				return CMD_RET_FAILURE;
-			}
-			return 0;
-		} else if (strncmp(argv[1], "part", 4) == 0) {
-			if (blk_list_part(IF_TYPE_SATA))
-				puts("\nno SATA devices available\n");
-			return 0;
-		}
-		return CMD_RET_USAGE;
-	case 3:
-		if (strncmp(argv[1], "dev", 3) == 0) {
-			int dev = (int)simple_strtoul(argv[2], NULL, 10);
-
-			if (!blk_show_device(IF_TYPE_SATA, dev)) {
-				sata_curr_device = dev;
-				printf("... is now current device\n");
-			} else {
-				return CMD_RET_FAILURE;
-			}
-			return 0;
-		} else if (strncmp(argv[1], "part", 4) == 0) {
-			int dev = (int)simple_strtoul(argv[2], NULL, 10);
-
-			if (blk_print_part_devnum(IF_TYPE_SATA, dev)) {
-				printf("\nSATA device %d not available\n",
-				       dev);
-				return CMD_RET_FAILURE;
-			}
-			return rc;
-		}
-		return CMD_RET_USAGE;
-
-	default: /* at least 4 args */
-		if (strcmp(argv[1], "read") == 0) {
-			ulong addr = simple_strtoul(argv[2], NULL, 16);
-			ulong cnt = simple_strtoul(argv[4], NULL, 16);
-			ulong n;
-			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
-
-			printf("\nSATA read: device %d block # %ld, count %ld ... ",
-				sata_curr_device, blk, cnt);
-
-			n = blk_read_devnum(IF_TYPE_SATA, sata_curr_device, blk,
-					    cnt, (ulong *)addr);
-
-			printf("%ld blocks read: %s\n",
-				n, (n==cnt) ? "OK" : "ERROR");
-			return (n == cnt) ? 0 : 1;
-		} else if (strcmp(argv[1], "write") == 0) {
-			ulong addr = simple_strtoul(argv[2], NULL, 16);
-			ulong cnt = simple_strtoul(argv[4], NULL, 16);
-			ulong n;
-
-			lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
-
-			printf("\nSATA write: device %d block # %ld, count %ld ... ",
-				sata_curr_device, blk, cnt);
-
-			n = blk_write_devnum(IF_TYPE_SATA, sata_curr_device,
-					     blk, cnt, (ulong *)addr);
-
-			printf("%ld blocks written: %s\n",
-				n, (n == cnt) ? "OK" : "ERROR");
-			return (n == cnt) ? 0 : 1;
-		} else {
-			return CMD_RET_USAGE;
-		}
-
-		return rc;
-	}
+	return blk_common_cmd(argc, argv, IF_TYPE_SATA, &sata_curr_device);
 }
 
 U_BOOT_CMD(
 	sata, 5, 1, do_sata,
 	"SATA sub system",
 	"init - init SATA sub system\n"
-	"sata stop - disable SATA sub system\n"
+	"sata stop [dev] - disable SATA sub system or device\n"
 	"sata info - show available SATA devices\n"
 	"sata device [dev] - show or set current device\n"
 	"sata part [dev] - print partition table\n"
diff --git a/cmd/scsi.c b/cmd/scsi.c
index 8e36de107e9a91a01376164accfdb96c4fd235a0..b9d086fb6b1943130193d02b20aef5d4905286f5 100644
--- a/cmd/scsi.c
+++ b/cmd/scsi.c
@@ -29,11 +29,7 @@ static int do_scsi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
 	int ret;
 
-	switch (argc) {
-	case 0:
-	case 1:
-		return CMD_RET_USAGE;
-	case 2:
+	if (argc == 2) {
 		if (strncmp(argv[1], "res", 3) == 0) {
 			printf("\nReset SCSI\n");
 #ifndef CONFIG_DM_SCSI
@@ -44,84 +40,15 @@ static int do_scsi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 				return CMD_RET_FAILURE;
 			return ret;
 		}
-		if (strncmp(argv[1], "inf", 3) == 0) {
-			blk_list_devices(IF_TYPE_SCSI);
-			return 0;
-		}
-		if (strncmp(argv[1], "dev", 3) == 0) {
-			if (blk_print_device_num(IF_TYPE_SCSI, scsi_curr_dev)) {
-				printf("\nno SCSI devices available\n");
-				return CMD_RET_FAILURE;
-			}
-
-			return 0;
-		}
 		if (strncmp(argv[1], "scan", 4) == 0) {
 			ret = scsi_scan(true);
 			if (ret)
 				return CMD_RET_FAILURE;
 			return ret;
 		}
-		if (strncmp(argv[1], "part", 4) == 0) {
-			if (blk_list_part(IF_TYPE_SCSI))
-				printf("\nno SCSI devices available\n");
-			return 0;
-		}
-		return CMD_RET_USAGE;
-	case 3:
-		if (strncmp(argv[1], "dev", 3) == 0) {
-			int dev = (int)simple_strtoul(argv[2], NULL, 10);
+	}
 
-			if (!blk_show_device(IF_TYPE_SCSI, dev)) {
-				scsi_curr_dev = dev;
-				printf("... is now current device\n");
-			} else {
-				return CMD_RET_FAILURE;
-			}
-			return 0;
-		}
-		if (strncmp(argv[1], "part", 4) == 0) {
-			int dev = (int)simple_strtoul(argv[2], NULL, 10);
-
-			if (blk_print_part_devnum(IF_TYPE_SCSI, dev)) {
-				printf("\nSCSI device %d not available\n",
-				       dev);
-				return CMD_RET_FAILURE;
-			}
-			return 0;
-		}
-		return CMD_RET_USAGE;
-	default:
-		/* at least 4 args */
-		if (strcmp(argv[1], "read") == 0) {
-			ulong addr = simple_strtoul(argv[2], NULL, 16);
-			ulong blk  = simple_strtoul(argv[3], NULL, 16);
-			ulong cnt  = simple_strtoul(argv[4], NULL, 16);
-			ulong n;
-
-			printf("\nSCSI read: device %d block # %ld, count %ld ... ",
-			       scsi_curr_dev, blk, cnt);
-			n = blk_read_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk,
-					    cnt, (ulong *)addr);
-			printf("%ld blocks read: %s\n", n,
-			       n == cnt ? "OK" : "ERROR");
-			return 0;
-		} else if (strcmp(argv[1], "write") == 0) {
-			ulong addr = simple_strtoul(argv[2], NULL, 16);
-			ulong blk = simple_strtoul(argv[3], NULL, 16);
-			ulong cnt = simple_strtoul(argv[4], NULL, 16);
-			ulong n;
-
-			printf("\nSCSI write: device %d block # %ld, count %ld ... ",
-			       scsi_curr_dev, blk, cnt);
-			n = blk_write_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk,
-					     cnt, (ulong *)addr);
-			printf("%ld blocks written: %s\n", n,
-			       n == cnt ? "OK" : "ERROR");
-			return 0;
-		}
-	} /* switch */
-	return CMD_RET_USAGE;
+	return blk_common_cmd(argc, argv, IF_TYPE_SCSI, &scsi_curr_dev);
 }
 
 U_BOOT_CMD(
diff --git a/cmd/usb.c b/cmd/usb.c
index 992d41408191c8fa20445a378ba80148850f8fde..d95bcf5c8eec43ed6997d9fe6b2042328eab434a 100644
--- a/cmd/usb.c
+++ b/cmd/usb.c
@@ -621,9 +621,6 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	struct usb_device *udev = NULL;
 	int i;
 	extern char usb_started;
-#ifdef CONFIG_USB_STORAGE
-	struct blk_desc *stor_dev;
-#endif
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
@@ -712,112 +709,10 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	if (strncmp(argv[1], "stor", 4) == 0)
 		return usb_stor_info();
 
-	if (strncmp(argv[1], "part", 4) == 0) {
-		int devno, ok = 0;
-		if (argc == 2) {
-			for (devno = 0; ; ++devno) {
-				stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
-								  devno);
-				if (stor_dev == NULL)
-					break;
-				if (stor_dev->type != DEV_TYPE_UNKNOWN) {
-					ok++;
-					if (devno)
-						printf("\n");
-					debug("print_part of %x\n", devno);
-					part_print(stor_dev);
-				}
-			}
-		} else {
-			devno = simple_strtoul(argv[2], NULL, 16);
-			stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno);
-			if (stor_dev != NULL &&
-			    stor_dev->type != DEV_TYPE_UNKNOWN) {
-				ok++;
-				debug("print_part of %x\n", devno);
-				part_print(stor_dev);
-			}
-		}
-		if (!ok) {
-			printf("\nno USB devices available\n");
-			return 1;
-		}
-		return 0;
-	}
-	if (strcmp(argv[1], "read") == 0) {
-		if (usb_stor_curr_dev < 0) {
-			printf("no current device selected\n");
-			return 1;
-		}
-		if (argc == 5) {
-			unsigned long addr = simple_strtoul(argv[2], NULL, 16);
-			unsigned long blk  = simple_strtoul(argv[3], NULL, 16);
-			unsigned long cnt  = simple_strtoul(argv[4], NULL, 16);
-			unsigned long n;
-			printf("\nUSB read: device %d block # %ld, count %ld"
-				" ... ", usb_stor_curr_dev, blk, cnt);
-			stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
-							  usb_stor_curr_dev);
-			n = blk_dread(stor_dev, blk, cnt, (ulong *)addr);
-			printf("%ld blocks read: %s\n", n,
-				(n == cnt) ? "OK" : "ERROR");
-			if (n == cnt)
-				return 0;
-			return 1;
-		}
-	}
-	if (strcmp(argv[1], "write") == 0) {
-		if (usb_stor_curr_dev < 0) {
-			printf("no current device selected\n");
-			return 1;
-		}
-		if (argc == 5) {
-			unsigned long addr = simple_strtoul(argv[2], NULL, 16);
-			unsigned long blk  = simple_strtoul(argv[3], NULL, 16);
-			unsigned long cnt  = simple_strtoul(argv[4], NULL, 16);
-			unsigned long n;
-			printf("\nUSB write: device %d block # %ld, count %ld"
-				" ... ", usb_stor_curr_dev, blk, cnt);
-			stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
-							  usb_stor_curr_dev);
-			n = blk_dwrite(stor_dev, blk, cnt, (ulong *)addr);
-			printf("%ld blocks write: %s\n", n,
-				(n == cnt) ? "OK" : "ERROR");
-			if (n == cnt)
-				return 0;
-			return 1;
-		}
-	}
-	if (strncmp(argv[1], "dev", 3) == 0) {
-		if (argc == 3) {
-			int dev = (int)simple_strtoul(argv[2], NULL, 10);
-			printf("\nUSB device %d: ", dev);
-			stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, dev);
-			if ((stor_dev == NULL) ||
-			    (stor_dev->if_type == IF_TYPE_UNKNOWN)) {
-				printf("unknown device\n");
-				return 1;
-			}
-			printf("\n    Device %d: ", dev);
-			dev_print(stor_dev);
-			if (stor_dev->type == DEV_TYPE_UNKNOWN)
-				return 1;
-			usb_stor_curr_dev = dev;
-			printf("... is now current device\n");
-			return 0;
-		} else {
-			printf("\nUSB device %d: ", usb_stor_curr_dev);
-			stor_dev = blk_get_devnum_by_type(IF_TYPE_USB,
-							  usb_stor_curr_dev);
-			dev_print(stor_dev);
-			if (stor_dev->type == DEV_TYPE_UNKNOWN)
-				return 1;
-			return 0;
-		}
-		return 0;
-	}
-#endif /* CONFIG_USB_STORAGE */
+	return blk_common_cmd(argc, argv, IF_TYPE_USB, &usb_stor_curr_dev);
+#else
 	return CMD_RET_USAGE;
+#endif /* CONFIG_USB_STORAGE */
 }
 
 U_BOOT_CMD(
diff --git a/common/splash_source.c b/common/splash_source.c
index 8c0ac581f7309f5bbf780970646e28e138e08a3f..a21ad62f82d7abd59d6789a345d7a5903d7e474b 100644
--- a/common/splash_source.c
+++ b/common/splash_source.c
@@ -166,7 +166,7 @@ static inline int splash_init_usb(void)
 #ifdef CONFIG_SATA
 static int splash_init_sata(void)
 {
-	return sata_initialize();
+	return sata_probe(0);
 }
 #else
 static inline int splash_init_sata(void)
diff --git a/configs/cm_fx6_defconfig b/configs/cm_fx6_defconfig
index bbe82a678dbc28f7efcfd4f5fa188c5af6042b56..d3aab58cf61c40d5de6fb052f4e333e3cc8b6680 100644
--- a/configs/cm_fx6_defconfig
+++ b/configs/cm_fx6_defconfig
@@ -11,6 +11,8 @@ CONFIG_SPL_SPI_SUPPORT=y
 CONFIG_SPL_WATCHDOG_SUPPORT=y
 CONFIG_VIDEO=y
 # CONFIG_CMD_BMODE is not set
+CONFIG_DEFAULT_DEVICE_TREE="imx6q-cm-fx6"
+CONFIG_AHCI=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg,MX6QDL"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
@@ -49,6 +51,8 @@ CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_CMD_MTDPARTS=y
+CONFIG_OF_CONTROL=y
+CONFIG_DM_MMC=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_ATMEL=y
 CONFIG_SPI_FLASH_EON=y
@@ -59,9 +63,11 @@ CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_SST=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_PHYLIB=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_REGULATOR=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
-CONFIG_OF_LIBFDT=y
 CONFIG_FDT_FIXUP_PARTITIONS=y
diff --git a/configs/imx6q_logic_defconfig b/configs/imx6q_logic_defconfig
index 1070f892c49809eb8140c20f833fd4cff8866aef..bb13abedf7b4763f1f8796e4f83549fa6d17278f 100644
--- a/configs/imx6q_logic_defconfig
+++ b/configs/imx6q_logic_defconfig
@@ -31,7 +31,6 @@ CONFIG_CMD_FS_GENERIC=y
 CONFIG_CMD_MTDPARTS=y
 # CONFIG_BLK is not set
 CONFIG_SYS_I2C_MXC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_NAND=y
 CONFIG_NAND_MXS=y
 CONFIG_PHYLIB=y
diff --git a/configs/imx6qdl_icore_mmc_defconfig b/configs/imx6qdl_icore_mmc_defconfig
index 090480aacbe7fb7ad288f82a9962366658167c8a..ec39d091348cbfc7c73b7cd44866a372015b769c 100644
--- a/configs/imx6qdl_icore_mmc_defconfig
+++ b/configs/imx6qdl_icore_mmc_defconfig
@@ -38,7 +38,6 @@ CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_LIST="imx6q-icore imx6dl-icore"
 # CONFIG_BLK is not set
 CONFIG_SYS_I2C_MXC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PHYLIB=y
 CONFIG_PHY_SMSC=y
 CONFIG_FEC_MXC=y
diff --git a/configs/imx6qdl_icore_rqs_defconfig b/configs/imx6qdl_icore_rqs_defconfig
index 78128a08726b36e624f9489b081d773c549037d4..ba3ac1bbf924a50fa7d45a26f21859656eb3ff3e 100644
--- a/configs/imx6qdl_icore_rqs_defconfig
+++ b/configs/imx6qdl_icore_rqs_defconfig
@@ -36,7 +36,6 @@ CONFIG_CMD_FS_GENERIC=y
 CONFIG_OF_LIST="imx6q-icore-rqs imx6dl-icore-rqs"
 # CONFIG_BLK is not set
 CONFIG_SYS_I2C_MXC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
 CONFIG_FEC_MXC=y
diff --git a/configs/imx6ul_geam_mmc_defconfig b/configs/imx6ul_geam_mmc_defconfig
index dfeb083c8f3e0eee037cca9fa88926ebb27c7932..d0abfd802949871fe70a70af1581070d871c56a8 100644
--- a/configs/imx6ul_geam_mmc_defconfig
+++ b/configs/imx6ul_geam_mmc_defconfig
@@ -35,7 +35,6 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 # CONFIG_BLK is not set
 CONFIG_SYS_I2C_MXC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PHYLIB=y
 CONFIG_PHY_SMSC=y
 CONFIG_FEC_MXC=y
diff --git a/configs/imx6ul_geam_nand_defconfig b/configs/imx6ul_geam_nand_defconfig
index ed81f61759c7ab4f427658ae977fea50c9b72aa5..3c0790118020bb6428961c5d325937e0d1db0b0c 100644
--- a/configs/imx6ul_geam_nand_defconfig
+++ b/configs/imx6ul_geam_nand_defconfig
@@ -34,7 +34,6 @@ CONFIG_CMD_FS_GENERIC=y
 CONFIG_CMD_UBI=y
 # CONFIG_BLK is not set
 CONFIG_SYS_I2C_MXC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_NAND=y
 CONFIG_NAND_MXS=y
 CONFIG_PHYLIB=y
diff --git a/configs/imx6ul_isiot_emmc_defconfig b/configs/imx6ul_isiot_emmc_defconfig
index 318deb692d5685019966a32e678b7501875b0eea..eeb0509e204dcfa30d4ecd375d47c2fe4a6c4f9b 100644
--- a/configs/imx6ul_isiot_emmc_defconfig
+++ b/configs/imx6ul_isiot_emmc_defconfig
@@ -33,7 +33,6 @@ CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 # CONFIG_BLK is not set
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PHYLIB=y
 CONFIG_PHY_SMSC=y
 CONFIG_FEC_MXC=y
diff --git a/configs/imx6ul_isiot_mmc_defconfig b/configs/imx6ul_isiot_mmc_defconfig
index 8abfbabfcc12bc396440bfe75bb71ca01b240c02..afa64d80553871e305b4cee7f13934cf290c0114 100644
--- a/configs/imx6ul_isiot_mmc_defconfig
+++ b/configs/imx6ul_isiot_mmc_defconfig
@@ -35,7 +35,6 @@ CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
 # CONFIG_BLK is not set
 CONFIG_SYS_I2C_MXC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PHYLIB=y
 CONFIG_PHY_SMSC=y
 CONFIG_FEC_MXC=y
diff --git a/configs/imx6ul_isiot_nand_defconfig b/configs/imx6ul_isiot_nand_defconfig
index ad11ac3a37760ec19ebe4792cb96cc17b5c03b92..9acf6c535fd29974396f0099b77ac937a84b90a9 100644
--- a/configs/imx6ul_isiot_nand_defconfig
+++ b/configs/imx6ul_isiot_nand_defconfig
@@ -34,7 +34,6 @@ CONFIG_CMD_FS_GENERIC=y
 CONFIG_CMD_UBI=y
 # CONFIG_BLK is not set
 CONFIG_SYS_I2C_MXC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_NAND=y
 CONFIG_NAND_MXS=y
 CONFIG_PHYLIB=y
diff --git a/configs/ls1012aqds_qspi_defconfig b/configs/ls1012aqds_qspi_defconfig
index ff58a74986e1701e092292474bcb4a096cbddba0..426992e577187bf6b77b5e7c8971aec720f060b9 100644
--- a/configs/ls1012aqds_qspi_defconfig
+++ b/configs/ls1012aqds_qspi_defconfig
@@ -36,7 +36,6 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM=y
 # CONFIG_BLK is not set
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_NETDEVICES=y
diff --git a/configs/ls1012ardb_qspi_defconfig b/configs/ls1012ardb_qspi_defconfig
index 6a150221b2545434160af77b188339317e1d0332..4eaaecd9912e9bd0a616c4851901894a4ed40346 100644
--- a/configs/ls1012ardb_qspi_defconfig
+++ b/configs/ls1012ardb_qspi_defconfig
@@ -34,7 +34,6 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM=y
 # CONFIG_BLK is not set
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_NETDEVICES=y
diff --git a/configs/mx6slevk_defconfig b/configs/mx6slevk_defconfig
index ee27daa68e0718897c7157bbcee3c01579b72aa0..f7f4b0edf1feb6f922ece94759187f685232172c 100644
--- a/configs/mx6slevk_defconfig
+++ b/configs/mx6slevk_defconfig
@@ -32,7 +32,6 @@ CONFIG_DM=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_PHYLIB=y
diff --git a/configs/mx6slevk_spinor_defconfig b/configs/mx6slevk_spinor_defconfig
index 354eae3f572972290de583df78b0f23c23ff4d1b..a3d68512cf08c1137602aec1f7c673771eb149e8 100644
--- a/configs/mx6slevk_spinor_defconfig
+++ b/configs/mx6slevk_spinor_defconfig
@@ -33,7 +33,6 @@ CONFIG_DM=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_PHYLIB=y
diff --git a/configs/mx6sllevk_defconfig b/configs/mx6sllevk_defconfig
index 916fa091fa6b63a08ceeced030d0b9218b6d1531..11d2500949a2cba4f067a0f7546490741bca4a68 100644
--- a/configs/mx6sllevk_defconfig
+++ b/configs/mx6sllevk_defconfig
@@ -29,7 +29,6 @@ CONFIG_OF_CONTROL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_IMX6=y
 CONFIG_DM_PMIC=y
diff --git a/configs/mx6sllevk_plugin_defconfig b/configs/mx6sllevk_plugin_defconfig
index 12f865713dde4b311daf4521e7aaf3036e05f070..064c949e35625faa3c836c2c7321700ca71232e7 100644
--- a/configs/mx6sllevk_plugin_defconfig
+++ b/configs/mx6sllevk_plugin_defconfig
@@ -30,7 +30,6 @@ CONFIG_OF_CONTROL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_IMX6=y
 CONFIG_DM_PMIC=y
diff --git a/configs/mx6sxsabreauto_defconfig b/configs/mx6sxsabreauto_defconfig
index a8144fe8021f9afa3370b5e88ff85ca48201cafd..ebf0a9aacba346d262701596e88ca88703830475 100644
--- a/configs/mx6sxsabreauto_defconfig
+++ b/configs/mx6sxsabreauto_defconfig
@@ -34,7 +34,6 @@ CONFIG_DM_GPIO=y
 CONFIG_DM_PCA953X=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_STMICRO=y
diff --git a/configs/mx6ull_14x14_evk_defconfig b/configs/mx6ull_14x14_evk_defconfig
index 2c03f8cba8398ad1249ac0e949232cbab0059910..6ed18da376952e5eb36beb1c6364f2b4cd7e7646 100644
--- a/configs/mx6ull_14x14_evk_defconfig
+++ b/configs/mx6ull_14x14_evk_defconfig
@@ -27,7 +27,6 @@ CONFIG_DM_GPIO=y
 CONFIG_DM_74X164=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_IMX6=y
 CONFIG_DM_REGULATOR=y
diff --git a/configs/mx6ull_14x14_evk_plugin_defconfig b/configs/mx6ull_14x14_evk_plugin_defconfig
index 1a5bbb6265f4b04e20c95f78d8efe494ecf3e504..2c5ae76f263b2e80787b3231920426cc7c1a8a64 100644
--- a/configs/mx6ull_14x14_evk_plugin_defconfig
+++ b/configs/mx6ull_14x14_evk_plugin_defconfig
@@ -28,7 +28,6 @@ CONFIG_DM_GPIO=y
 CONFIG_DM_74X164=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_IMX6=y
 CONFIG_DM_REGULATOR=y
diff --git a/configs/mx7dsabresd_defconfig b/configs/mx7dsabresd_defconfig
index 7c99420e853eba7ed53c145f0d8e8593ff336d54..8f2e33adc8684a527a030b73b6209a879f18dec7 100644
--- a/configs/mx7dsabresd_defconfig
+++ b/configs/mx7dsabresd_defconfig
@@ -45,7 +45,6 @@ CONFIG_DM_GPIO=y
 CONFIG_DM_74X164=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_EON=y
 CONFIG_PHYLIB=y
diff --git a/configs/mx7dsabresd_secure_defconfig b/configs/mx7dsabresd_secure_defconfig
index ea087d2af42f4a9e1551749ce76c3f5349821994..bba933f250b92021d3e296ae7cc820fff30583a6 100644
--- a/configs/mx7dsabresd_secure_defconfig
+++ b/configs/mx7dsabresd_secure_defconfig
@@ -47,7 +47,6 @@ CONFIG_DM_GPIO=y
 CONFIG_DM_74X164=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_EON=y
 CONFIG_PHYLIB=y
diff --git a/configs/mx7ulp_evk_defconfig b/configs/mx7ulp_evk_defconfig
index 5918f3c0c73e152ae14ef5351d0605244b485136..49b576954b58036fa7a0f6d1cdd2c5f398eeb503 100644
--- a/configs/mx7ulp_evk_defconfig
+++ b/configs/mx7ulp_evk_defconfig
@@ -16,7 +16,6 @@ CONFIG_DM_GPIO=y
 CONFIG_IMX_RGPIO2P=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_IMX7ULP=y
 CONFIG_DM_REGULATOR=y
diff --git a/configs/mx7ulp_evk_plugin_defconfig b/configs/mx7ulp_evk_plugin_defconfig
index 5918f3c0c73e152ae14ef5351d0605244b485136..49b576954b58036fa7a0f6d1cdd2c5f398eeb503 100644
--- a/configs/mx7ulp_evk_plugin_defconfig
+++ b/configs/mx7ulp_evk_plugin_defconfig
@@ -16,7 +16,6 @@ CONFIG_DM_GPIO=y
 CONFIG_IMX_RGPIO2P=y
 CONFIG_DM_I2C=y
 CONFIG_DM_MMC=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_IMX7ULP=y
 CONFIG_DM_REGULATOR=y
diff --git a/configs/opos6uldev_defconfig b/configs/opos6uldev_defconfig
index f4511af29300dc18c018a5c900f44090202349bd..88ba18eaeb28cb2674b4a06b102259b019f0aa93 100644
--- a/configs/opos6uldev_defconfig
+++ b/configs/opos6uldev_defconfig
@@ -62,7 +62,6 @@ CONFIG_SYSCON=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MXC=y
 CONFIG_PWRSEQ=y
-# CONFIG_DM_MMC_OPS is not set
 CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
 CONFIG_NETDEVICES=y
diff --git a/drivers/ata/dwc_ahsata.c b/drivers/ata/dwc_ahsata.c
index 78572a5b73afd22b76a13758a36930505b891a59..480ae115afd6cfc74516f04d70797c8d67f50aff 100644
--- a/drivers/ata/dwc_ahsata.c
+++ b/drivers/ata/dwc_ahsata.c
@@ -5,20 +5,22 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <libata.h>
+#include <common.h>
 #include <ahci.h>
+#include <dm.h>
+#include <dwc_ahsata.h>
 #include <fis.h>
-#include <sata.h>
-
-#include <common.h>
+#include <libata.h>
 #include <malloc.h>
-#include <linux/ctype.h>
-#include <linux/errno.h>
+#include <memalign.h>
+#include <sata.h>
 #include <asm/io.h>
-#include <linux/bitops.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/sys_proto.h>
-#include "dwc_ahsata.h"
+#include <linux/bitops.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include "dwc_ahsata_priv.h"
 
 struct sata_port_regs {
 	u32 clb;
@@ -78,8 +80,6 @@ struct sata_host_regs {
 
 #define writel_with_flush(a, b)	do { writel(a, b); readl(b); } while (0)
 
-static int is_ready;
-
 static inline void __iomem *ahci_port_base(void __iomem *base, u32 port)
 {
 	return base + 0x100 + (port * 0x80);
@@ -100,37 +100,33 @@ static int waiting_for_cmd_completed(u8 *offset,
 	return (i < timeout_msec) ? 0 : -1;
 }
 
-static int ahci_setup_oobr(struct ahci_uc_priv *probe_ent,
-						int clk)
+static int ahci_setup_oobr(struct ahci_uc_priv *uc_priv, int clk)
 {
-	struct sata_host_regs *host_mmio =
-		(struct sata_host_regs *)probe_ent->mmio_base;
+	struct sata_host_regs *host_mmio = uc_priv->mmio_base;
 
-	writel(SATA_HOST_OOBR_WE, &(host_mmio->oobr));
-	writel(0x02060b14, &(host_mmio->oobr));
+	writel(SATA_HOST_OOBR_WE, &host_mmio->oobr);
+	writel(0x02060b14, &host_mmio->oobr);
 
 	return 0;
 }
 
-static int ahci_host_init(struct ahci_uc_priv *probe_ent)
+static int ahci_host_init(struct ahci_uc_priv *uc_priv)
 {
 	u32 tmp, cap_save, num_ports;
 	int i, j, timeout = 1000;
 	struct sata_port_regs *port_mmio = NULL;
-	struct sata_host_regs *host_mmio =
-		(struct sata_host_regs *)probe_ent->mmio_base;
+	struct sata_host_regs *host_mmio = uc_priv->mmio_base;
 	int clk = mxc_get_clock(MXC_SATA_CLK);
 
-	cap_save = readl(&(host_mmio->cap));
+	cap_save = readl(&host_mmio->cap);
 	cap_save |= SATA_HOST_CAP_SSS;
 
 	/* global controller reset */
-	tmp = readl(&(host_mmio->ghc));
+	tmp = readl(&host_mmio->ghc);
 	if ((tmp & SATA_HOST_GHC_HR) == 0)
-		writel_with_flush(tmp | SATA_HOST_GHC_HR, &(host_mmio->ghc));
+		writel_with_flush(tmp | SATA_HOST_GHC_HR, &host_mmio->ghc);
 
-	while ((readl(&(host_mmio->ghc)) & SATA_HOST_GHC_HR)
-		&& --timeout)
+	while ((readl(&host_mmio->ghc) & SATA_HOST_GHC_HR) && --timeout)
 		;
 
 	if (timeout <= 0) {
@@ -139,15 +135,14 @@ static int ahci_host_init(struct ahci_uc_priv *probe_ent)
 	}
 
 	/* Set timer 1ms */
-	writel(clk / 1000, &(host_mmio->timer1ms));
+	writel(clk / 1000, &host_mmio->timer1ms);
 
-	ahci_setup_oobr(probe_ent, 0);
+	ahci_setup_oobr(uc_priv, 0);
 
-	writel_with_flush(SATA_HOST_GHC_AE, &(host_mmio->ghc));
-	writel(cap_save, &(host_mmio->cap));
+	writel_with_flush(SATA_HOST_GHC_AE, &host_mmio->ghc);
+	writel(cap_save, &host_mmio->cap);
 	num_ports = (cap_save & SATA_HOST_CAP_NP_MASK) + 1;
-	writel_with_flush((1 << num_ports) - 1,
-				&(host_mmio->pi));
+	writel_with_flush((1 << num_ports) - 1, &host_mmio->pi);
 
 	/*
 	 * Determine which Ports are implemented by the DWC_ahsata,
@@ -155,24 +150,21 @@ static int ahci_host_init(struct ahci_uc_priv *probe_ent)
 	 * software to determine how many Ports are available and
 	 * which Port registers need to be initialized.
 	 */
-	probe_ent->cap = readl(&(host_mmio->cap));
-	probe_ent->port_map = readl(&(host_mmio->pi));
+	uc_priv->cap = readl(&host_mmio->cap);
+	uc_priv->port_map = readl(&host_mmio->pi);
 
 	/* Determine how many command slots the HBA supports */
-	probe_ent->n_ports =
-		(probe_ent->cap & SATA_HOST_CAP_NP_MASK) + 1;
+	uc_priv->n_ports = (uc_priv->cap & SATA_HOST_CAP_NP_MASK) + 1;
 
 	debug("cap 0x%x  port_map 0x%x  n_ports %d\n",
-		probe_ent->cap, probe_ent->port_map, probe_ent->n_ports);
+		uc_priv->cap, uc_priv->port_map, uc_priv->n_ports);
 
-	for (i = 0; i < probe_ent->n_ports; i++) {
-		probe_ent->port[i].port_mmio =
-			ahci_port_base(host_mmio, i);
-		port_mmio =
-			(struct sata_port_regs *)probe_ent->port[i].port_mmio;
+	for (i = 0; i < uc_priv->n_ports; i++) {
+		uc_priv->port[i].port_mmio = ahci_port_base(host_mmio, i);
+		port_mmio = uc_priv->port[i].port_mmio;
 
 		/* Ensure that the DWC_ahsata is in idle state */
-		tmp = readl(&(port_mmio->cmd));
+		tmp = readl(&port_mmio->cmd);
 
 		/*
 		 * When P#CMD.ST, P#CMD.CR, P#CMD.FRE and P#CMD.FR
@@ -187,7 +179,7 @@ static int ahci_host_init(struct ahci_uc_priv *probe_ent)
 			 * 0 when read.
 			 */
 			tmp &= ~SATA_PORT_CMD_ST;
-			writel_with_flush(tmp, &(port_mmio->cmd));
+			writel_with_flush(tmp, &port_mmio->cmd);
 
 			/*
 			 * spec says 500 msecs for each bit, so
@@ -196,7 +188,7 @@ static int ahci_host_init(struct ahci_uc_priv *probe_ent)
 			mdelay(500);
 
 			timeout = 1000;
-			while ((readl(&(port_mmio->cmd)) & SATA_PORT_CMD_CR)
+			while ((readl(&port_mmio->cmd) & SATA_PORT_CMD_CR)
 				&& --timeout)
 				;
 
@@ -207,12 +199,12 @@ static int ahci_host_init(struct ahci_uc_priv *probe_ent)
 		}
 
 		/* Spin-up device */
-		tmp = readl(&(port_mmio->cmd));
-		writel((tmp | SATA_PORT_CMD_SUD), &(port_mmio->cmd));
+		tmp = readl(&port_mmio->cmd);
+		writel((tmp | SATA_PORT_CMD_SUD), &port_mmio->cmd);
 
 		/* Wait for spin-up to finish */
 		timeout = 1000;
-		while (!(readl(&(port_mmio->cmd)) | SATA_PORT_CMD_SUD)
+		while (!(readl(&port_mmio->cmd) | SATA_PORT_CMD_SUD)
 			&& --timeout)
 			;
 		if (timeout <= 0) {
@@ -222,7 +214,7 @@ static int ahci_host_init(struct ahci_uc_priv *probe_ent)
 
 		for (j = 0; j < 100; ++j) {
 			mdelay(10);
-			tmp = readl(&(port_mmio->ssts));
+			tmp = readl(&port_mmio->ssts);
 			if (((tmp & SATA_PORT_SSTS_DET_MASK) == 0x3) ||
 				((tmp & SATA_PORT_SSTS_DET_MASK) == 0x1))
 				break;
@@ -230,7 +222,7 @@ static int ahci_host_init(struct ahci_uc_priv *probe_ent)
 
 		/* Wait for COMINIT bit 26 (DIAG_X) in SERR */
 		timeout = 1000;
-		while (!(readl(&(port_mmio->serr)) | SATA_PORT_SERR_DIAG_X)
+		while (!(readl(&port_mmio->serr) | SATA_PORT_SERR_DIAG_X)
 			&& --timeout)
 			;
 		if (timeout <= 0) {
@@ -243,49 +235,48 @@ static int ahci_host_init(struct ahci_uc_priv *probe_ent)
 		 * register, by writing ones to each implemented\
 		 * bit location.
 		 */
-		tmp = readl(&(port_mmio->serr));
+		tmp = readl(&port_mmio->serr);
 		debug("P#SERR 0x%x\n",
 				tmp);
-		writel(tmp, &(port_mmio->serr));
+		writel(tmp, &port_mmio->serr);
 
 		/* Ack any pending irq events for this port */
-		tmp = readl(&(host_mmio->is));
+		tmp = readl(&host_mmio->is);
 		debug("IS 0x%x\n", tmp);
 		if (tmp)
-			writel(tmp, &(host_mmio->is));
+			writel(tmp, &host_mmio->is);
 
-		writel(1 << i, &(host_mmio->is));
+		writel(1 << i, &host_mmio->is);
 
 		/* set irq mask (enables interrupts) */
-		writel(DEF_PORT_IRQ, &(port_mmio->ie));
+		writel(DEF_PORT_IRQ, &port_mmio->ie);
 
 		/* register linkup ports */
-		tmp = readl(&(port_mmio->ssts));
+		tmp = readl(&port_mmio->ssts);
 		debug("Port %d status: 0x%x\n", i, tmp);
 		if ((tmp & SATA_PORT_SSTS_DET_MASK) == 0x03)
-			probe_ent->link_port_map |= (0x01 << i);
+			uc_priv->link_port_map |= (0x01 << i);
 	}
 
-	tmp = readl(&(host_mmio->ghc));
+	tmp = readl(&host_mmio->ghc);
 	debug("GHC 0x%x\n", tmp);
-	writel(tmp | SATA_HOST_GHC_IE, &(host_mmio->ghc));
-	tmp = readl(&(host_mmio->ghc));
+	writel(tmp | SATA_HOST_GHC_IE, &host_mmio->ghc);
+	tmp = readl(&host_mmio->ghc);
 	debug("GHC 0x%x\n", tmp);
 
 	return 0;
 }
 
-static void ahci_print_info(struct ahci_uc_priv *probe_ent)
+static void ahci_print_info(struct ahci_uc_priv *uc_priv)
 {
-	struct sata_host_regs *host_mmio =
-		(struct sata_host_regs *)probe_ent->mmio_base;
+	struct sata_host_regs *host_mmio = uc_priv->mmio_base;
 	u32 vers, cap, impl, speed;
 	const char *speed_s;
 	const char *scc_s;
 
-	vers = readl(&(host_mmio->vs));
-	cap = probe_ent->cap;
-	impl = probe_ent->port_map;
+	vers = readl(&host_mmio->vs);
+	cap = uc_priv->cap;
+	impl = uc_priv->port_map;
 
 	speed = (cap & SATA_HOST_CAP_ISS_MASK)
 		>> SATA_HOST_CAP_ISS_OFFSET;
@@ -328,43 +319,10 @@ static void ahci_print_info(struct ahci_uc_priv *probe_ent)
 		cap & (1 << 13) ? "part " : "");
 }
 
-static int ahci_init_one(int pdev)
-{
-	int rc;
-	struct ahci_uc_priv *probe_ent = NULL;
-
-	probe_ent = malloc(sizeof(struct ahci_uc_priv));
-	memset(probe_ent, 0, sizeof(struct ahci_uc_priv));
-	probe_ent->dev = pdev;
-
-	probe_ent->host_flags = ATA_FLAG_SATA
-				| ATA_FLAG_NO_LEGACY
-				| ATA_FLAG_MMIO
-				| ATA_FLAG_PIO_DMA
-				| ATA_FLAG_NO_ATAPI;
-
-	probe_ent->mmio_base = (void __iomem *)CONFIG_DWC_AHSATA_BASE_ADDR;
-
-	/* initialize adapter */
-	rc = ahci_host_init(probe_ent);
-	if (rc)
-		goto err_out;
-
-	ahci_print_info(probe_ent);
-
-	/* Save the private struct to block device struct */
-	sata_dev_desc[pdev].priv = (void *)probe_ent;
-
-	return 0;
-
-err_out:
-	return rc;
-}
-
-static int ahci_fill_sg(struct ahci_uc_priv *probe_ent,
-			u8 port, unsigned char *buf, int buf_len)
+static int ahci_fill_sg(struct ahci_uc_priv *uc_priv, u8 port,
+			unsigned char *buf, int buf_len)
 {
-	struct ahci_ioports *pp = &(probe_ent->port[port]);
+	struct ahci_ioports *pp = &uc_priv->port[port];
 	struct ahci_sg *ahci_sg = pp->cmd_tbl_sg;
 	u32 sg_count, max_bytes;
 	int i;
@@ -408,17 +366,16 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 cmd_slot, u32 opts)
 
 #define AHCI_GET_CMD_SLOT(c) ((c) ? ffs(c) : 0)
 
-static int ahci_exec_ata_cmd(struct ahci_uc_priv *probe_ent,
-		u8 port, struct sata_fis_h2d *cfis,
-		u8 *buf, u32 buf_len, s32 is_write)
+static int ahci_exec_ata_cmd(struct ahci_uc_priv *uc_priv, u8 port,
+			     struct sata_fis_h2d *cfis, u8 *buf, u32 buf_len,
+			     s32 is_write)
 {
-	struct ahci_ioports *pp = &(probe_ent->port[port]);
-	struct sata_port_regs *port_mmio =
-			(struct sata_port_regs *)pp->port_mmio;
+	struct ahci_ioports *pp = &uc_priv->port[port];
+	struct sata_port_regs *port_mmio = pp->port_mmio;
 	u32 opts;
 	int sg_count = 0, cmd_slot = 0;
 
-	cmd_slot = AHCI_GET_CMD_SLOT(readl(&(port_mmio->ci)));
+	cmd_slot = AHCI_GET_CMD_SLOT(readl(&port_mmio->ci));
 	if (32 == cmd_slot) {
 		printf("Can't find empty command slot!\n");
 		return 0;
@@ -433,7 +390,7 @@ static int ahci_exec_ata_cmd(struct ahci_uc_priv *probe_ent,
 
 	memcpy((u8 *)(pp->cmd_tbl), cfis, sizeof(struct sata_fis_h2d));
 	if (buf && buf_len)
-		sg_count = ahci_fill_sg(probe_ent, port, buf, buf_len);
+		sg_count = ahci_fill_sg(uc_priv, port, buf, buf_len);
 	opts = (sizeof(struct sata_fis_h2d) >> 2) | (sg_count << 16);
 	if (is_write) {
 		opts |= 0x40;
@@ -442,10 +399,10 @@ static int ahci_exec_ata_cmd(struct ahci_uc_priv *probe_ent,
 	ahci_fill_cmd_slot(pp, cmd_slot, opts);
 
 	flush_cache((int)(pp->cmd_slot), AHCI_PORT_PRIV_DMA_SZ);
-	writel_with_flush(1 << cmd_slot, &(port_mmio->ci));
+	writel_with_flush(1 << cmd_slot, &port_mmio->ci);
 
-	if (waiting_for_cmd_completed((u8 *)&(port_mmio->ci),
-				10000, 0x1 << cmd_slot)) {
+	if (waiting_for_cmd_completed((u8 *)&port_mmio->ci, 10000,
+				      0x1 << cmd_slot)) {
 		printf("timeout exit!\n");
 		return -1;
 	}
@@ -459,10 +416,8 @@ static int ahci_exec_ata_cmd(struct ahci_uc_priv *probe_ent,
 	return buf_len;
 }
 
-static void ahci_set_feature(u8 dev, u8 port)
+static void ahci_set_feature(struct ahci_uc_priv *uc_priv, u8 port)
 {
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
 	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
 	struct sata_fis_h2d *cfis = &h2d;
 
@@ -471,23 +426,21 @@ static void ahci_set_feature(u8 dev, u8 port)
 	cfis->pm_port_c = 1 << 7;
 	cfis->command = ATA_CMD_SET_FEATURES;
 	cfis->features = SETFEATURES_XFER;
-	cfis->sector_count = ffs(probe_ent->udma_mask + 1) + 0x3e;
+	cfis->sector_count = ffs(uc_priv->udma_mask + 1) + 0x3e;
 
-	ahci_exec_ata_cmd(probe_ent, port, cfis, NULL, 0, READ_CMD);
+	ahci_exec_ata_cmd(uc_priv, port, cfis, NULL, 0, READ_CMD);
 }
 
-static int ahci_port_start(struct ahci_uc_priv *probe_ent,
-					u8 port)
+static int ahci_port_start(struct ahci_uc_priv *uc_priv, u8 port)
 {
-	struct ahci_ioports *pp = &(probe_ent->port[port]);
-	struct sata_port_regs *port_mmio =
-		(struct sata_port_regs *)pp->port_mmio;
+	struct ahci_ioports *pp = &uc_priv->port[port];
+	struct sata_port_regs *port_mmio = pp->port_mmio;
 	u32 port_status;
 	u32 mem;
 	int timeout = 10000000;
 
 	debug("Enter start port: %d\n", port);
-	port_status = readl(&(port_mmio->ssts));
+	port_status = readl(&port_mmio->ssts);
 	debug("Port %d status: %x\n", port, port_status);
 	if ((port_status & 0xf) != 0x03) {
 		printf("No Link on this port!\n");
@@ -527,17 +480,17 @@ static int ahci_port_start(struct ahci_uc_priv *probe_ent,
 
 	mem += AHCI_CMD_TBL_HDR;
 
-	writel_with_flush(0x00004444, &(port_mmio->dmacr));
+	writel_with_flush(0x00004444, &port_mmio->dmacr);
 	pp->cmd_tbl_sg = (struct ahci_sg *)mem;
-	writel_with_flush((u32)pp->cmd_slot, &(port_mmio->clb));
-	writel_with_flush(pp->rx_fis, &(port_mmio->fb));
+	writel_with_flush((u32)pp->cmd_slot, &port_mmio->clb);
+	writel_with_flush(pp->rx_fis, &port_mmio->fb);
 
 	/* Enable FRE */
-	writel_with_flush((SATA_PORT_CMD_FRE | readl(&(port_mmio->cmd))),
-			&(port_mmio->cmd));
+	writel_with_flush((SATA_PORT_CMD_FRE | readl(&port_mmio->cmd)),
+			  &port_mmio->cmd);
 
 	/* Wait device ready */
-	while ((readl(&(port_mmio->tfd)) & (SATA_PORT_TFD_STS_ERR |
+	while ((readl(&port_mmio->tfd) & (SATA_PORT_TFD_STS_ERR |
 		SATA_PORT_TFD_STS_DRQ | SATA_PORT_TFD_STS_BSY))
 		&& --timeout)
 		;
@@ -549,79 +502,15 @@ static int ahci_port_start(struct ahci_uc_priv *probe_ent,
 
 	writel_with_flush(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
 			  PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
-			  PORT_CMD_START, &(port_mmio->cmd));
+			  PORT_CMD_START, &port_mmio->cmd);
 
 	debug("Exit start port %d\n", port);
 
 	return 0;
 }
 
-int init_sata(int dev)
-{
-	int i;
-	u32 linkmap;
-	struct ahci_uc_priv *probe_ent = NULL;
-
-#if defined(CONFIG_MX6)
-	if (!is_mx6dq() && !is_mx6dqp())
-		return 1;
-#endif
-	if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
-		printf("The sata index %d is out of ranges\n\r", dev);
-		return -1;
-	}
-
-	ahci_init_one(dev);
-
-	probe_ent = (struct ahci_uc_priv *)sata_dev_desc[dev].priv;
-	linkmap = probe_ent->link_port_map;
-
-	if (0 == linkmap) {
-		printf("No port device detected!\n");
-		return 1;
-	}
-
-	for (i = 0; i < probe_ent->n_ports; i++) {
-		if ((linkmap >> i) && ((linkmap >> i) & 0x01)) {
-			if (ahci_port_start(probe_ent, (u8)i)) {
-				printf("Can not start port %d\n", i);
-				return 1;
-			}
-			probe_ent->hard_port_no = i;
-			break;
-		}
-	}
-
-	return 0;
-}
-
-int reset_sata(int dev)
-{
-	struct ahci_uc_priv *probe_ent;
-	struct sata_host_regs *host_mmio;
-
-	if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
-		printf("The sata index %d is out of ranges\n\r", dev);
-		return -1;
-	}
-
-	probe_ent = (struct ahci_uc_priv *)sata_dev_desc[dev].priv;
-	if (NULL == probe_ent)
-		/* not initialized, so nothing to reset */
-		return 0;
-
-	host_mmio = (struct sata_host_regs *)probe_ent->mmio_base;
-	setbits_le32(&host_mmio->ghc, SATA_HOST_GHC_HR);
-	while (readl(&host_mmio->ghc) & SATA_HOST_GHC_HR)
-		udelay(100);
-
-	return 0;
-}
-
-static void dwc_ahsata_print_info(int dev)
+static void dwc_ahsata_print_info(struct blk_desc *pdev)
 {
-	struct blk_desc *pdev = &(sata_dev_desc[dev]);
-
 	printf("SATA Device Info:\n\r");
 #ifdef CONFIG_SYS_64BIT_LBA
 	printf("S/N: %s\n\rProduct model number: %s\n\r"
@@ -634,13 +523,11 @@ static void dwc_ahsata_print_info(int dev)
 #endif
 }
 
-static void dwc_ahsata_identify(int dev, u16 *id)
+static void dwc_ahsata_identify(struct ahci_uc_priv *uc_priv, u16 *id)
 {
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
 	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
 	struct sata_fis_h2d *cfis = &h2d;
-	u8 port = probe_ent->hard_port_no;
+	u8 port = uc_priv->hard_port_no;
 
 	memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
@@ -648,30 +535,24 @@ static void dwc_ahsata_identify(int dev, u16 *id)
 	cfis->pm_port_c = 0x80; /* is command */
 	cfis->command = ATA_CMD_ID_ATA;
 
-	ahci_exec_ata_cmd(probe_ent, port, cfis,
-			(u8 *)id, ATA_ID_WORDS * 2, READ_CMD);
+	ahci_exec_ata_cmd(uc_priv, port, cfis, (u8 *)id, ATA_ID_WORDS * 2,
+			  READ_CMD);
 	ata_swap_buf_le16(id, ATA_ID_WORDS);
 }
 
-static void dwc_ahsata_xfer_mode(int dev, u16 *id)
+static void dwc_ahsata_xfer_mode(struct ahci_uc_priv *uc_priv, u16 *id)
 {
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
-
-	probe_ent->pio_mask = id[ATA_ID_PIO_MODES];
-	probe_ent->udma_mask = id[ATA_ID_UDMA_MODES];
-	debug("pio %04x, udma %04x\n\r",
-		probe_ent->pio_mask, probe_ent->udma_mask);
+	uc_priv->pio_mask = id[ATA_ID_PIO_MODES];
+	uc_priv->udma_mask = id[ATA_ID_UDMA_MODES];
+	debug("pio %04x, udma %04x\n\r", uc_priv->pio_mask, uc_priv->udma_mask);
 }
 
-static u32 dwc_ahsata_rw_cmd(int dev, u32 start, u32 blkcnt,
-				u8 *buffer, int is_write)
+static u32 dwc_ahsata_rw_cmd(struct ahci_uc_priv *uc_priv, u32 start,
+			     u32 blkcnt, u8 *buffer, int is_write)
 {
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
 	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
 	struct sata_fis_h2d *cfis = &h2d;
-	u8 port = probe_ent->hard_port_no;
+	u8 port = uc_priv->hard_port_no;
 	u32 block;
 
 	block = start;
@@ -689,20 +570,18 @@ static u32 dwc_ahsata_rw_cmd(int dev, u32 start, u32 blkcnt,
 	cfis->lba_low = block & 0xff;
 	cfis->sector_count = (u8)(blkcnt & 0xff);
 
-	if (ahci_exec_ata_cmd(probe_ent, port, cfis,
-			buffer, ATA_SECT_SIZE * blkcnt, is_write) > 0)
+	if (ahci_exec_ata_cmd(uc_priv, port, cfis, buffer,
+			      ATA_SECT_SIZE * blkcnt, is_write) > 0)
 		return blkcnt;
 	else
 		return 0;
 }
 
-void dwc_ahsata_flush_cache(int dev)
+static void dwc_ahsata_flush_cache(struct ahci_uc_priv *uc_priv)
 {
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
 	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
 	struct sata_fis_h2d *cfis = &h2d;
-	u8 port = probe_ent->hard_port_no;
+	u8 port = uc_priv->hard_port_no;
 
 	memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
@@ -710,17 +589,15 @@ void dwc_ahsata_flush_cache(int dev)
 	cfis->pm_port_c = 0x80; /* is command */
 	cfis->command = ATA_CMD_FLUSH;
 
-	ahci_exec_ata_cmd(probe_ent, port, cfis, NULL, 0, 0);
+	ahci_exec_ata_cmd(uc_priv, port, cfis, NULL, 0, 0);
 }
 
-static u32 dwc_ahsata_rw_cmd_ext(int dev, u32 start, lbaint_t blkcnt,
-				u8 *buffer, int is_write)
+static u32 dwc_ahsata_rw_cmd_ext(struct ahci_uc_priv *uc_priv, u32 start,
+				 lbaint_t blkcnt, u8 *buffer, int is_write)
 {
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
 	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
 	struct sata_fis_h2d *cfis = &h2d;
-	u8 port = probe_ent->hard_port_no;
+	u8 port = uc_priv->hard_port_no;
 	u64 block;
 
 	block = (u64)start;
@@ -743,63 +620,18 @@ static u32 dwc_ahsata_rw_cmd_ext(int dev, u32 start, lbaint_t blkcnt,
 	cfis->sector_count_exp = (blkcnt >> 8) & 0xff;
 	cfis->sector_count = blkcnt & 0xff;
 
-	if (ahci_exec_ata_cmd(probe_ent, port, cfis, buffer,
-			ATA_SECT_SIZE * blkcnt, is_write) > 0)
+	if (ahci_exec_ata_cmd(uc_priv, port, cfis, buffer,
+			      ATA_SECT_SIZE * blkcnt, is_write) > 0)
 		return blkcnt;
 	else
 		return 0;
 }
 
-u32 dwc_ahsata_rw_ncq_cmd(int dev, u32 start, lbaint_t blkcnt,
-				u8 *buffer, int is_write)
-{
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
-	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
-	struct sata_fis_h2d *cfis = &h2d;
-	u8 port = probe_ent->hard_port_no;
-	u64 block;
-
-	if (sata_dev_desc[dev].lba48 != 1) {
-		printf("execute FPDMA command on non-LBA48 hard disk\n\r");
-		return -1;
-	}
-
-	block = (u64)start;
-
-	memset(cfis, 0, sizeof(struct sata_fis_h2d));
-
-	cfis->fis_type = SATA_FIS_TYPE_REGISTER_H2D;
-	cfis->pm_port_c = 0x80; /* is command */
-
-	cfis->command = (is_write) ? ATA_CMD_FPDMA_WRITE
-				 : ATA_CMD_FPDMA_READ;
-
-	cfis->lba_high_exp = (block >> 40) & 0xff;
-	cfis->lba_mid_exp = (block >> 32) & 0xff;
-	cfis->lba_low_exp = (block >> 24) & 0xff;
-	cfis->lba_high = (block >> 16) & 0xff;
-	cfis->lba_mid = (block >> 8) & 0xff;
-	cfis->lba_low = block & 0xff;
-
-	cfis->device = ATA_LBA;
-	cfis->features_exp = (blkcnt >> 8) & 0xff;
-	cfis->features = blkcnt & 0xff;
-
-	/* Use the latest queue */
-	ahci_exec_ata_cmd(probe_ent, port, cfis,
-			buffer, ATA_SECT_SIZE * blkcnt, is_write);
-
-	return blkcnt;
-}
-
-void dwc_ahsata_flush_cache_ext(int dev)
+static void dwc_ahsata_flush_cache_ext(struct ahci_uc_priv *uc_priv)
 {
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
 	struct sata_fis_h2d h2d __aligned(ARCH_DMA_MINALIGN);
 	struct sata_fis_h2d *cfis = &h2d;
-	u8 port = probe_ent->hard_port_no;
+	u8 port = uc_priv->hard_port_no;
 
 	memset(cfis, 0, sizeof(struct sata_fis_h2d));
 
@@ -807,24 +639,22 @@ void dwc_ahsata_flush_cache_ext(int dev)
 	cfis->pm_port_c = 0x80; /* is command */
 	cfis->command = ATA_CMD_FLUSH_EXT;
 
-	ahci_exec_ata_cmd(probe_ent, port, cfis, NULL, 0, 0);
+	ahci_exec_ata_cmd(uc_priv, port, cfis, NULL, 0, 0);
 }
 
-static void dwc_ahsata_init_wcache(int dev, u16 *id)
+static void dwc_ahsata_init_wcache(struct ahci_uc_priv *uc_priv, u16 *id)
 {
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
-
 	if (ata_id_has_wcache(id) && ata_id_wcache_enabled(id))
-		probe_ent->flags |= SATA_FLAG_WCACHE;
+		uc_priv->flags |= SATA_FLAG_WCACHE;
 	if (ata_id_has_flush(id))
-		probe_ent->flags |= SATA_FLAG_FLUSH;
+		uc_priv->flags |= SATA_FLAG_FLUSH;
 	if (ata_id_has_flush_ext(id))
-		probe_ent->flags |= SATA_FLAG_FLUSH_EXT;
+		uc_priv->flags |= SATA_FLAG_FLUSH_EXT;
 }
 
-u32 ata_low_level_rw_lba48(int dev, u32 blknr, lbaint_t blkcnt,
-				const void *buffer, int is_write)
+static u32 ata_low_level_rw_lba48(struct ahci_uc_priv *uc_priv, u32 blknr,
+				  lbaint_t blkcnt, const void *buffer,
+				  int is_write)
 {
 	u32 start, blks;
 	u8 *addr;
@@ -838,15 +668,16 @@ u32 ata_low_level_rw_lba48(int dev, u32 blknr, lbaint_t blkcnt,
 
 	do {
 		if (blks > max_blks) {
-			if (max_blks != dwc_ahsata_rw_cmd_ext(dev, start,
-						max_blks, addr, is_write))
+			if (max_blks != dwc_ahsata_rw_cmd_ext(uc_priv, start,
+							      max_blks, addr,
+							      is_write))
 				return 0;
 			start += max_blks;
 			blks -= max_blks;
 			addr += ATA_SECT_SIZE * max_blks;
 		} else {
-			if (blks != dwc_ahsata_rw_cmd_ext(dev, start,
-						blks, addr, is_write))
+			if (blks != dwc_ahsata_rw_cmd_ext(uc_priv, start, blks,
+							  addr, is_write))
 				return 0;
 			start += blks;
 			blks = 0;
@@ -857,8 +688,9 @@ u32 ata_low_level_rw_lba48(int dev, u32 blknr, lbaint_t blkcnt,
 	return blkcnt;
 }
 
-u32 ata_low_level_rw_lba28(int dev, u32 blknr, lbaint_t blkcnt,
-				const void *buffer, int is_write)
+static u32 ata_low_level_rw_lba28(struct ahci_uc_priv *uc_priv, u32 blknr,
+				  lbaint_t blkcnt, const void *buffer,
+				  int is_write)
 {
 	u32 start, blks;
 	u8 *addr;
@@ -871,15 +703,16 @@ u32 ata_low_level_rw_lba28(int dev, u32 blknr, lbaint_t blkcnt,
 	max_blks = ATA_MAX_SECTORS;
 	do {
 		if (blks > max_blks) {
-			if (max_blks != dwc_ahsata_rw_cmd(dev, start,
-						max_blks, addr, is_write))
+			if (max_blks != dwc_ahsata_rw_cmd(uc_priv, start,
+							  max_blks, addr,
+							  is_write))
 				return 0;
 			start += max_blks;
 			blks -= max_blks;
 			addr += ATA_SECT_SIZE * max_blks;
 		} else {
-			if (blks != dwc_ahsata_rw_cmd(dev, start,
-						blks, addr, is_write))
+			if (blks != dwc_ahsata_rw_cmd(uc_priv, start, blks,
+						      addr, is_write))
 				return 0;
 			start += blks;
 			blks = 0;
@@ -890,84 +723,44 @@ u32 ata_low_level_rw_lba28(int dev, u32 blknr, lbaint_t blkcnt,
 	return blkcnt;
 }
 
-int sata_port_status(int dev, int port)
+static int dwc_ahci_start_ports(struct ahci_uc_priv *uc_priv)
 {
-	struct sata_port_regs *port_mmio;
-	struct ahci_uc_priv *probe_ent = NULL;
-
-	if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1))
-		return -EINVAL;
-
-	if (sata_dev_desc[dev].priv == NULL)
-		return -ENODEV;
+	u32 linkmap;
+	int i;
 
-	probe_ent = (struct ahci_uc_priv *)sata_dev_desc[dev].priv;
-	port_mmio = (struct sata_port_regs *)probe_ent->port[port].port_mmio;
+	linkmap = uc_priv->link_port_map;
 
-	return readl(&(port_mmio->ssts)) & SATA_PORT_SSTS_DET_MASK;
-}
+	if (0 == linkmap) {
+		printf("No port device detected!\n");
+		return -ENXIO;
+	}
 
-/*
- * SATA interface between low level driver and command layer
- */
-ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
-{
-	u32 rc;
+	for (i = 0; i < uc_priv->n_ports; i++) {
+		if ((linkmap >> i) && ((linkmap >> i) & 0x01)) {
+			if (ahci_port_start(uc_priv, (u8)i)) {
+				printf("Can not start port %d\n", i);
+				return 1;
+			}
+			uc_priv->hard_port_no = i;
+			break;
+		}
+	}
 
-	if (sata_dev_desc[dev].lba48)
-		rc = ata_low_level_rw_lba48(dev, blknr, blkcnt,
-						buffer, READ_CMD);
-	else
-		rc = ata_low_level_rw_lba28(dev, blknr, blkcnt,
-						buffer, READ_CMD);
-	return rc;
+	return 0;
 }
 
-ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
-{
-	u32 rc;
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
-	u32 flags = probe_ent->flags;
-
-	if (sata_dev_desc[dev].lba48) {
-		rc = ata_low_level_rw_lba48(dev, blknr, blkcnt,
-						buffer, WRITE_CMD);
-		if ((flags & SATA_FLAG_WCACHE) &&
-			(flags & SATA_FLAG_FLUSH_EXT))
-			dwc_ahsata_flush_cache_ext(dev);
-	} else {
-		rc = ata_low_level_rw_lba28(dev, blknr, blkcnt,
-						buffer, WRITE_CMD);
-		if ((flags & SATA_FLAG_WCACHE) &&
-			(flags & SATA_FLAG_FLUSH))
-			dwc_ahsata_flush_cache(dev);
-	}
-	return rc;
-}
-
-int scan_sata(int dev)
+static int dwc_ahsata_scan_common(struct ahci_uc_priv *uc_priv,
+				  struct blk_desc *pdev)
 {
 	u8 serial[ATA_ID_SERNO_LEN + 1] = { 0 };
 	u8 firmware[ATA_ID_FW_REV_LEN + 1] = { 0 };
 	u8 product[ATA_ID_PROD_LEN + 1] = { 0 };
-	u16 *id;
 	u64 n_sectors;
-	struct ahci_uc_priv *probe_ent =
-		(struct ahci_uc_priv *)sata_dev_desc[dev].priv;
-	u8 port = probe_ent->hard_port_no;
-	struct blk_desc *pdev = &(sata_dev_desc[dev]);
-
-	id = (u16 *)memalign(ARCH_DMA_MINALIGN,
-				roundup(ARCH_DMA_MINALIGN,
-					(ATA_ID_WORDS * 2)));
-	if (!id) {
-		printf("id malloc failed\n\r");
-		return -1;
-	}
+	u8 port = uc_priv->hard_port_no;
+	ALLOC_CACHE_ALIGN_BUFFER(u16, id, ATA_ID_WORDS);
 
 	/* Identify device to get information */
-	dwc_ahsata_identify(dev, id);
+	dwc_ahsata_identify(uc_priv, id);
 
 	/* Serial number */
 	ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
@@ -987,7 +780,7 @@ int scan_sata(int dev)
 
 	pdev->type = DEV_TYPE_HARDDISK;
 	pdev->blksz = ATA_SECT_SIZE;
-	pdev->lun = 0 ;
+	pdev->lun = 0;
 
 	/* Check if support LBA48 */
 	if (ata_id_has_lba48(id)) {
@@ -996,23 +789,291 @@ int scan_sata(int dev)
 	}
 
 	/* Get the NCQ queue depth from device */
-	probe_ent->flags &= (~SATA_FLAG_Q_DEP_MASK);
-	probe_ent->flags |= ata_id_queue_depth(id);
+	uc_priv->flags &= (~SATA_FLAG_Q_DEP_MASK);
+	uc_priv->flags |= ata_id_queue_depth(id);
 
 	/* Get the xfer mode from device */
-	dwc_ahsata_xfer_mode(dev, id);
+	dwc_ahsata_xfer_mode(uc_priv, id);
 
 	/* Get the write cache status from device */
-	dwc_ahsata_init_wcache(dev, id);
+	dwc_ahsata_init_wcache(uc_priv, id);
 
 	/* Set the xfer mode to highest speed */
-	ahci_set_feature(dev, port);
+	ahci_set_feature(uc_priv, port);
+
+	dwc_ahsata_print_info(pdev);
+
+	return 0;
+}
+
+/*
+ * SATA interface between low level driver and command layer
+ */
+static ulong sata_read_common(struct ahci_uc_priv *uc_priv,
+			      struct blk_desc *desc, ulong blknr,
+			      lbaint_t blkcnt, void *buffer)
+{
+	u32 rc;
+
+	if (desc->lba48)
+		rc = ata_low_level_rw_lba48(uc_priv, blknr, blkcnt, buffer,
+					    READ_CMD);
+	else
+		rc = ata_low_level_rw_lba28(uc_priv, blknr, blkcnt, buffer,
+					    READ_CMD);
+
+	return rc;
+}
+
+static ulong sata_write_common(struct ahci_uc_priv *uc_priv,
+			       struct blk_desc *desc, ulong blknr,
+			       lbaint_t blkcnt, const void *buffer)
+{
+	u32 rc;
+	u32 flags = uc_priv->flags;
+
+	if (desc->lba48) {
+		rc = ata_low_level_rw_lba48(uc_priv, blknr, blkcnt, buffer,
+					    WRITE_CMD);
+		if ((flags & SATA_FLAG_WCACHE) && (flags & SATA_FLAG_FLUSH_EXT))
+			dwc_ahsata_flush_cache_ext(uc_priv);
+	} else {
+		rc = ata_low_level_rw_lba28(uc_priv, blknr, blkcnt, buffer,
+					    WRITE_CMD);
+		if ((flags & SATA_FLAG_WCACHE) && (flags & SATA_FLAG_FLUSH))
+			dwc_ahsata_flush_cache(uc_priv);
+	}
+
+	return rc;
+}
+
+#if !CONFIG_IS_ENABLED(AHCI)
+static int ahci_init_one(int pdev)
+{
+	int rc;
+	struct ahci_uc_priv *uc_priv = NULL;
+
+	uc_priv = malloc(sizeof(struct ahci_uc_priv));
+	memset(uc_priv, 0, sizeof(struct ahci_uc_priv));
+	uc_priv->dev = pdev;
+
+	uc_priv->host_flags = ATA_FLAG_SATA
+				| ATA_FLAG_NO_LEGACY
+				| ATA_FLAG_MMIO
+				| ATA_FLAG_PIO_DMA
+				| ATA_FLAG_NO_ATAPI;
+
+	uc_priv->mmio_base = (void __iomem *)CONFIG_DWC_AHSATA_BASE_ADDR;
+
+	/* initialize adapter */
+	rc = ahci_host_init(uc_priv);
+	if (rc)
+		goto err_out;
+
+	ahci_print_info(uc_priv);
+
+	/* Save the uc_private struct to block device struct */
+	sata_dev_desc[pdev].priv = uc_priv;
+
+	return 0;
+
+err_out:
+	return rc;
+}
+
+int init_sata(int dev)
+{
+	struct ahci_uc_priv *uc_priv = NULL;
+
+#if defined(CONFIG_MX6)
+	if (!is_mx6dq() && !is_mx6dqp())
+		return 1;
+#endif
+	if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
+		printf("The sata index %d is out of ranges\n\r", dev);
+		return -1;
+	}
+
+	ahci_init_one(dev);
+
+	uc_priv = sata_dev_desc[dev].priv;
+
+	return dwc_ahci_start_ports(uc_priv) ? 1 : 0;
+}
+
+int reset_sata(int dev)
+{
+	struct ahci_uc_priv *uc_priv;
+	struct sata_host_regs *host_mmio;
 
-	free((void *)id);
+	if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
+		printf("The sata index %d is out of ranges\n\r", dev);
+		return -1;
+	}
 
-	dwc_ahsata_print_info(dev);
+	uc_priv = sata_dev_desc[dev].priv;
+	if (NULL == uc_priv)
+		/* not initialized, so nothing to reset */
+		return 0;
 
-	is_ready = 1;
+	host_mmio = uc_priv->mmio_base;
+	setbits_le32(&host_mmio->ghc, SATA_HOST_GHC_HR);
+	while (readl(&host_mmio->ghc) & SATA_HOST_GHC_HR)
+		udelay(100);
 
 	return 0;
 }
+
+int sata_port_status(int dev, int port)
+{
+	struct sata_port_regs *port_mmio;
+	struct ahci_uc_priv *uc_priv = NULL;
+
+	if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1))
+		return -EINVAL;
+
+	if (sata_dev_desc[dev].priv == NULL)
+		return -ENODEV;
+
+	uc_priv = sata_dev_desc[dev].priv;
+	port_mmio = uc_priv->port[port].port_mmio;
+
+	return readl(&port_mmio->ssts) & SATA_PORT_SSTS_DET_MASK;
+}
+
+/*
+ * SATA interface between low level driver and command layer
+ */
+ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+	struct ahci_uc_priv *uc_priv = sata_dev_desc[dev].priv;
+
+	return sata_read_common(uc_priv, &sata_dev_desc[dev], blknr, blkcnt,
+				buffer);
+}
+
+ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
+{
+	struct ahci_uc_priv *uc_priv = sata_dev_desc[dev].priv;
+
+	return sata_write_common(uc_priv, &sata_dev_desc[dev], blknr, blkcnt,
+				 buffer);
+}
+
+int scan_sata(int dev)
+{
+	struct ahci_uc_priv *uc_priv = sata_dev_desc[dev].priv;
+	struct blk_desc *pdev = &sata_dev_desc[dev];
+
+	return dwc_ahsata_scan_common(uc_priv, pdev);
+}
+#endif /* CONFIG_IS_ENABLED(AHCI) */
+
+#if CONFIG_IS_ENABLED(AHCI)
+
+int dwc_ahsata_port_status(struct udevice *dev, int port)
+{
+	struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct sata_port_regs *port_mmio;
+
+	port_mmio = uc_priv->port[port].port_mmio;
+	return readl(&port_mmio->ssts) & SATA_PORT_SSTS_DET_MASK ? 0 : -ENXIO;
+}
+
+int dwc_ahsata_bus_reset(struct udevice *dev)
+{
+	struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct sata_host_regs *host_mmio = uc_priv->mmio_base;
+
+	setbits_le32(&host_mmio->ghc, SATA_HOST_GHC_HR);
+	while (readl(&host_mmio->ghc) & SATA_HOST_GHC_HR)
+		udelay(100);
+
+	return 0;
+}
+
+int dwc_ahsata_scan(struct udevice *dev)
+{
+	struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct blk_desc *desc;
+	struct udevice *blk;
+	int ret;
+
+	/*
+	* Create only one block device and do detection
+	* to make sure that there won't be a lot of
+	* block devices created
+	*/
+	device_find_first_child(dev, &blk);
+	if (!blk) {
+		ret = blk_create_devicef(dev, "dwc_ahsata_blk", "blk",
+					 IF_TYPE_SATA, -1, 512, 0, &blk);
+		if (ret) {
+			debug("Can't create device\n");
+			return ret;
+		}
+	}
+
+	desc = dev_get_uclass_platdata(blk);
+	ret = dwc_ahsata_scan_common(uc_priv, desc);
+	if (ret) {
+		debug("%s: Failed to scan bus\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+int dwc_ahsata_probe(struct udevice *dev)
+{
+	struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev);
+	int ret;
+
+	uc_priv->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+			ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NO_ATAPI;
+	uc_priv->mmio_base = (void __iomem *)dev_read_addr(dev);
+
+	/* initialize adapter */
+	ret = ahci_host_init(uc_priv);
+	if (ret)
+		return ret;
+
+	ahci_print_info(uc_priv);
+
+	return dwc_ahci_start_ports(uc_priv);
+}
+
+static ulong dwc_ahsata_read(struct udevice *blk, lbaint_t blknr,
+			     lbaint_t blkcnt, void *buffer)
+{
+	struct blk_desc *desc = dev_get_uclass_platdata(blk);
+	struct udevice *dev = dev_get_parent(blk);
+	struct ahci_uc_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+	return sata_read_common(uc_priv, desc, blknr, blkcnt, buffer);
+}
+
+static ulong dwc_ahsata_write(struct udevice *blk, lbaint_t blknr,
+			      lbaint_t blkcnt, const void *buffer)
+{
+	struct blk_desc *desc = dev_get_uclass_platdata(blk);
+	struct udevice *dev = dev_get_parent(blk);
+	struct ahci_uc_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(dev);
+	return sata_write_common(uc_priv, desc, blknr, blkcnt, buffer);
+}
+
+static const struct blk_ops dwc_ahsata_blk_ops = {
+	.read	= dwc_ahsata_read,
+	.write	= dwc_ahsata_write,
+};
+
+U_BOOT_DRIVER(dwc_ahsata_blk) = {
+	.name		= "dwc_ahsata_blk",
+	.id		= UCLASS_BLK,
+	.ops		= &dwc_ahsata_blk_ops,
+};
+
+#endif
diff --git a/drivers/ata/dwc_ahsata.h b/drivers/ata/dwc_ahsata_priv.h
similarity index 99%
rename from drivers/ata/dwc_ahsata.h
rename to drivers/ata/dwc_ahsata_priv.h
index caa2e501f9625f771b1315c4550aecfec171e95f..6089c0b268ded688824dcab616553c38ce67dc03 100644
--- a/drivers/ata/dwc_ahsata.h
+++ b/drivers/ata/dwc_ahsata_priv.h
@@ -5,8 +5,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#ifndef __FSL_SATA_H__
-#define __FSL_SATA_H__
+#ifndef __DWC_AHSATA_PRIV_H__
+#define __DWC_AHSATA_PRIV_H__
 
 #define DWC_AHSATA_MAX_CMD_SLOTS	32
 
@@ -317,4 +317,4 @@
 #define READ_CMD	0
 #define WRITE_CMD	1
 
-#endif /* __FSL_SATA_H__ */
+#endif /* __DWC_AHSATA_H__ */
diff --git a/drivers/ata/sata.c b/drivers/ata/sata.c
index 42ff5c7755a64d466965c81b75632a88fdb6f0f9..b3ebc05ead36bc1bf4412fc17b7a468f3e0d22ea 100644
--- a/drivers/ata/sata.c
+++ b/drivers/ata/sata.c
@@ -11,17 +11,52 @@
  */
 
 #include <common.h>
+#include <ahci.h>
 #include <dm.h>
 #include <sata.h>
 
+#ifndef CONFIG_AHCI
 struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
+#endif
+
+int sata_reset(struct udevice *dev)
+{
+	struct ahci_ops *ops = ahci_get_ops(dev);
+
+	if (!ops->reset)
+		return -ENOSYS;
+
+	return ops->reset(dev);
+}
+
+int sata_dm_port_status(struct udevice *dev, int port)
+{
+	struct ahci_ops *ops = ahci_get_ops(dev);
+
+	if (!ops->port_status)
+		return -ENOSYS;
 
+	return ops->port_status(dev, port);
+}
+
+int sata_scan(struct udevice *dev)
+{
+	struct ahci_ops *ops = ahci_get_ops(dev);
+
+	if (!ops->scan)
+		return -ENOSYS;
+
+	return ops->scan(dev);
+}
+
+#ifndef CONFIG_AHCI
 #ifdef CONFIG_PARTITIONS
 struct blk_desc *sata_get_dev(int dev)
 {
 	return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL;
 }
 #endif
+#endif
 
 #ifdef CONFIG_BLK
 static unsigned long sata_bread(struct udevice *dev, lbaint_t start,
@@ -49,6 +84,7 @@ static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start,
 }
 #endif
 
+#ifndef CONFIG_AHCI
 int __sata_initialize(void)
 {
 	int rc, ret = -1;
@@ -95,6 +131,7 @@ __weak int __sata_stop(void)
 	return err;
 }
 int sata_stop(void) __attribute__((weak, alias("__sata_stop")));
+#endif
 
 #ifdef CONFIG_BLK
 static const struct blk_ops sata_blk_ops = {
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index a3737badec6df61ca318cfee975f6f95a6535191..3aec569d124be830afa3100f1eff6e8bb2d0e280 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -57,6 +57,11 @@ static enum uclass_id if_type_to_uclass_id(enum if_type if_type)
 	return if_type_uclass_id[if_type];
 }
 
+const char *blk_get_if_type_name(enum if_type if_type)
+{
+	return if_typename_str[if_type];
+}
+
 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
 {
 	struct blk_desc *desc;
@@ -591,7 +596,7 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name,
 	}
 	device_set_name_alloced(*devp);
 
-	return ret;
+	return 0;
 }
 
 int blk_unbind_all(int if_type)
diff --git a/drivers/block/blk_legacy.c b/drivers/block/blk_legacy.c
index 7b90a8a6e18ebc3010bf043b5d71c4966f2fba75..981872ecb35cd516087effc09ffd6b30e21886cd 100644
--- a/drivers/block/blk_legacy.c
+++ b/drivers/block/blk_legacy.c
@@ -38,6 +38,13 @@ static struct blk_driver *blk_driver_lookup_typename(const char *if_typename)
 	return NULL;
 }
 
+const char *blk_get_if_type_name(enum if_type if_type)
+{
+	struct blk_driver *drv = blk_driver_lookup_type(if_type);
+
+	return drv ? drv->if_typename : NULL;
+}
+
 /**
  * get_desc() - Get the block device descriptor for the given device number
  *
diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c
index 2148469abc10e1e13468bc0ed58c695446d20c08..a69937e63c15d6db1a96baa6b28715c7f3ddb51a 100644
--- a/drivers/core/syscon-uclass.c
+++ b/drivers/core/syscon-uclass.c
@@ -104,5 +104,8 @@ static const struct udevice_id generic_syscon_ids[] = {
 U_BOOT_DRIVER(generic_syscon) = {
 	.name	= "syscon",
 	.id	= UCLASS_SYSCON,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.bind           = dm_scan_fdt_dev,
+#endif
 	.of_match = generic_syscon_ids,
 };
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 51a87cdd77dc1e3c2419ff7960d622ae6ebeaa50..56c352e72a0210ea417a8348581af971c9ba529b 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -20,16 +20,6 @@ config DM_MMC
 	  appear as block devices in U-Boot and can support filesystems such
 	  as EXT4 and FAT.
 
-config DM_MMC_OPS
-	bool "Support MMC controller operations using Driver Model"
-	depends on DM_MMC
-	default y if DM_MMC
-	help
-	  Driver model provides a means of supporting device operations. This
-	  option moves MMC operations under the control of driver model. The
-	  option will be removed as soon as all DM_MMC drivers use it, as it
-	  will the only supported behaviour.
-
 config SPL_DM_MMC
 	bool "Enable MMC controllers using Driver Model in SPL"
 	depends on SPL_DM && DM_MMC
@@ -41,16 +31,6 @@ config SPL_DM_MMC
 	  appear as block devices in U-Boot and can support filesystems such
 	  as EXT4 and FAT.
 
-config SPL_DM_MMC_OPS
-	bool "Support MMC controller operations using Driver Model in SPL"
-	depends on SPL_DM && DM_MMC_OPS
-	default y
-	help
-	  Driver model provides a means of supporting device operations. This
-	  option moves MMC operations under the control of driver model. The
-	  option will be removed as soon as all DM_MMC drivers use it, as it
-	  will the only supported behaviour.
-
 if MMC
 
 config SPL_MMC_TINY
@@ -124,7 +104,7 @@ config MMC_DW_SOCFPGA
 
 config MMC_MESON_GX
 	bool "Meson GX EMMC controller support"
-	depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_MESON
+	depends on DM_MMC && BLK && ARCH_MESON
 	help
 	 Support for EMMC host controller on Meson GX ARM SoCs platform (S905)
 
@@ -155,7 +135,7 @@ config MMC_PCI
 
 config MMC_OMAP_HS
 	bool "TI OMAP High Speed Multimedia Card Interface support"
-	select DM_MMC_OPS if DM_MMC
+	select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR
 	help
 	  This selects the TI OMAP High Speed Multimedia card Interface.
 	  If you have an omap2plus board with a Multimedia Card slot,
@@ -184,7 +164,7 @@ config SH_SDHI
 config MMC_UNIPHIER
 	bool "UniPhier SD/MMC Host Controller support"
 	depends on ARCH_UNIPHIER
-	depends on BLK && DM_MMC_OPS
+	depends on BLK && DM_MMC
 	depends on OF_CONTROL
 	help
 	  This selects support for the SD/MMC Host Controller on UniPhier SoCs.
@@ -192,7 +172,7 @@ config MMC_UNIPHIER
 config MMC_SANDBOX
 	bool "Sandbox MMC support"
 	depends on SANDBOX
-	depends on BLK && DM_MMC_OPS && OF_CONTROL
+	depends on BLK && DM_MMC && OF_CONTROL
 	help
 	  This select a dummy sandbox MMC driver. At present this does nothing
 	  other than allow sandbox to be build with MMC support. This
@@ -227,7 +207,7 @@ config MMC_SDHCI_SDMA
 config MMC_SDHCI_ATMEL
 	bool "Atmel SDHCI controller support"
 	depends on ARCH_AT91
-	depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91
+	depends on DM_MMC && BLK && ARCH_AT91
 	depends on MMC_SDHCI
 	help
 	  This enables support for the Atmel SDHCI controller, which supports
@@ -251,7 +231,7 @@ config MMC_SDHCI_BCM2835
 
 config MMC_SDHCI_CADENCE
 	bool "SDHCI support for the Cadence SD/SDIO/eMMC controller"
-	depends on BLK && DM_MMC_OPS
+	depends on BLK && DM_MMC
 	depends on MMC_SDHCI
 	depends on OF_CONTROL
 	help
@@ -273,7 +253,7 @@ config MMC_SDHCI_KONA
 
 config MMC_SDHCI_MSM
 	bool "Qualcomm SDHCI controller"
-	depends on BLK && DM_MMC_OPS
+	depends on BLK && DM_MMC
 	depends on MMC_SDHCI
 	help
 	  Enables support for SDHCI 2.0 controller present on some Qualcomm
@@ -303,7 +283,7 @@ config MMC_SDHCI_PIC32
 config MMC_SDHCI_ROCKCHIP
 	bool "Arasan SDHCI controller for Rockchip support"
 	depends on ARCH_ROCKCHIP
-	depends on DM_MMC && BLK && DM_MMC_OPS
+	depends on DM_MMC && BLK
 	depends on MMC_SDHCI
 	help
 	  Support for Arasan SDHCI host controller on Rockchip ARM SoCs platform
@@ -376,7 +356,7 @@ config MMC_SDHCI_TEGRA
 config MMC_SDHCI_ZYNQ
 	bool "Arasan SDHCI controller support"
 	depends on ARCH_ZYNQ || ARCH_ZYNQMP
-	depends on DM_MMC && OF_CONTROL && BLK && DM_MMC_OPS
+	depends on DM_MMC && OF_CONTROL && BLK
 	depends on MMC_SDHCI
 	help
 	  Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs platform
@@ -391,7 +371,7 @@ config MMC_SUNXI
 
 config GENERIC_ATMEL_MCI
 	bool "Atmel Multimedia Card Interface support"
-	depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91
+	depends on DM_MMC && BLK && ARCH_AT91
 	help
 	  This enables support for Atmel High Speed Multimedia Card Interface
 	  (HSMCI), which supports the MultiMedia Card (MMC) Specification V4.3,
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 700f7644329bc7e72019c315ce5699a799f17edd..23f642980bfa97ee41910c7ad0b1134eb8bc72e1 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -184,7 +184,7 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host,
 	return mode;
 }
 
-#ifdef CONFIG_DM_MMC_OPS
+#ifdef CONFIG_DM_MMC
 static int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 		   struct mmc_data *data)
 {
@@ -383,7 +383,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 	return 0;
 }
 
-#ifdef CONFIG_DM_MMC_OPS
+#ifdef CONFIG_DM_MMC
 static int dwmci_set_ios(struct udevice *dev)
 {
 	struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -466,7 +466,7 @@ static int dwmci_init(struct mmc *mmc)
 	return 0;
 }
 
-#ifdef CONFIG_DM_MMC_OPS
+#ifdef CONFIG_DM_MMC
 int dwmci_probe(struct udevice *dev)
 {
 	struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -491,7 +491,7 @@ void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host,
 		u32 max_clk, u32 min_clk)
 {
 	cfg->name = host->name;
-#ifndef CONFIG_DM_MMC_OPS
+#ifndef CONFIG_DM_MMC
 	cfg->ops = &dwmci_ops;
 #endif
 	cfg->f_min = min_clk;
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index b69c9b71e4c833c3bedb2cea8b399e7593dc9352..cc188c4260737c4fa29a399f410ba939ab09b67f 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -81,6 +81,11 @@ struct fsl_esdhc {
 	uint    scr;		/* eSDHC control register */
 };
 
+struct fsl_esdhc_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
 /**
  * struct fsl_esdhc_priv
  *
@@ -101,8 +106,9 @@ struct fsl_esdhc_priv {
 	struct fsl_esdhc *esdhc_regs;
 	unsigned int sdhc_clk;
 	unsigned int bus_width;
-	struct mmc_config cfg;
+#if !CONFIG_IS_ENABLED(BLK)
 	struct mmc *mmc;
+#endif
 	struct udevice *dev;
 	int non_removable;
 	int wp_enable;
@@ -156,10 +162,9 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
 /*
  * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
  */
-static void
-esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
+static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv,
+				 struct mmc_data *data)
 {
-	struct fsl_esdhc_priv *priv = mmc->priv;
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 	uint blocks;
 	char *buffer;
@@ -218,10 +223,10 @@ esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
 }
 #endif
 
-static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
+static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
+			    struct mmc_data *data)
 {
 	int timeout;
-	struct fsl_esdhc_priv *priv = mmc->priv;
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 #if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
 	dma_addr_t addr;
@@ -349,13 +354,12 @@ static void check_and_invalidate_dcache_range
  * Sends a command out on the bus.  Takes the mmc pointer,
  * a command pointer, and an optional data pointer.
  */
-static int
-esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
+				 struct mmc_cmd *cmd, struct mmc_data *data)
 {
 	int	err = 0;
 	uint	xfertyp;
 	uint	irqstat;
-	struct fsl_esdhc_priv *priv = mmc->priv;
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
@@ -384,7 +388,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 
 	/* Set up for a data transfer if we have one */
 	if (data) {
-		err = esdhc_setup_data(mmc, data);
+		err = esdhc_setup_data(priv, mmc, data);
 		if(err)
 			return err;
 
@@ -470,7 +474,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 	/* Wait until all of the blocks are transferred */
 	if (data) {
 #ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
-		esdhc_pio_read_write(mmc, data);
+		esdhc_pio_read_write(priv, data);
 #else
 		do {
 			irqstat = esdhc_read32(&regs->irqstat);
@@ -522,7 +526,7 @@ out:
 	return err;
 }
 
-static void set_sysctl(struct mmc *mmc, uint clock)
+static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
 {
 	int div = 1;
 #ifdef ARCH_MXC
@@ -531,7 +535,6 @@ static void set_sysctl(struct mmc *mmc, uint clock)
 	int pre_div = 2;
 #endif
 	int ddr_pre_div = mmc->ddr_mode ? 2 : 1;
-	struct fsl_esdhc_priv *priv = mmc->priv;
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 	int sdhc_clk = priv->sdhc_clk;
 	uint clk;
@@ -569,9 +572,8 @@ static void set_sysctl(struct mmc *mmc, uint clock)
 }
 
 #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
-static void esdhc_clock_control(struct mmc *mmc, bool enable)
+static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
 {
-	struct fsl_esdhc_priv *priv = mmc->priv;
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 	u32 value;
 	u32 time_out;
@@ -598,19 +600,18 @@ static void esdhc_clock_control(struct mmc *mmc, bool enable)
 }
 #endif
 
-static int esdhc_set_ios(struct mmc *mmc)
+static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
 {
-	struct fsl_esdhc_priv *priv = mmc->priv;
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 
 #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
 	/* Select to use peripheral clock */
-	esdhc_clock_control(mmc, false);
+	esdhc_clock_control(priv, false);
 	esdhc_setbits32(&regs->scr, ESDHCCTL_PCS);
-	esdhc_clock_control(mmc, true);
+	esdhc_clock_control(priv, true);
 #endif
 	/* Set the clock speed */
-	set_sysctl(mmc, mmc->clock);
+	set_sysctl(priv, mmc, mmc->clock);
 
 	/* Set the bus width */
 	esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
@@ -623,18 +624,20 @@ static int esdhc_set_ios(struct mmc *mmc)
 	return 0;
 }
 
-static int esdhc_init(struct mmc *mmc)
+static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
 {
-	struct fsl_esdhc_priv *priv = mmc->priv;
 	struct fsl_esdhc *regs = priv->esdhc_regs;
-	int timeout = 1000;
+	ulong start;
 
 	/* Reset the entire host controller */
 	esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
 
 	/* Wait until the controller is available */
-	while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
-		udelay(1000);
+	start = get_timer(0);
+	while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) {
+		if (get_timer(start) > 1000)
+			return -ETIMEDOUT;
+	}
 
 #if defined(CONFIG_FSL_USDHC)
 	/* RSTA doesn't reset MMC_BOOT register, so manually reset it */
@@ -679,9 +682,8 @@ static int esdhc_init(struct mmc *mmc)
 	return 0;
 }
 
-static int esdhc_getcd(struct mmc *mmc)
+static int esdhc_getcd_common(struct fsl_esdhc_priv *priv)
 {
-	struct fsl_esdhc_priv *priv = mmc->priv;
 	struct fsl_esdhc *regs = priv->esdhc_regs;
 	int timeout = 1000;
 
@@ -690,7 +692,7 @@ static int esdhc_getcd(struct mmc *mmc)
 		return 1;
 #endif
 
-#ifdef CONFIG_DM_MMC
+#if CONFIG_IS_ENABLED(DM_MMC)
 	if (priv->non_removable)
 		return 1;
 #ifdef CONFIG_DM_GPIO
@@ -705,32 +707,70 @@ static int esdhc_getcd(struct mmc *mmc)
 	return timeout > 0;
 }
 
-static void esdhc_reset(struct fsl_esdhc *regs)
+static int esdhc_reset(struct fsl_esdhc *regs)
 {
-	unsigned long timeout = 100; /* wait max 100 ms */
+	ulong start;
 
 	/* reset the controller */
 	esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
 
 	/* hardware clears the bit when it is done */
-	while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
-		udelay(1000);
-	if (!timeout)
-		printf("MMC/SD: Reset never completed.\n");
+	start = get_timer(0);
+	while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) {
+		if (get_timer(start) > 100) {
+			printf("MMC/SD: Reset never completed.\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+#if !CONFIG_IS_ENABLED(DM_MMC)
+static int esdhc_getcd(struct mmc *mmc)
+{
+	struct fsl_esdhc_priv *priv = mmc->priv;
+
+	return esdhc_getcd_common(priv);
+}
+
+static int esdhc_init(struct mmc *mmc)
+{
+	struct fsl_esdhc_priv *priv = mmc->priv;
+
+	return esdhc_init_common(priv, mmc);
+}
+
+static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+			  struct mmc_data *data)
+{
+	struct fsl_esdhc_priv *priv = mmc->priv;
+
+	return esdhc_send_cmd_common(priv, mmc, cmd, data);
+}
+
+static int esdhc_set_ios(struct mmc *mmc)
+{
+	struct fsl_esdhc_priv *priv = mmc->priv;
+
+	return esdhc_set_ios_common(priv, mmc);
 }
 
 static const struct mmc_ops esdhc_ops = {
+	.getcd		= esdhc_getcd,
+	.init		= esdhc_init,
 	.send_cmd	= esdhc_send_cmd,
 	.set_ios	= esdhc_set_ios,
-	.init		= esdhc_init,
-	.getcd		= esdhc_getcd,
 };
+#endif
 
-static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
+static int fsl_esdhc_init(struct fsl_esdhc_priv *priv,
+			  struct fsl_esdhc_plat *plat)
 {
+	struct mmc_config *cfg;
 	struct fsl_esdhc *regs;
-	struct mmc *mmc;
 	u32 caps, voltage_caps;
+	int ret;
 
 	if (!priv)
 		return -EINVAL;
@@ -738,7 +778,9 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
 	regs = priv->esdhc_regs;
 
 	/* First reset the eSDHC controller */
-	esdhc_reset(regs);
+	ret = esdhc_reset(regs);
+	if (ret)
+		return ret;
 
 #ifndef CONFIG_FSL_USDHC
 	esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
@@ -752,7 +794,10 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
 		esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
 
 	writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
-	memset(&priv->cfg, 0, sizeof(priv->cfg));
+	cfg = &plat->cfg;
+#ifndef CONFIG_DM_MMC
+	memset(cfg, '\0', sizeof(*cfg));
+#endif
 
 	voltage_caps = 0;
 	caps = esdhc_read32(&regs->hostcapblt);
@@ -774,58 +819,54 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
 	if (caps & ESDHC_HOSTCAPBLT_VS33)
 		voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;
 
-	priv->cfg.name = "FSL_SDHC";
-	priv->cfg.ops = &esdhc_ops;
+	cfg->name = "FSL_SDHC";
+#if !CONFIG_IS_ENABLED(DM_MMC)
+	cfg->ops = &esdhc_ops;
+#endif
 #ifdef CONFIG_SYS_SD_VOLTAGE
-	priv->cfg.voltages = CONFIG_SYS_SD_VOLTAGE;
+	cfg->voltages = CONFIG_SYS_SD_VOLTAGE;
 #else
-	priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 #endif
-	if ((priv->cfg.voltages & voltage_caps) == 0) {
+	if ((cfg->voltages & voltage_caps) == 0) {
 		printf("voltage not supported by controller\n");
 		return -1;
 	}
 
 	if (priv->bus_width == 8)
-		priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
+		cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
 	else if (priv->bus_width == 4)
-		priv->cfg.host_caps = MMC_MODE_4BIT;
+		cfg->host_caps = MMC_MODE_4BIT;
 
-	priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
+	cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
 #ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE
-	priv->cfg.host_caps |= MMC_MODE_DDR_52MHz;
+	cfg->host_caps |= MMC_MODE_DDR_52MHz;
 #endif
 
 	if (priv->bus_width > 0) {
 		if (priv->bus_width < 8)
-			priv->cfg.host_caps &= ~MMC_MODE_8BIT;
+			cfg->host_caps &= ~MMC_MODE_8BIT;
 		if (priv->bus_width < 4)
-			priv->cfg.host_caps &= ~MMC_MODE_4BIT;
+			cfg->host_caps &= ~MMC_MODE_4BIT;
 	}
 
 	if (caps & ESDHC_HOSTCAPBLT_HSS)
-		priv->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+		cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
 
 #ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
 	if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
-		priv->cfg.host_caps &= ~MMC_MODE_8BIT;
+		cfg->host_caps &= ~MMC_MODE_8BIT;
 #endif
 
-	priv->cfg.f_min = 400000;
-	priv->cfg.f_max = min(priv->sdhc_clk, (u32)52000000);
-
-	priv->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
-
-	mmc = mmc_create(&priv->cfg, priv);
-	if (mmc == NULL)
-		return -1;
+	cfg->f_min = 400000;
+	cfg->f_max = min(priv->sdhc_clk, (u32)52000000);
 
-	priv->mmc = mmc;
+	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
 	return 0;
 }
 
-#ifndef CONFIG_DM_MMC
+#if !CONFIG_IS_ENABLED(DM_MMC)
 static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg,
 				 struct fsl_esdhc_priv *priv)
 {
@@ -843,7 +884,9 @@ static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg,
 
 int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 {
+	struct fsl_esdhc_plat *plat;
 	struct fsl_esdhc_priv *priv;
+	struct mmc *mmc;
 	int ret;
 
 	if (!cfg)
@@ -852,21 +895,34 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 	priv = calloc(sizeof(struct fsl_esdhc_priv), 1);
 	if (!priv)
 		return -ENOMEM;
+	plat = calloc(sizeof(struct fsl_esdhc_plat), 1);
+	if (!plat) {
+		free(priv);
+		return -ENOMEM;
+	}
 
 	ret = fsl_esdhc_cfg_to_priv(cfg, priv);
 	if (ret) {
 		debug("%s xlate failure\n", __func__);
+		free(plat);
 		free(priv);
 		return ret;
 	}
 
-	ret = fsl_esdhc_init(priv);
+	ret = fsl_esdhc_init(priv, plat);
 	if (ret) {
 		debug("%s init failure\n", __func__);
+		free(plat);
 		free(priv);
 		return ret;
 	}
 
+	mmc = mmc_create(&plat->cfg, priv);
+	if (!mmc)
+		return -EIO;
+
+	priv->mmc = mmc;
+
 	return 0;
 }
 
@@ -954,7 +1010,7 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd)
 }
 #endif
 
-#ifdef CONFIG_DM_MMC
+#if CONFIG_IS_ENABLED(DM_MMC)
 #include <asm/arch/clock.h>
 __weak void init_clk_usdhc(u32 index)
 {
@@ -963,24 +1019,24 @@ __weak void init_clk_usdhc(u32 index)
 static int fsl_esdhc_probe(struct udevice *dev)
 {
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
 	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
-	const void *fdt = gd->fdt_blob;
-	int node = dev_of_offset(dev);
 #ifdef CONFIG_DM_REGULATOR
 	struct udevice *vqmmc_dev;
 #endif
 	fdt_addr_t addr;
 	unsigned int val;
+	struct mmc *mmc;
 	int ret;
 
-	addr = devfdt_get_addr(dev);
+	addr = dev_read_addr(dev);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
 	priv->esdhc_regs = (struct fsl_esdhc *)addr;
 	priv->dev = dev;
 
-	val = fdtdec_get_int(fdt, node, "bus-width", -1);
+	val = dev_read_u32_default(dev, "bus-width", -1);
 	if (val == 8)
 		priv->bus_width = 8;
 	else if (val == 4)
@@ -988,21 +1044,21 @@ static int fsl_esdhc_probe(struct udevice *dev)
 	else
 		priv->bus_width = 1;
 
-	if (fdt_get_property(fdt, node, "non-removable", NULL)) {
+	if (dev_read_bool(dev, "non-removable")) {
 		priv->non_removable = 1;
 	 } else {
 		priv->non_removable = 0;
 #ifdef CONFIG_DM_GPIO
-		gpio_request_by_name_nodev(offset_to_ofnode(node), "cd-gpios",
-					   0, &priv->cd_gpio, GPIOD_IS_IN);
+		gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
+				     GPIOD_IS_IN);
 #endif
 	}
 
 	priv->wp_enable = 1;
 
 #ifdef CONFIG_DM_GPIO
-	ret = gpio_request_by_name_nodev(offset_to_ofnode(node), "wp-gpios", 0,
-					 &priv->wp_gpio, GPIOD_IS_IN);
+	ret = gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio,
+				   GPIOD_IS_IN);
 	if (ret)
 		priv->wp_enable = 0;
 #endif
@@ -1057,18 +1113,53 @@ static int fsl_esdhc_probe(struct udevice *dev)
 		return -EINVAL;
 	}
 
-	ret = fsl_esdhc_init(priv);
+	ret = fsl_esdhc_init(priv, plat);
 	if (ret) {
 		dev_err(dev, "fsl_esdhc_init failure\n");
 		return ret;
 	}
 
-	upriv->mmc = priv->mmc;
-	priv->mmc->dev = dev;
+	mmc = &plat->mmc;
+	mmc->cfg = &plat->cfg;
+	mmc->dev = dev;
+	upriv->mmc = mmc;
 
-	return 0;
+	return esdhc_init_common(priv, mmc);
 }
 
+#if CONFIG_IS_ENABLED(DM_MMC)
+static int fsl_esdhc_get_cd(struct udevice *dev)
+{
+	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+
+	return true;
+	return esdhc_getcd_common(priv);
+}
+
+static int fsl_esdhc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+			      struct mmc_data *data)
+{
+	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+
+	return esdhc_send_cmd_common(priv, &plat->mmc, cmd, data);
+}
+
+static int fsl_esdhc_set_ios(struct udevice *dev)
+{
+	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+
+	return esdhc_set_ios_common(priv, &plat->mmc);
+}
+
+static const struct dm_mmc_ops fsl_esdhc_ops = {
+	.get_cd		= fsl_esdhc_get_cd,
+	.send_cmd	= fsl_esdhc_send_cmd,
+	.set_ios	= fsl_esdhc_set_ios,
+};
+#endif
+
 static const struct udevice_id fsl_esdhc_ids[] = {
 	{ .compatible = "fsl,imx6ul-usdhc", },
 	{ .compatible = "fsl,imx6sx-usdhc", },
@@ -1080,11 +1171,25 @@ static const struct udevice_id fsl_esdhc_ids[] = {
 	{ /* sentinel */ }
 };
 
+#if CONFIG_IS_ENABLED(BLK)
+static int fsl_esdhc_bind(struct udevice *dev)
+{
+	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+
+	return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+#endif
+
 U_BOOT_DRIVER(fsl_esdhc) = {
 	.name	= "fsl-esdhc-mmc",
 	.id	= UCLASS_MMC,
 	.of_match = fsl_esdhc_ids,
+	.ops	= &fsl_esdhc_ops,
+#if CONFIG_IS_ENABLED(BLK)
+	.bind	= fsl_esdhc_bind,
+#endif
 	.probe	= fsl_esdhc_probe,
+	.platdata_auto_alloc_size = sizeof(struct fsl_esdhc_plat),
 	.priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv),
 };
 #endif
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index e9f061e55dc3b7ef7123a5b60dbd5e53b56988af..22154d13d791464b39b81d8138594d4d604deab0 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -36,13 +36,22 @@ DECLARE_GLOBAL_DATA_PTR;
 # define MCI_BUS 0
 #endif
 
+#ifdef CONFIG_DM_MMC
+struct atmel_mci_plat {
+	struct mmc		mmc;
+	struct mmc_config	cfg;
+	struct atmel_mci	*mci;
+};
+#endif
+
 struct atmel_mci_priv {
+#ifndef CONFIG_DM_MMC
 	struct mmc_config	cfg;
 	struct atmel_mci	*mci;
+#endif
 	unsigned int		initialized:1;
 	unsigned int		curr_clk;
 #ifdef CONFIG_DM_MMC
-	struct mmc	mmc;
 	ulong		bus_clk_rate;
 #endif
 };
@@ -67,18 +76,21 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
 
 /* Setup for MCI Clock and Block Size */
 #ifdef CONFIG_DM_MMC
-static void mci_set_mode(struct atmel_mci_priv *priv, u32 hz, u32 blklen)
+static void mci_set_mode(struct udevice *dev, u32 hz, u32 blklen)
 {
-	struct mmc *mmc = &priv->mmc;
+	struct atmel_mci_plat *plat = dev_get_platdata(dev);
+	struct atmel_mci_priv *priv = dev_get_priv(dev);
+	struct mmc *mmc = &plat->mmc;
 	u32 bus_hz = priv->bus_clk_rate;
+	atmel_mci_t *mci = plat->mci;
 #else
 static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 {
 	struct atmel_mci_priv *priv = mmc->priv;
 	u32 bus_hz = get_mci_clk_rate();
+	atmel_mci_t *mci = priv->mci;
 #endif
 
-	atmel_mci_t *mci = priv->mci;
 	u32 clkdiv = 255;
 	unsigned int version = atmel_mci_get_version(mci);
 	u32 clkodd = 0;
@@ -222,15 +234,17 @@ io_fail:
 static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 			      struct mmc_data *data)
 {
+	struct atmel_mci_plat *plat = dev_get_platdata(dev);
 	struct atmel_mci_priv *priv = dev_get_priv(dev);
 	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	atmel_mci_t *mci = plat->mci;
 #else
 static int
 mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
 	struct atmel_mci_priv *priv = mmc->priv;
-#endif
 	atmel_mci_t *mci = priv->mci;
+#endif
 	u32 cmdr;
 	u32 error_flags = 0;
 	u32 status;
@@ -362,22 +376,23 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 #ifdef CONFIG_DM_MMC
 static int atmel_mci_set_ios(struct udevice *dev)
 {
-	struct atmel_mci_priv *priv = dev_get_priv(dev);
+	struct atmel_mci_plat *plat = dev_get_platdata(dev);
 	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	atmel_mci_t *mci = plat->mci;
 #else
 /* Entered into mmc structure during driver init */
 static int mci_set_ios(struct mmc *mmc)
 {
 	struct atmel_mci_priv *priv = mmc->priv;
-#endif
 	atmel_mci_t *mci = priv->mci;
+#endif
 	int bus_width = mmc->bus_width;
 	unsigned int version = atmel_mci_get_version(mci);
 	int busw;
 
 	/* Set the clock speed */
 #ifdef CONFIG_DM_MMC
-	mci_set_mode(priv, mmc->clock, MMC_DEFAULT_BLKLEN);
+	mci_set_mode(dev, mmc->clock, MMC_DEFAULT_BLKLEN);
 #else
 	mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
 #endif
@@ -410,15 +425,17 @@ static int mci_set_ios(struct mmc *mmc)
 }
 
 #ifdef CONFIG_DM_MMC
-static int atmel_mci_hw_init(struct atmel_mci_priv *priv)
+static int atmel_mci_hw_init(struct udevice *dev)
 {
+	struct atmel_mci_plat *plat = dev_get_platdata(dev);
+	atmel_mci_t *mci = plat->mci;
 #else
 /* Entered into mmc structure during driver init */
 static int mci_init(struct mmc *mmc)
 {
 	struct atmel_mci_priv *priv = mmc->priv;
-#endif
 	atmel_mci_t *mci = priv->mci;
+#endif
 
 	/* Initialize controller */
 	writel(MMCI_BIT(SWRST), &mci->cr);	/* soft reset */
@@ -433,7 +450,7 @@ static int mci_init(struct mmc *mmc)
 
 	/* Set default clocks and blocklen */
 #ifdef CONFIG_DM_MMC
-	mci_set_mode(priv, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
+	mci_set_mode(dev, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
 #else
 	mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
 #endif
@@ -509,12 +526,14 @@ static const struct dm_mmc_ops atmel_mci_mmc_ops = {
 	.set_ios = atmel_mci_set_ios,
 };
 
-static void atmel_mci_setup_cfg(struct atmel_mci_priv *priv)
+static void atmel_mci_setup_cfg(struct udevice *dev)
 {
+	struct atmel_mci_plat *plat = dev_get_platdata(dev);
+	struct atmel_mci_priv *priv = dev_get_priv(dev);
 	struct mmc_config *cfg;
 	u32 version;
 
-	cfg = &priv->cfg;
+	cfg = &plat->cfg;
 	cfg->name = "Atmel mci";
 	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 
@@ -522,7 +541,7 @@ static void atmel_mci_setup_cfg(struct atmel_mci_priv *priv)
 	 * If the version is above 3.0, the capabilities of the 8-bit
 	 * bus width and high speed are supported.
 	 */
-	version = atmel_mci_get_version(priv->mci);
+	version = atmel_mci_get_version(plat->mci);
 	if ((version & 0xf00) >= 0x300) {
 		cfg->host_caps = MMC_MODE_8BIT |
 				 MMC_MODE_HS | MMC_MODE_HS_52MHz;
@@ -568,7 +587,7 @@ failed:
 static int atmel_mci_probe(struct udevice *dev)
 {
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
-	struct atmel_mci_priv *priv = dev_get_priv(dev);
+	struct atmel_mci_plat *plat = dev_get_platdata(dev);
 	struct mmc *mmc;
 	int ret;
 
@@ -576,25 +595,25 @@ static int atmel_mci_probe(struct udevice *dev)
 	if (ret)
 		return ret;
 
-	priv->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev);
+	plat->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev);
 
-	atmel_mci_setup_cfg(priv);
+	atmel_mci_setup_cfg(dev);
 
-	mmc = &priv->mmc;
-	mmc->cfg = &priv->cfg;
+	mmc = &plat->mmc;
+	mmc->cfg = &plat->cfg;
 	mmc->dev = dev;
 	upriv->mmc = mmc;
 
-	atmel_mci_hw_init(priv);
+	atmel_mci_hw_init(dev);
 
 	return 0;
 }
 
 static int atmel_mci_bind(struct udevice *dev)
 {
-	struct atmel_mci_priv *priv = dev_get_priv(dev);
+	struct atmel_mci_plat *plat = dev_get_platdata(dev);
 
-	return mmc_bind(dev, &priv->mmc, &priv->cfg);
+	return mmc_bind(dev, &plat->mmc, &plat->cfg);
 }
 
 static const struct udevice_id atmel_mci_ids[] = {
@@ -608,6 +627,7 @@ U_BOOT_DRIVER(atmel_mci) = {
 	.of_match = atmel_mci_ids,
 	.bind = atmel_mci_bind,
 	.probe = atmel_mci_probe,
+	.platdata_auto_alloc_size = sizeof(struct atmel_mci_plat),
 	.priv_auto_alloc_size = sizeof(struct atmel_mci_priv),
 	.ops = &atmel_mci_mmc_ops,
 };
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 3e907253ea8d99eb86803a2fc3a27bcdc6fe072c..5dda20cda5e7c06189319590342a02a0f332bd26 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -15,7 +15,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if CONFIG_IS_ENABLED(DM_MMC_OPS)
 int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 		    struct mmc_data *data)
 {
@@ -79,7 +78,6 @@ int mmc_getcd(struct mmc *mmc)
 {
 	return dm_mmc_get_cd(mmc->dev);
 }
-#endif
 
 struct mmc *mmc_get_mmc_dev(struct udevice *dev)
 {
@@ -198,10 +196,8 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
 	struct udevice *bdev;
 	int ret, devnum = -1;
 
-#if CONFIG_IS_ENABLED(DM_MMC_OPS)
 	if (!mmc_get_ops(dev))
 		return -ENOSYS;
-#endif
 #ifndef CONFIG_SPL_BUILD
 	/* Use the fixed index with aliase node's index */
 	ret = dev_read_alias_seq(dev, &devnum);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 38e1c800e10c3b7c70d69828413444e34db12d9f..38d2e07dd51083872e47cf600cd36fdebc8591c5 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -53,7 +53,7 @@ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
 }
 #endif
 
-#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if !CONFIG_IS_ENABLED(DM_MMC)
 __weak int board_mmc_getwp(struct mmc *mmc)
 {
 	return -1;
@@ -149,7 +149,7 @@ void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
 }
 #endif
 
-#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if !CONFIG_IS_ENABLED(DM_MMC)
 int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
 	int ret;
@@ -839,7 +839,7 @@ int mmc_hwpart_config(struct mmc *mmc,
 	return 0;
 }
 
-#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if !CONFIG_IS_ENABLED(DM_MMC)
 int mmc_getcd(struct mmc *mmc)
 {
 	int cd;
@@ -1075,7 +1075,7 @@ static const u8 multipliers[] = {
 	80,
 };
 
-#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if !CONFIG_IS_ENABLED(DM_MMC)
 static void mmc_set_ios(struct mmc *mmc)
 {
 	if (mmc->cfg->ops->set_ios)
@@ -1652,7 +1652,7 @@ int mmc_start_init(struct mmc *mmc)
 
 	/* we pretend there's no card when init is NULL */
 	no_card = mmc_getcd(mmc) == 0;
-#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if !CONFIG_IS_ENABLED(DM_MMC)
 	no_card = no_card || (mmc->cfg->ops->init == NULL);
 #endif
 	if (no_card) {
@@ -1673,7 +1673,7 @@ int mmc_start_init(struct mmc *mmc)
 	if (err)
 		return err;
 
-#if CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if CONFIG_IS_ENABLED(DM_MMC)
 	/* The device has already been probed ready for use */
 #else
 	/* made sure it's not NULL earlier */
diff --git a/drivers/mmc/mmc_boot.c b/drivers/mmc/mmc_boot.c
index ac6f56f157a49078118348ab999c45c44b9fe398..6d77ce95e7e2ecaf68a47411396eade2d39c2685 100644
--- a/drivers/mmc/mmc_boot.c
+++ b/drivers/mmc/mmc_boot.c
@@ -100,10 +100,19 @@ int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
  */
 int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
 {
-	return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
-			  EXT_CSD_BOOT_ACK(ack) |
-			  EXT_CSD_BOOT_PART_NUM(part_num) |
-			  EXT_CSD_PARTITION_ACCESS(access));
+	int ret;
+	u8 part_conf;
+
+	part_conf = EXT_CSD_BOOT_ACK(ack) |
+		    EXT_CSD_BOOT_PART_NUM(part_num) |
+		    EXT_CSD_PARTITION_ACCESS(access);
+
+	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+			 part_conf);
+	if (!ret)
+		mmc->part_config = part_conf;
+
+	return ret;
 }
 
 /*
diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c
index 59dc3df35f8f057ef58e2005a6b10fa53ff62306..100b931e5b349f33d36691a5c552675935c4be8c 100644
--- a/drivers/mmc/mmc_legacy.c
+++ b/drivers/mmc/mmc_legacy.c
@@ -150,7 +150,7 @@ struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
 	    cfg->f_max == 0 || cfg->b_max == 0)
 		return NULL;
 
-#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if !CONFIG_IS_ENABLED(DM_MMC)
 	if (cfg->ops == NULL || cfg->ops->send_cmd == NULL)
 		return NULL;
 #endif
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c
index 6db89779ba3c1fada496030f533e533bc9a24262..05c0044a7a001148fc8e3183a2229fc171ed6b33 100644
--- a/drivers/mmc/pci_mmc.c
+++ b/drivers/mmc/pci_mmc.c
@@ -64,12 +64,7 @@ U_BOOT_DRIVER(pci_mmc) = {
 };
 
 static struct pci_device_id mmc_supported[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_SDIO) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_SD) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_EMMC2) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_SDIO) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_1) },
+	{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_SDHCI << 8, 0xffff00) },
 	{},
 };
 
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 161a6b1399c98456c4504042541a2d36213fe5d5..11d1f0c24cd84f25ae08e2e406150d7a966d9edc 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -134,7 +134,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
 #define SDHCI_CMD_DEFAULT_TIMEOUT		100
 #define SDHCI_READ_STATUS_TIMEOUT		1000
 
-#ifdef CONFIG_DM_MMC_OPS
+#ifdef CONFIG_DM_MMC
 static int sdhci_send_command(struct udevice *dev, struct mmc_cmd *cmd,
 			      struct mmc_data *data)
 {
@@ -422,7 +422,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 }
 
-#ifdef CONFIG_DM_MMC_OPS
+#ifdef CONFIG_DM_MMC
 static int sdhci_set_ios(struct udevice *dev)
 {
 	struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -502,7 +502,7 @@ static int sdhci_init(struct mmc *mmc)
 	return 0;
 }
 
-#ifdef CONFIG_DM_MMC_OPS
+#ifdef CONFIG_DM_MMC
 int sdhci_probe(struct udevice *dev)
 {
 	struct mmc *mmc = mmc_get_mmc_dev(dev);
@@ -543,7 +543,7 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 		host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
 	cfg->name = host->name;
-#ifndef CONFIG_DM_MMC_OPS
+#ifndef CONFIG_DM_MMC
 	cfg->ops = &sdhci_ops;
 #endif
 
diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c
index d181b6390586683cb61503fc136e8543f66951f7..eef061abb2de49634e9dea648022f7fb2b1e3fee 100644
--- a/drivers/mmc/sh_sdhi.c
+++ b/drivers/mmc/sh_sdhi.c
@@ -13,21 +13,26 @@
 #include <common.h>
 #include <malloc.h>
 #include <mmc.h>
+#include <dm.h>
 #include <linux/errno.h>
-#include <asm/io.h>
+#include <linux/compat.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
 #include <asm/arch/rmobile.h>
 #include <asm/arch/sh_sdhi.h>
+#include <clk.h>
 
 #define DRIVER_NAME "sh-sdhi"
 
 struct sh_sdhi_host {
-	unsigned long addr;
+	void __iomem *addr;
 	int ch;
 	int bus_shift;
 	unsigned long quirks;
 	unsigned char wait_int;
 	unsigned char sd_error;
 	unsigned char detect_waiting;
+	unsigned char app_cmd;
 };
 
 static inline void sh_sdhi_writeq(struct sh_sdhi_host *host, int reg, u64 val)
@@ -50,11 +55,6 @@ static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
 	return readw(host->addr + (reg << host->bus_shift));
 }
 
-static void *mmc_priv(struct mmc *mmc)
-{
-	return (void *)mmc->priv;
-}
-
 static void sh_sdhi_detect(struct sh_sdhi_host *host)
 {
 	sh_sdhi_writew(host, SDHI_OPTION,
@@ -477,65 +477,64 @@ static void sh_sdhi_get_response(struct sh_sdhi_host *host, struct mmc_cmd *cmd)
 static unsigned short sh_sdhi_set_cmd(struct sh_sdhi_host *host,
 			struct mmc_data *data, unsigned short opc)
 {
-	switch (opc) {
-	case SD_CMD_APP_SEND_OP_COND:
-	case SD_CMD_APP_SEND_SCR:
-		opc |= SDHI_APP;
-		break;
-	case SD_CMD_APP_SET_BUS_WIDTH:
-		 /* SD_APP_SET_BUS_WIDTH*/
+	if (host->app_cmd) {
 		if (!data)
-			opc |= SDHI_APP;
-		else /* SD_SWITCH */
-			opc = SDHI_SD_SWITCH;
-		break;
-	case MMC_CMD_SEND_OP_COND:
-		opc = SDHI_MMC_SEND_OP_COND;
-		break;
+			host->app_cmd = 0;
+		return opc | BIT(6);
+	}
+
+	switch (opc) {
+	case MMC_CMD_SWITCH:
+		return opc | (data ? 0x1c00 : 0x40);
 	case MMC_CMD_SEND_EXT_CSD:
-		if (data)
-			opc = SDHI_MMC_SEND_EXT_CSD;
-		break;
+		return opc | (data ? 0x1c00 : 0);
+	case MMC_CMD_SEND_OP_COND:
+		return opc | 0x0700;
+	case MMC_CMD_APP_CMD:
+		host->app_cmd = 1;
 	default:
-		break;
+		return opc;
 	}
-	return opc;
 }
 
 static unsigned short sh_sdhi_data_trans(struct sh_sdhi_host *host,
 			struct mmc_data *data, unsigned short opc)
 {
-	unsigned short ret;
-
-	switch (opc) {
-	case MMC_CMD_READ_MULTIPLE_BLOCK:
-		ret = sh_sdhi_multi_read(host, data);
-		break;
-	case MMC_CMD_WRITE_MULTIPLE_BLOCK:
-		ret = sh_sdhi_multi_write(host, data);
-		break;
-	case MMC_CMD_WRITE_SINGLE_BLOCK:
-		ret = sh_sdhi_single_write(host, data);
-		break;
-	case MMC_CMD_READ_SINGLE_BLOCK:
-	case SDHI_SD_APP_SEND_SCR:
-	case SDHI_SD_SWITCH: /* SD_SWITCH */
-	case SDHI_MMC_SEND_EXT_CSD:
-		ret = sh_sdhi_single_read(host, data);
-		break;
-	default:
-		printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
-		ret = -EINVAL;
-		break;
+	if (host->app_cmd) {
+		host->app_cmd = 0;
+		switch (opc) {
+		case SD_CMD_APP_SEND_SCR:
+		case SD_CMD_APP_SD_STATUS:
+			return sh_sdhi_single_read(host, data);
+		default:
+			printf(DRIVER_NAME": SD: NOT SUPPORT APP CMD = d'%04d\n",
+				opc);
+			return -EINVAL;
+		}
+	} else {
+		switch (opc) {
+		case MMC_CMD_WRITE_MULTIPLE_BLOCK:
+			return sh_sdhi_multi_write(host, data);
+		case MMC_CMD_READ_MULTIPLE_BLOCK:
+			return sh_sdhi_multi_read(host, data);
+		case MMC_CMD_WRITE_SINGLE_BLOCK:
+			return sh_sdhi_single_write(host, data);
+		case MMC_CMD_READ_SINGLE_BLOCK:
+		case MMC_CMD_SWITCH:
+		case MMC_CMD_SEND_EXT_CSD:;
+			return sh_sdhi_single_read(host, data);
+		default:
+			printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
+			return -EINVAL;
+		}
 	}
-	return ret;
 }
 
 static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
 			struct mmc_data *data, struct mmc_cmd *cmd)
 {
 	long time;
-	unsigned short opc = cmd->cmdidx;
+	unsigned short shcmd, opc = cmd->cmdidx;
 	int ret = 0;
 	unsigned long timeout;
 
@@ -563,7 +562,8 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
 		}
 		sh_sdhi_writew(host, SDHI_SIZE, data->blocksize);
 	}
-	opc = sh_sdhi_set_cmd(host, data, opc);
+
+	shcmd = sh_sdhi_set_cmd(host, data, opc);
 
 	/*
 	 *  U-Boot cannot use interrupt.
@@ -594,11 +594,12 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
 		       INFO2M_RESP_TIMEOUT | INFO2M_ILA) &
 		       sh_sdhi_readw(host, SDHI_INFO2_MASK));
 
-	sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(opc & CMD_MASK));
-
+	sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(shcmd & CMD_MASK));
 	time = sh_sdhi_wait_interrupt_flag(host);
-	if (!time)
+	if (!time) {
+		host->app_cmd = 0;
 		return sh_sdhi_error_manage(host);
+	}
 
 	if (host->sd_error) {
 		switch (cmd->cmdidx) {
@@ -616,15 +617,20 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
 		}
 		host->sd_error = 0;
 		host->wait_int = 0;
+		host->app_cmd = 0;
 		return ret;
 	}
-	if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END)
+
+	if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END) {
+		host->app_cmd = 0;
 		return -EINVAL;
+	}
 
 	if (host->wait_int) {
 		sh_sdhi_get_response(host, cmd);
 		host->wait_int = 0;
 	}
+
 	if (data)
 		ret = sh_sdhi_data_trans(host, data, opc);
 
@@ -634,23 +640,17 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
 	return ret;
 }
 
-static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
-			struct mmc_data *data)
+static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
+				   struct mmc_cmd *cmd, struct mmc_data *data)
 {
-	struct sh_sdhi_host *host = mmc_priv(mmc);
-	int ret;
-
 	host->sd_error = 0;
 
-	ret = sh_sdhi_start_cmd(host, data, cmd);
-
-	return ret;
+	return sh_sdhi_start_cmd(host, data, cmd);
 }
 
-static int sh_sdhi_set_ios(struct mmc *mmc)
+static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc)
 {
 	int ret;
-	struct sh_sdhi_host *host = mmc_priv(mmc);
 
 	ret = sh_sdhi_clock_control(host, mmc->clock);
 	if (ret)
@@ -674,9 +674,8 @@ static int sh_sdhi_set_ios(struct mmc *mmc)
 	return 0;
 }
 
-static int sh_sdhi_initialize(struct mmc *mmc)
+static int sh_sdhi_initialize_common(struct sh_sdhi_host *host)
 {
-	struct sh_sdhi_host *host = mmc_priv(mmc);
 	int ret = sh_sdhi_sync_reset(host);
 
 	sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
@@ -692,6 +691,34 @@ static int sh_sdhi_initialize(struct mmc *mmc)
 	return ret;
 }
 
+#ifndef CONFIG_DM_MMC
+static void *mmc_priv(struct mmc *mmc)
+{
+	return (void *)mmc->priv;
+}
+
+static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+			    struct mmc_data *data)
+{
+	struct sh_sdhi_host *host = mmc_priv(mmc);
+
+	return sh_sdhi_send_cmd_common(host, cmd, data);
+}
+
+static int sh_sdhi_set_ios(struct mmc *mmc)
+{
+	struct sh_sdhi_host *host = mmc_priv(mmc);
+
+	return sh_sdhi_set_ios_common(host, mmc);
+}
+
+static int sh_sdhi_initialize(struct mmc *mmc)
+{
+	struct sh_sdhi_host *host = mmc_priv(mmc);
+
+	return sh_sdhi_initialize_common(host);
+}
+
 static const struct mmc_ops sh_sdhi_ops = {
 	.send_cmd       = sh_sdhi_send_cmd,
 	.set_ios        = sh_sdhi_set_ios,
@@ -743,7 +770,7 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
 	}
 
 	host->ch = ch;
-	host->addr = addr;
+	host->addr = (void __iomem *)addr;
 	host->quirks = quirks;
 
 	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
@@ -757,3 +784,123 @@ error:
 		free(host);
 	return ret;
 }
+
+#else
+
+struct sh_sdhi_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+			struct mmc_data *data)
+{
+	struct sh_sdhi_host *host = dev_get_priv(dev);
+
+	return sh_sdhi_send_cmd_common(host, cmd, data);
+}
+
+int sh_sdhi_dm_set_ios(struct udevice *dev)
+{
+	struct sh_sdhi_host *host = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+	return sh_sdhi_set_ios_common(host, mmc);
+}
+
+static const struct dm_mmc_ops sh_sdhi_dm_ops = {
+	.send_cmd	= sh_sdhi_dm_send_cmd,
+	.set_ios	= sh_sdhi_dm_set_ios,
+};
+
+static int sh_sdhi_dm_bind(struct udevice *dev)
+{
+	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
+
+	return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static int sh_sdhi_dm_probe(struct udevice *dev)
+{
+	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
+	struct sh_sdhi_host *host = dev_get_priv(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct clk sh_sdhi_clk;
+	const u32 quirks = dev_get_driver_data(dev);
+	fdt_addr_t base;
+	int ret;
+
+	base = devfdt_get_addr(dev);
+	if (base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	host->addr = devm_ioremap(dev, base, SZ_2K);
+	if (!host->addr)
+		return -ENOMEM;
+
+	ret = clk_get_by_index(dev, 0, &sh_sdhi_clk);
+	if (ret) {
+		debug("failed to get clock, ret=%d\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(&sh_sdhi_clk);
+	if (ret) {
+		debug("failed to enable clock, ret=%d\n", ret);
+		return ret;
+	}
+
+	host->quirks = quirks;
+
+	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
+		host->bus_shift = 2;
+	else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
+		host->bus_shift = 1;
+
+	plat->cfg.name = dev->name;
+	plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+	switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
+			       1)) {
+	case 8:
+		plat->cfg.host_caps |= MMC_MODE_8BIT;
+		break;
+	case 4:
+		plat->cfg.host_caps |= MMC_MODE_4BIT;
+		break;
+	case 1:
+		break;
+	default:
+		dev_err(dev, "Invalid \"bus-width\" value\n");
+		return -EINVAL;
+	}
+
+	sh_sdhi_initialize_common(host);
+
+	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
+	plat->cfg.f_min = CLKDEV_INIT;
+	plat->cfg.f_max = CLKDEV_HS_DATA;
+	plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+	upriv->mmc = &plat->mmc;
+
+	return 0;
+}
+
+static const struct udevice_id sh_sdhi_sd_match[] = {
+	{ .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
+	{ .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sh_sdhi_mmc) = {
+	.name			= "sh-sdhi-mmc",
+	.id			= UCLASS_MMC,
+	.of_match		= sh_sdhi_sd_match,
+	.bind			= sh_sdhi_dm_bind,
+	.probe			= sh_sdhi_dm_probe,
+	.priv_auto_alloc_size	= sizeof(struct sh_sdhi_host),
+	.platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat),
+	.ops			= &sh_sdhi_dm_ops,
+};
+#endif
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 3c462bd5835e9e4efae745791fdaaff80a4c2af5..e272b141532456ba1cb4a46db895a9ba6e52b944 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -470,13 +470,13 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 		u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32);
 		u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10);
 
-		cmd->response[0] = (rsp_127_104 & 0xffffff) << 8 |
-							(rsp_103_72 & 0xff);
-		cmd->response[1] = (rsp_103_72  & 0xffffff) << 8 |
-							(rsp_71_40 & 0xff);
-		cmd->response[2] = (rsp_71_40   & 0xffffff) << 8 |
-							(rsp_39_8 & 0xff);
-		cmd->response[3] = (rsp_39_8    & 0xffffff) << 8;
+		cmd->response[0] = ((rsp_127_104 & 0x00ffffff) << 8) |
+				   ((rsp_103_72  & 0xff000000) >> 24);
+		cmd->response[1] = ((rsp_103_72  & 0x00ffffff) << 8) |
+				   ((rsp_71_40   & 0xff000000) >> 24);
+		cmd->response[2] = ((rsp_71_40   & 0x00ffffff) << 8) |
+				   ((rsp_39_8    & 0xff000000) >> 24);
+		cmd->response[3] = (rsp_39_8     & 0xffffff)   << 8;
 	} else {
 		/* bit 39-8 */
 		cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10);
diff --git a/include/ahci.h b/include/ahci.h
index 29f4ba1d13dabf64b60b5dc340c36b836e7099b6..33171b7ffd63824f457c3afe3af41feeaf697016 100644
--- a/include/ahci.h
+++ b/include/ahci.h
@@ -176,6 +176,60 @@ struct ahci_uc_priv {
 	u32	link_port_map; /*linkup port map*/
 };
 
+struct ahci_ops {
+	/**
+	 * reset() - reset the controller
+	 *
+	 * @dev:	Controller to reset
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*reset)(struct udevice *dev);
+
+	/**
+	 * port_status() - get the status of a SATA port
+	 *
+	 * @dev:	Controller to reset
+	 * @port:	Port number to check (0 for first)
+	 * @return 0 if detected, -ENXIO if nothing on port, other -ve on error
+	 */
+	int (*port_status)(struct udevice *dev, int port);
+
+	/**
+	 * scan() - scan SATA ports
+	 *
+	 * @dev:	Controller to scan
+	 * @return 0 if OK, -ve on error
+	 */
+	int (*scan)(struct udevice *dev);
+};
+
+#define ahci_get_ops(dev)        ((struct ahci_ops *)(dev)->driver->ops)
+
+/**
+ * sata_reset() - reset the controller
+ *
+ * @dev:	Controller to reset
+ * @return 0 if OK, -ve on error
+ */
+int sata_reset(struct udevice *dev);
+
+/**
+ * sata_port_status() - get the status of a SATA port
+ *
+ * @dev:	Controller to reset
+ * @port:	Port number to check (0 for first)
+ * @return 0 if detected, -ENXIO if nothin on port, other -ve on error
+ */
+int sata_dm_port_status(struct udevice *dev, int port);
+
+/**
+ * sata_scan() - scan SATA ports
+ *
+ * @dev:	Controller to scan
+ * @return 0 if OK, -ve on error
+ */
+int sata_scan(struct udevice *dev);
+
 int ahci_init(void __iomem *base);
 int ahci_reset(void __iomem *base);
 
diff --git a/include/blk.h b/include/blk.h
index 61b56281b3150cc815a7385969ed6504d8d0d379..a106f9ca0e5922170c48864060f9a7460666f35e 100644
--- a/include/blk.h
+++ b/include/blk.h
@@ -624,4 +624,24 @@ ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
  */
 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart);
 
+/**
+ * blk_get_if_type_name() - Get the name of an interface type
+ *
+ * @if_type: Interface type to check
+ * @return name of interface, or NULL if none
+ */
+const char *blk_get_if_type_name(enum if_type if_type);
+
+/**
+ * blk_common_cmd() - handle common commands with block devices
+ *
+ * @args: Number of arguments to the command (argv[0] is the command itself)
+ * @argv: Command arguments
+ * @if_type: Interface type
+ * @cur_devnump: Current device number for this interface type
+ * @return 0 if OK, CMD_RET_ERROR on error
+ */
+int blk_common_cmd(int argc, char * const argv[], enum if_type if_type,
+		   int *cur_devnump);
+
 #endif
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index c9420b2d739cd5d10f7fe6467a7f77b03e87f281..973f63f891b74858f5188bbc00ee09d8d0d37183 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -282,7 +282,6 @@
  */
 #ifdef CONFIG_SPL_BUILD
 #undef CONFIG_DM_MMC
-#undef CONFIG_DM_MMC_OPS
 #undef CONFIG_TIMER
 #undef CONFIG_DM_USB
 #endif
diff --git a/include/configs/am335x_shc.h b/include/configs/am335x_shc.h
index 62ab2d7227e0a92b76105e203d554284a5b43220..3fdbfdcdc670287f5fab71221c3034e911dd5128 100644
--- a/include/configs/am335x_shc.h
+++ b/include/configs/am335x_shc.h
@@ -256,7 +256,6 @@
  */
 #ifdef CONFIG_SPL_BUILD
 #undef CONFIG_DM_MMC
-#undef CONFIG_DM_MMC_OPS
 #undef CONFIG_TIMER
 #endif
 
diff --git a/include/configs/chiliboard.h b/include/configs/chiliboard.h
index fb3e67466ee0b34fb2d95d6bbc4cd494c7ffe818..20075915fd528d1ee1dff81938a7a59395eb3381 100644
--- a/include/configs/chiliboard.h
+++ b/include/configs/chiliboard.h
@@ -183,7 +183,6 @@
  */
 #ifdef CONFIG_SPL_BUILD
 #undef CONFIG_DM_MMC
-#undef CONFIG_DM_MMC_OPS
 #undef CONFIG_TIMER
 #undef CONFIG_DM_USB
 #endif
diff --git a/include/configs/omap3_logic.h b/include/configs/omap3_logic.h
index 5490fc945a18324c3be160788295e938f93ac1f6..b4311ab13b678e1f867681b8928071a9fe2cd3d0 100644
--- a/include/configs/omap3_logic.h
+++ b/include/configs/omap3_logic.h
@@ -23,7 +23,6 @@
  * DM support in SPL
  */
 #undef CONFIG_DM_MMC
-#undef CONFIG_DM_MMC_OPS
 #undef OMAP_HSMMC_USE_GPIO
 
 /* select serial console configuration for SPL */
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 81ab893b600d5c4c0fa975a48019afa6d1aa4dd8..eaeadd48d2a999506c6afd03bb6304c5f7f1329b 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -98,7 +98,7 @@ int device_probe(struct udevice *dev);
  * children are deactivated first.
  *
  * @dev: Pointer to device to remove
- * @flags: Flags for selective device removal
+ * @flags: Flags for selective device removal (DM_REMOVE_...)
  * @return 0 if OK, -ve on error (an error here is normally a very bad thing)
  */
 #if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
diff --git a/include/dwc_ahsata.h b/include/dwc_ahsata.h
new file mode 100644
index 0000000000000000000000000000000000000000..cae275fe75a1f28a7aa4db092b3ad74406e296d8
--- /dev/null
+++ b/include/dwc_ahsata.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2017 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DWC_AHSATA_H__
+#define __DWC_AHSATA_H__
+
+int dwc_ahsata_bus_reset(struct udevice *dev);
+int dwc_ahsata_probe(struct udevice *dev);
+int dwc_ahsata_scan(struct udevice *dev);
+int dwc_ahsata_port_status(struct udevice *dev, int port);
+
+#endif
diff --git a/include/dwmmc.h b/include/dwmmc.h
index 4dda0091cefc1e7773213f3968e4ff8111b5b971..a9058824e0d97869a827a4451b18ab2787578aa9 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -291,7 +291,7 @@ int dwmci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
 int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk);
 #endif /* !CONFIG_BLK */
 
-#ifdef CONFIG_DM_MMC_OPS
+#ifdef CONFIG_DM_MMC
 /* Export the operations to drivers */
 int dwmci_probe(struct udevice *dev);
 extern const struct dm_mmc_ops dm_dwmci_ops;
diff --git a/include/mmc.h b/include/mmc.h
index cb8bf6a971c0222234a35dc3651f06a845681e18..010ebe048c45ffb68d3ffcb0614b9b243bddcbcc 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -221,6 +221,10 @@
 #define EXT_CSD_BOOT_PART_NUM(x)	(x << 3)
 #define EXT_CSD_PARTITION_ACCESS(x)	(x << 0)
 
+#define EXT_CSD_EXTRACT_BOOT_ACK(x)		(((x) >> 6) & 0x1)
+#define EXT_CSD_EXTRACT_BOOT_PART(x)		(((x) >> 3) & 0x7)
+#define EXT_CSD_EXTRACT_PARTITION_ACCESS(x)	((x) & 0x7)
+
 #define EXT_CSD_BOOT_BUS_WIDTH_MODE(x)	(x << 3)
 #define EXT_CSD_BOOT_BUS_WIDTH_RESET(x)	(x << 2)
 #define EXT_CSD_BOOT_BUS_WIDTH_WIDTH(x)	(x)
@@ -321,7 +325,7 @@ struct mmc_data {
 /* forward decl. */
 struct mmc;
 
-#if CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if CONFIG_IS_ENABLED(DM_MMC)
 struct dm_mmc_ops {
 	/**
 	 * send_cmd() - Send a command to the MMC device
@@ -385,7 +389,7 @@ struct mmc_ops {
 
 struct mmc_config {
 	const char *name;
-#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if !CONFIG_IS_ENABLED(DM_MMC)
 	const struct mmc_ops *ops;
 #endif
 	uint host_caps;
@@ -519,7 +523,7 @@ int mmc_switch_part(struct mmc *mmc, unsigned int part_num);
 int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf,
 		      enum mmc_hwpart_conf_mode mode);
 
-#if !CONFIG_IS_ENABLED(DM_MMC_OPS)
+#if !CONFIG_IS_ENABLED(DM_MMC)
 int mmc_getcd(struct mmc *mmc);
 int board_mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
diff --git a/include/sata.h b/include/sata.h
index d18cc9aa87543453763f76f1cdb48f0e3a660765..d89f7a8a298ce1328b052b67882f42f092facda2 100644
--- a/include/sata.h
+++ b/include/sata.h
@@ -2,7 +2,7 @@
 #define __SATA_H__
 #include <part.h>
 
-#if !defined(CONFIG_DM_SCSI)
+#if !defined(CONFIG_DM_SCSI) && !defined(CONFIG_AHCI)
 int init_sata(int dev);
 int reset_sata(int dev);
 int scan_sata(int dev);
@@ -18,4 +18,7 @@ int sata_port_status(int dev, int port);
 extern struct blk_desc sata_dev_desc[];
 #endif
 
+int sata_probe(int devnum);
+int sata_remove(int devnum);
+
 #endif
diff --git a/include/sdhci.h b/include/sdhci.h
index 6a43271e963222f0c3321bf35aaa709ac22e863e..7e84012f60ec2b840a6abd64c139282e48baa37b 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -410,7 +410,7 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
 int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min);
 #endif /* !CONFIG_BLK */
 
-#ifdef CONFIG_DM_MMC_OPS
+#ifdef CONFIG_DM_MMC
 /* Export the operations to drivers */
 int sdhci_probe(struct udevice *dev);
 extern const struct dm_mmc_ops sdhci_ops;