Merge git://www.denx.de/git/u-boot-cfi-flash
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 1445731..74a63dd 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -62,6 +62,11 @@
 	case SOC_88F6820_ID:
 	case SOC_88F6828_ID:
 		return MVEBU_SOC_A38X;
+
+	case SOC_98DX3236_ID:
+	case SOC_98DX3336_ID:
+	case SOC_98DX4251_ID:
+		return MVEBU_SOC_MSYS;
 	}
 
 	return MVEBU_SOC_UNKNOWN;
@@ -107,13 +112,15 @@
 #elif defined(CONFIG_ARMADA_38X)
 /* SAR frequency values for Armada 38x */
 static const struct sar_freq_modes sar_freq_tab[] = {
-	{  0x0,  0x0,  666, 333, 333 },
-	{  0x2,  0x0,  800, 400, 400 },
-	{  0x4,  0x0, 1066, 533, 533 },
-	{  0x6,  0x0, 1200, 600, 600 },
-	{  0x8,  0x0, 1332, 666, 666 },
-	{  0xc,  0x0, 1600, 800, 800 },
-	{ 0xff, 0xff,    0,   0,   0 }	/* 0xff marks end of array */
+	{  0x0,  0x0,  666,  333, 333 },
+	{  0x2,  0x0,  800,  400, 400 },
+	{  0x4,  0x0, 1066,  533, 533 },
+	{  0x6,  0x0, 1200,  600, 600 },
+	{  0x8,  0x0, 1332,  666, 666 },
+	{  0xc,  0x0, 1600,  800, 800 },
+	{ 0x10,  0x0, 1866,  933, 933 },
+	{ 0x13,  0x0, 2000, 1000, 933 },
+	{ 0xff, 0xff,    0,    0,   0 }	/* 0xff marks end of array */
 };
 #else
 /* SAR frequency values for Armada XP */
@@ -208,6 +215,15 @@
 	case SOC_88F6828_ID:
 		puts("MV88F6828-");
 		break;
+	case SOC_98DX3236_ID:
+		puts("98DX3236-");
+		break;
+	case SOC_98DX3336_ID:
+		puts("98DX3336-");
+		break;
+	case SOC_98DX4251_ID:
+		puts("98DX4251-");
+		break;
 	default:
 		puts("Unknown-");
 		break;
diff --git a/arch/arm/mach-mvebu/dram.c b/arch/arm/mach-mvebu/dram.c
index e3f304c..e634905 100644
--- a/arch/arm/mach-mvebu/dram.c
+++ b/arch/arm/mach-mvebu/dram.c
@@ -179,11 +179,11 @@
 	reg_write(REG_SDRAM_CONFIG_ADDR, temp);
 
 	for (cs = 0; cs < CONFIG_NR_DRAM_BANKS; cs++) {
-		size = mvebu_sdram_bs(cs) - 1;
+		size = mvebu_sdram_bs(cs);
 		if (size == 0)
 			continue;
 
-		total = (u64)size + 1;
+		total = (u64)size;
 		total_mem += (u32)(total / (1 << 30));
 		start_addr = 0;
 		mv_xor_init2(cs);
@@ -194,7 +194,7 @@
 			size -= start_addr;
 		}
 
-		mv_xor_mem_init(SCRB_XOR_CHAN, start_addr, size,
+		mv_xor_mem_init(SCRB_XOR_CHAN, start_addr, size - 1,
 				SCRUB_MAGIC, SCRUB_MAGIC);
 
 		/* Wait for previous transfer completion */
@@ -216,6 +216,35 @@
 
 	return 0;
 }
+
+/* Return the width of the DRAM bus, or 0 for unknown. */
+static int bus_width(void)
+{
+	int full_width = 0;
+
+	if (reg_read(REG_SDRAM_CONFIG_ADDR) & (1 << REG_SDRAM_CONFIG_WIDTH_OFFS))
+		full_width = 1;
+
+	switch (mvebu_soc_family()) {
+	case MVEBU_SOC_AXP:
+	    return full_width ? 64 : 32;
+	    break;
+	case MVEBU_SOC_A375:
+	case MVEBU_SOC_A38X:
+	case MVEBU_SOC_MSYS:
+	    return full_width ? 32 : 16;
+	default:
+	    return 0;
+	}
+}
+
+static int cycle_mode(void)
+{
+	int val = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
+
+	return (val >> REG_DUNIT_CTRL_LOW_2T_OFFS) & REG_DUNIT_CTRL_LOW_2T_MASK;
+}
+
 #else
 static void dram_ecc_scrubbing(void)
 {
@@ -295,10 +324,26 @@
 void board_add_ram_info(int use_default)
 {
 	struct sar_freq_modes sar_freq;
+	int mode;
+	int width;
 
 	get_sar_freq(&sar_freq);
 	printf(" (%d MHz, ", sar_freq.d_clk);
 
+	width = bus_width();
+	if (width)
+		printf("%d-bit, ", width);
+
+	mode = cycle_mode();
+	/* Mode 0 = Single cycle
+	 * Mode 1 = Two cycles   (2T)
+	 * Mode 2 = Three cycles (3T)
+	 */
+	if (mode == 1)
+		printf("2T, ");
+	if (mode == 2)
+		printf("3T, ");
+
 	if (ecc_enabled())
 		printf("ECC");
 	else
diff --git a/arch/arm/mach-mvebu/include/mach/config.h b/arch/arm/mach-mvebu/include/mach/config.h
index 2dc9b1d..cfd0952 100644
--- a/arch/arm/mach-mvebu/include/mach/config.h
+++ b/arch/arm/mach-mvebu/include/mach/config.h
@@ -76,9 +76,6 @@
  */
 #ifdef CONFIG_CMD_NET
 #define CONFIG_MII		/* expose smi ove miiphy interface */
-#if !defined(CONFIG_ARMADA_375)
-#define CONFIG_MVNETA		/* Enable Marvell Gbe Controller Driver */
-#endif
 #define CONFIG_ENV_OVERWRITE	/* ethaddr can be reprogrammed */
 #define CONFIG_ARP_TIMEOUT	200
 #define CONFIG_NET_RETRY_COUNT	50
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index d241eea..b67b77a 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -65,6 +65,7 @@
 	MVEBU_SOC_AXP,
 	MVEBU_SOC_A375,
 	MVEBU_SOC_A38X,
+	MVEBU_SOC_MSYS,
 	MVEBU_SOC_UNKNOWN,
 };
 
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 0900e40..1d30276 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -18,6 +18,9 @@
 #define SOC_88F6810_ID		0x6810
 #define SOC_88F6820_ID		0x6820
 #define SOC_88F6828_ID		0x6828
+#define SOC_98DX3236_ID		0xf410
+#define SOC_98DX3336_ID		0xf400
+#define SOC_98DX4251_ID		0xfc00
 
 /* A375 revisions */
 #define MV_88F67XX_A0_ID	0x3
@@ -139,6 +142,7 @@
 #define BOOT_DEV_SEL_MASK	(0x3f << BOOT_DEV_SEL_OFFS)
 
 #define BOOT_FROM_UART		0x28
+#define BOOT_FROM_UART_ALT	0x3f
 #define BOOT_FROM_SPI		0x32
 #define BOOT_FROM_MMC		0x30
 #define BOOT_FROM_MMC_ALT	0x31
diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c
index 3cf02a5..a72a769 100644
--- a/arch/arm/mach-mvebu/spl.c
+++ b/arch/arm/mach-mvebu/spl.c
@@ -42,6 +42,9 @@
 		return BOOT_DEVICE_MMC1;
 #endif
 	case BOOT_FROM_UART:
+#ifdef BOOT_FROM_UART_ALT
+	case BOOT_FROM_UART_ALT:
+#endif
 		return BOOT_DEVICE_UART;
 	case BOOT_FROM_SPI:
 	default:
diff --git a/board/solidrun/clearfog/README b/board/solidrun/clearfog/README
index 2cfa5bf..ef1e3bf 100644
--- a/board/solidrun/clearfog/README
+++ b/board/solidrun/clearfog/README
@@ -16,3 +16,23 @@
 
 Please use the correct device node for your setup instead
 of "/dev/sdX" here!
+
+Boot from UART:
+---------------
+
+Connect the on-board micro-USB (CF Pro: CON11, CF Base: CON5)
+to your host.
+
+Set the SW1 DIP switches to UART boot (0: OFF, 1: ON):
+
+  ClearFog Base: 01001
+  ClearFog Pro:  11110
+
+Run the following command to initiate U-Boot download:
+
+  ./tools/kwboot -b u-boot-spl.kwb /dev/ttyUSBX
+
+Use the correct UART device node for /dev/ttyUSBX.
+
+When download finishes start your favorite terminal emulator
+on /dev/ttyUSBX.
diff --git a/board/theadorable/MAINTAINERS b/board/theadorable/MAINTAINERS
index 5ae6b64..1e8df93 100644
--- a/board/theadorable/MAINTAINERS
+++ b/board/theadorable/MAINTAINERS
@@ -4,4 +4,3 @@
 F:	board/theadorable/
 F:	include/configs/theadorable.h
 F:	configs/theadorable_debug_defconfig
-F:	configs/theadorable_defconfig
diff --git a/cmd/gpt.c b/cmd/gpt.c
index 638aa19..d4406e3 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -190,10 +190,9 @@
 static struct disk_part *allocate_disk_part(disk_partition_t *info, int partnum)
 {
 	struct disk_part *newpart;
-	newpart = malloc(sizeof(*newpart));
+	newpart = calloc(1, sizeof(struct disk_part));
 	if (!newpart)
 		return ERR_PTR(-ENOMEM);
-	memset(newpart, '\0', sizeof(newpart));
 
 	newpart->gpt_part_info.start = info->start;
 	newpart->gpt_part_info.size = info->size;
diff --git a/configs/clearfog_defconfig b/configs/clearfog_defconfig
index 580eaf3..5eceacf 100644
--- a/configs/clearfog_defconfig
+++ b/configs/clearfog_defconfig
@@ -35,8 +35,8 @@
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_MV=y
 CONFIG_SPI_FLASH=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
 CONFIG_PCI=y
 CONFIG_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_CLOCK=250000000
diff --git a/configs/controlcenterdc_defconfig b/configs/controlcenterdc_defconfig
index 836e00b..04f622a 100644
--- a/configs/controlcenterdc_defconfig
+++ b/configs/controlcenterdc_defconfig
@@ -46,8 +46,8 @@
 CONFIG_MMC_SDHCI_MV=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
 CONFIG_SCSI=y
 CONFIG_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_CLOCK=250000000
diff --git a/configs/db-88f6820-amc_defconfig b/configs/db-88f6820-amc_defconfig
index 3074994..e73d883 100644
--- a/configs/db-88f6820-amc_defconfig
+++ b/configs/db-88f6820-amc_defconfig
@@ -47,8 +47,8 @@
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
 CONFIG_PCI=y
 CONFIG_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_CLOCK=200000000
diff --git a/configs/db-88f6820-gp_defconfig b/configs/db-88f6820-gp_defconfig
index 9d1771d..d639925 100644
--- a/configs/db-88f6820-gp_defconfig
+++ b/configs/db-88f6820-gp_defconfig
@@ -45,8 +45,8 @@
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
 CONFIG_PCI=y
 CONFIG_SCSI=y
 CONFIG_DEBUG_UART_BASE=0xd0012000
diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig
index 9458f8c..03035d1 100644
--- a/configs/db-mv784mp-gp_defconfig
+++ b/configs/db-mv784mp-gp_defconfig
@@ -44,8 +44,8 @@
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
 CONFIG_PCI=y
 CONFIG_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_CLOCK=250000000
diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig
index 96bdbeb..f05ddd0 100644
--- a/configs/ds414_defconfig
+++ b/configs/ds414_defconfig
@@ -38,8 +38,8 @@
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
 CONFIG_PCI=y
 CONFIG_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_CLOCK=250000000
diff --git a/configs/maxbcm_defconfig b/configs/maxbcm_defconfig
index 131d5e1..5efaff3 100644
--- a/configs/maxbcm_defconfig
+++ b/configs/maxbcm_defconfig
@@ -32,8 +32,8 @@
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
 CONFIG_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_CLOCK=250000000
 CONFIG_DEBUG_UART_SHIFT=2
diff --git a/configs/theadorable_debug_defconfig b/configs/theadorable_debug_defconfig
index a394979..0b4025c 100644
--- a/configs/theadorable_debug_defconfig
+++ b/configs/theadorable_debug_defconfig
@@ -51,8 +51,8 @@
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
 CONFIG_PCI=y
 CONFIG_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_CLOCK=250000000
diff --git a/configs/theadorable_defconfig b/configs/theadorable_defconfig
deleted file mode 100644
index 0639f81..0000000
--- a/configs/theadorable_defconfig
+++ /dev/null
@@ -1,54 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_MVEBU=y
-CONFIG_SPL_LIBCOMMON_SUPPORT=y
-CONFIG_SPL_LIBGENERIC_SUPPORT=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
-CONFIG_TARGET_THEADORABLE=y
-CONFIG_SPL_SERIAL_SUPPORT=y
-CONFIG_SPL_SPI_FLASH_SUPPORT=y
-CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_VIDEO=y
-CONFIG_DEFAULT_DEVICE_TREE="armada-xp-theadorable"
-CONFIG_DEBUG_UART=y
-# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_FIT=y
-CONFIG_BOOTDELAY=3
-# CONFIG_CONSOLE_MUX is not set
-CONFIG_SYS_CONSOLE_INFO_QUIET=y
-# CONFIG_DISPLAY_BOARDINFO is not set
-CONFIG_SPL=y
-CONFIG_SPL_I2C_SUPPORT=y
-CONFIG_HUSH_PARSER=y
-CONFIG_CMD_BOOTZ=y
-# CONFIG_CMD_IMLS is not set
-# CONFIG_CMD_FLASH is not set
-CONFIG_CMD_I2C=y
-CONFIG_CMD_SF=y
-# CONFIG_CMD_SETEXPR is not set
-# CONFIG_CMD_NET is not set
-# CONFIG_CMD_NFS is not set
-CONFIG_CMD_BMP=y
-CONFIG_CMD_CACHE=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_EXT2=y
-CONFIG_CMD_EXT4=y
-CONFIG_CMD_FAT=y
-CONFIG_CMD_FS_GENERIC=y
-CONFIG_EFI_PARTITION=y
-# CONFIG_PARTITION_UUIDS is not set
-# CONFIG_SPL_PARTITION_UUIDS is not set
-CONFIG_SPL_OF_TRANSLATE=y
-CONFIG_FPGA_ALTERA=y
-CONFIG_DM_GPIO=y
-# CONFIG_MMC is not set
-CONFIG_SPI_FLASH=y
-CONFIG_SPI_FLASH_MACRONIX=y
-CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_DEBUG_UART_BASE=0xd0012000
-CONFIG_DEBUG_UART_CLOCK=250000000
-CONFIG_DEBUG_UART_SHIFT=2
-CONFIG_SYS_NS16550=y
-CONFIG_VIDEO_MVEBU=y
-# CONFIG_VIDEO_SW_CURSOR is not set
-CONFIG_REGEX=y
-CONFIG_LIB_RAND=y
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index a3834ac..870cfd51 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -33,8 +33,8 @@
 CONFIG_ATSHA204A=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_MV=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_GIGE=y
+CONFIG_MVNETA=y
 CONFIG_DEBUG_UART_BASE=0xd0012000
 CONFIG_DEBUG_UART_CLOCK=250000000
 CONFIG_DEBUG_UART_SHIFT=2
diff --git a/drivers/core/read.c b/drivers/core/read.c
index 065589a..eacf171 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -81,6 +81,17 @@
 	return ofnode_stringlist_search(dev_ofnode(dev), property, string);
 }
 
+int dev_read_string_index(struct udevice *dev, const char *propname, int index,
+			  const char **outp)
+{
+	return ofnode_read_string_index(dev_ofnode(dev), propname, index, outp);
+}
+
+int dev_read_string_count(struct udevice *dev, const char *propname)
+{
+	return ofnode_read_string_count(dev_ofnode(dev), propname);
+}
+
 int dev_read_phandle_with_args(struct udevice *dev, const char *list_name,
 				const char *cells_name, int cell_count,
 				int index,
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 6de927b..fa24c52 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -136,6 +136,7 @@
 config MMC_OMAP_HS
 	bool "TI OMAP High Speed Multimedia Card Interface support"
 	select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR
+	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,
@@ -162,12 +163,13 @@
 	  Support for the on-chip SDHI host controller on SuperH/Renesas ARM SoCs platform
 
 config MMC_UNIPHIER
-	bool "UniPhier SD/MMC Host Controller support"
-	depends on ARCH_UNIPHIER
+	bool "UniPhier/RCar SD/MMC Host Controller support"
+	depends on ARCH_UNIPHIER || ARCH_RMOBILE
 	depends on BLK && DM_MMC
 	depends on OF_CONTROL
 	help
-	  This selects support for the SD/MMC Host Controller on UniPhier SoCs.
+	  This selects support for the Matsushita SD/MMC Host Controller on
+	  SocioNext UniPhier and Renesas RCar SoCs.
 
 config MMC_SANDBOX
 	bool "Sandbox MMC support"
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 721b75f..0786ad0 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -132,8 +132,43 @@
 #define UNIPHIER_SD_CAP_NONREMOVABLE	BIT(0)	/* Nonremovable e.g. eMMC */
 #define UNIPHIER_SD_CAP_DMA_INTERNAL	BIT(1)	/* have internal DMA engine */
 #define UNIPHIER_SD_CAP_DIV1024		BIT(2)	/* divisor 1024 is available */
+#define UNIPHIER_SD_CAP_64BIT		BIT(3)	/* Controller is 64bit */
 };
 
+static u64 uniphier_sd_readq(struct uniphier_sd_priv *priv, const u32 reg)
+{
+	if (priv->caps & UNIPHIER_SD_CAP_64BIT)
+		return readq(priv->regbase + (reg << 1));
+	else
+		return readq(priv->regbase + reg);
+}
+
+static void uniphier_sd_writeq(struct uniphier_sd_priv *priv,
+			       const u64 val, const u32 reg)
+{
+	if (priv->caps & UNIPHIER_SD_CAP_64BIT)
+		writeq(val, priv->regbase + (reg << 1));
+	else
+		writeq(val, priv->regbase + reg);
+}
+
+static u32 uniphier_sd_readl(struct uniphier_sd_priv *priv, const u32 reg)
+{
+	if (priv->caps & UNIPHIER_SD_CAP_64BIT)
+		return readl(priv->regbase + (reg << 1));
+	else
+		return readl(priv->regbase + reg);
+}
+
+static void uniphier_sd_writel(struct uniphier_sd_priv *priv,
+			       const u32 val, const u32 reg)
+{
+	if (priv->caps & UNIPHIER_SD_CAP_64BIT)
+		writel(val, priv->regbase + (reg << 1));
+	else
+		writel(val, priv->regbase + reg);
+}
+
 static dma_addr_t __dma_map_single(void *ptr, size_t size,
 				   enum dma_data_direction dir)
 {
@@ -157,7 +192,7 @@
 static int uniphier_sd_check_error(struct udevice *dev)
 {
 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
-	u32 info2 = readl(priv->regbase + UNIPHIER_SD_INFO2);
+	u32 info2 = uniphier_sd_readl(priv, UNIPHIER_SD_INFO2);
 
 	if (info2 & UNIPHIER_SD_INFO2_ERR_RTO) {
 		/*
@@ -195,7 +230,7 @@
 	long wait = 1000000;
 	int ret;
 
-	while (!(readl(priv->regbase + reg) & flag)) {
+	while (!(uniphier_sd_readl(priv, reg) & flag)) {
 		if (wait-- < 0) {
 			dev_err(dev, "timeout\n");
 			return -ETIMEDOUT;
@@ -227,15 +262,40 @@
 	 * Clear the status flag _before_ read the buffer out because
 	 * UNIPHIER_SD_INFO2_BRE is edge-triggered, not level-triggered.
 	 */
-	writel(0, priv->regbase + UNIPHIER_SD_INFO2);
+	uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
 
 	if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
-		for (i = 0; i < blocksize / 4; i++)
-			*(*pbuf)++ = readl(priv->regbase + UNIPHIER_SD_BUF);
+		if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
+			for (i = 0; i < blocksize / 8; i++) {
+				u64 data;
+				data = uniphier_sd_readq(priv,
+							 UNIPHIER_SD_BUF);
+				*(*pbuf)++ = data;
+				*(*pbuf)++ = data >> 32;
+			}
+		} else {
+			for (i = 0; i < blocksize / 4; i++) {
+				u32 data;
+				data = uniphier_sd_readl(priv, UNIPHIER_SD_BUF);
+				*(*pbuf)++ = data;
+			}
+		}
 	} else {
-		for (i = 0; i < blocksize / 4; i++)
-			put_unaligned(readl(priv->regbase + UNIPHIER_SD_BUF),
-				      (*pbuf)++);
+		if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
+			for (i = 0; i < blocksize / 8; i++) {
+				u64 data;
+				data = uniphier_sd_readq(priv,
+							 UNIPHIER_SD_BUF);
+				put_unaligned(data, (*pbuf)++);
+				put_unaligned(data >> 32, (*pbuf)++);
+			}
+		} else {
+			for (i = 0; i < blocksize / 4; i++) {
+				u32 data;
+				data = uniphier_sd_readl(priv, UNIPHIER_SD_BUF);
+				put_unaligned(data, (*pbuf)++);
+			}
+		}
 	}
 
 	return 0;
@@ -253,15 +313,37 @@
 	if (ret)
 		return ret;
 
-	writel(0, priv->regbase + UNIPHIER_SD_INFO2);
+	uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
 
 	if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
-		for (i = 0; i < blocksize / 4; i++)
-			writel(*(*pbuf)++, priv->regbase + UNIPHIER_SD_BUF);
+		if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
+			for (i = 0; i < blocksize / 8; i++) {
+				u64 data = *(*pbuf)++;
+				data |= (u64)*(*pbuf)++ << 32;
+				uniphier_sd_writeq(priv, data,
+						   UNIPHIER_SD_BUF);
+			}
+		} else {
+			for (i = 0; i < blocksize / 4; i++) {
+				uniphier_sd_writel(priv, *(*pbuf)++,
+						   UNIPHIER_SD_BUF);
+			}
+		}
 	} else {
-		for (i = 0; i < blocksize / 4; i++)
-			writel(get_unaligned((*pbuf)++),
-			       priv->regbase + UNIPHIER_SD_BUF);
+		if (priv->caps & UNIPHIER_SD_CAP_64BIT) {
+			for (i = 0; i < blocksize / 8; i++) {
+				u64 data = get_unaligned((*pbuf)++);
+				data |= (u64)get_unaligned((*pbuf)++) << 32;
+				uniphier_sd_writeq(priv, data,
+						   UNIPHIER_SD_BUF);
+			}
+		} else {
+			for (i = 0; i < blocksize / 4; i++) {
+				u32 data = get_unaligned((*pbuf)++);
+				uniphier_sd_writel(priv, data,
+						   UNIPHIER_SD_BUF);
+			}
+		}
 	}
 
 	return 0;
