[PATCH 3/3] mmc: dw_mmc-rockchip: Add phase map support

Shawn Lin shawn.lin at rock-chips.com
Sun Mar 8 20:29:03 PDT 2026


Multiple boards require different phase settings, rendering the default
phase policy unscalable. Therefore, we introduce phase map to address this
limitation. To preserve backward compatibility, the default_sample_phase
and original drv phase for different modes are retained, with phase map
values taking precedence when available.

Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>

---

 drivers/mmc/host/dw_mmc-rockchip.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index 7699541..c6eece4 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -179,7 +179,8 @@ static int rockchip_mmc_set_phase(struct dw_mci *host, bool sample, int degrees)
 static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 {
 	struct dw_mci_rockchip_priv_data *priv = host->priv;
-	int ret;
+	struct mmc_clk_phase phase = host->phase_map.phase[ios->timing];
+	int ret, sample_phase, drv_phase;
 	unsigned int cclkin;
 	u32 bus_hz;
 
@@ -213,8 +214,15 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 	}
 
 	/* Make sure we use phases which we can enumerate with */
-	if (!IS_ERR(priv->sample_clk) && ios->timing <= MMC_TIMING_SD_HS)
-		rockchip_mmc_set_phase(host, true, priv->default_sample_phase);
+	if (!IS_ERR(priv->sample_clk)) {
+		/* Keep backward compatibility */
+		if (ios->timing <= MMC_TIMING_SD_HS) {
+			sample_phase = phase.valid ? phase.in_deg : priv->default_sample_phase;
+			rockchip_mmc_set_phase(host, true, sample_phase);
+		} else if (phase.valid) {
+			rockchip_mmc_set_phase(host, true, phase.in_deg);
+		}
+	}
 
 	/*
 	 * Set the drive phase offset based on speed mode to achieve hold times.
@@ -243,15 +251,13 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 	 * same results, for instance).
 	 */
 	if (!IS_ERR(priv->drv_clk)) {
-		int phase;
-
 		/*
 		 * In almost all cases a 90 degree phase offset will provide
 		 * sufficient hold times across all valid input clock rates
 		 * assuming delay_o is not absurd for a given SoC.  We'll use
 		 * that as a default.
 		 */
-		phase = 90;
+		drv_phase = 90;
 
 		switch (ios->timing) {
 		case MMC_TIMING_MMC_DDR52:
@@ -261,7 +267,7 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 			 * to get the same timings.
 			 */
 			if (ios->bus_width == MMC_BUS_WIDTH_8)
-				phase = 180;
+				drv_phase = 180;
 			break;
 		case MMC_TIMING_UHS_SDR104:
 		case MMC_TIMING_MMC_HS200:
@@ -273,11 +279,14 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 			 * SoCs measured this seems to be OK, but it doesn't
 			 * hurt to give margin here, so we use 180.
 			 */
-			phase = 180;
+			drv_phase = 180;
 			break;
 		}
 
-		rockchip_mmc_set_phase(host, false, phase);
+		/* Use out phase from phase map first */
+		if (phase.valid)
+			drv_phase = phase.out_deg;
+		rockchip_mmc_set_phase(host, false, drv_phase);
 	}
 }
 
-- 
2.7.4




More information about the Linux-rockchip mailing list