From 3f2da751beb84861ba0a999aaea09e73f578022a Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:02 -0500 Subject: [PATCH 01/12] mmc: Fix typo in MMC type checking macro The version flag constant name used in IS_MMC macro is incorrect/undefined. Signed-off-by: Andrew Gabbasov --- include/mmc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mmc.h b/include/mmc.h index 2ad0f191c3..a251531aed 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -61,7 +61,7 @@ #define SD_DATA_4BIT 0x00040000 #define IS_SD(x) ((x)->version & SD_VERSION_SD) -#define IS_MMC(x) ((x)->version & SD_VERSION_MMC) +#define IS_MMC(x) ((x)->version & MMC_VERSION_MMC) #define MMC_DATA_READ 1 #define MMC_DATA_WRITE 2 From a626c8d418d5fd1f8429294e7efe3fa2e4ca90fe Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:03 -0500 Subject: [PATCH 02/12] mmc: Avoid extra duplicate entry in mmc device structure The 'op_cond_response' field in mmc structure contains the response from the last SEND_OP_COND MMC command while making iterational polling of the card. Later it is copied to 'ocr' field, designed to contain the OCR register value, which is actually the same response from the same command. So, these fields have actually the same data, just in different time periods. It's easier to use the same 'ocr' field in both cases at once, without temporary using of the 'op_cond_response' field. Signed-off-by: Andrew Gabbasov --- drivers/mmc/mmc.c | 13 +++++++------ include/mmc.h | 1 - 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index a13769ea25..fe00a193a6 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -362,8 +362,8 @@ static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd, if (use_arg && !mmc_host_is_spi(mmc)) { cmd->cmdarg = (mmc->cfg->voltages & - (mmc->op_cond_response & OCR_VOLTAGE_MASK)) | - (mmc->op_cond_response & OCR_ACCESS_MODE); + (mmc->ocr & OCR_VOLTAGE_MASK)) | + (mmc->ocr & OCR_ACCESS_MODE); if (mmc->cfg->host_caps & MMC_MODE_HC) cmd->cmdarg |= OCR_HCS; @@ -371,7 +371,7 @@ static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd, err = mmc_send_cmd(mmc, cmd, NULL); if (err) return err; - mmc->op_cond_response = cmd->response[0]; + mmc->ocr = cmd->response[0]; return 0; } @@ -391,7 +391,7 @@ static int mmc_send_op_cond(struct mmc *mmc) return err; /* exit if not busy (flag seems to be inverted) */ - if (mmc->op_cond_response & OCR_BUSY) + if (mmc->ocr & OCR_BUSY) return 0; } return IN_PROGRESS; @@ -413,7 +413,7 @@ static int mmc_complete_op_cond(struct mmc *mmc) if (get_timer(start) > timeout) return UNUSABLE_ERR; udelay(100); - } while (!(mmc->op_cond_response & OCR_BUSY)); + } while (!(mmc->ocr & OCR_BUSY)); if (mmc_host_is_spi(mmc)) { /* read OCR for spi */ cmd.cmdidx = MMC_CMD_SPI_READ_OCR; @@ -424,10 +424,11 @@ static int mmc_complete_op_cond(struct mmc *mmc) if (err) return err; + + mmc->ocr = cmd.response[0]; } mmc->version = MMC_VERSION_UNKNOWN; - mmc->ocr = cmd.response[0]; mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); mmc->rca = 1; diff --git a/include/mmc.h b/include/mmc.h index a251531aed..644e3fa1e1 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -356,7 +356,6 @@ struct mmc { char op_cond_pending; /* 1 if we are waiting on an op_cond command */ 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; }; From 5289b5350ba5442cfcfbb18488b3a9d9e4f39ede Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:04 -0500 Subject: [PATCH 03/12] mmc: Do not pass external mmc_cmd structure to mmc_send_op_cond_iter() The previous change to use 'ocr' structure field for storing send_op_cond command response also stopped using command response directly outside of mmc_send_op_cond_iter(). Now it becomes possible to use command structure in mmc_send_op_cond_iter() locally, removing a necessity to pass it as an argument from the caller. Signed-off-by: Andrew Gabbasov --- drivers/mmc/mmc.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index fe00a193a6..d073d7900c 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -350,34 +350,32 @@ static int sd_send_op_cond(struct mmc *mmc) return 0; } -/* We pass in the cmd since otherwise the init seems to fail */ -static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd, - int use_arg) +static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg) { + struct mmc_cmd cmd; int err; - cmd->cmdidx = MMC_CMD_SEND_OP_COND; - cmd->resp_type = MMC_RSP_R3; - cmd->cmdarg = 0; + cmd.cmdidx = MMC_CMD_SEND_OP_COND; + cmd.resp_type = MMC_RSP_R3; + cmd.cmdarg = 0; if (use_arg && !mmc_host_is_spi(mmc)) { - cmd->cmdarg = + cmd.cmdarg = (mmc->cfg->voltages & (mmc->ocr & OCR_VOLTAGE_MASK)) | (mmc->ocr & OCR_ACCESS_MODE); if (mmc->cfg->host_caps & MMC_MODE_HC) - cmd->cmdarg |= OCR_HCS; + cmd.cmdarg |= OCR_HCS; } - err = mmc_send_cmd(mmc, cmd, NULL); + err = mmc_send_cmd(mmc, &cmd, NULL); if (err) return err; - mmc->ocr = cmd->response[0]; + mmc->ocr = cmd.response[0]; return 0; } static int mmc_send_op_cond(struct mmc *mmc) { - struct mmc_cmd cmd; int err, i; /* Some cards seem to need this */ @@ -386,7 +384,7 @@ static int mmc_send_op_cond(struct mmc *mmc) /* Asking to the card its capabilities */ mmc->op_cond_pending = 1; for (i = 0; i < 2; i++) { - err = mmc_send_op_cond_iter(mmc, &cmd, i != 0); + err = mmc_send_op_cond_iter(mmc, i != 0); if (err) return err; @@ -407,7 +405,7 @@ static int mmc_complete_op_cond(struct mmc *mmc) mmc->op_cond_pending = 0; start = get_timer(0); do { - err = mmc_send_op_cond_iter(mmc, &cmd, 1); + err = mmc_send_op_cond_iter(mmc, 1); if (err) return err; if (get_timer(start) > timeout) From cc17c01f2d3b691ddadbd46727d5f22db0a90808 Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:05 -0500 Subject: [PATCH 04/12] mmc: Continue polling MMC card for OCR only if it is still not ready Some MMC cards come to ready state quite quickly, so that the respective flag appears to be set in mmc_send_op_cond already. In this case trying to continue polling the card with CMD1 in mmc_complete_op_cond is incorrect and may lead to unpredictable results. So check the flag before polling and skip it appropriately. Signed-off-by: Andrew Gabbasov --- drivers/mmc/mmc.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index d073d7900c..42af47c4c2 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -403,15 +403,17 @@ static int mmc_complete_op_cond(struct mmc *mmc) int err; mmc->op_cond_pending = 0; - start = get_timer(0); - do { - err = mmc_send_op_cond_iter(mmc, 1); - if (err) - return err; - if (get_timer(start) > timeout) - return UNUSABLE_ERR; - udelay(100); - } while (!(mmc->ocr & OCR_BUSY)); + if (!(mmc->ocr & OCR_BUSY)) { + start = get_timer(0); + do { + err = mmc_send_op_cond_iter(mmc, 1); + if (err) + return err; + if (get_timer(start) > timeout) + return UNUSABLE_ERR; + udelay(100); + } while (!(mmc->ocr & OCR_BUSY)); + } if (mmc_host_is_spi(mmc)) { /* read OCR for spi */ cmd.cmdidx = MMC_CMD_SPI_READ_OCR; From 1677eef45976da1cdccc73cd4291877dbb05eea9 Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:06 -0500 Subject: [PATCH 05/12] mmc: Restructure polling loops to avoid extra delays The polling loops in sd_send_op_cond and mmc_complete_op_cond functions check the ready flag state at the end of the loop, that is after executing a delay inside the loop, which, in case of exiting with no error, is not needed. Also, one of these loops, as well as the loop in mmc_send_status, have the delay just before exiting on timeout conditions. Restructure all these loops to check the respective conditions before making a delay for the next loop pass, and to appropriately exit without the delay. Signed-off-by: Andrew Gabbasov --- drivers/mmc/mmc.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 42af47c4c2..b81533c600 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -118,7 +118,7 @@ int mmc_send_status(struct mmc *mmc, int timeout) if (!mmc_host_is_spi(mmc)) cmd.cmdarg = mmc->rca << 16; - do { + while (1) { err = mmc_send_cmd(mmc, &cmd, NULL); if (!err) { if ((cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) && @@ -135,9 +135,11 @@ int mmc_send_status(struct mmc *mmc, int timeout) } else if (--retries < 0) return err; - udelay(1000); + if (timeout-- <= 0) + break; - } while (timeout--); + udelay(1000); + } #ifdef CONFIG_MMC_TRACE status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9; @@ -291,7 +293,7 @@ static int sd_send_op_cond(struct mmc *mmc) int err; struct mmc_cmd cmd; - do { + while (1) { cmd.cmdidx = MMC_CMD_APP_CMD; cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = 0; @@ -322,11 +324,14 @@ static int sd_send_op_cond(struct mmc *mmc) if (err) return err; - udelay(1000); - } while ((!(cmd.response[0] & OCR_BUSY)) && timeout--); + if (cmd.response[0] & OCR_BUSY) + break; - if (timeout <= 0) - return UNUSABLE_ERR; + if (timeout-- <= 0) + return UNUSABLE_ERR; + + udelay(1000); + } if (mmc->version != SD_VERSION_2) mmc->version = SD_VERSION_1_0; @@ -405,14 +410,16 @@ static int mmc_complete_op_cond(struct mmc *mmc) mmc->op_cond_pending = 0; if (!(mmc->ocr & OCR_BUSY)) { start = get_timer(0); - do { + while (1) { err = mmc_send_op_cond_iter(mmc, 1); if (err) return err; + if (mmc->ocr & OCR_BUSY) + break; if (get_timer(start) > timeout) return UNUSABLE_ERR; udelay(100); - } while (!(mmc->ocr & OCR_BUSY)); + } } if (mmc_host_is_spi(mmc)) { /* read OCR for spi */ From bd47c13583f2c4bbd29914063d2bf3a98fcdf5cb Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:07 -0500 Subject: [PATCH 06/12] mmc: Fix splitting device initialization Starting part of device initialization sets the init_in_progress flag only if the MMC card did not yet come to ready state and needs to continue polling. If the card is SD or if the MMC card became ready quickly, the flag is not set and (if using pre-initialization) the starting phase will be re-executed from mmc_init function. Set the init_in_progress flag in all non-error cases. Also, move flags setting statements around so that the flags are not set in error paths. Also, IN_PROGRESS return status becomes unnecessary, so get rid of it. Signed-off-by: Andrew Gabbasov --- drivers/mmc/mmc.c | 16 ++++++++-------- include/mmc.h | 3 +-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index b81533c600..31f8647d86 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -387,7 +387,6 @@ static int mmc_send_op_cond(struct mmc *mmc) mmc_go_idle(mmc); /* Asking to the card its capabilities */ - mmc->op_cond_pending = 1; for (i = 0; i < 2; i++) { err = mmc_send_op_cond_iter(mmc, i != 0); if (err) @@ -395,9 +394,10 @@ static int mmc_send_op_cond(struct mmc *mmc) /* exit if not busy (flag seems to be inverted) */ if (mmc->ocr & OCR_BUSY) - return 0; + break; } - return IN_PROGRESS; + mmc->op_cond_pending = 1; + return 0; } static int mmc_complete_op_cond(struct mmc *mmc) @@ -1627,7 +1627,7 @@ int mmc_start_init(struct mmc *mmc) if (err == TIMEOUT) { err = mmc_send_op_cond(mmc); - if (err && err != IN_PROGRESS) { + if (err) { #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) printf("Card did not respond to voltage select!\n"); #endif @@ -1635,7 +1635,7 @@ int mmc_start_init(struct mmc *mmc) } } - if (err == IN_PROGRESS) + if (!err) mmc->init_in_progress = 1; return err; @@ -1645,6 +1645,7 @@ static int mmc_complete_init(struct mmc *mmc) { int err = 0; + mmc->init_in_progress = 0; if (mmc->op_cond_pending) err = mmc_complete_op_cond(mmc); @@ -1654,13 +1655,12 @@ static int mmc_complete_init(struct mmc *mmc) mmc->has_init = 0; else mmc->has_init = 1; - mmc->init_in_progress = 0; return err; } int mmc_init(struct mmc *mmc) { - int err = IN_PROGRESS; + int err = 0; unsigned start; if (mmc->has_init) @@ -1671,7 +1671,7 @@ int mmc_init(struct mmc *mmc) if (!mmc->init_in_progress) err = mmc_start_init(mmc); - if (!err || err == IN_PROGRESS) + if (!err) err = mmc_complete_init(mmc); debug("%s: %d, time %lu\n", __func__, err, get_timer(start)); return err; diff --git a/include/mmc.h b/include/mmc.h index 644e3fa1e1..fbcbe35a79 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -70,8 +70,7 @@ #define UNUSABLE_ERR -17 /* Unusable Card */ #define COMM_ERR -18 /* Communications Error */ #define TIMEOUT -19 -#define IN_PROGRESS -20 /* operation is in progress */ -#define SWITCH_ERR -21 /* Card reports failure to switch mode */ +#define SWITCH_ERR -20 /* Card reports failure to switch mode */ #define MMC_CMD_GO_IDLE_STATE 0 #define MMC_CMD_SEND_OP_COND 1 From 5a20397b007e9c1482997cf4418639e9ba3df5fe Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 23 Mar 2015 17:56:59 -0500 Subject: [PATCH 07/12] mmc: remove the MMC_MODE_HC flag High capacity support is not a host capability, but a device capability that is queried via the OCR. The flag in the operating conditions request argument can just be set unconditionally. This matches the Linux implementation. [panto] Hand merged and renumbering MMC_MODE_DDR_52MHz. Signed-off-by: Rob Herring Signed-off-by: Pantelis Antoniou Cc: Pantelis Antoniou --- drivers/mmc/dw_mmc.c | 2 +- drivers/mmc/fsl_esdhc.c | 2 +- drivers/mmc/kona_sdhci.c | 1 - drivers/mmc/mmc.c | 7 ++----- drivers/mmc/mvebu_mmc.c | 2 +- drivers/mmc/mxsmmc.c | 3 +-- drivers/mmc/omap_hsmmc.c | 3 +-- drivers/mmc/s3c_sdi.c | 2 +- drivers/mmc/s5p_sdhci.c | 1 - drivers/mmc/sh_mmcif.c | 2 +- drivers/mmc/sunxi_mmc.c | 2 +- drivers/mmc/tegra_mmc.c | 2 +- drivers/mmc/zynq_sdhci.c | 2 -- include/mmc.h | 3 +-- 14 files changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 76fa0b0534..53a8aca84b 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -388,7 +388,7 @@ int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) host->cfg.host_caps |= MMC_MODE_4BIT; host->cfg.host_caps &= ~MMC_MODE_8BIT; } - host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC; + host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz; host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 10ec216d2c..2bbacb36ba 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -652,7 +652,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) return -1; } - cfg->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC; + cfg->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; #ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE cfg->cfg.host_caps |= MMC_MODE_DDR_52MHz; #endif diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c index f804f4c0db..3653d00b1b 100644 --- a/drivers/mmc/kona_sdhci.c +++ b/drivers/mmc/kona_sdhci.c @@ -121,7 +121,6 @@ int kona_sdhci_init(int dev_index, u32 min_clk, u32 quirks) host->name = "kona-sdhci"; host->ioaddr = reg_base; host->quirks = quirks; - host->host_caps = MMC_MODE_HC; if (init_kona_mmc_core(host)) { free(host); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 31f8647d86..3909e14e72 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -363,15 +363,12 @@ static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg) cmd.cmdidx = MMC_CMD_SEND_OP_COND; cmd.resp_type = MMC_RSP_R3; cmd.cmdarg = 0; - if (use_arg && !mmc_host_is_spi(mmc)) { - cmd.cmdarg = + if (use_arg && !mmc_host_is_spi(mmc)) + cmd.cmdarg = OCR_HCS | (mmc->cfg->voltages & (mmc->ocr & OCR_VOLTAGE_MASK)) | (mmc->ocr & OCR_ACCESS_MODE); - if (mmc->cfg->host_caps & MMC_MODE_HC) - cmd.cmdarg |= OCR_HCS; - } err = mmc_send_cmd(mmc, &cmd, NULL); if (err) return err; diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c index 8ca09042d8..056aef5bef 100644 --- a/drivers/mmc/mvebu_mmc.c +++ b/drivers/mmc/mvebu_mmc.c @@ -418,7 +418,7 @@ static struct mmc_config mvebu_mmc_cfg = { .f_min = MVEBU_MMC_BASE_FAST_CLOCK / MVEBU_MMC_BASE_DIV_MAX, .f_max = MVEBU_MMC_CLOCKRATE_MAX, .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, - .host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HC | + .host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz, .part_type = PART_TYPE_DOS, .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 2fa4eeef44..31fb3abc9c 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -405,8 +405,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)) priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | - MMC_MODE_HS_52MHz | MMC_MODE_HS | - MMC_MODE_HC; + MMC_MODE_HS_52MHz | MMC_MODE_HS; /* * SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index dc725cb5b0..8238a7e8e0 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -651,8 +651,7 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, if (priv_data == NULL) return -1; - host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS | - MMC_MODE_HC; + host_caps_val = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS; switch (dev_index) { case 0: diff --git a/drivers/mmc/s3c_sdi.c b/drivers/mmc/s3c_sdi.c index 1b5b70512d..02d1138a5f 100644 --- a/drivers/mmc/s3c_sdi.c +++ b/drivers/mmc/s3c_sdi.c @@ -298,7 +298,7 @@ int s3cmmc_initialize(bd_t *bis, int (*getcd)(struct mmc *), cfg->name = "S3C MMC"; cfg->ops = &s3cmmc_ops; cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_HC | MMC_MODE_HS; + cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_HS; cfg->f_min = 400000; cfg->f_max = get_PCLK() / 2; cfg->b_max = 0x80; diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index 0eec7310e4..8e1968a4ea 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -76,7 +76,6 @@ static int s5p_sdhci_core_init(struct sdhci_host *host) host->set_control_reg = &s5p_sdhci_set_control_reg; host->set_clock = set_mmc_clk; - host->host_caps = MMC_MODE_HC; if (host->bus_width == 8) host->host_caps |= MMC_MODE_8BIT; diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index 76ba93b81d..f92cf00cf4 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -577,7 +577,7 @@ static struct mmc_config sh_mmcif_cfg = { .name = DRIVER_NAME, .ops = &sh_mmcif_ops, .host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT | - MMC_MODE_8BIT | MMC_MODE_HC, + MMC_MODE_8BIT, .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, }; diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 22335452c5..0b7eb1246b 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -449,7 +449,7 @@ struct mmc *sunxi_mmc_init(int sdc_no) cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; cfg->host_caps = MMC_MODE_4BIT; - cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; + cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; cfg->f_min = 400000; diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 2cd8cf10ae..ca41b4de78 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -559,7 +559,7 @@ static int do_mmc_init(int dev_index) host->cfg.host_caps |= MMC_MODE_8BIT; if (host->width >= 4) host->cfg.host_caps |= MMC_MODE_4BIT; - host->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; + host->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; /* * min freq is for card identification, and is the highest diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index d4f3882cbd..971acbb6df 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -29,8 +29,6 @@ int zynq_sdhci_init(phys_addr_t regbase) SDHCI_QUIRK_BROKEN_R1B; host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - host->host_caps = MMC_MODE_HC; - add_sdhci(host, 52000000, 52000000 >> 9); return 0; } diff --git a/include/mmc.h b/include/mmc.h index fbcbe35a79..dd98b3b8ac 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -55,8 +55,7 @@ #define MMC_MODE_4BIT (1 << 2) #define MMC_MODE_8BIT (1 << 3) #define MMC_MODE_SPI (1 << 4) -#define MMC_MODE_HC (1 << 5) -#define MMC_MODE_DDR_52MHz (1 << 6) +#define MMC_MODE_DDR_52MHz (1 << 5) #define SD_DATA_4BIT 0x00040000 From 5e1c23cd392f17be9d135e504d48925a1cd92aa2 Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Mon, 23 Mar 2015 17:57:00 -0500 Subject: [PATCH 08/12] mmc: sdhci: add timeout setting for response busy command Timeout interrupt also work for response busy command(R1b) like cmd38/cmd6. So need to set it accordingly. Current code only set timeout for data command. Signed-off-by: Kevin Liu Signed-off-by: Rob Herring Cc: Pantelis Antoniou --- drivers/mmc/sdhci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 5332e61cae..75556a332d 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -213,6 +213,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, SDHCI_BLOCK_SIZE); sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); + } else if (cmd->resp_type & MMC_RSP_BUSY) { + sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); } sdhci_writel(host, cmd->cmdarg, SDHCI_ARGUMENT); From 253d5bdd64504a1a569b4eb330555e2449fa3d3f Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Wed, 15 Apr 2015 10:13:12 +0800 Subject: [PATCH 09/12] mmc: fsl_esdhc: update eMMC44 adapter card erase timeout Freescale eMMC44 adapter card uses Micron N2M400FDB311A3CF eMMC memory. According to the silicon datasheet, secure erase timeout is 600ms. So increase erase timeout value from 250ms to 600ms. Signed-off-by: Yangbo Lu Cc: York Sun --- drivers/mmc/fsl_esdhc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 2bbacb36ba..b9bc1654d3 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -387,9 +387,9 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Workaround for ESDHC errata ENGcm03648 */ if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { - int timeout = 2500; + int timeout = 6000; - /* Poll on DATA0 line for cmd with busy signal for 250 ms */ + /* Poll on DATA0 line for cmd with busy signal for 600 ms */ while (timeout > 0 && !(esdhc_read32(®s->prsstat) & PRSSTAT_DAT0)) { udelay(100); From ebe78bb993423851b947b1e00f76c835c23e29b5 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Fri, 17 Apr 2015 17:33:17 +0200 Subject: [PATCH 10/12] mmc: bcm2835_sdhci: Use calloc to allocate bcm2835_sdhci_host We need to clear the allocated memory explicitly as the included struct sdhci_host has function pointers. Those are compared to NULL to test if this (optional) feature is supported. Leaving them undefined let u-boot jump to arbitrary memory. Signed-off-by: Alexander Stein --- drivers/mmc/bcm2835_sdhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 4ec2968ece..56775131f0 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -154,9 +154,9 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) struct bcm2835_sdhci_host *bcm_host; struct sdhci_host *host; - bcm_host = malloc(sizeof(*bcm_host)); + bcm_host = calloc(1, sizeof(*bcm_host)); if (!bcm_host) { - printf("sdhci_host malloc fail!\n"); + printf("sdhci_host calloc fail!\n"); return 1; } From 707ac1ad17c09a952b366709d98a5f454cfab909 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 4 May 2015 11:31:16 -0600 Subject: [PATCH 11/12] tegra: mmc: Set the removable flag correctly If the mmc device is non-removable (as indicated by the device tree), set the flag so that users of the device know. Signed-off-by: Simon Glass Reviewed-by: Joe Hershberger --- drivers/mmc/tegra_mmc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index ca41b4de78..d555692f7f 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -528,7 +528,7 @@ static const struct mmc_ops tegra_mmc_ops = { .getcd = tegra_mmc_getcd, }; -static int do_mmc_init(int dev_index) +static int do_mmc_init(int dev_index, bool removable) { struct mmc_host *host; struct mmc *mmc; @@ -573,6 +573,7 @@ static int do_mmc_init(int dev_index) host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; mmc = mmc_create(&host->cfg, host); + mmc->block_dev.removable = removable; if (mmc == NULL) return -1; @@ -586,7 +587,8 @@ static int do_mmc_init(int dev_index) * @param node Device index (0-3) * @param host Structure to fill in (reg, width, mmc_id) */ -static int mmc_get_config(const void *blob, int node, struct mmc_host *host) +static int mmc_get_config(const void *blob, int node, struct mmc_host *host, + bool *removablep) { debug("%s: node = %d\n", __func__, node); @@ -619,6 +621,7 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host) GPIOD_IS_IN); gpio_request_by_name_nodev(blob, node, "power-gpios", 0, &host->pwr_gpio, GPIOD_IS_OUT); + *removablep = !fdtdec_get_bool(blob, node, "non-removable"); debug("%s: found controller at %p, width = %d, periph_id = %d\n", __func__, host->reg, host->width, host->mmc_id); @@ -636,6 +639,7 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host) static int process_nodes(const void *blob, int node_list[], int count) { struct mmc_host *host; + bool removable; int i, node; debug("%s: count = %d\n", __func__, count); @@ -649,11 +653,11 @@ static int process_nodes(const void *blob, int node_list[], int count) host = &mmc_host[i]; host->id = i; - if (mmc_get_config(blob, node, host)) { + if (mmc_get_config(blob, node, host, &removable)) { printf("%s: failed to decode dev %d\n", __func__, i); return -1; } - do_mmc_init(i); + do_mmc_init(i, removable); } return 0; } From 33fe2fb8df01647f97a7bce96a1c7781a7f6d253 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 4 May 2015 22:54:36 +0200 Subject: [PATCH 12/12] ARM: mmc: bcm283x: Remove get_timer_us() from mmc driver The get_timer_us() function is something which is no longer existing in case we use generic timer framework, so replace it with get_timer(). Signed-off-by: Marek Vasut Cc: Stephen Warren Cc: Tyler Baker --- drivers/mmc/bcm2835_sdhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 56775131f0..078ef0523a 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -69,11 +69,11 @@ static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val, * (Which is just as well - otherwise we'd have to nobble the DMA engine * too) */ - while (get_timer_us(bcm_host->last_write) < bcm_host->twoticks_delay) + while (get_timer(bcm_host->last_write) < bcm_host->twoticks_delay) ; writel(val, host->ioaddr + reg); - bcm_host->last_write = get_timer_us(0); + bcm_host->last_write = get_timer(0); } static inline u32 bcm2835_sdhci_raw_readl(struct sdhci_host *host, int reg)