All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay
@ 2020-10-26 11:42 Michal Simek
  2020-10-26 11:42 ` [PATCH v3 1/8] Revert "mmc: zynq: parse dt when probing" Michal Simek
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Michal Simek @ 2020-10-26 11:42 UTC (permalink / raw)
  To: u-boot

Hi,

this patchset adding support for Tap delay programming for ZynqMP and
Versal.
Based on mainline discussion also DT properties have been introduced which
are documented here.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/Documentation/devicetree/bindings/mmc/mmc-controller.yaml?h=v5.7-rc6&id=fec81c5bca2499b4a263667860018c2ce47f4f51
The patchset is using these DT properties which are optional.
Default values are also listed.

The patchset is based on:
https://lists.denx.de/pipermail/u-boot/2020-May/410326.html

Also new code is adding checking for SOCs which are not needed at that time
when patch is applied (For example "mmc: zynq_sdhci: Read clock phase
delays from dt" and IS_ENABLED(CONFIG_ARCH_ZYNQMP)...
But I kept it there for more cleaner patches built on the top.

Thanks,
Michal


Changes in v3:
 - replace host->version by SDHCI_GET_VERSION(host) reported by Jaehoon
 - replace host->version by SDHCI_GET_VERSION(host) reported by Jaehoon

Changes in v2:
 - Timing macro's are common to all mmc drivers, hence remove zynq_sdhci
   from subject and description.
 - Add common function to set tapdelays based on the values read from DT
 - Remove tapdelay settings based on speed

Ashok Reddy Soma (6):
  Revert "mmc: zynq: parse dt when probing"
  mmc: Define timing macro's
  mmc: zynq_sdhci: Set tapdelays based on clk phase delays
  mmc: zynq_sdhci: Add clock phase delays for Versal
  mmc: zynq_sdhci: Extend UHS timings till hs200
  mmc: zynq_sdhci: Add common function to set input/output tapdelays

Michal Simek (2):
  mmc: zynq_sdhci: Move macro to the top
  mmc: zynq_sdhci: Read clock phase delays from dt

 board/xilinx/zynqmp/tap_delays.c | 199 +++------------
 drivers/mmc/sdhci.c              |   3 +-
 drivers/mmc/zynq_sdhci.c         | 406 +++++++++++++++++++++++++++++--
 include/mmc.h                    |  13 +
 include/sdhci.h                  |   1 +
 include/zynqmp_tap_delay.h       |   5 +-
 6 files changed, 434 insertions(+), 193 deletions(-)

-- 
2.28.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/8] Revert "mmc: zynq: parse dt when probing"
  2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
@ 2020-10-26 11:42 ` Michal Simek
  2020-10-26 11:42 ` [PATCH v3 2/8] mmc: Define timing macro's Michal Simek
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Michal Simek @ 2020-10-26 11:42 UTC (permalink / raw)
  To: u-boot

From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>

This reverts commit 942b5fc03218d1c94468fc658e7dec65dabcc830.

This is partial revert of the above commit.

mmc_of_parse() is reading no-1-8-v from device tree and if set,
it is clearing the UHS speed capabilities of cfg->host_caps.
cfg->host_caps &= ~(UHS_CAPS | MMC_MODE_HS200 |
		    MMC_MODE_HS400 | MMC_MODE_HS400_ES);

This is still missing to clear UHS speeds like SDHCI_SUPPORT_SDR104,
SDHCI_SUPPORT_SDR50 and SDHCI_SUPPORT_DDR50.

Even if we clear the flags SDHCI_SUPPORT_XXX in mmc_of_parse(),
these speed flags are getting set again in cfg->host_caps in
sdhci_setup_cfg().

The reason for this is, SDHCI_SUPPORT_XXX flags are cleared
only if controller is not capable of supporting MMC_VDD_165_195 volts.

if (caps & SDHCI_CAN_VDD_180)
	cfg->voltages |= MMC_VDD_165_195;

if (!(cfg->voltages & MMC_VDD_165_195))
	caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
		    SDHCI_SUPPORT_DDR50);

It means "no-1-8-v", which is read from DT is not coming in to effect.
So it is better we keep the host quirks(SDHCI_QUIRK_NO_1_8_V) to
clear UHS speeds based on no-1-8-v from device tree.

Hence revert the functionality related to no-1-8-v only, rest is fine
in the patch.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
---

(no changes since v1)

 drivers/mmc/sdhci.c      | 3 ++-
 drivers/mmc/zynq_sdhci.c | 5 +++++
 include/sdhci.h          | 1 +
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index d549a264d73b..06289343124e 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -812,7 +812,8 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 		cfg->host_caps &= ~MMC_MODE_HS_52MHz;
 	}
 
-	if (!(cfg->voltages & MMC_VDD_165_195))
+	if (!(cfg->voltages & MMC_VDD_165_195) ||
+	    (host->quirks & SDHCI_QUIRK_NO_1_8_V))
 		caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
 			    SDHCI_SUPPORT_DDR50);
 
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 775c17baac5b..88e478ee11c1 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -28,6 +28,7 @@ struct arasan_sdhci_priv {
 	struct sdhci_host *host;
 	u8 deviceid;
 	u8 bank;
+	u8 no_1p8;
 };
 
 #if defined(CONFIG_ARCH_ZYNQMP)
@@ -236,6 +237,9 @@ static int arasan_sdhci_probe(struct udevice *dev)
 	host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE;
 #endif
 
+	if (priv->no_1p8)
+		host->quirks |= SDHCI_QUIRK_NO_1_8_V;
+
 	plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
 
 	ret = mmc_of_parse(dev, &plat->cfg);
@@ -277,6 +281,7 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
 
 	priv->deviceid = dev_read_u32_default(dev, "xlnx,device_id", -1);
 	priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0);
+	priv->no_1p8 = dev_read_bool(dev, "no-1-8-v");
 
 	return 0;
 }
diff --git a/include/sdhci.h b/include/sdhci.h
index f69d5f81fb1b..1fd20ec0860b 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -244,6 +244,7 @@
 #define SDHCI_QUIRK_BROKEN_HISPD_MODE	BIT(5)
 #define SDHCI_QUIRK_WAIT_SEND_CMD	(1 << 6)
 #define SDHCI_QUIRK_USE_WIDE8		(1 << 8)
+#define SDHCI_QUIRK_NO_1_8_V		(1 << 9)
 
 /* to make gcc happy */
 struct sdhci_host;
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 2/8] mmc: Define timing macro's
  2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
  2020-10-26 11:42 ` [PATCH v3 1/8] Revert "mmc: zynq: parse dt when probing" Michal Simek
@ 2020-10-26 11:42 ` Michal Simek
  2020-10-26 11:42 ` [PATCH v3 3/8] mmc: zynq_sdhci: Move macro to the top Michal Simek
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Michal Simek @ 2020-10-26 11:42 UTC (permalink / raw)
  To: u-boot

From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>

Define timing macro's for all the available speeds of mmc. This is
done similar to linux. Replace speed macro's used with these new timing
macro's wherever applicable.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
---

(no changes since v2)

Changes in v2:
 - Timing macro's are common to all mmc drivers, hence remove zynq_sdhci
   from subject and description.

 board/xilinx/zynqmp/tap_delays.c |  9 ---------
 drivers/mmc/zynq_sdhci.c         | 24 +++++++++++-------------
 include/mmc.h                    | 13 +++++++++++++
 3 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
index 5fde0aed7dbe..813650cabcc4 100644
--- a/board/xilinx/zynqmp/tap_delays.c
+++ b/board/xilinx/zynqmp/tap_delays.c
@@ -54,15 +54,6 @@
 
 #define MMC_BANK2		0x2
 
