Commit a161c45f authored by Faiz Abbas's avatar Faiz Abbas Committed by Ulf Hansson

mmc: sdhci_am654: Enable DLL only for some speed modes

Its recommended that DLL must only be enabled for SDR50, DDR50, DDR52,
SDR104, HS200 and HS400 speed modes. Move DLL configuration to its own
function and call it only in the above speed modes.
Signed-off-by: default avatarFaiz Abbas <faiz_abbas@ti.com>
Acked-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Link: https://lore.kernel.org/r/20200108150920.14547-4-faiz_abbas@ti.comSigned-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 8ee5fc0e
......@@ -119,50 +119,14 @@ static const struct timing_data td[] = {
[MMC_TIMING_MMC_HS400] = {"ti,otap-del-sel-hs400", MMC_CAP2_HS400},
};
static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
static void sdhci_am654_setup_dll(struct sdhci_host *host, unsigned int clock)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
unsigned char timing = host->mmc->ios.timing;
int sel50, sel100, freqsel;
u32 otap_del_sel;
u32 otap_del_ena;
u32 mask, val;
int ret;
if (sdhci_am654->dll_on) {
regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0);
sdhci_am654->dll_on = false;
}
sdhci_set_clock(host, clock);
if (clock > CLOCK_TOO_SLOW_HZ) {
/* Setup DLL Output TAP delay */
if (sdhci_am654->legacy_otapdly)
otap_del_sel = sdhci_am654->otap_del_sel[0];
else
otap_del_sel = sdhci_am654->otap_del_sel[timing];
otap_del_ena = (timing > MMC_TIMING_UHS_SDR25) ? 1 : 0;
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
val = (otap_del_ena << OTAPDLYENA_SHIFT) |
(otap_del_sel << OTAPDLYSEL_SHIFT);
/* Write to STRBSEL for HS400 speed mode */
if (timing == MMC_TIMING_MMC_HS400) {
if (sdhci_am654->flags & STRBSEL_4_BIT)
mask |= STRBSEL_4BIT_MASK;
else
mask |= STRBSEL_8BIT_MASK;
val |= sdhci_am654->strb_sel << STRBSEL_SHIFT;
}
regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val);
if (sdhci_am654->flags & FREQSEL_2_BIT) {
switch (clock) {
case 200000000:
......@@ -181,8 +145,8 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
/* Configure PHY DLL frequency */
mask = SEL50_MASK | SEL100_MASK;
val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT);
regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask,
val);
regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val);
} else {
switch (clock) {
case 200000000:
......@@ -192,11 +156,9 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
freqsel = 0x4;
}
regmap_update_bits(sdhci_am654->base, PHY_CTRL5,
FREQSEL_MASK,
regmap_update_bits(sdhci_am654->base, PHY_CTRL5, FREQSEL_MASK,
freqsel << FREQSEL_SHIFT);
}
/* Configure DLL TRIM */
mask = DLL_TRIM_ICP_MASK;
val = sdhci_am654->trm_icp << DLL_TRIM_ICP_SHIFT;
......@@ -205,6 +167,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
mask |= DR_TY_MASK;
val |= sdhci_am654->drv_strength << DR_TY_SHIFT;
regmap_update_bits(sdhci_am654->base, PHY_CTRL1, mask, val);
/* Enable DLL */
regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK,
0x1 << ENDLL_SHIFT);
......@@ -212,15 +175,60 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
* Poll for DLL ready. Use a one second timeout.
* Works in all experiments done so far
*/
ret = regmap_read_poll_timeout(sdhci_am654->base, PHY_STAT1,
val, val & DLLRDY_MASK, 1000,
1000000);
ret = regmap_read_poll_timeout(sdhci_am654->base, PHY_STAT1, val,
val & DLLRDY_MASK, 1000, 1000000);
if (ret) {
dev_err(mmc_dev(host->mmc), "DLL failed to relock\n");
return;
}
sdhci_am654->dll_on = true;
}
static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
unsigned char timing = host->mmc->ios.timing;
u32 otap_del_sel;
u32 otap_del_ena;
u32 mask, val;
if (sdhci_am654->dll_on) {
regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0);
sdhci_am654->dll_on = false;
}
sdhci_set_clock(host, clock);
if (clock > CLOCK_TOO_SLOW_HZ) {
/* Setup DLL Output TAP delay */
if (sdhci_am654->legacy_otapdly)
otap_del_sel = sdhci_am654->otap_del_sel[0];
else
otap_del_sel = sdhci_am654->otap_del_sel[timing];
otap_del_ena = (timing > MMC_TIMING_UHS_SDR25) ? 1 : 0;
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
val = (otap_del_ena << OTAPDLYENA_SHIFT) |
(otap_del_sel << OTAPDLYSEL_SHIFT);
/* Write to STRBSEL for HS400 speed mode */
if (timing == MMC_TIMING_MMC_HS400) {
if (sdhci_am654->flags & STRBSEL_4_BIT)
mask |= STRBSEL_4BIT_MASK;
else
mask |= STRBSEL_8BIT_MASK;
val |= sdhci_am654->strb_sel << STRBSEL_SHIFT;
}
regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val);
if (timing > MMC_TIMING_UHS_SDR25)
sdhci_am654_setup_dll(host, clock);
}
}
......
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