Merge branch 'master' of git://www.denx.de/git/u-boot-imx
diff --git a/.travis.yml b/.travis.yml
index 48b7b10..8333fae 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,11 +28,12 @@
     - grub-efi-ia32-bin
     - rpm2cpio
     - wget
+    - device-tree-compiler
 
 install:
  # install latest device tree compiler
- - git clone --depth=1 git://git.kernel.org/pub/scm/utils/dtc/dtc.git /tmp/dtc
- - make -j4 -C /tmp/dtc
+ #- git clone --depth=1 git://git.kernel.org/pub/scm/utils/dtc/dtc.git /tmp/dtc
+ #- make -j4 -C /tmp/dtc
  # Clone uboot-test-hooks
  - git clone --depth=1 git://github.com/swarren/uboot-test-hooks.git /tmp/uboot-test-hooks
  - ln -s travis-ci /tmp/uboot-test-hooks/bin/`hostname`
diff --git a/arch/arm/dts/uniphier-ld11-ref.dts b/arch/arm/dts/uniphier-ld11-ref.dts
index ea11198..7693bf2 100644
--- a/arch/arm/dts/uniphier-ld11-ref.dts
+++ b/arch/arm/dts/uniphier-ld11-ref.dts
@@ -71,7 +71,3 @@
 &pinctrl_uart0 {
 	u-boot,dm-pre-reloc;
 };
-
-&pinctrl_system_bus {
-	u-boot,dm-pre-reloc;
-};
diff --git a/arch/arm/dts/uniphier-ld20-ref.dts b/arch/arm/dts/uniphier-ld20-ref.dts
index 044e000..41ee07e 100644
--- a/arch/arm/dts/uniphier-ld20-ref.dts
+++ b/arch/arm/dts/uniphier-ld20-ref.dts
@@ -59,7 +59,3 @@
 &pinctrl_uart0 {
 	u-boot,dm-pre-reloc;
 };
-
-&pinctrl_system_bus {
-	u-boot,dm-pre-reloc;
-};
diff --git a/arch/arm/mach-uniphier/Makefile b/arch/arm/mach-uniphier/Makefile
index 166b41f..124a1c6 100644
--- a/arch/arm/mach-uniphier/Makefile
+++ b/arch/arm/mach-uniphier/Makefile
@@ -8,6 +8,7 @@
 obj-y += spl_board_init.o
 obj-y += memconf.o
 obj-y += bcu/
+obj-$(CONFIG_SPL_MMC_SUPPORT) += mmc-boot-mode.o
 
 else
 
@@ -19,11 +20,12 @@
 
 obj-$(CONFIG_MICRO_SUPPORT_CARD) += sbc/ micro-support-card.o
 obj-y += pinctrl-glue.o
+obj-$(CONFIG_MMC) += mmc-first-dev.o
 
 endif
 
 obj-y += soc-info.o
-obj-y += boot-mode/
+obj-y += boot-device/
 obj-y += clk/
 obj-y += dram/
 
diff --git a/arch/arm/mach-uniphier/bcu/bcu-ld4.c b/arch/arm/mach-uniphier/bcu/bcu-ld4.c
index 7557880..a16b24e 100644
--- a/arch/arm/mach-uniphier/bcu/bcu-ld4.c
+++ b/arch/arm/mach-uniphier/bcu/bcu-ld4.c
@@ -24,7 +24,7 @@
 	writel(0x11111111, BCSCR5); /* 0xe0000000-0Xffffffff: IPPC/IPPD-bus */
 
 	/* Specify DDR channel */
-	shift = (bd->dram_ch[1].base - bd->dram_ch[0].base) / 0x04000000 * 4;
+	shift = bd->dram_ch[0].size / 0x04000000 * 4;
 	writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */
 
 	shift -= 32;
diff --git a/arch/arm/mach-uniphier/bcu/bcu-sld3.c b/arch/arm/mach-uniphier/bcu/bcu-sld3.c
index 64efd37..99b318f 100644
--- a/arch/arm/mach-uniphier/bcu/bcu-sld3.c
+++ b/arch/arm/mach-uniphier/bcu/bcu-sld3.c
@@ -28,7 +28,7 @@
 	writel(0x24440000, BCSCR5);
 
 	/* Specify DDR channel */
-	shift = (bd->dram_ch[1].base - bd->dram_ch[0].base) / 0x04000000 * 4;
+	shift = bd->dram_ch[0].size / 0x04000000 * 4;
 	writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */
 
 	shift -= 32;
diff --git a/arch/arm/mach-uniphier/board_init.c b/arch/arm/mach-uniphier/board_init.c
index e89a4c5..2564a02 100644
--- a/arch/arm/mach-uniphier/board_init.c
+++ b/arch/arm/mach-uniphier/board_init.c
@@ -165,6 +165,7 @@
 		.nand_2cs = false,
 		.sbc_init = uniphier_ld11_sbc_init,
 		.pll_init = uniphier_ld20_pll_init,
+		.clk_init = uniphier_ld20_clk_init,
 		.misc_init = uniphier_ld20_misc_init,
 	},
 #endif
diff --git a/arch/arm/mach-uniphier/board_late_init.c b/arch/arm/mach-uniphier/board_late_init.c
index ece761f..92dd610 100644
--- a/arch/arm/mach-uniphier/board_late_init.c
+++ b/arch/arm/mach-uniphier/board_late_init.c
@@ -13,7 +13,7 @@
 #include <linux/io.h>
 #include <../drivers/mtd/nand/denali.h>
 
-#include "boot-mode/boot-device.h"
+#include "init.h"
 
 static void nand_denali_wp_disable(void)
 {
@@ -62,7 +62,7 @@
 {
 	puts("MODE:  ");
 
-	switch (spl_boot_device_raw()) {
+	switch (uniphier_boot_device_raw()) {
 	case BOOT_DEVICE_MMC1:
 		printf("eMMC Boot\n");
 		setenv("bootmode", "emmcboot");
diff --git a/arch/arm/mach-uniphier/boards.c b/arch/arm/mach-uniphier/boards.c
index 0596451..db7d192 100644
--- a/arch/arm/mach-uniphier/boards.c
+++ b/arch/arm/mach-uniphier/boards.c
@@ -16,36 +16,30 @@
 #if defined(CONFIG_ARCH_UNIPHIER_SLD3)
 static const struct uniphier_board_data uniphier_sld3_data = {
 	.dram_freq = 1600,
-	.dram_nr_ch = 3,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x20000000,
 		.width = 32,
 	},
 	.dram_ch[1] = {
-		.base = 0xc0000000,
 		.size = 0x20000000,
 		.width = 16,
 	},
 	.dram_ch[2] = {
-		.base = 0xc0000000,
 		.size = 0x10000000,
 		.width = 16,
 	},
+	.flags = UNIPHIER_BD_DRAM_SPARSE,
 };
 #endif
 
 #if defined(CONFIG_ARCH_UNIPHIER_LD4)
 static const struct uniphier_board_data uniphier_ld4_data = {
 	.dram_freq = 1600,
-	.dram_nr_ch = 2,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x10000000,
 		.width = 16,
 	},
 	.dram_ch[1] = {
-		.base = 0x90000000,
 		.size = 0x10000000,
 		.width = 16,
 	},
@@ -57,14 +51,11 @@
 /* 1GB RAM board */
 static const struct uniphier_board_data uniphier_pro4_data = {
 	.dram_freq = 1600,
-	.dram_nr_ch = 2,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x20000000,
 		.width = 32,
 	},
 	.dram_ch[1] = {
-		.base = 0xa0000000,
 		.size = 0x20000000,
 		.width = 32,
 	},
@@ -73,14 +64,11 @@
 /* 2GB RAM board */
 static const struct uniphier_board_data uniphier_pro4_2g_data = {
 	.dram_freq = 1600,
-	.dram_nr_ch = 2,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x40000000,
 		.width = 32,
 	},
 	.dram_ch[1] = {
-		.base = 0xc0000000,
 		.size = 0x40000000,
 		.width = 32,
 	},
@@ -90,14 +78,11 @@
 #if defined(CONFIG_ARCH_UNIPHIER_SLD8)
 static const struct uniphier_board_data uniphier_sld8_data = {
 	.dram_freq = 1333,
-	.dram_nr_ch = 2,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x10000000,
 		.width = 16,
 	},
 	.dram_ch[1] = {
-		.base = 0x90000000,
 		.size = 0x10000000,
 		.width = 16,
 	},
@@ -108,14 +93,11 @@
 #if defined(CONFIG_ARCH_UNIPHIER_PRO5)
 static const struct uniphier_board_data uniphier_pro5_data = {
 	.dram_freq = 1866,
-	.dram_nr_ch = 2,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x20000000,
 		.width = 32,
 	},
 	.dram_ch[1] = {
-		.base = 0xa0000000,
 		.size = 0x20000000,
 		.width = 32,
 	},
@@ -125,19 +107,15 @@
 #if defined(CONFIG_ARCH_UNIPHIER_PXS2)
 static const struct uniphier_board_data uniphier_pxs2_data = {
 	.dram_freq = 2133,
-	.dram_nr_ch = 3,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x40000000,
 		.width = 32,
 	},
 	.dram_ch[1] = {
-		.base = 0xc0000000,
 		.size = 0x20000000,
 		.width = 32,
 	},
 	.dram_ch[2] = {
-		.base = 0xe0000000,
 		.size = 0x20000000,
 		.width = 16,
 	},
@@ -147,19 +125,15 @@
 #if defined(CONFIG_ARCH_UNIPHIER_LD6B)
 static const struct uniphier_board_data uniphier_ld6b_data = {
 	.dram_freq = 1866,
-	.dram_nr_ch = 3,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x40000000,
 		.width = 32,
 	},
 	.dram_ch[1] = {
-		.base = 0xc0000000,
 		.size = 0x20000000,
 		.width = 32,
 	},
 	.dram_ch[2] = {
-		.base = 0xe0000000,
 		.size = 0x20000000,
 		.width = 16,
 	},
@@ -169,14 +143,11 @@
 #if defined(CONFIG_ARCH_UNIPHIER_LD11)
 static const struct uniphier_board_data uniphier_ld11_data = {
 	.dram_freq = 1600,
-	.dram_nr_ch = 2,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x20000000,
 		.width = 16,
 	},
 	.dram_ch[1] = {
-		.base = 0xa0000000,
 		.size = 0x20000000,
 		.width = 16,
 	},
@@ -186,19 +157,15 @@
 #if defined(CONFIG_ARCH_UNIPHIER_LD20)
 static const struct uniphier_board_data uniphier_ld20_ref_data = {
 	.dram_freq = 1866,
-	.dram_nr_ch = 3,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x40000000,
 		.width = 32,
 	},
 	.dram_ch[1] = {
-		.base = 0xc0000000,
 		.size = 0x40000000,
 		.width = 32,
 	},
 	.dram_ch[2] = {
-		.base = 0x100000000UL,
 		.size = 0x40000000,
 		.width = 32,
 	},
@@ -207,19 +174,15 @@
 
 static const struct uniphier_board_data uniphier_ld20_data = {
 	.dram_freq = 1866,
-	.dram_nr_ch = 3,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x40000000,
 		.width = 32,
 	},
 	.dram_ch[1] = {
-		.base = 0xc0000000,
 		.size = 0x40000000,
 		.width = 32,
 	},
 	.dram_ch[2] = {
-		.base = 0x100000000UL,
 		.size = 0x40000000,
 		.width = 32,
 	},
@@ -228,14 +191,11 @@
 
 static const struct uniphier_board_data uniphier_ld21_data = {
 	.dram_freq = 1866,
-	.dram_nr_ch = 2,
 	.dram_ch[0] = {
-		.base = 0x80000000,
 		.size = 0x20000000,
 		.width = 32,
 	},
 	.dram_ch[1] = {
-		.base = 0xc0000000,
 		.size = 0x40000000,
 		.width = 32,
 	},
diff --git a/arch/arm/mach-uniphier/boot-device/Makefile b/arch/arm/mach-uniphier/boot-device/Makefile
new file mode 100644
index 0000000..a54d2ac
--- /dev/null
+++ b/arch/arm/mach-uniphier/boot-device/Makefile
@@ -0,0 +1,19 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y					+= boot-device.o
+
+obj-$(CONFIG_ARCH_UNIPHIER_SLD3)	+= boot-device-sld3.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD4)		+= boot-device-ld4.o
+obj-$(CONFIG_ARCH_UNIPHIER_PRO4)	+= boot-device-ld4.o
+obj-$(CONFIG_ARCH_UNIPHIER_SLD8)	+= boot-device-ld4.o
+obj-$(CONFIG_ARCH_UNIPHIER_PRO5)	+= boot-device-pro5.o
+obj-$(CONFIG_ARCH_UNIPHIER_PXS2)	+= boot-device-pxs2.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD6B)	+= boot-device-pxs2.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= boot-device-ld11.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= boot-device-ld11.o
+
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_BOARD_LOAD_IMAGE)	+= spl_board.o
+endif
diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-ld20.c b/arch/arm/mach-uniphier/boot-device/boot-device-ld11.c
similarity index 72%
rename from arch/arm/mach-uniphier/boot-mode/boot-mode-ld20.c
rename to arch/arm/mach-uniphier/boot-device/boot-device-ld11.c
index 2992fd7..f1a467c 100644
--- a/arch/arm/mach-uniphier/boot-mode/boot-mode-ld20.c
+++ b/arch/arm/mach-uniphier/boot-device/boot-device-ld11.c
@@ -8,12 +8,11 @@
 #include <common.h>
 #include <spl.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 
-#include "../sg-regs.h"
-#include "../soc-info.h"
 #include "boot-device.h"
 
-static struct boot_device_info boot_device_table[] = {
+const struct uniphier_boot_device uniphier_ld11_boot_device_table[] = {
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC  8, EraseSize 128KB, Addr 4)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 4)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC  8, EraseSize 128KB, Addr 5)"},
@@ -48,48 +47,23 @@
 	{BOOT_DEVICE_NOR,  "NOR  (XECS1)"},
 };
 