-#define MMC_TIMING_UHS_SDR25		1
-#define MMC_TIMING_UHS_SDR50		2
-#define MMC_TIMING_UHS_SDR104		3
-#define MMC_TIMING_UHS_DDR50		4
-#define MMC_TIMING_MMC_HS200		5
-#define MMC_TIMING_SD_HS		6
-#define MMC_TIMING_MMC_DDR52		7
-#define MMC_TIMING_MMC_HS		8
-
 void zynqmp_dll_reset(u8 deviceid)
 {
 	/* Issue DLL Reset */
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 88e478ee11c1..4f62bd008d24 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -32,20 +32,18 @@ struct arasan_sdhci_priv {
 };
 
 #if defined(CONFIG_ARCH_ZYNQMP)
-#define MMC_HS200_BUS_SPEED	5
-
 static const u8 mode2timing[] = {
-	[MMC_LEGACY] = UHS_SDR12_BUS_SPEED,
-	[MMC_HS] = HIGH_SPEED_BUS_SPEED,
-	[SD_HS] = HIGH_SPEED_BUS_SPEED,
-	[MMC_HS_52] = HIGH_SPEED_BUS_SPEED,
-	[MMC_DDR_52] = HIGH_SPEED_BUS_SPEED,
-	[UHS_SDR12] = UHS_SDR12_BUS_SPEED,
-	[UHS_SDR25] = UHS_SDR25_BUS_SPEED,
-	[UHS_SDR50] = UHS_SDR50_BUS_SPEED,
-	[UHS_DDR50] = UHS_DDR50_BUS_SPEED,
-	[UHS_SDR104] = UHS_SDR104_BUS_SPEED,
-	[MMC_HS_200] = MMC_HS200_BUS_SPEED,
+	[MMC_LEGACY] = MMC_TIMING_LEGACY,
+	[MMC_HS] = MMC_TIMING_MMC_HS,
+	[SD_HS] = MMC_TIMING_SD_HS,
+	[MMC_HS_52] = MMC_TIMING_UHS_SDR50,
+	[MMC_DDR_52] = MMC_TIMING_UHS_DDR50,
+	[UHS_SDR12] = MMC_TIMING_UHS_SDR12,
+	[UHS_SDR25] = MMC_TIMING_UHS_SDR25,
+	[UHS_SDR50] = MMC_TIMING_UHS_SDR50,
+	[UHS_DDR50] = MMC_TIMING_UHS_DDR50,
+	[UHS_SDR104] = MMC_TIMING_UHS_SDR104,
+	[MMC_HS_200] = MMC_TIMING_MMC_HS200,
 };
 
 #define SDHCI_TUNING_LOOP_COUNT	40
diff --git a/include/mmc.h b/include/mmc.h
index ac7b54f1a7e0..1d377e0281f1 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -360,6 +360,19 @@ enum mmc_voltage {
 #define MMC_NUM_BOOT_PARTITION	2
 #define MMC_PART_RPMB           3       /* RPMB partition number */
 
+/* timing specification used */
+#define MMC_TIMING_LEGACY	0
+#define MMC_TIMING_MMC_HS	1
+#define MMC_TIMING_SD_HS	2
+#define MMC_TIMING_UHS_SDR12	3
+#define MMC_TIMING_UHS_SDR25	4
+#define MMC_TIMING_UHS_SDR50	5
+#define MMC_TIMING_UHS_SDR104	6
+#define MMC_TIMING_UHS_DDR50	7
+#define MMC_TIMING_MMC_DDR52	8
+#define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
+
 /* Driver model support */
 
 /**
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 3/8] mmc: zynq_sdhci: Move macro to the top
  2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
  2020-10-26 11:42 ` [PATCH v3 1/8] Revert "mmc: zynq: parse dt when probing" Michal Simek
  2020-10-26 11:42 ` [PATCH v3 2/8] mmc: Define timing macro's Michal Simek
@ 2020-10-26 11:42 ` Michal Simek
  2020-10-26 21:38   ` Jaehoon Chung
  2020-10-26 11:42 ` [PATCH v3 4/8] mmc: zynq_sdhci: Read clock phase delays from dt Michal Simek
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2020-10-26 11:42 UTC (permalink / raw)
  To: u-boot

Just group macros below headers. Other patches will be using this location
too.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
---

(no changes since v1)

 drivers/mmc/zynq_sdhci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 4f62bd008d24..998a38450680 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -19,6 +19,8 @@
 #include <sdhci.h>
 #include <zynqmp_tap_delay.h>
 
+#define SDHCI_TUNING_LOOP_COUNT		40
+
 struct arasan_sdhci_plat {
 	struct mmc_config cfg;
 	struct mmc mmc;
@@ -46,8 +48,6 @@ static const u8 mode2timing[] = {
 	[MMC_HS_200] = MMC_TIMING_MMC_HS200,
 };
 
-#define SDHCI_TUNING_LOOP_COUNT	40
-
 static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
 {
 	u16 clk;
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 4/8] mmc: zynq_sdhci: Read clock phase delays from dt
  2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
                   ` (2 preceding siblings ...)
  2020-10-26 11:42 ` [PATCH v3 3/8] mmc: zynq_sdhci: Move macro to the top Michal Simek
@ 2020-10-26 11:42 ` Michal Simek
  2020-10-26 21:38   ` Jaehoon Chung
  2020-10-26 11:42 ` [PATCH v3 5/8] mmc: zynq_sdhci: Set tapdelays based on clk phase delays Michal Simek
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2020-10-26 11:42 UTC (permalink / raw)
  To: u-boot

Define input and output clock phase delays with pre-defined values.

Define arasan_sdhci_clk_data type structure and add it to priv
structure and store these clock phase delays in it.

Read input and output clock phase delays from dt. If these values are
not passed through dt, use pre-defined values.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
---

(no changes since v1)

 drivers/mmc/zynq_sdhci.c | 85 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 998a38450680..e69f375cce07 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -20,6 +20,12 @@
 #include <zynqmp_tap_delay.h>
 
 #define SDHCI_TUNING_LOOP_COUNT		40
+#define MMC_BANK2			0x2
+
+struct arasan_sdhci_clk_data {
+	int clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
+	int clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
+};
 
 struct arasan_sdhci_plat {
 	struct mmc_config cfg;
@@ -28,12 +34,17 @@ struct arasan_sdhci_plat {
 
 struct arasan_sdhci_priv {
 	struct sdhci_host *host;
+	struct arasan_sdhci_clk_data clk_data;
 	u8 deviceid;
 	u8 bank;
 	u8 no_1p8;
 };
 
 #if defined(CONFIG_ARCH_ZYNQMP)
+/* Default settings for ZynqMP Clock Phases */
+const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63,  0,   0, 183, 54,  0, 0};
+const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0};
+
 static const u8 mode2timing[] = {
 	[MMC_LEGACY] = MMC_TIMING_LEGACY,
 	[MMC_HS] = MMC_TIMING_MMC_HS,
@@ -168,6 +179,79 @@ static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
 					   priv->bank);
 }
 
