From f49b39526f797f679d729f8dfdd70474d89a2848 Mon Sep 17 00:00:00 2001 From: "Bao D. Nguyen" Date: Thu, 30 Jan 2020 20:50:28 -0800 Subject: [PATCH] mmc: sdhci-msm: Add SD card DLL setting for SRD104 Mode Port the SDCC's DLL setting logic from Qualcomm's Kona target to Lahaina using the DLL setting recommended by the Hardware Settings Reference guide which is defined in the dt file. This is a snapshot of the sdhci-msm driver changes taken as of msm-4.19 commit <74f401c241ba> ("mmc: sdhci-msm: Port base platform driver from 4.14 to 4.19"). Change-Id: Iaf85a498f9c9d051300ad84654497cf4f0762ba7 Signed-off-by: Veerabhadrarao Badiganti Signed-off-by: Bao D. Nguyen --- drivers/mmc/host/sdhci-msm.c | 122 +++++++++++++++++++++++++++++++---- 1 file changed, 111 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 641a330628d5..510ae3ae4afb 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -100,7 +100,12 @@ #define CORE_PWRSAVE_DLL BIT(3) -#define DDR_CONFIG_POR_VAL 0x80040873 +#define DDR_CONFIG_POR_VAL 0x80040873 +#define DLL_USR_CTL_POR_VAL 0x10800 +#define ENABLE_DLL_LOCK_STATUS BIT(26) +#define FINE_TUNE_MODE_EN BIT(27) +#define BIAS_OK_SIGNAL BIT(29) +#define DLL_CONFIG_3_POR_VAL 0x10 #define INVALID_TUNING_PHASE -1 @@ -152,6 +157,7 @@ struct sdhci_msm_offset { u32 core_dll_config_3; u32 core_ddr_config_old; /* Applicable to sdcc minor ver < 0x49 */ u32 core_ddr_config; + u32 core_dll_usr_ctl; /* Present on SDCC5.1 onwards */ }; static const struct sdhci_msm_offset sdhci_msm_v5_offset = { @@ -181,6 +187,7 @@ static const struct sdhci_msm_offset sdhci_msm_v5_offset = { .core_dll_config_2 = 0x254, .core_dll_config_3 = 0x258, .core_ddr_config = 0x25c, + .core_dll_usr_ctl = 0x388, }; static const struct sdhci_msm_offset sdhci_msm_mci_offset = { @@ -209,6 +216,7 @@ static const struct sdhci_msm_offset sdhci_msm_mci_offset = { .core_ddr_200_cfg = 0x184, .core_vendor_spec3 = 0x1b0, .core_dll_config_2 = 0x1b4, + .core_dll_config_3 = 0x1b8, .core_ddr_config_old = 0x1b8, .core_ddr_config = 0x1bc, }; @@ -254,6 +262,19 @@ struct sdhci_msm_bus_vote_data { u32 curr_vote; }; +/* + * DLL registers which needs be programmed with HSR settings. + * Add any new register only at the end and don't change the + * sequence. + */ +struct sdhci_msm_dll_hsr { + u32 dll_config; + u32 dll_config_2; + u32 dll_config_3; + u32 dll_usr_ctl; + u32 ddr_config; +}; + struct sdhci_msm_host { struct platform_device *pdev; void __iomem *core_mem; /* MSM SDCC mapped address */ @@ -283,10 +304,15 @@ struct sdhci_msm_host { bool skip_bus_bw_voting; struct sdhci_msm_bus_vote_data *bus_vote_data; struct delayed_work bus_vote_work; + bool use_7nm_dll; + struct sdhci_msm_dll_hsr *dll_hsr; }; static void sdhci_msm_bus_voting(struct sdhci_host *host, bool enable); +static int sdhci_msm_dt_get_array(struct device *dev, const char *prop_name, + u32 **bw_vecs, int *len, u32 size); + static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -651,21 +677,31 @@ static int msm_init_cm_dll(struct sdhci_host *host) config |= CORE_DLL_PDN; writel_relaxed(config, host->ioaddr + msm_offset->core_dll_config); - msm_cm_dll_set_freq(host); if (msm_host->use_14lpp_dll_reset && !IS_ERR_OR_NULL(msm_host->xo_clk)) { u32 mclk_freq = 0; + switch (host->clock) { + case 208000000: + case 202000000: + case 201500000: + case 200000000: + mclk_freq = 42; + break; + case 192000000: + mclk_freq = 40; + break; + default: + pr_err("%s: %s: Error. Unsupported clk freq\n", + mmc_hostname(mmc), __func__); + } + config = readl_relaxed(host->ioaddr + msm_offset->core_dll_config_2); config &= CORE_FLL_CYCLE_CNT; if (config) - mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 8), - xo_clk); - else - mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 4), - xo_clk); + mclk_freq *= 2; config = readl_relaxed(host->ioaddr + msm_offset->core_dll_config_2); @@ -691,7 +727,6 @@ static int msm_init_cm_dll(struct sdhci_host *host) msm_offset->core_dll_config); if (msm_host->use_14lpp_dll_reset) { - msm_cm_dll_set_freq(host); config = readl_relaxed(host->ioaddr + msm_offset->core_dll_config_2); config &= ~CORE_DLL_CLOCK_DISABLE; @@ -699,6 +734,37 @@ static int msm_init_cm_dll(struct sdhci_host *host) msm_offset->core_dll_config_2); } + /* Configure Tassadar DLL (Only applicable for 7FF projects) */ + if (msm_host->use_7nm_dll) { + if (msm_host->dll_hsr) { + writel_relaxed(msm_host->dll_hsr->dll_usr_ctl, + host->ioaddr + + msm_offset->core_dll_usr_ctl); + writel_relaxed(msm_host->dll_hsr->dll_config_3, + host->ioaddr + + msm_offset->core_dll_config_3); + } else { + writel_relaxed(DLL_USR_CTL_POR_VAL | FINE_TUNE_MODE_EN | + ENABLE_DLL_LOCK_STATUS | BIAS_OK_SIGNAL, + host->ioaddr + + msm_offset->core_dll_usr_ctl); + + writel_relaxed(DLL_CONFIG_3_POR_VAL, host->ioaddr + + msm_offset->core_dll_config_3); + } + } + + /* + * Update the lower two bytes of DLL_CONFIG only with HSR values. + * Since these are the static settings. + */ + if (msm_host->dll_hsr) { + writel_relaxed((readl_relaxed(host->ioaddr + + msm_offset->core_dll_config) | + (msm_host->dll_hsr->dll_config & 0xffff)), + host->ioaddr + msm_offset->core_dll_config); + } + config = readl_relaxed(host->ioaddr + msm_offset->core_dll_config); config |= CORE_DLL_EN; @@ -1021,8 +1087,8 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); - struct mmc_host *mmc = host->mmc; int ret; + struct mmc_host *mmc = host->mmc; u32 config; const struct sdhci_msm_offset *msm_offset = msm_host->offset; @@ -1038,9 +1104,9 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host) goto out; if (!mmc->ios.enhanced_strobe) { - /* Set the selected phase in delay line hw block */ + /* set the selected phase in delay line hw block */ ret = msm_config_cm_dll_phase(host, - msm_host->saved_tuning_phase); + msm_host->saved_tuning_phase); if (ret) goto out; config = readl_relaxed(host->ioaddr + @@ -1308,6 +1374,32 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host, sdhci_msm_hs400(host, &mmc->ios); } +static int sdhci_msm_dt_parse_hsr_info(struct device *dev, + struct sdhci_msm_host *msm_host) + +{ + u32 *dll_hsr_table = NULL; + int dll_hsr_table_len, dll_hsr_reg_count; + int ret = 0; + + if (sdhci_msm_dt_get_array(dev, "qcom,dll-hsr-list", + &dll_hsr_table, &dll_hsr_table_len, 0)) + goto skip_hsr; + + dll_hsr_reg_count = sizeof(struct sdhci_msm_dll_hsr) / sizeof(u32); + if (dll_hsr_table_len != dll_hsr_reg_count) { + dev_err(dev, "Number of HSR entries are not matching\n"); + ret = -EINVAL; + } else { + msm_host->dll_hsr = (struct sdhci_msm_dll_hsr *)dll_hsr_table; + } + +skip_hsr: + if (!msm_host->dll_hsr) + dev_info(dev, "Failed to get dll hsr settings from dt\n"); + return ret; +} + static inline void sdhci_msm_init_pwr_irq_wait(struct sdhci_msm_host *msm_host) { init_waitqueue_head(&msm_host->pwr_irq_wait); @@ -2127,6 +2219,8 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host->saved_tuning_phase = INVALID_TUNING_PHASE; + sdhci_msm_dt_parse_hsr_info(&pdev->dev, msm_host); + /* Setup SDCC bus voter clock. */ msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus"); if (!IS_ERR(msm_host->bus_clk)) { @@ -2259,6 +2353,12 @@ static int sdhci_msm_probe(struct platform_device *pdev) if (core_major == 1 && core_minor >= 0x49) msm_host->updated_ddr_cfg = true; + /* 7FF projects with 7nm DLL */ + if ((core_major == 1) && ((core_minor == 0x6e) || + (core_minor == 0x71) || + (core_minor == 0x72))) + msm_host->use_7nm_dll = true; + /* * Power on reset state may trigger power irq if previous status of * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq