All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] Arasan sdhci driver updates
@ 2021-07-30 12:28 Ashok Reddy Soma
  2021-07-30 12:28 ` [PATCH v3 1/7] mmc: zynq_sdhci: Return errors from arasan_sdhci_set_tapdelay Ashok Reddy Soma
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Ashok Reddy Soma @ 2021-07-30 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: peng.fan, jh80.chung, faiz_abbas, sjg, michael, git, monstr,
	somaashokreddy, Ashok Reddy Soma

This patch series updates/fixes below things:
 - Handle errors from tapdelay functions and return to set_delay()
 - Add ZynqMP firmware related enums which are used in sdhci driver
 - Replace mmio_write() with firmware call xilinx_pm_request()
 - Move tapdelay setting code from tap_delays.c to driver and remove
   tap_dealy.c and zynqmp_tap_delay.h
 - Change variable name from deviceid to node_id in couple of functions
   for consistancy
 - Add a workaround for sd card detect stable issue for Versal platforms
 - Use set_control_reg from sdhci.c

These patches are based on below microblaze U-Boot 'next' branch.
https://source.denx.de/u-boot/custodians/u-boot-microblaze/-/commits/next

Changes in v3:
 - Added new line after return at two places
 - As we are seeing issues with SPL flow, keep zynqmp_mmio_write method
   to set tapdelay's and DLL resets. Add xilinx_pm_request on top of it
   for regular flow.
 - Changed the patch title to reflect these changes
 - Make the changes on top of patch 4/7 to move the code to zynq_sdhci.c

Changes in v2:
 - Split patch 1/7 to two patches, one for zynq_sdhci and other one
   for sdhci
 - This is the second patch that has been split from 1/7
 - This covers changes for sdhci driver separately
 - Added a debug print in case of error from set_delay()
 - Added comment for why 1ms delay is needed between DLL assert and
 release
 - Remove mmc->dev->seq_ and use priv->deviceid instead
 - Changed return error from -EIO to -ETIMEDOUT in arasan_sdhci_probe()
   in card detect state stable workaround

Ashok Reddy Soma (5):
  mmc: zynq_sdhci: Return errors from arasan_sdhci_set_tapdelay
  mmc: sdhci: Change prototype of set_delay to return errors
  mmc: zynq_sdhci: Add xilinx_pm_request() method to set tapdelays
  mmc: zynq_sdhci: Move setting tapdelay code to driver
  mmc: zynq_sdhci: Use set_control_reg from sdhci.c

T Karthik Reddy (2):
  zynqmp_firmware: Add zynqmp firmware related enums
  mmc: zynq_sdhci: Wait till sd card detect state is stable

 board/xilinx/zynqmp/Makefile     |   2 -
 board/xilinx/zynqmp/tap_delays.c | 101 -------------
 drivers/mmc/sdhci.c              |  10 +-
 drivers/mmc/zynq_sdhci.c         | 242 ++++++++++++++++++++++++++-----
 include/sdhci.h                  |   2 +-
 include/zynqmp_firmware.h        | 127 ++++++++++++++++
 include/zynqmp_tap_delay.h       |  21 ---
 7 files changed, 338 insertions(+), 167 deletions(-)
 delete mode 100644 board/xilinx/zynqmp/tap_delays.c
 delete mode 100644 include/zynqmp_tap_delay.h

-- 
2.17.1


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

* [PATCH v3 1/7] mmc: zynq_sdhci: Return errors from arasan_sdhci_set_tapdelay
  2021-07-30 12:28 [PATCH v3 0/7] Arasan sdhci driver updates Ashok Reddy Soma
@ 2021-07-30 12:28 ` Ashok Reddy Soma
  2021-08-01 23:08   ` Jaehoon Chung
  2021-07-30 12:28 ` [PATCH v3 2/7] mmc: sdhci: Change prototype of set_delay to return errors Ashok Reddy Soma
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 10+ messages in thread
From: Ashok Reddy Soma @ 2021-07-30 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: peng.fan, jh80.chung, faiz_abbas, sjg, michael, git, monstr,
	somaashokreddy, Ashok Reddy Soma, T Karthik Reddy

Change return type of arasan_sdhci_set_tapdelay() to int, to facilitate
returning errors. Get return values from input and output set clock phase
functions inside arasan_sdhci_set_tapdelay() and return those errors.

Signed-off-by: T Karthik Reddy <t.karthik.reddy@xilinx.com>
Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
---

Changes in v3:
 - Added new line after return at two places

Changes in v2:
 - Split patch 1/7 to two patches, one for zynq_sdhci and other one
   for sdhci

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

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index ba87ee8dd5..1ecc2ec669 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -422,7 +422,7 @@ static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
 	return 0;
 }
 
-static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
+static int 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;
@@ -431,18 +431,31 @@ static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
 	u8 timing = mode2timing[mmc->selected_mode];
 	u32 iclk_phase = clk_data->clk_phase_in[timing];
 	u32 oclk_phase = clk_data->clk_phase_out[timing];
+	int ret;
 
 	dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
 
 	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);
+		ret = sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
+		if (ret)
+			return ret;
+
+		ret = sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
+		if (ret)
+			return ret;
 	} 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);
+		ret = sdhci_versal_sampleclk_set_phase(host, iclk_phase);
+		if (ret)
+			return ret;
+
+		ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
+		if (ret)
+			return ret;
 	}
+
+	return 0;
 }
 
 static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
-- 
2.17.1


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

* [PATCH v3 2/7] mmc: sdhci: Change prototype of set_delay to return errors
  2021-07-30 12:28 [PATCH v3 0/7] Arasan sdhci driver updates Ashok Reddy Soma
  2021-07-30 12:28 ` [PATCH v3 1/7] mmc: zynq_sdhci: Return errors from arasan_sdhci_set_tapdelay Ashok Reddy Soma
@ 2021-07-30 12:28 ` Ashok Reddy Soma
  2021-08-01 23:09   ` Jaehoon Chung
  2021-07-30 12:28 ` [PATCH v3 3/7] zynqmp_firmware: Add zynqmp firmware related enums Ashok Reddy Soma
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 10+ messages in thread
From: Ashok Reddy Soma @ 2021-07-30 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: peng.fan, jh80.chung, faiz_abbas, sjg, michael, git, monstr,
	somaashokreddy, Ashok Reddy Soma

set_delay() has return type as void. If there are any errors while
setting tapdelay's it won't be able to return them.

Change the prototype of set_delay() in sdhci_ops structure and return
the errors from wherever it is called.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
---

(no changes since v2)