-static int get_boot_mode_sel(void)
+const unsigned uniphier_ld11_boot_device_count =
+				ARRAY_SIZE(uniphier_ld11_boot_device_table);
+
+int uniphier_ld11_boot_device_is_usb(u32 pinmon)
 {
-	return (readl(SG_PINMON0) >> 1) & 0x1f;
+	return !!(~pinmon & 0x00000080);
 }
 
-u32 uniphier_ld20_boot_device(void)
+int uniphier_ld20_boot_device_is_usb(u32 pinmon)
 {
-	int boot_mode;
-	u32 usb_boot_mask;
-
-	switch (uniphier_get_soc_id()) {
-#if defined(CONFIG_ARCH_UNIPHIER_LD11)
-	case UNIPHIER_LD11_ID:
-		usb_boot_mask = 0x00000080;
-		break;
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_LD20)
-	case UNIPHIER_LD20_ID:
-		usb_boot_mask = 0x00000780;
-		break;
-#endif
-	default:
-		BUG();
-	}
-
-	if (~readl(SG_PINMON0) & usb_boot_mask)
-		return BOOT_DEVICE_USB;
-
-	boot_mode = get_boot_mode_sel();
-
-	return boot_device_table[boot_mode].type;
+	return !!(~pinmon & 0x00000780);
 }
 
-void uniphier_ld20_boot_mode_show(void)
+unsigned int uniphier_ld11_boot_device_fixup(unsigned int mode)
 {
-	int mode_sel, i;
-
-	mode_sel = get_boot_mode_sel();
-
-	puts("Boot Mode Pin:\n");
+	if (mode == BOOT_DEVICE_MMC1 || mode == BOOT_DEVICE_USB)
+		mode = BOOT_DEVICE_BOARD;
 
-	for (i = 0; i < ARRAY_SIZE(boot_device_table); i++)
-		printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i,
-		       boot_device_table[i].info);
+	return mode;
 }
diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-ld4.c b/arch/arm/mach-uniphier/boot-device/boot-device-ld4.c
similarity index 76%
rename from arch/arm/mach-uniphier/boot-mode/boot-mode-ld4.c
rename to arch/arm/mach-uniphier/boot-device/boot-device-ld4.c
index b066ed9..b5d2321 100644
--- a/arch/arm/mach-uniphier/boot-mode/boot-mode-ld4.c
+++ b/arch/arm/mach-uniphier/boot-device/boot-device-ld4.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2014      Panasonic Corporation
+ * Copyright (C) 2015-2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -7,11 +9,11 @@
 #include <common.h>
 #include <spl.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 
-#include "../sg-regs.h"
 #include "boot-device.h"
 
-struct boot_device_info boot_device_table[] = {
+const struct uniphier_boot_device uniphier_ld4_boot_device_table[] = {
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC  8, EraseSize 128KB, Addr 4)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC  8, EraseSize 128KB, Addr 5)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"},
@@ -46,29 +48,5 @@
 	{BOOT_DEVICE_NOR,  "NOR  (XECS0)"},
 };
 
-static int get_boot_mode_sel(void)
-{
-	return (readl(SG_PINMON0) >> 1) & 0x1f;
-}
-
-u32 uniphier_ld4_boot_device(void)
-{
-	int boot_mode;
-
-	boot_mode = get_boot_mode_sel();
-
-	return boot_device_table[boot_mode].type;
-}
-
-void uniphier_ld4_boot_mode_show(void)
-{
-	int mode_sel, i;
-
-	mode_sel = get_boot_mode_sel();
-
-	puts("Boot Mode Pin:\n");
-
-	for (i = 0; i < ARRAY_SIZE(boot_device_table); i++)
-		printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i,
-		       boot_device_table[i].info);
-}
+const unsigned uniphier_ld4_boot_device_count =
+				ARRAY_SIZE(uniphier_ld4_boot_device_table);
diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-pro5.c b/arch/arm/mach-uniphier/boot-device/boot-device-pro5.c
similarity index 76%
rename from arch/arm/mach-uniphier/boot-mode/boot-mode-pro5.c
rename to arch/arm/mach-uniphier/boot-device/boot-device-pro5.c
index 450c43b..47221ee 100644
--- a/arch/arm/mach-uniphier/boot-mode/boot-mode-pro5.c
+++ b/arch/arm/mach-uniphier/boot-device/boot-device-pro5.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -7,11 +8,11 @@
 #include <common.h>
 #include <spl.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 
-#include "../sg-regs.h"
 #include "boot-device.h"
 
-static struct boot_device_info boot_device_table[] = {
+const struct uniphier_boot_device uniphier_pro5_boot_device_table[] = {
 	{BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC  8, EraseSize 128KB, Addr 5)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC 16, EraseSize 128KB, Addr 5)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 1, ECC  8, EraseSize 256KB, Addr 5)"},
@@ -44,32 +45,7 @@
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC  8, EraseSize 256KB, Addr 5)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 256KB, Addr 5)"},
-	{ /* sentinel */ }
 };
 
-static int get_boot_mode_sel(void)
-{
-	return (readl(SG_PINMON0) >> 1) & 0x1f;
-}
-
-u32 uniphier_pro5_boot_device(void)
-{
-	int boot_mode;
-
-	boot_mode = get_boot_mode_sel();
-
-	return boot_device_table[boot_mode].type;
-}
-
-void uniphier_pro5_boot_mode_show(void)
-{
-	int mode_sel, i;
-
-	mode_sel = get_boot_mode_sel();
-
-	puts("Boot Mode Pin:\n");
-
-	for (i = 0; i < ARRAY_SIZE(boot_device_table); i++)
-		printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i,
-		       boot_device_table[i].info);
-}
+const unsigned uniphier_pro5_boot_device_count =
+				ARRAY_SIZE(uniphier_pro5_boot_device_table);
diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-pxs2.c b/arch/arm/mach-uniphier/boot-device/boot-device-pxs2.c
similarity index 76%
rename from arch/arm/mach-uniphier/boot-mode/boot-mode-pxs2.c
rename to arch/arm/mach-uniphier/boot-device/boot-device-pxs2.c
index 20ff773..20a9511 100644
--- a/arch/arm/mach-uniphier/boot-mode/boot-mode-pxs2.c
+++ b/arch/arm/mach-uniphier/boot-device/boot-device-pxs2.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -7,11 +8,11 @@
 #include <common.h>
 #include <spl.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 
-#include "../sg-regs.h"
 #include "boot-device.h"
 
-static struct boot_device_info boot_device_table[] = {
+const struct uniphier_boot_device uniphier_pxs2_boot_device_table[] = {
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC  8, EraseSize 128KB, Addr 4)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC  8, EraseSize 128KB, Addr 5)"},
 	{BOOT_DEVICE_NAND, "NAND (Mirror 8, ECC 16, EraseSize 128KB, Addr 5)"},
@@ -46,32 +47,18 @@
 	{BOOT_DEVICE_NONE, "Reserved"},
 };
 
-static int get_boot_mode_sel(void)
-{
-	return (readl(SG_PINMON0) >> 1) & 0x1f;
-}
+const unsigned uniphier_pxs2_boot_device_count =
+				ARRAY_SIZE(uniphier_pxs2_boot_device_table);
 
-u32 uniphier_pxs2_boot_device(void)
+int uniphier_pxs2_boot_device_is_usb(u32 pinmon)
 {
-	int boot_mode;
-
-	if (readl(SG_PINMON0) & BIT(6))
-		return BOOT_DEVICE_USB;
-
-	boot_mode = get_boot_mode_sel();
-
-	return boot_device_table[boot_mode].type;
+	return !!(pinmon & 0x00000040);
 }
 
-void uniphier_pxs2_boot_mode_show(void)
+unsigned int uniphier_pxs2_boot_device_fixup(unsigned int mode)
 {
-	int mode_sel, i;
-
-	mode_sel = get_boot_mode_sel();
-
-	puts("Boot Mode Pin:\n");
+	if (mode == BOOT_DEVICE_USB)
+		return BOOT_DEVICE_NOR;
 
-	for (i = 0; i < ARRAY_SIZE(boot_device_table); i++)
-		printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i,
-		       boot_device_table[i].info);
+	return mode;
 }
diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode-sld3.c b/arch/arm/mach-uniphier/boot-device/boot-device-sld3.c
similarity index 82%
rename from arch/arm/mach-uniphier/boot-mode/boot-mode-sld3.c
rename to arch/arm/mach-uniphier/boot-device/boot-device-sld3.c
index ddf8259..2b36494 100644
--- a/arch/arm/mach-uniphier/boot-mode/boot-mode-sld3.c
+++ b/arch/arm/mach-uniphier/boot-device/boot-device-sld3.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2014      Panasonic Corporation
+ * Copyright (C) 2015-2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -7,11 +9,11 @@
 #include <common.h>
 #include <spl.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 
-#include "../sg-regs.h"
 #include "boot-device.h"
 
-static struct boot_device_info boot_device_table[] = {
+const struct uniphier_boot_device uniphier_sld3_boot_device_table[] = {
 	{BOOT_DEVICE_NOR,  "NOR  (XECS0)"},
 	{BOOT_DEVICE_NONE, "External Master"},
 	{BOOT_DEVICE_NONE, "Reserved"},
@@ -78,29 +80,5 @@
 	{BOOT_DEVICE_NONE, "Reserved"},
 };
 
-static int get_boot_mode_sel(void)
-{
-	return readl(SG_PINMON0) & 0x3f;
-}
-
-u32 uniphier_sld3_boot_device(void)
-{
-	int boot_mode;
-
-	boot_mode = get_boot_mode_sel();
-
-	return boot_device_table[boot_mode].type;
-}
-
-void uniphier_sld3_boot_mode_show(void)
-{
-	int mode_sel, i;
-
-	mode_sel = get_boot_mode_sel();
-
-	puts("Boot Mode Pin:\n");
-
-	for (i = 0; i < ARRAY_SIZE(boot_device_table); i++)
-		printf(" %c %02x %s\n", i == mode_sel ? '*' : ' ', i,
-		       boot_device_table[i].info);
-}
+const unsigned uniphier_sld3_boot_device_count =
+				ARRAY_SIZE(uniphier_sld3_boot_device_table);
diff --git a/arch/arm/mach-uniphier/boot-device/boot-device.c b/arch/arm/mach-uniphier/boot-device/boot-device.c
new file mode 100644
index 0000000..5ec0b5b
--- /dev/null
+++ b/arch/arm/mach-uniphier/boot-device/boot-device.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2015-2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <linux/log2.h>
+
+#include "../init.h"
+#include "../sbc/sbc-regs.h"
+#include "../sg-regs.h"
+#include "../soc-info.h"
+#include "boot-device.h"
+
+struct uniphier_boot_device_info {
+	unsigned int soc_id;
+	unsigned int boot_device_sel_shift;
+	const struct uniphier_boot_device *boot_device_table;
+	const unsigned int *boot_device_count;
+	int (*boot_device_is_usb)(u32 pinmon);
+	unsigned int (*boot_device_fixup)(unsigned int mode);
+};
+
+static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
+#if defined(CONFIG_ARCH_UNIPHIER_SLD3)
+	{
+		.soc_id = UNIPHIER_SLD3_ID,
+		.boot_device_sel_shift = 0,
+		.boot_device_table = uniphier_sld3_boot_device_table,
+		.boot_device_count = &uniphier_sld3_boot_device_count,
+	},
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_LD4)
+	{
+		.soc_id = UNIPHIER_LD4_ID,
+		.boot_device_sel_shift = 1,
+		.boot_device_table = uniphier_ld4_boot_device_table,
+		.boot_device_count = &uniphier_ld4_boot_device_count,
+	},
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_PRO4)
+	{
+		.soc_id = UNIPHIER_PRO4_ID,
+		.boot_device_sel_shift = 1,
+		.boot_device_table = uniphier_ld4_boot_device_table,
+		.boot_device_count = &uniphier_ld4_boot_device_count,
+	},
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_SLD8)
+	{
+		.soc_id = UNIPHIER_SLD8_ID,
+		.boot_device_sel_shift = 1,
+		.boot_device_table = uniphier_ld4_boot_device_table,
+		.boot_device_count = &uniphier_ld4_boot_device_count,
+	},
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_PRO5)
+	{
+		.soc_id = UNIPHIER_PRO5_ID,
+		.boot_device_sel_shift = 1,
+		.boot_device_table = uniphier_pro5_boot_device_table,
+		.boot_device_count = &uniphier_pro5_boot_device_count,
+	},
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_PXS2)
+	{
+		.soc_id = UNIPHIER_PXS2_ID,
+		.boot_device_sel_shift = 1,
+		.boot_device_table = uniphier_pxs2_boot_device_table,
+		.boot_device_count = &uniphier_pxs2_boot_device_count,
+		.boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
+		.boot_device_fixup = uniphier_pxs2_boot_device_fixup,
+	},
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_LD6B)
+	{
+		.soc_id = UNIPHIER_LD6B_ID,
+		.boot_device_sel_shift = 1,
+		.boot_device_table = uniphier_pxs2_boot_device_table,
+		.boot_device_count = &uniphier_pxs2_boot_device_count,
+		.boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
+		.boot_device_fixup = uniphier_pxs2_boot_device_fixup,
+	},
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_LD11)
+	{
+		.soc_id = UNIPHIER_LD11_ID,
+		.boot_device_sel_shift = 1,
+		.boot_device_table = uniphier_ld11_boot_device_table,
+		.boot_device_count = &uniphier_ld11_boot_device_count,
+		.boot_device_is_usb = uniphier_ld11_boot_device_is_usb,
+		.boot_device_fixup = uniphier_ld11_boot_device_fixup,
+	},
+#endif
+#if defined(CONFIG_ARCH_UNIPHIER_LD20)
+	{
+		.soc_id = UNIPHIER_LD20_ID,
+		.boot_device_sel_shift = 1,
+		.boot_device_table = uniphier_ld11_boot_device_table,
+		.boot_device_count = &uniphier_ld11_boot_device_count,
+		.boot_device_is_usb = uniphier_ld20_boot_device_is_usb,
+		.boot_device_fixup = uniphier_ld11_boot_device_fixup,
+	},
+#endif
+};
+UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info,
+			     uniphier_boot_device_info)
+
+static unsigned int __uniphier_boot_device_raw(
+				const struct uniphier_boot_device_info *info)
+{
+	u32 pinmon;
+	unsigned int boot_sel;
+
+	if (boot_is_swapped())
+		return BOOT_DEVICE_NOR;
+
+	pinmon = readl(SG_PINMON0);
+
+	if (info->boot_device_is_usb && info->boot_device_is_usb(pinmon))
+		return BOOT_DEVICE_USB;
+
+	boot_sel = pinmon >> info->boot_device_sel_shift;
+
+	BUG_ON(!is_power_of_2(*info->boot_device_count));
+	boot_sel &= *info->boot_device_count - 1;
+
+	return info->boot_device_table[boot_sel].boot_device;
+}
+
+unsigned int uniphier_boot_device_raw(void)
+{
+	const struct uniphier_boot_device_info *info;
+
+	info = uniphier_get_boot_device_info();
+	if (!info) {
+		pr_err("unsupported SoC\n");
+		return BOOT_DEVICE_NONE;
+	}
+
+	return __uniphier_boot_device_raw(info);
+}
+
+u32 spl_boot_device(void)
+{
+	const struct uniphier_boot_device_info *info;
+	u32 raw_mode;
+
+	info = uniphier_get_boot_device_info();
+	if (!info) {
+		pr_err("unsupported SoC\n");
+		return BOOT_DEVICE_NONE;
+	}
+
+	raw_mode = __uniphier_boot_device_raw(info);
+
+	return info->boot_device_fixup ?
+				info->boot_device_fixup(raw_mode) : raw_mode;
+}
+
+#ifndef CONFIG_SPL_BUILD
+
+static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	const struct uniphier_boot_device_info *info;
+	u32 pinmon;
+	unsigned int boot_device_count, boot_sel;
+	int i;
+
+	info = uniphier_get_boot_device_info();
+	if (!info) {
+		pr_err("unsupported SoC\n");
+		return CMD_RET_FAILURE;
+	}
+
+	printf("Boot Swap: %s\n\n", boot_is_swapped() ? "ON" : "OFF");
+
+	pinmon = readl(SG_PINMON0);
+
+	if (info->boot_device_is_usb)
+		printf("USB Boot: %s\n\n",
+		       info->boot_device_is_usb(pinmon) ? "ON" : "OFF");
+
+	boot_device_count = *info->boot_device_count;
+
+	boot_sel = pinmon >> info->boot_device_sel_shift;
+	boot_sel &= boot_device_count - 1;
+
+	printf("Boot Mode Sel:\n");
+	for (i = 0; i < boot_device_count; i++)
+		printf(" %c %02x %s\n", i == boot_sel ? '*' : ' ', i,
+		       info->boot_device_table[i].desc);
+
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+	pinmon,	1,	1,	do_pinmon,
+	"pin monitor",
+	""
+);
+
+#endif /* !CONFIG_SPL_BUILD */
diff --git a/arch/arm/mach-uniphier/boot-device/boot-device.h b/arch/arm/mach-uniphier/boot-device/boot-device.h
new file mode 100644
index 0000000..f3fb2f3
--- /dev/null
+++ b/arch/arm/mach-uniphier/boot-device/boot-device.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _UNIPHIER_BOOT_DEVICE_H_
+#define _UNIPHIER_BOOT_DEVICE_H_
+
+struct uniphier_boot_device {
+	unsigned int boot_device;
+	const char *desc;
+};
+
+extern const struct uniphier_boot_device uniphier_sld3_boot_device_table[];
+extern const struct uniphier_boot_device uniphier_ld4_boot_device_table[];
+extern const struct uniphier_boot_device uniphier_pro5_boot_device_table[];
+extern const struct uniphier_boot_device uniphier_pxs2_boot_device_table[];
+extern const struct uniphier_boot_device uniphier_ld11_boot_device_table[];
+
+extern const unsigned int uniphier_sld3_boot_device_count;
+extern const unsigned int uniphier_ld4_boot_device_count;
+extern const unsigned int uniphier_pro5_boot_device_count;
+extern const unsigned int uniphier_pxs2_boot_device_count;
+extern const unsigned int uniphier_ld11_boot_device_count;
+
+int uniphier_pxs2_boot_device_is_usb(u32 pinmon);
+int uniphier_ld11_boot_device_is_usb(u32 pinmon);
+int uniphier_ld20_boot_device_is_usb(u32 pinmon);
+
+unsigned int uniphier_pxs2_boot_device_fixup(unsigned int mode);
+unsigned int uniphier_ld11_boot_device_fixup(unsigned int mode);
+
+#endif /* _UNIPHIER_BOOT_DEVICE_H_ */
diff --git a/arch/arm/mach-uniphier/boot-device/spl_board.c b/arch/arm/mach-uniphier/boot-device/spl_board.c
new file mode 100644
index 0000000..bd47ac8
--- /dev/null
+++ b/arch/arm/mach-uniphier/boot-device/spl_board.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/io.h>
+#include <asm/processor.h>
+
+#include "../soc-info.h"
+
+#define MMC_CMD_SWITCH			6
+#define MMC_CMD_SELECT_CARD		7
+#define MMC_CMD_SEND_CSD		9
+#define MMC_CMD_READ_MULTIPLE_BLOCK	18
+
+#define EXT_CSD_PART_CONF		179	/* R/W */
+
+#define MMC_RSP_PRESENT BIT(0)
+#define MMC_RSP_136	BIT(1)		/* 136 bit response */
+#define MMC_RSP_CRC	BIT(2)		/* expect valid crc */
+#define MMC_RSP_BUSY	BIT(3)		/* card may send busy */
+#define MMC_RSP_OPCODE	BIT(4)		/* response contains opcode */
+
+#define MMC_RSP_NONE	(0)
+#define MMC_RSP_R1	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R1b	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | \
+			MMC_RSP_BUSY)
+#define MMC_RSP_R2	(MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
+#define MMC_RSP_R3	(MMC_RSP_PRESENT)
+#define MMC_RSP_R4	(MMC_RSP_PRESENT)
+#define MMC_RSP_R5	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R6	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R7	(MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+
+#define SDHCI_DMA_ADDRESS	0x00
+#define SDHCI_BLOCK_SIZE	0x04
+#define  SDHCI_MAKE_BLKSZ(dma, blksz) ((((dma) & 0x7) << 12) | ((blksz) & 0xFFF))
+#define SDHCI_BLOCK_COUNT	0x06
+#define SDHCI_ARGUMENT		0x08
+#define SDHCI_TRANSFER_MODE	0x0C
+#define  SDHCI_TRNS_DMA		BIT(0)
+#define  SDHCI_TRNS_BLK_CNT_EN	BIT(1)
+#define  SDHCI_TRNS_ACMD12	BIT(2)
+#define  SDHCI_TRNS_READ	BIT(4)
+#define  SDHCI_TRNS_MULTI	BIT(5)
+#define SDHCI_COMMAND		0x0E
+#define  SDHCI_CMD_RESP_MASK	0x03
+#define  SDHCI_CMD_CRC		0x08
+#define  SDHCI_CMD_INDEX	0x10
+#define  SDHCI_CMD_DATA		0x20
+#define  SDHCI_CMD_ABORTCMD	0xC0
+#define  SDHCI_CMD_RESP_NONE	0x00
+#define  SDHCI_CMD_RESP_LONG	0x01
+#define  SDHCI_CMD_RESP_SHORT	0x02
+#define  SDHCI_CMD_RESP_SHORT_BUSY 0x03
+#define  SDHCI_MAKE_CMD(c, f) ((((c) & 0xff) << 8) | ((f) & 0xff))
+#define SDHCI_RESPONSE		0x10
+#define SDHCI_HOST_CONTROL	0x28
+#define  SDHCI_CTRL_DMA_MASK	0x18
+#define   SDHCI_CTRL_SDMA	0x00
+#define SDHCI_BLOCK_GAP_CONTROL	0x2A
+#define SDHCI_SOFTWARE_RESET	0x2F
+#define  SDHCI_RESET_CMD	0x02
+#define  SDHCI_RESET_DATA	0x04
+#define SDHCI_INT_STATUS	0x30
+#define  SDHCI_INT_RESPONSE	BIT(0)
+#define  SDHCI_INT_DATA_END	BIT(1)
+#define  SDHCI_INT_ERROR	BIT(15)
+#define SDHCI_SIGNAL_ENABLE	0x38
+
+/* RCA assigned by Boot ROM */
+#define UNIPHIER_EMMC_RCA	0x1000
+
+struct uniphier_mmc_cmd {
+	unsigned int cmdidx;
+	unsigned int resp_type;
+	unsigned int cmdarg;
+	unsigned int is_data;
+};
+
+static int uniphier_emmc_send_cmd(void __iomem *host_base,
+				  struct uniphier_mmc_cmd *cmd)
+{
+	u32 mode = 0;
+	u32 mask = SDHCI_INT_RESPONSE;
+	u32 stat, flags;
+
+	writel(U32_MAX, host_base + SDHCI_INT_STATUS);
+	writel(0, host_base + SDHCI_SIGNAL_ENABLE);
+	writel(cmd->cmdarg, host_base + SDHCI_ARGUMENT);
+
+	if (cmd->is_data)
+		mode = SDHCI_TRNS_DMA | SDHCI_TRNS_BLK_CNT_EN |
+			SDHCI_TRNS_ACMD12 | SDHCI_TRNS_READ |
+			SDHCI_TRNS_MULTI;
+
+	writew(mode, host_base + SDHCI_TRANSFER_MODE);
+
+	if (!(cmd->resp_type & MMC_RSP_PRESENT))
+		flags = SDHCI_CMD_RESP_NONE;
+	else if (cmd->resp_type & MMC_RSP_136)
+		flags = SDHCI_CMD_RESP_LONG;
+	else if (cmd->resp_type & MMC_RSP_BUSY)
+		flags = SDHCI_CMD_RESP_SHORT_BUSY;
+	else
+		flags = SDHCI_CMD_RESP_SHORT;
+
+	if (cmd->resp_type & MMC_RSP_CRC)
+		flags |= SDHCI_CMD_CRC;
+	if (cmd->resp_type & MMC_RSP_OPCODE)
+		flags |= SDHCI_CMD_INDEX;
+	if (cmd->is_data)
+		flags |= SDHCI_CMD_DATA;
+
+	if (cmd->resp_type & MMC_RSP_BUSY || cmd->is_data)
+		mask |= SDHCI_INT_DATA_END;
+
+	writew(SDHCI_MAKE_CMD(cmd->cmdidx, flags), host_base + SDHCI_COMMAND);
+
+	do {
+		stat = readl(host_base + SDHCI_INT_STATUS);
+		if (stat & SDHCI_INT_ERROR)
+			return -EIO;
+
+	} while ((stat & mask) != mask);
+
+	return 0;
+}
+
+static int uniphier_emmc_switch_part(void __iomem *host_base, int part_num)
+{
+	struct uniphier_mmc_cmd cmd = {};
+
+	cmd.cmdidx = MMC_CMD_SWITCH;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = (EXT_CSD_PART_CONF << 16) | (part_num << 8) | (3 << 24);
+
+	return uniphier_emmc_send_cmd(host_base, &cmd);
+}
+
+static int uniphier_emmc_is_over_2gb(void __iomem *host_base)
+{
+	struct uniphier_mmc_cmd cmd = {};
+	u32 csd40, csd72;	/* CSD[71:40], CSD[103:72] */
+	int ret;
+
+	cmd.cmdidx = MMC_CMD_SEND_CSD;
+	cmd.resp_type = MMC_RSP_R2;
+	cmd.cmdarg = UNIPHIER_EMMC_RCA << 16;
+
+	ret = uniphier_emmc_send_cmd(host_base, &cmd);
+	if (ret)
+		return ret;
+
+	csd40 = readl(host_base + SDHCI_RESPONSE + 4);
+	csd72 = readl(host_base + SDHCI_RESPONSE + 8);
+
+	return !(~csd40 & 0xffc00380) && !(~csd72 & 0x3);
+}
+
+static int uniphier_emmc_load_image(void __iomem *host_base, u32 dev_addr,
+				    unsigned long load_addr, u32 block_cnt)
+{
+	struct uniphier_mmc_cmd cmd = {};
+	u8 tmp;
+
+	WARN_ON(load_addr >> 32);
+
+	writel(load_addr, host_base + SDHCI_DMA_ADDRESS);
+	writew(SDHCI_MAKE_BLKSZ(7, 512), host_base + SDHCI_BLOCK_SIZE);
+	writew(block_cnt, host_base + SDHCI_BLOCK_COUNT);
+
+	tmp = readb(host_base + SDHCI_HOST_CONTROL);
+	tmp &= ~SDHCI_CTRL_DMA_MASK;
+	tmp |= SDHCI_CTRL_SDMA;
+	writeb(tmp, host_base + SDHCI_HOST_CONTROL);
+
+	tmp = readb(host_base + SDHCI_BLOCK_GAP_CONTROL);
+	tmp &= ~1;		/* clear Stop At Block Gap Request */
+	writeb(tmp, host_base + SDHCI_BLOCK_GAP_CONTROL);
+
+	cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
+	cmd.resp_type = MMC_RSP_R1;
+	cmd.cmdarg = dev_addr;
+	cmd.is_data = 1;
+
+	return uniphier_emmc_send_cmd(host_base, &cmd);
+}
+
+static int spl_board_load_image(struct spl_image_info *spl_image,
+				struct spl_boot_device *bootdev)
+{
+	u32 dev_addr = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR;
+	void __iomem *host_base = (void __iomem *)0x5a000200;
+	struct uniphier_mmc_cmd cmd = {};
+	int ret;
+
+	/*
+	 * deselect card before SEND_CSD command.
+	 * Do not check the return code.  It fails, but it is OK.
+	 */
+	cmd.cmdidx = MMC_CMD_SELECT_CARD;
+	cmd.resp_type = MMC_RSP_R1;
+
+	uniphier_emmc_send_cmd(host_base, &cmd); /* CMD7 (arg=0) */
+
+	/* reset CMD Line */
+	writeb(SDHCI_RESET_CMD | SDHCI_RESET_DATA,
+	       host_base + SDHCI_SOFTWARE_RESET);
+	while (readb(host_base + SDHCI_SOFTWARE_RESET))
+		cpu_relax();
+
+	ret = uniphier_emmc_is_over_2gb(host_base);
+	if (ret < 0)
+		return ret;
+	if (ret) {
+		debug("card is block addressing\n");
+	} else {
+		debug("card is byte addressing\n");
+		dev_addr *= 512;
+	}
+
+	cmd.cmdarg = UNIPHIER_EMMC_RCA << 16;
+
+	/* select card again */
+	ret = uniphier_emmc_send_cmd(host_base, &cmd);
+	if (ret)
+		printf("failed to select card\n");
+
+	/* Switch to Boot Partition 1 */
+	ret = uniphier_emmc_switch_part(host_base, 1);
+	if (ret)
+		printf("failed to switch partition\n");
+
+	ret = uniphier_emmc_load_image(host_base, dev_addr,
+				       CONFIG_SYS_TEXT_BASE, 1);
+	if (ret) {
+		printf("failed to load image\n");
+		return ret;
+	}
+
+	ret = spl_parse_image_header(spl_image, (void *)CONFIG_SYS_TEXT_BASE);
+	if (ret)
+		return ret;
+
+	ret = uniphier_emmc_load_image(host_base, dev_addr,
+				       spl_image->load_addr,
+				       spl_image->size / 512);
+	if (ret) {
+		printf("failed to load image\n");
+		return ret;
+	}
+
+	return 0;
+}
+SPL_LOAD_IMAGE_METHOD("eMMC", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
diff --git a/arch/arm/mach-uniphier/boot-mode/Makefile b/arch/arm/mach-uniphier/boot-mode/Makefile
deleted file mode 100644
index a898021..0000000
--- a/arch/arm/mach-uniphier/boot-mode/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y					+= boot-mode.o
-
-obj-$(CONFIG_ARCH_UNIPHIER_SLD3)	+= boot-mode-sld3.o
-obj-$(CONFIG_ARCH_UNIPHIER_LD4)		+= boot-mode-ld4.o
-obj-$(CONFIG_ARCH_UNIPHIER_PRO4)	+= boot-mode-ld4.o
-obj-$(CONFIG_ARCH_UNIPHIER_SLD8)	+= boot-mode-ld4.o
-obj-$(CONFIG_ARCH_UNIPHIER_PRO5)	+= boot-mode-pro5.o
-obj-$(CONFIG_ARCH_UNIPHIER_PXS2)	+= boot-mode-pxs2.o
-obj-$(CONFIG_ARCH_UNIPHIER_LD6B)	+= boot-mode-pxs2.o
-obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= boot-mode-ld20.o
-obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= boot-mode-ld20.o
-
-ifdef CONFIG_SPL_BUILD
-obj-$(CONFIG_SPL_BOARD_LOAD_IMAGE)	+= spl_board.o
-else
-obj-$(CONFIG_CMD_PINMON) += cmd_pinmon.o
-endif
diff --git a/arch/arm/mach-uniphier/boot-mode/boot-device.h b/arch/arm/mach-uniphier/boot-mode/boot-device.h
deleted file mode 100644
index bd44d73..0000000
--- a/arch/arm/mach-uniphier/boot-mode/boot-device.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef _ASM_BOOT_DEVICE_H_
-#define _ASM_BOOT_DEVICE_H_
-
-struct boot_device_info {
-	u32 type;
-	char *info;
-};
-
-u32 uniphier_sld3_boot_device(void);
-u32 uniphier_ld4_boot_device(void);
-u32 uniphier_pro5_boot_device(void);
-u32 uniphier_pxs2_boot_device(void);
-u32 uniphier_ld20_boot_device(void);
-
-void uniphier_sld3_boot_mode_show(void);
-void uniphier_ld4_boot_mode_show(void);
-void uniphier_pro5_boot_mode_show(void);
-void uniphier_pxs2_boot_mode_show(void);
-void uniphier_ld20_boot_mode_show(void);
-
-u32 spl_boot_device_raw(void);
-
-#endif /* _ASM_BOOT_DEVICE_H_ */
diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode.c b/arch/arm/mach-uniphier/boot-mode/boot-mode.c
deleted file mode 100644
index a552770..0000000
--- a/arch/arm/mach-uniphier/boot-mode/boot-mode.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <mmc.h>
-#include <spl.h>
-#include <linux/errno.h>
-
-#include "../sbc/sbc-regs.h"
-#include "../soc-info.h"
-#include "boot-device.h"
-
-u32 spl_boot_device_raw(void)
-{
-	if (boot_is_swapped())
-		return BOOT_DEVICE_NOR;
-
-	switch (uniphier_get_soc_id()) {
-#if defined(CONFIG_ARCH_UNIPHIER_SLD3)
-	case UNIPHIER_SLD3_ID:
-		return uniphier_sld3_boot_device();
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_PRO4) || \
-	defined(CONFIG_ARCH_UNIPHIER_SLD8)
-	case UNIPHIER_LD4_ID:
-	case UNIPHIER_PRO4_ID:
-	case UNIPHIER_SLD8_ID:
-		return uniphier_ld4_boot_device();
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_PRO5)
-	case UNIPHIER_PRO5_ID:
-		return uniphier_pro5_boot_device();
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B)
-	case UNIPHIER_PXS2_ID:
-	case UNIPHIER_LD6B_ID:
-		return uniphier_pxs2_boot_device();
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20)
-	case UNIPHIER_LD11_ID:
-	case UNIPHIER_LD20_ID:
-		return uniphier_ld20_boot_device();
-#endif
-	default:
-		return BOOT_DEVICE_NONE;
-	}
-}
-
-u32 spl_boot_device(void)
-{
-	u32 mode;
-
-	mode = spl_boot_device_raw();
-
-	switch (uniphier_get_soc_id()) {
-#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B)
-	case UNIPHIER_PXS2_ID:
-	case UNIPHIER_LD6B_ID:
-		if (mode == BOOT_DEVICE_USB)
-			mode = BOOT_DEVICE_NOR;
-		break;
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20)
-	case UNIPHIER_LD11_ID:
-	case UNIPHIER_LD20_ID:
-		if (mode == BOOT_DEVICE_MMC1 || mode == BOOT_DEVICE_USB)
-			mode = BOOT_DEVICE_BOARD;
-		break;
-#endif
-	default:
-		break;
-	}
-
-	return mode;
-}
-
-u32 spl_boot_mode(const u32 boot_device)
-{
-	struct mmc *mmc;
-
-	/*
-	 * work around a bug in the Boot ROM of PH1-sLD3, LD4, Pro4, and sLD8:
-	 *
-	 * The boot ROM in these SoCs breaks the PARTITION_CONFIG [179] of
-	 * Extended CSD register; when switching to the Boot Partition 1, the
-	 * Boot ROM should issue the SWITCH command (CMD6) with Set Bits for
-	 * the Access Bits, but in fact it uses Write Byte for the Access Bits.
-	 * As a result, the BOOT_PARTITION_ENABLE field of the PARTITION_CONFIG
-	 * is lost.  This bug was fixed for PH1-Pro5 and later SoCs.
-	 *
-	 * Fixup mmc->part_config here because it is used to determine the
-	 * partition which the U-Boot image is read from.
-	 */
-	mmc = find_mmc_device(0);
-	mmc->part_config &= ~EXT_CSD_BOOT_PART_NUM(PART_ACCESS_MASK);
-	mmc->part_config |= EXT_CSD_BOOT_PARTITION_ENABLE;
-
-	return MMCSD_MODE_EMMCBOOT;
-}
-
-#if defined(CONFIG_DM_MMC) && !defined(CONFIG_SPL_BUILD)
-static int find_first_mmc_device(void)
-{
-	struct mmc *mmc;
-	int i;
-
-	for (i = 0; (mmc = find_mmc_device(i)); i++) {
-		if (!mmc_init(mmc) && IS_MMC(mmc))
-			return i;
-	}
-
-	return -ENODEV;
-}
-
-int mmc_get_env_dev(void)
-{
-	return find_first_mmc_device();
-}
-
-static int do_mmcsetn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	int dev;
-
-	dev = find_first_mmc_device();
-	if (dev < 0)
-		return CMD_RET_FAILURE;
-
-	setenv_ulong("mmc_first_dev", dev);
-	return CMD_RET_SUCCESS;
-}
-
-U_BOOT_CMD(
-	   mmcsetn,	1,	1,	do_mmcsetn,
-	"Set the first MMC (not SD) dev number to \"mmc_first_dev\" environment",
-	""
-);
-#endif
diff --git a/arch/arm/mach-uniphier/boot-mode/cmd_pinmon.c b/arch/arm/mach-uniphier/boot-mode/cmd_pinmon.c
deleted file mode 100644
index 670d4f6..0000000
--- a/arch/arm/mach-uniphier/boot-mode/cmd_pinmon.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-
-#include "../sbc/sbc-regs.h"
-#include "../soc-info.h"
-#include "boot-device.h"
-
-static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	printf("Boot Swap: %s\n\n", boot_is_swapped() ? "ON" : "OFF");
-
-	switch (uniphier_get_soc_id()) {
-#if defined(CONFIG_ARCH_UNIPHIER_SLD3)
-	case UNIPHIER_SLD3_ID:
-		uniphier_sld3_boot_mode_show();
-		break;
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_PRO4) || \
-	defined(CONFIG_ARCH_UNIPHIER_SLD8)
-	case UNIPHIER_LD4_ID:
-	case UNIPHIER_PRO4_ID:
-	case UNIPHIER_SLD8_ID:
-		uniphier_ld4_boot_mode_show();
-		break;
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_PRO5)
-	case UNIPHIER_PRO5_ID:
-		uniphier_pro5_boot_mode_show();
-		break;
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B)
-	case UNIPHIER_PXS2_ID:
-	case UNIPHIER_LD6B_ID:
-		uniphier_pxs2_boot_mode_show();
-		break;
-#endif
-#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20)
-	case UNIPHIER_LD11_ID:
-	case UNIPHIER_LD20_ID:
-		uniphier_ld20_boot_mode_show();
-		break;
-#endif
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-U_BOOT_CMD(
-	pinmon,	1,	1,	do_pinmon,
-	"pin monitor",
-	""
-);
diff --git a/arch/arm/mach-uniphier/boot-mode/spl_board.c b/arch/arm/mach-uniphier/boot-mode/spl_board.c
deleted file mode 100644
index 0aac924..0000000
--- a/arch/arm/mach-uniphier/boot-mode/spl_board.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2016 Socionext Inc.
- *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <spl.h>
-#include <linux/io.h>
-#include <asm/processor.h>
-
-#include "../soc-info.h"
-
-struct uniphier_romfunc_table {
-	void *mmc_send_cmd;
-	void *mmc_card_blockaddr;
-	void *mmc_switch_part;
-	void *mmc_load_image;
-};
-
-static const struct uniphier_romfunc_table uniphier_ld11_romfunc_table = {
-	.mmc_send_cmd = (void *)0x20d8,
-	.mmc_card_blockaddr = (void *)0x1b68,
-	.mmc_switch_part = (void *)0x1c38,
-	.mmc_load_image = (void *)0x2e48,
-};
-
-static const struct uniphier_romfunc_table uniphier_ld20_romfunc_table = {
-	.mmc_send_cmd = (void *)0x2130,
-	.mmc_card_blockaddr = (void *)0x1ba0,
-	.mmc_switch_part = (void *)0x1c70,
-	.mmc_load_image = (void *)0x2ef0,
-};
-
-int uniphier_rom_get_mmc_funcptr(int (**send_cmd)(u32, u32),
-				 int (**card_blockaddr)(u32),
-				 int (**switch_part)(int),
-				 int (**load_image)(u32, uintptr_t, u32))
-{
-	const struct uniphier_romfunc_table *table;
-
-	switch (uniphier_get_soc_id()) {
-	case UNIPHIER_LD11_ID:
-		table = &uniphier_ld11_romfunc_table;
-		break;
-	case UNIPHIER_LD20_ID:
-		table = &uniphier_ld20_romfunc_table;
-		break;
-	default:
-		printf("unsupported SoC\n");
-		return -EINVAL;
-	}
-
-	*send_cmd = table->mmc_send_cmd;
-	*card_blockaddr = table->mmc_card_blockaddr;
-	*switch_part = table->mmc_switch_part;
-	*load_image = table->mmc_load_image;
-
-	return 0;
-}
-
-static int spl_board_load_image(struct spl_image_info *spl_image,
-				struct spl_boot_device *bootdev)
-{
-	int (*send_cmd)(u32 cmd, u32 arg);
-	int (*card_blockaddr)(u32 rca);
-	int (*switch_part)(int part);
-	int (*load_image)(u32 dev_addr, uintptr_t load_addr, u32 block_cnt);
-	u32 dev_addr = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR;
-	const u32 rca = 0x1000; /* RCA assigned by Boot ROM */
-	int ret;
-
-	ret = uniphier_rom_get_mmc_funcptr(&send_cmd, &card_blockaddr,
-					   &switch_part, &load_image);
-	if (ret)
-		return ret;
-
-	/*
-	 * deselect card before SEND_CSD command.
-	 * Do not check the return code.  It fails, but it is OK.
-	 */
-	(*send_cmd)(0x071a0000, 0); /* CMD7 (arg=0) */
-
-	/* reset CMD Line */
-	writeb(0x6, 0x5a00022f);
-	while (readb(0x5a00022f))
-		cpu_relax();
-
-	ret = (*card_blockaddr)(rca);
-	if (ret) {
-		debug("card is block addressing\n");
-	} else {
-		debug("card is byte addressing\n");
-		dev_addr *= 512;
-	}
-
-	ret = (*send_cmd)(0x071a0000, rca << 16); /* CMD7: select card again */
-	if (ret)
-		printf("failed to select card\n");
-
-	ret = (*switch_part)(1); /* Switch to Boot Partition 1 */
-	if (ret)
-		printf("failed to switch partition\n");
-
-	ret = (*load_image)(dev_addr, CONFIG_SYS_TEXT_BASE, 1);
-	if (ret) {
-		printf("failed to load image\n");
-		return ret;
-	}
-
-	ret = spl_parse_image_header(spl_image, (void *)CONFIG_SYS_TEXT_BASE);
-	if (ret)
-		return ret;
-
-	ret = (*load_image)(dev_addr, spl_image->load_addr,
-			    spl_image->size / 512);
-	if (ret) {
-		printf("failed to load image\n");
-		return ret;
-	}
-
-	return 0;
-}
-SPL_LOAD_IMAGE_METHOD("eMMC", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
diff --git a/arch/arm/mach-uniphier/clk/Makefile b/arch/arm/mach-uniphier/clk/Makefile
index 43df670..4134197 100644
--- a/arch/arm/mach-uniphier/clk/Makefile
+++ b/arch/arm/mach-uniphier/clk/Makefile
@@ -24,7 +24,7 @@
 obj-$(CONFIG_ARCH_UNIPHIER_PXS2)	+= clk-pxs2.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD6B)	+= clk-pxs2.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= clk-ld11.o pll-ld11.o
-obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= pll-ld20.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= clk-ld20.o pll-ld20.o
 obj-$(CONFIG_ARCH_UNIPHIER_PXS3)	+= pll-pxs3.o
 
 endif
diff --git a/arch/arm/mach-uniphier/clk/clk-ld11.c b/arch/arm/mach-uniphier/clk/clk-ld11.c
index 58069cb..a4dcde7 100644
--- a/arch/arm/mach-uniphier/clk/clk-ld11.c
+++ b/arch/arm/mach-uniphier/clk/clk-ld11.c
@@ -9,16 +9,17 @@
 #include <linux/bitops.h>
 #include <linux/io.h>
 
-#include "../boot-mode/boot-device.h"
 #include "../init.h"
 #include "../sc64-regs.h"
 #include "../sg-regs.h"
 
+#define SDCTRL_EMMC_HW_RESET	0x59810280
+
 void uniphier_ld11_clk_init(void)
 {
 	/* if booted from a device other than USB, without stand-by MPU */
 	if ((readl(SG_PINMON0) & BIT(27)) &&
-	    spl_boot_device_raw() != BOOT_DEVICE_USB) {
+	    uniphier_boot_device_raw() != BOOT_DEVICE_USB) {
 		writel(1, SG_ETPHYPSHUT);
 		writel(1, SG_ETPHYCNT);
 
@@ -29,6 +30,9 @@
 		writel(7, SG_ETPHYCNT);
 	}
 
+	/* TODO: use "mmc-pwrseq-emmc" */
+	writel(1, SDCTRL_EMMC_HW_RESET);
+
 #ifdef CONFIG_USB_EHCI
 	{
 		/* FIXME: the current clk driver can not handle parents */
diff --git a/arch/arm/mach-uniphier/clk/clk-ld20.c b/arch/arm/mach-uniphier/clk/clk-ld20.c
new file mode 100644
index 0000000..5bb560c
--- /dev/null
+++ b/arch/arm/mach-uniphier/clk/clk-ld20.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2017 Socionext Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <linux/io.h>
+
+#include "../init.h"
+
+#define SDCTRL_EMMC_HW_RESET	0x59810280
+
+void uniphier_ld20_clk_init(void)
+{
+	/* TODO: use "mmc-pwrseq-emmc" */
+	writel(1, SDCTRL_EMMC_HW_RESET);
+}
diff --git a/arch/arm/mach-uniphier/clk/pll-base-ld20.c b/arch/arm/mach-uniphier/clk/pll-base-ld20.c
index c66f083..697eb7a 100644
--- a/arch/arm/mach-uniphier/clk/pll-base-ld20.c
+++ b/arch/arm/mach-uniphier/clk/pll-base-ld20.c
@@ -18,6 +18,8 @@
 #define SC_PLLCTRL_SSC_EN		BIT(31)
 #define SC_PLLCTRL2_NRSTDS		BIT(28)
 #define SC_PLLCTRL2_SSC_JK_MASK		GENMASK(26, 0)
+#define SC_PLLCTRL3_REGI_SHIFT		16
+#define SC_PLLCTRL3_REGI_MASK		GENMASK(19, 16)
 
 /* PLL type: VPLL27 */
 #define SC_VPLL27CTRL_WP		BIT(0)
@@ -77,6 +79,25 @@
 	return 0;
 }
 
+int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi)
+{
+	void __iomem *base;
+	u32 tmp;
+
+	base = ioremap(reg_base, SZ_16);
+	if (!base)
+		return -ENOMEM;
+
+	tmp = readl(base + 8);	/* SSCPLLCTRL */
+	tmp &= ~SC_PLLCTRL3_REGI_MASK;
+	tmp |= regi << SC_PLLCTRL3_REGI_SHIFT;
+	writel(tmp, base + 8);
+
+	iounmap(base);
+
+	return 0;
+}
+
 int uniphier_ld20_vpll27_init(unsigned long reg_base)
 {
 	void __iomem *base;
diff --git a/arch/arm/mach-uniphier/clk/pll-ld11.c b/arch/arm/mach-uniphier/clk/pll-ld11.c
index 7746deb..02befa2 100644
--- a/arch/arm/mach-uniphier/clk/pll-ld11.c
+++ b/arch/arm/mach-uniphier/clk/pll-ld11.c
@@ -18,6 +18,8 @@
 	uniphier_ld20_sscpll_init(SC_MPLLCTRL, 1600, 1, 2);	/* 1500MHz -> 1600MHz */
 	uniphier_ld20_sscpll_init(SC_VSPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2);
 
+	uniphier_ld20_sscpll_set_regi(SC_MPLLCTRL, 5);
+
 	mdelay(1);
 
 	uniphier_ld20_sscpll_ssc_en(SC_CPLLCTRL);
diff --git a/arch/arm/mach-uniphier/clk/pll.h b/arch/arm/mach-uniphier/clk/pll.h
index d7e9303..5eefc4e 100644
--- a/arch/arm/mach-uniphier/clk/pll.h
+++ b/arch/arm/mach-uniphier/clk/pll.h
@@ -15,6 +15,7 @@
 int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq,
 			      unsigned int ssc_rate, unsigned int divn);
 int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base);
+int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi);
 int uniphier_ld20_vpll27_init(unsigned long reg_base);
 int uniphier_ld20_dspll_init(unsigned long reg_base);
 
diff --git a/arch/arm/mach-uniphier/dram/umc-ld11.c b/arch/arm/mach-uniphier/dram/umc-ld11.c
index 97a9fef..69aa4f2 100644
--- a/arch/arm/mach-uniphier/dram/umc-ld11.c
+++ b/arch/arm/mach-uniphier/dram/umc-ld11.c
@@ -471,7 +471,7 @@
 
 	ddrphy_init(phy_base, freq);
 
-	for (ch = 0; ch < bd->dram_nr_ch; ch++) {
+	for (ch = 0; ch < DRAM_CH_NR; ch++) {
 		unsigned long size = bd->dram_ch[ch].size;
 		unsigned int width = bd->dram_ch[ch].width;
 
diff --git a/arch/arm/mach-uniphier/dram/umc-ld20.c b/arch/arm/mach-uniphier/dram/umc-ld20.c
index 157b915..500c1c1 100644
--- a/arch/arm/mach-uniphier/dram/umc-ld20.c
+++ b/arch/arm/mach-uniphier/dram/umc-ld20.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2016-2017 Socionext Inc.
  *
- * based on commit e732175d0b0dbc2a3855cb8ac791c538666b6fd4 of Diag
+ * based on commit 5ffd75ecd4929f22361ef65a35f0331d2fbc0f35 of Diag
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -177,12 +177,18 @@
 	       phy_base + PHY_LANE_SEL);
 }
 
+#define DDRPHY_EFUSEMON		(void *)0x5f900118
+
 static void ddrphy_init(void __iomem *phy_base, enum dram_board board, int ch)
 {
 	writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
 	while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1)))
 		cpu_relax();
-	writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
+
+	if (readl(DDRPHY_EFUSEMON) & BIT(ch))
+		writel(0x00000000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
+	else
+		writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
 
 	writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3);
 	writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1);
@@ -606,15 +612,18 @@
 		return -EINVAL;
 	}
 
-	for (ch = 0; ch < bd->dram_nr_ch; ch++) {
+	for (ch = 0; ch < DRAM_CH_NR; ch++) {
 		unsigned long size = bd->dram_ch[ch].size;
 		unsigned int width = bd->dram_ch[ch].width;
 
-		ret = umc_ch_init(umc_ch_base, phy_ch_base, board,
-				  bd->dram_freq, size / (width / 16), ch);
-		if (ret) {
-			pr_err("failed to initialize UMC ch%d\n", ch);
-			return ret;
+		if (size) {
+			ret = umc_ch_init(umc_ch_base, phy_ch_base, board,
+					  bd->dram_freq, size / (width / 16),
+					  ch);
+			if (ret) {
+				pr_err("failed to initialize UMC ch%d\n", ch);
+				return ret;
+			}
 		}
 
 		umc_ch_base += 0x00200000;
diff --git a/arch/arm/mach-uniphier/dram/umc-pxs2.c b/arch/arm/mach-uniphier/dram/umc-pxs2.c
index 05a62de..7fa29f1 100644
--- a/arch/arm/mach-uniphier/dram/umc-pxs2.c
+++ b/arch/arm/mach-uniphier/dram/umc-pxs2.c
@@ -619,15 +619,17 @@
 		return -EINVAL;
 	}
 
-	for (ch = 0; ch < bd->dram_nr_ch; ch++) {
+	for (ch = 0; ch < DRAM_CH_NR; ch++) {
 		unsigned long size = bd->dram_ch[ch].size;
 		unsigned int width = bd->dram_ch[ch].width;
 
-		ret = umc_ch_init(umc_ch_base, freq, size / (width / 16),
-				  width, ch);
-		if (ret) {
-			pr_err("failed to initialize UMC ch%d\n", ch);
-			return ret;
+		if (size) {
+			ret = umc_ch_init(umc_ch_base, freq,
+					  size / (width / 16), width, ch);
+			if (ret) {
+				pr_err("failed to initialize UMC ch%d\n", ch);
+				return ret;
+			}
 		}
 
 		umc_ch_base += 0x00200000;
diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c
index 881062d..d9f6c16 100644
--- a/arch/arm/mach-uniphier/dram_init.c
+++ b/arch/arm/mach-uniphier/dram_init.c
@@ -11,10 +11,12 @@
 #include <linux/errno.h>
 #include <linux/sizes.h>
 
-#include "init.h"
 #include "sg-regs.h"
 #include "soc-info.h"
 
+#define pr_warn(fmt, args...)	printf(fmt, ##args)
+#define pr_err(fmt, args...)	printf(fmt, ##args)
+
 DECLARE_GLOBAL_DATA_PTR;
 
 struct uniphier_memif_data {
@@ -76,7 +78,12 @@
 };
 UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_memif_data, uniphier_memif_data)
 
-static int uniphier_memconf_decode(struct uniphier_dram_ch *dram_ch)
+struct uniphier_dram_map {
+	unsigned long base;
+	unsigned long size;
+};
+
+static int uniphier_memconf_decode(struct uniphier_dram_map *dram_map)
 {
 	const struct uniphier_memif_data *data;
 	unsigned long size;
@@ -91,7 +98,7 @@
 	val = readl(SG_MEMCONF);
 
 	/* set up ch0 */
-	dram_ch[0].base = CONFIG_SYS_SDRAM_BASE;
+	dram_map[0].base = CONFIG_SYS_SDRAM_BASE;
 
 	switch (val & SG_MEMCONF_CH0_SZ_MASK) {
 	case SG_MEMCONF_CH0_SZ_64M:
@@ -110,27 +117,27 @@
 		size = SZ_1G;
 		break;
 	default:
-		pr_err("error: invald value is set to MEMCONF ch0 size\n");
+		pr_err("error: invalid value is set to MEMCONF ch0 size\n");
 		return -EINVAL;
 	}
 
 	if ((val & SG_MEMCONF_CH0_NUM_MASK) == SG_MEMCONF_CH0_NUM_2)
 		size *= 2;
 
-	dram_ch[0].size = size;
+	dram_map[0].size = size;
 
 	/* set up ch1 */
-	dram_ch[1].base = dram_ch[0].base + size;
+	dram_map[1].base = dram_map[0].base + size;
 
 	if (val & SG_MEMCONF_SPARSEMEM) {
-		if (dram_ch[1].base > data->sparse_ch1_base) {
+		if (dram_map[1].base > data->sparse_ch1_base) {
 			pr_warn("Sparse mem is enabled, but ch0 and ch1 overlap\n");
 			pr_warn("Only ch0 is available\n");
-			dram_ch[1].base = 0;
+			dram_map[1].base = 0;
 			return 0;
 		}
 
-		dram_ch[1].base = data->sparse_ch1_base;
+		dram_map[1].base = data->sparse_ch1_base;
 	}
 
 	switch (val & SG_MEMCONF_CH1_SZ_MASK) {
@@ -150,20 +157,20 @@
 		size = SZ_1G;
 		break;
 	default:
-		pr_err("error: invald value is set to MEMCONF ch1 size\n");
+		pr_err("error: invalid value is set to MEMCONF ch1 size\n");
 		return -EINVAL;
 	}
 
 	if ((val & SG_MEMCONF_CH1_NUM_MASK) == SG_MEMCONF_CH1_NUM_2)
 		size *= 2;
 
-	dram_ch[1].size = size;
+	dram_map[1].size = size;
 
-	if (!data->have_ch2)
+	if (!data->have_ch2 || val & SG_MEMCONF_CH2_DISABLE)
 		return 0;
 
 	/* set up ch2 */
-	dram_ch[2].base = dram_ch[1].base + size;
+	dram_map[2].base = dram_map[1].base + size;
 
 	switch (val & SG_MEMCONF_CH2_SZ_MASK) {
 	case SG_MEMCONF_CH2_SZ_64M:
@@ -182,32 +189,32 @@
 		size = SZ_1G;
 		break;
 	default:
-		pr_err("error: invald value is set to MEMCONF ch2 size\n");
+		pr_err("error: invalid value is set to MEMCONF ch2 size\n");
 		return -EINVAL;
 	}
 
 	if ((val & SG_MEMCONF_CH2_NUM_MASK) == SG_MEMCONF_CH2_NUM_2)
 		size *= 2;
 
-	dram_ch[2].size = size;
+	dram_map[2].size = size;
 
 	return 0;
 }
 
 int dram_init(void)
 {
-	struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH] = {};
+	struct uniphier_dram_map dram_map[3] = {};
 	int ret, i;
 
 	gd->ram_size = 0;
 
-	ret = uniphier_memconf_decode(dram_ch);
+	ret = uniphier_memconf_decode(dram_map);
 	if (ret)
 		return ret;
 
-	for (i = 0; i < ARRAY_SIZE(dram_ch); i++) {
+	for (i = 0; i < ARRAY_SIZE(dram_map); i++) {
 
-		if (!dram_ch[i].size)
+		if (!dram_map[i].size)
 			break;
 
 		/*
@@ -215,11 +222,11 @@
 		 * but it does not expect sparse memory.  We use the first
 		 * contiguous chunk here.
 		 */
-		if (i > 0 &&
-		    dram_ch[i - 1].base + dram_ch[i - 1].size < dram_ch[i].base)
+		if (i > 0 && dram_map[i - 1].base + dram_map[i - 1].size <
+							dram_map[i].base)
 			break;
 
-		gd->ram_size += dram_ch[i].size;
+		gd->ram_size += dram_map[i].size;
 	}
 
 	return 0;
@@ -227,17 +234,17 @@
 
 void dram_init_banksize(void)
 {
-	struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH] = {};
+	struct uniphier_dram_map dram_map[3] = {};
 	int i;
 
-	uniphier_memconf_decode(dram_ch);
+	uniphier_memconf_decode(dram_map);
 
-	for (i = 0; i < ARRAY_SIZE(dram_ch); i++) {
+	for (i = 0; i < ARRAY_SIZE(dram_map); i++) {
 		if (i >= ARRAY_SIZE(gd->bd->bi_dram))
 			break;
 
-		gd->bd->bi_dram[i].start = dram_ch[i].base;
-		gd->bd->bi_dram[i].size = dram_ch[i].size;
+		gd->bd->bi_dram[i].start = dram_map[i].base;
+		gd->bd->bi_dram[i].size = dram_map[i].size;
 	}
 }
 
@@ -256,6 +263,9 @@
 		return 0;
 
 	for (i = 0; i < ARRAY_SIZE(gd->bd->bi_dram); i++) {
+		if (!gd->bd->bi_dram[i].size)
+			continue;
+
 		rsv_addr = gd->bd->bi_dram[i].start + gd->bd->bi_dram[i].size;
 		rsv_addr -= rsv_size;
 
diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h
index 453e68a..5c45f2d 100644
--- a/arch/arm/mach-uniphier/init.h
+++ b/arch/arm/mach-uniphier/init.h
@@ -13,18 +13,17 @@
 #define UNIPHIER_MAX_NR_DRAM_CH		3
 
 struct uniphier_dram_ch {
-	unsigned long base;
 	unsigned long size;
 	unsigned int width;
 };
 
 struct uniphier_board_data {
 	unsigned int dram_freq;
-	unsigned int dram_nr_ch;
 	struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH];
 	unsigned int flags;
 
-#define UNIPHIER_BD_DDR3PLUS			BIT(2)
+#define UNIPHIER_BD_DRAM_SPARSE			BIT(9)
+#define UNIPHIER_BD_DDR3PLUS			BIT(8)
 
 #define UNIPHIER_BD_BOARD_GET_TYPE(f)		((f) & 0x7)
 #define UNIPHIER_BD_BOARD_LD20_REF		0	/* LD20 reference */
@@ -119,12 +118,16 @@
 void uniphier_pro5_clk_init(void);
 void uniphier_pxs2_clk_init(void);
 void uniphier_ld11_clk_init(void);
+void uniphier_ld20_clk_init(void);
 
+unsigned int uniphier_boot_device_raw(void);
 int uniphier_pin_init(const char *pinconfig_name);
 void uniphier_smp_kick_all_cpus(void);
 void cci500_init(int nr_slaves);
 
+#undef pr_warn
 #define pr_warn(fmt, args...)	printf(fmt, ##args)
+#undef pr_err
 #define pr_err(fmt, args...)	printf(fmt, ##args)
 
 #endif /* __MACH_INIT_H */
diff --git a/arch/arm/mach-uniphier/memconf.c b/arch/arm/mach-uniphier/memconf.c
index dcfc645..4ced2cb 100644
--- a/arch/arm/mach-uniphier/memconf.c
+++ b/arch/arm/mach-uniphier/memconf.c
@@ -93,7 +93,7 @@
 	}
 
 	/* is sparse mem? */
-	if (bd->dram_ch[0].base + bd->dram_ch[0].size < bd->dram_ch[1].base)
+	if (bd->flags & UNIPHIER_BD_DRAM_SPARSE)
 		val |= SG_MEMCONF_SPARSEMEM;
 
 	if (!have_ch2)
diff --git a/arch/arm/mach-uniphier/micro-support-card.c b/arch/arm/mach-uniphier/micro-support-card.c
index 2b231ac..8a30341 100644
--- a/arch/arm/mach-uniphier/micro-support-card.c
+++ b/arch/arm/mach-uniphier/micro-support-card.c
@@ -43,18 +43,13 @@
 	revision &= 0xff;
 
 	/* revision 3.6.x card changed the revision format */
-	printf("(CPLD version %s%d.%d)\n", revision >> 4 == 6 ? "3." : "",
+	printf("SC:    Micro Support Card (CPLD version %s%d.%d)\n",
+	       revision >> 4 == 6 ? "3." : "",
 	       revision >> 4, revision & 0xf);
 
 	return 0;
 }
 
-int checkboard(void)
-{
-	printf("SC:    Micro Support Card ");
-	return support_card_show_revision();
-}
-
 void support_card_init(void)
 {
 	support_card_reset();
@@ -64,6 +59,8 @@
 	 */
 	udelay(200);
 	support_card_reset_deassert();
+
+	support_card_show_revision();
 }
 
 #if defined(CONFIG_SMC911X)
diff --git a/arch/arm/mach-uniphier/mmc-boot-mode.c b/arch/arm/mach-uniphier/mmc-boot-mode.c
new file mode 100644
index 0000000..d60c578
--- /dev/null
+++ b/arch/arm/mach-uniphier/mmc-boot-mode.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <spl.h>
+
+u32 spl_boot_mode(const u32 boot_device)
+{
+	struct mmc *mmc;
+
+	/*
+	 * work around a bug in the Boot ROM of PH1-sLD3, LD4, Pro4, and sLD8:
+	 *
+	 * The boot ROM in these SoCs breaks the PARTITION_CONFIG [179] of
+	 * Extended CSD register; when switching to the Boot Partition 1, the
+	 * Boot ROM should issue the SWITCH command (CMD6) with Set Bits for
+	 * the Access Bits, but in fact it uses Write Byte for the Access Bits.
+	 * As a result, the BOOT_PARTITION_ENABLE field of the PARTITION_CONFIG
+	 * is lost.  This bug was fixed for PH1-Pro5 and later SoCs.
+	 *
+	 * Fixup mmc->part_config here because it is used to determine the
+	 * partition which the U-Boot image is read from.
+	 */
+	mmc = find_mmc_device(0);
+	mmc->part_config &= ~EXT_CSD_BOOT_PART_NUM(PART_ACCESS_MASK);
+	mmc->part_config |= EXT_CSD_BOOT_PARTITION_ENABLE;
+
+	return MMCSD_MODE_EMMCBOOT;
+}
diff --git a/arch/arm/mach-uniphier/mmc-first-dev.c b/arch/arm/mach-uniphier/mmc-first-dev.c
new file mode 100644
index 0000000..8c45229
--- /dev/null
+++ b/arch/arm/mach-uniphier/mmc-first-dev.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include <linux/errno.h>
+
+static int find_first_mmc_device(void)
+{
+	struct mmc *mmc;
+	int i;
+
+	for (i = 0; (mmc = find_mmc_device(i)); i++) {
+		if (!mmc_init(mmc) && IS_MMC(mmc))
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+int mmc_get_env_dev(void)
+{
+	return find_first_mmc_device();
+}
+
+static int do_mmcsetn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int dev;
+
+	dev = find_first_mmc_device();
+	if (dev < 0)
+		return CMD_RET_FAILURE;
+
+	setenv_ulong("mmc_first_dev", dev);
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+	   mmcsetn,	1,	1,	do_mmcsetn,
+	"Set the first MMC (not SD) dev number to \"mmc_first_dev\" environment",
+	""
+);
diff --git a/arch/arm/mach-uniphier/spl_board_init.c b/arch/arm/mach-uniphier/spl_board_init.c
index da749a3..0079a08 100644
--- a/arch/arm/mach-uniphier/spl_board_init.c
+++ b/arch/arm/mach-uniphier/spl_board_init.c
@@ -168,4 +168,8 @@
 		pr_err("failed to init DRAM\n");
 		hang();
 	}
+
+#ifdef CONFIG_ARM64
+	dcache_disable();
+#endif
 }
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5f9597b..dfdd756 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -80,6 +80,20 @@
 
 endchoice
 
+# subarchitectures-specific options below
+config INTEL_MID
+	bool "Intel MID platform support"
+	help
+	  Select to build a U-Boot capable of supporting Intel MID
+	  (Mobile Internet Device) platform systems which do not have
+	  the PCI legacy interfaces.
+
+	  If you are building for a PC class system say N here.
+
+	  Intel MID platforms are based on an Intel processor and
+	  chipset which consume less power than most of the x86
+	  derivatives.
+
 # board-specific options below
 source "board/advantech/Kconfig"
 source "board/congatec/Kconfig"
diff --git a/arch/x86/cpu/i386/interrupt.c b/arch/x86/cpu/i386/interrupt.c
index a058303..ba576fe 100644
--- a/arch/x86/cpu/i386/interrupt.c
+++ b/arch/x86/cpu/i386/interrupt.c
@@ -28,7 +28,7 @@
 	".type irq_"#x", @function\n" \
 	"irq_"#x":\n" \
 	"pushl $"#x"\n" \
-	"jmp irq_common_entry\n"
+	"jmp.d32 irq_common_entry\n"
 
 static char *exceptions[] = {
 	"Divide Error",
diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c
index 988073c..cfd9bb4 100644
--- a/arch/x86/cpu/mp_init.c
+++ b/arch/x86/cpu/mp_init.c
@@ -248,7 +248,8 @@
 	if (!stack)
 		return -ENOMEM;
 	params->stack_top = (u32)(stack + size);
-#if !defined(CONFIG_QEMU) && !defined(CONFIG_HAVE_FSP)
+#if !defined(CONFIG_QEMU) && !defined(CONFIG_HAVE_FSP) && \
+	!defined(CONFIG_INTEL_MID)
 	params->microcode_ptr = ucode_base;
 	debug("Microcode at %x\n", params->microcode_ptr);
 #endif
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index b6b0f2b..aafbeb0 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -246,6 +246,10 @@
 			hdr->setup_move_size = 0x9100;
 		}
 
+#if defined(CONFIG_INTEL_MID)
+		hdr->hardware_subarch = X86_SUBARCH_INTEL_MID;
+#endif
+
 		/* build command line at COMMAND_LINE_OFFSET */
 		build_command_line(cmd_line, auto_boot);
 	}
diff --git a/common/splash_source.c b/common/splash_source.c
index a5eeb3f..d1647c8 100644
--- a/common/splash_source.c
+++ b/common/splash_source.c
@@ -216,6 +216,7 @@
 {
 	int res = 0;
 	loff_t bmp_size;
+	loff_t actread;
 	char *splash_file;
 
 	splash_file = getenv("splashfile");
@@ -251,7 +252,7 @@
 	}
 
 	splash_select_fs_dev(location);
-	res = fs_read(splash_file, bmp_load_addr, 0, 0, NULL);
+	res = fs_read(splash_file, bmp_load_addr, 0, 0, &actread);
 
 out:
 	if (location->ubivol != NULL)
diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig
index e425260..3d3f85f 100644
--- a/configs/am335x_boneblack_vboot_defconfig
+++ b/configs/am335x_boneblack_vboot_defconfig
@@ -8,7 +8,7 @@
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
 CONFIG_FIT_VERBOSE=y
-CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT,ENABLE_VBOOT"
+CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
diff --git a/configs/uniphier_ld11_defconfig b/configs/uniphier_ld11_defconfig
index f14ae04..e5cfab6 100644
--- a/configs/uniphier_ld11_defconfig
+++ b/configs/uniphier_ld11_defconfig
@@ -10,8 +10,10 @@
 CONFIG_SPL=y
 CONFIG_SPL_NOR_SUPPORT=y
 CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CONFIG=y
 # CONFIG_CMD_XIMG is not set
 # CONFIG_CMD_ENV_EXISTS is not set
+CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
@@ -23,6 +25,8 @@
 CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_CMD_FAT=y
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_GPIO_UNIPHIER=y
@@ -31,7 +35,6 @@
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_CADENCE=y
-CONFIG_MTD_NOR_FLASH=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_GENERIC=y
diff --git a/configs/uniphier_ld20_defconfig b/configs/uniphier_ld20_defconfig
index c065bf2..6251359 100644
--- a/configs/uniphier_ld20_defconfig
+++ b/configs/uniphier_ld20_defconfig
@@ -10,8 +10,10 @@
 CONFIG_SPL=y
 CONFIG_SPL_NOR_SUPPORT=y
 CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CONFIG=y
 # CONFIG_CMD_XIMG is not set
 # CONFIG_CMD_ENV_EXISTS is not set
+CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
@@ -23,6 +25,8 @@
 CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_CMD_FAT=y
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_GPIO_UNIPHIER=y
@@ -31,7 +35,6 @@
 CONFIG_MMC_UNIPHIER=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_CADENCE=y
-CONFIG_MTD_NOR_FLASH=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig
index b9a9524..68bca19 100644
--- a/configs/uniphier_ld4_sld8_defconfig
+++ b/configs/uniphier_ld4_sld8_defconfig
@@ -12,9 +12,11 @@
 CONFIG_SPL=y
 CONFIG_SPL_NOR_SUPPORT=y
 CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CONFIG=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_XIMG is not set
 # CONFIG_CMD_ENV_EXISTS is not set
+CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_NAND=y
 CONFIG_CMD_I2C=y
@@ -27,12 +29,13 @@
 CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_CMD_FAT=y
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_GPIO_UNIPHIER=y
 CONFIG_MISC=y
 CONFIG_I2C_EEPROM=y
 CONFIG_MMC_UNIPHIER=y
-CONFIG_MTD_NOR_FLASH=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_pro4_defconfig b/configs/uniphier_pro4_defconfig
index 0b83a1b..fc72889 100644
--- a/configs/uniphier_pro4_defconfig
+++ b/configs/uniphier_pro4_defconfig
@@ -11,9 +11,11 @@
 CONFIG_SPL=y
 CONFIG_SPL_NOR_SUPPORT=y
 CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CONFIG=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_XIMG is not set
 # CONFIG_CMD_ENV_EXISTS is not set
+CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_NAND=y
 CONFIG_CMD_I2C=y
@@ -26,12 +28,13 @@
 CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_CMD_FAT=y
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_GPIO_UNIPHIER=y
 CONFIG_MISC=y
 CONFIG_I2C_EEPROM=y
 CONFIG_MMC_UNIPHIER=y
-CONFIG_MTD_NOR_FLASH=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_pxs2_ld6b_defconfig
index 7e6f0a0..7a358e3 100644
--- a/configs/uniphier_pxs2_ld6b_defconfig
+++ b/configs/uniphier_pxs2_ld6b_defconfig
@@ -12,9 +12,11 @@
 CONFIG_SPL=y
 CONFIG_SPL_NOR_SUPPORT=y
 CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CONFIG=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_XIMG is not set
 # CONFIG_CMD_ENV_EXISTS is not set
+CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_NAND=y
 CONFIG_CMD_I2C=y
@@ -27,12 +29,13 @@
 CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_CMD_FAT=y
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_GPIO_UNIPHIER=y
 CONFIG_MISC=y
 CONFIG_I2C_EEPROM=y
 CONFIG_MMC_UNIPHIER=y
-CONFIG_MTD_NOR_FLASH=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_sld3_defconfig b/configs/uniphier_sld3_defconfig
index f1f2a3f..ef5d1e4 100644
--- a/configs/uniphier_sld3_defconfig
+++ b/configs/uniphier_sld3_defconfig
@@ -12,9 +12,11 @@
 CONFIG_SPL=y
 CONFIG_SPL_NOR_SUPPORT=y
 CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CONFIG=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_XIMG is not set
 # CONFIG_CMD_ENV_EXISTS is not set
+CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_NAND=y
 CONFIG_CMD_I2C=y
@@ -27,12 +29,13 @@
 CONFIG_CMD_TIME=y
 # CONFIG_CMD_MISC is not set
 CONFIG_CMD_FAT=y
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_GPIO_UNIPHIER=y
 CONFIG_MISC=y
 CONFIG_I2C_EEPROM=y
 CONFIG_MMC_UNIPHIER=y
-CONFIG_MTD_NOR_FLASH=y
 CONFIG_NAND_DENALI=y
 CONFIG_SYS_NAND_DENALI_64BIT=y
 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_v8_defconfig b/configs/uniphier_v8_defconfig
index a8f2816..85f8da5 100644
--- a/configs/uniphier_v8_defconfig
+++ b/configs/uniphier_v8_defconfig
@@ -7,8 +7,10 @@
 CONFIG_DEFAULT_DEVICE_TREE="uniphier-ld20-ref"
 # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
 CONFIG_HUSH_PARSER=y
+CONFIG_CMD_CONFIG=y
 # CONFIG_CMD_XIMG is not set
 # CONFIG_CMD_ENV_EXISTS is not set
+CONFIG_CMD_GPT=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
@@ -27,8 +29,9 @@
 CONFIG_MMC_UNIPHIER=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_CADENCE=y
-CONFIG_MTD_NOR_FLASH=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
 CONFIG_USB_STORAGE=y
diff --git a/doc/README.uniphier b/doc/README.uniphier
index 539b1f2..f79659c 100644
--- a/doc/README.uniphier
+++ b/doc/README.uniphier
@@ -75,7 +75,7 @@
 Write the following to the NAND device:
 
  - spl/u-boot-spl.bin at the offset address 0x00000000
- - u-boot.bin         at the offset address 0x00010000
+ - u-boot.bin         at the offset address 0x00020000
 
 or
 
@@ -94,7 +94,7 @@
 Write the following to the Boot partition 1 of the eMMC device:
 
  - spl/u-boot-spl.bin at the offset address 0x00000000
- - u-boot.bin         at the offset address 0x00010000
+ - u-boot.bin         at the offset address 0x00020000
 
 or
 
@@ -179,4 +179,4 @@
 
 --
 Masahiro Yamada <yamada.masahiro@socionext.com>
-Oct. 2016
+Jan. 2017
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 51144b8..d8e9948 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -5,6 +5,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <common.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/sizes.h>
@@ -15,6 +16,7 @@
 
 #define UNIPHIER_PINCTRL_PINMUX_BASE	0x1000
 #define UNIPHIER_PINCTRL_LOAD_PINMUX	0x1700
+#define UNIPHIER_PINCTRL_PUPDCTRL_BASE	0x1a00
 #define UNIPHIER_PINCTRL_IECTRL		0x1d00
 
 static const char *uniphier_pinctrl_dummy_name = "_dummy";
@@ -55,8 +57,8 @@
 	return priv->socdata->functions[selector];
 }
 
-static void uniphier_pinconf_input_enable_perpin(struct udevice *dev,
-						 unsigned pin)
+static int uniphier_pinconf_input_enable_perpin(struct udevice *dev,
+						unsigned int pin, int enable)
 {
 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 	unsigned reg;
@@ -66,18 +68,30 @@
 	mask = BIT(pin % 32);
 
 	tmp = readl(priv->base + reg);
-	tmp |= mask;
+	if (enable)
+		tmp |= mask;
+	else
+		tmp &= ~mask;
 	writel(tmp, priv->base + reg);
+
+	return 0;
 }
 
-static void uniphier_pinconf_input_enable_legacy(struct udevice *dev,
-						 unsigned pin)
+static int uniphier_pinconf_input_enable_legacy(struct udevice *dev,
+						unsigned int pin, int enable)
 {
 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 	int pins_count = priv->socdata->pins_count;
 	const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
 	int i;
 
+	/*
+	 * Multiple pins share one input enable, per-pin disabling is
+	 * impossible.
+	 */
+	if (!enable)
+		return -EINVAL;
+
 	for (i = 0; i < pins_count; i++) {
 		if (pins[i].number == pin) {
 			unsigned int iectrl;
@@ -89,18 +103,115 @@
 			writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
 		}
 	}
+
+	return 0;
 }
 
-static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin)
+static int uniphier_pinconf_input_enable(struct udevice *dev,
+					 unsigned int pin, int enable)
 {
 	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
 
 	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
-		uniphier_pinconf_input_enable_perpin(dev, pin);
+		return uniphier_pinconf_input_enable_perpin(dev, pin, enable);
 	else
-		uniphier_pinconf_input_enable_legacy(dev, pin);
+		return uniphier_pinconf_input_enable_legacy(dev, pin, enable);
 }
 
+#if CONFIG_IS_ENABLED(PINCONF)
+
+static const struct pinconf_param uniphier_pinconf_params[] = {
+	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+	{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
+	{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
+	{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
+};
+
+static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin,
+				     unsigned int param, unsigned int arg)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+	unsigned int enable = 1;
+	unsigned int reg;
+	u32 mask, tmp;
+
+	if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE))
+		return -ENOTSUPP;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		enable = 0;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (arg == 0)	/* total bias is not supported */
+			return -EINVAL;
+		break;
+	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+		if (arg == 0)	/* configuration ignored */
+			return 0;
+	default:
+		BUG();
+	}
+
+	reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pin / 32 * 4;
+	mask = BIT(pin % 32);
+
+	tmp = readl(priv->base + reg);
+	if (enable)
+		tmp |= mask;
+	else
+		tmp &= ~mask;
+	writel(tmp, priv->base + reg);
+
+	return 0;
+}
+
+static int uniphier_pinconf_set_one(struct udevice *dev, unsigned int pin,
+				    unsigned int param, unsigned int arg)
+{
+	int ret;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+	case PIN_CONFIG_BIAS_PULL_UP:
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+		ret = uniphier_pinconf_bias_set(dev, pin, param, arg);
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		ret = uniphier_pinconf_input_enable(dev, pin, arg);
+		break;
+	default:
+		printf("unsupported configuration parameter %u\n", param);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int uniphier_pinconf_group_set(struct udevice *dev,
+				      unsigned int group_selector,
+				      unsigned int param, unsigned int arg)
+{
+	struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct uniphier_pinctrl_group *grp =
+					&priv->socdata->groups[group_selector];
+	int i, ret;
+
+	for (i = 0; i < grp->num_pins; i++) {
+		ret = uniphier_pinconf_set_one(dev, grp->pins[i], param, arg);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_IS_ENABLED(PINCONF) */
+
 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
 				    int muxval)
 {
@@ -112,7 +223,7 @@
 	u32 tmp;
 
 	/* some pins need input-enabling */
-	uniphier_pinconf_input_enable(dev, pin);
+	uniphier_pinconf_input_enable(dev, pin, 1);
 
 	if (muxval < 0)
 		return;		/* dedicated pin; nothing to do for pin-mux */
@@ -174,6 +285,11 @@
 	.get_functions_count = uniphier_pinmux_get_functions_count,
 	.get_function_name = uniphier_pinmux_get_function_name,
 	.pinmux_group_set = uniphier_pinmux_group_set,
+#if CONFIG_IS_ENABLED(PINCONF)
+	.pinconf_num_params = ARRAY_SIZE(uniphier_pinconf_params),
+	.pinconf_params = uniphier_pinconf_params,
+	.pinconf_group_set = uniphier_pinconf_group_set,
+#endif
 	.set_state = pinctrl_generic_set_state,
 };
 
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
index 1d318d8..53c37cd 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
@@ -92,7 +92,8 @@
 	.groups_count = ARRAY_SIZE(uniphier_ld11_groups),
 	.functions = uniphier_ld11_functions,
 	.functions_count = ARRAY_SIZE(uniphier_ld11_functions),
-	.caps = UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
+	.caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE |
+		UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
 };
 
 static int uniphier_ld11_pinctrl_probe(struct udevice *dev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
index 0c46450..5a7d142 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
@@ -106,7 +106,8 @@
 	.groups_count = ARRAY_SIZE(uniphier_ld20_groups),
 	.functions = uniphier_ld20_functions,
 	.functions_count = ARRAY_SIZE(uniphier_ld20_functions),
-	.caps = UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
+	.caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE |
+		UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
 };
 
 static int uniphier_ld20_pinctrl_probe(struct udevice *dev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index 80d782c8..b25c7ea 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -140,6 +140,7 @@
 	.groups_count = ARRAY_SIZE(uniphier_ld6b_groups),
 	.functions = uniphier_ld6b_functions,
 	.functions_count = ARRAY_SIZE(uniphier_ld6b_functions),
+	.caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE,
 };
 
 static int uniphier_ld6b_pinctrl_probe(struct udevice *dev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 9670f25..70c90ba 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -147,7 +147,8 @@
 	.groups_count = ARRAY_SIZE(uniphier_pro5_groups),
 	.functions = uniphier_pro5_functions,
 	.functions_count = ARRAY_SIZE(uniphier_pro5_functions),
-	.caps = UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE,
+	.caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE |
+		UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE,
 };
 
 static int uniphier_pro5_pinctrl_probe(struct udevice *dev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index 1d29170..60777c3 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -140,6 +140,7 @@
 	.groups_count = ARRAY_SIZE(uniphier_pxs2_groups),
 	.functions = uniphier_pxs2_functions,
 	.functions_count = ARRAY_SIZE(uniphier_pxs2_functions),
+	.caps = UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE,
 };
 
 static int uniphier_pxs2_pinctrl_probe(struct udevice *dev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
index 21e2d37..a0eccf8 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -67,6 +67,7 @@
 	const char * const *functions;
 	int functions_count;
 	unsigned caps;
+#define UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE	BIT(3)
 #define UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL	BIT(2)
 #define UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE	BIT(1)
 #define UNIPHIER_PINCTRL_CAPS_MUX_4BIT		BIT(0)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 25ccc01..1156662 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -23,7 +23,6 @@
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <asm/arch/sys_proto.h>
 
 #include "core.h"
 #include "gadget.h"
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index 8e7c981..dfa4359 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -159,7 +159,7 @@
 	int ret;
 
 	ret = dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
-			req->length, f_dfu->blk_seq_num);
+			req->actual, f_dfu->blk_seq_num);
 	if (ret) {
 		f_dfu->dfu_status = DFU_STATUS_errUNKNOWN;
 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
@@ -178,7 +178,7 @@
 		DFU_MANIFEST_POLL_TIMEOUT;
 }
 
-static void handle_getstatus(struct usb_request *req)
+static int handle_getstatus(struct usb_request *req)
 {
 	struct dfu_status *dstat = (struct dfu_status *)req->buf;
 	struct f_dfu *f_dfu = req->context;
@@ -210,14 +210,16 @@
 	dstat->bStatus = f_dfu->dfu_status;
 	dstat->bState = f_dfu->dfu_state;
 	dstat->iString = 0;
+
+	return sizeof(struct dfu_status);
 }
 
-static void handle_getstate(struct usb_request *req)
+static int handle_getstate(struct usb_request *req)
 {
 	struct f_dfu *f_dfu = req->context;
 
 	((u8 *)req->buf)[0] = f_dfu->dfu_state;
-	req->actual = sizeof(u8);
+	return sizeof(u8);
 }
 
 static inline void to_dfu_mode(struct f_dfu *f_dfu)
@@ -268,11 +270,10 @@
 
 	switch (ctrl->bRequest) {
 	case USB_REQ_DFU_GETSTATUS:
-		handle_getstatus(req);
-		value = RET_STAT_LEN;
+		value = handle_getstatus(req);
 		break;
 	case USB_REQ_DFU_GETSTATE:
-		handle_getstate(req);
+		value = handle_getstate(req);
 		break;
 	case USB_REQ_DFU_DETACH:
 		f_dfu->dfu_state = DFU_STATE_appDETACH;
@@ -296,11 +297,10 @@
 
 	switch (ctrl->bRequest) {
 	case USB_REQ_DFU_GETSTATUS:
-		handle_getstatus(req);
-		value = RET_STAT_LEN;
+		value = handle_getstatus(req);
 		break;
 	case USB_REQ_DFU_GETSTATE:
-		handle_getstate(req);
+		value = handle_getstate(req);
 		break;
 	default:
 		f_dfu->dfu_state = DFU_STATE_appIDLE;
@@ -341,11 +341,10 @@
 		value = RET_ZLP;
 		break;
 	case USB_REQ_DFU_GETSTATUS:
-		handle_getstatus(req);
-		value = RET_STAT_LEN;
+		value = handle_getstatus(req);
 		break;
 	case USB_REQ_DFU_GETSTATE:
-		handle_getstate(req);
+		value = handle_getstate(req);
 		break;
 	case USB_REQ_DFU_DETACH:
 		/*
@@ -381,11 +380,10 @@
 
 	switch (ctrl->bRequest) {
 	case USB_REQ_DFU_GETSTATUS:
-		handle_getstatus(req);
-		value = RET_STAT_LEN;
+		value = handle_getstatus(req);
 		break;
 	case USB_REQ_DFU_GETSTATE:
-		handle_getstate(req);
+		value = handle_getstate(req);
 		break;
 	default:
 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
@@ -405,8 +403,7 @@
 
 	switch (ctrl->bRequest) {
 	case USB_REQ_DFU_GETSTATUS:
-		handle_getstatus(req);
-		value = RET_STAT_LEN;
+		value = handle_getstatus(req);
 		break;
 	default:
 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
@@ -437,11 +434,10 @@
 		value = RET_ZLP;
 		break;
 	case USB_REQ_DFU_GETSTATUS:
-		handle_getstatus(req);
-		value = RET_STAT_LEN;
+		value = handle_getstatus(req);
 		break;
 	case USB_REQ_DFU_GETSTATE:
-		handle_getstate(req);
+		value = handle_getstate(req);
 		break;
 	default:
 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
@@ -463,13 +459,12 @@
 	case USB_REQ_DFU_GETSTATUS:
 		/* We're MainfestationTolerant */
 		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST;
-		handle_getstatus(req);
+		value = handle_getstatus(req);
 		f_dfu->blk_seq_num = 0;
-		value = RET_STAT_LEN;
 		req->complete = dnload_request_flush;
 		break;
 	case USB_REQ_DFU_GETSTATE:
-		handle_getstate(req);
+		value = handle_getstate(req);
 		break;
 	default:
 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
@@ -491,13 +486,12 @@
 	case USB_REQ_DFU_GETSTATUS:
 		/* We're MainfestationTolerant */
 		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
-		handle_getstatus(req);
+		value = handle_getstatus(req);
 		f_dfu->blk_seq_num = 0;
-		value = RET_STAT_LEN;
 		puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
 		break;
 	case USB_REQ_DFU_GETSTATE:
-		handle_getstate(req);
+		value = handle_getstate(req);
 		break;
 	default:
 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
@@ -530,11 +524,10 @@
 		value = RET_ZLP;
 		break;
 	case USB_REQ_DFU_GETSTATUS:
-		handle_getstatus(req);
-		value = RET_STAT_LEN;
+		value = handle_getstatus(req);
 		break;
 	case USB_REQ_DFU_GETSTATE:
-		handle_getstate(req);
+		value = handle_getstate(req);
 		break;
 	default:
 		f_dfu->dfu_state = DFU_STATE_dfuERROR;
@@ -554,11 +547,10 @@
 
 	switch (ctrl->bRequest) {
 	case USB_REQ_DFU_GETSTATUS:
-		handle_getstatus(req);
-		value = RET_STAT_LEN;
+		value = handle_getstatus(req);
 		break;
 	case USB_REQ_DFU_GETSTATE:
-		handle_getstate(req);
+		value = handle_getstate(req);
 		break;
 	case USB_REQ_DFU_CLRSTATUS:
 		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
@@ -654,7 +646,7 @@
 	struct usb_interface_descriptor *d;
 	int i = 0;
 
-	f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1);
+	f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 2);
 	if (!f_dfu->function)
 		goto enomem;
 
@@ -673,6 +665,14 @@
 
 		f_dfu->function[i] = (struct usb_descriptor_header *)d;
 	}
+
+	/* add DFU Functional Descriptor */
+	f_dfu->function[i] = calloc(sizeof(dfu_func), 1);
+	if (!f_dfu->function[i])
+		goto enomem;
+	memcpy(f_dfu->function[i], &dfu_func, sizeof(dfu_func));
+
+	i++;
 	f_dfu->function[i] = NULL;
 
 	return 0;
@@ -691,6 +691,7 @@
 {
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_dfu *f_dfu = func_to_dfu(f);
+	const char *s;
 	int alt_num = dfu_get_alt_number();
 	int rv, id, i;
 
@@ -724,6 +725,10 @@
 
 	cdev->req->context = f_dfu;
 
+	s = getenv("serial#");
+	if (s)
+		g_dnl_set_serialnumber((char *)s);
+
 error:
 	return rv;
 }
diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
index 0c29954..a256577 100644
--- a/drivers/usb/gadget/f_dfu.h
+++ b/drivers/usb/gadget/f_dfu.h
@@ -51,7 +51,6 @@
 
 #define RET_STALL			-1
 #define RET_ZLP				0
-#define RET_STAT_LEN			6
 
 enum dfu_state {
 	DFU_STATE_appIDLE		= 0,
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index 45a484c..4ba7c1d 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -49,8 +49,7 @@
 void g_dnl_set_serialnumber(char *s)
 {
 	memset(g_dnl_serial, 0, MAX_STRING_SERIAL);
-	if (strlen(s) < MAX_STRING_SERIAL)
-		strncpy(g_dnl_serial, s, strlen(s));
+	strncpy(g_dnl_serial, s, MAX_STRING_SERIAL - 1);
 }
 
 static struct usb_device_descriptor device_desc = {
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 3cc03ca..32ecbe2 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -136,6 +136,9 @@
 	struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
 	int timeout = 1000000;
 
+	if (!panel.frameAdrs)
+		return;
+
 	writel(panel.frameAdrs, &regs->hw_lcdif_cur_buf_reg);
 	writel(panel.frameAdrs, &regs->hw_lcdif_next_buf_reg);
 	writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ, &regs->hw_lcdif_ctrl1_clr);
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index 1a4fa36..7b0c43b 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -110,7 +110,7 @@
 		.mpixelclock = 66000000,
 		.cpce = 0x013e, .gmp = 0x0003, .curr = 0x0038,
 	}, {
-		.mpixelclock = 835000000,
+		.mpixelclock = 83500000,
 		.cpce = 0x0072, .gmp = 0x0001, .curr = 0x0028,
 	}, {
 		.mpixelclock = 146250000,
diff --git a/include/configs/bav335x.h b/include/configs/bav335x.h
index 6dd6f09..fc9dc9c 100644
--- a/include/configs/bav335x.h
+++ b/include/configs/bav335x.h
@@ -23,8 +23,6 @@
 #ifndef CONFIG_SPL_BUILD
 # define CONFIG_TIMESTAMP
 # define CONFIG_LZO
-# ifdef CONFIG_ENABLE_VBOOT
-# endif
 #endif
 
 #define CONFIG_SYS_BOOTM_LEN		(16 << 20)
diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h
index ab35191..2976d63 100644
--- a/include/configs/uniphier.h
+++ b/include/configs/uniphier.h
@@ -142,7 +142,7 @@
 #if defined(CONFIG_ARM64) && !defined(CONFIG_ARMV8_MULTIENTRY)
 /* ARM Trusted Firmware */
 #define BOOT_IMAGES \
-	"second_image=bl1.bin\0" \
+	"second_image=unph_bl.bin\0" \
 	"third_image=fip.bin\0"
 #else
 #define BOOT_IMAGES \
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 826d031..f6c9101 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -951,7 +951,6 @@
 CONFIG_ENABLE_36BIT_PHYS
 CONFIG_ENABLE_MMU
 CONFIG_ENABLE_MUST_CHECK
-CONFIG_ENABLE_VBOOT
 CONFIG_ENABLE_WARN_DEPRECATED
 CONFIG_ENC_SILENTLINK
 CONFIG_ENV_ACCESS_IGNORE_FORCE