mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 23:51:33 +00:00
mmc: tmio: sdhi: Skip bad taps
Some of the tuning taps produce suboptimal results. Add code which skips those "bad" taps. Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
This commit is contained in:
parent
6900066cf6
commit
1bdcb83d29
2 changed files with 49 additions and 1 deletions
|
@ -97,6 +97,7 @@ 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;
|
||||
unsigned long error_tap = priv->tap_set;
|
||||
u32 reg, smpcmp;
|
||||
|
||||
if ((priv->caps & TMIO_SD_CAP_RCAR_UHS) &&
|
||||
|
@ -140,15 +141,32 @@ static bool renesas_sdhi_check_scc_error(struct udevice *dev)
|
|||
case RENESAS_SDHI_SCC_SMPCMP_CMD_REQUP:
|
||||
new_tap = (priv->tap_set +
|
||||
priv->tap_num + 1) % priv->tap_num;
|
||||
error_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;
|
||||
error_tap = (priv->tap_set +
|
||||
priv->tap_num + 1) % priv->tap_num;
|
||||
break;
|
||||
default:
|
||||
return true; /* Need re-tune */
|
||||
}
|
||||
|
||||
if (priv->hs400_bad_tap & BIT(new_tap)) {
|
||||
/*
|
||||
* New tap is bad tap (cannot change).
|
||||
* Compare with HS200 tuning result.
|
||||
* In HS200 tuning, when smpcmp[error_tap]
|
||||
* is OK, retune is executed.
|
||||
*/
|
||||
if (priv->smpcmp & BIT(error_tap))
|
||||
return true; /* Need retune */
|
||||
|
||||
return false; /* cannot change */
|
||||
}
|
||||
|
||||
priv->tap_set = new_tap;
|
||||
} else {
|
||||
if (reg & RENESAS_SDHI_SCC_RVSREQ_RVSERR)
|
||||
|
@ -303,6 +321,7 @@ static int renesas_sdhi_hs400(struct udevice *dev)
|
|||
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||
bool hs400 = (mmc->selected_mode == MMC_HS_400);
|
||||
int ret, taps = hs400 ? priv->nrtaps : 8;
|
||||
unsigned long new_tap;
|
||||
u32 reg;
|
||||
|
||||
if (taps == 4) /* HS400 on 4tap SoC needs different clock */
|
||||
|
@ -335,6 +354,24 @@ static int renesas_sdhi_hs400(struct udevice *dev)
|
|||
RENESAS_SDHI_SCC_DTCNTL_TAPEN,
|
||||
RENESAS_SDHI_SCC_DTCNTL);
|
||||
|
||||
/* Avoid bad TAP */
|
||||
if (priv->hs400_bad_tap & BIT(priv->tap_set)) {
|
||||
new_tap = (priv->tap_set +
|
||||
priv->tap_num + 1) % priv->tap_num;
|
||||
|
||||
if (priv->hs400_bad_tap & BIT(new_tap))
|
||||
new_tap = (priv->tap_set +
|
||||
priv->tap_num - 1) % priv->tap_num;
|
||||
|
||||
if (priv->hs400_bad_tap & BIT(new_tap)) {
|
||||
new_tap = priv->tap_set;
|
||||
debug("Three consecutive bad tap is prohibited\n");
|
||||
}
|
||||
|
||||
priv->tap_set = new_tap;
|
||||
tmio_sd_writel(priv, priv->tap_set, RENESAS_SDHI_SCC_TAPSET);
|
||||
}
|
||||
|
||||
if (taps == 4) {
|
||||
tmio_sd_writel(priv, priv->tap_set >> 1,
|
||||
RENESAS_SDHI_SCC_TAPSET);
|
||||
|
@ -682,13 +719,23 @@ static void renesas_sdhi_filter_caps(struct udevice *dev)
|
|||
(rmobile_get_cpu_rev_fraction() <= 2)))
|
||||
plat->cfg.host_caps &= ~MMC_MODE_HS400;
|
||||
|
||||
/* M3W ES1.x for x>2 can use HS400 with manual adjustment */
|
||||
/* H3 ES2.0, ES3.0 and M3W ES1.2 and M3N bad taps */
|
||||
if (((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
|
||||
(rmobile_get_cpu_rev_integer() >= 2)) ||
|
||||
((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) &&
|
||||
(rmobile_get_cpu_rev_integer() == 1) &&
|
||||
(rmobile_get_cpu_rev_fraction() == 2)) ||
|
||||
(rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A77965))
|
||||
priv->hs400_bad_tap = BIT(2) | BIT(3) | BIT(6) | BIT(7);
|
||||
|
||||
/* M3W ES1.x for x>2 can use HS400 with manual adjustment and taps */
|
||||
if ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) &&
|
||||
(rmobile_get_cpu_rev_integer() == 1) &&
|
||||
(rmobile_get_cpu_rev_fraction() > 2)) {
|
||||
priv->adjust_hs400_enable = true;
|
||||
priv->adjust_hs400_offset = 3;
|
||||
priv->adjust_hs400_calibrate = 0x9;
|
||||
priv->hs400_bad_tap = BIT(1) | BIT(3) | BIT(5) | BIT(7);
|
||||
}
|
||||
|
||||
/* M3N can use HS400 with manual adjustment */
|
||||
|
|
|
@ -145,6 +145,7 @@ struct tmio_sd_priv {
|
|||
bool adjust_hs400_enable;
|
||||
u8 adjust_hs400_offset;
|
||||
u8 adjust_hs400_calibrate;
|
||||
u8 hs400_bad_tap;
|
||||
#endif
|
||||
ulong (*clk_get_rate)(struct tmio_sd_priv *);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue