From 3b3d6dec05277f7786d813592a31ea4a1ce60a74 Mon Sep 17 00:00:00 2001
From: Breno Lima <breno.lima@nxp.com>
Date: Tue, 29 Jun 2021 17:01:58 -0400
Subject: [PATCH] LF-4086-1 mmc: sdhci-esdhc-imx: Add device tree property to
 select DATA[0] and CMD signals for periodic tuning

SDIO cards can implement an optional feature that uses DATA[1] to signal
the card's interrupt to the i.MX device, this feature can be enabled by
the SDIO card device and does not depends on i.MX uSDHC driver setup
configuration.

Out of reset uSDHC is configuring the uSDHC_VEND_SPEC2 register to use
DATA[3:0] signals for calculating the appropriate delay cell for the
current operation environment, this setup can conflict with the SDIO
interrupt as DATA[1] signal can be asserted asynchronously.

SDIO failures can be observed when running i.MX6ULL EVK and
88w8987/88w8997 at higher frequencies such as SDR104 or SDR50.
Wi-Fi driver is reporting CMD53 read error due to incorrect delay
cell calculated by the i.MX processor and uSDHC controller.

Add optional device tree property to select DATA[0] and CMD signals
for uSDHC auto tuning mechanism. This setup can only be used if SD
interface length are well matched.

Signed-off-by: Breno Lima <breno.lima@nxp.com>
Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c          | 13 +++++++++++++
 include/linux/platform_data/mmc-esdhc-imx.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 4da4f47346415d..4bf3d7afb1ae3f 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -96,6 +96,8 @@
 #define ESDHC_STROBE_DLL_STS_SLV_LOCK	0x1
 
 #define ESDHC_VEND_SPEC2		0xc8
+#define ESDHC_VEND_SPEC2_TUNING_EN_MASK	0x00000070
+#define ESDHC_VEND_SPEC2_TUNING_EN_SHIFT	4
 #define ESDHC_VEND_SPEC2_EN_BUSY_IRQ	(1 << 8)
 
 #define ESDHC_TUNING_CTRL		0xcc
@@ -1417,6 +1419,14 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
 			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
 		}
 
+		/* uSDHC auto tuning mechanism should use DAT[0] and CMD lines
+		 * if SDIO card is enabling SDIO Interrupts on DAT[1].
+		 */
+		if (imx_data->boarddata.sdio_interrupt_enabled)
+			esdhc_clrset_le(host, ESDHC_VEND_SPEC2_TUNING_EN_MASK,
+					0x6 << ESDHC_VEND_SPEC2_TUNING_EN_SHIFT,
+			                ESDHC_VEND_SPEC2);
+
 		/*
 		 * On i.MX8MM, we are running Dual Linux OS, with 1st Linux using SD Card
 		 * as rootfs storage, 2nd Linux using eMMC as rootfs storage. We let the
@@ -1526,6 +1536,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
 	if (of_find_property(np, "no-1-8-v", NULL))
 		host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
 
+	if (of_property_read_bool(np, "fsl,sdio-interrupt-enabled"))
+		boarddata->sdio_interrupt_enabled = true;
+
 	if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line))
 		boarddata->delay_line = 0;
 
diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
index cba1184b364c97..40d64d15242f46 100644
--- a/include/linux/platform_data/mmc-esdhc-imx.h
+++ b/include/linux/platform_data/mmc-esdhc-imx.h
@@ -38,5 +38,6 @@ struct esdhc_platform_data {
 	unsigned int tuning_step;       /* The delay cell steps in tuning procedure */
 	unsigned int tuning_start_tap;	/* The start delay cell point in tuning procedure */
 	unsigned int strobe_dll_delay_target;	/* The delay cell for strobe pad (read clock) */
+	bool sdio_interrupt_enabled;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
-- 
GitLab