From d581076a33e7fd1f2b019a0a53eebe58d76623c1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 20 Jun 2020 14:28:25 +0200 Subject: [PATCH 1/5] cmd: mmc: Cache-align extcsd read target The extcsd read target must be cache aligned in case the controller uses DMA to read the extcsd register, make it so. Signed-off-by: Marek Vasut Reviewed-by: Michael Trimarchi --- cmd/mmc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/mmc.c b/cmd/mmc.c index 1c252e05028..1529a3e05dd 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,8 @@ static void print_mmcinfo(struct mmc *mmc) if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4_41) { bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0; bool usr_enh = has_enh && (mmc->part_attr & EXT_CSD_ENH_USR); - u8 wp, ext_csd[MMC_MAX_BLOCK_LEN]; + ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); + u8 wp; int ret; #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING) From 135c10a7834aa7e0f26f52e5173925e695cba48f Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Mon, 22 Jun 2020 19:38:03 +0800 Subject: [PATCH 2/5] mmc: fsl_esdhc_imx: fix the mask for tuning start point According the RM, the bit[6~0] of register ESDHC_TUNING_CTRL is TUNING_START_TAP, bit[7] of this register is to disable the command CRC check for standard tuning. So fix it here. Fixes: fa33d207494c ("mmc: split fsl_esdhc driver for i.MX") Signed-off-by: Haibo Chen --- include/fsl_esdhc_imx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fsl_esdhc_imx.h b/include/fsl_esdhc_imx.h index 33c6d52bfe9..220a76b9ee5 100644 --- a/include/fsl_esdhc_imx.h +++ b/include/fsl_esdhc_imx.h @@ -203,7 +203,7 @@ #define ESDHC_STD_TUNING_EN BIT(24) /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */ #define ESDHC_TUNING_START_TAP_DEFAULT 0x1 -#define ESDHC_TUNING_START_TAP_MASK 0xff +#define ESDHC_TUNING_START_TAP_MASK 0x7f #define ESDHC_TUNING_STEP_MASK 0x00070000 #define ESDHC_TUNING_STEP_SHIFT 16 From ba61676ff9f8225ebc0ea33ad9f48862e718fd01 Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Mon, 22 Jun 2020 19:38:04 +0800 Subject: [PATCH 3/5] mmc: fsl_esdhc_imx: disable the CMD CRC check for standard tuning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In current code, we add 1ms dealy after each tuning command for standard tuning method. Adding this 1ms dealy is because USDHC default check the CMD CRC and DATA line. If detect the CMD CRC, USDHC standard tuning IC logic do not wait for the tuning data sending out by the card, trigger the buffer read ready interrupt immediately, and step to next cycle. So when next time the new tuning command send out by USDHC, card may still not send out the tuning data of the upper command,then some eMMC cards may stuck, can't response to any command, block the whole tuning procedure. If do not check the CMD CRC for tuning, then do not has this issue. USDHC will wait for the tuning data of each tuning command and check them. If the tuning data pass the check, it also means the CMD line also okay for tuning. So this patch disable the CMD CRC check for tuning, save some time for the whole tuning procedure. Signed-off-by: Haibo Chen --- drivers/mmc/fsl_esdhc_imx.c | 22 ++++++++++++---------- include/fsl_esdhc_imx.h | 1 + 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index f42e0184343..5b61eeb2146 100644 --- a/drivers/mmc/fsl_esdhc_imx.c +++ b/drivers/mmc/fsl_esdhc_imx.c @@ -907,19 +907,9 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) ctrl = readl(®s->autoc12err); if ((!(ctrl & MIX_CTRL_EXE_TUNE)) && (ctrl & MIX_CTRL_SMPCLK_SEL)) { - /* - * need to wait some time, make sure sd/mmc fininsh - * send out tuning data, otherwise, the sd/mmc can't - * response to any command when the card still out - * put the tuning data. - */ - mdelay(1); ret = 0; break; } - - /* Add 1ms delay for SD and eMMC */ - mdelay(1); } writel(irqstaten, ®s->irqstaten); @@ -1267,6 +1257,18 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv, val |= priv->tuning_start_tap; val &= ~ESDHC_TUNING_STEP_MASK; val |= (priv->tuning_step) << ESDHC_TUNING_STEP_SHIFT; + + /* Disable the CMD CRC check for tuning, if not, need to + * add some delay after every tuning command, because + * hardware standard tuning logic will directly go to next + * step once it detect the CMD CRC error, will not wait for + * the card side to finally send out the tuning data, trigger + * the buffer read ready interrupt immediately. If usdhc send + * the next tuning command some eMMC card will stuck, can't + * response, block the tuning procedure or the first command + * after the whole tuning procedure always can't get any response. + */ + val |= ESDHC_TUNING_CMD_CRC_CHECK_DISABLE; writel(val, ®s->tuning_ctrl); } } diff --git a/include/fsl_esdhc_imx.h b/include/fsl_esdhc_imx.h index 220a76b9ee5..279a66d9bff 100644 --- a/include/fsl_esdhc_imx.h +++ b/include/fsl_esdhc_imx.h @@ -204,6 +204,7 @@ /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */ #define ESDHC_TUNING_START_TAP_DEFAULT 0x1 #define ESDHC_TUNING_START_TAP_MASK 0x7f +#define ESDHC_TUNING_CMD_CRC_CHECK_DISABLE BIT(7) #define ESDHC_TUNING_STEP_MASK 0x00070000 #define ESDHC_TUNING_STEP_SHIFT 16 From fe95905ffed57d617cad81a71ac419d53aaa1ebf Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Mon, 15 Jun 2020 17:18:12 +0800 Subject: [PATCH 4/5] mmc: retry CMD1 in mmc_send_op_cond() until the eMMC is ready According to eMMC specification v5.1 section 6.4.3, we should issue CMD1 repeatedly in the idle state until the eMMC is ready even if mmc_send_op_cond() send CMD1 with argument = 0. Otherwise some eMMC devices seems to enter the inactive mode after mmc_complete_op_cond() issued CMD0 when the eMMC device is busy. Signed-off-by: Haibo Chen Reviewed-by: Peng Fan --- drivers/mmc/mmc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 620bb930640..725a36799d3 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -669,12 +669,15 @@ static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg) static int mmc_send_op_cond(struct mmc *mmc) { int err, i; + int timeout = 1000; + uint start; /* Some cards seem to need this */ mmc_go_idle(mmc); + start = get_timer(0); /* Asking to the card its capabilities */ - for (i = 0; i < 2; i++) { + for (i = 0; ; i++) { err = mmc_send_op_cond_iter(mmc, i != 0); if (err) return err; @@ -682,6 +685,10 @@ static int mmc_send_op_cond(struct mmc *mmc) /* exit if not busy (flag seems to be inverted) */ if (mmc->ocr & OCR_BUSY) break; + + if (get_timer(start) > timeout) + return -ETIMEDOUT; + udelay(100); } mmc->op_cond_pending = 1; return 0; From f12341a9529540113f01989149bbbeb68662a829 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Thu, 18 Jun 2020 19:33:12 +0530 Subject: [PATCH 5/5] mmc: sdhci: Fix HISPD bit handling SDHCI HISPD bits need to be configured based on desired mmc timings mode and some HISPD quirks. So, handle the HISPD bit based on the mmc computed selected mode(timing parameter) rather than fixed mmc card clock frequency. Linux handle the HISPD similar like this in below commit but no SDHCI_QUIRK_BROKEN_HISPD_MODE, commit <501639bf2173> ("mmc: sdhci: fix SDHCI_QUIRK_NO_HISPD_BIT handling") This eventually fixed the mmc write issue observed in rk3399 sdhci controller. Bug log for refernece, => gpt write mmc 0 $partitions Writing GPT: mmc write failed ** Can't write to device 0 ** ** Can't write to device 0 ** error! Cc: Kever Yang Cc: Peng Fan Peng Fan: added back "ctrl &= ~SDHCI_CTRL_HISPD;" per Jaehoon's suggestion Tested-by: Suniel Mahesh # roc-rk3399-pc Signed-off-by: Jagan Teki --- drivers/mmc/sdhci.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 92cc8434af2..f4eb655f6ec 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -567,6 +567,7 @@ static int sdhci_set_ios(struct mmc *mmc) #endif u32 ctrl; struct sdhci_host *host = mmc->priv; + bool no_hispd_bit = false; if (host->ops && host->ops->set_control_reg) host->ops->set_control_reg(host); @@ -594,14 +595,26 @@ static int sdhci_set_ios(struct mmc *mmc) ctrl &= ~SDHCI_CTRL_4BITBUS; } - if (mmc->clock > 26000000) - ctrl |= SDHCI_CTRL_HISPD; - else - ctrl &= ~SDHCI_CTRL_HISPD; - if ((host->quirks & SDHCI_QUIRK_NO_HISPD_BIT) || - (host->quirks & SDHCI_QUIRK_BROKEN_HISPD_MODE)) + (host->quirks & SDHCI_QUIRK_BROKEN_HISPD_MODE)) { ctrl &= ~SDHCI_CTRL_HISPD; + no_hispd_bit = true; + } + + if (!no_hispd_bit) { + if (mmc->selected_mode == MMC_HS || + mmc->selected_mode == SD_HS || + mmc->selected_mode == MMC_DDR_52 || + mmc->selected_mode == MMC_HS_200 || + mmc->selected_mode == MMC_HS_400 || + mmc->selected_mode == UHS_SDR25 || + mmc->selected_mode == UHS_SDR50 || + mmc->selected_mode == UHS_SDR104 || + mmc->selected_mode == UHS_DDR50) + ctrl |= SDHCI_CTRL_HISPD; + else + ctrl &= ~SDHCI_CTRL_HISPD; + } sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);