]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
mmc: tmio: add eMMC HS400 mode support
authorMasaharu Hayakawa <masaharu.hayakawa.ry@renesas.com>
Mon, 18 Jun 2018 12:57:50 +0000 (14:57 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 16 Jul 2018 09:21:45 +0000 (11:21 +0200)
This patch adds processing for selecting HS400 mode.

Signed-off-by: Masaharu Hayakawa <masaharu.hayakawa.ry@renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/tmio_mmc.h
drivers/mmc/host/tmio_mmc_core.c
include/linux/mfd/tmio.h

index e7d651352dc90fb80bcb6b96b2546bc7f0578d91..5d141f79e175b2a3690beab69b626a5416efe76d 100644 (file)
@@ -46,6 +46,7 @@
 #define CTL_DMA_ENABLE 0xd8
 #define CTL_RESET_SD 0xe0
 #define CTL_VERSION 0xe2
+#define CTL_SDIF_MODE 0xe6
 #define CTL_SDIO_REGS 0x100
 #define CTL_CLK_AND_WAIT_CTL 0x138
 #define CTL_RESET_SDIO 0x1e0
@@ -191,6 +192,11 @@ struct tmio_mmc_host {
        /* Tuning values: 1 for success, 0 for failure */
        DECLARE_BITMAP(taps, BITS_PER_BYTE * sizeof(long));
        unsigned int tap_num;
+       unsigned long tap_set;
+
+       void (*prepare_hs400_tuning)(struct tmio_mmc_host *host);
+       void (*hs400_downgrade)(struct tmio_mmc_host *host);
+       void (*hs400_complete)(struct tmio_mmc_host *host);
 
        const struct tmio_mmc_dma_ops *dma_ops;
 };
index 3080299303045adc5908683b5509e4420ead2063..416f9e078fda8b2491b52db17412a6b88222579d 100644 (file)
@@ -199,6 +199,14 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host,
                tmio_mmc_clk_stop(host);
                return;
        }
+       /*
+        * Both HS400 and HS200/SD104 set 200MHz, but some devices need to
+        * set 400MHz to distinguish the CPG settings in HS400.
+        */
+       if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400 &&
+           host->pdata->flags & TMIO_MMC_HAVE_4TAP_HS400 &&
+           new_clock == 200000000)
+               new_clock = 400000000;
 
        if (host->clk_update)
                clock = host->clk_update(host, new_clock) / 512;
@@ -209,8 +217,13 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host,
                clock <<= 1;
 
        /* 1/1 clock is option */
-       if ((host->pdata->flags & TMIO_MMC_CLK_ACTUAL) && ((clk >> 22) & 0x1))
-               clk |= 0xff;
+       if ((host->pdata->flags & TMIO_MMC_CLK_ACTUAL) &&
+           ((clk >> 22) & 0x1)) {
+               if (!(host->mmc->ios.timing == MMC_TIMING_MMC_HS400))
+                       clk |= 0xff;
+               else
+                       clk &= ~0xff;
+       }
 
        if (host->set_clk_div)
                host->set_clk_div(host->pdev, (clk >> 22) & 1);
@@ -1087,6 +1100,33 @@ static int tmio_multi_io_quirk(struct mmc_card *card,
        return blk_size;
 }
 
+static int tmio_mmc_prepare_hs400_tuning(struct mmc_host *mmc,
+                                        struct mmc_ios *ios)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+
+       if (host->prepare_hs400_tuning)
+               host->prepare_hs400_tuning(host);
+
+       return 0;
+}
+
+static void tmio_mmc_hs400_downgrade(struct mmc_host *mmc)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+
+       if (host->hs400_downgrade)
+               host->hs400_downgrade(host);
+}
+
+static void tmio_mmc_hs400_complete(struct mmc_host *mmc)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+
+       if (host->hs400_complete)
+               host->hs400_complete(host);
+}
+
 static const struct mmc_host_ops tmio_mmc_ops = {
        .request        = tmio_mmc_request,
        .set_ios        = tmio_mmc_set_ios,
@@ -1096,6 +1136,9 @@ static const struct mmc_host_ops tmio_mmc_ops = {
        .multi_io_quirk = tmio_multi_io_quirk,
        .hw_reset       = tmio_mmc_hw_reset,
        .execute_tuning = tmio_mmc_execute_tuning,
+       .prepare_hs400_tuning = tmio_mmc_prepare_hs400_tuning,
+       .hs400_downgrade = tmio_mmc_hs400_downgrade,
+       .hs400_complete = tmio_mmc_hs400_complete,
 };
 
 static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
index 91f92215ca746cbb9f91eccd7ff732ad31179557..77866214ab51b31582559c384df8e6ffaaadc7b5 100644 (file)
@@ -90,6 +90,9 @@
 /* Some controllers have a CBSY bit */
 #define TMIO_MMC_HAVE_CBSY             BIT(11)
 
+/* Some controllers that support HS400 use use 4 taps while others use 8. */
+#define TMIO_MMC_HAVE_4TAP_HS400       BIT(13)
+
 int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
 int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);
 void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state);