From 977a7a15231f6c510229f616dd0c24632fcbee4d Mon Sep 17 00:00:00 2001 From: Sahitya Tummala <stummala@codeaurora.org> Date: Wed, 12 Mar 2014 16:27:32 +0530 Subject: [PATCH] mmc: sdhci-msm: fix issue with tuning command As of now we ignore CRC/INDEX command failures to tuning command and still wait for data from card but in case the card did not receive the command, it won't send the data. This is causing software request timeout for tuning commands. Hence, software must not ignore such cmd errors for tuning commands but end the request immediately after resetting the controller for both CMD and DATA. Also, wait for 146 MCLK cycles for card to send out the data and thus to move to transfer state. Its corresponding phase must also be considered as bad phase. Bug: 13936571 CRs-fixed: 625855 Change-Id: Ic8462dd9c67e4f18a3ce73d972591772be8c6d10 Signed-off-by: Sahitya Tummala <stummala@codeaurora.org> --- drivers/mmc/host/sdhci-msm.c | 9 ++++++++- drivers/mmc/host/sdhci.c | 25 +------------------------ include/linux/mmc/sdhci.h | 14 ++++++-------- 3 files changed, 15 insertions(+), 33 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 1e54cead1134..f360554e2d56 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1002,6 +1002,14 @@ retry: memset(data_buf, 0, size); mmc_wait_for_req(mmc, &mrq); + /* + * wait for 146 MCLK cycles for the card to send out the data + * and thus move to TRANS state. As the MCLK would be minimum + * 200MHz when tuning is performed, we need maximum 0.73us + * delay. To be on safer side 1ms delay is given. + */ + if (cmd.error) + usleep_range(1000, 1200); if (!cmd.error && !data.error && !memcmp(data_buf, tuning_block_pattern, size)) { /* tuning is successful at this tuning point */ @@ -3037,7 +3045,6 @@ static int sdhci_msm_probe(struct platform_device *pdev) host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE; host->quirks |= SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN; host->quirks2 |= SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK; - host->quirks2 |= SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING; host->quirks2 |= SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE; host->quirks2 |= SDHCI_QUIRK2_IGNORE_DATATOUT_FOR_R1BCMD; host->quirks2 |= SDHCI_QUIRK2_BROKEN_PRESET_VALUE; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index a373491600fd..956833f1fb4d 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2801,17 +2801,6 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) host->cmd->error = -EILSEQ; } - if (host->quirks2 & SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING) { - if ((host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS400) || - (host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) || - (host->cmd->opcode == MMC_SEND_TUNING_BLOCK)) { - if (intmask & SDHCI_INT_CRC) { - sdhci_reset(host, SDHCI_RESET_CMD); - host->cmd->error = 0; - } - } - } - if (host->cmd->error) { if (host->cmd->error == -EILSEQ) host->flags |= SDHCI_NEEDS_RETUNING; @@ -2841,17 +2830,6 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) * fall through and take the SDHCI_INT_RESPONSE */ } - if (host->quirks2 & SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING) { - if ((host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS400) || - (host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) || - (host->cmd->opcode == MMC_SEND_TUNING_BLOCK)) { - if (intmask & SDHCI_INT_CRC) { - sdhci_finish_command(host); - return; - } - } - } - if (intmask & SDHCI_INT_RESPONSE) sdhci_finish_command(host); } @@ -2946,8 +2924,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) host->ops->adma_workaround(host, intmask); } if (host->data->error) { - if ((intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT)) && - (host->quirks2 & SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING)) { + if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT)) { command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)); if ((command != MMC_SEND_TUNING_BLOCK_HS400) && diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 7eba5729b559..e3a90e0c8e6e 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -117,39 +117,37 @@ struct sdhci_host { * be called twice. */ #define SDHCI_QUIRK2_SLOW_INT_CLR (1<<5) -/* Ignore CMD CRC errors for tuning commands */ -#define SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING (1<<6) /* * If the base clock can be scalable, then there should be no further * clock dividing as the input clock itself will be scaled down to * required frequency. */ -#define SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK (1<<7) +#define SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK (1<<6) /* * Dont use the max_discard_to in sdhci driver so that the maximum discard * unit gets picked by the mmc queue. Otherwise, it takes a long time for * secure discard kind of operations to complete. */ -#define SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE (1<<8) +#define SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE (1<<7) /* * Ignore data timeout error for R1B commands as there will be no * data associated and the busy timeout value for these commands * could be lager than the maximum timeout value that controller * can handle. */ -#define SDHCI_QUIRK2_IGNORE_DATATOUT_FOR_R1BCMD (1<<9) +#define SDHCI_QUIRK2_IGNORE_DATATOUT_FOR_R1BCMD (1<<8) /* * The preset value registers are not properly initialized by * some hardware and hence preset value must not be enabled for * such controllers. */ -#define SDHCI_QUIRK2_BROKEN_PRESET_VALUE (1<<10) +#define SDHCI_QUIRK2_BROKEN_PRESET_VALUE (1<<9) /* * Some controllers define the usage of 0xF in data timeout counter * register (0x2E) which is actually a reserved bit as per * specification. */ -#define SDHCI_QUIRK2_USE_RESERVED_MAX_TIMEOUT (1<<11) +#define SDHCI_QUIRK2_USE_RESERVED_MAX_TIMEOUT (1<<10) /* * This is applicable for controllers that advertize timeout clock * value in capabilities register (bit 5-0) as just 50MHz whereas the @@ -162,7 +160,7 @@ struct sdhci_host { * will be used in such cases to avoid controller mulplication when timeout is * calculated based on the base clock. */ -#define SDHCI_QUIRK2_DIVIDE_TOUT_BY_4 (1 << 12) +#define SDHCI_QUIRK2_DIVIDE_TOUT_BY_4 (1 << 11) /* * Some SDHC controllers are unable to handle data-end bit error in -- GitLab