diff options
-rw-r--r-- | common/cmd_mmc.c | 3 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/exynos_dw_mmc.c | 22 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 85 | ||||
-rw-r--r-- | include/mmc.h | 5 |
5 files changed, 81 insertions, 36 deletions
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index 4286e26..96478e4 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -90,7 +90,8 @@ static void print_mmcinfo(struct mmc *mmc) puts("Capacity: "); print_size(mmc->capacity, "\n"); - printf("Bus Width: %d-bit\n", mmc->bus_width); + printf("Bus Width: %d-bit%s\n", mmc->bus_width, + mmc->ddr_mode ? " DDR" : ""); } static struct mmc *init_mmc_device(int dev, bool force_init) { diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 785eed5..b18c75d 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -318,7 +318,7 @@ static void dwmci_set_ios(struct mmc *mmc) dwmci_writel(host, DWMCI_CTYPE, ctype); regs = dwmci_readl(host, DWMCI_UHS_REG); - if (mmc->card_caps & MMC_MODE_DDR_52MHz) + if (mmc->ddr_mode) regs |= DWMCI_DDR_MODE; else regs &= DWMCI_DDR_MODE; diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index d96dfe1..dfa209b 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -101,7 +101,7 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index) host->get_mmc_clk = exynos_dwmci_get_clk; /* Add the mmc channel to be registered with mmc core */ if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) { - debug("dwmmc%d registration failed\n", index); + printf("DWMMC%d registration failed\n", index); return -1; } return 0; @@ -146,7 +146,7 @@ static int do_dwmci_init(struct dwmci_host *host) flag = host->buswidth == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE; err = exynos_pinmux_config(host->dev_id, flag); if (err) { - debug("DWMMC not configure\n"); + printf("DWMMC%d not configure\n", index); return err; } @@ -162,21 +162,22 @@ static int exynos_dwmci_get_config(const void *blob, int node, /* Extract device id for each mmc channel */ host->dev_id = pinmux_decode_periph_id(blob, node); + host->dev_index = fdtdec_get_int(blob, node, "index", host->dev_id); + 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) { - debug("DWMMC: Can't get bus-width\n"); + printf("DWMMC%d: Can't get bus-width\n", host->dev_index); return -EINVAL; } - host->dev_index = fdtdec_get_int(blob, node, "index", host->dev_id); - if (host->dev_index == host->dev_id) - host->dev_index = host->dev_id - PERIPH_ID_SDMMC0; - /* Set the base address from the device node */ base = fdtdec_get_addr(blob, node, "reg"); if (!base) { - debug("DWMMC: Can't get base address\n"); + printf("DWMMC%d: Can't get base address\n", host->dev_index); return -EINVAL; } host->ioaddr = (void *)base; @@ -184,7 +185,8 @@ static int exynos_dwmci_get_config(const void *blob, int node, /* Extract the timing info from the node */ err = fdtdec_get_int_array(blob, node, "samsung,timing", timing, 3); if (err) { - debug("Can't get sdr-timings for devider\n"); + printf("DWMMC%d: Can't get sdr-timings for devider\n", + host->dev_index); return -EINVAL; } @@ -214,7 +216,7 @@ static int exynos_dwmci_process_node(const void *blob, host = &dwmci_host[i]; err = exynos_dwmci_get_config(blob, node, host); if (err) { - debug("%s: failed to decode dev %d\n", __func__, i); + printf("%s: failed to decode dev %d\n", __func__, i); return err; } diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 8436bc7..1eb9c27 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -159,7 +159,7 @@ int mmc_set_blocklen(struct mmc *mmc, int len) { struct mmc_cmd cmd; - if (mmc->card_caps & MMC_MODE_DDR_52MHz) + if (mmc->ddr_mode) return 0; cmd.cmdidx = MMC_CMD_SET_BLOCKLEN; @@ -486,7 +486,7 @@ static int mmc_change_freq(struct mmc *mmc) char cardtype; int err; - mmc->card_caps = 0; + mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; if (mmc_host_is_spi(mmc)) return 0; @@ -519,7 +519,7 @@ static int mmc_change_freq(struct mmc *mmc) /* High Speed is set, there are two types: 52MHz and 26MHz */ if (cardtype & EXT_CSD_CARD_TYPE_52) { - if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) + if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V) mmc->card_caps |= MMC_MODE_DDR_52MHz; mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; } else { @@ -1001,6 +1001,9 @@ static int mmc_startup(struct mmc *mmc) case 6: mmc->version = MMC_VERSION_4_5; break; + case 7: + mmc->version = MMC_VERSION_5_0; + break; } /* @@ -1022,6 +1025,21 @@ static int mmc_startup(struct mmc *mmc) mmc->erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * MMC_MAX_BLOCK_LEN * 1024; + /* + * if high capacity and partition setting completed + * SEC_COUNT is valid even if it is smaller than 2 GiB + * JEDEC Standard JESD84-B45, 6.2.4 + */ + if (mmc->high_capacity && + (ext_csd[EXT_CSD_PARTITION_SETTING] & + EXT_CSD_PARTITION_SETTING_COMPLETED)) { + capacity = (ext_csd[EXT_CSD_SEC_CNT]) | + (ext_csd[EXT_CSD_SEC_CNT + 1] << 8) | + (ext_csd[EXT_CSD_SEC_CNT + 2] << 16) | + (ext_csd[EXT_CSD_SEC_CNT + 3] << 24); + capacity *= MMC_MAX_BLOCK_LEN; + mmc->capacity_user = capacity; + } } else { /* Calculate the group size from the csd value. */ int erase_gsz, erase_gmul; @@ -1103,8 +1121,10 @@ static int mmc_startup(struct mmc *mmc) /* An array to map CSD bus widths to host cap bits */ static unsigned ext_to_hostcaps[] = { - [EXT_CSD_DDR_BUS_WIDTH_4] = MMC_MODE_DDR_52MHz, - [EXT_CSD_DDR_BUS_WIDTH_8] = MMC_MODE_DDR_52MHz, + [EXT_CSD_DDR_BUS_WIDTH_4] = + MMC_MODE_DDR_52MHz | MMC_MODE_4BIT, + [EXT_CSD_DDR_BUS_WIDTH_8] = + MMC_MODE_DDR_52MHz | MMC_MODE_8BIT, [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT, [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT, }; @@ -1116,13 +1136,13 @@ static int mmc_startup(struct mmc *mmc) for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) { unsigned int extw = ext_csd_bits[idx]; + unsigned int caps = ext_to_hostcaps[extw]; /* - * Check to make sure the controller supports - * this bus width, if it's more than 1 + * Check to make sure the card and controller support + * these capabilities */ - if (extw != EXT_CSD_BUS_WIDTH_1 && - !(mmc->cfg->host_caps & ext_to_hostcaps[extw])) + if ((mmc->card_caps & caps) != caps) continue; err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, @@ -1131,26 +1151,33 @@ static int mmc_startup(struct mmc *mmc) if (err) continue; + mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0; mmc_set_bus_width(mmc, widths[idx]); err = mmc_send_ext_csd(mmc, test_csd); + + if (err) + continue; + /* Only compare read only fields */ - if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \ - == test_csd[EXT_CSD_PARTITIONING_SUPPORT] - && ext_csd[EXT_CSD_HC_WP_GRP_SIZE] \ - == test_csd[EXT_CSD_HC_WP_GRP_SIZE] \ - && ext_csd[EXT_CSD_REV] \ - == test_csd[EXT_CSD_REV] - && ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \ - == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] - && memcmp(&ext_csd[EXT_CSD_SEC_CNT], \ - &test_csd[EXT_CSD_SEC_CNT], 4) == 0) { - - mmc->card_caps |= ext_to_hostcaps[extw]; + if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] + == test_csd[EXT_CSD_PARTITIONING_SUPPORT] && + ext_csd[EXT_CSD_HC_WP_GRP_SIZE] + == test_csd[EXT_CSD_HC_WP_GRP_SIZE] && + ext_csd[EXT_CSD_REV] + == test_csd[EXT_CSD_REV] && + ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] + == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] && + memcmp(&ext_csd[EXT_CSD_SEC_CNT], + &test_csd[EXT_CSD_SEC_CNT], 4) == 0) break; - } + else + err = SWITCH_ERR; } + if (err) + return err; + if (mmc->card_caps & MMC_MODE_HS) { if (mmc->card_caps & MMC_MODE_HS_52MHz) mmc->tran_speed = 52000000; @@ -1161,6 +1188,12 @@ static int mmc_startup(struct mmc *mmc) mmc_set_clock(mmc, mmc->tran_speed); + /* Fix the block length for DDR mode */ + if (mmc->ddr_mode) { + mmc->read_bl_len = MMC_MAX_BLOCK_LEN; + mmc->write_bl_len = MMC_MAX_BLOCK_LEN; + } + /* fill in device description */ mmc->block_dev.lun = 0; mmc->block_dev.type = 0; @@ -1306,6 +1339,7 @@ int mmc_start_init(struct mmc *mmc) if (err) return err; + mmc->ddr_mode = 0; mmc_set_bus_width(mmc, 1); mmc_set_clock(mmc, 1); @@ -1408,8 +1442,11 @@ void print_mmc_devices(char separator) printf("%s: %d", m->cfg->name, m->block_dev.dev); - if (entry->next != &mmc_devices) - printf("%c ", separator); + if (entry->next != &mmc_devices) { + printf("%c", separator); + if (separator != '\n') + puts (" "); + } } printf("\n"); diff --git a/include/mmc.h b/include/mmc.h index adffc35..7ec255d 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -31,6 +31,7 @@ #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) #define MMC_MODE_HS (1 << 0) #define MMC_MODE_HS_52MHz (1 << 1) @@ -147,6 +148,7 @@ * EXT_CSD fields */ #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ +#define EXT_CSD_PARTITION_SETTING 155 /* R/W */ #define EXT_CSD_PARTITIONS_ATTRIBUTE 156 /* R/W */ #define EXT_CSD_PARTITIONING_SUPPORT 160 /* RO */ #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ @@ -197,6 +199,8 @@ #define EXT_CSD_BOOT_BUS_WIDTH_RESET(x) (x << 2) #define EXT_CSD_BOOT_BUS_WIDTH_WIDTH(x) (x) +#define EXT_CSD_PARTITION_SETTING_COMPLETED (1 << 0) + #define R1_ILLEGAL_COMMAND (1 << 22) #define R1_APP_CMD (1 << 5) @@ -314,6 +318,7 @@ struct mmc { char init_in_progress; /* 1 if we have done mmc_start_init() */ char preinit; /* start init as early as possible */ uint op_cond_response; /* the response byte from the last op_cond */ + int ddr_mode; }; int mmc_register(struct mmc *mmc); |