Changes in v2:
 - This is the second patch that has been split from 1/7
 - This covers changes for sdhci driver separately
 - Added a debug print in case of error from set_delay()

 drivers/mmc/sdhci.c | 10 ++++++++--
 include/sdhci.h     |  2 +-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index d9ab6a0a83..a99014236a 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -366,6 +366,7 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 {
 	struct sdhci_host *host = mmc->priv;
 	unsigned int div, clk = 0, timeout;
+	int ret;
 
 	/* Wait max 20 ms */
 	timeout = 200;
@@ -386,8 +387,13 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 	if (clock == 0)
 		return 0;
 
-	if (host->ops && host->ops->set_delay)
-		host->ops->set_delay(host);
+	if (host->ops && host->ops->set_delay) {
+		ret = host->ops->set_delay(host);
+		if (ret) {
+			printf("%s: Error while setting tap delay\n", __func__);
+			return ret;
+		}
+	}
 
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
 		/*
diff --git a/include/sdhci.h b/include/sdhci.h
index 0ae9471ad7..44a0d84e5a 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -268,7 +268,7 @@ struct sdhci_ops {
 	int	(*set_ios_post)(struct sdhci_host *host);
 	void	(*set_clock)(struct sdhci_host *host, u32 div);
 	int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
-	void (*set_delay)(struct sdhci_host *host);
+	int (*set_delay)(struct sdhci_host *host);
 	int	(*deferred_probe)(struct sdhci_host *host);
 };
 
-- 
2.17.1


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

* [PATCH v3 3/7] zynqmp_firmware: Add zynqmp firmware related enums
  2021-07-30 12:28 [PATCH v3 0/7] Arasan sdhci driver updates Ashok Reddy Soma
  2021-07-30 12:28 ` [PATCH v3 1/7] mmc: zynq_sdhci: Return errors from arasan_sdhci_set_tapdelay Ashok Reddy Soma
  2021-07-30 12:28 ` [PATCH v3 2/7] mmc: sdhci: Change prototype of set_delay to return errors Ashok Reddy Soma
@ 2021-07-30 12:28 ` Ashok Reddy Soma
  2021-07-30 12:28 ` [PATCH v3 4/7] mmc: zynq_sdhci: Add xilinx_pm_request() method to set tapdelays Ashok Reddy Soma
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Ashok Reddy Soma @ 2021-07-30 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: peng.fan, jh80.chung, faiz_abbas, sjg, michael, git, monstr,
	somaashokreddy, T Karthik Reddy, Ashok Reddy Soma

From: T Karthik Reddy <t.karthik.reddy@xilinx.com>

Add enums for pm node id's, pm ioctl id's, tapdelay types, dll reset types

Signed-off-by: T Karthik Reddy <t.karthik.reddy@xilinx.com>
Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
---

(no changes since v1)

 include/zynqmp_firmware.h | 127 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
index f6f82bf882..c559ee7d3c 100644
--- a/include/zynqmp_firmware.h
+++ b/include/zynqmp_firmware.h
@@ -62,6 +62,99 @@ enum pm_api_id {
 	PM_API_MAX,
 };
 
+enum pm_node_id {
+	NODE_UNKNOWN = 0,
+	NODE_APU = 1,
+	NODE_APU_0 = 2,
+	NODE_APU_1 = 3,
+	NODE_APU_2 = 4,
+	NODE_APU_3 = 5,
+	NODE_RPU = 6,
+	NODE_RPU_0 = 7,
+	NODE_RPU_1 = 8,
+	NODE_PLD = 9,
+	NODE_FPD = 10,
+	NODE_OCM_BANK_0 = 11,
+	NODE_OCM_BANK_1 = 12,
+	NODE_OCM_BANK_2 = 13,
+	NODE_OCM_BANK_3 = 14,
+	NODE_TCM_0_A = 15,
+	NODE_TCM_0_B = 16,
+	NODE_TCM_1_A = 17,
+	NODE_TCM_1_B = 18,
+	NODE_L2 = 19,
+	NODE_GPU_PP_0 = 20,
+	NODE_GPU_PP_1 = 21,
+	NODE_USB_0 = 22,
+	NODE_USB_1 = 23,
+	NODE_TTC_0 = 24,
+	NODE_TTC_1 = 25,
+	NODE_TTC_2 = 26,
+	NODE_TTC_3 = 27,
+	NODE_SATA = 28,
+	NODE_ETH_0 = 29,
+	NODE_ETH_1 = 30,
+	NODE_ETH_2 = 31,
+	NODE_ETH_3 = 32,
+	NODE_UART_0 = 33,
+	NODE_UART_1 = 34,
+	NODE_SPI_0 = 35,
+	NODE_SPI_1 = 36,
+	NODE_I2C_0 = 37,
+	NODE_I2C_1 = 38,
+	NODE_SD_0 = 39,
+	NODE_SD_1 = 40,
+	NODE_DP = 41,
+	NODE_GDMA = 42,
+	NODE_ADMA = 43,
+	NODE_NAND = 44,
+	NODE_QSPI = 45,
+	NODE_GPIO = 46,
+	NODE_CAN_0 = 47,
+	NODE_CAN_1 = 48,
+	NODE_EXTERN = 49,
+	NODE_APLL = 50,
+	NODE_VPLL = 51,
+	NODE_DPLL = 52,
+	NODE_RPLL = 53,
+	NODE_IOPLL = 54,
+	NODE_DDR = 55,
+	NODE_IPI_APU = 56,
+	NODE_IPI_RPU_0 = 57,
+	NODE_GPU = 58,
+	NODE_PCIE = 59,
+	NODE_PCAP = 60,
+	NODE_RTC = 61,
+	NODE_LPD = 62,
+	NODE_VCU = 63,
+	NODE_IPI_RPU_1 = 64,
+	NODE_IPI_PL_0 = 65,
+	NODE_IPI_PL_1 = 66,
+	NODE_IPI_PL_2 = 67,
+	NODE_IPI_PL_3 = 68,
+	NODE_PL = 69,
+	NODE_GEM_TSU = 70,
+	NODE_SWDT_0 = 71,
+	NODE_SWDT_1 = 72,
+	NODE_CSU = 73,
+	NODE_PJTAG = 74,
+	NODE_TRACE = 75,
+	NODE_TESTSCAN = 76,
+	NODE_PMU = 77,
+	NODE_MAX = 78,
+};
+
+enum tap_delay_type {
+	PM_TAPDELAY_INPUT = 0,
+	PM_TAPDELAY_OUTPUT = 1,
+};
+
+enum dll_reset_type {
+	PM_DLL_RESET_ASSERT = 0,
+	PM_DLL_RESET_RELEASE = 1,
+	PM_DLL_RESET_PULSE = 2,
+};
+
 enum pm_query_id {
 	PM_QID_INVALID = 0,
 	PM_QID_CLOCK_GET_NAME = 1,
@@ -79,6 +172,40 @@ enum pm_query_id {
 	PM_QID_CLOCK_GET_MAX_DIVISOR = 13,
 };
 
+enum pm_ioctl_id {
+	IOCTL_GET_RPU_OPER_MODE,
+	IOCTL_SET_RPU_OPER_MODE,
+	IOCTL_RPU_BOOT_ADDR_CONFIG,
+	IOCTL_TCM_COMB_CONFIG,
+	IOCTL_SET_TAPDELAY_BYPASS,
+	IOCTL_SET_SGMII_MODE,
+	IOCTL_SD_DLL_RESET,
+	IOCTL_SET_SD_TAPDELAY,
+	IOCTL_SET_PLL_FRAC_MODE,
+	IOCTL_GET_PLL_FRAC_MODE,
+	IOCTL_SET_PLL_FRAC_DATA,
+	IOCTL_GET_PLL_FRAC_DATA,
+	IOCTL_WRITE_GGS,
+	IOCTL_READ_GGS,
+	IOCTL_WRITE_PGGS,
+	IOCTL_READ_PGGS,
+	/* IOCTL for ULPI reset */
+	IOCTL_ULPI_RESET,
+	/* Set healthy bit value*/
+	IOCTL_SET_BOOT_HEALTH_STATUS,
+	IOCTL_AFI,
+	/* Probe counter read/write */
+	IOCTL_PROBE_COUNTER_READ,
+	IOCTL_PROBE_COUNTER_WRITE,
+	IOCTL_OSPI_MUX_SELECT,
+	/* IOCTL for USB power request */
+	IOCTL_USB_SET_STATE,
+	/* IOCTL to get last reset reason */
+	IOCTL_GET_LAST_RESET_REASON,
+	/* AIE ISR Clear */
+	IOCTL_AIE_ISR_CLEAR,
+};
+
 #define PM_SIP_SVC      0xc2000000
 
 #define ZYNQMP_PM_VERSION_MAJOR         1
