[U-Boot] [PATCH v1] mmc: dwmmc: Enable small delay before returning error

Marek Vasut marex at denx.de
Mon Feb 18 20:38:36 UTC 2019


On 2/18/19 3:51 PM, Ang, Chee Hong wrote:
> On Mon, 2019-02-18 at 12:57 +0100, Marek Vasut wrote:
>> On 2/18/19 5:16 AM, chee.hong.ang at intel.com wrote:
>>>
>>> From: "Ang, Chee Hong" <chee.hong.ang at intel.com>
>>>
>>> 'SET_BLOCKLEN' may occasionally fail on first attempt.
>> Why ?
> This is part of the workaround of mmc driver which is enabled with
> 'CONFIG_MMC_QUIRKS' config.
> https://github.com/u-boot/u-boot/blob/dbe70c7d4e3d5c705a98d82952e05a591
> efd0683/drivers/mmc/mmc.c#L272

OK, let's take a step back. What problem do you observe, that you're
trying to fix ?

>>> This patch enable a small delay in dwmci_send_cmd() on
>>> busy, I/O or CRC error to allow the MMC controller recovers
>>> from the failure/error on subsequent retries.
>> Why 100 uS ?
> This is a good question. Perhaps the driver's authors can explain this.
> The driver delay 100us after dwmci_send_cmd() success with the command
> sent. But it never delay 100us whenever mmc controller response to the
> command sent with I/O or CRC errors. MMC drivers expect the first
> 'SET_BLOCKEN' command issued by dwmci_send_cmd() may fail
> intermittently so it will retry up to 4 times before it gave up and
> return error. Without this 100us delay after error response,
> 'SET_BLOCKEN' may sometime fail in 4 attempts in a row. Therefore, we
> encountered intermittent failure in loading u-boot (SSBL) from MMC.

Can you be more specific about the failure you saw ?

>> Can we rather detect whether the controller recovered by polling some
>> bit?
> Hmmm...I can take a look at the databook of this controller and dig
> further. Probably this is the limitation of the controller itself. The
> mmc driver code which introduce 100us delay after every command sent in
> dwmci_send_cmd() looks iffy.

If you have access to it, please do.

btw do you have the same problem if you disable caches ?

>>> Signed-off-by: Ang, Chee Hong <chee.hong.ang at intel.com>
>>> ---
>>>  drivers/mmc/dw_mmc.c | 14 ++++++++++----
>>>  1 file changed, 10 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
>>> index 7544b84..8dcc518 100644
>>> --- a/drivers/mmc/dw_mmc.c
>>> +++ b/drivers/mmc/dw_mmc.c
>>> @@ -266,8 +266,11 @@ static int dwmci_send_cmd(struct mmc *mmc,
>>> struct mmc_cmd *cmd,
>>>  	if (data)
>>>  		flags = dwmci_set_transfer_mode(host, data);
>>>  
>>> -	if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type &
>>> MMC_RSP_BUSY))
>>> -		return -1;
>>> +	if ((cmd->resp_type & MMC_RSP_136) &&
>>> +	    (cmd->resp_type & MMC_RSP_BUSY)) {
>>> +		ret = -1;
>>> +		goto delay_ret;
>>> +	}
>>>  
>>>  	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
>>>  		flags |= DWMCI_CMD_ABORT_STOP;
>>> @@ -316,11 +319,13 @@ static int dwmci_send_cmd(struct mmc *mmc,
>>> struct mmc_cmd *cmd,
>>>  		return -ETIMEDOUT;
>>>  	} else if (mask & DWMCI_INTMSK_RE) {
>>>  		debug("%s: Response Error.\n", __func__);
>>> -		return -EIO;
>>> +		ret = -EIO;
>>> +		goto delay_ret;
>>>  	} else if ((cmd->resp_type & MMC_RSP_CRC) &&
>>>  		   (mask & DWMCI_INTMSK_RCRC)) {
>>>  		debug("%s: Response CRC Error.\n", __func__);
>>> -		return -EIO;
>>> +		ret = -EIO;
>>> +		goto delay_ret;
>>>  	}
>>>  
>>>  
>>> @@ -347,6 +352,7 @@ static int dwmci_send_cmd(struct mmc *mmc,
>>> struct mmc_cmd *cmd,
>>>  		}
>>>  	}
>>>  
>>> +delay_ret:
>>>  	udelay(100);
>>>  
>>>  	return ret;
>>>


-- 
Best regards,
Marek Vasut


More information about the U-Boot mailing list