mmc: tmio: Configure HOST_MODE WMODE according to bus width
[pandora-u-boot.git] / drivers / mmc / tmio-common.c
index 2a73829..6e656e5 100644 (file)
@@ -347,12 +347,10 @@ static int tmio_sd_dma_xfer(struct udevice *dev, struct mmc_data *data)
                /*
                 * The DMA READ completion flag position differs on Socionext
                 * and Renesas SoCs. It is bit 20 on Socionext SoCs and using
-                * bit 17 is a hardware bug and forbidden. It is bit 17 on
-                * Renesas SoCs and bit 20 does not work on them.
+                * bit 17 is a hardware bug and forbidden. It is either bit 17
+                * or bit 20 on Renesas SoCs, depending on SoC.
                 */
-               poll_flag = (priv->caps & TMIO_SD_CAP_RCAR) ?
-                           TMIO_SD_DMA_INFO1_END_RD :
-                           TMIO_SD_DMA_INFO1_END_RD2;
+               poll_flag = priv->read_poll_flag;
                tmp |= TMIO_SD_DMA_MODE_DIR_RD;
        } else {
                buf = (void *)data->src;
@@ -369,6 +367,9 @@ static int tmio_sd_dma_xfer(struct udevice *dev, struct mmc_data *data)
 
        ret = tmio_sd_dma_wait_for_irq(dev, poll_flag, data->blocks);
 
+       if (poll_flag == TMIO_SD_DMA_INFO1_END_RD)
+               udelay(1);
+
        __dma_unmap_single(dma_addr, len, dir);
 
        return ret;
@@ -555,55 +556,76 @@ static void tmio_sd_set_ddr_mode(struct tmio_sd_priv *priv,
        tmio_sd_writel(priv, tmp, TMIO_SD_IF_MODE);
 }
 
-static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
-                                    struct mmc *mmc)
+static ulong tmio_sd_clk_get_rate(struct tmio_sd_priv *priv)
 {
-       unsigned int divisor;
-       u32 val, tmp;
+       return priv->clk_get_rate(priv);
+}
 
