Commit 83736352 authored by Venkat Gopalakrishnan's avatar Venkat Gopalakrishnan Committed by Ulf Hansson

mmc: sdhci-msm: Update DLL reset sequence

SDCC core with minor version >= 0x42 introduced new 14lpp
DLL. This has additional requirements in the reset sequence
for DLL tuning. Make necessary changes as needed.

Without this patch we see below errors on such SDHC controllers
	sdhci_msm 7464900.sdhci: mmc0: DLL failed to LOCK
	mmc0: tuning execution failed: -110
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
Signed-off-by: default avatarRitesh Harjani <riteshh@codeaurora.org>
Acked-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent f927ea41
...@@ -59,6 +59,10 @@ ...@@ -59,6 +59,10 @@
#define CORE_DLL_CONFIG 0x100 #define CORE_DLL_CONFIG 0x100
#define CORE_DLL_STATUS 0x108 #define CORE_DLL_STATUS 0x108
#define CORE_DLL_CONFIG_2 0x1b4
#define CORE_FLL_CYCLE_CNT BIT(18)
#define CORE_DLL_CLOCK_DISABLE BIT(21)
#define CORE_VENDOR_SPEC 0x10c #define CORE_VENDOR_SPEC 0x10c
#define CORE_CLK_PWRSAVE BIT(1) #define CORE_CLK_PWRSAVE BIT(1)
...@@ -77,7 +81,9 @@ struct sdhci_msm_host { ...@@ -77,7 +81,9 @@ struct sdhci_msm_host {
struct clk *clk; /* main SD/MMC bus clock */ struct clk *clk; /* main SD/MMC bus clock */
struct clk *pclk; /* SDHC peripheral bus clock */ struct clk *pclk; /* SDHC peripheral bus clock */
struct clk *bus_clk; /* SDHC bus voter clock */ struct clk *bus_clk; /* SDHC bus voter clock */
struct clk *xo_clk; /* TCXO clk needed for FLL feature of cm_dll*/
struct mmc_host *mmc; struct mmc_host *mmc;
bool use_14lpp_dll_reset;
}; };
/* Platform specific tuning */ /* Platform specific tuning */
...@@ -305,6 +311,8 @@ static inline void msm_cm_dll_set_freq(struct sdhci_host *host) ...@@ -305,6 +311,8 @@ static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
static int msm_init_cm_dll(struct sdhci_host *host) static int msm_init_cm_dll(struct sdhci_host *host)
{ {
struct mmc_host *mmc = host->mmc; struct mmc_host *mmc = host->mmc;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
int wait_cnt = 50; int wait_cnt = 50;
unsigned long flags; unsigned long flags;
u32 config; u32 config;
...@@ -320,6 +328,16 @@ static int msm_init_cm_dll(struct sdhci_host *host) ...@@ -320,6 +328,16 @@ static int msm_init_cm_dll(struct sdhci_host *host)
config &= ~CORE_CLK_PWRSAVE; config &= ~CORE_CLK_PWRSAVE;
writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
if (msm_host->use_14lpp_dll_reset) {
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
config &= ~CORE_CK_OUT_EN;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
config |= CORE_DLL_CLOCK_DISABLE;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
}
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
config |= CORE_DLL_RST; config |= CORE_DLL_RST;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
...@@ -329,6 +347,28 @@ static int msm_init_cm_dll(struct sdhci_host *host) ...@@ -329,6 +347,28 @@ static int msm_init_cm_dll(struct sdhci_host *host)
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
msm_cm_dll_set_freq(host); 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;
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
config &= CORE_FLL_CYCLE_CNT;
if (config)
mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 8),
clk_get_rate(msm_host->xo_clk));
else
mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 4),
clk_get_rate(msm_host->xo_clk));
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
config &= ~(0xFF << 10);
config |= mclk_freq << 10;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
/* wait for 5us before enabling DLL clock */
udelay(5);
}
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
config &= ~CORE_DLL_RST; config &= ~CORE_DLL_RST;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
...@@ -337,6 +377,13 @@ static int msm_init_cm_dll(struct sdhci_host *host) ...@@ -337,6 +377,13 @@ static int msm_init_cm_dll(struct sdhci_host *host)
config &= ~CORE_DLL_PDN; config &= ~CORE_DLL_PDN;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
if (msm_host->use_14lpp_dll_reset) {
msm_cm_dll_set_freq(host);
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
config &= ~CORE_DLL_CLOCK_DISABLE;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
}
config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
config |= CORE_DLL_EN; config |= CORE_DLL_EN;
writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
...@@ -590,6 +637,16 @@ static int sdhci_msm_probe(struct platform_device *pdev) ...@@ -590,6 +637,16 @@ static int sdhci_msm_probe(struct platform_device *pdev)
goto pclk_disable; goto pclk_disable;
} }
/*
* xo clock is needed for FLL feature of cm_dll.
* In case if xo clock is not mentioned in DT, warn and proceed.
*/
msm_host->xo_clk = devm_clk_get(&pdev->dev, "xo");
if (IS_ERR(msm_host->xo_clk)) {
ret = PTR_ERR(msm_host->xo_clk);
dev_warn(&pdev->dev, "TCXO clk not present (%d)\n", ret);
}
/* Vote for maximum clock rate for maximum performance */ /* Vote for maximum clock rate for maximum performance */
ret = clk_set_rate(msm_host->clk, INT_MAX); ret = clk_set_rate(msm_host->clk, INT_MAX);
if (ret) if (ret)
...@@ -635,6 +692,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) ...@@ -635,6 +692,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n", dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
core_version, core_major, core_minor); core_version, core_major, core_minor);
if (core_major == 1 && core_minor >= 0x42)
msm_host->use_14lpp_dll_reset = true;
/* /*
* Support for some capabilities is not advertised by newer * Support for some capabilities is not advertised by newer
* controller versions and must be explicitly enabled. * controller versions and must be explicitly enabled.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment