From 3f2da751beb84861ba0a999aaea09e73f578022a Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:02 -0500 Subject: 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 2ad0f19..a251531 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 -- cgit v1.1 From a626c8d418d5fd1f8429294e7efe3fa2e4ca90fe Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:03 -0500 Subject: 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 a13769e..fe00a19 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 a251531..644e3fa 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; }; -- cgit v1.1 From 5289b5350ba5442cfcfbb18488b3a9d9e4f39ede Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:04 -0500 Subject: 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 fe00a19..d073d79 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) -- cgit v1.1 From cc17c01f2d3b691ddadbd46727d5f22db0a90808 Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:05 -0500 Subject: 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 d073d79..42af47c 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; -- cgit v1.1 From 1677eef45976da1cdccc73cd4291877dbb05eea9 Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:06 -0500 Subject: 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 42af47c..b81533c 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 */ -- cgit v1.1 From bd47c13583f2c4bbd29914063d2bf3a98fcdf5cb Mon Sep 17 00:00:00 2001 From: Andrew Gabbasov Date: Thu, 19 Mar 2015 07:44:07 -0500 Subject: 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 b81533c..31f8647 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 644e3fa..fbcbe35 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 -- cgit v1.1 From 5a20397b007e9c1482997cf4418639e9ba3df5fe Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 23 Mar 2015 17:56:59 -0500 Subject: 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 76fa0b0..53a8aca 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 10ec216..2bbacb3 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 f804f4c..3653d00 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 31f8647..3909e14 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 8ca0904..056aef5 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 2fa4eee..31fb3ab 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 dc725cb..8238a7e 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 1b5b705..02d1138 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 0eec731..8e1968a 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 76ba93b..f92cf00 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 2233545..0b7eb12 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 2cd8cf1..ca41b4d 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 d4f3882..971acbb 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 fbcbe35..dd98b3b 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 -- cgit v1.1 From 5e1c23cd392f17be9d135e504d48925a1cd92aa2 Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Mon, 23 Mar 2015 17:57:00 -0500 Subject: 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 5332e61..75556a3 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); -- cgit v1.1 From 253d5bdd64504a1a569b4eb330555e2449fa3d3f Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Wed, 15 Apr 2015 10:13:12 +0800 Subject: 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 2bbacb3..b9bc165 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); -- cgit v1.1 From ebe78bb993423851b947b1e00f76c835c23e29b5 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Fri, 17 Apr 2015 17:33:17 +0200 Subject: 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 4ec2968..5677513 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; } -- cgit v1.1 From 707ac1ad17c09a952b366709d98a5f454cfab909 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 4 May 2015 11:31:16 -0600 Subject: 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 ca41b4d..d555692 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; } -- cgit v1.1 From 33fe2fb8df01647f97a7bce96a1c7781a7f6d253 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 4 May 2015 22:54:36 +0200 Subject: 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 5677513..078ef05 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) -- cgit v1.1