Re: [PATCH v3] mmc: sdhci-msm: Disable CDR function on TX

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

 



On Fri, 30 Nov 2018 at 09:15, Loic Poulain <loic.poulain@xxxxxxxxxx> wrote:
>
> The Clock Data Recovery (CDR) circuit allows to automatically adjust
> the RX sampling-point/phase for high frequency cards (SDR104, HS200...).
> CDR is automatically enabled during DLL configuration.
> However, according to the APQ8016 reference manual, this function
> must be disabled during TX and tuning phase in order to prevent any
> interferences during tuning challenges and unexpected phase alteration
> during TX transfers.
>
> This patch enables/disables CDR according to the current transfer mode.
>
> This fixes sporadic write transfer issues observed with some SDR104 and
> HS200 cards.
>
> Inspired by sdhci-msm downstream patch:
> https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/432516/
>
> Reported-by: Leonid Segal <leonid.s@xxxxxxxxxxxxx>
> Reported-by: Manabu Igusa <migusa@xxxxxxxxxxxxxx>
> Signed-off-by: Loic Poulain <loic.poulain@xxxxxxxxxx>

This patch doesn't apply on my next branch, can you please re-base it.

Kind regards
Uffe
> ---
>  v2: reword: previous commit message was not the good version
>  v3: rebase on upstream
>
>  drivers/mmc/host/sdhci-msm.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 43 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
> index 3cc8bfe..6f230cd 100644
> --- a/drivers/mmc/host/sdhci-msm.c
> +++ b/drivers/mmc/host/sdhci-msm.c
> @@ -258,6 +258,8 @@ struct sdhci_msm_host {
>         bool mci_removed;
>         const struct sdhci_msm_variant_ops *var_ops;
>         const struct sdhci_msm_offset *offset;
> +       bool use_cdr;
> +       u32 transfer_mode;
>  };
>
>  static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
> @@ -1025,6 +1027,27 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
>         return ret;
>  }
>
> +static void sdhci_msm_set_cdr(struct sdhci_host *host, bool enable)
> +{
> +       const struct sdhci_msm_offset *msm_offset = sdhci_priv_msm_offset(host);
> +       u32 config, oldconfig = readl_relaxed(host->ioaddr +
> +                                             msm_offset->core_dll_config);
> +
> +       config = oldconfig;
> +       if (enable) {
> +               config |= CORE_CDR_EN;
> +               config &= ~CORE_CDR_EXT_EN;
> +       } else {
> +               config &= ~CORE_CDR_EN;
> +               config |= CORE_CDR_EXT_EN;
> +       }
> +
> +       if (config != oldconfig) {
> +               writel_relaxed(config, host->ioaddr +
> +                              msm_offset->core_dll_config);
> +       }
> +}
> +
>  static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
>  {
>         struct sdhci_host *host = mmc_priv(mmc);
> @@ -1042,8 +1065,14 @@ static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
>         if (host->clock <= CORE_FREQ_100MHZ ||
>             !(ios.timing == MMC_TIMING_MMC_HS400 ||
>             ios.timing == MMC_TIMING_MMC_HS200 ||
> -           ios.timing == MMC_TIMING_UHS_SDR104))
> +           ios.timing == MMC_TIMING_UHS_SDR104)) {
> +               msm_host->use_cdr = false;
> +               sdhci_msm_set_cdr(host, false);
>                 return 0;
> +       }
> +
> +       /* Clock-Data-Recovery used to dynamically adjust RX sampling point */
> +       msm_host->use_cdr = true;
>
>         /*
>          * For HS400 tuning in HS200 timing requires:
> @@ -1525,6 +1554,19 @@ static int __sdhci_msm_check_write(struct sdhci_host *host, u16 val, int reg)
>         case SDHCI_POWER_CONTROL:
>                 req_type = !val ? REQ_BUS_OFF : REQ_BUS_ON;
>                 break;
> +       case SDHCI_TRANSFER_MODE:
> +               msm_host->transfer_mode = val;
> +               break;
> +       case SDHCI_COMMAND:
> +               if (!msm_host->use_cdr)
> +                       break;
> +               if ((msm_host->transfer_mode & SDHCI_TRNS_READ) &&
> +                   (SDHCI_GET_CMD(val) != MMC_SEND_TUNING_BLOCK_HS200) &&
> +                   (SDHCI_GET_CMD(val) != MMC_SEND_TUNING_BLOCK))
> +                       sdhci_msm_set_cdr(host, true);
> +               else
> +                       sdhci_msm_set_cdr(host, false);
> +               break;
>         }
>
>         if (req_type) {
> --
> 2.7.4
>



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux