[PATCH 1/4] mmc: sdhci-cadence6: use const PHY config tables with per-call overrides
[email protected] Wed, 26 Aug 2026 10:53:00 +0800
Newsgroups
org.u-boot-project.lists.u-boot
Message-ID
<7431866da9cda49057125df1b28986f04d63e168.1787710268.git.tze.yee.ng@altera.com>
From: Tze Yee Ng <[email protected] >
The per-mode PHY and controller configuration arrays are static globals
shared across all SD6HC instances. sdhci_cdns6_phy_adj() read device
tree overrides directly into these tables, so DT-derived values could
leak between controllers, and a missing DT property on one controller
would silently reuse a value programmed for another.
Mark the configuration tables const and copy the selected defaults into
per-call local storage before applying any device tree overrides, so the
shared defaults are never mutated
Signed-off-by: Tze Yee Ng <[email protected] >
---
drivers/mmc/sdhci-cadence6.c | 88 ++++++++++++++++++++----------------
1 file changed, 49 insertions(+), 39 deletions(-)
diff --git a/drivers/mmc/sdhci-cadence6.c b/drivers/mmc/sdhci-cadence6.c
index 407eae96dd4..1ff974ecd44 100644
--- a/drivers/mmc/sdhci-cadence6.c
+++ b/drivers/mmc/sdhci-cadence6.c
@@ -72,7 +72,7 @@ struct sdhci_cdns6_ctrl_cfg {
u32 val;
};
-static struct sdhci_cdns6_phy_cfg sd_ds_phy_cfgs[] = {
+static const struct sdhci_cdns6_phy_cfg sd_ds_phy_cfgs[] = {
{ "cdns,phy-dqs-timing-delay-sd-ds", 0x00380004, },
{ "cdns,phy-gate-lpbk-ctrl-delay-sd-ds", 0x01A00040, },
{ "cdns,phy-dll-slave-ctrl-sd-ds", 0x00000000, },
@@ -80,7 +80,7 @@ static struct sdhci_cdns6_phy_cfg sd_ds_phy_cfgs[] = {
{ "cdns,phy-dll-master-ctrl-sd-ds", 0x00800004, },
};
-static struct sdhci_cdns6_phy_cfg sd_hs_phy_cfgs[] = {
+static const struct sdhci_cdns6_phy_cfg sd_hs_phy_cfgs[] = {
{ "cdns,phy-dqs-timing-delay-sd-hs", 0x00380004, },
{ "cdns,phy-gate-lpbk-ctrl-delay-sd-hs", 0x01A00040, },
{ "cdns,phy-dll-slave-ctrl-sd-hs", 0x00000000, },
@@ -88,7 +88,7 @@ static struct sdhci_cdns6_phy_cfg sd_hs_phy_cfgs[] = {
{ "cdns,phy-dll-master-ctrl-sd-hs", 0x00800004, },
};
-static struct sdhci_cdns6_phy_cfg emmc_sdr_phy_cfgs[] = {
+static const struct sdhci_cdns6_phy_cfg emmc_sdr_phy_cfgs[] = {
{ "cdns,phy-dqs-timing-delay-emmc-sdr", 0x00380004, },
{ "cdns,phy-gate-lpbk-ctrl-delay-emmc-sdr", 0x01A00040, },
{ "cdns,phy-dll-slave-ctrl-emmc-sdr", 0x00000000, },
@@ -96,7 +96,7 @@ static struct sdhci_cdns6_phy_cfg emmc_sdr_phy_cfgs[] = {
{ "cdns,phy-dll-master-ctrl-emmc-sdr", 0x00800004, },
};
-static struct sdhci_cdns6_phy_cfg emmc_ddr_phy_cfgs[] = {
+static const struct sdhci_cdns6_phy_cfg emmc_ddr_phy_cfgs[] = {
{ "cdns,phy-dqs-timing-delay-emmc-ddr", 0x00380004, },
{ "cdns,phy-gate-lpbk-ctrl-delay-emmc-ddr", 0x01A00040, },
{ "cdns,phy-dll-slave-ctrl-emmc-ddr", 0x00000000, },
@@ -104,7 +104,7 @@ static struct sdhci_cdns6_phy_cfg emmc_ddr_phy_cfgs[] = {
{ "cdns,phy-dll-master-ctrl-emmc-ddr", 0x00800004, },
};
-static struct sdhci_cdns6_phy_cfg emmc_hs200_phy_cfgs[] = {
+static const struct sdhci_cdns6_phy_cfg emmc_hs200_phy_cfgs[] = {
{ "cdns,phy-dqs-timing-delay-emmc-hs200", 0x00380004, },
{ "cdns,phy-gate-lpbk-ctrl-delay-emmc-hs200", 0x01A00040, },
{ "cdns,phy-dll-slave-ctrl-emmc-hs200", 0x00DADA00, },
@@ -112,7 +112,7 @@ static struct sdhci_cdns6_phy_cfg emmc_hs200_phy_cfgs[] = {
{ "cdns,phy-dll-master-ctrl-emmc-hs200", 0x00000004, },
};
-static struct sdhci_cdns6_phy_cfg emmc_hs400_phy_cfgs[] = {
+static const struct sdhci_cdns6_phy_cfg emmc_hs400_phy_cfgs[] = {
{ "cdns,phy-dqs-timing-delay-emmc-hs400", 0x00280004, },
{ "cdns,phy-gate-lpbk-ctrl-delay-emmc-hs400", 0x01A00040, },
{ "cdns,phy-dll-slave-ctrl-emmc-hs400", 0x00DAD800, },
@@ -120,42 +120,42 @@ static struct sdhci_cdns6_phy_cfg emmc_hs400_phy_cfgs[] = {
{ "cdns,phy-dll-master-ctrl-emmc-hs400", 0x00000004, },
};
-static struct sdhci_cdns6_ctrl_cfg sd_ds_ctrl_cfgs[] = {
+static const struct sdhci_cdns6_ctrl_cfg sd_ds_ctrl_cfgs[] = {
{ "cdns,ctrl-hrs09-timing-delay-sd-ds", 0x0001800C, },
{ "cdns,ctrl-hrs10-lpbk-ctrl-delay-sd-ds", 0x00020000, },
{ "cdns,ctrl-hrs16-slave-ctrl-sd-ds", 0x00000000, },
{ "cdns,ctrl-hrs07-timing-delay-sd-ds", 0x00080000, },
};
-static struct sdhci_cdns6_ctrl_cfg sd_hs_ctrl_cfgs[] = {
+static const struct sdhci_cdns6_ctrl_cfg sd_hs_ctrl_cfgs[] = {
{ "cdns,ctrl-hrs09-timing-delay-sd-hs", 0x0001800C, },
{ "cdns,ctrl-hrs10-lpbk-ctrl-delay-sd-hs", 0x00030000, },
{ "cdns,ctrl-hrs16-slave-ctrl-sd-hs", 0x00000000, },
{ "cdns,ctrl-hrs07-timing-delay-sd-hs", 0x00080000, },
};
-static struct sdhci_cdns6_ctrl_cfg emmc_sdr_ctrl_cfgs[] = {
+static const struct sdhci_cdns6_ctrl_cfg emmc_sdr_ctrl_cfgs[] = {
{ "cdns,ctrl-hrs09-timing-delay-emmc-sdr", 0x0001800C, },
{ "cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-sdr", 0x00030000, },
{ "cdns,ctrl-hrs16-slave-ctrl-emmc-sdr", 0x00000000, },
{ "cdns,ctrl-hrs07-timing-delay-emmc-sdr", 0x00080000, },
};
-static struct sdhci_cdns6_ctrl_cfg emmc_ddr_ctrl_cfgs[] = {
+static const struct sdhci_cdns6_ctrl_cfg emmc_ddr_ctrl_cfgs[] = {
{ "cdns,ctrl-hrs09-timing-delay-emmc-ddr", 0x0001800C, },
{ "cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-ddr", 0x00020000, },
{ "cdns,ctrl-hrs16-slave-ctrl-emmc-ddr", 0x11000001, },
{ "cdns,ctrl-hrs07-timing-delay-emmc-ddr", 0x00090001, },
};
-static struct sdhci_cdns6_ctrl_cfg emmc_hs200_ctrl_cfgs[] = {
+static const struct sdhci_cdns6_ctrl_cfg emmc_hs200_ctrl_cfgs[] = {
{ "cdns,ctrl-hrs09-timing-delay-emmc-hs200", 0x00018000, },
{ "cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-hs200", 0x00080000, },
{ "cdns,ctrl-hrs16-slave-ctrl-emmc-hs200", 0x00000000, },
{ "cdns,ctrl-hrs07-timing-delay-emmc-hs200", 0x00090000, },
};
-static struct sdhci_cdns6_ctrl_cfg emmc_hs400_ctrl_cfgs[] = {
+static const struct sdhci_cdns6_ctrl_cfg emmc_hs400_ctrl_cfgs[] = {
{ "cdns,ctrl-hrs09-timing-delay-emmc-hs400", 0x00018000, },
{ "cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-hs400", 0x00080000, },
{ "cdns,ctrl-hrs16-slave-ctrl-emmc-hs400", 0x11000000, },
@@ -212,65 +212,75 @@ static int sdhci_cdns6_reset_phy_dll(struct sdhci_cdns_plat *plat, bool reset)
int sdhci_cdns6_phy_adj(struct udevice *dev, struct sdhci_cdns_plat *plat, u32 mode)
{
- struct sdhci_cdns6_phy_cfg *sdhci_cdns6_phy_cfgs;
- struct sdhci_cdns6_ctrl_cfg *sdhci_cdns6_ctrl_cfgs;
+ const struct sdhci_cdns6_phy_cfg *phy_defaults;
+ const struct sdhci_cdns6_ctrl_cfg *ctrl_defaults;
+ struct sdhci_cdns6_phy_cfg phy_cfgs[SDHCI_CDNS6_PHY_CFG_NUM];
+ struct sdhci_cdns6_ctrl_cfg ctrl_cfgs[SDHCI_CDNS6_CTRL_CFG_NUM];
u32 tmp;
int i, ret;
switch (mode) {
case UHS_SDR12:
case MMC_LEGACY:
- sdhci_cdns6_phy_cfgs = sd_ds_phy_cfgs;
- sdhci_cdns6_ctrl_cfgs = sd_ds_ctrl_cfgs;
+ phy_defaults = sd_ds_phy_cfgs;
+ ctrl_defaults = sd_ds_ctrl_cfgs;
break;
case SD_HS:
case UHS_SDR25:
case MMC_HS:
- sdhci_cdns6_phy_cfgs = sd_hs_phy_cfgs;
- sdhci_cdns6_ctrl_cfgs = sd_hs_ctrl_cfgs;
+ phy_defaults = sd_hs_phy_cfgs;
+ ctrl_defaults = sd_hs_ctrl_cfgs;
break;
case UHS_SDR50:
case MMC_HS_52:
- sdhci_cdns6_phy_cfgs = emmc_sdr_phy_cfgs;
- sdhci_cdns6_ctrl_cfgs = emmc_sdr_ctrl_cfgs;
+ phy_defaults = emmc_sdr_phy_cfgs;
+ ctrl_defaults = emmc_sdr_ctrl_cfgs;
break;
case UHS_DDR50:
case MMC_DDR_52:
- sdhci_cdns6_phy_cfgs = emmc_ddr_phy_cfgs;
- sdhci_cdns6_ctrl_cfgs = emmc_ddr_ctrl_cfgs;
+ phy_defaults = emmc_ddr_phy_cfgs;
+ ctrl_defaults = emmc_ddr_ctrl_cfgs;
break;
case UHS_SDR104:
case MMC_HS_200:
- sdhci_cdns6_phy_cfgs = emmc_hs200_phy_cfgs;
- sdhci_cdns6_ctrl_cfgs = emmc_hs200_ctrl_cfgs;
+ phy_defaults = emmc_hs200_phy_cfgs;
+ ctrl_defaults = emmc_hs200_ctrl_cfgs;
break;
case MMC_HS_400:
case MMC_HS_400_ES:
- sdhci_cdns6_phy_cfgs = emmc_hs400_phy_cfgs;
- sdhci_cdns6_ctrl_cfgs = emmc_hs400_ctrl_cfgs;
+ phy_defaults = emmc_hs400_phy_cfgs;
+ ctrl_defaults = emmc_hs400_ctrl_cfgs;
break;
default:
return -EINVAL;
}
- for (i = 0; i < SDHCI_CDNS6_PHY_CFG_NUM; i++)
- dev_read_u32(dev, sdhci_cdns6_phy_cfgs[i].property, &sdhci_cdns6_phy_cfgs[i].val);
+ /*
+ * Work on per-call copies so DT overrides never mutate the shared
+ * const defaults, which would otherwise leak between controllers.
+ */
+ for (i = 0; i < SDHCI_CDNS6_PHY_CFG_NUM; i++) {
+ phy_cfgs[i] = phy_defaults[i];
+ dev_read_u32(dev, phy_cfgs[i].property, &phy_cfgs[i].val);
+ }
- for (i = 0; i < SDHCI_CDNS6_CTRL_CFG_NUM; i++)
- dev_read_u32(dev, sdhci_cdns6_ctrl_cfgs[i].property, &sdhci_cdns6_ctrl_cfgs[i].val);
+ for (i = 0; i < SDHCI_CDNS6_CTRL_CFG_NUM; i++) {
+ ctrl_cfgs[i] = ctrl_defaults[i];
+ dev_read_u32(dev, ctrl_cfgs[i].property, &ctrl_cfgs[i].val);
+ }
/* Switch On the DLL Reset */
sdhci_cdns6_reset_phy_dll(plat, true);
- sdhci_cdns6_write_phy_reg(plat, PHY_DQS_TIMING_REG_ADDR, sdhci_cdns6_phy_cfgs[0].val);
- sdhci_cdns6_write_phy_reg(plat, PHY_GATE_LPBK_CTRL_REG_ADDR, sdhci_cdns6_phy_cfgs[1].val);
- sdhci_cdns6_write_phy_reg(plat, PHY_DLL_MASTER_CTRL_REG_ADDR, sdhci_cdns6_phy_cfgs[4].val);
- sdhci_cdns6_write_phy_reg(plat, PHY_DLL_SLAVE_CTRL_REG_ADDR, sdhci_cdns6_phy_cfgs[2].val);
+ sdhci_cdns6_write_phy_reg(plat, PHY_DQS_TIMING_REG_ADDR, phy_cfgs[0].val);
+ sdhci_cdns6_write_phy_reg(plat, PHY_GATE_LPBK_CTRL_REG_ADDR, phy_cfgs[1].val);
+ sdhci_cdns6_write_phy_reg(plat, PHY_DLL_MASTER_CTRL_REG_ADDR, phy_cfgs[4].val);
+ sdhci_cdns6_write_phy_reg(plat, PHY_DLL_SLAVE_CTRL_REG_ADDR, phy_cfgs[2].val);
/* Switch Off the DLL Reset */
ret = sdhci_cdns6_reset_phy_dll(plat, false);
@@ -280,7 +290,7 @@ int sdhci_cdns6_phy_adj(struct udevice *dev, struct sdhci_cdns_plat *plat, u32 m
}
/* Set PHY DQ TIMING control register */
- sdhci_cdns6_write_phy_reg(plat, PHY_DQ_TIMING_REG_ADDR, sdhci_cdns6_phy_cfgs[3].val);
+ sdhci_cdns6_write_phy_reg(plat, PHY_DQ_TIMING_REG_ADDR, phy_cfgs[3].val);
/* Set HRS09 register */
tmp = readl(plat->hrs_addr + SDHCI_CDNS_HRS09);
@@ -288,20 +298,20 @@ int sdhci_cdns6_phy_adj(struct udevice *dev, struct sdhci_cdns_plat *plat, u32 m
SDHCI_CDNS_HRS09_EXTENDED_RD_MODE |
SDHCI_CDNS_HRS09_RDDATA_EN |
SDHCI_CDNS_HRS09_RDCMD_EN);
- tmp |= sdhci_cdns6_ctrl_cfgs[0].val;
+ tmp |= ctrl_cfgs[0].val;
writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS09);
/* Set HRS10 register */
tmp = readl(plat->hrs_addr + SDHCI_CDNS_HRS10);
tmp &= ~SDHCI_CDNS_HRS10_HCSDCLKADJ;
- tmp |= sdhci_cdns6_ctrl_cfgs[1].val;
+ tmp |= ctrl_cfgs[1].val;
writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS10);
/* Set HRS16 register */
- writel(sdhci_cdns6_ctrl_cfgs[2].val, plat->hrs_addr + SDHCI_CDNS_HRS16);
+ writel(ctrl_cfgs[2].val, plat->hrs_addr + SDHCI_CDNS_HRS16);
/* Set HRS07 register */
- writel(sdhci_cdns6_ctrl_cfgs[3].val, plat->hrs_addr + SDHCI_CDNS_HRS07);
+ writel(ctrl_cfgs[3].val, plat->hrs_addr + SDHCI_CDNS_HRS07);
/*
* Wait for the PHY/DLL to settle before the first data transfer.
--
2.43.7