Skip to content

Commit

Permalink
mmc: sdhci-cadence: send tune request twice to work around errata
Browse files Browse the repository at this point in the history
Cadence sent out an errata report to their customers of this IP.
This errata is not so severe, but the tune request should be sent
twice to avoid the potential issue.

Quote from the report:

Problem Summary
---------------
The IP6116 SD/eMMC PHY design has a timing issue on receive data path.
This issue may lead to an incorrect values of read/write pointers of
the synchronization FIFO. Such a situation can happen at the SDR104
and HS200 tuning procedure when the PHY is requested to change a phase
of sampling clock when moving to the next tuning iteration.

Workarounds
-----------
The following are valid workarounds to resolve the issue:

1. In eMMC mode, software sends tune request twice instead of once at
   each iteration. This means that the clock phase is not changed on
   the second request so there is no potential for clock instability.
2. In SD mode, software must not use the hardware tuning and instead
   perform an almost identical procedure to eMMC, using the HRS34 Tune
   Force register.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
  • Loading branch information
masahir0y authored and storulf committed May 2, 2018
1 parent e79dc1b commit ef6b756
Showing 1 changed file with 18 additions and 4 deletions.
22 changes: 18 additions & 4 deletions drivers/mmc/host/sdhci-cadence.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,18 +253,32 @@ static int sdhci_cdns_set_tune_val(struct sdhci_host *host, unsigned int val)
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS06;
u32 tmp;
int i, ret;

if (WARN_ON(!FIELD_FIT(SDHCI_CDNS_HRS06_TUNE, val)))
return -EINVAL;

tmp = readl(reg);
tmp &= ~SDHCI_CDNS_HRS06_TUNE;
tmp |= FIELD_PREP(SDHCI_CDNS_HRS06_TUNE, val);
tmp |= SDHCI_CDNS_HRS06_TUNE_UP;
writel(tmp, reg);

return readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS06_TUNE_UP),
0, 1);
/*
* Workaround for IP errata:
* The IP6116 SD/eMMC PHY design has a timing issue on receive data
* path. Send tune request twice.
*/
for (i = 0; i < 2; i++) {
tmp |= SDHCI_CDNS_HRS06_TUNE_UP;
writel(tmp, reg);

ret = readl_poll_timeout(reg, tmp,
!(tmp & SDHCI_CDNS_HRS06_TUNE_UP),
0, 1);

return ret;
}

return 0;
}

static int sdhci_cdns_execute_tuning(struct mmc_host *mmc, u32 opcode)
Expand Down

0 comments on commit ef6b756

Please sign in to comment.