@@ -292,22 +374,22 @@
 {
 	u32 tmp;
 
-	writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1);
-	writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2);
+	uniphier_sd_writel(priv, 0, UNIPHIER_SD_DMA_INFO1);
+	uniphier_sd_writel(priv, 0, UNIPHIER_SD_DMA_INFO2);
 
 	/* enable DMA */
-	tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE);
+	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_EXTMODE);
 	tmp |= UNIPHIER_SD_EXTMODE_DMA_EN;
-	writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_EXTMODE);
 
-	writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_L);
+	uniphier_sd_writel(priv, dma_addr & U32_MAX, UNIPHIER_SD_DMA_ADDR_L);
 
 	/* suppress the warning "right shift count >= width of type" */
 	dma_addr >>= min_t(int, 32, 8 * sizeof(dma_addr));
 
-	writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_H);
+	uniphier_sd_writel(priv, dma_addr & U32_MAX, UNIPHIER_SD_DMA_ADDR_H);
 
-	writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL);
+	uniphier_sd_writel(priv, UNIPHIER_SD_DMA_CTL_START, UNIPHIER_SD_DMA_CTL);
 }
 
 static int uniphier_sd_dma_wait_for_irq(struct udevice *dev, u32 flag,
@@ -316,7 +398,7 @@
 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
 	long wait = 1000000 + 10 * blocks;
 
-	while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) {
+	while (!(uniphier_sd_readl(priv, UNIPHIER_SD_DMA_INFO1) & flag)) {
 		if (wait-- < 0) {
 			dev_err(dev, "timeout during DMA\n");
 			return -ETIMEDOUT;
@@ -325,7 +407,7 @@
 		udelay(10);
 	}
 
-	if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) {
+	if (uniphier_sd_readl(priv, UNIPHIER_SD_DMA_INFO2)) {
 		dev_err(dev, "error during DMA\n");
 		return -EIO;
 	}
@@ -343,7 +425,7 @@
 	u32 poll_flag, tmp;
 	int ret;
 
-	tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE);
+	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_DMA_MODE);
 
 	if (data->flags & MMC_DATA_READ) {
 		buf = data->dest;
@@ -357,7 +439,7 @@
 		tmp &= ~UNIPHIER_SD_DMA_MODE_DIR_RD;
 	}
 
