From: Ricky WU ricky_wu@realtek.com
stable inclusion from stable-v5.10.115 commit 8528806abed5a759ce2061206d5152a89350ef63 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5IZ9C
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 1f311c94aabdb419c28e3147bcc8ab89269f1a7e upstream.
SD spec definition: "Host provides at least 74 Clocks before issuing first command" After 1ms for the voltage stable then start issuing the Clock signals
if POWER STATE is MMC_POWER_OFF to MMC_POWER_UP to issue Clock signal to card MMC_POWER_UP to MMC_POWER_ON to stop issuing signal to card
Signed-off-by: Ricky Wu ricky_wu@realtek.com Link: https://lore.kernel.org/r/1badf10aba764191a1a752edcbf90389@realtek.com Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Christian Loehle cloehle@hyperstone.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com --- drivers/mmc/host/rtsx_pci_sdmmc.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index e00167bcfaf6..b5cb83bb9b85 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -37,10 +37,7 @@ struct realtek_pci_sdmmc { bool double_clk; bool eject; bool initial_mode; - int power_state; -#define SDMMC_POWER_ON 1 -#define SDMMC_POWER_OFF 0 - + int prev_power_state; int sg_count; s32 cookie; int cookie_sg_count; @@ -902,14 +899,21 @@ static int sd_set_bus_width(struct realtek_pci_sdmmc *host, return err; }
-static int sd_power_on(struct realtek_pci_sdmmc *host) +static int sd_power_on(struct realtek_pci_sdmmc *host, unsigned char power_mode) { struct rtsx_pcr *pcr = host->pcr; int err;
- if (host->power_state == SDMMC_POWER_ON) + if (host->prev_power_state == MMC_POWER_ON) return 0;
+ if (host->prev_power_state == MMC_POWER_UP) { + rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0); + goto finish; + } + + msleep(100); + rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE, @@ -928,11 +932,17 @@ static int sd_power_on(struct realtek_pci_sdmmc *host) if (err < 0) return err;
+ mdelay(1); + err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN); if (err < 0) return err;
- host->power_state = SDMMC_POWER_ON; + /* send at least 74 clocks */ + rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN); + +finish: + host->prev_power_state = power_mode; return 0; }
@@ -941,7 +951,7 @@ static int sd_power_off(struct realtek_pci_sdmmc *host) struct rtsx_pcr *pcr = host->pcr; int err;
- host->power_state = SDMMC_POWER_OFF; + host->prev_power_state = MMC_POWER_OFF;
rtsx_pci_init_cmd(pcr);
@@ -967,7 +977,7 @@ static int sd_set_power_mode(struct realtek_pci_sdmmc *host, if (power_mode == MMC_POWER_OFF) err = sd_power_off(host); else - err = sd_power_on(host); + err = sd_power_on(host, power_mode);
return err; } @@ -1404,10 +1414,11 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
host = mmc_priv(mmc); host->pcr = pcr; + mmc->ios.power_delay_ms = 5; host->mmc = mmc; host->pdev = pdev; host->cookie = -1; - host->power_state = SDMMC_POWER_OFF; + host->prev_power_state = MMC_POWER_OFF; INIT_WORK(&host->work, sd_request); platform_set_drvdata(pdev, host); pcr->slots[RTSX_SD_CARD].p_dev = pdev;