+static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
+				     const char *prop)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+	struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
+	u32 clk_phase[2] = {0};
+
+	/*
+	 * Read Tap Delay values from DT, if the DT does not contain the
+	 * Tap Values then use the pre-defined values
+	 */
+	if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) {
+		dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
+			prop, clk_data->clk_phase_in[timing],
+			clk_data->clk_phase_out[timing]);
+		return;
+	}
+
+	/* The values read are Input and Output Clock Delays in order */
+	clk_data->clk_phase_in[timing] = clk_phase[0];
+	clk_data->clk_phase_out[timing] = clk_phase[1];
+}
+
+/**
+ * arasan_dt_parse_clk_phases - Read Tap Delay values from DT
+ *
+ * Called at initialization to parse the values of Tap Delays.
+ *
+ * @dev:                Pointer to our struct udevice.
+ */
+static void arasan_dt_parse_clk_phases(struct udevice *dev)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
+	struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
+	int i;
+
+	if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
+	    device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
+		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
+			clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i];
+			clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i];
+		}
+
+		if (priv->bank == MMC_BANK2) {
+			clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90;
+			clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90;
+		}
+	}
+
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
+				 "clk-phase-legacy");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
+				 "clk-phase-mmc-hs");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS,
+				 "clk-phase-sd-hs");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12,
+				 "clk-phase-uhs-sdr12");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25,
+				 "clk-phase-uhs-sdr25");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50,
+				 "clk-phase-uhs-sdr50");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104,
+				 "clk-phase-uhs-sdr104");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50,
+				 "clk-phase-uhs-ddr50");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52,
+				 "clk-phase-mmc-ddr52");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200,
+				 "clk-phase-mmc-hs200");
+	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400,
+				 "clk-phase-mmc-hs400");
+}
+
 static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
 {
 	struct mmc *mmc = (struct mmc *)host->mmc;
@@ -271,6 +355,7 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
 
 #if defined(CONFIG_ARCH_ZYNQMP)
 	priv->host->ops = &arasan_ops;
+	arasan_dt_parse_clk_phases(dev);
 #endif
 
 	priv->host->ioaddr = (void *)dev_read_addr(dev);
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 5/8] mmc: zynq_sdhci: Set tapdelays based on clk phase delays
  2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
                   ` (3 preceding siblings ...)
  2020-10-26 11:42 ` [PATCH v3 4/8] mmc: zynq_sdhci: Read clock phase delays from dt Michal Simek
@ 2020-10-26 11:42 ` Michal Simek
  2020-10-26 21:38   ` Jaehoon Chung
  2020-10-26 11:42 ` [PATCH v3 6/8] mmc: zynq_sdhci: Add clock phase delays for Versal Michal Simek
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2020-10-26 11:42 UTC (permalink / raw)
  To: u-boot

From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>

Define and use functions for setting input and output tapdelays
based on clk phase delays.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>

---

Changes in v3:
 - replace host->version by SDHCI_GET_VERSION(host) reported by Jaehoon

 drivers/mmc/zynq_sdhci.c | 128 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 123 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index e69f375cce07..8871765711d4 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -166,17 +166,135 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 	return 0;
 }
 
+/**
+ * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
+ *
+ * Set the SD Output Clock Tap Delays for Output path
+ *
+ * @host:		Pointer to the sdhci_host structure.
+ * @degrees:		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
+					    int degrees)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+	int timing = mode2timing[mmc->selected_mode];
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * ZynqMP does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
+	    timing == MMC_TIMING_LEGACY ||
+	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
+		return 0;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 30 Taps are available */
+		tap_max = 30;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 15 Taps are available */
+		tap_max = 15;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 8 Taps are available */
+		tap_max = 8;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	arasan_zynqmp_set_tapdelay(priv->deviceid, 0, tap_delay);
+
+	return ret;
+}
+
+/**
+ * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
+ *
+ * Set the SD Input Clock Tap Delays for Input path
+ *
+ * @host:		Pointer to the sdhci_host structure.
+ * @degrees:		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
+					    int degrees)
+{
+	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+	int timing = mode2timing[mmc->selected_mode];
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * ZynqMP does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
+	    timing == MMC_TIMING_LEGACY ||
+	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
+		return 0;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 120 Taps are available */
+		tap_max = 120;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 60 Taps are available */
+		tap_max = 60;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 30 Taps are available */
+		tap_max = 30;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	arasan_zynqmp_set_tapdelay(priv->deviceid, tap_delay, 0);
+
+	return ret;
+}
+
 static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
 {
 	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
+	struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
 	struct mmc *mmc = (struct mmc *)host->mmc;
-	u8 uhsmode;
+	struct udevice *dev = mmc->dev;
+	u8 timing = mode2timing[mmc->selected_mode];
+	u32 iclk_phase = clk_data->clk_phase_in[timing];
+	u32 oclk_phase = clk_data->clk_phase_out[timing];
 
-	uhsmode = mode2timing[mmc->selected_mode];
+	dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
 
-	if (uhsmode >= UHS_SDR25_BUS_SPEED)
-		arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode,
-					   priv->bank);
+	if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
+	    device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
+		sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
+		sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
+	}
 }
 
 static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 6/8] mmc: zynq_sdhci: Add clock phase delays for Versal
  2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
                   ` (4 preceding siblings ...)
  2020-10-26 11:42 ` [PATCH v3 5/8] mmc: zynq_sdhci: Set tapdelays based on clk phase delays Michal Simek
@ 2020-10-26 11:42 ` Michal Simek
  2020-10-26 21:38   ` Jaehoon Chung
  2020-10-26 11:43 ` [PATCH v3 7/8] mmc: zynq_sdhci: Extend UHS timings till hs200 Michal Simek
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2020-10-26 11:42 UTC (permalink / raw)
  To: u-boot

From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>

Define default values for input and output clock phase delays for
Versal. Also define functions for setting tapdelays based on these
clock phase delays.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
---

Changes in v3:
 - replace host->version by SDHCI_GET_VERSION(host) reported by Jaehoon

 drivers/mmc/zynq_sdhci.c | 160 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 156 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 8871765711d4..d55ba74b2c38 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -19,6 +19,12 @@
 #include <sdhci.h>
 #include <zynqmp_tap_delay.h>
 
+#define SDHCI_ARASAN_ITAPDLY_REGISTER   0xF0F8
+#define SDHCI_ARASAN_OTAPDLY_REGISTER   0xF0FC
+#define SDHCI_ITAPDLY_CHGWIN            0x200
+#define SDHCI_ITAPDLY_ENABLE            0x100
+#define SDHCI_OTAPDLY_ENABLE            0x40
+
 #define SDHCI_TUNING_LOOP_COUNT		40
 #define MMC_BANK2			0x2
 
@@ -40,11 +46,15 @@ struct arasan_sdhci_priv {
 	u8 no_1p8;
 };
 
-#if defined(CONFIG_ARCH_ZYNQMP)
+#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
 /* Default settings for ZynqMP Clock Phases */
 const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63,  0,   0, 183, 54,  0, 0};
 const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0};
 
+/* Default settings for Versal Clock Phases */
+const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0};
+const u32 versal_oclk_phases[] = {0,  60, 48, 0, 48, 72, 90, 36, 60, 90, 0};
+
 static const u8 mode2timing[] = {
 	[MMC_LEGACY] = MMC_TIMING_LEGACY,
 	[MMC_HS] = MMC_TIMING_MMC_HS,
@@ -278,6 +288,138 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
 	return ret;
 }
 
+/**
+ * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
+ *
+ * Set the SD Output Clock Tap Delays for Output path
+ *
+ * @host:		Pointer to the sdhci_host structure.
+ * @degrees		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host,
+					    int degrees)
+{
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+	int timing = mode2timing[mmc->selected_mode];
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * Versal does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
+	    timing == MMC_TIMING_LEGACY ||
+	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
+		return 0;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 30 Taps are available */
+		tap_max = 30;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 15 Taps are available */
+		tap_max = 15;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 8 Taps are available */
+		tap_max = 8;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	/* Set the Clock Phase */
+	if (tap_delay) {
+		u32 regval;
+
+		regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
+		regval |= SDHCI_OTAPDLY_ENABLE;
+		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
+		regval |= tap_delay;
+		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
+	}
+
+	return ret;
+}
+
+/**
+ * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
+ *
+ * Set the SD Input Clock Tap Delays for Input path
+ *
+ * @host:		Pointer to the sdhci_host structure.
+ * @degrees		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
+					    int degrees)
+{
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+	int timing = mode2timing[mmc->selected_mode];
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * Versal does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
+	    timing == MMC_TIMING_LEGACY ||
+	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
+		return 0;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 120 Taps are available */
+		tap_max = 120;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 60 Taps are available */
+		tap_max = 60;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 30 Taps are available */
+		tap_max = 30;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	/* Set the Clock Phase */
+	if (tap_delay) {
+		u32 regval;
+
+		regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval |= SDHCI_ITAPDLY_CHGWIN;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval |= SDHCI_ITAPDLY_ENABLE;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval |= tap_delay;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval &= ~SDHCI_ITAPDLY_CHGWIN;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+	}
+
+	return ret;
+}
+
 static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
 {
 	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
@@ -294,6 +436,10 @@ static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
 	    device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
 		sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
 		sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
+	} else if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
+		   device_is_compatible(dev, "xlnx,versal-8.9a")) {
+		sdhci_versal_sampleclk_set_phase(host, iclk_phase);
+		sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
 	}
 }
 
