diff options
author | Marek Vasut <marek.vasut@gmail.com> | 2019-11-23 13:36:24 +0100 |
---|---|---|
committer | Peng Fan <peng.fan@nxp.com> | 2019-11-27 16:56:46 +0800 |
commit | 1bdcb83d293614dc770a7b76229da61ee19855bf (patch) | |
tree | 31ce411410ad465f06124ffb8e187a95e1b63749 | |
parent | 6900066cf67cb95503a922088eed4b31cccba8c2 (diff) | |
download | u-boot-1bdcb83d293614dc770a7b76229da61ee19855bf.tar.gz u-boot-1bdcb83d293614dc770a7b76229da61ee19855bf.tar.xz u-boot-1bdcb83d293614dc770a7b76229da61ee19855bf.zip |
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>
-rw-r--r-- | drivers/mmc/renesas-sdhi.c | 49 | ||||
-rw-r--r-- | drivers/mmc/tmio-common.h | 1 |
2 files changed, 49 insertions, 1 deletions
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index dcc77dd86c..087d8b47a8 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -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 */ diff --git a/drivers/mmc/tmio-common.h b/drivers/mmc/tmio-common.h index 79f51d21af..f39118e337 100644 --- a/drivers/mmc/tmio-common.h +++ b/drivers/mmc/tmio-common.h @@ -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 *); }; |