-- 
2.17.1


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

* [PATCH v3 4/7] mmc: zynq_sdhci: Add xilinx_pm_request() method to set tapdelays
  2021-07-30 12:28 [PATCH v3 0/7] Arasan sdhci driver updates Ashok Reddy Soma
                   ` (2 preceding siblings ...)
  2021-07-30 12:28 ` [PATCH v3 3/7] zynqmp_firmware: Add zynqmp firmware related enums Ashok Reddy Soma
@ 2021-07-30 12:28 ` Ashok Reddy Soma
  2021-07-30 12:28 ` [PATCH v3 5/7] mmc: zynq_sdhci: Move setting tapdelay code to driver Ashok Reddy Soma
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Ashok Reddy Soma @ 2021-07-30 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: peng.fan, jh80.chung, faiz_abbas, sjg, michael, git, monstr,
	somaashokreddy, Ashok Reddy Soma, T Karthik Reddy

Currently xilinx sdhci driver is using zynqmp_mmio_write() to set
tapdelay values and DLL resets. Continue to use this for SPL and mini
U-Boot where U-Boot will be executed at EL3 level.

Use firmware call xilinx_pm_request() using appropriate arguments to
set input/output tapdelays and also for DLL resets in regular flow(EL2).

Host driver should explicitly request DLL reset before ITAP (assert DLL)
and after OTAP (release DLL) to avoid issues in some cases. Also handle
error return where possible.

Signed-off-by: T Karthik Reddy <t.karthik.reddy@xilinx.com>
Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
---

Changes in v3:
 - As we are seeing issues with SPL flow, keep zynqmp_mmio_write method
   to set tapdelay's and DLL resets. Add xilinx_pm_request on top of it
   for regular flow.
 - Changed the patch title to reflect these changes

Changes in v2:
 - Added comment for why 1ms delay is needed between DLL assert and
 release
 - Remove mmc->dev->seq_ and use priv->deviceid instead

 board/xilinx/zynqmp/tap_delays.c | 148 +++++++++++++++++--------------
 drivers/mmc/zynq_sdhci.c         |  73 ++++++++++++---
 include/zynqmp_tap_delay.h       |  25 ++++--
 3 files changed, 159 insertions(+), 87 deletions(-)

diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
index d16bbb8eff..514f86a29a 100644
--- a/board/xilinx/zynqmp/tap_delays.c
+++ b/board/xilinx/zynqmp/tap_delays.c
@@ -8,94 +8,108 @@
 #include <common.h>
 #include <zynqmp_tap_delay.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/cache.h>
 #include <linux/delay.h>
 #include <mmc.h>
+#include <zynqmp_firmware.h>
 
 #define SD_DLL_CTRL			0xFF180358
 #define SD_ITAP_DLY			0xFF180314
 #define SD_OTAP_DLY			0xFF180318
-#define SD0_DLL_RST_MASK		0x00000004
-#define SD0_DLL_RST			0x00000004
-#define SD1_DLL_RST_MASK		0x00040000
-#define SD1_DLL_RST			0x00040000
-#define SD0_ITAPCHGWIN_MASK		0x00000200
-#define SD0_ITAPCHGWIN			0x00000200
-#define SD1_ITAPCHGWIN_MASK		0x02000000
-#define SD1_ITAPCHGWIN			0x02000000
-#define SD0_ITAPDLYENA_MASK		0x00000100
-#define SD0_ITAPDLYENA			0x00000100
-#define SD1_ITAPDLYENA_MASK		0x01000000
-#define SD1_ITAPDLYENA			0x01000000
-#define SD0_ITAPDLYSEL_MASK		0x000000FF
-#define SD1_ITAPDLYSEL_MASK		0x00FF0000
-#define SD0_OTAPDLYSEL_MASK		0x0000003F
-#define SD1_OTAPDLYSEL_MASK		0x003F0000
+#define SD0_DLL_RST			BIT(2)
+#define SD1_DLL_RST			BIT(18)
+#define SD0_ITAPCHGWIN			BIT(9)
+#define SD1_ITAPCHGWIN			BIT(25)
+#define SD0_ITAPDLYENA			BIT(8)
+#define SD1_ITAPDLYENA			BIT(24)
+#define SD0_ITAPDLYSEL_MASK		GENMASK(7, 0)
+#define SD1_ITAPDLYSEL_MASK		GENMASK(23, 16)
+#define SD0_OTAPDLYSEL_MASK		GENMASK(5, 0)
+#define SD1_OTAPDLYSEL_MASK		GENMASK(21, 16)
 