@@ -346,6 +492,14 @@ static void arasan_dt_parse_clk_phases(struct udevice *dev)
 		}
 	}
 
+	if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
+	    device_is_compatible(dev, "xlnx,versal-8.9a")) {
+		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
+			clk_data->clk_phase_in[i] = versal_iclk_phases[i];
+			clk_data->clk_phase_out[i] = versal_oclk_phases[i];
+		}
+	}
+
 	arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
 				 "clk-phase-legacy");
 	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
@@ -388,9 +542,7 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
 	    mmc->selected_mode <= UHS_DDR50)
 		sdhci_set_uhs_timing(host);
 }
-#endif
 
-#if defined(CONFIG_ARCH_ZYNQMP)
 const struct sdhci_ops arasan_ops = {
 	.platform_execute_tuning = &arasan_sdhci_execute_tuning,
 	.set_delay = &arasan_sdhci_set_tapdelay,
@@ -471,7 +623,7 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
 
 	priv->host->name = dev->name;
 
-#if defined(CONFIG_ARCH_ZYNQMP)
+#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
 	priv->host->ops = &arasan_ops;
 	arasan_dt_parse_clk_phases(dev);
 #endif
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 7/8] mmc: zynq_sdhci: Extend UHS timings till hs200
  2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
                   ` (5 preceding siblings ...)
  2020-10-26 11:42 ` [PATCH v3 6/8] mmc: zynq_sdhci: Add clock phase delays for Versal Michal Simek
@ 2020-10-26 11:43 ` Michal Simek
  2020-10-26 21:39   ` Jaehoon Chung
  2020-10-26 11:43 ` [PATCH v3 8/8] mmc: zynq_sdhci: Add common function to set input/output tapdelays Michal Simek
  2020-10-29  7:57 ` [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
  8 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2020-10-26 11:43 UTC (permalink / raw)
  To: u-boot

From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>

Fix the condition to set UHS timings for speeds upto HS200.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
---

(no changes since v1)

 drivers/mmc/zynq_sdhci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index d55ba74b2c38..147ecc0d708d 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -539,7 +539,7 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
 	}
 
 	if (mmc->selected_mode > SD_HS &&
-	    mmc->selected_mode <= UHS_DDR50)
+	    mmc->selected_mode <= MMC_HS_200)
 		sdhci_set_uhs_timing(host);
 }
 
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 8/8] mmc: zynq_sdhci: Add common function to set input/output tapdelays
  2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
                   ` (6 preceding siblings ...)
  2020-10-26 11:43 ` [PATCH v3 7/8] mmc: zynq_sdhci: Extend UHS timings till hs200 Michal Simek
@ 2020-10-26 11:43 ` Michal Simek
  2020-10-29  7:57 ` [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
  8 siblings, 0 replies; 15+ messages in thread
From: Michal Simek @ 2020-10-26 11:43 UTC (permalink / raw)
  To: u-boot

From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>

Remove setting tapdelays for different speeds separately. Instead use
the ITAP and OTAP delay values which are read from the device tree.
If the DT does not contain tap delay values, the predefined values
will be used for the same.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
---

(no changes since v2)

Changes in v2:
 - Add common function to set tapdelays based on the values read from DT
 - Remove tapdelay settings based on speed

 board/xilinx/zynqmp/tap_delays.c | 190 ++++++-------------------------
 include/zynqmp_tap_delay.h       |   5 +-
 2 files changed, 36 insertions(+), 159 deletions(-)

diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
index 813650cabcc4..c4770c8fb6e9 100644
--- a/board/xilinx/zynqmp/tap_delays.c
+++ b/board/xilinx/zynqmp/tap_delays.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <zynqmp_tap_delay.h>
 #include <asm/arch/sys_proto.h>
 #include <linux/delay.h>
 
@@ -25,34 +26,9 @@
 #define SD1_ITAPDLYENA_MASK		0x01000000
 #define SD1_ITAPDLYENA			0x01000000
 #define SD0_ITAPDLYSEL_MASK		0x000000FF
-#define SD0_ITAPDLYSEL_HSD		0x00000015
-#define SD0_ITAPDLYSEL_SD_DDR50		0x0000003D
-#define SD0_ITAPDLYSEL_MMC_DDR50	0x00000012
-
 #define SD1_ITAPDLYSEL_MASK		0x00FF0000
-#define SD1_ITAPDLYSEL_HSD		0x00150000
-#define SD1_ITAPDLYSEL_SD_DDR50		0x003D0000
-#define SD1_ITAPDLYSEL_MMC_DDR50	0x00120000
-
 #define SD0_OTAPDLYSEL_MASK		0x0000003F
-#define SD0_OTAPDLYSEL_MMC_HSD		0x00000006
-#define SD0_OTAPDLYSEL_SD_HSD		0x00000005
-#define SD0_OTAPDLYSEL_SDR50		0x00000003
-#define SD0_OTAPDLYSEL_SDR104_B0	0x00000003
-#define SD0_OTAPDLYSEL_SDR104_B2	0x00000002
-#define SD0_OTAPDLYSEL_SD_DDR50		0x00000004
-#define SD0_OTAPDLYSEL_MMC_DDR50	0x00000006
-
 #define SD1_OTAPDLYSEL_MASK		0x003F0000
-#define SD1_OTAPDLYSEL_MMC_HSD		0x00060000
-#define SD1_OTAPDLYSEL_SD_HSD		0x00050000
-#define SD1_OTAPDLYSEL_SDR50		0x00030000
-#define SD1_OTAPDLYSEL_SDR104_B0	0x00030000
-#define SD1_OTAPDLYSEL_SDR104_B2	0x00020000
-#define SD1_OTAPDLYSEL_SD_DDR50		0x00040000
-#define SD1_OTAPDLYSEL_MMC_DDR50	0x00060000
-
-#define MMC_BANK2		0x2
 
 void zynqmp_dll_reset(u8 deviceid)
 {
@@ -73,149 +49,49 @@ void zynqmp_dll_reset(u8 deviceid)
 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
 }
 
-static void arasan_zynqmp_tap_sdr104(u8 deviceid, u8 timing, u8 bank)
-{
-	if (deviceid == 0) {
-		/* Program OTAP */
-		if (bank == MMC_BANK2)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_SDR104_B2);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_SDR104_B0);
-	} else {
-		/* Program OTAP */
-		if (bank == MMC_BANK2)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_SDR104_B2);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_SDR104_B0);
-	}
-}
-
-static void arasan_zynqmp_tap_hs(u8 deviceid, u8 timing, u8 bank)
-{
-	if (deviceid == 0) {
-		/* Program ITAP */
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
-				  SD0_ITAPCHGWIN);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
-				  SD0_ITAPDLYENA);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
-				  SD0_ITAPDLYSEL_HSD);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
-		/* Program OTAP */
-		if (timing == MMC_TIMING_MMC_HS)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_MMC_HSD);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_SD_HSD);
-	} else {
-		/* Program ITAP */
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
-				  SD1_ITAPCHGWIN);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
-				  SD1_ITAPDLYENA);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
-				  SD1_ITAPDLYSEL_HSD);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
-		/* Program OTAP */
-		if (timing == MMC_TIMING_MMC_HS)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_MMC_HSD);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_SD_HSD);
-	}
-}
-
-static void arasan_zynqmp_tap_ddr50(u8 deviceid, u8 timing, u8 bank)
+void arasan_zynqmp_set_tapdelay(u8 deviceid, u32 itap_delay, u32 otap_delay)
 {
 	if (deviceid == 0) {
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
+				  SD0_DLL_RST);
 		/* Program ITAP */
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
-				  SD0_ITAPCHGWIN);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
-				  SD0_ITAPDLYENA);
-		if (timing == MMC_TIMING_UHS_DDR50)
-			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
-					  SD0_ITAPDLYSEL_SD_DDR50);
-		else
+		if (itap_delay) {
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+					  SD0_ITAPCHGWIN);
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA_MASK,
+					  SD0_ITAPDLYENA);
 			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
