mmc: sdhci-cadence: fix PHY write

Message ID 20200525074053.7309-1-vladimir.kondratiev@intel.com
State New
Headers show
Series
  • mmc: sdhci-cadence: fix PHY write
Related show

Commit Message

Vladimir Kondratiev May 25, 2020, 7:40 a.m.
Accordingly to Cadence documentation, PHY write procedure is:

1. Software sets the PHY Register Address (HRS04[5:0]) and the
   PHY Write Data (HRS04[15:8]) fields.
2. Software sets the PHY Write Transaction Request (HRS04[24]) field to 1.
3. Software waits as the PHY Write Transaction Acknowledge (HRS04[26])
   field is equal to 0.
4. Hardware performs the write transaction to PHY register where
   HRS04[15:8] is a data written to register under HRS04[5:0] address.
5. Hardware sets the PHY Transaction Acknowledge (HRS04[26]) to 1 when
   transaction is completed.
6. Software clears the PHY Write Transaction Request (HRS04[24]) to 1
   after noticing that the PHY Write Transaction Acknowledge (HRS04[26])
   field is equal to 1.
7. Software waits for the PHY Acknowledge Register (HRS04[26]) field is
   equal to 0.

Add missing steps 3 and 7. Lack of these steps causes
integrity errors detested by hardware.

Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@intel.com>
---
 drivers/mmc/host/sdhci-cadence.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

Patch

diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c
index e474d3fa099e..6b2e7c43cbc1 100644
--- a/drivers/mmc/host/sdhci-cadence.c
+++ b/drivers/mmc/host/sdhci-cadence.c
@@ -114,6 +114,11 @@  static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
 	u32 tmp;
 	int ret;
 
+	ret = readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS04_ACK),
+				 0, 10);
+	if (ret)
+		return ret;
+
 	tmp = FIELD_PREP(SDHCI_CDNS_HRS04_WDATA, data) |
 	      FIELD_PREP(SDHCI_CDNS_HRS04_ADDR, addr);
 	writel(tmp, reg);
@@ -128,7 +133,10 @@  static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
 	tmp &= ~SDHCI_CDNS_HRS04_WR;
 	writel(tmp, reg);
 
-	return 0;
+	ret = readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS04_ACK),
+				 0, 10);
+
+	return ret;
 }
 
 static unsigned int sdhci_cdns_phy_param_count(struct device_node *np)