[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