-					  SD0_ITAPDLYSEL_MMC_DDR50);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+					  itap_delay);
+			zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK,
+					  0x0);
+		}
+
 		/* Program OTAP */
-		if (timing == MMC_TIMING_UHS_DDR50)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_SD_DDR50);
-		else
+		if (otap_delay)
 			zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-					  SD0_OTAPDLYSEL_MMC_DDR50);
-	} else {
-		/* Program ITAP */
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
-				  SD1_ITAPCHGWIN);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
-				  SD1_ITAPDLYENA);
-		if (timing == MMC_TIMING_UHS_DDR50)
-			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
-					  SD1_ITAPDLYSEL_SD_DDR50);
-		else
-			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
-					  SD1_ITAPDLYSEL_MMC_DDR50);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK, 0x0);
-		/* Program OTAP */
-		if (timing == MMC_TIMING_UHS_DDR50)
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_SD_DDR50);
-		else
-			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					  SD1_OTAPDLYSEL_MMC_DDR50);
-	}
-}
+					  otap_delay);
 
-static void arasan_zynqmp_tap_sdr50(u8 deviceid, u8 timing, u8 bank)
-{
-	if (deviceid == 0) {
-		/* Program OTAP */
-		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK,
-				  SD0_OTAPDLYSEL_SDR50);
+		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
 	} else {
-		/* Program OTAP */
-		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-				  SD1_OTAPDLYSEL_SDR50);
-	}
-}
-
-void arasan_zynqmp_set_tapdelay(u8 deviceid, u8 timing, u8 bank)
-{
-	if (deviceid == 0)
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK,
-				  SD0_DLL_RST);
-	else
 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK,
 				  SD1_DLL_RST);
+		/* Program ITAP */
+		if (itap_delay) {
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+					  SD1_ITAPCHGWIN);
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA_MASK,
+					  SD1_ITAPDLYENA);
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+					  (itap_delay << 16));
+			zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN_MASK,
+					  0x0);
+		}
 
-	switch (timing) {
-	case MMC_TIMING_UHS_SDR25:
-		arasan_zynqmp_tap_hs(deviceid, timing, bank);
-		break;
-	case MMC_TIMING_UHS_SDR50:
-		arasan_zynqmp_tap_sdr50(deviceid, timing, bank);
-		break;
-	case MMC_TIMING_UHS_SDR104:
-	case MMC_TIMING_MMC_HS200:
-		arasan_zynqmp_tap_sdr104(deviceid, timing, bank);
-		break;
-	case MMC_TIMING_UHS_DDR50:
-		arasan_zynqmp_tap_ddr50(deviceid, timing, bank);
-		break;
-	}
+		/* Program OTAP */
+		if (otap_delay)
+			zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					  (otap_delay << 16));
 
-	if (deviceid == 0)
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
-	else
 		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+	}
 }
diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h
index b07e3e069224..7b713438f752 100644
--- a/include/zynqmp_tap_delay.h
+++ b/include/zynqmp_tap_delay.h
@@ -10,10 +10,11 @@
 
 #ifdef CONFIG_ARCH_ZYNQMP
 void zynqmp_dll_reset(u8 deviceid);
-void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank);
+void arasan_zynqmp_set_tapdelay(u8 device_id, u32 itap_delay, u32 otap_delay);
 #else
 inline void zynqmp_dll_reset(u8 deviceid) {}
-inline void arasan_zynqmp_set_tapdelay(u8 device_id, u8 uhsmode, u8 bank) {}
+inline void arasan_zynqmp_set_tapdelay(u8 device_id, u32 itap_delay,
+				       u32 otap_delay) {}
 #endif
 
 #endif
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 3/8] mmc: zynq_sdhci: Move macro to the top
  2020-10-26 11:42 ` [PATCH v3 3/8] mmc: zynq_sdhci: Move macro to the top Michal Simek
@ 2020-10-26 21:38   ` Jaehoon Chung
  0 siblings, 0 replies; 15+ messages in thread
From: Jaehoon Chung @ 2020-10-26 21:38 UTC (permalink / raw)
  To: u-boot

On 10/26/20 8:42 PM, Michal Simek wrote:
> Just group macros below headers. Other patches will be using this location
> too.
> 
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
> Reviewed-by: Peng Fan <peng.fan@nxp.com>

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

> ---
> 
> (no changes since v1)
> 
>  drivers/mmc/zynq_sdhci.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
> index 4f62bd008d24..998a38450680 100644
> --- a/drivers/mmc/zynq_sdhci.c
> +++ b/drivers/mmc/zynq_sdhci.c
> @@ -19,6 +19,8 @@
>  #include <sdhci.h>
>  #include <zynqmp_tap_delay.h>
>  
> +#define SDHCI_TUNING_LOOP_COUNT		40
> +
>  struct arasan_sdhci_plat {
>  	struct mmc_config cfg;
>  	struct mmc mmc;
> @@ -46,8 +48,6 @@ static const u8 mode2timing[] = {
>  	[MMC_HS_200] = MMC_TIMING_MMC_HS200,
>  };
>  
> -#define SDHCI_TUNING_LOOP_COUNT	40
> -
>  static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
>  {
>  	u16 clk;
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 4/8] mmc: zynq_sdhci: Read clock phase delays from dt
  2020-10-26 11:42 ` [PATCH v3 4/8] mmc: zynq_sdhci: Read clock phase delays from dt Michal Simek
@ 2020-10-26 21:38   ` Jaehoon Chung
  0 siblings, 0 replies; 15+ messages in thread
From: Jaehoon Chung @ 2020-10-26 21:38 UTC (permalink / raw)
  To: u-boot

On 10/26/20 8:42 PM, Michal Simek wrote:
> Define input and output clock phase delays with pre-defined values.
> 
> Define arasan_sdhci_clk_data type structure and add it to priv
> structure and store these clock phase delays in it.
> 
> Read input and output clock phase delays from dt. If these values are
> not passed through dt, use pre-defined values.
> 
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> Reviewed-by: Peng Fan <peng.fan@nxp.com>

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

> ---
> 
> (no changes since v1)
> 
>  drivers/mmc/zynq_sdhci.c | 85 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 85 insertions(+)
> 
> diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
> index 998a38450680..e69f375cce07 100644
> --- a/drivers/mmc/zynq_sdhci.c
> +++ b/drivers/mmc/zynq_sdhci.c
> @@ -20,6 +20,12 @@
>  #include <zynqmp_tap_delay.h>
>  
>  #define SDHCI_TUNING_LOOP_COUNT		40
> +#define MMC_BANK2			0x2
> +
> +struct arasan_sdhci_clk_data {
> +	int clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
> +	int clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
> +};
>  
>  struct arasan_sdhci_plat {
>  	struct mmc_config cfg;
> @@ -28,12 +34,17 @@ struct arasan_sdhci_plat {
>  
>  struct arasan_sdhci_priv {
>  	struct sdhci_host *host;
> +	struct arasan_sdhci_clk_data clk_data;
>  	u8 deviceid;
>  	u8 bank;
>  	u8 no_1p8;
>  };
>  
>  #if defined(CONFIG_ARCH_ZYNQMP)
> +/* Default settings for ZynqMP Clock Phases */
> +const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63,  0,   0, 183, 54,  0, 0};
> +const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0};
> +
>  static const u8 mode2timing[] = {
>  	[MMC_LEGACY] = MMC_TIMING_LEGACY,
>  	[MMC_HS] = MMC_TIMING_MMC_HS,
> @@ -168,6 +179,79 @@ static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
>  					   priv->bank);
>  }
>  
> +static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
> +				     const char *prop)
> +{
> +	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
> +	struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
> +	u32 clk_phase[2] = {0};
> +
> +	/*
> +	 * Read Tap Delay values from DT, if the DT does not contain the
> +	 * Tap Values then use the pre-defined values
> +	 */
> +	if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) {
> +		dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
> +			prop, clk_data->clk_phase_in[timing],
> +			clk_data->clk_phase_out[timing]);
> +		return;
> +	}
> +
> +	/* The values read are Input and Output Clock Delays in order */
> +	clk_data->clk_phase_in[timing] = clk_phase[0];
> +	clk_data->clk_phase_out[timing] = clk_phase[1];
> +}
> +
> +/**
> + * arasan_dt_parse_clk_phases - Read Tap Delay values from DT
> + *
> + * Called at initialization to parse the values of Tap Delays.
> + *
> + * @dev:                Pointer to our struct udevice.
> + */
> +static void arasan_dt_parse_clk_phases(struct udevice *dev)
> +{
> +	struct arasan_sdhci_priv *priv = dev_get_priv(dev);
> +	struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
> +	int i;
> +
> +	if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
> +	    device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
> +		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
> +			clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i];
> +			clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i];
> +		}
> +
> +		if (priv->bank == MMC_BANK2) {
> +			clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90;
> +			clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90;
> +		}
> +	}
> +
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
> +				 "clk-phase-legacy");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
> +				 "clk-phase-mmc-hs");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS,
> +				 "clk-phase-sd-hs");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12,
> +				 "clk-phase-uhs-sdr12");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25,
> +				 "clk-phase-uhs-sdr25");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50,
> +				 "clk-phase-uhs-sdr50");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104,
> +				 "clk-phase-uhs-sdr104");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50,
> +				 "clk-phase-uhs-ddr50");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52,
> +				 "clk-phase-mmc-ddr52");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200,
> +				 "clk-phase-mmc-hs200");
> +	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400,
> +				 "clk-phase-mmc-hs400");
> +}
> +
>  static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
>  {
>  	struct mmc *mmc = (struct mmc *)host->mmc;
> @@ -271,6 +355,7 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
>  
>  #if defined(CONFIG_ARCH_ZYNQMP)
>  	priv->host->ops = &arasan_ops;
> +	arasan_dt_parse_clk_phases(dev);
>  #endif
>  
>  	priv->host->ioaddr = (void *)dev_read_addr(dev);
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 5/8] mmc: zynq_sdhci: Set tapdelays based on clk phase delays
  2020-10-26 11:42 ` [PATCH v3 5/8] mmc: zynq_sdhci: Set tapdelays based on clk phase delays Michal Simek
@ 2020-10-26 21:38   ` Jaehoon Chung
  0 siblings, 0 replies; 15+ messages in thread
From: Jaehoon Chung @ 2020-10-26 21:38 UTC (permalink / raw)
  To: u-boot

On 10/26/20 8:42 PM, Michal Simek wrote:
> From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
> 
> Define and use functions for setting input and output tapdelays
> based on clk phase delays.
> 
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> Reviewed-by: Peng Fan <peng.fan@nxp.com>

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

> 
> ---
> 
> Changes in v3:
>  - replace host->version by SDHCI_GET_VERSION(host) reported by Jaehoon
> 
>  drivers/mmc/zynq_sdhci.c | 128 +++++++++++++++++++++++++++++++++++++--
>  1 file changed, 123 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
> index e69f375cce07..8871765711d4 100644
> --- a/drivers/mmc/zynq_sdhci.c
> +++ b/drivers/mmc/zynq_sdhci.c
> @@ -166,17 +166,135 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
>  	return 0;
>  }
>  
> +/**
> + * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
> + *
> + * Set the SD Output Clock Tap Delays for Output path
> + *
> + * @host:		Pointer to the sdhci_host structure.
> + * @degrees:		The clock phase shift between 0 - 359.
> + * Return: 0 on success and error value on error
> + */
> +static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
> +					    int degrees)
> +{
> +	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
> +	struct mmc *mmc = (struct mmc *)host->mmc;
> +	u8 tap_delay, tap_max = 0;
> +	int ret;
> +	int timing = mode2timing[mmc->selected_mode];
> +
> +	/*
> +	 * This is applicable for SDHCI_SPEC_300 and above
> +	 * ZynqMP does not set phase for <=25MHz clock.
> +	 * If degrees is zero, no need to do anything.
> +	 */
> +	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
> +	    timing == MMC_TIMING_LEGACY ||
> +	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
> +		return 0;
> +
> +	switch (timing) {
> +	case MMC_TIMING_MMC_HS:
> +	case MMC_TIMING_SD_HS:
> +	case MMC_TIMING_UHS_SDR25:
> +	case MMC_TIMING_UHS_DDR50:
> +	case MMC_TIMING_MMC_DDR52:
> +		/* For 50MHz clock, 30 Taps are available */
> +		tap_max = 30;
> +		break;
> +	case MMC_TIMING_UHS_SDR50:
> +		/* For 100MHz clock, 15 Taps are available */
> +		tap_max = 15;
> +		break;
> +	case MMC_TIMING_UHS_SDR104:
> +	case MMC_TIMING_MMC_HS200:
> +		/* For 200MHz clock, 8 Taps are available */
> +		tap_max = 8;
> +	default:
> +		break;
> +	}
> +
> +	tap_delay = (degrees * tap_max) / 360;
> +
> +	arasan_zynqmp_set_tapdelay(priv->deviceid, 0, tap_delay);
> +
> +	return ret;
> +}
> +
> +/**
> + * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
> + *
> + * Set the SD Input Clock Tap Delays for Input path
> + *
> + * @host:		Pointer to the sdhci_host structure.
> + * @degrees:		The clock phase shift between 0 - 359.
> + * Return: 0 on success and error value on error
> + */
> +static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
> +					    int degrees)
> +{
> +	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
> +	struct mmc *mmc = (struct mmc *)host->mmc;
> +	u8 tap_delay, tap_max = 0;
> +	int ret;
> +	int timing = mode2timing[mmc->selected_mode];
> +
> +	/*
> +	 * This is applicable for SDHCI_SPEC_300 and above
> +	 * ZynqMP does not set phase for <=25MHz clock.
> +	 * If degrees is zero, no need to do anything.
> +	 */
> +	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
> +	    timing == MMC_TIMING_LEGACY ||
> +	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
> +		return 0;
> +
> +	switch (timing) {
> +	case MMC_TIMING_MMC_HS:
> +	case MMC_TIMING_SD_HS:
> +	case MMC_TIMING_UHS_SDR25:
> +	case MMC_TIMING_UHS_DDR50:
> +	case MMC_TIMING_MMC_DDR52:
> +		/* For 50MHz clock, 120 Taps are available */
> +		tap_max = 120;
> +		break;
> +	case MMC_TIMING_UHS_SDR50:
> +		/* For 100MHz clock, 60 Taps are available */
> +		tap_max = 60;
> +		break;
> +	case MMC_TIMING_UHS_SDR104:
> +	case MMC_TIMING_MMC_HS200:
> +		/* For 200MHz clock, 30 Taps are available */
> +		tap_max = 30;
> +	default:
> +		break;
> +	}
> +
> +	tap_delay = (degrees * tap_max) / 360;
> +
> +	arasan_zynqmp_set_tapdelay(priv->deviceid, tap_delay, 0);
> +
> +	return ret;
> +}
> +
>  static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
>  {
>  	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
> +	struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
>  	struct mmc *mmc = (struct mmc *)host->mmc;
> -	u8 uhsmode;
> +	struct udevice *dev = mmc->dev;
> +	u8 timing = mode2timing[mmc->selected_mode];
> +	u32 iclk_phase = clk_data->clk_phase_in[timing];
> +	u32 oclk_phase = clk_data->clk_phase_out[timing];
>  
> -	uhsmode = mode2timing[mmc->selected_mode];
> +	dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
>  
> -	if (uhsmode >= UHS_SDR25_BUS_SPEED)
> -		arasan_zynqmp_set_tapdelay(priv->deviceid, uhsmode,
> -					   priv->bank);
> +	if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
> +	    device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
> +		sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
> +		sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
> +	}
>  }
>  
>  static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 6/8] mmc: zynq_sdhci: Add clock phase delays for Versal
  2020-10-26 11:42 ` [PATCH v3 6/8] mmc: zynq_sdhci: Add clock phase delays for Versal Michal Simek
@ 2020-10-26 21:38   ` Jaehoon Chung
  0 siblings, 0 replies; 15+ messages in thread
