Commit 1ad9f880 authored by Shirley Her's avatar Shirley Her Committed by Ulf Hansson
Browse files

mmc: sdhci-pci-o2micro: Bug fix for SDR104 HW tuning failure



Force chip enter L0 power state during SDR104 HW tuning to avoid tuning failure

Signed-off-by: default avatarShirley Her <shirley.her@bayhubtech.com>
Link: https://lore.kernel.org/r/20210206014051.3418-1-shirley.her@bayhubtech.com


Fixes: 7b7d897e ("mmc: sdhci-pci-o2micro: Add HW tuning for SDR104 mode")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 3f957dec
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@
#define O2_SD_ADMA2		0xE7
#define O2_SD_INF_MOD		0xF1
#define O2_SD_MISC_CTRL4	0xFC
#define O2_SD_MISC_CTRL		0x1C0
#define O2_SD_PWR_FORCE_L0	0x0002
#define O2_SD_TUNING_CTRL	0x300
#define O2_SD_PLL_SETTING	0x304
#define O2_SD_MISC_SETTING	0x308
@@ -300,6 +302,8 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
	struct sdhci_host *host = mmc_priv(mmc);
	int current_bus_width = 0;
	u32 scratch32 = 0;
	u16 scratch = 0;

	/*
	 * This handler only implements the eMMC tuning that is specific to
@@ -312,6 +316,17 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
	if (WARN_ON((opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
			(opcode != MMC_SEND_TUNING_BLOCK)))
		return -EINVAL;

	/* Force power mode enter L0 */
	scratch = sdhci_readw(host, O2_SD_MISC_CTRL);
	scratch |= O2_SD_PWR_FORCE_L0;
	sdhci_writew(host, scratch, O2_SD_MISC_CTRL);

	/* wait DLL lock, timeout value 5ms */
	if (readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host,
		scratch32, (scratch32 & O2_DLL_LOCK_STATUS), 1, 5000))
		pr_warn("%s: DLL can't lock in 5ms after force L0 during tuning.\n",
				mmc_hostname(host->mmc));
	/*
	 * Judge the tuning reason, whether caused by dll shift
	 * If cause by dll shift, should call sdhci_o2_dll_recovery
@@ -344,6 +359,11 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode)
		sdhci_set_bus_width(host, current_bus_width);
	}

	/* Cancel force power mode enter L0 */
	scratch = sdhci_readw(host, O2_SD_MISC_CTRL);
	scratch &= ~(O2_SD_PWR_FORCE_L0);
	sdhci_writew(host, scratch, O2_SD_MISC_CTRL);

	sdhci_reset(host, SDHCI_RESET_CMD);
	sdhci_reset(host, SDHCI_RESET_DATA);