* [PATCH v2 0/4] mmc: sdhci-cadence: SD6HC DDR50/DDR52 read-path tuning and fixes
@ 2026-10-09 2:14 tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 1/4] mmc: sdhci-cadence: add PHY settle after tuning for SD6HC tze.yee.ng
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: tze.yee.ng @ 2026-10-09 2:14 UTC (permalink / raw)
To: Tanmay Kathpalia, Adrian Hunter, linux-mmc, linux-kernel,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
From: Tze Yee Ng <tze.yee.ng@altera.com>
This series enables the extended-read DDR modes - SD DDR50 and eMMC
DDR52 - on the Cadence SD6HC (SD/eMMC v6) PHY. Neither mode runs a host
tuning sequence (CMD19/CMD21), so the read path must be centred by
static, board/SoC-characterised PHY settings. Bringing it up on Agilex5
also exposed PHY issues affecting the existing tuned modes.
- Patch 1: settle the PHY once after the final tuning tap, before the
first post-tuning command (an R1b CMD6 during HS400 selection can
otherwise time out); matches sdhci_cdns6_phy_init().
- Patch 2: program PHONY_DQS_TIMING (left 0 in all modes); in the
extended-read DDR modes it must be the rebar pulse width in clk_phy
cycles minus 1, else one DDR beat is duplicated.
- Patch 3: document three optional SD6HC read-path properties for the
extended-read DDR modes (SD DDR50, eMMC DDR52).
- Patch 4: read those properties at probe and apply them in DDR50 and
DDR52, and make the DQS_TIMING update clear USE_LPBK_DQS before
reprogramming it so the loopback/phony selection takes effect.
The new cdns,ddr-* properties are unused in this series; they will be
consumed by the socfpga_agilex5_socdk and socfpga_agilex5_socdk_emmc
device trees, submitted as a separate series.
Tested on Agilex5 SoCDK: SD DDR50 and eMMC DDR52.
Changes in v2:
- Patch 1: moved the 5 ms PHY settle out of the per-tap tuning loop to
a single settle after the winning tap, on the success path only, and
rewrote the comment to explain this specific call site. (Adrian
Hunter, Tanmay Kathpalia)
- Patch 2: added Adrian's Acked-by; reworded the commit message to drop
the "generic to any SD6HC-PHY SoC" framing. (Adrian Hunter)
- Patch 3: retitled to "dt-bindings: mmc: cdns,sd6hc:"; renamed
cdns,ddr50-* -> cdns,ddr-*; cdns,ddr-read-dqs-delay-ps is now in
picoseconds; replaced the read-DQS source selector with a
cdns,ddr-no-lpbk-dqs boolean; reworded the phony-dqs-timing text;
dropped the SD4HC note. (Krzysztof Kozlowski, Tanmay Kathpalia)
- Patch 4: renamed the properties to cdns,ddr-*; read
cdns,ddr-read-dqs-delay-ps in ps and convert it to delay elements
(dividing by cdns,delay-element-ps), clamping that quotient to the
8-bit PHY field so a small delay element cannot make it wrap; read
cdns,ddr-no-lpbk-dqs via of_property_read_bool() to opt out of the
default loopback DQS read path; dropped the v1 per-property range
checks and redundant FIELD_MAX() write masks; apply the overrides in
both DDR50 and DDR52. Also retitled to "mmc: sdhci-cadence6:" since it
touches only the v6 PHY. (Krzysztof Kozlowski, Adrian Hunter,
Tanmay Kathpalia)
Tze Yee Ng (4):
mmc: sdhci-cadence: add PHY settle after tuning for SD6HC
mmc: sdhci-cadence6: program PHONY_DQS_TIMING for extended-read DDR
dt-bindings: mmc: cdns,sd6hc: add SD6HC DDR50 read-path tuning
mmc: sdhci-cadence6: read SD6HC DDR50 tuning from device tree
.../devicetree/bindings/mmc/cdns,sd6hc.yaml | 30 ++++++++
drivers/mmc/host/sdhci-cadence-core.c | 6 +-
drivers/mmc/host/sdhci-cadence-phy-v6.c | 74 ++++++++++++++++++-
3 files changed, 108 insertions(+), 2 deletions(-)
base-commit: 2d2431cf24dda7303d59e47b7d116be8beda66b1
--
2.43.7
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/4] mmc: sdhci-cadence: add PHY settle after tuning for SD6HC
2026-10-09 2:14 [PATCH v2 0/4] mmc: sdhci-cadence: SD6HC DDR50/DDR52 read-path tuning and fixes tze.yee.ng
@ 2026-10-09 2:14 ` tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 2/4] mmc: sdhci-cadence6: program PHONY_DQS_TIMING for extended-read DDR tze.yee.ng
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: tze.yee.ng @ 2026-10-09 2:14 UTC (permalink / raw)
To: Tanmay Kathpalia, Adrian Hunter, linux-mmc, linux-kernel,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
From: Tze Yee Ng <tze.yee.ng@altera.com>
On SD6HC the first command after tuning may be an R1b busy command (e.g.
the HS200->HS CMD6 during HS400 selection) that can time out on some eMMC
unless the PHY is given a brief settle after the final tap and DLL
re-lock.
Add a single 5 to 5.5 ms settle at the end of the SD6HC tuning path,
after the winning tap is applied, rather than on every set_tune_val()
call in the scan.
Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
---
Changes in v2:
- Moved the 5ms PHY settle out of the per-tap tuning loop to a single
settle after the winning tap, on the success path only.
(Adrian Hunter, Tanmay Kathpalia)
- Rewrote the comment to explain this specific call site.
(Tanmay Kathpalia)
---
drivers/mmc/host/sdhci-cadence-core.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci-cadence-core.c b/drivers/mmc/host/sdhci-cadence-core.c
index 745455743b01..c25b235ee909 100644
--- a/drivers/mmc/host/sdhci-cadence-core.c
+++ b/drivers/mmc/host/sdhci-cadence-core.c
@@ -7,6 +7,7 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/iopoll.h>
#include <linux/module.h>
@@ -352,8 +353,11 @@ static int sdhci_cdns_execute_tuning(struct sdhci_host *host, u32 opcode)
return ret;
/* Block gap tuning is only required for SD4HC, not for SD6HC */
- if (host->version >= SDHCI_SPEC_420)
+ if (host->version >= SDHCI_SPEC_420) {
+ /* Let the PHY settle after the final tap and DLL re-lock. */
+ usleep_range(5000, 5500);
return 0;
+ }
return sdhci_cdns_tune_blkgap(host->mmc);
}
--
2.43.7
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/4] mmc: sdhci-cadence6: program PHONY_DQS_TIMING for extended-read DDR
2026-10-09 2:14 [PATCH v2 0/4] mmc: sdhci-cadence: SD6HC DDR50/DDR52 read-path tuning and fixes tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 1/4] mmc: sdhci-cadence: add PHY settle after tuning for SD6HC tze.yee.ng
@ 2026-10-09 2:14 ` tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 3/4] dt-bindings: mmc: cdns,sd6hc: add SD6HC DDR50 read-path tuning tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 4/4] mmc: sdhci-cadence6: read SD6HC DDR50 tuning from device tree tze.yee.ng
3 siblings, 0 replies; 6+ messages in thread
From: tze.yee.ng @ 2026-10-09 2:14 UTC (permalink / raw)
To: Tanmay Kathpalia, Adrian Hunter, linux-mmc, linux-kernel,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
From: Tze Yee Ng <tze.yee.ng@altera.com>
The SD6HC PHY left PHONY_DQS_TIMING (phy_ctrl_reg[9:4]) at 0 in all
modes. Per the Cadence DLL PHY documentation it must be the rebar (RE#)
pulse width in clk_phy cycles minus 1 in extended read mode, and 0
otherwise. Leaving it 0 in extended-read DDR duplicates one DDR edge
(the silent odd/even edge-capture defect).
On this integration the rebar pulse is 2 clk_phy cycles, so extended-
read DDR needs 1; confirmed on DDR50 hardware (1 captures both beats, 2
corrupts reads). Derive it from the extended-read-mode state and apply
it only in DDR modes, since SDR extended-read samples a single edge and
is unaffected.
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
---
Changes in v2:
- Added Adrian's Acked-by.
- Reworded the commit message to drop the "generic to any SD6HC-PHY SoC"
framing. (Adrian Hunter)
---
drivers/mmc/host/sdhci-cadence-phy-v6.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/mmc/host/sdhci-cadence-phy-v6.c b/drivers/mmc/host/sdhci-cadence-phy-v6.c
index 22d56bb46d75..8d6a9c26c139 100644
--- a/drivers/mmc/host/sdhci-cadence-phy-v6.c
+++ b/drivers/mmc/host/sdhci-cadence-phy-v6.c
@@ -90,6 +90,9 @@
#define SDHCI_CDNS6_PHY_CTRL_REG 0x2080
#define SDHCI_CDNS6_PHY_CTRL_PHONY_DQS_TIMING GENMASK(9, 4)
+/* Width of this controller's rebar (RE#) pulse in clk_phy cycles. */
+#define SDHCI_CDNS6_PHY_REBAR_PULSE_CYCLES 2
+
/* Default PHY settings */
#define SDHCI_CDNS6_PHY_DEFAULT_IOCELL_DELAY 2500
#define SDHCI_CDNS6_PHY_DEFAULT_DELAY_ELEMENT 24
@@ -143,6 +146,9 @@ struct sdhci_cdns6_phy {
bool cp_use_phony_dqs; /* bit [20] */
bool cp_use_phony_dqs_cmd; /* bit [19] */
+ /* PHY_CTRL register fields */
+ u32 cp_phony_dqs_timing;
+
/* HRS07 register - IO delay Information */
u8 sdhc_rw_compensate; /* bits [20:16] */
u8 sdhc_idelay_val; /* bits [4:0] */
@@ -517,6 +523,13 @@ static void sdhci_cdns6_phy_calc_dat_in(struct sdhci_cdns6_phy *phy)
if (phy->mode == MMC_TIMING_MMC_HS200)
phy->cp_read_dqs_delay = phy->hs200_tune_val;
+ if (phy->sdhc_extended_rd_mode &&
+ (phy->mode == MMC_TIMING_UHS_DDR50 ||
+ phy->mode == MMC_TIMING_MMC_DDR52))
+ phy->cp_phony_dqs_timing = SDHCI_CDNS6_PHY_REBAR_PULSE_CYCLES - 1;
+ else
+ phy->cp_phony_dqs_timing = 0;
+
if (strobe_dat) {
/* dqs loopback input via IO cell */
hcsdclkadj += phy->iocell_input_delay;
@@ -715,6 +728,8 @@ int sdhci_cdns6_phy_init(struct sdhci_cdns_priv *priv)
reg = sdhci_cdns6_read_phy_reg(priv, SDHCI_CDNS6_PHY_CTRL_REG);
reg &= ~SDHCI_CDNS6_PHY_CTRL_PHONY_DQS_TIMING;
+ reg |= FIELD_PREP(SDHCI_CDNS6_PHY_CTRL_PHONY_DQS_TIMING,
+ phy->cp_phony_dqs_timing);
sdhci_cdns6_write_phy_reg(priv, SDHCI_CDNS6_PHY_CTRL_REG, reg);
/*
--
2.43.7
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/4] dt-bindings: mmc: cdns,sd6hc: add SD6HC DDR50 read-path tuning
2026-10-09 2:14 [PATCH v2 0/4] mmc: sdhci-cadence: SD6HC DDR50/DDR52 read-path tuning and fixes tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 1/4] mmc: sdhci-cadence: add PHY settle after tuning for SD6HC tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 2/4] mmc: sdhci-cadence6: program PHONY_DQS_TIMING for extended-read DDR tze.yee.ng
@ 2026-10-09 2:14 ` tze.yee.ng
2026-10-12 8:48 ` Krzysztof Kozlowski
2026-10-09 2:14 ` [PATCH v2 4/4] mmc: sdhci-cadence6: read SD6HC DDR50 tuning from device tree tze.yee.ng
3 siblings, 1 reply; 6+ messages in thread
From: tze.yee.ng @ 2026-10-09 2:14 UTC (permalink / raw)
To: Tanmay Kathpalia, Adrian Hunter, linux-mmc, linux-kernel,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
From: Tze Yee Ng <tze.yee.ng@altera.com>
DDR50 has no CMD19 tuning, so the SD6HC read path must be centred by
static, board/SoC-characterised PHY settings. Add three optional SD6HC
properties for the extended-read DDR modes (SD DDR50 and eMMC DDR52):
- cdns,ddr-read-dqs-delay-ps: read-DQS delay in picoseconds that centres
the read eye (default 0).
- cdns,ddr-no-lpbk-dqs: disable the loopback DQS read strobe and
use the fabricated phony DQS instead. Loopback DQS is the recommended
default; set this only on boards that need the phony DQS read path.
- cdns,ddr-phony-dqs-timing: PHY_CTRL[9:4] phony DQS assertion timing.
The driver derives this from the RE# pulse width; this property
overrides the computed value for boards whose flight time shifts the
DDR data return.
Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
---
Changes in v2:
- Retitled to "dt-bindings: mmc: cdns,sd6hc:". (Tanmay Kathpalia)
- Renamed cdns,ddr50-* -> cdns,ddr-*. (Tanmay Kathpalia)
- cdns,ddr-read-dqs-delay-ps is now in picoseconds. (Krzysztof Kozlowski)
- Replaced the read-DQS source selector with a cdns,ddr-no-lpbk-dqs
boolean. (Krzysztof Kozlowski)
- Reworded the phony-dqs-timing text. (Krzysztof Kozlowski,
Tanmay Kathpalia)
- Dropped the SD4HC note. (Tanmay Kathpalia)
- Scope the new properties to the extended-read DDR modes (DDR50 and
DDR52). (Tanmay Kathpalia)
---
.../devicetree/bindings/mmc/cdns,sd6hc.yaml | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/Documentation/devicetree/bindings/mmc/cdns,sd6hc.yaml b/Documentation/devicetree/bindings/mmc/cdns,sd6hc.yaml
index d5ea2717904b..911ce58f8dab 100644
--- a/Documentation/devicetree/bindings/mmc/cdns,sd6hc.yaml
+++ b/Documentation/devicetree/bindings/mmc/cdns,sd6hc.yaml
@@ -74,6 +74,36 @@ properties:
maximum: 1000
default: 24
+ cdns,ddr-read-dqs-delay-ps:
+ description: >
+ Read-DQS delay (DLL_SLAVE[7:0]) in picoseconds that centres the read
+ eye in the extended-read DDR modes (SD DDR50, eMMC DDR52), which have
+ no CMD19 tuning. The PHY runs the DLL bypassed in these modes, so the
+ driver converts this to delay elements (divided by
+ cdns,delay-element-ps). The 8-bit field holds at most 255 elements;
+ larger values are clamped to that limit.
+ minimum: 0
+ default: 0
+
+ cdns,ddr-no-lpbk-dqs:
+ description: >
+ Disable the loopback DQS read strobe and use the fabricated (phony)
+ DQS instead in the extended-read DDR modes (SD DDR50, eMMC DDR52).
+ Loopback DQS is the recommended default; set this only on boards that
+ require the phony DQS read path.
+ type: boolean
+
+ cdns,ddr-phony-dqs-timing:
+ description: >
+ Phony DQS assertion timing (PHY_CTRL[9:4]) for the extended-read DDR
+ modes (SD DDR50, eMMC DDR52). The driver computes this from the RE#
+ pulse width per the Cadence PHY guide; set it only to override that
+ value on boards whose DDR data returns shifted (e.g. longer flight
+ time on modular/SoM layouts). If absent, the computed value is used.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 0x3f
+
required:
- compatible
- reg
--
2.43.7
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 4/4] mmc: sdhci-cadence6: read SD6HC DDR50 tuning from device tree
2026-10-09 2:14 [PATCH v2 0/4] mmc: sdhci-cadence: SD6HC DDR50/DDR52 read-path tuning and fixes tze.yee.ng
` (2 preceding siblings ...)
2026-10-09 2:14 ` [PATCH v2 3/4] dt-bindings: mmc: cdns,sd6hc: add SD6HC DDR50 read-path tuning tze.yee.ng
@ 2026-10-09 2:14 ` tze.yee.ng
3 siblings, 0 replies; 6+ messages in thread
From: tze.yee.ng @ 2026-10-09 2:14 UTC (permalink / raw)
To: Tanmay Kathpalia, Adrian Hunter, linux-mmc, linux-kernel,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
From: Tze Yee Ng <tze.yee.ng@altera.com>
DDR50 has no CMD19 tuning, so the SD6HC read path relies on static PHY
settings that need board/SoC characterisation. Read the read-DQS delay,
read-DQS source and phony DQS assertion timing from the new
cdns,ddr-read-dqs-delay-ps, cdns,ddr-no-lpbk-dqs and
cdns,ddr-phony-dqs-timing DT properties at PHY probe and apply them in
the extended-read DDR modes (DDR50 and DDR52). The read-DQS delay is
given in picoseconds and converted to delay elements with
cdns,delay-element-ps; since that quotient depends on the element size,
it is clamped to the 8-bit PHY field maximum (255) to avoid wrap-around.
Loopback DQS is the recommended read-capture path and stays the default;
cdns,ddr-no-lpbk-dqs lets a board fall back to the fabricated phony DQS.
When a property is absent the driver-computed value is kept - for the
phony DQS timing, the value derived from the RE# pulse width
(REBAR_PULSE_CYCLES-1).
Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
---
Changes in v2:
- Updated patch title to "mmc: sdhci-cadence6:" since it touches only the
v6 PHY.
- Renamed the properties to cdns,ddr-*.
- Read cdns,ddr-read-dqs-delay-ps in ps and convert it to delay elements
(dividing by cdns,delay-element-ps), clamping that quotient to the 8-bit
PHY field. (Krzysztof Kozlowski)
- Read cdns,ddr-no-lpbk-dqs via of_property_read_bool(). (Krzysztof Kozlowski)
- Dropped the v1 per-property range checks and redundant FIELD_MAX() write
masks. (Adrian Hunter)
- Apply the overrides in both DDR50 and DDR52.
---
drivers/mmc/host/sdhci-cadence-phy-v6.c | 59 ++++++++++++++++++++++++-
1 file changed, 58 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci-cadence-phy-v6.c b/drivers/mmc/host/sdhci-cadence-phy-v6.c
index 8d6a9c26c139..2b1b7256731a 100644
--- a/drivers/mmc/host/sdhci-cadence-phy-v6.c
+++ b/drivers/mmc/host/sdhci-cadence-phy-v6.c
@@ -129,6 +129,11 @@ struct sdhci_cdns6_phy {
/* Active delay element (ps); doubled when one SDMCLK requires > 256 steps */
u32 delay_element;
+ /* DDR read-path overrides (SoC-specific) */
+ u32 ddr_read_dqs_delay_ps;
+ bool ddr_no_lpbk_dqs;
+ s32 ddr_phony_dqs_timing;
+
/* PHY_DLL_SLAVE_CTRL register fields */
u8 cp_read_dqs_cmd_delay; /* bits [31:24] */
u8 cp_clk_wrdqs_delay; /* bits [23:16] */
@@ -145,6 +150,7 @@ struct sdhci_cdns6_phy {
/* PHY_DQS_TIMING register fields */
bool cp_use_phony_dqs; /* bit [20] */
bool cp_use_phony_dqs_cmd; /* bit [19] */
+ bool cp_use_lpbk_dqs; /* bit [21] */
/* PHY_CTRL register fields */
u32 cp_phony_dqs_timing;
@@ -523,6 +529,16 @@ static void sdhci_cdns6_phy_calc_dat_in(struct sdhci_cdns6_phy *phy)
if (phy->mode == MMC_TIMING_MMC_HS200)
phy->cp_read_dqs_delay = phy->hs200_tune_val;
+ if ((phy->mode == MMC_TIMING_UHS_DDR50 ||
+ phy->mode == MMC_TIMING_MMC_DDR52) && phy->ddr_read_dqs_delay_ps) {
+ u32 steps = phy->ddr_read_dqs_delay_ps / phy->delay_element_org;
+ u32 max_steps = FIELD_MAX(SDHCI_CDNS6_PHY_DLL_SLAVE_CTRL_READ_DQS_DELAY);
+
+ phy->cp_read_dqs_delay = min_t(u32, steps, max_steps);
+ }
+
+ phy->cp_use_lpbk_dqs = 1;
+
if (phy->sdhc_extended_rd_mode &&
(phy->mode == MMC_TIMING_UHS_DDR50 ||
phy->mode == MMC_TIMING_MMC_DDR52))
@@ -530,6 +546,23 @@ static void sdhci_cdns6_phy_calc_dat_in(struct sdhci_cdns6_phy *phy)
else
phy->cp_phony_dqs_timing = 0;
+ /*
+ * Loopback DQS is the recommended read-capture path; allow boards that
+ * need the fabricated phony DQS instead to opt out in the DDR modes.
+ */
+ if ((phy->mode == MMC_TIMING_UHS_DDR50 ||
+ phy->mode == MMC_TIMING_MMC_DDR52) && phy->ddr_no_lpbk_dqs)
+ phy->cp_use_lpbk_dqs = 0;
+
+ /*
+ * The computed phony DQS timing above is derived from the RE# pulse
+ * width. Allow a DT override for boards whose flight time shifts the
+ * returning DDR data relative to the fabricated strobe.
+ */
+ if ((phy->mode == MMC_TIMING_UHS_DDR50 ||
+ phy->mode == MMC_TIMING_MMC_DDR52) && phy->ddr_phony_dqs_timing >= 0)
+ phy->cp_phony_dqs_timing = phy->ddr_phony_dqs_timing;
+
if (strobe_dat) {
/* dqs loopback input via IO cell */
hcsdclkadj += phy->iocell_input_delay;
@@ -693,10 +726,11 @@ int sdhci_cdns6_phy_init(struct sdhci_cdns_priv *priv)
sdhci_cdns6_dll_reset(priv, true);
reg = sdhci_cdns6_read_phy_reg(priv, SDHCI_CDNS6_PHY_DQS_TIMING_REG);
+ reg &= ~SDHCI_CDNS6_PHY_DQS_TIMING_USE_LPBK_DQS;
reg &= ~SDHCI_CDNS6_PHY_DQS_TIMING_USE_PHONY_DQS;
reg &= ~SDHCI_CDNS6_PHY_DQS_TIMING_USE_PHONY_DQS_CMD;
reg |= SDHCI_CDNS6_PHY_DQS_TIMING_USE_EXT_LPBK_DQS;
- reg |= SDHCI_CDNS6_PHY_DQS_TIMING_USE_LPBK_DQS;
+ reg |= FIELD_PREP(SDHCI_CDNS6_PHY_DQS_TIMING_USE_LPBK_DQS, phy->cp_use_lpbk_dqs);
reg |= FIELD_PREP(SDHCI_CDNS6_PHY_DQS_TIMING_USE_PHONY_DQS, phy->cp_use_phony_dqs);
reg |= FIELD_PREP(SDHCI_CDNS6_PHY_DQS_TIMING_USE_PHONY_DQS_CMD, phy->cp_use_phony_dqs_cmd);
sdhci_cdns6_write_phy_reg(priv, SDHCI_CDNS6_PHY_DQS_TIMING_REG, reg);
@@ -878,6 +912,7 @@ int sdhci_cdns6_phy_probe(struct platform_device *pdev, struct sdhci_cdns_priv *
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_cdns6_phy *phy;
unsigned long val;
+ u32 prop;
int ret;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
@@ -916,6 +951,28 @@ int sdhci_cdns6_phy_probe(struct platform_device *pdev, struct sdhci_cdns_priv *
phy->delay_element_org = phy->delay_element;
+ /*
+ * Optional read-path tuning for the extended-read DDR modes (SD DDR50,
+ * eMMC DDR52).
+ */
+ phy->ddr_read_dqs_delay_ps = 0;
+ of_property_read_u32(dev->of_node, "cdns,ddr-read-dqs-delay-ps",
+ &phy->ddr_read_dqs_delay_ps);
+ if (phy->ddr_read_dqs_delay_ps / phy->delay_element_org >
+ FIELD_MAX(SDHCI_CDNS6_PHY_DLL_SLAVE_CTRL_READ_DQS_DELAY))
+ dev_warn(dev,
+ "cdns,ddr-read-dqs-delay-ps %u too large, clamping to %lu elements\n",
+ phy->ddr_read_dqs_delay_ps,
+ (unsigned long)FIELD_MAX(SDHCI_CDNS6_PHY_DLL_SLAVE_CTRL_READ_DQS_DELAY));
+
+ phy->ddr_no_lpbk_dqs = of_property_read_bool(dev->of_node,
+ "cdns,ddr-no-lpbk-dqs");
+
+ phy->ddr_phony_dqs_timing = -1;
+ if (!of_property_read_u32(dev->of_node, "cdns,ddr-phony-dqs-timing",
+ &prop))
+ phy->ddr_phony_dqs_timing = prop;
+
priv->phy = phy;
return 0;
--
2.43.7
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 3/4] dt-bindings: mmc: cdns,sd6hc: add SD6HC DDR50 read-path tuning
2026-10-09 2:14 ` [PATCH v2 3/4] dt-bindings: mmc: cdns,sd6hc: add SD6HC DDR50 read-path tuning tze.yee.ng
@ 2026-10-12 8:48 ` Krzysztof Kozlowski
0 siblings, 0 replies; 6+ messages in thread
From: Krzysztof Kozlowski @ 2026-10-12 8:48 UTC (permalink / raw)
To: tze.yee.ng
Cc: Tanmay Kathpalia, Adrian Hunter, linux-mmc, linux-kernel,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
On Fri, Oct 09, 2026 at 10:14:50AM +0800, tze.yee.ng@altera.com wrote:
> From: Tze Yee Ng <tze.yee.ng@altera.com>
>
> DDR50 has no CMD19 tuning, so the SD6HC read path must be centred by
> static, board/SoC-characterised PHY settings. Add three optional SD6HC
> properties for the extended-read DDR modes (SD DDR50 and eMMC DDR52):
>
> - cdns,ddr-read-dqs-delay-ps: read-DQS delay in picoseconds that centres
> the read eye (default 0).
> - cdns,ddr-no-lpbk-dqs: disable the loopback DQS read strobe and
> use the fabricated phony DQS instead. Loopback DQS is the recommended
> default; set this only on boards that need the phony DQS read path.
> - cdns,ddr-phony-dqs-timing: PHY_CTRL[9:4] phony DQS assertion timing.
> The driver derives this from the RE# pulse width; this property
> overrides the computed value for boards whose flight time shifts the
> DDR data return.
>
> Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
> ---
> Changes in v2:
> - Retitled to "dt-bindings: mmc: cdns,sd6hc:". (Tanmay Kathpalia)
> - Renamed cdns,ddr50-* -> cdns,ddr-*. (Tanmay Kathpalia)
> - cdns,ddr-read-dqs-delay-ps is now in picoseconds. (Krzysztof Kozlowski)
> - Replaced the read-DQS source selector with a cdns,ddr-no-lpbk-dqs
> boolean. (Krzysztof Kozlowski)
> - Reworded the phony-dqs-timing text. (Krzysztof Kozlowski,
> Tanmay Kathpalia)
> - Dropped the SD4HC note. (Tanmay Kathpalia)
> - Scope the new properties to the extended-read DDR modes (DDR50 and
> DDR52). (Tanmay Kathpalia)
There are no lore links in the cover letter to previous versions and b4
diff fails.
b4 diff 'cover.1791459448.git.tze.yee.ng@altera.com'
Looking up cover.1791459448.git.tze.yee.ng@altera.com
Checking for older revisions
Grabbing search results from lore.kernel.org
---
Analyzing 5 messages in the thread
Could not find lower series to compare against.
Why aren't you using b4 to send patches? Why making it difficult for us?
> ---
> .../devicetree/bindings/mmc/cdns,sd6hc.yaml | 30 +++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mmc/cdns,sd6hc.yaml b/Documentation/devicetree/bindings/mmc/cdns,sd6hc.yaml
> index d5ea2717904b..911ce58f8dab 100644
> --- a/Documentation/devicetree/bindings/mmc/cdns,sd6hc.yaml
> +++ b/Documentation/devicetree/bindings/mmc/cdns,sd6hc.yaml
> @@ -74,6 +74,36 @@ properties:
> maximum: 1000
> default: 24
>
> + cdns,ddr-read-dqs-delay-ps:
> + description: >
> + Read-DQS delay (DLL_SLAVE[7:0]) in picoseconds that centres the read
> + eye in the extended-read DDR modes (SD DDR50, eMMC DDR52), which have
> + no CMD19 tuning. The PHY runs the DLL bypassed in these modes, so the
> + driver converts this to delay elements (divided by
> + cdns,delay-element-ps). The 8-bit field holds at most 255 elements;
> + larger values are clamped to that limit.
> + minimum: 0
Drop, 0 is the default.
Where is the maximum value?
> + default: 0
> +
> + cdns,ddr-no-lpbk-dqs:
> + description: >
Drop > everywhere
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-12 8:48 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-09 2:14 [PATCH v2 0/4] mmc: sdhci-cadence: SD6HC DDR50/DDR52 read-path tuning and fixes tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 1/4] mmc: sdhci-cadence: add PHY settle after tuning for SD6HC tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 2/4] mmc: sdhci-cadence6: program PHONY_DQS_TIMING for extended-read DDR tze.yee.ng
2026-10-09 2:14 ` [PATCH v2 3/4] dt-bindings: mmc: cdns,sd6hc: add SD6HC DDR50 read-path tuning tze.yee.ng
2026-10-12 8:48 ` Krzysztof Kozlowski
2026-10-09 2:14 ` [PATCH v2 4/4] mmc: sdhci-cadence6: read SD6HC DDR50 tuning from device tree 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.