All of lore.kernel.org
 help / color / mirror / Atom feed
From: Aswath Govindraju <a-govindraju@ti.com>
To: u-boot@lists.denx.de
Subject: [PATCH v3 06/20] mmc: am654_sdhci: Add support for input tap delay
Date: Thu, 21 Jan 2021 18:10:38 +0530	[thread overview]
Message-ID: <20210121124052.3454-7-a-govindraju@ti.com> (raw)
In-Reply-To: <20210121124052.3454-1-a-govindraju@ti.com>

From: Faiz Abbas <faiz_abbas@ti.com>

DLL need only be enabled for speed modes and clock frequencies at or
above 50 MHz. For speed modes that don't enable the DLL, we need to
configure a static input delay value. This involves reading an optional
itap-del-sel-* value from the device tree and configuring it for the
appropriate speed mode.

Therefore, move all dll configurations to their own functions and gate it
with 50 MHz speed and a minimum mode. If both these conditions are not
satisfied then configure delay chain modes.

Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
Signed-off-by: Aswath Govindraju <a-govindraju@ti.com>
---
 drivers/mmc/am654_sdhci.c | 241 +++++++++++++++++++++++++-------------
 1 file changed, 161 insertions(+), 80 deletions(-)

diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c
index 5790fa3d0dbf..b82558254ebb 100644
--- a/drivers/mmc/am654_sdhci.c
+++ b/drivers/mmc/am654_sdhci.c
@@ -62,6 +62,16 @@
 #define CALDONE_MASK		BIT(CALDONE_SHIFT)
 #define RETRIM_SHIFT		17
 #define RETRIM_MASK		BIT(RETRIM_SHIFT)
+#define SELDLYTXCLK_SHIFT	17
+#define SELDLYTXCLK_MASK	BIT(SELDLYTXCLK_SHIFT)
+#define SELDLYRXCLK_SHIFT	16
+#define SELDLYRXCLK_MASK	BIT(SELDLYRXCLK_SHIFT)
+#define ITAPDLYSEL_SHIFT	0
+#define ITAPDLYSEL_MASK		GENMASK(4, 0)
+#define ITAPDLYENA_SHIFT	8
+#define ITAPDLYENA_MASK		BIT(ITAPDLYENA_SHIFT)
+#define ITAPCHGWIN_SHIFT	9
+#define ITAPCHGWIN_MASK		BIT(ITAPCHGWIN_SHIFT)
 
 #define DRIVER_STRENGTH_50_OHM	0x0
 #define DRIVER_STRENGTH_33_OHM	0x1
@@ -70,6 +80,7 @@
 #define DRIVER_STRENGTH_40_OHM	0x4
 
 #define AM654_SDHCI_MIN_FREQ	400000
