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 August 2018 at 10:48, Yinbo Zhu <yinbo.zhu@xxxxxxx> 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>

Thanks, applied for next!

Kind regards
Uffe

> ---
> 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;
>
> --
> 1.7.1
>



[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