spi: cadence_qspi: Use #define for bits instead of bit shifts
[oweals/u-boot.git] / drivers / mmc / sdhci.c
index 7ddb549e03caea136fd6987d393eecc8706f9d7f..766e9eef84a964df4e4762be5b864dd2743dcabf 100644 (file)
@@ -87,7 +87,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
                if (stat & SDHCI_INT_ERROR) {
                        printf("%s: Error detected in status(0x%X)!\n",
                               __func__, stat);
-                       return -1;
+                       return -EIO;
                }
                if (stat & rdy) {
                        if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask))
@@ -110,7 +110,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
                        udelay(10);
                else {
                        printf("%s: Transfer data timeout\n", __func__);
-                       return -1;
+                       return -ETIMEDOUT;
                }
        } while (!(stat & SDHCI_INT_DATA_END));
        return 0;
@@ -121,13 +121,10 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
  * for card ready state.
  * Every time when card is busy after timeout then (last) timeout value will be
  * increased twice but only if it doesn't exceed global defined maximum.
- * Each function call will use last timeout value. Max timeout can be redefined
- * in board config file.
+ * Each function call will use last timeout value.
  */
-#ifndef CONFIG_SDHCI_CMD_MAX_TIMEOUT
-#define CONFIG_SDHCI_CMD_MAX_TIMEOUT           3200
-#endif
-#define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT       100
+#define SDHCI_CMD_MAX_TIMEOUT                  3200
+#define SDHCI_CMD_DEFAULT_TIMEOUT              100
 #define SDHCI_READ_STATUS_TIMEOUT              1000
 
 #ifdef CONFIG_DM_MMC_OPS
@@ -151,7 +148,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
        unsigned start = get_timer(0);
 
        /* Timeout unit - ms */
-       static unsigned int cmd_timeout = CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT;
+       static unsigned int cmd_timeout = SDHCI_CMD_DEFAULT_TIMEOUT;
 
        sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
        mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
@@ -164,7 +161,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
        while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
                if (time >= cmd_timeout) {
                        printf("%s: MMC: %d busy ", __func__, mmc_dev);
-                       if (2 * cmd_timeout <= CONFIG_SDHCI_CMD_MAX_TIMEOUT) {
+                       if (2 * cmd_timeout <= SDHCI_CMD_MAX_TIMEOUT) {
                                cmd_timeout += cmd_timeout;
                                printf("timeout increasing to: %u ms.\n",
                                       cmd_timeout);
@@ -245,6 +242,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 
        sdhci_writel(host, cmd->cmdarg, SDHCI_ARGUMENT);
 #ifdef CONFIG_MMC_SDMA
+       trans_bytes = ALIGN(trans_bytes, CONFIG_SYS_CACHELINE_SIZE);
        flush_cache(start_addr, trans_bytes);
 #endif
        sdhci_writew(host, SDHCI_MAKE_CMD(cmd->cmdidx, flags), SDHCI_COMMAND);
@@ -297,7 +295,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
 static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 {
        struct sdhci_host *host = mmc->priv;
-       unsigned int div, clk, timeout, reg;
+       unsigned int div, clk = 0, timeout, reg;
 
        /* Wait max 20 ms */
        timeout = 200;
@@ -306,7 +304,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
                if (timeout == 0) {
                        printf("%s: Timeout to wait cmd & data inhibit\n",
                               __func__);
-                       return -1;
+                       return -EBUSY;
                }
 
                timeout--;
@@ -321,14 +319,36 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
                return 0;
 
        if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
-               /* Version 3.00 divisors must be a multiple of 2. */
-               if (mmc->cfg->f_max <= clock)
-                       div = 1;
-               else {
-                       for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
-                               if ((mmc->cfg->f_max / div) <= clock)
+               /*
+                * Check if the Host Controller supports Programmable Clock
+                * Mode.
+                */
+               if (host->clk_mul) {
+                       for (div = 1; div <= 1024; div++) {
+                               if ((mmc->cfg->f_max * host->clk_mul / div)
+                                       <= clock)
                                        break;
                        }
+
+                       /*
+                        * Set Programmable Clock Mode in the Clock
+                        * Control register.
+                        */
+                       clk = SDHCI_PROG_CLOCK_MODE;
+                       div--;
+               } else {
+                       /* Version 3.00 divisors must be a multiple of 2. */
+                       if (mmc->cfg->f_max <= clock) {
+                               div = 1;
+                       } else {
+                               for (div = 2;
+                                    div < SDHCI_MAX_DIV_SPEC_300;
+                                    div += 2) {
+                                       if ((mmc->cfg->f_max / div) <= clock)
+                                               break;
+                               }
+                       }
+                       div >>= 1;
                }
        } else {
                /* Version 2.00 divisors must be a power of 2. */
@@ -336,13 +356,13 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
                        if ((mmc->cfg->f_max / div) <= clock)
                                break;
                }
+               div >>= 1;
        }
-       div >>= 1;
 
        if (host->set_clock)
                host->set_clock(host->index, div);
 
-       clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
+       clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
        clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
                << SDHCI_DIVIDER_HI_SHIFT;
        clk |= SDHCI_CLOCK_INT_EN;
@@ -355,7 +375,7 @@ static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
                if (timeout == 0) {
                        printf("%s: Internal clock never stabilised.\n",
                               __func__);
-                       return -1;
+                       return -EBUSY;
                }
                timeout--;
                udelay(1000);
@@ -451,12 +471,14 @@ static int sdhci_init(struct mmc *mmc)
 {
        struct sdhci_host *host = mmc->priv;
 
+       sdhci_reset(host, SDHCI_RESET_ALL);
+
        if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) {
                aligned_buffer = memalign(8, 512*1024);
                if (!aligned_buffer) {
                        printf("%s: Aligned buffer alloc failed!!!\n",
                               __func__);
-                       return -1;
+                       return -ENOMEM;
                }
        }
 
@@ -514,10 +536,22 @@ static const struct mmc_ops sdhci_ops = {
 int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
                u32 max_clk, u32 min_clk)
 {
-       u32 caps;
+       u32 caps, caps_1;
 
        caps = sdhci_readl(host, SDHCI_CAPABILITIES);
-       host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+
+#ifdef CONFIG_MMC_SDMA
+       if (!(caps & SDHCI_CAN_DO_SDMA)) {
+               printf("%s: Your controller doesn't support SDMA!!\n",
+                      __func__);
+               return -EINVAL;
+       }
+#endif
+       if (host->quirks & SDHCI_QUIRK_REG32_RW)
+               host->version =
+                       sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16;
+       else
+               host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
        cfg->name = host->name;
 #ifndef CONFIG_DM_MMC_OPS
@@ -534,8 +568,11 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
                                SDHCI_CLOCK_BASE_SHIFT;
                cfg->f_max *= 1000000;
        }
-       if (cfg->f_max == 0)
+       if (cfg->f_max == 0) {
+               printf("%s: Hardware doesn't specify base clock frequency\n",
+                      __func__);
                return -EINVAL;
+       }
        if (min_clk)
                cfg->f_min = min_clk;
        else {
@@ -552,6 +589,9 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
        if (caps & SDHCI_CAN_VDD_180)
                cfg->voltages |= MMC_VDD_165_195;
 
+       if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
+               cfg->voltages |= host->voltages;
+
        cfg->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
        if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
                if (caps & SDHCI_CAN_DO_8BIT)
@@ -564,6 +604,16 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 
        cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
+       /*
+        * In case of Host Controller v3.00, find out whether clock
+        * multiplier is supported.
+        */
+       if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
+               caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+               host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
+                               SDHCI_CLOCK_MUL_SHIFT;
+       }
+
        return 0;
 }
 
@@ -575,32 +625,16 @@ int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
 #else
 int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
 {
-#ifdef CONFIG_MMC_SDMA
-       unsigned int caps;
+       int ret;
 
-       caps = sdhci_readl(host, SDHCI_CAPABILITIES);
-       if (!(caps & SDHCI_CAN_DO_SDMA)) {
-               printf("%s: Your controller doesn't support SDMA!!\n",
-                      __func__);
-               return -1;
-       }
-#endif
-
-       if (sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk)) {
-               printf("%s: Hardware doesn't specify base clock frequency\n",
-                      __func__);
-               return -EINVAL;
-       }
-
-       if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
-               host->cfg.voltages |= host->voltages;
-
-       sdhci_reset(host, SDHCI_RESET_ALL);
+       ret = sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk);
+       if (ret)
+               return ret;
 
        host->mmc = mmc_create(&host->cfg, host);
        if (host->mmc == NULL) {
                printf("%s: mmc create fail!\n", __func__);
-               return -1;
+               return -ENOMEM;
        }
 
        return 0;