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.