From e62120e3b77a52a4647585b3f27e56cac7b6b0da Mon Sep 17 00:00:00 2001 From: liangshuang Date: Fri, 7 Jun 2024 11:10:10 +0800 Subject: [PATCH 049/219] fix:optimize SDHCI driver. Changelogs: 1.Fix the issue of failed tuning of the Sandisk SD card. 2.Fix the issue of unexpected interrupts generated by EMMC/SDIO during the probe process. --- drivers/mmc/host/sdhci-of-eswin-sdio.c | 36 +++++++++++++++++++++----- drivers/mmc/host/sdhci-of-eswin.c | 8 ++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-eswin-sdio.c b/drivers/mmc/host/sdhci-of-eswin-sdio.c index 83cbdb61c936..badbee00b39e 100644 --- a/drivers/mmc/host/sdhci-of-eswin-sdio.c +++ b/drivers/mmc/host/sdhci-of-eswin-sdio.c @@ -42,7 +42,7 @@ #define ESWIN_SDHCI_SD1_INT_STATUS 0x708 #define ESWIN_SDHCI_SD1_PWR_CTRL 0x70c -#define DELAY_RANGE_THRESHOLD 40 +#define DELAY_RANGE_THRESHOLD 20 struct eswin_sdio_private { int phase_code; @@ -150,7 +150,22 @@ static void eswin_sdhci_sdio_reset(struct sdhci_host *host, u8 mask) struct eswin_sdhci_data *eswin_sdhci_sdio = sdhci_pltfm_priv(pltfm_host); - sdhci_reset(host, mask); + sdhci_writel(host, 0, SDHCI_INT_ENABLE); + sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); + + if (mask & SDHCI_RESET_ALL) { + sdhci_reset(host, SDHCI_RESET_ALL); + } + if (mask & SDHCI_RESET_DATA) { + sdhci_reset(host, SDHCI_RESET_DATA); + } + + if (mask & SDHCI_RESET_CMD) { + sdhci_reset(host, SDHCI_RESET_CMD); + } + + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); if (eswin_sdhci_sdio->quirks & SDHCI_ESWIN_QUIRK_FORCE_CDTEST) { ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); @@ -181,10 +196,9 @@ static int eswin_sdhci_sdio_delay_tuning(struct sdhci_host *host, u32 opcode) eswin_sdhci_sdio_config_phy_delay(host, i); eswin_sdhci_enable_card_clk(host); ret = mmc_send_tuning(host->mmc, opcode, &cmd_error); + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); if (ret) { - pr_debug("%s: bad delay:0x%x\n", mmc_hostname(host->mmc), i); - sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); - udelay(200); + pr_debug("%s: bad delay:0x%x!\n", mmc_hostname(host->mmc), i); if (delay_min != -1 && delay_max != -1) { if (delay_max - delay_min > delay_range) { delay_range = delay_max - delay_min; @@ -227,6 +241,14 @@ static int eswin_sdhci_sdio_delay_tuning(struct sdhci_host *host, u32 opcode) eswin_sdhci_sdio_config_phy_delay(host, delay); eswin_sdhci_enable_card_clk(host); + ret = mmc_send_tuning(host->mmc, opcode, &cmd_error); + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + if (ret) { + pr_err("%s: delay code(0x%x) not work, tuning failed!\n", + mmc_hostname(host->mmc), delay); + return ret; + } + return 0; } @@ -245,9 +267,9 @@ static int eswin_sdhci_sdio_phase_code_tuning(struct sdhci_host *host, eswin_sdhci_enable_card_clk(host); ret = mmc_send_tuning(host->mmc, opcode, &cmd_error); + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); if (ret) { - sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); - udelay(200); + pr_debug("%s: bad phase_code:0x%x\n", mmc_hostname(host->mmc), phase_code); if (code_min != -1 && code_max != -1) break; } else { diff --git a/drivers/mmc/host/sdhci-of-eswin.c b/drivers/mmc/host/sdhci-of-eswin.c index 41aa80f8dbe3..a0347ac5c739 100644 --- a/drivers/mmc/host/sdhci-of-eswin.c +++ b/drivers/mmc/host/sdhci-of-eswin.c @@ -181,7 +181,11 @@ static void eswin_sdhci_reset(struct sdhci_host *host, u8 mask) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct eswin_sdhci_data *eswin_sdhci = sdhci_pltfm_priv(pltfm_host); + sdhci_writel(host, 0, SDHCI_INT_ENABLE); + sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); sdhci_reset(host, mask); + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); if (eswin_sdhci->quirks & SDHCI_ESWIN_QUIRK_FORCE_CDTEST) { ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); @@ -243,7 +247,7 @@ static int eswin_sdhci_delay_tuning(struct sdhci_host *host, u32 opcode) eswin_sdhci_enable_card_clk(host); ret = mmc_send_tuning(host->mmc, opcode, &cmd_error); if (ret) { - sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); udelay(200); if (delay_min != -1 && delay_max != -1) break; @@ -291,7 +295,7 @@ static int eswin_sdhci_phase_code_tuning(struct sdhci_host *host, u32 opcode) ret = mmc_send_tuning(host->mmc, opcode, &cmd_error); if (ret) { - sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); udelay(200); if (code_min != -1 && code_max != -1) break; -- 2.47.0