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: Faiz Abbas <faiz_abbas@ti.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> Link: https://lore.kernel.org/r/20200108150920.14547-4-faiz_abbas@ti.com Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
parent
8ee5fc0e0b
commit
a161c45f29
@ -119,16 +119,80 @@ static const struct timing_data td[] = {
|
||||
[MMC_TIMING_MMC_HS400] = {"ti,otap-del-sel-hs400", MMC_CAP2_HS400},
|
||||
};
|
||||
|
||||
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);
|
||||
int sel50, sel100, freqsel;
|
||||
u32 mask, val;
|
||||
int ret;
|
||||
|
||||
if (sdhci_am654->flags & FREQSEL_2_BIT) {
|
||||
switch (clock) {
|
||||
case 200000000:
|
||||
sel50 = 0;
|
||||
sel100 = 0;
|
||||
break;
|
||||
case 100000000:
|
||||
sel50 = 0;
|
||||
sel100 = 1;
|
||||
break;
|
||||
default:
|
||||
sel50 = 1;
|
||||
sel100 = 0;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
} else {
|
||||
switch (clock) {
|
||||
case 200000000:
|
||||
freqsel = 0x0;
|
||||
break;
|
||||
default:
|
||||
freqsel = 0x4;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* Configure DLL driver strength */
|
||||
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);
|
||||
/*
|
||||
* 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);
|
||||
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;
|
||||
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);
|
||||
@ -163,64 +227,8 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||
|
||||
regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val);
|
||||
|
||||
if (sdhci_am654->flags & FREQSEL_2_BIT) {
|
||||
switch (clock) {
|
||||
case 200000000:
|
||||
sel50 = 0;
|
||||
sel100 = 0;
|
||||
break;
|
||||
case 100000000:
|
||||
sel50 = 0;
|
||||
sel100 = 1;
|
||||
break;
|
||||
default:
|
||||
sel50 = 1;
|
||||
sel100 = 0;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
} else {
|
||||
switch (clock) {
|
||||
case 200000000:
|
||||
freqsel = 0x0;
|
||||
break;
|
||||
default:
|
||||
freqsel = 0x4;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* Configure DLL driver strength */
|
||||
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);
|
||||
/*
|
||||
* 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);
|
||||
if (ret) {
|
||||
dev_err(mmc_dev(host->mmc), "DLL failed to relock\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sdhci_am654->dll_on = true;
|
||||
if (timing > MMC_TIMING_UHS_SDR25)
|
||||
sdhci_am654_setup_dll(host, clock);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user