Merge branch 'master' of git://git.denx.de/u-boot-mmc
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 4e28c9d..1335e3d 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -85,8 +85,12 @@
 	printf("Tran Speed: %d\n", mmc->tran_speed);
 	printf("Rd Block Len: %d\n", mmc->read_bl_len);
 
-	printf("%s version %d.%d\n", IS_SD(mmc) ? "SD" : "MMC",
-			(mmc->version >> 8) & 0xf, mmc->version & 0xff);
+	printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC",
+			EXTRACT_SDMMC_MAJOR_VERSION(mmc->version),
+			EXTRACT_SDMMC_MINOR_VERSION(mmc->version));
+	if (EXTRACT_SDMMC_CHANGE_VERSION(mmc->version) != 0)
+		printf(".%d", EXTRACT_SDMMC_CHANGE_VERSION(mmc->version));
+	printf("\n");
 
 	printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
 	puts("Capacity: ");
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index b18c75d..76fa0b0 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -321,7 +321,7 @@
 	if (mmc->ddr_mode)
 		regs |= DWMCI_DDR_MODE;
 	else
-		regs &= DWMCI_DDR_MODE;
+		regs &= ~DWMCI_DDR_MODE;
 
 	dwmci_writel(host, DWMCI_UHS_REG, regs);
 
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index dfa209b..e083745 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -13,14 +13,20 @@
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/pinmux.h>
+#include <asm/arch/power.h>
 #include <asm/gpio.h>
 #include <asm-generic/errno.h>
 
 #define	DWMMC_MAX_CH_NUM		4
 #define	DWMMC_MAX_FREQ			52000000
 #define	DWMMC_MIN_FREQ			400000
-#define	DWMMC_MMC0_CLKSEL_VAL		0x03030001
-#define	DWMMC_MMC2_CLKSEL_VAL		0x03020001
+#define	DWMMC_MMC0_SDR_TIMING_VAL	0x03030001
+#define	DWMMC_MMC2_SDR_TIMING_VAL	0x03020001
+
+/* Exynos implmentation specific drver private data */
+struct dwmci_exynos_priv_data {
+	u32 sdr_timing;
+};
 
 /*
  * Function used as callback function to initialise the
@@ -28,7 +34,9 @@
  */
 static void exynos_dwmci_clksel(struct dwmci_host *host)
 {
-	dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val);
+	struct dwmci_exynos_priv_data *priv = host->priv;
+
+	dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing);
 }
 
 unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
@@ -55,6 +63,8 @@
 
 static void exynos_dwmci_board_init(struct dwmci_host *host)
 {
+	struct dwmci_exynos_priv_data *priv = host->priv;
+
 	if (host->quirks & DWMCI_QUIRK_DISABLE_SMU) {
 		dwmci_writel(host, EMMCP_MPSBEGIN0, 0);
 		dwmci_writel(host, EMMCP_SEND0, 0);
@@ -64,12 +74,17 @@
 			     MPSCTRL_NON_SECURE_READ_BIT |
 			     MPSCTRL_NON_SECURE_WRITE_BIT | MPSCTRL_VALID);
 	}
