Commit 11a21960 authored by Takeshi Saito's avatar Takeshi Saito Committed by Ulf Hansson
Browse files

mmc: renesas_sdhi: Add manual correction



This patch adds a manual correction mechanism for SDHI. Currently, SDHI
uses automatic TAP position correction. However, TAP position can also
be corrected manually via correction error status flags.

Signed-off-by: default avatarTakeshi Saito <takeshi.saito.xv@renesas.com>
Reviewed-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: default avatarWolfram Sang <wsa+renesas@sang-engineering.com>
Link: https://lore.kernel.org/r/20191217114034.13290-3-wsa+renesas@sang-engineering.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 44f54e70
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ struct renesas_sdhi {
	void __iomem *scc_ctl;
	u32 scc_tappos;
	u32 scc_tappos_hs400;
	bool doing_tune;
};

#define host_to_priv(host) \
+51 −10
Original line number Diff line number Diff line
@@ -263,6 +263,8 @@ static int renesas_sdhi_start_signal_voltage_switch(struct mmc_host *mmc,
#define SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN	BIT(0)
/* Definitions for values the SH_MOBILE_SDHI_SCC_RVSREQ register */
#define SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR	BIT(2)
#define SH_MOBILE_SDHI_SCC_RVSREQ_REQTAPUP	BIT(1)
#define SH_MOBILE_SDHI_SCC_RVSREQ_REQTAPDOWN	BIT(0)
/* Definitions for values the SH_MOBILE_SDHI_SCC_TMPPORT2 register */
#define SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL	BIT(4)
#define SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN	BIT(31)
@@ -321,6 +323,8 @@ static void renesas_sdhi_prepare_tuning(struct tmio_mmc_host *host,
{
	struct renesas_sdhi *priv = host_to_priv(host);

	priv->doing_tune = true;

	/* Set sampling clock position */
	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, tap);
}
@@ -426,6 +430,8 @@ static int renesas_sdhi_select_tuning(struct tmio_mmc_host *host)
	unsigned long ntap;     /* temporary counter of tuning success */
	unsigned long i;

	priv->doing_tune = false;

	/* Clear SCC_RVSREQ */
	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);

@@ -485,6 +491,47 @@ static int renesas_sdhi_select_tuning(struct tmio_mmc_host *host)
	return 0;
}

static bool renesas_sdhi_manual_correction(struct tmio_mmc_host *host, bool use_4tap)
{
	struct renesas_sdhi *priv = host_to_priv(host);
	u32 val;

	val = sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ);
	if (!val)
		return false;

	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);

	/* Change TAP position according to correction status */
	if (val & SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR)
		return true;    /* Need re-tune */
	else if (val & SH_MOBILE_SDHI_SCC_RVSREQ_REQTAPUP)
		host->tap_set = (host->tap_set + 1) % host->tap_num;
	else if (val & SH_MOBILE_SDHI_SCC_RVSREQ_REQTAPDOWN)
		host->tap_set = (host->tap_set - 1) % host->tap_num;
	else
		return false;

	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET,
		       host->tap_set / (use_4tap ? 2 : 1));

	return false;
}

static bool renesas_sdhi_auto_correction(struct tmio_mmc_host *host)
{
	struct renesas_sdhi *priv = host_to_priv(host);

	/* Check SCC error */
	if (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ) &
	    SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR) {
		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);
		return true;
	}

	return false;
}

static bool renesas_sdhi_check_scc_error(struct tmio_mmc_host *host)
{
	struct renesas_sdhi *priv = host_to_priv(host);
@@ -499,20 +546,14 @@ static bool renesas_sdhi_check_scc_error(struct tmio_mmc_host *host)
	    !(host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && !use_4tap))
		return false;

	if (mmc_doing_retune(host->mmc))
	if (mmc_doing_retune(host->mmc) || priv->doing_tune)
		return false;

	/* Check SCC error */
	if (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL) &
	    SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &&
	    sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ) &
	    SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR) {
		/* Clear SCC error */
		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);
		return true;
	}
	    SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN)
		return renesas_sdhi_auto_correction(host);

	return false;
	return renesas_sdhi_manual_correction(host, use_4tap);
}

static void renesas_sdhi_hw_reset(struct tmio_mmc_host *host)