diff options
-rw-r--r-- | common/cmd_mmc.c | 8 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/exynos_dw_mmc.c | 71 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 8 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 3 | ||||
-rw-r--r-- | include/dwmmc.h | 2 | ||||
-rw-r--r-- | include/mmc.h | 56 |
7 files changed, 114 insertions, 36 deletions
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 @@ static void print_mmcinfo(struct mmc *mmc) 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 @@ static void dwmci_set_ios(struct mmc *mmc) 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 @@ unsigned int exynos_dwmci_get_clk(struct dwmci_host *host) 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 @@ static void exynos_dwmci_board_init(struct dwmci_host *host) 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 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index) #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 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index) 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 @@ int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) 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 @@ static int exynos_dwmci_get_config(const void *blob, int node, 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 @@ static int exynos_dwmci_get_config(const void *blob, int node, 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 @@ static int exynos_dwmci_get_config(const void *blob, int node, 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 exynos_dwmmc_init(const void *blob) { 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 @@ void print_mmc_devices(char separator) { 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 @@ static void sdhci_set_ios(struct mmc *mmc) (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 @@ struct dwmci_host { 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 |