-void zynqmp_dll_reset(u8 deviceid)
+int zynqmp_dll_reset(u8 node_id, u32 type)
 {
-	/* Issue DLL Reset */
-	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);
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		if (node_id == NODE_SD_0)
+			return zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST,
+						 type == PM_DLL_RESET_ASSERT ?
+						 SD0_DLL_RST : 0);
 
-	mdelay(1);
-
-	/* Release DLL Reset */
-	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);
+		return zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST,
+					 type == PM_DLL_RESET_ASSERT ?
+					 SD1_DLL_RST : 0);
+	} else {
+		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+					 IOCTL_SD_DLL_RESET, type, 0, NULL);
+	}
 }
 
-void arasan_zynqmp_set_in_tapdelay(u8 deviceid, u32 itap_delay)
+int arasan_zynqmp_set_in_tapdelay(u8 node_id, u32 itap_delay)
 {
-	if (deviceid == 0) {
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, SD0_DLL_RST);
+	int ret;
 
-		/* Program 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, itap_delay);
-		zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN_MASK, 0x0);
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		if (node_id == NODE_SD_0) {
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN,
+						SD0_ITAPCHGWIN);
+			if (ret)
+				return ret;
 
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
-	} else {
-		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, SD1_DLL_RST);
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA,
+						SD0_ITAPDLYENA);
+			if (ret)
+				return ret;
 
-		/* Program 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);
+			ret = zynqmp_mmio_write(SD_ITAP_DLY,
+						SD0_ITAPDLYSEL_MASK,
+						itap_delay);
+			if (ret)
+				return ret;
 
-		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
-	}
-}
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, 0);
+			if (ret)
+				return ret;
+		}
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN,
+					SD1_ITAPCHGWIN);
+		if (ret)
+			return ret;
 
-void arasan_zynqmp_set_out_tapdelay(u8 deviceid, u32 otap_delay)
-{
-	if (deviceid == 0) {
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, SD0_DLL_RST);
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA,
+					SD1_ITAPDLYENA);
+		if (ret)
+			return ret;
 
-		/* Program OTAP delay */
-		zynqmp_mmio_write(SD_OTAP_DLY, SD0_OTAPDLYSEL_MASK, otap_delay);
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+					(itap_delay << 16));
+		if (ret)
+			return ret;
 
-		zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST_MASK, 0x0);
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0);
+		if (ret)
+			return ret;
 	} else {
-		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, SD1_DLL_RST);
+		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+					 IOCTL_SET_SD_TAPDELAY,
+					 PM_TAPDELAY_INPUT, itap_delay, NULL);
+	}
+
+	return 0;
+}
 
-		/* Program OTAP delay */
-		zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-				  (otap_delay << 16));
+int arasan_zynqmp_set_out_tapdelay(u8 node_id, u32 otap_delay)
+{
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		if (node_id == NODE_SD_0)
+			return zynqmp_mmio_write(SD_OTAP_DLY,
+						 SD0_OTAPDLYSEL_MASK,
+						 otap_delay);
 
-		zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST_MASK, 0x0);
+		return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					 (otap_delay << 16));
+	} else {
+		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+					 IOCTL_SET_SD_TAPDELAY,
+					 PM_TAPDELAY_OUTPUT, otap_delay, NULL);
 	}
 }
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 1ecc2ec669..8397f24255 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -18,6 +18,7 @@
 #include <malloc.h>
 #include <sdhci.h>
 #include <zynqmp_tap_delay.h>
+#include <zynqmp_firmware.h>
 
 #define SDHCI_ARASAN_ITAPDLY_REGISTER	0xF0F8
 #define SDHCI_ARASAN_ITAPDLY_SEL_MASK	GENMASK(7, 0)
@@ -75,26 +76,40 @@ static const u8 mode2timing[] = {
 	[MMC_HS_200] = MMC_TIMING_MMC_HS200,
 };
 
-static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
+static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 node_id)
 {
-	u16 clk;
+	struct mmc *mmc = (struct mmc *)host->mmc;
+	struct udevice *dev = mmc->dev;
 	unsigned long timeout;
+	int ret;
+	u16 clk;
 
 	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
 	clk &= ~(SDHCI_CLOCK_CARD_EN);
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 
 	/* Issue DLL Reset */
-	zynqmp_dll_reset(deviceid);
+	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
+	if (ret) {
+		dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
+		return ret;
+	}
+
+	/* Allow atleast 1ms delay for proper DLL reset */
+	mdelay(1);
+	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
+	if (ret) {
+		dev_err(dev, "dll_reset release failed with err: %d\n", ret);
+		return ret;
+	}
 
 	/* Wait max 20 ms */
 	timeout = 100;
 	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
 				& SDHCI_CLOCK_INT_STABLE)) {
 		if (timeout == 0) {
-			dev_err(mmc_dev(host->mmc),
-				": Internal clock never stabilised.\n");
-			return;
+			dev_err(dev, ": Internal clock never stabilised.\n");
+			return -EBUSY;
 		}
 		timeout--;
 		udelay(1000);
@@ -102,6 +117,8 @@ static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
 
 	clk |= SDHCI_CLOCK_CARD_EN;
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	return 0;
 }
 
 static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
@@ -112,12 +129,11 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 	struct sdhci_host *host;
 	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
 	char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
-	u8 deviceid;
+	u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 
 	debug("%s\n", __func__);
 
 	host = priv->host;
-	deviceid = priv->deviceid;
 
 	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 	ctrl |= SDHCI_CTRL_EXEC_TUNING;
@@ -125,7 +141,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 
 	mdelay(1);
 
-	arasan_zynqmp_dll_reset(host, deviceid);
+	arasan_zynqmp_dll_reset(host, node_id);
 
 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
 	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
@@ -171,7 +187,7 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 	}
 
 	udelay(1);
-	arasan_zynqmp_dll_reset(host, deviceid);
+	arasan_zynqmp_dll_reset(host, node_id);
 
 	/* Enable only interrupts served by the SD controller */
 	sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
@@ -194,10 +210,13 @@ static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
 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;
+	struct udevice *dev = mmc->dev;
+	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
+	u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 	u8 tap_delay, tap_max = 0;
 	int timing = mode2timing[mmc->selected_mode];
+	int ret;
 
 	/*
 	 * This is applicable for SDHCI_SPEC_300 and above
@@ -233,7 +252,19 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
 	/* Limit output tap_delay value to 6 bits */
 	tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
 
-	arasan_zynqmp_set_out_tapdelay(priv->deviceid, tap_delay);
+	/* Set the Clock Phase */
+	ret = arasan_zynqmp_set_out_tapdelay(node_id, tap_delay);
+	if (ret) {
+		dev_err(dev, "Error setting output Tap Delay\n");
+		return ret;
+	}
+
+	/* Release DLL Reset */
+	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
+	if (ret) {
+		dev_err(dev, "dll_reset release failed with err: %d\n", ret);
+		return ret;
+	}
 
 	return 0;
 }
@@ -250,10 +281,13 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
 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;
+	struct udevice *dev = mmc->dev;
+	struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
+	u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
 	u8 tap_delay, tap_max = 0;
 	int timing = mode2timing[mmc->selected_mode];
+	int ret;
 
 	/*
 	 * This is applicable for SDHCI_SPEC_300 and above
@@ -263,6 +297,13 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
 	if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
 		return 0;
 
+	/* Assert DLL Reset */
+	ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
+	if (ret) {
+		dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
+		return ret;
+	}
+
 	switch (timing) {
 	case MMC_TIMING_MMC_HS:
 	case MMC_TIMING_SD_HS:
@@ -289,7 +330,11 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
 	/* Limit input tap_delay value to 8 bits */
 	tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
 
-	arasan_zynqmp_set_in_tapdelay(priv->deviceid, tap_delay);
+	ret = arasan_zynqmp_set_in_tapdelay(node_id, tap_delay);
+	if (ret) {
+		dev_err(dev, "Error setting Input Tap Delay\n");
+		return ret;
+	}
 
 	return 0;
 }
diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h
index 1c1e3e7dee..7ef172f0fa 100644
--- a/include/zynqmp_tap_delay.h
+++ b/include/zynqmp_tap_delay.h
@@ -8,14 +8,27 @@
 #ifndef __ZYNQMP_TAP_DELAY_H__
 #define __ZYNQMP_TAP_DELAY_H__
 
+#include <zynqmp_firmware.h>
+
 #ifdef CONFIG_ARCH_ZYNQMP
-void zynqmp_dll_reset(u8 deviceid);
-void arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay);
-void arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay);
+int zynqmp_dll_reset(u8 node_id, u32 type);
+int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay);
+int arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay);
 #else
-inline void zynqmp_dll_reset(u8 deviceid) {}
-inline void arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay) {}
-inline void arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay) {}
+inline int zynqmp_dll_reset(u8 deviceid, u32 type)
+{
+	return 0;
+}
+
+inline int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay)
+{
+	return 0;
+}
+
+inline int arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay)
+{
+	return 0;
+}
 #endif
 
 #endif
-- 
2.17.1


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

* [PATCH v3 5/7] mmc: zynq_sdhci: Move setting tapdelay code to driver
  2021-07-30 12:28 [PATCH v3 0/7] Arasan sdhci driver updates Ashok Reddy Soma
                   ` (3 preceding siblings ...)
  2021-07-30 12:28 ` [PATCH v3 4/7] mmc: zynq_sdhci: Add xilinx_pm_request() method to set tapdelays Ashok Reddy Soma
