Re: [PATCH v6 2/2] mmc: sdhci-of-esdhc: add erratum A008171 support

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

 



On 23/08/18 11:48, Yinbo Zhu wrote:
> In tuning mode of operation, when TBCTL[TB_EN] is set, eSDHC may report
> one of the following errors :
> 1)Tuning error while running tuning operation where SYSCTL2[SAMPCLKSEL]
> will not get set even when SYSCTL2[EXTN] is reset. OR
> 2)Data transaction error (e.g. IRQSTAT[DCE], IRQSTAT[DEBE]) during data
> transaction errors.
> This issue occurs when the data window sampled within eSDHC is in full
> cycle. So, in that case, eSDHC is not able to find out the start and
> end points of the data window and sets the sampling pointer at default
> location (which is middle of the internal SD clock). If this sampling
> point coincides with the data eye boundary, then it can result in the
> above mentioned errors. Impact: Tuning mode of operation for SDR50,
> SDR104 or HS200 speed modes may not work properly
> Workaround: In case eSDHC reports tuning error or data errors in tuning
> mode of operation, by add the erratum A008171 support to fix the issue.
> 
> Signed-off-by: Yinbo Zhu <yinbo.zhu@xxxxxxx>

Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>

> ---
> Change in v6:
> 		Make the sdhci.[ch] changes a separate patch. 
> 
>  drivers/mmc/host/sdhci-esdhc.h    |    1 +
>  drivers/mmc/host/sdhci-of-esdhc.c |   44 ++++++++++++++++++++++++++++++++++++-
>  2 files changed, 44 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
> index dfa58f8..3f16d9c 100644
> --- a/drivers/mmc/host/sdhci-esdhc.h
> +++ b/drivers/mmc/host/sdhci-esdhc.h
> @@ -60,6 +60,7 @@
>  /* Tuning Block Control Register */
>  #define ESDHC_TBCTL			0x120
>  #define ESDHC_TB_EN			0x00000004
> +#define ESDHC_TBPTR			0x128
>  
>  /* Control Register for DMA transfer */
>  #define ESDHC_DMA_SYSCTL		0x40c
> diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
> index c9685c6..07ba209 100644
> --- a/drivers/mmc/host/sdhci-of-esdhc.c
> +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> @@ -77,8 +77,10 @@ struct sdhci_esdhc {
>  	u8 vendor_ver;
>  	u8 spec_ver;
>  	bool quirk_incorrect_hostver;
> +	bool quirk_fixup_tuning;
>  	unsigned int peripheral_clock;
>  	const struct esdhc_clk_fixup *clk_fixup;
> +	u32 div_ratio;
>  };
>  
>  /**
> @@ -574,6 +576,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
>  	dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
>  		clock, host->max_clk / pre_div / div);
>  	host->mmc->actual_clock = host->max_clk / pre_div / div;
> +	esdhc->div_ratio = pre_div * div;
>  	pre_div >>= 1;
>  	div--;
>  
> @@ -706,9 +709,24 @@ static int esdhc_signal_voltage_switch(struct mmc_host *mmc,
>  	}
>  }
>  
> +static struct soc_device_attribute soc_fixup_tuning[] = {
> +	{ .family = "QorIQ T1040", .revision = "1.0", },
> +	{ .family = "QorIQ T2080", .revision = "1.0", },
> +	{ .family = "QorIQ T1023", .revision = "1.0", },
> +	{ .family = "QorIQ LS1021A", .revision = "1.0", },
> +	{ .family = "QorIQ LS1080A", .revision = "1.0", },
> +	{ .family = "QorIQ LS2080A", .revision = "1.0", },
> +	{ .family = "QorIQ LS1012A", .revision = "1.0", },
> +	{ .family = "QorIQ LS1043A", .revision = "1.*", },
> +	{ .family = "QorIQ LS1046A", .revision = "1.0", },
> +	{ },
> +};
> +
>  static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
>  {
>  	struct sdhci_host *host = mmc_priv(mmc);
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
>  	u32 val;
>  
>  	/* Use tuning block for tuning procedure */
> @@ -722,7 +740,26 @@ static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
>  	sdhci_writel(host, val, ESDHC_TBCTL);
>  	esdhc_clock_enable(host, true);
>  
> -	return sdhci_execute_tuning(mmc, opcode);
> +	sdhci_execute_tuning(mmc, opcode);
> +	if (host->tuning_err == -EAGAIN && esdhc->quirk_fixup_tuning) {
> +
> +		/* program TBPTR[TB_WNDW_END_PTR] = 3*DIV_RATIO and
> +		 * program TBPTR[TB_WNDW_START_PTR] = 5*DIV_RATIO
> +		 */
> +		val = sdhci_readl(host, ESDHC_TBPTR);
> +		val = (val & ~((0x7f << 8) | 0x7f)) |
> +		(3 * esdhc->div_ratio) | ((5 * esdhc->div_ratio) << 8);
> +		sdhci_writel(host, val, ESDHC_TBPTR);
> +
> +		/* program the software tuning mode by setting
> +		 * TBCTL[TB_MODE]=2'h3
> +		 */
> +		val = sdhci_readl(host, ESDHC_TBCTL);
> +		val |= 0x3;
> +		sdhci_writel(host, val, ESDHC_TBCTL);
> +		sdhci_execute_tuning(mmc, opcode);
> +	}
> +	return 0;
>  }
>  
>  #ifdef CONFIG_PM_SLEEP
> @@ -897,6 +934,11 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
>  
>  	pltfm_host = sdhci_priv(host);
>  	esdhc = sdhci_pltfm_priv(pltfm_host);
> +	if (soc_device_match(soc_fixup_tuning))
> +		esdhc->quirk_fixup_tuning = true;
> +	else
> +		esdhc->quirk_fixup_tuning = false;
> +
>  	if (esdhc->vendor_ver == VENDOR_V_22)
>  		host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
>  
> 




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

  Powered by Linux