* [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; 13+ 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] 13+ 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
2026-09-21 3:39 ` NG, TZE YEE
0 siblings, 1 reply; 13+ 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] 13+ messages in thread
* Re: [PATCH 1/4] mmc: sdhci-cadence6: use const PHY config tables with per-call overrides
2026-09-12 20:26 ` Kathpalia, Tanmay
@ 2026-09-21 3:39 ` NG, TZE YEE
0 siblings, 0 replies; 13+ messages in thread
From: NG, TZE YEE @ 2026-09-21 3:39 UTC (permalink / raw)
To: Kathpalia, Tanmay, 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 13/9/2026 4:26 am, Kathpalia, Tanmay wrote:
>
> 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.
Hi Tanmay,
Thanks for review. I will rebase on current main and submit as v2.
^ permalink raw reply [flat|nested] 13+ 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; 13+ 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] 13+ 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
2026-09-21 3:40 ` NG, TZE YEE
0 siblings, 1 reply; 13+ 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] 13+ messages in thread* Re: [PATCH 2/4] mmc: sdhci-cadence6: name PHY and controller config table slots
2026-09-12 20:36 ` Kathpalia, Tanmay
@ 2026-09-21 3:40 ` NG, TZE YEE
0 siblings, 0 replies; 13+ messages in thread
From: NG, TZE YEE @ 2026-09-21 3:40 UTC (permalink / raw)
To: Kathpalia, Tanmay, 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 13/9/2026 4:36 am, Kathpalia, Tanmay wrote:
>
> 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.
Hi Tanmay,
I will drop the blank line in v2.
Thanks,
Tze Yee
>
>> 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] 13+ 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; 13+ 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] 13+ 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
2026-09-21 3:50 ` NG, TZE YEE
0 siblings, 1 reply; 13+ 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] 13+ messages in thread
* Re: [PATCH 3/4] mmc: sdhci-cadence6: configure PHY control register per speed mode
2026-09-12 21:06 ` Kathpalia, Tanmay
@ 2026-09-21 3:50 ` NG, TZE YEE
2026-10-03 18:53 ` Kathpalia, Tanmay
0 siblings, 1 reply; 13+ messages in thread
From: NG, TZE YEE @ 2026-09-21 3:50 UTC (permalink / raw)
To: Kathpalia, Tanmay, 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 13/9/2026 5:06 am, Kathpalia, Tanmay wrote:
> 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
Hi Tanmay,
0x41F0 is the PHY_CTRL (0x2080) reset value from the PHY spec. The
driver never wrote this register before, so the PHY already ran at
0x41F0 in every mode. Using it as the default in all six tables just
preserves that (the write is a no-op unless overridden), while making
the register tunable per mode/board via cdns,phy-ctrl-<mode> in DT, e.g.
on Agilex5:
013b: cdns,phy-ctrl-emmc-ddr = <0x4010>; (phony_dqs_timing = 1)
modular: cdns,phy-ctrl-emmc-ddr = <0x4000>; (phony_dqs_timing = 0)
So the defaults match only because the reset value is mode-independent;
the real tuning lives in DT. You're right that six bare 0x41F0 literals
are misleading. For v3 I'll add a named constant
(SDHCI_CDNS6_PHY_CTRL_REG_DEFAULT = 0x000041F0) for the default and
reword the commit to say the register is made programmable with the
reset value as default (no functional change), overridable per
mode/board via DT.
Does that work for you, or did you expect distinct per-mode defaults? I
don't have validated per-mode values, that tuning is meant to live in DT.
Thanks,
Tze Yee
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/4] mmc: sdhci-cadence6: configure PHY control register per speed mode
2026-09-21 3:50 ` NG, TZE YEE
@ 2026-10-03 18:53 ` Kathpalia, Tanmay
2026-10-05 8:06 ` NG, TZE YEE
0 siblings, 1 reply; 13+ messages in thread
From: Kathpalia, Tanmay @ 2026-10-03 18:53 UTC (permalink / raw)
To: NG, TZE YEE, 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 21-09-2026 09:20, NG, TZE YEE wrote:
>
>
> On 13/9/2026 5:06 am, Kathpalia, Tanmay wrote:
>> 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
>
> Hi Tanmay,
>
> 0x41F0 is the PHY_CTRL (0x2080) reset value from the PHY spec. The
> driver never wrote this register before, so the PHY already ran at
> 0x41F0 in every mode. Using it as the default in all six tables just
> preserves that (the write is a no-op unless overridden), while making
> the register tunable per mode/board via cdns,phy-ctrl-<mode> in DT,
> e.g. on Agilex5:
>
> 013b: cdns,phy-ctrl-emmc-ddr = <0x4010>; (phony_dqs_timing = 1)
> modular: cdns,phy-ctrl-emmc-ddr = <0x4000>; (phony_dqs_timing = 0)
>
>
> So the defaults match only because the reset value is mode-independent;
> the real tuning lives in DT. You're right that six bare 0x41F0
> literals are misleading. For v3 I'll add a named constant
> (SDHCI_CDNS6_PHY_CTRL_REG_DEFAULT = 0x000041F0) for the default and
> reword the commit to say the register is made programmable with the
> reset value as default (no functional change), overridable per
> mode/board via DT.
>
> Does that work for you, or did you expect distinct per-mode defaults? I
> don't have validated per-mode values, that tuning is meant to live in DT.
>
>
I expect mode-specific, validated defaults, consistent with the other
PHY configuration values in each mode table.
Please determine the appropriate default for each speed mode rather
than using 0x41F0 universally. Board-specific DT values may still
override those defaults where required.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/4] mmc: sdhci-cadence6: configure PHY control register per speed mode
2026-10-03 18:53 ` Kathpalia, Tanmay
@ 2026-10-05 8:06 ` NG, TZE YEE
0 siblings, 0 replies; 13+ messages in thread
From: NG, TZE YEE @ 2026-10-05 8:06 UTC (permalink / raw)
To: Kathpalia, Tanmay, 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 4/10/2026 2:53 am, Kathpalia, Tanmay wrote:
>
> On 21-09-2026 09:20, NG, TZE YEE wrote:
>>
>>
>> On 13/9/2026 5:06 am, Kathpalia, Tanmay wrote:
>>> 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
>>
>> Hi Tanmay,
>>
>> 0x41F0 is the PHY_CTRL (0x2080) reset value from the PHY spec. The
>> driver never wrote this register before, so the PHY already ran at
>> 0x41F0 in every mode. Using it as the default in all six tables just
>> preserves that (the write is a no-op unless overridden), while making
>> the register tunable per mode/board via cdns,phy-ctrl-<mode> in DT,
>> e.g. on Agilex5:
>>
>> 013b: cdns,phy-ctrl-emmc-ddr = <0x4010>; (phony_dqs_timing = 1)
>> modular: cdns,phy-ctrl-emmc-ddr = <0x4000>; (phony_dqs_timing = 0)
>>
>>
>> So the defaults match only because the reset value is mode-independent;
>> the real tuning lives in DT. You're right that six bare 0x41F0
>> literals are misleading. For v3 I'll add a named constant
>> (SDHCI_CDNS6_PHY_CTRL_REG_DEFAULT = 0x000041F0) for the default and
>> reword the commit to say the register is made programmable with the
>> reset value as default (no functional change), overridable per mode/
>> board via DT.
>>
>> Does that work for you, or did you expect distinct per-mode defaults? I
>> don't have validated per-mode values, that tuning is meant to live in DT.
>>
>>
>
> I expect mode-specific, validated defaults, consistent with the other
> PHY configuration values in each mode table.
> Please determine the appropriate default for each speed mode rather
> than using 0x41F0 universally. Board-specific DT values may still
> override those defaults where required.
Hi Tanmay,
For v3, I'll drop the universal 0x41F0 and the per-mode cdns,phy-ctrl
table entirely. The PHY_CTRL reset value already works for the SD/eMMC
SDR and HS modes, so there are no per-mode defaults to validate there,
the driver simply leaves PHY_CTRL untouched in those modes.
Only the DDR read path is sensitive to phony_dqs_timing, so the driver
programs it just for DDR50/DDR52 via a single mode-neutral property,
cdns,ddr-phony-dqs-timing (shared by SD DDR50 and eMMC DDR52). It
defaults to 0 (the neutral assertion timing) and a board whose DDR read
path needs tuning sets it explicitly: SoCDK, eMMC and 013B use 1, while
the modular SoM's longer SD path uses the default 0.
The binding goes through Linux (its canonical home), currently under
review:
https://lore.kernel.org/all/25649477d9967bb04b12c6e60b0ee76443f356af.1790074790.git.tze.yee.ng@altera.com/
I've adopted the cdns,ddr-* naming you recommended there, so the U-Boot
property matches the binding.
Let me know if you see it differently.
Thanks,
Tze Yee
^ permalink raw reply [flat|nested] 13+ 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; 13+ 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] 13+ messages in thread