@ 2021-07-30 12:28 ` Ashok Reddy Soma
  2021-07-30 12:28 ` [PATCH v3 6/7] mmc: zynq_sdhci: Wait till sd card detect state is stable Ashok Reddy Soma
  2021-07-30 12:28 ` [PATCH v3 7/7] mmc: zynq_sdhci: Use set_control_reg from sdhci.c Ashok Reddy Soma
  6 siblings, 0 replies; 10+ messages in thread
From: Ashok Reddy Soma @ 2021-07-30 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: peng.fan, jh80.chung, faiz_abbas, sjg, michael, git, monstr,
	somaashokreddy, Ashok Reddy Soma

Move tapdelay function calls to zynq_sdhci.c and make them static
inline. zynqmp_tap_delay.h has function prototypes for the functions
defined in tap_delays.c, which will not be needed anymore.

Remove tap_delays.c and zynqmp_tap_delay.h files.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
---

Changes in v3:
 - Make the changes on top of patch 4/7 to move the code to zynq_sdhci.c

 board/xilinx/zynqmp/Makefile     |   2 -
 board/xilinx/zynqmp/tap_delays.c | 115 -------------------------------
 drivers/mmc/zynq_sdhci.c         | 108 ++++++++++++++++++++++++++++-
 include/zynqmp_tap_delay.h       |  34 ---------
 4 files changed, 107 insertions(+), 152 deletions(-)
 delete mode 100644 board/xilinx/zynqmp/tap_delays.c
 delete mode 100644 include/zynqmp_tap_delay.h

diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile
index 7d8277ca40..a914028753 100644
--- a/board/xilinx/zynqmp/Makefile
+++ b/board/xilinx/zynqmp/Makefile
@@ -44,8 +44,6 @@ $(obj)/pm_cfg_obj.o: $(shell cd $(srctree); readlink -f $(CONFIG_ZYNQMP_SPL_PM_C
 endif
 endif
 
-obj-$(CONFIG_MMC_SDHCI_ZYNQ) += tap_delays.o
-
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_ZYNQMP) += cmds.o
 endif
diff --git a/board/xilinx/zynqmp/tap_delays.c b/board/xilinx/zynqmp/tap_delays.c
deleted file mode 100644
index 514f86a29a..0000000000
--- a/board/xilinx/zynqmp/tap_delays.c
+++ /dev/null
@@ -1,115 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Xilinx ZynqMP SoC Tap Delay Programming
- *
- * Copyright (C) 2018 Xilinx, Inc.
- */
-
-#include <common.h>
-#include <zynqmp_tap_delay.h>
-#include <asm/arch/sys_proto.h>
-#include <asm/cache.h>
-#include <linux/delay.h>
-#include <mmc.h>
-#include <zynqmp_firmware.h>
-
-#define SD_DLL_CTRL			0xFF180358
-#define SD_ITAP_DLY			0xFF180314
-#define SD_OTAP_DLY			0xFF180318
-#define SD0_DLL_RST			BIT(2)
-#define SD1_DLL_RST			BIT(18)
-#define SD0_ITAPCHGWIN			BIT(9)
-#define SD1_ITAPCHGWIN			BIT(25)
-#define SD0_ITAPDLYENA			BIT(8)
-#define SD1_ITAPDLYENA			BIT(24)
-#define SD0_ITAPDLYSEL_MASK		GENMASK(7, 0)
-#define SD1_ITAPDLYSEL_MASK		GENMASK(23, 16)
-#define SD0_OTAPDLYSEL_MASK		GENMASK(5, 0)
-#define SD1_OTAPDLYSEL_MASK		GENMASK(21, 16)
-
-int zynqmp_dll_reset(u8 node_id, u32 type)
-{
-	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
-		if (node_id == NODE_SD_0)
-			return zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST,
-						 type == PM_DLL_RESET_ASSERT ?
-						 SD0_DLL_RST : 0);
-
-		return zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST,
-					 type == PM_DLL_RESET_ASSERT ?
-					 SD1_DLL_RST : 0);
-	} else {
-		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
-					 IOCTL_SD_DLL_RESET, type, 0, NULL);
-	}
-}
-
-int arasan_zynqmp_set_in_tapdelay(u8 node_id, u32 itap_delay)
-{
-	int ret;
-
-	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
-		if (node_id == NODE_SD_0) {
-			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN,
-						SD0_ITAPCHGWIN);
-			if (ret)
-				return ret;
-
-			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA,
-						SD0_ITAPDLYENA);
-			if (ret)
-				return ret;
-
-			ret = zynqmp_mmio_write(SD_ITAP_DLY,
-						SD0_ITAPDLYSEL_MASK,
-						itap_delay);
-			if (ret)
-				return ret;
-
-			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, 0);
-			if (ret)
-				return ret;
-		}
-		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN,
-					SD1_ITAPCHGWIN);
-		if (ret)
-			return ret;
-
-		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA,
-					SD1_ITAPDLYENA);
-		if (ret)
-			return ret;
-
-		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
-					(itap_delay << 16));
-		if (ret)
-			return ret;
-
-		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0);
-		if (ret)
-			return ret;
-	} else {
-		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
-					 IOCTL_SET_SD_TAPDELAY,
-					 PM_TAPDELAY_INPUT, itap_delay, NULL);
-	}
-
-	return 0;
-}
-
-int arasan_zynqmp_set_out_tapdelay(u8 node_id, u32 otap_delay)
-{
-	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
-		if (node_id == NODE_SD_0)
-			return zynqmp_mmio_write(SD_OTAP_DLY,
-						 SD0_OTAPDLYSEL_MASK,
-						 otap_delay);
-
-		return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
-					 (otap_delay << 16));
-	} else {
-		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
-					 IOCTL_SET_SD_TAPDELAY,
-					 PM_TAPDELAY_OUTPUT, otap_delay, NULL);
-	}
-}
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 8397f24255..9a1693940a 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -15,9 +15,9 @@
 #include <dm/device_compat.h>
 #include <linux/err.h>
 #include <linux/libfdt.h>
+#include <asm/cache.h>
 #include <malloc.h>
 #include <sdhci.h>
-#include <zynqmp_tap_delay.h>
 #include <zynqmp_firmware.h>
 
 #define SDHCI_ARASAN_ITAPDLY_REGISTER	0xF0F8
@@ -31,6 +31,20 @@
 #define SDHCI_TUNING_LOOP_COUNT		40
 #define MMC_BANK2			0x2
 
+#define SD_DLL_CTRL			0xFF180358
+#define SD_ITAP_DLY			0xFF180314
+#define SD_OTAP_DLY			0xFF180318
+#define SD0_DLL_RST			BIT(2)
+#define SD1_DLL_RST			BIT(18)
+#define SD0_ITAPCHGWIN			BIT(9)
+#define SD1_ITAPCHGWIN			BIT(25)
+#define SD0_ITAPDLYENA			BIT(8)
+#define SD1_ITAPDLYENA			BIT(24)
+#define SD0_ITAPDLYSEL_MASK		GENMASK(7, 0)
+#define SD1_ITAPDLYSEL_MASK		GENMASK(23, 16)
+#define SD0_OTAPDLYSEL_MASK		GENMASK(5, 0)
+#define SD1_OTAPDLYSEL_MASK		GENMASK(21, 16)
+
 struct arasan_sdhci_clk_data {
 	int clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
 	int clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
@@ -49,6 +63,12 @@ struct arasan_sdhci_priv {
 	u8 no_1p8;
 };
 
+/* For Versal platforms zynqmp_mmio_write() won't be available */
+__weak int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value)
+{
+	return 0;
+}
+
 #if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
 /* Default settings for ZynqMP Clock Phases */
 static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63,  0,
@@ -76,6 +96,92 @@ static const u8 mode2timing[] = {
 	[MMC_HS_200] = MMC_TIMING_MMC_HS200,
 };
 
+static inline int arasan_zynqmp_set_in_tapdelay(u8 node_id, u32 itap_delay)
+{
+	int ret;
+
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		if (node_id == NODE_SD_0) {
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN,
+						SD0_ITAPCHGWIN);
+			if (ret)
+				return ret;
+
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA,
+						SD0_ITAPDLYENA);
+			if (ret)
+				return ret;
+
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
+						itap_delay);
+			if (ret)
+				return ret;
+
+			ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, 0);
+			if (ret)
+				return ret;
+		}
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN,
+					SD1_ITAPCHGWIN);
+		if (ret)
+			return ret;
+
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA,
+					SD1_ITAPDLYENA);
+		if (ret)
+			return ret;
+
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
+					(itap_delay << 16));
+		if (ret)
+			return ret;
+
+		ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0);
+		if (ret)
+			return ret;
+	} else {
+		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+					 IOCTL_SET_SD_TAPDELAY,
+					 PM_TAPDELAY_INPUT, itap_delay, NULL);
+	}
+
+	return 0;
+}
+
+static inline int arasan_zynqmp_set_out_tapdelay(u8 node_id, u32 otap_delay)
+{
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		if (node_id == NODE_SD_0)
+			return zynqmp_mmio_write(SD_OTAP_DLY,
+						 SD0_OTAPDLYSEL_MASK,
+						 otap_delay);
+
+		return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
+					 (otap_delay << 16));
+	} else {
+		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+					 IOCTL_SET_SD_TAPDELAY,
+					 PM_TAPDELAY_OUTPUT, otap_delay, NULL);
+	}
+}
+
+static inline int zynqmp_dll_reset(u8 node_id, u32 type)
+{
+	if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
+		if (node_id == NODE_SD_0)
+			return zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST,
+						 type == PM_DLL_RESET_ASSERT ?
+						 SD0_DLL_RST : 0);
+
+		return zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST,
+					 type == PM_DLL_RESET_ASSERT ?
+					 SD1_DLL_RST : 0);
+	} else {
+		return xilinx_pm_request(PM_IOCTL, (u32)node_id,
+					 IOCTL_SD_DLL_RESET, type, 0, NULL);
+	}
+}
+
 static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 node_id)
 {
 	struct mmc *mmc = (struct mmc *)host->mmc;
diff --git a/include/zynqmp_tap_delay.h b/include/zynqmp_tap_delay.h
deleted file mode 100644
index 7ef172f0fa..0000000000
--- a/include/zynqmp_tap_delay.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Xilinx ZynqMP SoC Tap Delay Programming
- *
- * Copyright (C) 2018 Xilinx, Inc.
- */
-
-#ifndef __ZYNQMP_TAP_DELAY_H__
-#define __ZYNQMP_TAP_DELAY_H__
-
-#include <zynqmp_firmware.h>
-
-#ifdef CONFIG_ARCH_ZYNQMP
-int zynqmp_dll_reset(u8 node_id, u32 type);
-int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay);
-int arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay);
-#else
-inline int zynqmp_dll_reset(u8 deviceid, u32 type)
-{
-	return 0;
-}
-
-inline int arasan_zynqmp_set_in_tapdelay(u8 device_id, u32 itap_delay)
-{
-	return 0;
-}
-
-inline int arasan_zynqmp_set_out_tapdelay(u8 device_id, u32 otap_delay)
-{
-	return 0;
-}
-#endif
-
-#endif
-- 
2.17.1


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

* [PATCH v3 6/7] mmc: zynq_sdhci: Wait till sd card detect state is stable
  2021-07-30 12:28 [PATCH v3 0/7] Arasan sdhci driver updates Ashok Reddy Soma
                   ` (4 preceding siblings ...)
  2021-07-30 12:28 ` [PATCH v3 5/7] mmc: zynq_sdhci: Move setting tapdelay code to driver Ashok Reddy Soma
@ 2021-07-30 12:28 ` Ashok Reddy Soma
  2021-07-30 12:28 ` [PATCH v3 7/7] mmc: zynq_sdhci: Use set_control_reg from sdhci.c Ashok Reddy Soma
  6 siblings, 0 replies; 10+ messages in thread
From: Ashok Reddy Soma @ 2021-07-30 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: peng.fan, jh80.chung, faiz_abbas, sjg, michael, git, monstr,
	somaashokreddy, T Karthik Reddy, Ashok Reddy Soma

From: T Karthik Reddy <t.karthik.reddy@xilinx.com>

As per SD spec when SD host controller is reset, it takes 1000msec
to detect the card state. In case, if we enable the sd bus voltage &
card detect state is not stable, then host controller will disable
the sd bus voltage.

In case of warm/subsystem reboot, due to unstable card detect state
host controller is disabling the sd bus voltage to sd card causing
sd card timeout error. So we wait for a maximum of 1000msec to get
the card detect state stable before we enable the sd bus voltage.

This current fix is workaround for now, this needs to be analysed
further. Zynqmp platform should behave the same as Versal, but we
did not encounter this issue as of now. So we are fixing it for
Versal only.

Signed-off-by: T Karthik Reddy <t.karthik.reddy@xilinx.com>
Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
---

(no changes since v2)

Changes in v2:
 - Changed return error from -EIO to -ETIMEDOUT in arasan_sdhci_probe()
   in card detect state stable workaround

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

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 9a1693940a..89776f48eb 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -776,6 +776,23 @@ static int arasan_sdhci_probe(struct udevice *dev)
 		return ret;
 	upriv->mmc = host->mmc;
 
+	/*
+	 * Wait for 1000msec till the card detect state gets stable
+	 * else host controller will set sd power bus voltage to 0.
+	 */
+	if (IS_ENABLED(CONFIG_ARCH_VERSAL)) {
+		u32 timeout = 1000;
+
+		while (((sdhci_readl(host, SDHCI_PRESENT_STATE) &
+			 SDHCI_CARD_STATE_STABLE) == 0) && timeout--) {
+			mdelay(1);
+		}
+		if (!timeout) {
+			dev_err(dev, "Sdhci card detect state not stable\n");
+			return -ETIMEDOUT;
+		}
+	}
+
 	return sdhci_probe(dev);
 }
 
-- 
2.17.1


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

* [PATCH v3 7/7] mmc: zynq_sdhci: Use set_control_reg from sdhci.c
  2021-07-30 12:28 [PATCH v3 0/7] Arasan sdhci driver updates Ashok Reddy Soma
                   ` (5 preceding siblings ...)
  2021-07-30 12:28 ` [PATCH v3 6/7] mmc: zynq_sdhci: Wait till sd card detect state is stable Ashok Reddy Soma
@ 2021-07-30 12:28 ` Ashok Reddy Soma
  6 siblings, 0 replies; 10+ messages in thread