-	writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_DMA_MODE);
 
 	dma_addr = __dma_map_single(buf, len, dir);
 
@@ -396,27 +478,27 @@
 	int ret;
 	u32 tmp;
 
-	if (readl(priv->regbase + UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) {
+	if (uniphier_sd_readl(priv, UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) {
 		dev_err(dev, "command busy\n");
 		return -EBUSY;
 	}
 
 	/* clear all status flags */
-	writel(0, priv->regbase + UNIPHIER_SD_INFO1);
-	writel(0, priv->regbase + UNIPHIER_SD_INFO2);
+	uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO1);
+	uniphier_sd_writel(priv, 0, UNIPHIER_SD_INFO2);
 
 	/* disable DMA once */
-	tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE);
+	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_EXTMODE);
 	tmp &= ~UNIPHIER_SD_EXTMODE_DMA_EN;
-	writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_EXTMODE);
 
-	writel(cmd->cmdarg, priv->regbase + UNIPHIER_SD_ARG);
+	uniphier_sd_writel(priv, cmd->cmdarg, UNIPHIER_SD_ARG);
 
 	tmp = cmd->cmdidx;
 
 	if (data) {
-		writel(data->blocksize, priv->regbase + UNIPHIER_SD_SIZE);
-		writel(data->blocks, priv->regbase + UNIPHIER_SD_SECCNT);
+		uniphier_sd_writel(priv, data->blocksize, UNIPHIER_SD_SIZE);
+		uniphier_sd_writel(priv, data->blocks, UNIPHIER_SD_SECCNT);
 
 		/* Do not send CMD12 automatically */
 		tmp |= UNIPHIER_SD_CMD_NOSTOP | UNIPHIER_SD_CMD_DATA;
@@ -457,7 +539,7 @@
 
 	dev_dbg(dev, "sending CMD%d (SD_CMD=%08x, SD_ARG=%08x)\n",
 		cmd->cmdidx, tmp, cmd->cmdarg);
-	writel(tmp, priv->regbase + UNIPHIER_SD_CMD);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CMD);
 
 	ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO1,
 				       UNIPHIER_SD_INFO1_RSP);
@@ -465,10 +547,10 @@
 		return ret;
 
 	if (cmd->resp_type & MMC_RSP_136) {
-		u32 rsp_127_104 = readl(priv->regbase + UNIPHIER_SD_RSP76);
-		u32 rsp_103_72 = readl(priv->regbase + UNIPHIER_SD_RSP54);
-		u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32);
-		u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10);
+		u32 rsp_127_104 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP76);
+		u32 rsp_103_72 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP54);
+		u32 rsp_71_40 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP32);
+		u32 rsp_39_8 = uniphier_sd_readl(priv, UNIPHIER_SD_RSP10);
 
 		cmd->response[0] = ((rsp_127_104 & 0x00ffffff) << 8) |
 				   ((rsp_103_72  & 0xff000000) >> 24);
@@ -479,7 +561,7 @@
 		cmd->response[3] = (rsp_39_8     & 0xffffff)   << 8;
 	} else {
 		/* bit 39-8 */
-		cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10);
+		cmd->response[0] = uniphier_sd_readl(priv, UNIPHIER_SD_RSP10);
 	}
 
 	if (data) {
@@ -518,10 +600,10 @@
 		return -EINVAL;
 	}
 
-	tmp = readl(priv->regbase + UNIPHIER_SD_OPTION);
+	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_OPTION);
 	tmp &= ~UNIPHIER_SD_OPTION_WIDTH_MASK;
 	tmp |= val;
-	writel(tmp, priv->regbase + UNIPHIER_SD_OPTION);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_OPTION);
 
 	return 0;
 }
@@ -531,12 +613,12 @@
 {
 	u32 tmp;
 
-	tmp = readl(priv->regbase + UNIPHIER_SD_IF_MODE);
+	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_IF_MODE);
 	if (mmc->ddr_mode)
 		tmp |= UNIPHIER_SD_IF_MODE_DDR;
 	else
 		tmp &= ~UNIPHIER_SD_IF_MODE_DDR;
-	writel(tmp, priv->regbase + UNIPHIER_SD_IF_MODE);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_IF_MODE);
 }
 
 static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv,
@@ -573,21 +655,21 @@
 	else
 		val = UNIPHIER_SD_CLKCTL_DIV1024;
 
-	tmp = readl(priv->regbase + UNIPHIER_SD_CLKCTL);
+	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_CLKCTL);
 	if (tmp & UNIPHIER_SD_CLKCTL_SCLKEN &&
 	    (tmp & UNIPHIER_SD_CLKCTL_DIV_MASK) == val)
 		return;
 
 	/* stop the clock before changing its rate to avoid a glitch signal */
 	tmp &= ~UNIPHIER_SD_CLKCTL_SCLKEN;
-	writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL);
 
 	tmp &= ~UNIPHIER_SD_CLKCTL_DIV_MASK;
 	tmp |= val | UNIPHIER_SD_CLKCTL_OFFEN;
-	writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL);
 
 	tmp |= UNIPHIER_SD_CLKCTL_SCLKEN;
-	writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_CLKCTL);
 
 	udelay(1000);
 }
@@ -617,7 +699,7 @@
 	if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE)
 		return 1;
 
-	return !!(readl(priv->regbase + UNIPHIER_SD_INFO1) &
+	return !!(uniphier_sd_readl(priv, UNIPHIER_SD_INFO1) &
 		  UNIPHIER_SD_INFO1_CD);
 }
 
@@ -632,28 +714,28 @@
 	u32 tmp;
 
 	/* soft reset of the host */
-	tmp = readl(priv->regbase + UNIPHIER_SD_SOFT_RST);
+	tmp = uniphier_sd_readl(priv, UNIPHIER_SD_SOFT_RST);
 	tmp &= ~UNIPHIER_SD_SOFT_RST_RSTX;
-	writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_SOFT_RST);
 	tmp |= UNIPHIER_SD_SOFT_RST_RSTX;
-	writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST);
+	uniphier_sd_writel(priv, tmp, UNIPHIER_SD_SOFT_RST);
 
 	/* FIXME: implement eMMC hw_reset */
 
-	writel(UNIPHIER_SD_STOP_SEC, priv->regbase + UNIPHIER_SD_STOP);
+	uniphier_sd_writel(priv, UNIPHIER_SD_STOP_SEC, UNIPHIER_SD_STOP);
 
 	/*
 	 * Connected to 32bit AXI.
 	 * This register dropped backward compatibility at version 0x10.
 	 * Write an appropriate value depending on the IP version.
 	 */
-	writel(priv->version >= 0x10 ? 0x00000101 : 0x00000000,
-	       priv->regbase + UNIPHIER_SD_HOST_MODE);
+	uniphier_sd_writel(priv, priv->version >= 0x10 ? 0x00000101 : 0x00000000,
+			   UNIPHIER_SD_HOST_MODE);
 
 	if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL) {
-		tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE);
+		tmp = uniphier_sd_readl(priv, UNIPHIER_SD_DMA_MODE);
 		tmp |= UNIPHIER_SD_DMA_MODE_ADDR_INC;
-		writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE);
+		uniphier_sd_writel(priv, tmp, UNIPHIER_SD_DMA_MODE);
 	}
 }
 
@@ -669,6 +751,7 @@
 	struct uniphier_sd_plat *plat = dev_get_platdata(dev);
 	struct uniphier_sd_priv *priv = dev_get_priv(dev);
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	const u32 quirks = dev_get_driver_data(dev);
 	fdt_addr_t base;
 	struct clk clk;
 	int ret;
@@ -720,18 +803,22 @@
 		return -EINVAL;
 	}
 
+	if (quirks) {
+		priv->caps = quirks;
+	} else {
+		priv->version = uniphier_sd_readl(priv, UNIPHIER_SD_VERSION) &
+							UNIPHIER_SD_VERSION_IP;
+		dev_dbg(dev, "version %x\n", priv->version);
+		if (priv->version >= 0x10) {
+			priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL;
+			priv->caps |= UNIPHIER_SD_CAP_DIV1024;
+		}
+	}
+
 	if (fdt_get_property(gd->fdt_blob, dev_of_offset(dev), "non-removable",
 			     NULL))
 		priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE;
 
-	priv->version = readl(priv->regbase + UNIPHIER_SD_VERSION) &
-							UNIPHIER_SD_VERSION_IP;
-	dev_dbg(dev, "version %x\n", priv->version);
-	if (priv->version >= 0x10) {
-		priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL;
-		priv->caps |= UNIPHIER_SD_CAP_DIV1024;
-	}
-
 	uniphier_sd_host_init(priv);
 
 	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
@@ -746,7 +833,9 @@
 }
 
 static const struct udevice_id uniphier_sd_match[] = {
-	{ .compatible = "socionext,uniphier-sdhc" },
+	{ .compatible = "renesas,sdhi-r8a7795", .data = UNIPHIER_SD_CAP_64BIT },
+	{ .compatible = "renesas,sdhi-r8a7796", .data = UNIPHIER_SD_CAP_64BIT },
+	{ .compatible = "socionext,uniphier-sdhc", .data = 0 },
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c
index b2ab439..13f64e7 100644
--- a/drivers/mtd/spi/spi_flash_ids.c
+++ b/drivers/mtd/spi/spi_flash_ids.c
@@ -92,7 +92,7 @@
 	{"s25fl016a",	   INFO(0x010214, 0x0, 64 * 1024,    32, 0) },
 	{"s25fl032a",	   INFO(0x010215, 0x0, 64 * 1024,    64, 0) },
 	{"s25fl064a",	   INFO(0x010216, 0x0, 64 * 1024,   128, 0) },
-	{"s25fl116k",	   INFO(0x014015, 0x0, 64 * 1024,   128, 0) },
+	{"s25fl116k",	   INFO(0x014015, 0x0, 64 * 1024,    32, 0) },
 	{"s25fl164k",	   INFO(0x014017, 0x0140,  64 * 1024,   128, 0) },
 	{"s25fl128p_256k", INFO(0x012018, 0x0300, 256 * 1024,    64, RD_FULL | WR_QPP) },
 	{"s25fl128p_64k",  INFO(0x012018, 0x0301,  64 * 1024,   256, RD_FULL | WR_QPP) },
@@ -101,8 +101,8 @@
 	{"s25fl128s_256k", INFO(0x012018, 0x4d00, 256 * 1024,    64, RD_FULL | WR_QPP) },
 	{"s25fl128s_64k",  INFO(0x012018, 0x4d01,  64 * 1024,   256, RD_FULL | WR_QPP) },
 	{"s25fl256s_256k", INFO(0x010219, 0x4d00, 256 * 1024,   128, RD_FULL | WR_QPP) },
-	{"s25fl256s_64k",  INFO(0x010219, 0x4d01,  64 * 1024,   512, RD_FULL | WR_QPP) },
 	{"s25fs256s_64k",  INFO6(0x010219, 0x4d0181, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) },
+	{"s25fl256s_64k",  INFO(0x010219, 0x4d01,  64 * 1024,   512, RD_FULL | WR_QPP) },
 	{"s25fs512s",      INFO6(0x010220, 0x4d0081, 128 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) },
 	{"s25fl512s_256k", INFO(0x010220, 0x4d00, 256 * 1024,   256, RD_FULL | WR_QPP) },
 	{"s25fl512s_64k",  INFO(0x010220, 0x4d01,  64 * 1024,  1024, RD_FULL | WR_QPP) },
@@ -135,6 +135,7 @@
 	{"n25q1024a",	   INFO(0x20bb21, 0x0,  64 * 1024,  2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) },
 	{"mt25qu02g",	   INFO(0x20bb22, 0x0,  64 * 1024,  4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) },
 	{"mt25ql02g",	   INFO(0x20ba22, 0x0,  64 * 1024,  4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) },
+	{"mt35xu512g",	   INFO6(0x2c5b1a, 0x104100,  128 * 1024,  512, E_FSR | SECT_4K) },
 #endif
 #ifdef CONFIG_SPI_FLASH_SST		/* SST */
 	{"sst25vf040b",	   INFO(0xbf258d, 0x0,	64 * 1024,     8, SECT_4K | SST_WR) },
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5ceea44..d67927c 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -159,6 +159,14 @@
 	help
 	  This MAC is present in Andestech SoCs.
 
+config MVNETA
+	bool "Marvell Armada 385 network interface support"
+	depends on ARMADA_XP || ARMADA_38X
+	select PHYLIB
+	help
+	  This driver supports the network interface units in the
+	  Marvell ARMADA XP and 38X SoCs
+
 config MVPP2
 	bool "Marvell Armada 375/7K/8K network interface support"
 	depends on ARMADA_375 || ARMADA_8K
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index c82a936..2cfade1 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -151,6 +151,19 @@
 	features for REGULATOR PALMAS and the family of PALMAS PMICs.
 	The driver implements get/set api for: value and enable.
 
+config DM_REGULATOR_PBIAS
+	bool "Enable driver for PBIAS regulator"
+	depends on DM_REGULATOR
+	select REGMAP
+	select SYSCON
+	---help---
+	This enables implementation of driver-model regulator uclass
+	features for pseudo-regulator PBIAS found in the OMAP SOCs.
+	This pseudo-regulator is used to provide a BIAS voltage to MMC1
+	signal pads and must be configured properly during a voltage switch.
+	Voltage switching is required by some operating modes of SDcards and
+	eMMC.
+
 config DM_REGULATOR_LP873X
 	bool "Enable driver for LP873X PMIC regulators"
         depends on PMIC_LP873X
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 18fb870..6c149a9 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -18,5 +18,6 @@
 obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
 obj-$(CONFIG_REGULATOR_TPS65090) += tps65090_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_PALMAS) += palmas_regulator.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_PBIAS) += pbias_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o
