From patchwork Fri May 15 07:14:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bough Chen X-Patchwork-Id: 245854 List-Id: U-Boot discussion From: haibo.chen at nxp.com (haibo.chen at nxp.com) Date: Fri, 15 May 2020 15:14:05 +0800 Subject: [PATCH] mmc: retry CMD1 in mmc_send_op_cond() until the eMMC is ready Message-ID: <1589526845-14680-1-git-send-email-haibo.chen@nxp.com> From: Haibo Chen 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. This patch also align with Linux 5.7. Signed-off-by: Haibo Chen --- drivers/mmc/mmc.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 523c055967..509549756b 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -664,21 +664,46 @@ static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg) static int mmc_send_op_cond(struct mmc *mmc) { + struct mmc_cmd cmd; int err, i; + int timeout = 1000; + ulong start; /* Some cards seem to need this */ mmc_go_idle(mmc); - /* Asking to the card its capabilities */ - for (i = 0; i < 2; i++) { - err = mmc_send_op_cond_iter(mmc, i != 0); + cmd.cmdidx = MMC_CMD_SEND_OP_COND; + cmd.resp_type = MMC_RSP_R3; + cmd.cmdarg = 0; + + start = get_timer(0); + /* + * According to eMMC specification v5.1 section 6.4.3, we + * should issue CMD1 repeatedly in the idle state until + * the eMMC is ready. Otherwise some eMMC devices seem to enter + * the inactive mode after mmc_complete_op_cond() issued CMD0 when + * the eMMC device is busy. + */ + while (1) { + err = mmc_send_cmd(mmc, &cmd, NULL); if (err) return err; - - /* exit if not busy (flag seems to be inverted) */ - if (mmc->ocr & OCR_BUSY) - break; + if (mmc_host_is_spi(mmc)) { + if (!(cmd.response[0] & (1 << 0))) + break; + } else { + mmc->ocr = cmd.response[0]; + /* exit if not busy (flag seems to be inverted) */ + if (mmc->ocr & OCR_BUSY) + break; + } + if (get_timer(start) > timeout) + return -EOPNOTSUPP; + udelay(100); + if (!mmc_host_is_spi(mmc)) + cmd.cmdarg = cmd.response[0] | (1 << 30); } + mmc->op_cond_pending = 1; return 0; } @@ -691,7 +716,7 @@ static int mmc_complete_op_cond(struct mmc *mmc) int err; mmc->op_cond_pending = 0; - if (!(mmc->ocr & OCR_BUSY)) { + if (mmc->ocr & OCR_BUSY) { /* Some cards seem to need this */ mmc_go_idle(mmc);