mmc: sdhci: Fix HISPD bit handling
authorJagan Teki <jagan@amarulasolutions.com>
Thu, 18 Jun 2020 14:03:12 +0000 (19:33 +0530)
committerPeng Fan <peng.fan@nxp.com>
Wed, 24 Jun 2020 06:05:30 +0000 (14:05 +0800)
SDHCI HISPD bits need to be configured based on desired mmc
timings mode and some HISPD quirks.

So, handle the HISPD bit based on the mmc computed selected
mode(timing parameter) rather than fixed mmc card clock
frequency.

Linux handle the HISPD similar like this in below commit but no
SDHCI_QUIRK_BROKEN_HISPD_MODE,

commit <501639bf2173> ("mmc: sdhci: fix SDHCI_QUIRK_NO_HISPD_BIT handling")

This eventually fixed the mmc write issue observed in
rk3399 sdhci controller.

Bug log for refernece,
=> gpt write mmc 0 $partitions
Writing GPT: mmc write failed
** Can't write to device 0 **
** Can't write to device 0 **
error!

Cc: Kever Yang <kever.yang@rock-chips.com>
Cc: Peng Fan <peng.fan@nxp.com>
Peng Fan: added back "ctrl &= ~SDHCI_CTRL_HISPD;" per Jaehoon's suggestion
Tested-by: Suniel Mahesh <sunil@amarulasolutions.com> # roc-rk3399-pc
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
drivers/mmc/sdhci.c

index 92cc8434af240a7f9f62acb087644db251514aa9..f4eb655f6ec17333a94685e30ad6fb2d7f52a908 100644 (file)
@@ -567,6 +567,7 @@ static int sdhci_set_ios(struct mmc *mmc)
 #endif
        u32 ctrl;
        struct sdhci_host *host = mmc->priv;
+       bool no_hispd_bit = false;
 
        if (host->ops && host->ops->set_control_reg)
                host->ops->set_control_reg(host);
@@ -594,14 +595,26 @@ static int sdhci_set_ios(struct mmc *mmc)
                        ctrl &= ~SDHCI_CTRL_4BITBUS;
        }
 
-       if (mmc->clock > 26000000)
-               ctrl |= SDHCI_CTRL_HISPD;
-       else
-               ctrl &= ~SDHCI_CTRL_HISPD;
-
        if ((host->quirks & SDHCI_QUIRK_NO_HISPD_BIT) ||
-           (host->quirks & SDHCI_QUIRK_BROKEN_HISPD_MODE))
+           (host->quirks & SDHCI_QUIRK_BROKEN_HISPD_MODE)) {
                ctrl &= ~SDHCI_CTRL_HISPD;
+               no_hispd_bit = true;
+       }
+
+       if (!no_hispd_bit) {
+               if (mmc->selected_mode == MMC_HS ||
+                   mmc->selected_mode == SD_HS ||
+                   mmc->selected_mode == MMC_DDR_52 ||
+                   mmc->selected_mode == MMC_HS_200 ||
+                   mmc->selected_mode == MMC_HS_400 ||
+                   mmc->selected_mode == UHS_SDR25 ||
+                   mmc->selected_mode == UHS_SDR50 ||
+                   mmc->selected_mode == UHS_SDR104 ||
+                   mmc->selected_mode == UHS_DDR50)
+                       ctrl |= SDHCI_CTRL_HISPD;
+               else
+                       ctrl &= ~SDHCI_CTRL_HISPD;
+       }
 
        sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);