From: Ashok Reddy Soma @ 2021-07-30 12:28 UTC (permalink / raw)
  To: u-boot
  Cc: peng.fan, jh80.chung, faiz_abbas, sjg, michael, git, monstr,
	somaashokreddy, Ashok Reddy Soma

Since set_control_reg is available in sdhci.c, use it and remove
arasan_sdhci_set_control_reg().

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
---

(no changes since v1)

 drivers/mmc/zynq_sdhci.c | 21 +--------------------
 1 file changed, 1 insertion(+), 20 deletions(-)

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 89776f48eb..73bb3abbc2 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -690,29 +690,10 @@ static void arasan_dt_parse_clk_phases(struct udevice *dev)
 				 "clk-phase-mmc-hs400");
 }
 
-static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
-{
-	struct mmc *mmc = (struct mmc *)host->mmc;
-	u32 reg;
-
-	if (!IS_SD(mmc))
-		return;
-
-	if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
-		reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-		reg |= SDHCI_CTRL_VDD_180;
-		sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
-	}
-
-	if (mmc->selected_mode > SD_HS &&
-	    mmc->selected_mode <= MMC_HS_200)
-		sdhci_set_uhs_timing(host);
-}
-
 static const struct sdhci_ops arasan_ops = {
 	.platform_execute_tuning	= &arasan_sdhci_execute_tuning,
 	.set_delay = &arasan_sdhci_set_tapdelay,
-	.set_control_reg = &arasan_sdhci_set_control_reg,
+	.set_control_reg = &sdhci_set_control_reg,
 };
 #endif
 
-- 
2.17.1


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

