| From 1f311c94aabdb419c28e3147bcc8ab89269f1a7e Mon Sep 17 00:00:00 2001 |
| From: Ricky WU <ricky_wu@realtek.com> |
| Date: Wed, 2 Mar 2022 09:43:01 +0000 |
| Subject: mmc: rtsx: add 74 Clocks in power on flow |
| |
| From: Ricky WU <ricky_wu@realtek.com> |
| |
| 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> |
| --- |
| drivers/mmc/host/rtsx_pci_sdmmc.c | 31 +++++++++++++++++++++---------- |
| 1 file changed, 21 insertions(+), 10 deletions(-) |
| |
| --- 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 realt |
| 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_pc |
| 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_p |
| 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 real |
| 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(stru |
| |
| 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; |