-       if (!mmc->clock)
-               return;
-
-       divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
-
-       if (divisor <= 1)
-               val = (priv->caps & TMIO_SD_CAP_RCAR) ?
-                     TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
-       else if (divisor <= 2)
-               val = TMIO_SD_CLKCTL_DIV2;
-       else if (divisor <= 4)
-               val = TMIO_SD_CLKCTL_DIV4;
-       else if (divisor <= 8)
-               val = TMIO_SD_CLKCTL_DIV8;
-       else if (divisor <= 16)
-               val = TMIO_SD_CLKCTL_DIV16;
-       else if (divisor <= 32)
-               val = TMIO_SD_CLKCTL_DIV32;
-       else if (divisor <= 64)
-               val = TMIO_SD_CLKCTL_DIV64;
-       else if (divisor <= 128)
-               val = TMIO_SD_CLKCTL_DIV128;
-       else if (divisor <= 256)
-               val = TMIO_SD_CLKCTL_DIV256;
-       else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
-               val = TMIO_SD_CLKCTL_DIV512;
-       else
-               val = TMIO_SD_CLKCTL_DIV1024;
+static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv, struct mmc *mmc)
+{
+       unsigned int divisor;
+       u32 tmp, val = 0;
+       ulong mclk;
+
+       if (mmc->clock) {
+               mclk = tmio_sd_clk_get_rate(priv);
+
+               divisor = DIV_ROUND_UP(mclk, mmc->clock);
+
+               /* Do not set divider to 0xff in DDR mode */
+               if (mmc->ddr_mode && (divisor == 1))
+                       divisor = 2;
+
+               if (divisor <= 1)
+                       val = (priv->caps & TMIO_SD_CAP_RCAR) ?
+                             TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
+               else if (divisor <= 2)
+                       val = TMIO_SD_CLKCTL_DIV2;
+               else if (divisor <= 4)
+                       val = TMIO_SD_CLKCTL_DIV4;
+               else if (divisor <= 8)
+                       val = TMIO_SD_CLKCTL_DIV8;
+               else if (divisor <= 16)
+                       val = TMIO_SD_CLKCTL_DIV16;
+               else if (divisor <= 32)
+                       val = TMIO_SD_CLKCTL_DIV32;
+               else if (divisor <= 64)
+                       val = TMIO_SD_CLKCTL_DIV64;
+               else if (divisor <= 128)
+                       val = TMIO_SD_CLKCTL_DIV128;
+               else if (divisor <= 256)
+                       val = TMIO_SD_CLKCTL_DIV256;
+               else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
+                       val = TMIO_SD_CLKCTL_DIV512;
+               else
+                       val = TMIO_SD_CLKCTL_DIV1024;
+       }
 
        tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
-       if (tmp & TMIO_SD_CLKCTL_SCLKEN &&
-           (tmp & TMIO_SD_CLKCTL_DIV_MASK) == val)
-               return;
+       if (mmc->clock &&
+           !((tmp & TMIO_SD_CLKCTL_SCLKEN) &&
+             ((tmp & TMIO_SD_CLKCTL_DIV_MASK) == val))) {
+               /*
+                * Stop the clock before changing its rate
+                * to avoid a glitch signal
+                */
+               tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+               tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
-       /* stop the clock before changing its rate to avoid a glitch signal */
-       tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
-       tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+               /* Change the clock rate. */
+               tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
+               tmp |= val;
+       }
 
-       tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
-       tmp |= val | TMIO_SD_CLKCTL_OFFEN;
-       tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+       /* Enable or Disable the clock */
+       if (mmc->clk_disable) {
+               tmp |= TMIO_SD_CLKCTL_OFFEN;
+               tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+       } else {
+               tmp &= ~TMIO_SD_CLKCTL_OFFEN;
+               tmp |= TMIO_SD_CLKCTL_SCLKEN;
+       }
 
-       tmp |= TMIO_SD_CLKCTL_SCLKEN;
        tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
        udelay(1000);
@@ -683,10 +705,14 @@ static void tmio_sd_host_init(struct tmio_sd_priv *priv)
         * This register dropped backward compatibility at version 0x10.
         * Write an appropriate value depending on the IP version.
         */
-       if (priv->version >= 0x10)
-               tmio_sd_writel(priv, 0x101, TMIO_SD_HOST_MODE);
-       else
+       if (priv->version >= 0x10) {
+               if (priv->caps & TMIO_SD_CAP_64BIT)
+                       tmio_sd_writel(priv, 0x100, TMIO_SD_HOST_MODE);
+               else
+                       tmio_sd_writel(priv, 0x101, TMIO_SD_HOST_MODE);
+       } else {
                tmio_sd_writel(priv, 0x0, TMIO_SD_HOST_MODE);
+       }
 
        if (priv->caps & TMIO_SD_CAP_DMA_INTERNAL) {
                tmp = tmio_sd_readl(priv, TMIO_SD_DMA_MODE);
@@ -708,6 +734,7 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
        struct tmio_sd_priv *priv = dev_get_priv(dev);
        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
        fdt_addr_t base;
+       ulong mclk;
        int ret;
 
        base = devfdt_get_addr(dev);
@@ -720,6 +747,8 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
 
 #ifdef CONFIG_DM_REGULATOR
        device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc_dev);
+       if (priv->vqmmc_dev)
+               regulator_set_value(priv->vqmmc_dev, 3300000);
 #endif
 
        ret = mmc_of_parse(dev, &plat->cfg);
@@ -748,10 +777,12 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks)
 
        tmio_sd_host_init(priv);
 
+       mclk = tmio_sd_clk_get_rate(priv);
+
        plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
-       plat->cfg.f_min = priv->mclk /
+       plat->cfg.f_min = mclk /
                        (priv->caps & TMIO_SD_CAP_DIV1024 ? 1024 : 512);
-       plat->cfg.f_max = priv->mclk;
+       plat->cfg.f_max = mclk;
        plat->cfg.b_max = U32_MAX; /* max value of TMIO_SD_SECCNT */
 
        upriv->mmc = &plat->mmc;