mmc: tmio: sdhi: Add SCC error checking
Check SCC for errors after check command if applicable and optionally adjust the bus skew settings accordingly. Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
This commit is contained in:
parent
8f39b03022
commit
6900066cf6
@ -34,7 +34,12 @@
|
||||
#define RENESAS_SDHI_SCC_RVSCNTL_RVSEN BIT(0)
|
||||
#define RENESAS_SDHI_SCC_RVSREQ 0x814
|
||||
#define RENESAS_SDHI_SCC_RVSREQ_RVSERR BIT(2)
|
||||
#define RENESAS_SDHI_SCC_RVSREQ_REQTAPUP BIT(1)
|
||||
#define RENESAS_SDHI_SCC_RVSREQ_REQTAPDOWN BIT(0)
|
||||
#define RENESAS_SDHI_SCC_SMPCMP 0x818
|
||||
#define RENESAS_SDHI_SCC_SMPCMP_CMD_ERR (BIT(24) | BIT(8))
|
||||
#define RENESAS_SDHI_SCC_SMPCMP_CMD_REQUP BIT(24)
|
||||
#define RENESAS_SDHI_SCC_SMPCMP_CMD_REQDOWN BIT(8)
|
||||
#define RENESAS_SDHI_SCC_TMPPORT2 0x81c
|
||||
#define RENESAS_SDHI_SCC_TMPPORT2_HS400EN BIT(31)
|
||||
#define RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL BIT(4)
|
||||
@ -87,6 +92,84 @@ static void sd_scc_tmpport_write32(struct tmio_sd_priv *priv, u32 addr, u32 val)
|
||||
tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_TMPPORT4);
|
||||
}
|
||||
|
||||
static bool renesas_sdhi_check_scc_error(struct udevice *dev)
|
||||
{
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||
unsigned long new_tap = priv->tap_set;
|
||||
u32 reg, smpcmp;
|
||||
|
||||
if ((priv->caps & TMIO_SD_CAP_RCAR_UHS) &&
|
||||
(mmc->selected_mode != UHS_SDR104) &&
|
||||
(mmc->selected_mode != MMC_HS_200) &&
|
||||
(mmc->selected_mode != MMC_HS_400) &&
|
||||
(priv->nrtaps != 4))
|
||||
return false;
|
||||
|
||||
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
|
||||
/* Handle automatic tuning correction */
|
||||
if (reg & RENESAS_SDHI_SCC_RVSCNTL_RVSEN) {
|
||||
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSREQ);
|
||||
if (reg & RENESAS_SDHI_SCC_RVSREQ_RVSERR) {
|
||||
tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_RVSREQ);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Handle manual tuning correction */
|
||||
reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSREQ);
|
||||
if (!reg) /* No error */
|
||||
return false;
|
||||
|
||||
tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_RVSREQ);
|
||||
|
||||
if (mmc->selected_mode == MMC_HS_400) {
|
||||
/*
|
||||
* Correction Error Status contains CMD and DAT signal status.
|
||||
* In HS400, DAT signal based on DS signal, not CLK.
|
||||
* Therefore, use only CMD status.
|
||||
*/
|
||||
smpcmp = tmio_sd_readl(priv, RENESAS_SDHI_SCC_SMPCMP) &
|
||||
RENESAS_SDHI_SCC_SMPCMP_CMD_ERR;
|
||||
|
||||
switch (smpcmp) {
|
||||
case 0:
|
||||
return false; /* No error in CMD signal */
|
||||
case RENESAS_SDHI_SCC_SMPCMP_CMD_REQUP:
|
||||
new_tap = (priv->tap_set +
|
||||
priv->tap_num + 1) % priv->tap_num;
|
||||
break;
|
||||
case RENESAS_SDHI_SCC_SMPCMP_CMD_REQDOWN:
|
||||
new_tap = (priv->tap_set +
|
||||
priv->tap_num - 1) % priv->tap_num;
|
||||
break;
|
||||
default:
|
||||
return true; /* Need re-tune */
|
||||
}
|
||||
|
||||
priv->tap_set = new_tap;
|
||||
} else {
|
||||
if (reg & RENESAS_SDHI_SCC_RVSREQ_RVSERR)
|
||||
return true; /* Need re-tune */
|
||||
else if (reg & RENESAS_SDHI_SCC_RVSREQ_REQTAPUP)
|
||||
priv->tap_set = (priv->tap_set +
|
||||
priv->tap_num + 1) % priv->tap_num;
|
||||
else if (reg & RENESAS_SDHI_SCC_RVSREQ_REQTAPDOWN)
|
||||
priv->tap_set = (priv->tap_set +
|
||||
priv->tap_num - 1) % priv->tap_num;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set TAP position */
|
||||
tmio_sd_writel(priv, priv->tap_set >> ((priv->nrtaps == 4) ? 1 : 0),
|
||||
RENESAS_SDHI_SCC_TAPSET);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void renesas_sdhi_adjust_hs400_mode_enable(struct tmio_sd_priv *priv)
|
||||
{
|
||||
u32 calib_code;
|
||||
@ -536,6 +619,8 @@ static int renesas_sdhi_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
||||
|
||||
renesas_sdhi_check_scc_error(dev);
|
||||
|
||||
if (cmd->cmdidx == MMC_CMD_SEND_STATUS)
|
||||
renesas_sdhi_adjust_hs400_mode_enable(priv);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user