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

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.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 8ee5fc0e
Loading
Loading
Loading
Loading
+68 −60
Original line number Diff line number Diff line
@@ -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,9 +175,8 @@ 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;
@@ -222,6 +184,52 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)

	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);
	}
}

static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host,