diff options
author | Tom Rini <trini@konsulko.com> | 2020-06-24 09:05:35 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-06-24 09:05:35 -0400 |
commit | 922c6d5d0090e51fdd5bb75795c3384a18f5d2b6 (patch) | |
tree | 434b45e0a8a458884dbb0119da404808a2f4f488 | |
parent | 331c7438104149655a5fe96ed4a3d29b00d422de (diff) | |
parent | f12341a9529540113f01989149bbbeb68662a829 (diff) | |
download | u-boot-922c6d5d0090e51fdd5bb75795c3384a18f5d2b6.tar.gz |
Merge tag 'mmc-2020-6-24' of https://gitlab.denx.de/u-boot/custodians/u-boot-mmcWIP/24Jun2020
- Fix fsl_esdhc_imx tunning mask
- Disable CMD CRC for normal tuning for fsl_esdhc_imx
- Retry CM1 until emmc ready
- Fix sdhci HISPD handling
- Cache-aligned extcsd reading
-rw-r--r-- | cmd/mmc.c | 4 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc_imx.c | 22 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 9 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 25 | ||||
-rw-r--r-- | include/fsl_esdhc_imx.h | 3 |
5 files changed, 44 insertions, 19 deletions
@@ -8,6 +8,7 @@ #include <blk.h> #include <command.h> #include <console.h> +#include <memalign.h> #include <mmc.h> #include <part.h> #include <sparse_format.h> @@ -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) diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index f42e018434..5b61eeb214 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/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 620bb93064..725a36799d 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; diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 92cc8434af..f4eb655f6e 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); diff --git a/include/fsl_esdhc_imx.h b/include/fsl_esdhc_imx.h index 33c6d52bfe..279a66d9bf 100644 --- a/include/fsl_esdhc_imx.h +++ b/include/fsl_esdhc_imx.h @@ -203,7 +203,8 @@ #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_CMD_CRC_CHECK_DISABLE BIT(7) #define ESDHC_TUNING_STEP_MASK 0x00070000 #define ESDHC_TUNING_STEP_SHIFT 16 |