+#define CLOCK_TOO_SLOW_HZ	50000000
 
 struct am654_sdhci_plat {
 	struct mmc_config cfg;
@@ -77,6 +88,7 @@ struct am654_sdhci_plat {
 	struct regmap *base;
 	bool non_removable;
 	u32 otap_del_sel[MMC_MODES_END];
+	u32 itap_del_sel[MMC_MODES_END];
 	u32 trm_icp;
 	u32 drv_strength;
 	u32 strb_sel;
@@ -89,22 +101,45 @@ struct am654_sdhci_plat {
 };
 
 struct timing_data {
-	const char *binding;
+	const char *otap_binding;
+	const char *itap_binding;
 	u32 capability;
 };
 
 static const struct timing_data td[] = {
-	[MMC_LEGACY] = {"ti,otap-del-sel-legacy", 0},
-	[MMC_HS] = {"ti,otap-del-sel-mmc-hs", MMC_CAP(MMC_HS)},
-	[SD_HS]  = {"ti,otap-del-sel-sd-hs", MMC_CAP(SD_HS)},
-	[UHS_SDR12] = {"ti,otap-del-sel-sdr12", MMC_CAP(UHS_SDR12)},
-	[UHS_SDR25] = {"ti,otap-del-sel-sdr25", MMC_CAP(UHS_SDR25)},
-	[UHS_SDR50] = {"ti,otap-del-sel-sdr50", MMC_CAP(UHS_SDR50)},
-	[UHS_SDR104] = {"ti,otap-del-sel-sdr104", MMC_CAP(UHS_SDR104)},
-	[UHS_DDR50] = {"ti,otap-del-sel-ddr50", MMC_CAP(UHS_DDR50)},
-	[MMC_DDR_52] = {"ti,otap-del-sel-ddr52", MMC_CAP(MMC_DDR_52)},
-	[MMC_HS_200] = {"ti,otap-del-sel-hs200", MMC_CAP(MMC_HS_200)},
-	[MMC_HS_400] = {"ti,otap-del-sel-hs400", MMC_CAP(MMC_HS_400)},
+	[MMC_LEGACY]	= {"ti,otap-del-sel-legacy",
+			   "ti,itap-del-sel-legacy",
+			   0},
+	[MMC_HS]	= {"ti,otap-del-sel-mmc-hs",
+			   "ti,itap-del-sel-mms-hs",
+			   MMC_CAP(MMC_HS)},
+	[SD_HS]		= {"ti,otap-del-sel-sd-hs",
+			   "ti,itap-del-sel-sd-hs",
+			   MMC_CAP(SD_HS)},
+	[UHS_SDR12]	= {"ti,otap-del-sel-sdr12",
+			   "ti,itap-del-sel-sdr12",
+			   MMC_CAP(UHS_SDR12)},
+	[UHS_SDR25]	= {"ti,otap-del-sel-sdr25",
+			   "ti,itap-del-sel-sdr25",
+			   MMC_CAP(UHS_SDR25)},
+	[UHS_SDR50]	= {"ti,otap-del-sel-sdr50",
+			   NULL,
+			   MMC_CAP(UHS_SDR50)},
+	[UHS_SDR104]	= {"ti,otap-del-sel-sdr104",
+			   NULL,
+			   MMC_CAP(UHS_SDR104)},
+	[UHS_DDR50]	= {"ti,otap-del-sel-ddr50",
+			   NULL,
+			   MMC_CAP(UHS_DDR50)},
+	[MMC_DDR_52]	= {"ti,otap-del-sel-ddr52",
+			   "ti,itap-del-sel-ddr52",
+			   MMC_CAP(MMC_DDR_52)},
+	[MMC_HS_200]	= {"ti,otap-del-sel-hs200",
+			   NULL,
+			   MMC_CAP(MMC_HS_200)},
+	[MMC_HS_400]	= {"ti,otap-del-sel-hs400",
+			   NULL,
+			   MMC_CAP(MMC_HS_400)},
 };
 
 struct am654_driver_data {
@@ -127,12 +162,99 @@ static void am654_sdhci_set_control_reg(struct sdhci_host *host)
 	sdhci_set_uhs_timing(host);
 }
 
+static int am654_sdhci_setup_dll(struct am654_sdhci_plat *plat,
+				 unsigned int speed)
+{
+	int sel50, sel100, freqsel;
+	u32 mask, val;
+	int ret;
+
+	/* Disable delay chain mode */
+	regmap_update_bits(plat->base, PHY_CTRL5,
+			   SELDLYTXCLK_MASK | SELDLYRXCLK_MASK, 0);
+
+	if (plat->flags & FREQSEL_2_BIT) {
+		switch (speed) {
+		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(plat->base, PHY_CTRL5, mask, val);
+	} else {
+		switch (speed) {
+		case 200000000:
+			freqsel = 0x0;
+			break;
+		default:
+			freqsel = 0x4;
+		}
+		regmap_update_bits(plat->base, PHY_CTRL5, FREQSEL_MASK,
+				   freqsel << FREQSEL_SHIFT);
+	}
+
+	/* Configure DLL TRIM */
+	mask = DLL_TRIM_ICP_MASK;
+	val = plat->trm_icp << DLL_TRIM_ICP_SHIFT;
+
+	/* Configure DLL driver strength */
+	mask |= DR_TY_MASK;
+	val |= plat->drv_strength << DR_TY_SHIFT;
+	regmap_update_bits(plat->base, PHY_CTRL1, mask, val);
+
+	/* Enable DLL */
+	regmap_update_bits(plat->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(plat->base, PHY_STAT1, val,
+				       val & DLLRDY_MASK, 1000, 1000000);
+
+	return ret;
+}
+
+static void am654_sdhci_write_itapdly(struct am654_sdhci_plat *plat,
+				      u32 itapdly)
+{
+	/* Set ITAPCHGWIN before writing to ITAPDLY */
+	regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK,
+			   1 << ITAPCHGWIN_SHIFT);
+	regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYSEL_MASK,
+			   itapdly << ITAPDLYSEL_SHIFT);
+	regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
+}
+
+static void am654_sdhci_setup_delay_chain(struct am654_sdhci_plat *plat,
+					  int mode)
+{
+	u32 mask, val;
+
+	val = 1 << SELDLYTXCLK_SHIFT | 1 << SELDLYRXCLK_SHIFT;
+	mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK;
+	regmap_update_bits(plat->base, PHY_CTRL5, mask, val);
+
+	am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode]);
+}
+
 static int am654_sdhci_set_ios_post(struct sdhci_host *host)
 {
 	struct udevice *dev = host->mmc->dev;
 	struct am654_sdhci_plat *plat = dev_get_plat(dev);
 	unsigned int speed = host->mmc->clock;
-	int sel50, sel100, freqsel;
+	int mode = host->mmc->selected_mode;
 	u32 otap_del_sel;
 	u32 mask, val;
 	int ret;
@@ -148,75 +270,29 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host)
 	sdhci_set_clock(host->mmc, speed);
 
 	/* switch phy back on */