* Re: [PATCH v3 1/7] mmc: zynq_sdhci: Return errors from arasan_sdhci_set_tapdelay
  2021-07-30 12:28 ` [PATCH v3 1/7] mmc: zynq_sdhci: Return errors from arasan_sdhci_set_tapdelay Ashok Reddy Soma
@ 2021-08-01 23:08   ` Jaehoon Chung
  0 siblings, 0 replies; 10+ messages in thread
From: Jaehoon Chung @ 2021-08-01 23:08 UTC (permalink / raw)
  To: Ashok Reddy Soma, u-boot
  Cc: peng.fan, faiz_abbas, sjg, michael, git, monstr, somaashokreddy,
	T Karthik Reddy

On 7/30/21 9:28 PM, Ashok Reddy Soma wrote:
> Change return type of arasan_sdhci_set_tapdelay() to int, to facilitate
> returning errors. Get return values from input and output set clock phase
> functions inside arasan_sdhci_set_tapdelay() and return those errors.
> 
> Signed-off-by: T Karthik Reddy <t.karthik.reddy@xilinx.com>
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>

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

Best Regards,
Jaehoon Chung

> ---
> 
> Changes in v3:
>  - Added new line after return at two places
> 
> Changes in v2:
>  - Split patch 1/7 to two patches, one for zynq_sdhci and other one
>    for sdhci
> 
>  drivers/mmc/zynq_sdhci.c | 23 ++++++++++++++++++-----
>  1 file changed, 18 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
> index ba87ee8dd5..1ecc2ec669 100644
> --- a/drivers/mmc/zynq_sdhci.c
> +++ b/drivers/mmc/zynq_sdhci.c
> @@ -422,7 +422,7 @@ static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
>  	return 0;
>  }
>  
> -static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
> +static int 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;
> @@ -431,18 +431,31 @@ static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
>  	u8 timing = mode2timing[mmc->selected_mode];
>  	u32 iclk_phase = clk_data->clk_phase_in[timing];
>  	u32 oclk_phase = clk_data->clk_phase_out[timing];
> +	int ret;
>  
>  	dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
>  
>  	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);
> +		ret = sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
> +		if (ret)
> +			return ret;
> +
> +		ret = sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
> +		if (ret)
> +			return ret;
>  	} 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);
> +		ret = sdhci_versal_sampleclk_set_phase(host, iclk_phase);
> +		if (ret)
> +			return ret;
> +
> +		ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
> +		if (ret)
> +			return ret;
>  	}
> +
> +	return 0;
>  }
>  
>  static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
> 


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

* Re: [PATCH v3 2/7] mmc: sdhci: Change prototype of set_delay to return errors
  2021-07-30 12:28 ` [PATCH v3 2/7] mmc: sdhci: Change prototype of set_delay to return errors Ashok Reddy Soma
@ 2021-08-01 23:09   ` Jaehoon Chung
  0 siblings, 0 replies; 10+ messages in thread
From: Jaehoon Chung @ 2021-08-01 23:09 UTC (permalink / raw)
  To: Ashok Reddy Soma, u-boot
  Cc: peng.fan, faiz_abbas, sjg, michael, git, monstr, somaashokreddy

On 7/30/21 9:28 PM, Ashok Reddy Soma wrote:
> set_delay() has return type as void. If there are any errors while
> setting tapdelay's it won't be able to return them.
> 
> Change the prototype of set_delay() in sdhci_ops structure and return
> the errors from wherever it is called.
> 
> Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>


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

Best Regards,
Jaehoon Chung

> ---
> 
> (no changes since v2)
> 
> Changes in v2:
>  - This is the second patch that has been split from 1/7
>  - This covers changes for sdhci driver separately
>  - Added a debug print in case of error from set_delay()
> 
>  drivers/mmc/sdhci.c | 10 ++++++++--
>  include/sdhci.h     |  2 +-
>  2 files changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
> index d9ab6a0a83..a99014236a 100644
> --- a/drivers/mmc/sdhci.c
> +++ b/drivers/mmc/sdhci.c
> @@ -366,6 +366,7 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
>  {
>  	struct sdhci_host *host = mmc->priv;
>  	unsigned int div, clk = 0, timeout;
> +	int ret;
>  
>  	/* Wait max 20 ms */
>  	timeout = 200;
> @@ -386,8 +387,13 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
>  	if (clock == 0)
>  		return 0;
>  
> -	if (host->ops && host->ops->set_delay)
> -		host->ops->set_delay(host);
> +	if (host->ops && host->ops->set_delay) {
> +		ret = host->ops->set_delay(host);
> +		if (ret) {
> +			printf("%s: Error while setting tap delay\n", __func__);
> +			return ret;
> +		}
> +	}
>  
>  	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
>  		/*
> diff --git a/include/sdhci.h b/include/sdhci.h
> index 0ae9471ad7..44a0d84e5a 100644
> --- a/include/sdhci.h
> +++ b/include/sdhci.h
> @@ -268,7 +268,7 @@ struct sdhci_ops {
>  	int	(*set_ios_post)(struct sdhci_host *host);
>  	void	(*set_clock)(struct sdhci_host *host, u32 div);
>  	int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
> -	void (*set_delay)(struct sdhci_host *host);
> +	int (*set_delay)(struct sdhci_host *host);
>  	int	(*deferred_probe)(struct sdhci_host *host);
>  };
>  
> 


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

end of thread, other threads:[~2021-08-01 23:08 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-30 12:28 [PATCH v3 0/7] Arasan sdhci driver updates Ashok Reddy Soma
2021-07-30 12:28 ` [PATCH v3 1/7] mmc: zynq_sdhci: Return errors from arasan_sdhci_set_tapdelay Ashok Reddy Soma
2021-08-01 23:08   ` Jaehoon Chung
2021-07-30 12:28 ` [PATCH v3 2/7] mmc: sdhci: Change prototype of set_delay to return errors Ashok Reddy Soma
2021-08-01 23:09   ` Jaehoon Chung
2021-07-30 12:28 ` [PATCH v3 3/7] zynqmp_firmware: Add zynqmp firmware related enums Ashok Reddy Soma
2021-07-30 12:28 ` [PATCH v3 4/7] mmc: zynq_sdhci: Add xilinx_pm_request() method to set tapdelays Ashok Reddy Soma
2021-07-30 12:28 ` [PATCH v3 5/7] mmc: zynq_sdhci: Move setting tapdelay code to driver Ashok Reddy Soma
2021-07-30 12:28 ` [PATCH v3 6/7] mmc: zynq_sdhci: Wait till sd card detect state is stable Ashok Reddy Soma
2021-07-30 12:28 ` [PATCH v3 7/7] mmc: zynq_sdhci: Use set_control_reg from sdhci.c Ashok Reddy Soma

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.