[PATCH] mmc: retry CMD1 in mmc_send_op_cond() until the eMMC is ready
Jaehoon Chung
jh80.chung at samsung.com
Tue May 19 09:37:15 CEST 2020
On 5/19/20 12:37 PM, Peng Fan wrote:
>> Subject: [PATCH] mmc: retry CMD1 in mmc_send_op_cond() until the eMMC
>> is ready
>>
>> From: Haibo Chen <haibo.chen at nxp.com>
>>
>> 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.
Well, i think that it can't compare to linux driver.
is your issue fixed with this patch?
As i know, this sequence is not follow correct spec.
To enhance boot, it was skipping the polling time.
If there is a problem, could you explain in more detail?
Then I will also check on my targets.
>>
>> Signed-off-by: Haibo Chen <haibo.chen at nxp.com>
>> ---
>> 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.
>> + */
>
> Could we just extend the previous for loop to fix the issue?
> Your piece code duplicate much of the code and changed
> the original behavior.
>
>> + 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;
>
> TIMEOUT, please.
>
>> + udelay(100);
>
> This will change the original behavior by adding a delay.
>
>> + if (!mmc_host_is_spi(mmc))
>> + cmd.cmdarg = cmd.response[0] | (1 << 30);
>
> Do we need "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) {
>
> When card not go out busy, it means card not
> finish power up seq. Why drop !?
Right. It doesn't finish power-ups seq.
If it's working with this patch, it seems something wrong.
>
>> /* Some cards seem to need this */
>> mmc_go_idle(mmc);
>>
>> --
>
> Would the following patch help?
yes. it's more better.
If need to increase polling time, i think it's correct place in mmc_complete_op_cond().
Best Regards,
Jaehoon Chung
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 523c055967..d3a0538cdb 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -665,12 +665,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;
> + ulong 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;
> @@ -678,6 +681,9 @@ 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;
> }
> mmc->op_cond_pending = 1;
> return 0;
>
> Thanks,
> Peng.
>> 2.17.1
>
>
More information about the U-Boot
mailing list