From: Jaehoon Chung @ 2020-10-26 21:38 UTC (permalink / raw)
  To: u-boot

On 10/26/20 8:42 PM, Michal Simek wrote:
> From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
> 
> Define default values for input and output clock phase delays for
> Versal. Also define functions for setting tapdelays based on these
> clock phase delays.
> 
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> Reviewed-by: Peng Fan <peng.fan@nxp.com>

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

> ---
> 
> Changes in v3:
>  - replace host->version by SDHCI_GET_VERSION(host) reported by Jaehoon
> 
>  drivers/mmc/zynq_sdhci.c | 160 ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 156 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
> index 8871765711d4..d55ba74b2c38 100644
> --- a/drivers/mmc/zynq_sdhci.c
> +++ b/drivers/mmc/zynq_sdhci.c
> @@ -19,6 +19,12 @@
>  #include <sdhci.h>
>  #include <zynqmp_tap_delay.h>
>  
> +#define SDHCI_ARASAN_ITAPDLY_REGISTER   0xF0F8
> +#define SDHCI_ARASAN_OTAPDLY_REGISTER   0xF0FC
> +#define SDHCI_ITAPDLY_CHGWIN            0x200
> +#define SDHCI_ITAPDLY_ENABLE            0x100
> +#define SDHCI_OTAPDLY_ENABLE            0x40
> +
>  #define SDHCI_TUNING_LOOP_COUNT		40
>  #define MMC_BANK2			0x2
>  
> @@ -40,11 +46,15 @@ struct arasan_sdhci_priv {
>  	u8 no_1p8;
>  };
>  
> -#if defined(CONFIG_ARCH_ZYNQMP)
> +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
>  /* Default settings for ZynqMP Clock Phases */
>  const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63,  0,   0, 183, 54,  0, 0};
>  const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0};
>  
> +/* Default settings for Versal Clock Phases */
> +const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0};
> +const u32 versal_oclk_phases[] = {0,  60, 48, 0, 48, 72, 90, 36, 60, 90, 0};
> +
>  static const u8 mode2timing[] = {
>  	[MMC_LEGACY] = MMC_TIMING_LEGACY,
>  	[MMC_HS] = MMC_TIMING_MMC_HS,
> @@ -278,6 +288,138 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
>  	return ret;
>  }
>  
> +/**
> + * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
> + *
> + * Set the SD Output Clock Tap Delays for Output path
> + *
> + * @host:		Pointer to the sdhci_host structure.
> + * @degrees		The clock phase shift between 0 - 359.
> + * Return: 0 on success and error value on error
> + */
> +static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host,
> +					    int degrees)
> +{
> +	struct mmc *mmc = (struct mmc *)host->mmc;
> +	u8 tap_delay, tap_max = 0;
> +	int ret;
> +	int timing = mode2timing[mmc->selected_mode];
> +
> +	/*
> +	 * This is applicable for SDHCI_SPEC_300 and above
> +	 * Versal does not set phase for <=25MHz clock.
> +	 * If degrees is zero, no need to do anything.
> +	 */
> +	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
> +	    timing == MMC_TIMING_LEGACY ||
> +	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
> +		return 0;
> +
> +	switch (timing) {
> +	case MMC_TIMING_MMC_HS:
> +	case MMC_TIMING_SD_HS:
> +	case MMC_TIMING_UHS_SDR25:
> +	case MMC_TIMING_UHS_DDR50:
> +	case MMC_TIMING_MMC_DDR52:
> +		/* For 50MHz clock, 30 Taps are available */
> +		tap_max = 30;
> +		break;
> +	case MMC_TIMING_UHS_SDR50:
> +		/* For 100MHz clock, 15 Taps are available */
> +		tap_max = 15;
> +		break;
> +	case MMC_TIMING_UHS_SDR104:
> +	case MMC_TIMING_MMC_HS200:
> +		/* For 200MHz clock, 8 Taps are available */
> +		tap_max = 8;
> +	default:
> +		break;
> +	}
> +
> +	tap_delay = (degrees * tap_max) / 360;
> +
> +	/* Set the Clock Phase */
> +	if (tap_delay) {
> +		u32 regval;
> +
> +		regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
> +		regval |= SDHCI_OTAPDLY_ENABLE;
> +		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
> +		regval |= tap_delay;
> +		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
> + *
> + * Set the SD Input Clock Tap Delays for Input path
> + *
> + * @host:		Pointer to the sdhci_host structure.
> + * @degrees		The clock phase shift between 0 - 359.
> + * Return: 0 on success and error value on error
> + */
> +static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
> +					    int degrees)
> +{
> +	struct mmc *mmc = (struct mmc *)host->mmc;
> +	u8 tap_delay, tap_max = 0;
> +	int ret;
> +	int timing = mode2timing[mmc->selected_mode];
> +
> +	/*
> +	 * This is applicable for SDHCI_SPEC_300 and above
> +	 * Versal does not set phase for <=25MHz clock.
> +	 * If degrees is zero, no need to do anything.
> +	 */
> +	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300 ||
> +	    timing == MMC_TIMING_LEGACY ||
> +	    timing == MMC_TIMING_UHS_SDR12 || !degrees)
> +		return 0;
> +
> +	switch (timing) {
> +	case MMC_TIMING_MMC_HS:
> +	case MMC_TIMING_SD_HS:
> +	case MMC_TIMING_UHS_SDR25:
> +	case MMC_TIMING_UHS_DDR50:
> +	case MMC_TIMING_MMC_DDR52:
> +		/* For 50MHz clock, 120 Taps are available */
> +		tap_max = 120;
> +		break;
> +	case MMC_TIMING_UHS_SDR50:
> +		/* For 100MHz clock, 60 Taps are available */
> +		tap_max = 60;
> +		break;
> +	case MMC_TIMING_UHS_SDR104:
> +	case MMC_TIMING_MMC_HS200:
> +		/* For 200MHz clock, 30 Taps are available */
> +		tap_max = 30;
> +	default:
> +		break;
> +	}
> +
> +	tap_delay = (degrees * tap_max) / 360;
> +
> +	/* Set the Clock Phase */
> +	if (tap_delay) {
> +		u32 regval;
> +
> +		regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
> +		regval |= SDHCI_ITAPDLY_CHGWIN;
> +		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
> +		regval |= SDHCI_ITAPDLY_ENABLE;
> +		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
> +		regval |= tap_delay;
> +		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
> +		regval &= ~SDHCI_ITAPDLY_CHGWIN;
> +		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
> +	}
> +
> +	return ret;
> +}
> +
>  static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
>  {
>  	struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
> @@ -294,6 +436,10 @@ static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
>  	    device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
>  		sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
>  		sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
> +	} else if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
> +		   device_is_compatible(dev, "xlnx,versal-8.9a")) {
> +		sdhci_versal_sampleclk_set_phase(host, iclk_phase);
> +		sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
>  	}
>  }
>  
> @@ -346,6 +492,14 @@ static void arasan_dt_parse_clk_phases(struct udevice *dev)
>  		}
>  	}
>  
> +	if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
> +	    device_is_compatible(dev, "xlnx,versal-8.9a")) {
> +		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
> +			clk_data->clk_phase_in[i] = versal_iclk_phases[i];
> +			clk_data->clk_phase_out[i] = versal_oclk_phases[i];
> +		}
> +	}
> +
>  	arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
>  				 "clk-phase-legacy");
>  	arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
> @@ -388,9 +542,7 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
>  	    mmc->selected_mode <= UHS_DDR50)
>  		sdhci_set_uhs_timing(host);
>  }
> -#endif
>  
> -#if defined(CONFIG_ARCH_ZYNQMP)
>  const struct sdhci_ops arasan_ops = {
>  	.platform_execute_tuning = &arasan_sdhci_execute_tuning,
>  	.set_delay = &arasan_sdhci_set_tapdelay,
> @@ -471,7 +623,7 @@ static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev)
>  
>  	priv->host->name = dev->name;
>  
> -#if defined(CONFIG_ARCH_ZYNQMP)
> +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
>  	priv->host->ops = &arasan_ops;
>  	arasan_dt_parse_clk_phases(dev);
>  #endif
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 7/8] mmc: zynq_sdhci: Extend UHS timings till hs200
  2020-10-26 11:43 ` [PATCH v3 7/8] mmc: zynq_sdhci: Extend UHS timings till hs200 Michal Simek
@ 2020-10-26 21:39   ` Jaehoon Chung
  0 siblings, 0 replies; 15+ messages in thread
