* [PATCH 0/4] mmc: sdhci-cadence6: harden PHY config tables and enable Agilex5 UHS modes
@ 2026-08-26 2:52 tze.yee.ng
2026-08-26 2:53 ` [PATCH 1/4] mmc: sdhci-cadence6: use const PHY config tables with per-call overrides tze.yee.ng
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: tze.yee.ng @ 2026-08-26 2:52 UTC (permalink / raw)
To: u-boot
Cc: Tanmay Kathpalia, Peng Fan, Jaehoon Chung, Tom Rini, Marek Vasut,
Simon Goldschmidt, Tien Fong Chee, Ilias Apalodimas, u-boot,
Chen Huei Lok, Alif Zakuan Yuslaimi, Dinesh Maniyam, Boon Khai Ng,
Kok Kiang Hea
From: Tze Yee Ng <tze.yee.ng@altera.com>
This series hardens the per-mode PHY/controller configuration handling in
the Cadence SD6HC (v6) driver and then enables the UHS-I higher-speed
modes (SDR104 and DDR50, plus eMMC DDR52) on the Agilex5 SoCDK and its
013B and modular variants:
- const config tables + per-call copies, so device-tree overrides can
no longer mutate the shared defaults and leak between controllers;
- named enum slots for the PHY/HRS config tables, so reordering or
inserting an entry cannot silently reprogram the wrong register
(no functional change);
- program the PHY control register (0x2080) per speed mode, with a
per-mode / per-board device-tree override;
- add the SDR104 (emmc-hs200) and DDR50 (emmc-ddr) PHY timing for the
Agilex5 SoCDK, 013B and modular boards and advertise the matching
sd-uhs-* / mmc-ddr-1_8v capabilities.
Dependencies
------------
The driver patches (1-3) apply on top of, and depend on, the fixes
series (series=519635):
"mmc: sdhci-cadence6: fix PHY programming reliability"
The HRS05 posted-write flush and the post-adjustment settle delay from
that series are required for reliable higher-speed operation.
The device-tree patch (4) additionally depends on two Agilex5 board
patches still under review, as it extends the .dts/.dtsi files they add:
"arm: dts: socfpga: Add MDK support with external GPIO expander"
- Tanmay Kathpalia (series=16401)
"arm: dts: socfpga: Add Agilex5 E-Series 013B SoCDK variant"
- Dinesh Maniyam (series=32177)
Tze Yee Ng (4):
mmc: sdhci-cadence6: use const PHY config tables with per-call
overrides
mmc: sdhci-cadence6: name PHY and controller config table slots
mmc: sdhci-cadence6: configure PHY control register per speed mode
arm: dts: socfpga: agilex5: add SD/eMMC UHS PHY timing
.../arm/dts/socfpga_agilex5_socdk-u-boot.dtsi | 13 ++
.../socfpga_agilex5_socdk_013b-u-boot.dtsi | 24 +++-
arch/arm/dts/socfpga_agilex5_socdk_013b.dts | 4 +-
arch/arm/dts/socfpga_agilex5_socdk_emmc.dts | 13 ++
.../arm/dts/socfpga_agilex5_socdk_modular.dts | 20 +++
drivers/mmc/sdhci-cadence6.c | 136 ++++++++++++------
6 files changed, 166 insertions(+), 44 deletions(-)
--
2.43.7
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] mmc: sdhci-cadence6: use const PHY config tables with per-call overrides
2026-08-26 2:52 [PATCH 0/4] mmc: sdhci-cadence6: harden PHY config tables and enable Agilex5 UHS modes tze.yee.ng
@ 2026-08-26 2:53 ` tze.yee.ng
2026-09-12 20:26 ` Kathpalia, Tanmay
2026-08-26 2:53 ` [PATCH 2/4] mmc: sdhci-cadence6: name PHY and controller config table slots tze.yee.ng
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: tze.yee.ng @ 2026-08-26 2:53 UTC (permalink / raw)
To: u-boot
Cc: Tanmay Kathpalia, Peng Fan, Jaehoon Chung, Tom Rini, Marek Vasut,
Simon Goldschmidt, Tien Fong Chee, Ilias Apalodimas, u-boot,
Chen Huei Lok, Alif Zakuan Yuslaimi, Dinesh Maniyam, Boon Khai Ng,
Kok Kiang Hea
From: Tze Yee Ng <tze.yee.ng@altera.com>
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 <tze.yee.ng@altera.com>
---
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
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] mmc: sdhci-cadence6: name PHY and controller config table slots
2026-08-26 2:52 [PATCH 0/4] mmc: sdhci-cadence6: harden PHY config tables and enable Agilex5 UHS modes tze.yee.ng
2026-08-26 2:53 ` [PATCH 1/4] mmc: sdhci-cadence6: use const PHY config tables with per-call overrides tze.yee.ng
@ 2026-08-26 2:53 ` tze.yee.ng
2026-09-12 20:36 ` Kathpalia, Tanmay
2026-08-26 2:53 ` [PATCH 3/4] mmc: sdhci-cadence6: configure PHY control register per speed mode tze.yee.ng
2026-08-26 2:53 ` [PATCH 4/4] arm: dts: socfpga: agilex5: add SD/eMMC UHS PHY timing tze.yee.ng
3 siblings, 1 reply; 8+ messages in thread
From: tze.yee.ng @ 2026-08-26 2:53 UTC (permalink / raw)
To: u-boot
Cc: Tanmay Kathpalia, Peng Fan, Jaehoon Chung, Tom Rini, Marek Vasut,
Simon Goldschmidt, Tien Fong Chee, Ilias Apalodimas, u-boot,
Chen Huei Lok, Alif Zakuan Yuslaimi, Dinesh Maniyam, Boon Khai Ng,
Kok Kiang Hea
From: Tze Yee Ng <tze.yee.ng@altera.com>
sdhci_cdns6_phy_adj() programs the PHY and HRS controller registers by
indexing the *_phy_cfgs[] and *_ctrl_cfgs[] tables with bare positional
constants. This is fragile: reordering or inserting a table entry
silently changes which register each slot programs.
Introduce enums that name every PHY and controller configuration slot,
whose terminators double as the table sizes (SDHCI_CDNS6_PHY_CFG_NUM and
SDHCI_CDNS6_CTRL_CFG_NUM), and use those names when programming the
registers. No functional change.
Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
---
drivers/mmc/sdhci-cadence6.c | 54 ++++++++++++++++++++++++++++--------
1 file changed, 43 insertions(+), 11 deletions(-)
diff --git a/drivers/mmc/sdhci-cadence6.c b/drivers/mmc/sdhci-cadence6.c
index 1ff974ecd44..7bd47b462a4 100644
--- a/drivers/mmc/sdhci-cadence6.c
+++ b/drivers/mmc/sdhci-cadence6.c
@@ -59,8 +59,6 @@
#define PHY_DLL_SLAVE_CTRL_REG_READ_DQS_CMD_DELAY GENMASK(31, 24)
#define PHY_DLL_SLAVE_CTRL_REG_READ_DQS_DELAY GENMASK(7, 0)
-#define SDHCI_CDNS6_PHY_CFG_NUM 5
-#define SDHCI_CDNS6_CTRL_CFG_NUM 4
struct sdhci_cdns6_phy_cfg {
const char *property;
@@ -72,6 +70,33 @@ struct sdhci_cdns6_ctrl_cfg {
u32 val;
};
+/*
+ * PHY configuration slots. The enumeration order must match the entry
+ * order in every *_phy_cfgs[] table; SDHCI_CDNS6_PHY_CFG_NUM tracks the
+ * table size so the two never drift out of sync.
+ */
+enum {
+ SDHCI_CDNS6_PHY_CFG_DQS_TIMING,
+ SDHCI_CDNS6_PHY_CFG_GATE_LPBK_CTRL,
+ SDHCI_CDNS6_PHY_CFG_DLL_SLAVE_CTRL,
+ SDHCI_CDNS6_PHY_CFG_DQ_TIMING,
+ SDHCI_CDNS6_PHY_CFG_DLL_MASTER_CTRL,
+ SDHCI_CDNS6_PHY_CFG_NUM,
+};
+
+/*
+ * Controller (HRS) configuration slots. The enumeration order must match
+ * the entry order in every *_ctrl_cfgs[] table; SDHCI_CDNS6_CTRL_CFG_NUM
+ * tracks the table size so the two never drift out of sync.
+ */
+enum {
+ SDHCI_CDNS6_CTRL_CFG_HRS09,
+ SDHCI_CDNS6_CTRL_CFG_HRS10,
+ SDHCI_CDNS6_CTRL_CFG_HRS16,
+ SDHCI_CDNS6_CTRL_CFG_HRS07,
+ SDHCI_CDNS6_CTRL_CFG_NUM,
+};
+
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, },
@@ -277,10 +302,14 @@ int sdhci_cdns6_phy_adj(struct udevice *dev, struct sdhci_cdns_plat *plat, u32 m
/* Switch On the DLL Reset */
sdhci_cdns6_reset_phy_dll(plat, true);
- 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);
+ sdhci_cdns6_write_phy_reg(plat, PHY_DQS_TIMING_REG_ADDR,
+ phy_cfgs[SDHCI_CDNS6_PHY_CFG_DQS_TIMING].val);
+ sdhci_cdns6_write_phy_reg(plat, PHY_GATE_LPBK_CTRL_REG_ADDR,
+ phy_cfgs[SDHCI_CDNS6_PHY_CFG_GATE_LPBK_CTRL].val);
+ sdhci_cdns6_write_phy_reg(plat, PHY_DLL_MASTER_CTRL_REG_ADDR,
+ phy_cfgs[SDHCI_CDNS6_PHY_CFG_DLL_MASTER_CTRL].val);
+ sdhci_cdns6_write_phy_reg(plat, PHY_DLL_SLAVE_CTRL_REG_ADDR,
+ phy_cfgs[SDHCI_CDNS6_PHY_CFG_DLL_SLAVE_CTRL].val);
/* Switch Off the DLL Reset */
ret = sdhci_cdns6_reset_phy_dll(plat, false);
@@ -290,7 +319,8 @@ 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, phy_cfgs[3].val);
+ sdhci_cdns6_write_phy_reg(plat, PHY_DQ_TIMING_REG_ADDR,
+ phy_cfgs[SDHCI_CDNS6_PHY_CFG_DQ_TIMING].val);
/* Set HRS09 register */
tmp = readl(plat->hrs_addr + SDHCI_CDNS_HRS09);
@@ -298,20 +328,22 @@ 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 |= ctrl_cfgs[0].val;
+ tmp |= ctrl_cfgs[SDHCI_CDNS6_CTRL_CFG_HRS09].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 |= ctrl_cfgs[1].val;
+ tmp |= ctrl_cfgs[SDHCI_CDNS6_CTRL_CFG_HRS10].val;
writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS10);
/* Set HRS16 register */
- writel(ctrl_cfgs[2].val, plat->hrs_addr + SDHCI_CDNS_HRS16);
+ writel(ctrl_cfgs[SDHCI_CDNS6_CTRL_CFG_HRS16].val,
+ plat->hrs_addr + SDHCI_CDNS_HRS16);
/* Set HRS07 register */
- writel(ctrl_cfgs[3].val, plat->hrs_addr + SDHCI_CDNS_HRS07);
+ writel(ctrl_cfgs[SDHCI_CDNS6_CTRL_CFG_HRS07].val,
+ plat->hrs_addr + SDHCI_CDNS_HRS07);
/*
* Wait for the PHY/DLL to settle before the first data transfer.
--
2.43.7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] mmc: sdhci-cadence6: configure PHY control register per speed mode
2026-08-26 2:52 [PATCH 0/4] mmc: sdhci-cadence6: harden PHY config tables and enable Agilex5 UHS modes tze.yee.ng
2026-08-26 2:53 ` [PATCH 1/4] mmc: sdhci-cadence6: use const PHY config tables with per-call overrides tze.yee.ng
2026-08-26 2:53 ` [PATCH 2/4] mmc: sdhci-cadence6: name PHY and controller config table slots tze.yee.ng
@ 2026-08-26 2:53 ` tze.yee.ng
2026-09-12 21:06 ` Kathpalia, Tanmay
2026-08-26 2:53 ` [PATCH 4/4] arm: dts: socfpga: agilex5: add SD/eMMC UHS PHY timing tze.yee.ng
3 siblings, 1 reply; 8+ messages in thread
From: tze.yee.ng @ 2026-08-26 2:53 UTC (permalink / raw)
To: u-boot
Cc: Tanmay Kathpalia, Peng Fan, Jaehoon Chung, Tom Rini, Marek Vasut,
Simon Goldschmidt, Tien Fong Chee, Ilias Apalodimas, u-boot,
Chen Huei Lok, Alif Zakuan Yuslaimi, Dinesh Maniyam, Boon Khai Ng,
Kok Kiang Hea
From: Tze Yee Ng <tze.yee.ng@altera.com>
The PHY control register (0x2080) holds phony_dqs_timing (bits [9:4]),
which shifts the read-capture strobe relative to the data slices.
Extend the per-mode PHY configuration arrays with a "cdns,phy-ctrl-*"
entry (default 0x41F0) and program register 0x2080 during PHY
adjustment. This lets each speed mode - and each board via device tree -
select an appropriate value.
Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
---
drivers/mmc/sdhci-cadence6.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/mmc/sdhci-cadence6.c b/drivers/mmc/sdhci-cadence6.c
index 7bd47b462a4..412433ea39c 100644
--- a/drivers/mmc/sdhci-cadence6.c
+++ b/drivers/mmc/sdhci-cadence6.c
@@ -59,6 +59,8 @@
#define PHY_DLL_SLAVE_CTRL_REG_READ_DQS_CMD_DELAY GENMASK(31, 24)
#define PHY_DLL_SLAVE_CTRL_REG_READ_DQS_DELAY GENMASK(7, 0)
+/* PHY control/status register */
+#define SDHCI_CDNS6_PHY_CTRL_REG 0x2080
struct sdhci_cdns6_phy_cfg {
const char *property;
@@ -81,6 +83,7 @@ enum {
SDHCI_CDNS6_PHY_CFG_DLL_SLAVE_CTRL,
SDHCI_CDNS6_PHY_CFG_DQ_TIMING,
SDHCI_CDNS6_PHY_CFG_DLL_MASTER_CTRL,
+ SDHCI_CDNS6_PHY_CFG_CTRL,
SDHCI_CDNS6_PHY_CFG_NUM,
};
@@ -103,6 +106,7 @@ static const struct sdhci_cdns6_phy_cfg sd_ds_phy_cfgs[] = {
{ "cdns,phy-dll-slave-ctrl-sd-ds", 0x00000000, },
{ "cdns,phy-dq-timing-delay-sd-ds", 0x00000001, },
{ "cdns,phy-dll-master-ctrl-sd-ds", 0x00800004, },
+ { "cdns,phy-ctrl-sd-ds", 0x000041F0, },
};
static const struct sdhci_cdns6_phy_cfg sd_hs_phy_cfgs[] = {
@@ -111,6 +115,7 @@ static const struct sdhci_cdns6_phy_cfg sd_hs_phy_cfgs[] = {
{ "cdns,phy-dll-slave-ctrl-sd-hs", 0x00000000, },
{ "cdns,phy-dq-timing-delay-sd-hs", 0x00000001, },
{ "cdns,phy-dll-master-ctrl-sd-hs", 0x00800004, },
+ { "cdns,phy-ctrl-sd-hs", 0x000041F0, },
};
static const struct sdhci_cdns6_phy_cfg emmc_sdr_phy_cfgs[] = {
@@ -119,6 +124,7 @@ static const struct sdhci_cdns6_phy_cfg emmc_sdr_phy_cfgs[] = {
{ "cdns,phy-dll-slave-ctrl-emmc-sdr", 0x00000000, },
{ "cdns,phy-dq-timing-delay-emmc-sdr", 0x00000001, },
{ "cdns,phy-dll-master-ctrl-emmc-sdr", 0x00800004, },
+ { "cdns,phy-ctrl-emmc-sdr", 0x000041F0, },
};
static const struct sdhci_cdns6_phy_cfg emmc_ddr_phy_cfgs[] = {
@@ -127,6 +133,7 @@ static const struct sdhci_cdns6_phy_cfg emmc_ddr_phy_cfgs[] = {
{ "cdns,phy-dll-slave-ctrl-emmc-ddr", 0x00000000, },
{ "cdns,phy-dq-timing-delay-emmc-ddr", 0x10000001, },
{ "cdns,phy-dll-master-ctrl-emmc-ddr", 0x00800004, },
+ { "cdns,phy-ctrl-emmc-ddr", 0x000041F0, },
};
static const struct sdhci_cdns6_phy_cfg emmc_hs200_phy_cfgs[] = {
@@ -135,6 +142,7 @@ static const struct sdhci_cdns6_phy_cfg emmc_hs200_phy_cfgs[] = {
{ "cdns,phy-dll-slave-ctrl-emmc-hs200", 0x00DADA00, },
{ "cdns,phy-dq-timing-delay-emmc-hs200", 0x00000001, },
{ "cdns,phy-dll-master-ctrl-emmc-hs200", 0x00000004, },
+ { "cdns,phy-ctrl-emmc-hs200", 0x000041F0, },
};
static const struct sdhci_cdns6_phy_cfg emmc_hs400_phy_cfgs[] = {
@@ -143,6 +151,7 @@ static const struct sdhci_cdns6_phy_cfg emmc_hs400_phy_cfgs[] = {
{ "cdns,phy-dll-slave-ctrl-emmc-hs400", 0x00DAD800, },
{ "cdns,phy-dq-timing-delay-emmc-hs400", 0x00000001, },
{ "cdns,phy-dll-master-ctrl-emmc-hs400", 0x00000004, },
+ { "cdns,phy-ctrl-emmc-hs400", 0x000041F0, },
};
static const struct sdhci_cdns6_ctrl_cfg sd_ds_ctrl_cfgs[] = {
@@ -310,6 +319,9 @@ int sdhci_cdns6_phy_adj(struct udevice *dev, struct sdhci_cdns_plat *plat, u32 m
phy_cfgs[SDHCI_CDNS6_PHY_CFG_DLL_MASTER_CTRL].val);
sdhci_cdns6_write_phy_reg(plat, PHY_DLL_SLAVE_CTRL_REG_ADDR,
phy_cfgs[SDHCI_CDNS6_PHY_CFG_DLL_SLAVE_CTRL].val);
+ /* Program PHY CTRL register */
+ sdhci_cdns6_write_phy_reg(plat, SDHCI_CDNS6_PHY_CTRL_REG,
+ phy_cfgs[SDHCI_CDNS6_PHY_CFG_CTRL].val);
/* Switch Off the DLL Reset */
ret = sdhci_cdns6_reset_phy_dll(plat, false);
--
2.43.7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] arm: dts: socfpga: agilex5: add SD/eMMC UHS PHY timing
2026-08-26 2:52 [PATCH 0/4] mmc: sdhci-cadence6: harden PHY config tables and enable Agilex5 UHS modes tze.yee.ng
` (2 preceding siblings ...)
2026-08-26 2:53 ` [PATCH 3/4] mmc: sdhci-cadence6: configure PHY control register per speed mode tze.yee.ng
@ 2026-08-26 2:53 ` tze.yee.ng
3 siblings, 0 replies; 8+ messages in thread
From: tze.yee.ng @ 2026-08-26 2:53 UTC (permalink / raw)
To: u-boot
Cc: Tanmay Kathpalia, Peng Fan, Jaehoon Chung, Tom Rini, Marek Vasut,
Simon Goldschmidt, Tien Fong Chee, Ilias Apalodimas, u-boot,
Chen Huei Lok, Alif Zakuan Yuslaimi, Dinesh Maniyam, Boon Khai Ng,
Kok Kiang Hea
From: Tze Yee Ng <tze.yee.ng@altera.com>
Add UHS-I PHY and controller timing so SD cards and eMMC can run in the
higher speed modes on the Agilex5 SoCDK and its 013B and modular
variants:
- SoCDK: DDR50 (emmc-ddr) timing so SD cards / eMMC can run in UHS-I
DDR50 / DDR52 mode; advertise sd-uhs-ddr50 on the SD board and
mmc-ddr-1_8v on the eMMC board.
- 013B: drop no-1-8-v to allow 1.8V signalling and add SDR104
(emmc-hs200) and DDR50 (emmc-ddr) timing; advertise sd-uhs-sdr50,
sd-uhs-sdr104 and sd-uhs-ddr50.
- Modular: advertise sd-uhs-sdr50, sd-uhs-sdr104 and sd-uhs-ddr50 and
add DDR50 (emmc-ddr) timing (phony_dqs_timing = 0 re-centres the
returning data on the longer SoM SD path).
Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
---
.../arm/dts/socfpga_agilex5_socdk-u-boot.dtsi | 13 ++++++++++
.../socfpga_agilex5_socdk_013b-u-boot.dtsi | 24 +++++++++++++++++--
arch/arm/dts/socfpga_agilex5_socdk_013b.dts | 4 +++-
arch/arm/dts/socfpga_agilex5_socdk_emmc.dts | 13 ++++++++++
.../arm/dts/socfpga_agilex5_socdk_modular.dts | 20 ++++++++++++++++
5 files changed, 71 insertions(+), 3 deletions(-)
diff --git a/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi
index c03f78b2fdf..1cd54e29679 100644
--- a/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi
@@ -114,6 +114,7 @@
cap-sd-highspeed;
sd-uhs-sdr50;
sd-uhs-sdr104;
+ sd-uhs-ddr50;
vmmc-supply = <&sd_emmc_power>;
vqmmc-supply = <&sd_io_1v8_reg>;
max-frequency = <200000000>;
@@ -153,6 +154,18 @@
cdns,ctrl-hrs16-slave-ctrl-emmc-hs200 = <0x101>;
cdns,ctrl-hrs07-timing-delay-emmc-hs200 = <0xa0001>;
+ /* SD card UHS-I DDR50 mode & eMMC DDR52 mode timing configuration */
+ cdns,phy-dqs-timing-delay-emmc-ddr = <0x00580000>;
+ cdns,phy-gate-lpbk-ctrl-delay-emmc-ddr = <0x81a40040>;
+ cdns,phy-dll-master-ctrl-emmc-ddr = <0xa00004>;
+ cdns,phy-dll-slave-ctrl-emmc-ddr = <0x60>;
+ cdns,phy-ctrl-emmc-ddr = <0x4010>;
+ cdns,phy-dq-timing-delay-emmc-ddr = <0x10000001>;
+ cdns,ctrl-hrs09-timing-delay-emmc-ddr = <0xf1c1800f>;
+ cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-ddr = <0x00020000>;
+ cdns,ctrl-hrs16-slave-ctrl-emmc-ddr = <0x11000000>;
+ cdns,ctrl-hrs07-timing-delay-emmc-ddr = <0x00090001>;
+
bootph-all;
};
diff --git a/arch/arm/dts/socfpga_agilex5_socdk_013b-u-boot.dtsi b/arch/arm/dts/socfpga_agilex5_socdk_013b-u-boot.dtsi
index 75d51ef06e3..819e0ba9798 100644
--- a/arch/arm/dts/socfpga_agilex5_socdk_013b-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_agilex5_socdk_013b-u-boot.dtsi
@@ -121,14 +121,12 @@
status = "okay";
no-mmc;
- no-1-8-v;
disable-wp;
cap-sd-highspeed;
vmmc-supply = <&sd_emmc_power>;
vqmmc-supply = <&sd_io_1v8_reg>;
max-frequency = <200000000>;
sdhci-caps = <0x00000000 0x0000c800>;
- sdhci-caps-mask = <0x00002007 0x0000ff00>;
/* SD card default speed (DS) and UHS-I SDR12 mode timing configuration */
cdns,phy-dqs-timing-delay-sd-ds = <0x00780000>;
@@ -153,6 +151,28 @@
cdns,ctrl-hrs16-slave-ctrl-emmc-sdr = <0x101>;
cdns,ctrl-hrs07-timing-delay-emmc-sdr = <0x90005>;
+ /* SD card UHS-I SDR104 mode timing configuration */
+ cdns,phy-dq-timing-delay-emmc-hs200 = <0x11000001>;
+ cdns,phy-dqs-timing-delay-emmc-hs200 = <0x780004>;
+ cdns,phy-dll-slave-ctrl-emmc-hs200 = <0x4d4d00>;
+ cdns,phy-gate-lpbk-ctrl-delay-emmc-hs200 = <0x81a40040>;
+ cdns,ctrl-hrs09-timing-delay-emmc-hs200 = <0xf1c18000>;
+ cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-hs200 = <0x90000>;
+ cdns,ctrl-hrs16-slave-ctrl-emmc-hs200 = <0x101>;
+ cdns,ctrl-hrs07-timing-delay-emmc-hs200 = <0xa0001>;
+
+ /* SD card UHS-I DDR50 mode & eMMC DDR52 mode timing configuration */
+ cdns,phy-dqs-timing-delay-emmc-ddr = <0x00580000>;
+ cdns,phy-gate-lpbk-ctrl-delay-emmc-ddr = <0x81a40040>;
+ cdns,phy-dll-master-ctrl-emmc-ddr = <0xa00004>;
+ cdns,phy-dll-slave-ctrl-emmc-ddr = <0x60>;
+ cdns,phy-ctrl-emmc-ddr = <0x4010>;
+ cdns,phy-dq-timing-delay-emmc-ddr = <0x10000001>;
+ cdns,ctrl-hrs09-timing-delay-emmc-ddr = <0xf1c1800f>;
+ cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-ddr = <0x00020000>;
+ cdns,ctrl-hrs16-slave-ctrl-emmc-ddr = <0x11000000>;
+ cdns,ctrl-hrs07-timing-delay-emmc-ddr = <0x00090001>;
+
bootph-all;
};
diff --git a/arch/arm/dts/socfpga_agilex5_socdk_013b.dts b/arch/arm/dts/socfpga_agilex5_socdk_013b.dts
index 9605fa4cb00..1bec13d998e 100644
--- a/arch/arm/dts/socfpga_agilex5_socdk_013b.dts
+++ b/arch/arm/dts/socfpga_agilex5_socdk_013b.dts
@@ -90,11 +90,13 @@
&mmc {
status = "okay";
bus-width = <4>;
- no-1-8-v;
cap-sd-highspeed;
cap-mmc-highspeed;
disable-wp;
sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ sd-uhs-ddr50;
+ sdhci-caps-mask = <0x00002000 0x0000ff00>;
cdns,phy-use-ext-lpbk-dqs = <1>;
cdns,phy-use-lpbk-dqs = <1>;
cdns,phy-use-phony-dqs = <1>;
diff --git a/arch/arm/dts/socfpga_agilex5_socdk_emmc.dts b/arch/arm/dts/socfpga_agilex5_socdk_emmc.dts
index c06781064ca..6c608cfc562 100644
--- a/arch/arm/dts/socfpga_agilex5_socdk_emmc.dts
+++ b/arch/arm/dts/socfpga_agilex5_socdk_emmc.dts
@@ -25,6 +25,7 @@
disable-wp;
non-removable;
cap-mmc-highspeed;
+ mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
bus-width = <8>;
@@ -71,4 +72,16 @@
cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-hs400 = <0x80000>;
cdns,ctrl-hrs16-slave-ctrl-emmc-hs400 = <0x11000001>;
cdns,ctrl-hrs07-timing-delay-emmc-hs400 = <0x90001>;
+
+ /* SD card UHS-I DDR50 mode & eMMC DDR52 mode timing configuration */
+ cdns,phy-dqs-timing-delay-emmc-ddr = <0x00580000>;
+ cdns,phy-gate-lpbk-ctrl-delay-emmc-ddr = <0x81a40040>;
+ cdns,phy-dll-master-ctrl-emmc-ddr = <0xa00004>;
+ cdns,phy-dll-slave-ctrl-emmc-ddr = <0x60>;
+ cdns,phy-ctrl-emmc-ddr = <0x4010>;
+ cdns,phy-dq-timing-delay-emmc-ddr = <0x10000001>;
+ cdns,ctrl-hrs09-timing-delay-emmc-ddr = <0xf1c1800f>;
+ cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-ddr = <0x00020000>;
+ cdns,ctrl-hrs16-slave-ctrl-emmc-ddr = <0x11000000>;
+ cdns,ctrl-hrs07-timing-delay-emmc-ddr = <0x00090001>;
};
diff --git a/arch/arm/dts/socfpga_agilex5_socdk_modular.dts b/arch/arm/dts/socfpga_agilex5_socdk_modular.dts
index 032e40fc639..30a5a749d1d 100644
--- a/arch/arm/dts/socfpga_agilex5_socdk_modular.dts
+++ b/arch/arm/dts/socfpga_agilex5_socdk_modular.dts
@@ -33,6 +33,9 @@
no-mmc;
disable-wp;
cap-sd-highspeed;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ sd-uhs-ddr50;
vmmc-supply = <&sd_emmc_power>;
vqmmc-supply = <&sd_io_1v8_reg>;
max-frequency = <200000000>;
@@ -71,5 +74,22 @@
cdns,ctrl-hrs16-slave-ctrl-emmc-hs200 = <0x101>;
cdns,ctrl-hrs07-timing-delay-emmc-hs200 = <0xa0001>;
+ /* SD card UHS-I DDR50 mode & eMMC DDR52 mode timing configuration */
+ cdns,phy-dqs-timing-delay-emmc-ddr = <0x00580000>;
+ cdns,phy-gate-lpbk-ctrl-delay-emmc-ddr = <0x81a40040>;
+ cdns,phy-dll-master-ctrl-emmc-ddr = <0xa00004>;
+ cdns,phy-dll-slave-ctrl-emmc-ddr = <0x60>;
+ /*
+ * Modular SoM: PHONY_DQS_TIMING (PHY_CTRL[9:4]) = 0 instead of the
+ * default 1. The longer SD path offsets the returning DDR data from the
+ * phony strobe; re-centring it stops one DDR beat collapsing onto both.
+ */
+ cdns,phy-ctrl-emmc-ddr = <0x4000>;
+ cdns,phy-dq-timing-delay-emmc-ddr = <0x10000001>;
+ cdns,ctrl-hrs09-timing-delay-emmc-ddr = <0xf1c1800f>;
+ cdns,ctrl-hrs10-lpbk-ctrl-delay-emmc-ddr = <0x00020000>;
+ cdns,ctrl-hrs16-slave-ctrl-emmc-ddr = <0x11000000>;
+ cdns,ctrl-hrs07-timing-delay-emmc-ddr = <0x00090001>;
+
bootph-all;
};
--
2.43.7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/4] mmc: sdhci-cadence6: use const PHY config tables with per-call overrides
2026-08-26 2:53 ` [PATCH 1/4] mmc: sdhci-cadence6: use const PHY config tables with per-call overrides tze.yee.ng
@ 2026-09-12 20:26 ` Kathpalia, Tanmay
0 siblings, 0 replies; 8+ messages in thread
From: Kathpalia, Tanmay @ 2026-09-12 20:26 UTC (permalink / raw)
To: tze.yee.ng, u-boot
Cc: Peng Fan, Jaehoon Chung, Tom Rini, Marek Vasut, Simon Goldschmidt,
Tien Fong Chee, Ilias Apalodimas, u-boot, Chen Huei Lok,
Alif Zakuan Yuslaimi, Dinesh Maniyam, Boon Khai Ng, Kok Kiang Hea
On 26-08-2026 08:23, tze.yee.ng@altera.com wrote:
> From: Tze Yee Ng <tze.yee.ng@altera.com>
>
> 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 <tze.yee.ng@altera.com>
This patch does not apply on current main. Please rebase and resend.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/4] mmc: sdhci-cadence6: name PHY and controller config table slots
2026-08-26 2:53 ` [PATCH 2/4] mmc: sdhci-cadence6: name PHY and controller config table slots tze.yee.ng
@ 2026-09-12 20:36 ` Kathpalia, Tanmay
0 siblings, 0 replies; 8+ messages in thread
From: Kathpalia, Tanmay @ 2026-09-12 20:36 UTC (permalink / raw)
To: tze.yee.ng, u-boot
Cc: Peng Fan, Jaehoon Chung, Tom Rini, Marek Vasut, Simon Goldschmidt,
Tien Fong Chee, Ilias Apalodimas, u-boot, Chen Huei Lok,
Alif Zakuan Yuslaimi, Dinesh Maniyam, Boon Khai Ng, Kok Kiang Hea
On 26-08-2026 08:23, tze.yee.ng@altera.com wrote:
> From: Tze Yee Ng <tze.yee.ng@altera.com>
>
> sdhci_cdns6_phy_adj() programs the PHY and HRS controller registers by
> indexing the *_phy_cfgs[] and *_ctrl_cfgs[] tables with bare positional
> constants. This is fragile: reordering or inserting a table entry
> silently changes which register each slot programs.
>
> Introduce enums that name every PHY and controller configuration slot,
> whose terminators double as the table sizes (SDHCI_CDNS6_PHY_CFG_NUM and
> SDHCI_CDNS6_CTRL_CFG_NUM), and use those names when programming the
> registers. No functional change.
>
> Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
> ---
> drivers/mmc/sdhci-cadence6.c | 54 ++++++++++++++++++++++++++++--------
> 1 file changed, 43 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/mmc/sdhci-cadence6.c b/drivers/mmc/sdhci-cadence6.c
> index 1ff974ecd44..7bd47b462a4 100644
> --- a/drivers/mmc/sdhci-cadence6.c
> +++ b/drivers/mmc/sdhci-cadence6.c
> @@ -59,8 +59,6 @@
> #define PHY_DLL_SLAVE_CTRL_REG_READ_DQS_CMD_DELAY GENMASK(31, 24)
> #define PHY_DLL_SLAVE_CTRL_REG_READ_DQS_DELAY GENMASK(7, 0)
>
> -#define SDHCI_CDNS6_PHY_CFG_NUM 5
> -#define SDHCI_CDNS6_CTRL_CFG_NUM 4
>
Dropping the two size macros leaves a double blank line.
> struct sdhci_cdns6_phy_cfg {
> const char *property;
> @@ -72,6 +70,33 @@ struct sdhci_cdns6_ctrl_cfg {
> u32 val;
> };
>
> +/*
> + * PHY configuration slots. The enumeration order must match the entry
> + * order in every *_phy_cfgs[] table; SDHCI_CDNS6_PHY_CFG_NUM tracks the
> + * table size so the two never drift out of sync.
> + */
> +enum {
> + SDHCI_CDNS6_PHY_CFG_DQS_TIMING,
> + SDHCI_CDNS6_PHY_CFG_GATE_LPBK_CTRL,
> + SDHCI_CDNS6_PHY_CFG_DLL_SLAVE_CTRL,
> + SDHCI_CDNS6_PHY_CFG_DQ_TIMING,
> + SDHCI_CDNS6_PHY_CFG_DLL_MASTER_CTRL,
> + SDHCI_CDNS6_PHY_CFG_NUM,
> +};
> +
> +/*
> + * Controller (HRS) configuration slots. The enumeration order must match
> + * the entry order in every *_ctrl_cfgs[] table; SDHCI_CDNS6_CTRL_CFG_NUM
> + * tracks the table size so the two never drift out of sync.
> + */
> +enum {
> + SDHCI_CDNS6_CTRL_CFG_HRS09,
> + SDHCI_CDNS6_CTRL_CFG_HRS10,
> + SDHCI_CDNS6_CTRL_CFG_HRS16,
> + SDHCI_CDNS6_CTRL_CFG_HRS07,
> + SDHCI_CDNS6_CTRL_CFG_NUM,
> +};
> +
> 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, },
> @@ -277,10 +302,14 @@ int sdhci_cdns6_phy_adj(struct udevice *dev, struct sdhci_cdns_plat *plat, u32 m
> /* Switch On the DLL Reset */
> sdhci_cdns6_reset_phy_dll(plat, true);
>
> - 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);
> + sdhci_cdns6_write_phy_reg(plat, PHY_DQS_TIMING_REG_ADDR,
> + phy_cfgs[SDHCI_CDNS6_PHY_CFG_DQS_TIMING].val);
> + sdhci_cdns6_write_phy_reg(plat, PHY_GATE_LPBK_CTRL_REG_ADDR,
> + phy_cfgs[SDHCI_CDNS6_PHY_CFG_GATE_LPBK_CTRL].val);
> + sdhci_cdns6_write_phy_reg(plat, PHY_DLL_MASTER_CTRL_REG_ADDR,
> + phy_cfgs[SDHCI_CDNS6_PHY_CFG_DLL_MASTER_CTRL].val);
> + sdhci_cdns6_write_phy_reg(plat, PHY_DLL_SLAVE_CTRL_REG_ADDR,
> + phy_cfgs[SDHCI_CDNS6_PHY_CFG_DLL_SLAVE_CTRL].val);
>
> /* Switch Off the DLL Reset */
> ret = sdhci_cdns6_reset_phy_dll(plat, false);
> @@ -290,7 +319,8 @@ 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, phy_cfgs[3].val);
> + sdhci_cdns6_write_phy_reg(plat, PHY_DQ_TIMING_REG_ADDR,
> + phy_cfgs[SDHCI_CDNS6_PHY_CFG_DQ_TIMING].val);
>
> /* Set HRS09 register */
> tmp = readl(plat->hrs_addr + SDHCI_CDNS_HRS09);
> @@ -298,20 +328,22 @@ 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 |= ctrl_cfgs[0].val;
> + tmp |= ctrl_cfgs[SDHCI_CDNS6_CTRL_CFG_HRS09].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 |= ctrl_cfgs[1].val;
> + tmp |= ctrl_cfgs[SDHCI_CDNS6_CTRL_CFG_HRS10].val;
> writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS10);
>
> /* Set HRS16 register */
> - writel(ctrl_cfgs[2].val, plat->hrs_addr + SDHCI_CDNS_HRS16);
> + writel(ctrl_cfgs[SDHCI_CDNS6_CTRL_CFG_HRS16].val,
> + plat->hrs_addr + SDHCI_CDNS_HRS16);
>
> /* Set HRS07 register */
> - writel(ctrl_cfgs[3].val, plat->hrs_addr + SDHCI_CDNS_HRS07);
> + writel(ctrl_cfgs[SDHCI_CDNS6_CTRL_CFG_HRS07].val,
> + plat->hrs_addr + SDHCI_CDNS_HRS07);
>
> /*
> * Wait for the PHY/DLL to settle before the first data transfer.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 3/4] mmc: sdhci-cadence6: configure PHY control register per speed mode
2026-08-26 2:53 ` [PATCH 3/4] mmc: sdhci-cadence6: configure PHY control register per speed mode tze.yee.ng
@ 2026-09-12 21:06 ` Kathpalia, Tanmay
0 siblings, 0 replies; 8+ messages in thread
From: Kathpalia, Tanmay @ 2026-09-12 21:06 UTC (permalink / raw)
To: tze.yee.ng, u-boot
Cc: Peng Fan, Jaehoon Chung, Tom Rini, Marek Vasut, Simon Goldschmidt,
Tien Fong Chee, Ilias Apalodimas, u-boot, Chen Huei Lok,
Alif Zakuan Yuslaimi, Dinesh Maniyam, Boon Khai Ng, Kok Kiang Hea
Hi Tze,
On 26-08-2026 08:23, tze.yee.ng@altera.com wrote:
> From: Tze Yee Ng <tze.yee.ng@altera.com>
>
> The PHY control register (0x2080) holds phony_dqs_timing (bits [9:4]),
> which shifts the read-capture strobe relative to the data slices.
>
> Extend the per-mode PHY configuration arrays with a "cdns,phy-ctrl-*"
> entry (default 0x41F0) and program register 0x2080 during PHY
> adjustment. This lets each speed mode - and each board via device tree -
> select an appropriate value.
>
> Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
> ---
The PHY_CTRL default needs to be corrected. All six tables also use the
same 0x41F0, so this is not actually per-mode.
Please fix the defaults.
Regards,
Tanmay
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-12 21:07 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-26 2:52 [PATCH 0/4] mmc: sdhci-cadence6: harden PHY config tables and enable Agilex5 UHS modes tze.yee.ng
2026-08-26 2:53 ` [PATCH 1/4] mmc: sdhci-cadence6: use const PHY config tables with per-call overrides tze.yee.ng
2026-09-12 20:26 ` Kathpalia, Tanmay
2026-08-26 2:53 ` [PATCH 2/4] mmc: sdhci-cadence6: name PHY and controller config table slots tze.yee.ng
2026-09-12 20:36 ` Kathpalia, Tanmay
2026-08-26 2:53 ` [PATCH 3/4] mmc: sdhci-cadence6: configure PHY control register per speed mode tze.yee.ng
2026-09-12 21:06 ` Kathpalia, Tanmay
2026-08-26 2:53 ` [PATCH 4/4] arm: dts: socfpga: agilex5: add SD/eMMC UHS PHY timing tze.yee.ng
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.