-	if (speed > AM654_SDHCI_MIN_FREQ) {
-		otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode];
-		mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
-		val = (1 << OTAPDLYENA_SHIFT) |
-		      (otap_del_sel << OTAPDLYSEL_SHIFT);
-
-		/* Write to STRBSEL for HS400 speed mode */
-		if (host->mmc->selected_mode == MMC_HS_400) {
-			if (plat->flags & STRBSEL_4_BIT)
-				mask |= STRBSEL_4BIT_MASK;
-			else
-				mask |= STRBSEL_8BIT_MASK;
-
-			val |= plat->strb_sel << STRBSEL_SHIFT;
-		}
+	otap_del_sel = plat->otap_del_sel[mode];
+	mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
+	val = (1 << OTAPDLYENA_SHIFT) |
+	      (otap_del_sel << OTAPDLYSEL_SHIFT);
 
-		regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
-
-		if (plat->flags & FREQSEL_2_BIT) {
-			switch (speed) {
-			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(plat->base, PHY_CTRL5, mask, val);
-		} else {
-			switch (speed) {
-			case 200000000:
-				freqsel = 0x0;
-				break;
-			default:
-				freqsel = 0x4;
-			}
-			regmap_update_bits(plat->base, PHY_CTRL5, FREQSEL_MASK,
-					   freqsel << FREQSEL_SHIFT);
-		}
+	/* Write to STRBSEL for HS400 speed mode */
+	if (host->mmc->selected_mode == MMC_HS_400) {
+		if (plat->flags & STRBSEL_4_BIT)
+			mask |= STRBSEL_4BIT_MASK;
+		else
+			mask |= STRBSEL_8BIT_MASK;
 
-		/* Configure DLL TRIM */
-		mask = DLL_TRIM_ICP_MASK;
-		val = plat->trm_icp << DLL_TRIM_ICP_SHIFT;
-
-		/* Configure DLL driver strength */
-		mask |= DR_TY_MASK;
-		val |= plat->drv_strength << DR_TY_SHIFT;
-		regmap_update_bits(plat->base, PHY_CTRL1, mask, val);
-
-		/* Enable DLL */
-		regmap_update_bits(plat->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(plat->base, PHY_STAT1, val,
-					 val & DLLRDY_MASK, 1000, 1000000);
+		val |= plat->strb_sel << STRBSEL_SHIFT;
+	}
+
+	regmap_update_bits(plat->base, PHY_CTRL4, mask, val);
+
+	if (mode > UHS_SDR25 && speed >= CLOCK_TOO_SLOW_HZ) {
+		ret = am654_sdhci_setup_dll(plat, speed);
 		if (ret)
 			return ret;
+	} else {
+		am654_sdhci_setup_delay_chain(plat, mode);
 	}
 
 	return 0;
@@ -354,15 +430,20 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev,
 	 * value is not found
 	 */
 	for (i = MMC_HS; i <= MMC_HS_400; i++) {
-		ret = dev_read_u32(dev, td[i].binding, &plat->otap_del_sel[i]);
+		ret = dev_read_u32(dev, td[i].otap_binding,
+				   &plat->otap_del_sel[i]);
 		if (ret) {
-			dev_dbg(dev, "Couldn't find %s\n", td[i].binding);
+			dev_dbg(dev, "Couldn't find %s\n", td[i].otap_binding);
 			/*
 			 * Remove the corresponding capability
 			 * if an otap-del-sel value is not found
 			 */
 			cfg->host_caps &= ~td[i].capability;
 		}
+
+		if (td[i].itap_binding)
+			dev_read_u32(dev, td[i].itap_binding,
+				     &plat->itap_del_sel[i]);
 	}
 
 	return 0;
-- 
2.17.1

  parent reply	other threads:[~2021-01-21 12:40 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-21 12:40 [PATCH v3 00/20] Add support for MMC higher speed modes for TI's am65x, j721e and j7200 platforms Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 01/20] mmc: sdhci: Add helper functions for UHS modes Aswath Govindraju
2021-01-24  2:03   ` Simon Glass
2021-01-25 10:23     ` Aswath Govindraju
2021-01-25 22:18   ` Jaehoon Chung
2021-01-28  9:20     ` Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 02/20] mmc: am654_sdhci: Unconditionally switch off DLL in the beginning of ios_post() Aswath Govindraju
2021-01-25 22:19   ` Jaehoon Chung
2021-01-21 12:40 ` [PATCH v3 03/20] mmc: am654_sdhci: Convert flag fields to BIT macro Aswath Govindraju
2021-01-25 22:19   ` Jaehoon Chung
2021-01-21 12:40 ` [PATCH v3 04/20] mmc: am654_sdhci: Add flag for PHY calibration Aswath Govindraju
2021-01-25 22:19   ` Jaehoon Chung
2021-01-21 12:40 ` [PATCH v3 05/20] mmc: am654_sdhci: Add support for AM65x SR2.0 Aswath Govindraju
2021-01-25 22:19   ` Jaehoon Chung
2021-01-28  9:15     ` Aswath Govindraju
2021-01-21 12:40 ` Aswath Govindraju [this message]
2021-01-25 22:21   ` [PATCH v3 06/20] mmc: am654_sdhci: Add support for input tap delay Jaehoon Chung
2021-01-21 12:40 ` [PATCH v3 07/20] mmc: am654_sdhci: Add support for writing to clkbuf_sel Aswath Govindraju
2021-01-25 22:22   ` Jaehoon Chung
2021-01-21 12:40 ` [PATCH v3 08/20] mmc: am654_sdhci: Add support for software tuning Aswath Govindraju
2021-01-25 22:41   ` Jaehoon Chung
2021-01-21 12:40 ` [PATCH v3 09/20] mmc: am654_sdhci: Fix HISPD bit configuration in some lower speed modes Aswath Govindraju
2021-01-25 22:43   ` Jaehoon Chung
2021-01-21 12:40 ` [PATCH v3 10/20] mmc: am654_sdhci: Use sdhci_set_control_reg() Aswath Govindraju
2021-01-25 22:43   ` Jaehoon Chung
2021-01-21 12:40 ` [PATCH v3 11/20] arm: dts: k3-am65: Fix mmc nodes Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 12/20] arm: dts: k3-j721e-main: Update otap-delay values Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 13/20] arm: dts: k3-j721e-common-proc-board: Add support for UHS modes for SD card Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 14/20] arm: dts: k3-j7200-main: Add support for gpio0 Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 15/20] arm: dts: k3-j7200-common-proc-board: Enable support for UHS modes Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 16/20] configs: j721e_evm: Add " Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 17/20] configs: j7200_evm: " Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 18/20] arm: dts: k3-am65-main: Add itapdly and clkbuf-sel values Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 19/20] arm: dts: k3-am654-base-board: Limit Sd card to High speed modes Aswath Govindraju
2021-01-21 12:40 ` [PATCH v3 20/20] configs: am65x_evm: Add configs for UHS modes Aswath Govindraju

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210121124052.3454-7-a-govindraju@ti.com \
    --to=a-govindraju@ti.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.