Commit 3e68abf2 authored by Andy-ld Lu's avatar Andy-ld Lu Committed by Ulf Hansson
Browse files

mmc: mtk-sd: Fix register settings for hs400(es) mode



For hs400(es) mode, the 'hs400-ds-delay' is typically configured in the
dts. However, some projects may only define 'mediatek,hs400-ds-dly3',
which can lead to initialization failures in hs400es mode. CMD13 reported
response crc error in the mmc_switch_status() just after switching to
hs400es mode.

[    1.914038][   T82] mmc0: mmc_select_hs400es failed, error -84
[    1.914954][   T82] mmc0: error -84 whilst initialising MMC card

Currently, the hs400_ds_dly3 value is set within the tuning function. This
means that the PAD_DS_DLY3 field is not configured before tuning process,
which is the reason for the above-mentioned CMD13 response crc error.

Move the PAD_DS_DLY3 field configuration into msdc_prepare_hs400_tuning(),
and add a value check of hs400_ds_delay to prevent overwriting by zero when
the 'hs400-ds-delay' is not set in the dts. In addition, since hs400(es)
only tune the PAD_DS_DLY1, the PAD_DS_DLY2_SEL bit should be cleared to
bypass it.

Fixes: c4ac38c6 ("mmc: mtk-sd: Add HS400 online tuning support")
Signed-off-by: default avatarAndy-ld Lu <andy-ld.lu@mediatek.com>
Reviewed-by: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20250123092644.7359-1-andy-ld.lu@mediatek.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent ac5a41b4
Loading
Loading
Loading
Loading
+20 −11
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@
#define MSDC_PAD_TUNE_CMD2_SEL	  BIT(21)   /* RW */

#define PAD_DS_TUNE_DLY_SEL       BIT(0)	  /* RW */
#define PAD_DS_TUNE_DLY2_SEL      BIT(1)	  /* RW */
#define PAD_DS_TUNE_DLY1	  GENMASK(6, 2)   /* RW */
#define PAD_DS_TUNE_DLY2	  GENMASK(11, 7)  /* RW */
#define PAD_DS_TUNE_DLY3	  GENMASK(16, 12) /* RW */
@@ -318,6 +319,7 @@

/* EMMC50_PAD_DS_TUNE mask */
#define PAD_DS_DLY_SEL		BIT(16)	/* RW */
#define PAD_DS_DLY2_SEL		BIT(15)	/* RW */
#define PAD_DS_DLY1		GENMASK(14, 10)	/* RW */
#define PAD_DS_DLY3		GENMASK(4, 0)	/* RW */

@@ -2504,13 +2506,23 @@ static int msdc_execute_tuning(struct mmc_host *mmc, u32 opcode)
static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
{
	struct msdc_host *host = mmc_priv(mmc);

	host->hs400_mode = true;

	if (host->top_base)
	if (host->top_base) {
		if (host->hs400_ds_dly3)
			sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE,
				      PAD_DS_DLY3, host->hs400_ds_dly3);
		if (host->hs400_ds_delay)
			writel(host->hs400_ds_delay,
			       host->top_base + EMMC50_PAD_DS_TUNE);
	else
	} else {
		if (host->hs400_ds_dly3)
			sdr_set_field(host->base + PAD_DS_TUNE,
				      PAD_DS_TUNE_DLY3, host->hs400_ds_dly3);
		if (host->hs400_ds_delay)
			writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE);
	}
	/* hs400 mode must set it to 0 */
	sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS);
	/* to improve read performance, set outstanding to 2 */
@@ -2530,14 +2542,11 @@ static int msdc_execute_hs400_tuning(struct mmc_host *mmc, struct mmc_card *card
	if (host->top_base) {
		sdr_set_bits(host->top_base + EMMC50_PAD_DS_TUNE,
			     PAD_DS_DLY_SEL);
		if (host->hs400_ds_dly3)
			sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE,
				      PAD_DS_DLY3, host->hs400_ds_dly3);
		sdr_clr_bits(host->top_base + EMMC50_PAD_DS_TUNE,
			     PAD_DS_DLY2_SEL);
	} else {
		sdr_set_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY_SEL);
		if (host->hs400_ds_dly3)
			sdr_set_field(host->base + PAD_DS_TUNE,
				      PAD_DS_TUNE_DLY3, host->hs400_ds_dly3);
		sdr_clr_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY2_SEL);
	}

	host->hs400_tuning = true;