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

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

 



On Tue, 4 Dec 2018 at 13:25, 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>
> Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
> Acked-by: Georgi Djakov <georgi.djakov@xxxxxxxxxx>

Applied for next, thanks!

Kind regards
Uffe

> ---
>  v2: reword: previous commit message was not the good version
>  v3: rebase on upstream
>  v4: remove extra parenthis
>      rebase on mmc next branch
>
>  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 4cac593..5497a71 100644
> --- a/drivers/mmc/host/sdhci-msm.c
> +++ b/drivers/mmc/host/sdhci-msm.c
> @@ -260,6 +260,8 @@ struct sdhci_msm_host {
>         bool restore_dll_config;
>         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)
> @@ -1069,6 +1071,27 @@ static int sdhci_msm_restore_sdr_dll_config(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);
> @@ -1079,8 +1102,14 @@ static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
>         struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>         struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
>
> -       if (!sdhci_msm_is_tuning_needed(host))
> +       if (!sdhci_msm_is_tuning_needed(host)) {
> +               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:
> @@ -1562,6 +1591,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 Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux