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

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

 



On 11/28/2018 2:48 AM, Loic Poulain wrote:
Hi Jeffrey,

On Tue, 27 Nov 2018 at 16:36, Jeffrey Hugo <jhugo@xxxxxxxxxxxxxx <mailto:jhugo@xxxxxxxxxxxxxx>> wrote:

    On 11/22/2018 3:18 AM, Loic Poulain 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

    Is this "errata" also mentioned in the reference manuals for other
    devices?  It looks like the below patch gets applied to every device
    that the driver is used for.


This is not really an errata but a normal step descibed in the SDCC Write data sequence
(cf chapter 9.4.8 of APQ8016E Technical Reference Manual [1]).

I tested the patch with apq8096 as well (dragonboard-820c), but since I have only access to the apq8016 documentation, I can not confirm it 100% applies to all other platforms.

However, I noted this mechanism is also present in littlekernel(LK) as msm **shared** sdhci code [2].
I concluded it was a common msm sdhci configuration.

Let me know if you have more information but it does not look like a specific apq8016 quirk for me.

The downstream Qualcomm driver appears to do this, and I see similar text in the hardware programming guide, so it appears that this is not a apq8016 specific quirk. Thanks for the clarification.

I'm going to give this change a go on 8998. I do notice a minor issue (see below) which I need to workaround when applying the change.


[1] https://developer.qualcomm.com/download/sd410/snapdragon-410e-technical-reference-manual.pdf [2] https://git.linaro.org/landing-teams/working/qualcomm/lk.git/tree/platform/msm_shared/sdhci.c?h=release/LA.HB.1.3.2-19600-8x96.0#n854



     > 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
    <mailto:leonid.s@xxxxxxxxxxxxx>>
     > Reported-by: Manabu Igusa <migusa@xxxxxxxxxxxxxx
    <mailto:migusa@xxxxxxxxxxxxxx>>
     > Signed-off-by: Loic Poulain <loic.poulain@xxxxxxxxxx
    <mailto:loic.poulain@xxxxxxxxxx>>
     > ---
     >   v2: reword: previous commit message was not the good version
     >
     >   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 a28f5fe..7495854 100644
     > --- a/drivers/mmc/host/sdhci-msm.c
     > +++ b/drivers/mmc/host/sdhci-msm.c
     > @@ -260,6 +260,8 @@ struct sdhci_msm_host {
     >       const struct sdhci_msm_variant_ops *var_ops;
     >       const struct sdhci_msm_offset *offset;
     >       struct icc_path *path;

I don't see "struct icc_path *path;" in mainline or -next. Is there some dependency I'm missing?

     > +     bool use_cdr;
     > +     u32 transfer_mode;
     >   };
     >
     >   static const struct sdhci_msm_offset
    *sdhci_priv_msm_offset(struct sdhci_host *host)
     > @@ -1027,6 +1029,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);
     > @@ -1044,8 +1067,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:
     > @@ -1527,6 +1556,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) {
     >


Regards,
Loic


--
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.



[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