+
+	/* Set to timing value at initial time */
+	if (priv->sdr_timing)
+		exynos_dwmci_clksel(host);
 }
 
 static int exynos_dwmci_core_init(struct dwmci_host *host, int index)
 {
 	unsigned int div;
 	unsigned long freq, sclk;
+	struct dwmci_exynos_priv_data *priv = host->priv;
 
 	if (host->bus_hz)
 		freq = host->bus_hz;
@@ -88,11 +103,11 @@
 #endif
 	host->board_init = exynos_dwmci_board_init;
 
-	if (!host->clksel_val) {
+	if (!priv->sdr_timing) {
 		if (index == 0)
-			host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+			priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL;
 		else if (index == 2)
-			host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+			priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL;
 	}
 
 	host->caps = MMC_MODE_DDR_52MHz;
@@ -118,6 +133,7 @@
 int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
 {
 	struct dwmci_host *host = NULL;
+	struct dwmci_exynos_priv_data *priv;
 
 	host = malloc(sizeof(struct dwmci_host));
 	if (!host) {
@@ -125,11 +141,19 @@
 		return -ENOMEM;
 	}
 
+	priv = malloc(sizeof(struct dwmci_exynos_priv_data));
+	if (!priv) {
+		error("dwmci_exynos_priv_data malloc fail!\n");
+		return -ENOMEM;
+	}
+
 	host->ioaddr = (void *)regbase;
 	host->buswidth = bus_width;
 
 	if (clksel)
-		host->clksel_val = clksel;
+		priv->sdr_timing = clksel;
+
+	host->priv = priv;
 
 	return exynos_dwmci_core_init(host, index);
 }
@@ -157,7 +181,14 @@
 					struct dwmci_host *host)
 {
 	int err = 0;
-	u32 base, clksel_val, timing[3];
+	u32 base, timing[3];
+	struct dwmci_exynos_priv_data *priv;
+
+	priv = malloc(sizeof(struct dwmci_exynos_priv_data));
+	if (!priv) {
+		error("dwmci_exynos_priv_data malloc fail!\n");
+		return -ENOMEM;
+	}
 
 	/* Extract device id for each mmc channel */
 	host->dev_id = pinmux_decode_periph_id(blob, node);
@@ -166,7 +197,6 @@
 	if (host->dev_index == host->dev_id)
 		host->dev_index = host->dev_id - PERIPH_ID_SDMMC0;
 
-
 	/* Get the bus width from the device node */
 	host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
 	if (host->buswidth <= 0) {
@@ -190,16 +220,24 @@
 		return -EINVAL;
 	}
 
-	clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+	priv->sdr_timing = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
 			DWMCI_SET_DRV_CLK(timing[1]) |
 			DWMCI_SET_DIV_RATIO(timing[2]));
-	if (clksel_val)
-		host->clksel_val = clksel_val;
+
+	/* sdr_timing didn't assigned anything, use the default value */
+	if (!priv->sdr_timing) {
+		if (host->dev_index == 0)
+			priv->sdr_timing = DWMMC_MMC0_SDR_TIMING_VAL;
+		else if (host->dev_index == 2)
+			priv->sdr_timing = DWMMC_MMC2_SDR_TIMING_VAL;
+	}
 
 	host->fifoth_val = fdtdec_get_int(blob, node, "fifoth_val", 0);
 	host->bus_hz = fdtdec_get_int(blob, node, "bus_hz", 0);
 	host->div = fdtdec_get_int(blob, node, "div", 0);
 
+	host->priv = priv;
+
 	return 0;
 }
 
@@ -229,12 +267,21 @@
 {
 	int compat_id;
 	int node_list[DWMMC_MAX_CH_NUM];
+	int boot_dev_node;
 	int err = 0, count;
 
 	compat_id = COMPAT_SAMSUNG_EXYNOS_DWMMC;
 
 	count = fdtdec_find_aliases_for_id(blob, "mmc",
 				compat_id, node_list, DWMMC_MAX_CH_NUM);
+
+	/* For DWMMC always set boot device as mmc 0 */
+	if (count >= 3 && get_boot_mode() == BOOT_MODE_SD) {
+		boot_dev_node = node_list[2];
+		node_list[2] = node_list[0];
+		node_list[0] = boot_dev_node;
+	}
+
 	err = exynos_dwmci_process_node(blob, node_list, count);
 
 	return err;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index b8039cd..a13769e 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1693,11 +1693,19 @@
 {
 	struct mmc *m;
 	struct list_head *entry;
+	char *mmc_type;
 
 	list_for_each(entry, &mmc_devices) {
 		m = list_entry(entry, struct mmc, link);
 
+		if (m->has_init)
+			mmc_type = IS_SD(m) ? "SD" : "eMMC";
+		else
+			mmc_type = NULL;
+
 		printf("%s: %d", m->cfg->name, m->block_dev.dev);
+		if (mmc_type)
+			printf(" (%s)", mmc_type);
 
 		if (entry->next != &mmc_devices) {
 			printf("%c", separator);
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index de88e19..82d7984 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -374,7 +374,8 @@
 				(host->quirks & SDHCI_QUIRK_USE_WIDE8))
 			ctrl |= SDHCI_CTRL_8BITBUS;
 	} else {
-		if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
+		if ((SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) ||
+				(host->quirks & SDHCI_QUIRK_USE_WIDE8))
 			ctrl &= ~SDHCI_CTRL_8BITBUS;
 		if (mmc->bus_width == 4)
 			ctrl |= SDHCI_CTRL_4BITBUS;
diff --git a/include/dwmmc.h b/include/dwmmc.h
index 109f7c8..86a5491 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -141,9 +141,9 @@
 	int dev_index;
 	int dev_id;
 	int buswidth;
-	u32 clksel_val;
 	u32 fifoth_val;
 	struct mmc *mmc;
+	void *priv;
 
 	void (*clksel)(struct dwmci_host *host);
 	void (*board_init)(struct dwmci_host *host);
diff --git a/include/mmc.h b/include/mmc.h
index 56d97bb..7d6feca 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -14,24 +14,41 @@
 #include <linux/compiler.h>
 #include <part.h>
 
-#define SD_VERSION_SD	0x20000
-#define SD_VERSION_3	(SD_VERSION_SD | 0x300)
-#define SD_VERSION_2	(SD_VERSION_SD | 0x200)
-#define SD_VERSION_1_0	(SD_VERSION_SD | 0x100)
-#define SD_VERSION_1_10	(SD_VERSION_SD | 0x10a)
-#define MMC_VERSION_MMC		0x10000
-#define MMC_VERSION_UNKNOWN	(MMC_VERSION_MMC)
-#define MMC_VERSION_1_2		(MMC_VERSION_MMC | 0x102)
-#define MMC_VERSION_1_4		(MMC_VERSION_MMC | 0x104)
-#define MMC_VERSION_2_2		(MMC_VERSION_MMC | 0x202)
-#define MMC_VERSION_3		(MMC_VERSION_MMC | 0x300)
-#define MMC_VERSION_4		(MMC_VERSION_MMC | 0x400)
-#define MMC_VERSION_4_1		(MMC_VERSION_MMC | 0x401)
-#define MMC_VERSION_4_2		(MMC_VERSION_MMC | 0x402)
-#define MMC_VERSION_4_3		(MMC_VERSION_MMC | 0x403)
-#define MMC_VERSION_4_41	(MMC_VERSION_MMC | 0x429)
-#define MMC_VERSION_4_5		(MMC_VERSION_MMC | 0x405)
-#define MMC_VERSION_5_0		(MMC_VERSION_MMC | 0x500)
+/* SD/MMC version bits; 8 flags, 8 major, 8 minor, 8 change */
+#define SD_VERSION_SD	(1U << 31)
+#define MMC_VERSION_MMC	(1U << 30)
+
+#define MAKE_SDMMC_VERSION(a, b, c)	\
+	((((u32)(a)) << 16) | ((u32)(b) << 8) | (u32)(c))
+#define MAKE_SD_VERSION(a, b, c)	\
+	(SD_VERSION_SD | MAKE_SDMMC_VERSION(a, b, c))
+#define MAKE_MMC_VERSION(a, b, c)	\
+	(MMC_VERSION_MMC | MAKE_SDMMC_VERSION(a, b, c))
+
+#define EXTRACT_SDMMC_MAJOR_VERSION(x)	\
+	(((u32)(x) >> 16) & 0xff)
+#define EXTRACT_SDMMC_MINOR_VERSION(x)	\
+	(((u32)(x) >> 8) & 0xff)
+#define EXTRACT_SDMMC_CHANGE_VERSION(x)	\
+	((u32)(x) & 0xff)
+
+#define SD_VERSION_3		MAKE_SD_VERSION(3, 0, 0)
+#define SD_VERSION_2		MAKE_SD_VERSION(2, 0, 0)
+#define SD_VERSION_1_0		MAKE_SD_VERSION(1, 0, 0)
+#define SD_VERSION_1_10		MAKE_SD_VERSION(1, 10, 0)
+
+#define MMC_VERSION_UNKNOWN	MAKE_MMC_VERSION(0, 0, 0)
+#define MMC_VERSION_1_2		MAKE_MMC_VERSION(1, 2, 0)
+#define MMC_VERSION_1_4		MAKE_MMC_VERSION(1, 4, 0)
+#define MMC_VERSION_2_2		MAKE_MMC_VERSION(2, 2, 0)
+#define MMC_VERSION_3		MAKE_MMC_VERSION(3, 0, 0)
+#define MMC_VERSION_4		MAKE_MMC_VERSION(4, 0, 0)
+#define MMC_VERSION_4_1		MAKE_MMC_VERSION(4, 1, 0)
+#define MMC_VERSION_4_2		MAKE_MMC_VERSION(4, 2, 0)
+#define MMC_VERSION_4_3		MAKE_MMC_VERSION(4, 3, 0)
+#define MMC_VERSION_4_41	MAKE_MMC_VERSION(4, 4, 1)
+#define MMC_VERSION_4_5		MAKE_MMC_VERSION(4, 5, 0)
+#define MMC_VERSION_5_0		MAKE_MMC_VERSION(5, 0, 0)
 
 #define MMC_MODE_HS		(1 << 0)
 #define MMC_MODE_HS_52MHz	(1 << 1)
@@ -43,7 +60,8 @@
 
 #define SD_DATA_4BIT	0x00040000
 
-#define IS_SD(x) (x->version & SD_VERSION_SD)
+#define IS_SD(x)	((x)->version & SD_VERSION_SD)
+#define IS_MMC(x)	((x)->version & SD_VERSION_MMC)
 
 #define MMC_DATA_READ		1
 #define MMC_DATA_WRITE		2