Re: [PATCH 8/9] mmc: core: Allow CMD13 polling when switch to HS400 mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 16/11/16 12:51, Ulf Hansson wrote:
> In cases when the mmc host doesn't support HW busy detection, polling for
> busy by using CMD13 is beneficial. The reasons have already been explained
> in earlier change logs.
> 
> Moreover, when polling with CMD13 during bus timing changes, we should
> retry instead of fail when we get CRC errors.
> 
> Switching from HS200 to HS400 and reverse includes several steps, where
> each step changes the bus speed timing. Let's improve the behaviour during
> these sequences, by allowing CMD13 polling for each of the step. Let's also
> make sure the CMD13 polling becomes retried, while receiving a CRC error.

I don't know we need to try to get polling for HS400.  The support of HS400
suggests a relatively sophisticated host controller which really should
support busy waiting as well.

> 
> Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx>
> ---
>  drivers/mmc/core/mmc.c | 87 +++++++++++++++-----------------------------------
>  1 file changed, 26 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 0b26383..24b9e72 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1094,8 +1094,7 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
>  static int mmc_select_hs400(struct mmc_card *card)
>  {
>  	struct mmc_host *host = card->host;
> -	unsigned int max_dtr;
> -	int err = 0;
> +	int err;
>  	u8 val;
>  
>  	/*
> @@ -1105,34 +1104,26 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	      host->ios.bus_width == MMC_BUS_WIDTH_8))
>  		return 0;
>  
> -	/* Switch card to HS mode */
> -	val = EXT_CSD_TIMING_HS;
> -	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> -			   EXT_CSD_HS_TIMING, val,
> -			   card->ext_csd.generic_cmd6_time, 0,
> -			   true, false, true);
> +	/*
> +	 * Switch card to HS mode.
> +	 * First reduce to the HS frequency as CMD13 are sent to poll for busy
> +	 * and/or to validate the switch status.
> +	 */
> +	mmc_set_clock(host, card->ext_csd.hs_max_dtr);

That was moved by commit 649c6059d2371fef886a8f967e21416204723d63
("mmc: mmc: Fix HS switch failure in mmc_select_hs400()") i.e. if you put it
back I would expect the gru board problem to reappear.

> +	err = mmc_select_hs(card);
>  	if (err) {
>  		pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
>  			mmc_hostname(host), err);
>  		return err;
>  	}
>  
> -	/* Set host controller to HS timing */
> -	mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
> -
> -	/* Reduce frequency to HS frequency */
> -	max_dtr = card->ext_csd.hs_max_dtr;
> -	mmc_set_clock(host, max_dtr);
> -
> -	err = mmc_switch_status(card);
> -	if (err)
> -		goto out_err;
> -
> -	/* Switch card to DDR */
> -	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> -			 EXT_CSD_BUS_WIDTH,
> -			 EXT_CSD_DDR_BUS_WIDTH_8,
> -			 card->ext_csd.generic_cmd6_time);
> +	/* Switch card to HS DDR */
> +	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> +			   EXT_CSD_BUS_WIDTH,
> +			   EXT_CSD_DDR_BUS_WIDTH_8,
> +			   card->ext_csd.generic_cmd6_time,
> +			   MMC_TIMING_MMC_DDR52,
> +			   true, true, true);
>  	if (err) {
>  		pr_err("%s: switch to bus width for hs400 failed, err:%d\n",
>  			mmc_hostname(host), err);
> @@ -1144,28 +1135,17 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  			   EXT_CSD_HS_TIMING, val,
> -			   card->ext_csd.generic_cmd6_time, 0,
> -			   true, false, true);
> +			   card->ext_csd.generic_cmd6_time,
> +			   MMC_TIMING_MMC_HS400,
> +			   true, true, true);

This is not exactly right.  Tuning has been done at the HS400 operating
frequency.  That is why we set the bus speed before sending any more
commands. i.e. mmc_switch_status(card) is below mmc_set_bus_speed(card)

>  	if (err) {
>  		pr_err("%s: switch to hs400 failed, err:%d\n",
>  			 mmc_hostname(host), err);
>  		return err;
>  	}
>  
> -	/* Set host controller to HS400 timing and frequency */
> -	mmc_set_timing(host, MMC_TIMING_MMC_HS400);
>  	mmc_set_bus_speed(card);
> -
> -	err = mmc_switch_status(card);
> -	if (err)
> -		goto out_err;
> -
>  	return 0;
> -
> -out_err:
> -	pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
> -	       __func__, err);
> -	return err;
>  }
>  
>  int mmc_hs200_to_hs400(struct mmc_card *card)
> @@ -1187,27 +1167,17 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
>  	/* Switch HS400 to HS DDR */
>  	val = EXT_CSD_TIMING_HS;
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
> -			   val, card->ext_csd.generic_cmd6_time, 0,
> -			   true, false, true);
> -	if (err)
> -		goto out_err;
> -
> -	mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
> -
> -	err = mmc_switch_status(card);
> +			   val, card->ext_csd.generic_cmd6_time,
> +			   MMC_TIMING_MMC_DDR52,
> +			   true, true, true);
>  	if (err)
>  		goto out_err;
>  
>  	/* Switch HS DDR to HS */
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
>  			   EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
> -			   0, true, false, true);
> -	if (err)
> -		goto out_err;
> -
> -	mmc_set_timing(host, MMC_TIMING_MMC_HS);
> -
> -	err = mmc_switch_status(card);
> +			   MMC_TIMING_MMC_HS,
> +			   true, true, true);
>  	if (err)
>  		goto out_err;
>  
> @@ -1215,14 +1185,9 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
>  	val = EXT_CSD_TIMING_HS200 |
>  	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
> -			   val, card->ext_csd.generic_cmd6_time, 0,
> -			   true, false, true);
> -	if (err)
> -		goto out_err;
> -
> -	mmc_set_timing(host, MMC_TIMING_MMC_HS200);
> -
> -	err = mmc_switch_status(card);
> +			   val, card->ext_csd.generic_cmd6_time,
> +			   MMC_TIMING_MMC_HS200,
> +			   true, true, true);
>  	if (err)
>  		goto out_err;
>  
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux