On 28/8/2026 11:35 pm, Kathpalia, Tanmay wrote:

On 8/21/2026 1:38 PM, [email protected] wrote:
From: Tze Yee Ng <[email protected]>

Indirect PHY register writes go through HRS04/HRS05 and are posted: the
write returns before the PHY has latched the value and there is no ACK
handshake. Back-to-back PHY configuration writes can therefore race and
leave the PHY partially programmed, corrupting the first data transfer
after a mode switch.

Read back HRS05 after each indirect write to flush the posted write
before the next PHY access.

Fixes: fe11aa0b8ca3 ("mmc: sdhci-cadence: Add support for Cadence sdmmc v6")
Signed-off-by: Tze Yee Ng <[email protected]>
---
  drivers/mmc/sdhci-cadence6.c | 10 ++++++++++
  1 file changed, 10 insertions(+)

diff --git a/drivers/mmc/sdhci-cadence6.c b/drivers/mmc/sdhci-cadence6.c
index ca1086e2359..93cb19ecaaf 100644
--- a/drivers/mmc/sdhci-cadence6.c
+++ b/drivers/mmc/sdhci-cadence6.c
@@ -171,6 +171,16 @@ static void sdhci_cdns6_write_phy_reg(struct sdhci_cdns_plat *plat, u32 addr, u3
  {
      writel(addr, plat->hrs_addr + SDHCI_CDNS_HRS04);
      writel(val, plat->hrs_addr + SDHCI_CDNS_HRS05);
+
+    /*
+     * HRS04/HRS05 form the indirect PHY register port: HRS04 latches the
+     * target address, HRS05 the data. Both are posted writes, so read
+     * HRS05 back to force them to complete before the next PHY access.
+     * The readback also orders the preceding HRS04 write - reads and
+     * writes to the same slave are not reordered on this interconnect, so
+     * a single HRS05 readback flushes the whole address+data pair.
+     */
+    (void)readl(plat->hrs_addr + SDHCI_CDNS_HRS05);

Did you ever hit a case where a PHY readback after a burst of writes did
not match what you wrote (HRS04 = target SFR, readl(HRS05) != expected
value)? Do you have a capture of that, with and without the dummy
HRS05 read?

Hi Tanmay,


No, I don't have a capture of read(HRS05) returning a value other than what was written. Every indirect‑register read‑back I did during bring‑up matched the programmed/expected values; the corruption I captured was always at the first data transfer after a mode switch (CRC/timeout), not at the register level.

Thanks,
Tze Yee

Reply via email to