From: Jaehoon Chung @ 2020-10-26 21:39 UTC (permalink / raw)
  To: u-boot

On 10/26/20 8:43 PM, Michal Simek wrote:
> From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
> 
> Fix the condition to set UHS timings for speeds upto HS200.
> 
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> Reviewed-by: Peng Fan <peng.fan@nxp.com>

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

> ---
> 
> (no changes since v1)
> 
>  drivers/mmc/zynq_sdhci.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
> index d55ba74b2c38..147ecc0d708d 100644
> --- a/drivers/mmc/zynq_sdhci.c
> +++ b/drivers/mmc/zynq_sdhci.c
> @@ -539,7 +539,7 @@ static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
>  	}
>  
>  	if (mmc->selected_mode > SD_HS &&
> -	    mmc->selected_mode <= UHS_DDR50)
> +	    mmc->selected_mode <= MMC_HS_200)
>  		sdhci_set_uhs_timing(host);
>  }
>  
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay
  2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
                   ` (7 preceding siblings ...)
  2020-10-26 11:43 ` [PATCH v3 8/8] mmc: zynq_sdhci: Add common function to set input/output tapdelays Michal Simek
@ 2020-10-29  7:57 ` Michal Simek
  8 siblings, 0 replies; 15+ messages in thread
From: Michal Simek @ 2020-10-29  7:57 UTC (permalink / raw)
  To: u-boot

po 26. 10. 2020 v 12:43 odes?latel Michal Simek
<michal.simek@xilinx.com> napsal:
>
> Hi,
>
> this patchset adding support for Tap delay programming for ZynqMP and
> Versal.
> Based on mainline discussion also DT properties have been introduced which
> are documented here.
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/Documentation/devicetree/bindings/mmc/mmc-controller.yaml?h=v5.7-rc6&id=fec81c5bca2499b4a263667860018c2ce47f4f51
> The patchset is using these DT properties which are optional.
> Default values are also listed.
>
> The patchset is based on:
> https://lists.denx.de/pipermail/u-boot/2020-May/410326.html
>
> Also new code is adding checking for SOCs which are not needed at that time
> when patch is applied (For example "mmc: zynq_sdhci: Read clock phase
> delays from dt" and IS_ENABLED(CONFIG_ARCH_ZYNQMP)...
> But I kept it there for more cleaner patches built on the top.
>
> Thanks,
> Michal
>
>
> Changes in v3:
>  - replace host->version by SDHCI_GET_VERSION(host) reported by Jaehoon
>  - replace host->version by SDHCI_GET_VERSION(host) reported by Jaehoon
>
> Changes in v2:
>  - Timing macro's are common to all mmc drivers, hence remove zynq_sdhci
>    from subject and description.
>  - Add common function to set tapdelays based on the values read from DT
>  - Remove tapdelay settings based on speed
>
> Ashok Reddy Soma (6):
>   Revert "mmc: zynq: parse dt when probing"
>   mmc: Define timing macro's
>   mmc: zynq_sdhci: Set tapdelays based on clk phase delays
>   mmc: zynq_sdhci: Add clock phase delays for Versal
>   mmc: zynq_sdhci: Extend UHS timings till hs200
>   mmc: zynq_sdhci: Add common function to set input/output tapdelays
>
> Michal Simek (2):
>   mmc: zynq_sdhci: Move macro to the top
>   mmc: zynq_sdhci: Read clock phase delays from dt
>
>  board/xilinx/zynqmp/tap_delays.c | 199 +++------------
>  drivers/mmc/sdhci.c              |   3 +-
>  drivers/mmc/zynq_sdhci.c         | 406 +++++++++++++++++++++++++++++--
>  include/mmc.h                    |  13 +
>  include/sdhci.h                  |   1 +
>  include/zynqmp_tap_delay.h       |   5 +-
>  6 files changed, 434 insertions(+), 193 deletions(-)
>
> --
> 2.28.0
>

The whole series is acked.
Applied to my tree.

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-10-29  7:57 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-26 11:42 [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek
2020-10-26 11:42 ` [PATCH v3 1/8] Revert "mmc: zynq: parse dt when probing" Michal Simek
2020-10-26 11:42 ` [PATCH v3 2/8] mmc: Define timing macro's Michal Simek
2020-10-26 11:42 ` [PATCH v3 3/8] mmc: zynq_sdhci: Move macro to the top Michal Simek
2020-10-26 21:38   ` Jaehoon Chung
2020-10-26 11:42 ` [PATCH v3 4/8] mmc: zynq_sdhci: Read clock phase delays from dt Michal Simek
2020-10-26 21:38   ` Jaehoon Chung
2020-10-26 11:42 ` [PATCH v3 5/8] mmc: zynq_sdhci: Set tapdelays based on clk phase delays Michal Simek
2020-10-26 21:38   ` Jaehoon Chung
2020-10-26 11:42 ` [PATCH v3 6/8] mmc: zynq_sdhci: Add clock phase delays for Versal Michal Simek
2020-10-26 21:38   ` Jaehoon Chung
2020-10-26 11:43 ` [PATCH v3 7/8] mmc: zynq_sdhci: Extend UHS timings till hs200 Michal Simek
2020-10-26 21:39   ` Jaehoon Chung
2020-10-26 11:43 ` [PATCH v3 8/8] mmc: zynq_sdhci: Add common function to set input/output tapdelays Michal Simek
2020-10-29  7:57 ` [PATCH v3 0/8] mmc: zynqmp_sdhci: Add support for Tap delay Michal Simek

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.