diff --git a/drivers/power/regulator/pbias_regulator.c b/drivers/power/regulator/pbias_regulator.c
new file mode 100644
index 0000000..914500b
--- /dev/null
+++ b/drivers/power/regulator/pbias_regulator.c
@@ -0,0 +1,301 @@
+/*
+ * (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
+ * Jean-Jacques Hiblot <jjhiblot@ti.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <linux/bitops.h>
+#include <linux/ioport.h>
+#include <dm/read.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct pbias_reg_info {
+	u32 enable;
+	u32 enable_mask;
+	u32 disable_val;
+	u32 vmode;
+	unsigned int enable_time;
+	char *name;
+};
+
+struct pbias_priv {
+	struct regmap *regmap;
+	int offset;
+};
+
+static const struct pmic_child_info pmic_children_info[] = {
+	{ .prefix = "pbias", .driver = "pbias_regulator"},
+	{ },
+};
+
+static int pbias_write(struct udevice *dev, uint reg, const uint8_t *buff,
+		       int len)
+{
+	struct pbias_priv *priv = dev_get_priv(dev);
+	u32 val = *(u32 *)buff;
+
+	if (len != 4)
+		return -EINVAL;
+
+	return regmap_write(priv->regmap, priv->offset, val);
+}
+
+static int pbias_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+	struct pbias_priv *priv = dev_get_priv(dev);
+
+	if (len != 4)
+		return -EINVAL;
+
+	return regmap_read(priv->regmap, priv->offset, (u32 *)buff);
+}
+
+static int pbias_ofdata_to_platdata(struct udevice *dev)
+{
+	struct pbias_priv *priv = dev_get_priv(dev);
+	struct udevice *syscon;
+	struct regmap *regmap;
+	struct resource res;
+	int err;
+
+	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
+					   "syscon", &syscon);
+	if (err) {
+		error("%s: unable to find syscon device (%d)\n", __func__,
+		      err);
+		return err;
+	}
+
+	regmap = syscon_get_regmap(syscon);
+	if (IS_ERR(regmap)) {
+		error("%s: unable to find regmap (%ld)\n", __func__,
+		      PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+	priv->regmap = regmap;
+
+	err = dev_read_resource(dev, 0, &res);
+	if (err) {
+		error("%s: unable to find offset (%d)\n", __func__, err);
+		return err;
+	}
+	priv->offset = res.start;
+
+	return 0;
+}
+
+static int pbias_bind(struct udevice *dev)
+{
+	int children;
+
+	children = pmic_bind_children(dev, dev->node, pmic_children_info);
+	if (!children)
+		debug("%s: %s - no child found\n", __func__, dev->name);
+
+	return 0;
+}
+
+static struct dm_pmic_ops pbias_ops = {
+	.read = pbias_read,
+	.write = pbias_write,
+};
+
+static const struct udevice_id pbias_ids[] = {
+	{ .compatible = "ti,pbias-dra7" },
+	{ }
+};
+
+U_BOOT_DRIVER(pbias_pmic) = {
+	.name = "pbias_pmic",
+	.id = UCLASS_PMIC,
+	.of_match = pbias_ids,
+	.bind = pbias_bind,
+	.ops = &pbias_ops,
+	.ofdata_to_platdata = pbias_ofdata_to_platdata,
+	.priv_auto_alloc_size = sizeof(struct pbias_priv),
+};
+
+static const struct pbias_reg_info pbias_mmc_omap2430 = {
+	.enable = BIT(1),
+	.enable_mask = BIT(1),
+	.vmode = BIT(0),
+	.disable_val = 0,
+	.enable_time = 100,
+	.name = "pbias_mmc_omap2430"
+};
+
+static const struct pbias_reg_info pbias_sim_omap3 = {
+	.enable = BIT(9),
+	.enable_mask = BIT(9),
+	.vmode = BIT(8),
+	.enable_time = 100,
+	.name = "pbias_sim_omap3"
+};
+
+static const struct pbias_reg_info pbias_mmc_omap4 = {
+	.enable = BIT(26) | BIT(22),
+	.enable_mask = BIT(26) | BIT(25) | BIT(22),
+	.disable_val = BIT(25),
+	.vmode = BIT(21),
+	.enable_time = 100,
+	.name = "pbias_mmc_omap4"
+};
+
+static const struct pbias_reg_info pbias_mmc_omap5 = {
+	.enable = BIT(27) | BIT(26),
+	.enable_mask = BIT(27) | BIT(25) | BIT(26),
+	.disable_val = BIT(25),
+	.vmode = BIT(21),
+	.enable_time = 100,
+	.name = "pbias_mmc_omap5"
+};
+
+static const struct pbias_reg_info *pbias_reg_infos[] = {
+	&pbias_mmc_omap5,
+	&pbias_mmc_omap4,
+	&pbias_sim_omap3,
+	&pbias_mmc_omap2430,
+	NULL
+};
+
+static int pbias_regulator_probe(struct udevice *dev)
+{
+	const struct pbias_reg_info **p = pbias_reg_infos;
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	while (*p) {
+		int rc;
+
+		rc = dev_read_stringlist_search(dev, "regulator-name",
+						(*p)->name);
+		if (rc >= 0) {
+			debug("found regulator %s\n", (*p)->name);
+			break;
+		} else if (rc != -ENODATA) {
+			return rc;
+		}
+		p++;
+	}
+	if (!*p) {
+		int i = 0;
+		const char *s;
+
+		debug("regulator ");
+		while (dev_read_string_index(dev, "regulator-name", i++, &s) >= 0)
+			debug("%s'%s' ", (i > 1) ? ", " : "", s);
+		debug("%s not supported\n", (i > 2) ? "are" : "is");
+		return -EINVAL;
+	}
+
+	uc_pdata->type = REGULATOR_TYPE_OTHER;
+	dev->priv = (void *)*p;
+
+	return 0;
+}
+
+static int pbias_regulator_get_value(struct udevice *dev)
+{
+	const struct pbias_reg_info *p = dev_get_priv(dev);
+	int rc;
+	u32 reg;
+
+	rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
+	if (rc)
+		return rc;
+
+	debug("%s voltage id %s\n", p->name,
+	      (reg & p->vmode) ? "3.0v" : "1.8v");
+	return (reg & p->vmode) ? 3000000 : 1800000;
+}
+
+static int pbias_regulator_set_value(struct udevice *dev, int uV)
+{
+	const struct pbias_reg_info *p = dev_get_priv(dev);
+	int rc;
+	u32 reg;
+
+	debug("Setting %s voltage to %s\n", p->name,
+	      (reg & p->vmode) ? "3.0v" : "1.8v");
+
+	rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
+	if (rc)
+		return rc;
+
+	if (uV == 3000000)
+		reg |= p->vmode;
+	else if (uV == 1800000)
+		reg &= ~p->vmode;
+	else
+		return -EINVAL;
+
+	return pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
+}
+
+static int pbias_regulator_get_enable(struct udevice *dev)
+{
+	const struct pbias_reg_info *p = dev_get_priv(dev);
+	int rc;
+	u32 reg;
+
+	rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
+	if (rc)
+		return rc;
+
+	debug("%s id %s\n", p->name,
+	      (reg & p->enable_mask) == (p->disable_val) ? "on" : "off");
+
+	return (reg & p->enable_mask) == (p->disable_val);
+}
+
+static int pbias_regulator_set_enable(struct udevice *dev, bool enable)
+{
+	const struct pbias_reg_info *p = dev_get_priv(dev);
+	int rc;
+	u32 reg;
+
+	debug("Turning %s %s\n", enable ? "on" : "off", p->name);
+
+	rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
+	if (rc)
+		return rc;
+
+	reg &= ~p->enable_mask;
+	if (enable)
+		reg |= p->enable;
+	else
+		reg |= p->disable_val;
+
+	rc = pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
+	if (rc)
+		return rc;
+
+	if (enable)
+		udelay(p->enable_time);
+
+	return 0;
+}
+
+static const struct dm_regulator_ops pbias_regulator_ops = {
+	.get_value  = pbias_regulator_get_value,
+	.set_value  = pbias_regulator_set_value,
+	.get_enable = pbias_regulator_get_enable,
+	.set_enable = pbias_regulator_set_enable,
+};
+
+U_BOOT_DRIVER(pbias_regulator) = {
+	.name = "pbias_regulator",
+	.id = UCLASS_REGULATOR,
+	.ops = &pbias_regulator_ops,
+	.probe = pbias_regulator_probe,
+};
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 1dfa89a..0f3f7d9 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -14,6 +14,7 @@
 #include <dm.h>
 #include <errno.h>
 #include <watchdog.h>
+#include <wait_bit.h>
 #include "fsl_qspi.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -663,22 +664,20 @@
 	tx_size = (len > TX_BUFFER_SIZE) ?
 		TX_BUFFER_SIZE : len;
 
-	size = tx_size / 4;
-	for (i = 0; i < size; i++) {
+	size = tx_size / 16;
+	/*
+	 * There must be atleast 128bit data
+	 * available in TX FIFO for any pop operation
+	 */
+	if (tx_size % 16)
+		size++;
+	for (i = 0; i < size * 4; i++) {
 		memcpy(&data, txbuf, 4);
 		data = qspi_endian_xchg(data);
 		qspi_write32(priv->flags, &regs->tbdr, data);
 		txbuf += 4;
 	}
 
-	size = tx_size % 4;
-	if (size) {
-		data = 0;
-		memcpy(&data, txbuf, size);
-		data = qspi_endian_xchg(data);
-		qspi_write32(priv->flags, &regs->tbdr, data);
-	}
-
 	qspi_write32(priv->flags, &regs->ipcr,
 		     (seqid << QSPI_IPCR_SEQID_SHIFT) | tx_size);
 	while (qspi_read32(priv->flags, &regs->sr) & QSPI_SR_BUSY_MASK)
@@ -991,7 +990,7 @@
 	struct fsl_qspi_platdata *plat = dev_get_platdata(bus);
 	struct fsl_qspi_priv *priv = dev_get_priv(bus);
 	struct dm_spi_bus *dm_spi_bus;
-	int i;
+	int i, ret;
 
 	dm_spi_bus = bus->uclass_priv;
 
@@ -1011,6 +1010,18 @@
 	priv->flash_num = plat->flash_num;
 	priv->num_chipselect = plat->num_chipselect;
 
+	/* make sure controller is not busy anywhere */
+	ret = wait_for_bit(__func__, &priv->regs->sr,
+			   QSPI_SR_BUSY_MASK |
+			   QSPI_SR_AHB_ACC_MASK |
+			   QSPI_SR_IP_ACC_MASK,
+			   false, 100, false);
+
+	if (ret) {
+		debug("ERROR : The controller is busy\n");
+		return ret;
+	}
+
 	mcr_val = qspi_read32(priv->flags, &priv->regs->mcr);
 	qspi_write32(priv->flags, &priv->regs->mcr,
 		     QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK |
@@ -1156,10 +1167,23 @@
 	struct fsl_qspi_priv *priv;
 	struct udevice *bus;
 	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+	int ret;
 
 	bus = dev->parent;
 	priv = dev_get_priv(bus);
 
+	/* make sure controller is not busy anywhere */
+	ret = wait_for_bit(__func__, &priv->regs->sr,
+			   QSPI_SR_BUSY_MASK |
+			   QSPI_SR_AHB_ACC_MASK |
+			   QSPI_SR_IP_ACC_MASK,
+			   false, 100, false);
+
+	if (ret) {
+		debug("ERROR : The controller is busy\n");
+		return ret;
+	}
+
 	priv->cur_amba_base = priv->amba_base[slave_plat->cs];
 
 	qspi_module_disable(priv, 0);
diff --git a/drivers/spi/fsl_qspi.h b/drivers/spi/fsl_qspi.h
index 6cb3610..e468eb2 100644
--- a/drivers/spi/fsl_qspi.h
+++ b/drivers/spi/fsl_qspi.h
@@ -105,6 +105,10 @@
 #define QSPI_RBCT_RXBRD_SHIFT		8
 #define QSPI_RBCT_RXBRD_USEIPS		(1 << QSPI_RBCT_RXBRD_SHIFT)
 
+#define QSPI_SR_AHB_ACC_SHIFT		2
+#define QSPI_SR_AHB_ACC_MASK		(1 << QSPI_SR_AHB_ACC_SHIFT)
+#define QSPI_SR_IP_ACC_SHIFT		1
+#define QSPI_SR_IP_ACC_MASK		(1 << QSPI_SR_IP_ACC_SHIFT)
 #define QSPI_SR_BUSY_SHIFT		0
 #define QSPI_SR_BUSY_MASK		(1 << QSPI_SR_BUSY_SHIFT)
 
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index e1562c3..41f0cfc 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <spi.h>
 #include <linux/errno.h>
@@ -14,6 +15,8 @@
 #include <asm/arch/clock.h>
 #include <asm/mach-imx/spi.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #ifdef CONFIG_MX27
 /* i.MX27 has a completely wrong register layout and register definitions in the
  * datasheet, the correct one is in the Freescale's Linux driver */
@@ -22,10 +25,6 @@
 "See linux mxc_spi driver from Freescale for details."
 #endif
 
-static unsigned long spi_bases[] = {
-	MXC_SPI_BASE_ADDRESSES
-};
-
 __weak int board_spi_cs_gpio(unsigned bus, unsigned cs)
 {
 	return -1;
@@ -51,6 +50,7 @@
 	int		ss_pol;
 	unsigned int	max_hz;
 	unsigned int	mode;
+	struct gpio_desc ss;
 };
 
 static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave)
@@ -58,19 +58,24 @@
 	return container_of(slave, struct mxc_spi_slave, slave);
 }
 
-void spi_cs_activate(struct spi_slave *slave)
+static void mxc_spi_cs_activate(struct mxc_spi_slave *mxcs)
 {
-	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
-	if (mxcs->gpio > 0)
-		gpio_set_value(mxcs->gpio, mxcs->ss_pol);
+	if (CONFIG_IS_ENABLED(DM_SPI)) {
+		dm_gpio_set_value(&mxcs->ss, mxcs->ss_pol);
+	} else {
+		if (mxcs->gpio > 0)
+			gpio_set_value(mxcs->gpio, mxcs->ss_pol);
+	}
 }
 
-void spi_cs_deactivate(struct spi_slave *slave)
+static void mxc_spi_cs_deactivate(struct mxc_spi_slave *mxcs)
 {
-	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
-	if (mxcs->gpio > 0)
-		gpio_set_value(mxcs->gpio,
-			      !(mxcs->ss_pol));
+	if (CONFIG_IS_ENABLED(DM_SPI)) {
+		dm_gpio_set_value(&mxcs->ss, !(mxcs->ss_pol));
+	} else {
+		if (mxcs->gpio > 0)
+			gpio_set_value(mxcs->gpio, !(mxcs->ss_pol));
+	}
 }
 
 u32 get_cspi_div(u32 div)
@@ -211,10 +216,9 @@
 }
 #endif
 
-int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
+int spi_xchg_single(struct mxc_spi_slave *mxcs, unsigned int bitlen,
 	const u8 *dout, u8 *din, unsigned long flags)
 {
-	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
 	int nbytes = DIV_ROUND_UP(bitlen, 8);
 	u32 data, cnt, i;
 	struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
@@ -327,8 +331,9 @@
 
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-		void *din, unsigned long flags)
+static int mxc_spi_xfer_internal(struct mxc_spi_slave *mxcs,
+				 unsigned int bitlen, const void *dout,
+				 void *din, unsigned long flags)
 {
 	int n_bytes = DIV_ROUND_UP(bitlen, 8);
 	int n_bits;
@@ -337,11 +342,11 @@
 	u8 *p_outbuf = (u8 *)dout;
 	u8 *p_inbuf = (u8 *)din;
 
-	if (!slave)
-		return -1;
+	if (!mxcs)
+		return -EINVAL;
 
 	if (flags & SPI_XFER_BEGIN)
-		spi_cs_activate(slave);
+		mxc_spi_cs_activate(mxcs);
 
 	while (n_bytes > 0) {
 		if (n_bytes < MAX_SPI_BYTES)
@@ -351,7 +356,7 @@
 
 		n_bits = blk_size * 8;
 
-		ret = spi_xchg_single(slave, n_bits, p_outbuf, p_inbuf, 0);
+		ret = spi_xchg_single(mxcs, n_bits, p_outbuf, p_inbuf, 0);
 
 		if (ret)
 			return ret;
@@ -363,12 +368,39 @@
 	}
 
 	if (flags & SPI_XFER_END) {
-		spi_cs_deactivate(slave);
+		mxc_spi_cs_deactivate(mxcs);
 	}
 
 	return 0;
 }
 
+static int mxc_spi_claim_bus_internal(struct mxc_spi_slave *mxcs, int cs)
+{
+	struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
+	int ret;
+
+	reg_write(&regs->rxdata, 1);
+	udelay(1);
+	ret = spi_cfg_mxc(mxcs, cs);
+	if (ret) {
+		printf("mxc_spi: cannot setup SPI controller\n");
+		return ret;
+	}
+	reg_write(&regs->period, MXC_CSPIPERIOD_32KHZ);
+	reg_write(&regs->intr, 0);
+
+	return 0;
+}
+
+#ifndef CONFIG_DM_SPI
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+		void *din, unsigned long flags)
+{
+	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+
+	return mxc_spi_xfer_internal(mxcs, bitlen, dout, din, flags);
+}
+
 void spi_init(void)
 {
 }
@@ -390,6 +422,7 @@
 	if (mxcs->gpio == -1)
 		return 0;
 
+	gpio_request(mxcs->gpio, "spi-cs");
 	ret = gpio_direction_output(mxcs->gpio, !(mxcs->ss_pol));
 	if (ret) {
 		printf("mxc_spi: cannot setup gpio %d\n", mxcs->gpio);
@@ -399,6 +432,10 @@
 	return 0;
 }
 
+static unsigned long spi_bases[] = {
+	MXC_SPI_BASE_ADDRESSES
+};
+
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 			unsigned int max_hz, unsigned int mode)
 {
@@ -443,24 +480,104 @@
 
 int spi_claim_bus(struct spi_slave *slave)
 {
-	int ret;
 	struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
-	struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
 
-	reg_write(&regs->rxdata, 1);
-	udelay(1);
-	ret = spi_cfg_mxc(mxcs, slave->cs);
+	return mxc_spi_claim_bus_internal(mxcs, slave->cs);
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	/* TODO: Shut the controller down */
+}
+#else
+
+static int mxc_spi_probe(struct udevice *bus)
+{
+	struct mxc_spi_slave *plat = bus->platdata;
+	struct mxc_spi_slave *mxcs = dev_get_platdata(bus);
+	int node = dev_of_offset(bus);
+	const void *blob = gd->fdt_blob;
+	int ret;
+
+	if (gpio_request_by_name(bus, "cs-gpios", 0, &plat->ss,
+				 GPIOD_IS_OUT)) {
+		dev_err(bus, "No cs-gpios property\n");
+		return -EINVAL;
+	}
+
+	plat->base = dev_get_addr(bus);
+	if (plat->base == FDT_ADDR_T_NONE)
+		return -ENODEV;
+
+	ret = dm_gpio_set_value(&plat->ss, !(mxcs->ss_pol));
 	if (ret) {
-		printf("mxc_spi: cannot setup SPI controller\n");
+		dev_err(bus, "Setting cs error\n");
 		return ret;
 	}
-	reg_write(&regs->period, MXC_CSPIPERIOD_32KHZ);
-	reg_write(&regs->intr, 0);
+
+	mxcs->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency",
+				      20000000);
 
 	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
+static int mxc_spi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
 {
-	/* TODO: Shut the controller down */
+	struct mxc_spi_slave *mxcs = dev_get_platdata(dev->parent);
+
+
+	return mxc_spi_xfer_internal(mxcs, bitlen, dout, din, flags);
+}
+
+static int mxc_spi_claim_bus(struct udevice *dev)
+{
+	struct mxc_spi_slave *mxcs = dev_get_platdata(dev->parent);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+
+	return mxc_spi_claim_bus_internal(mxcs, slave_plat->cs);
 }
+
+static int mxc_spi_release_bus(struct udevice *dev)
+{
+	return 0;
+}
+
+static int mxc_spi_set_speed(struct udevice *bus, uint speed)
+{
+	/* Nothing to do */
+	return 0;
+}
+
+static int mxc_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct mxc_spi_slave *mxcs = dev_get_platdata(bus);
+
+	mxcs->mode = mode;
+	mxcs->ss_pol = (mode & SPI_CS_HIGH) ? 1 : 0;
+
+	return 0;
+}
+
+static const struct dm_spi_ops mxc_spi_ops = {
+	.claim_bus	= mxc_spi_claim_bus,
+	.release_bus	= mxc_spi_release_bus,
+	.xfer		= mxc_spi_xfer,
+	.set_speed	= mxc_spi_set_speed,
+	.set_mode	= mxc_spi_set_mode,
+};
+
+static const struct udevice_id mxc_spi_ids[] = {
+	{ .compatible = "fsl,imx51-ecspi" },
+	{ }
+};
+
+U_BOOT_DRIVER(mxc_spi) = {
+	.name	= "mxc_spi",
+	.id	= UCLASS_SPI,
+	.of_match = mxc_spi_ids,
+	.ops	= &mxc_spi_ops,
+	.platdata_auto_alloc_size = sizeof(struct mxc_spi_slave),
+	.probe	= mxc_spi_probe,
+};
+#endif
diff --git a/include/configs/mvebu_armada-37xx.h b/include/configs/mvebu_armada-37xx.h
index 66c7001..1b2e0d7 100644
--- a/include/configs/mvebu_armada-37xx.h
+++ b/include/configs/mvebu_armada-37xx.h
@@ -84,7 +84,6 @@
 /*
  * Ethernet Driver configuration
  */
-#define CONFIG_MVNETA		/* Enable Marvell Gbe Controller Driver */
 #define CONFIG_ENV_OVERWRITE	/* ethaddr can be reprogrammed */
 #define CONFIG_ARP_TIMEOUT	200
 #define CONFIG_NET_RETRY_COUNT	50
diff --git a/include/dm/read.h b/include/dm/read.h
index e7f7125..8114037 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -166,6 +166,29 @@
 			  const char *string);
 
 /**
+ * dev_read_string_index() - obtain an indexed string from a string list
+ *
+ * @dev: device to examine
+ * @propname: name of the property containing the string list
+ * @index: index of the string to return
+ * @out: return location for the string
+ *
+ * @return:
+ *   length of string, if found or -ve error value if not found
+ */
+int dev_read_string_index(struct udevice *dev, const char *propname, int index,
+			  const char **outp);
+
+/**
+ * dev_read_string_count() - find the number of strings in a string list
+ *
+ * @dev: device to examine
+ * @propname: name of the property containing the string list
+ * @return:
+ *   number of strings in the list, or -ve error value if not found
+ */
+int dev_read_string_count(struct udevice *dev, const char *propname);
+/**
  * dev_read_phandle_with_args() - Find a node pointed by phandle in a list
  *
  * This function is useful to parse lists of phandles and their arguments.
@@ -451,6 +474,19 @@
 	return ofnode_stringlist_search(dev_ofnode(dev), propname, string);
 }
 
+static inline int dev_read_string_index(struct udevice *dev,
+					const char *propname, int index,
+					const char **outp)
+{
+	return ofnode_read_string_index(dev_ofnode(dev), propname, index, outp);
+}
+
+static inline int dev_read_string_count(struct udevice *dev,
+					const char *propname)
+{
+	return ofnode_read_string_count(dev_ofnode(dev), propname);
+}
+
 static inline int dev_read_phandle_with_args(struct udevice *dev,
 		const char *list_name, const char *cells_name, int cell_count,
 		int index, struct ofnode_phandle_args *out_args)
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 56bb639..db5d88b 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -1497,7 +1497,6 @@
 CONFIG_MVGBE
 CONFIG_MVGBE_PORTS
 CONFIG_MVMFP_V2
-CONFIG_MVNETA
 CONFIG_MVS
 CONFIG_MVSATA_IDE
 CONFIG_MVSATA_IDE_USE_PORT0