mmc: dw_mmc: The "clock-freq-min-max" property was deprecated
[platform/kernel/linux-starfive.git] / drivers / mmc / host / dw_mmc.c
index df478ae..881ca3e 100644 (file)
@@ -54,7 +54,7 @@
 #define DW_MCI_DMA_THRESHOLD   16
 
 #define DW_MCI_FREQ_MAX        200000000       /* unit: HZ */
-#define DW_MCI_FREQ_MIN        400000          /* unit: HZ */
+#define DW_MCI_FREQ_MIN        100000          /* unit: HZ */
 
 #define IDMAC_INT_CLR          (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \
                                 SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \
@@ -165,12 +165,14 @@ static const struct file_operations dw_mci_req_fops = {
 
 static int dw_mci_regs_show(struct seq_file *s, void *v)
 {
-       seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS);
-       seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS);
-       seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD);
-       seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL);
-       seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK);
-       seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA);
+       struct dw_mci *host = s->private;
+
+       seq_printf(s, "STATUS:\t0x%08x\n", mci_readl(host, STATUS));
+       seq_printf(s, "RINTSTS:\t0x%08x\n", mci_readl(host, RINTSTS));
+       seq_printf(s, "CMD:\t0x%08x\n", mci_readl(host, CMD));
+       seq_printf(s, "CTRL:\t0x%08x\n", mci_readl(host, CTRL));
+       seq_printf(s, "INTMASK:\t0x%08x\n", mci_readl(host, INTMASK));
+       seq_printf(s, "CLKENA:\t0x%08x\n", mci_readl(host, CLKENA));
 
        return 0;
 }
@@ -234,7 +236,6 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg);
 
 static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
 {
-       struct mmc_data *data;
        struct dw_mci_slot *slot = mmc_priv(mmc);
        struct dw_mci *host = slot->host;
        u32 cmdr;
@@ -289,10 +290,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
        if (cmd->flags & MMC_RSP_CRC)
                cmdr |= SDMMC_CMD_RESP_CRC;
 
-       data = cmd->data;
-       if (data) {
+       if (cmd->data) {
                cmdr |= SDMMC_CMD_DAT_EXP;
-               if (data->flags & MMC_DATA_WRITE)
+               if (cmd->data->flags & MMC_DATA_WRITE)
                        cmdr |= SDMMC_CMD_DAT_WR;
        }
 
@@ -335,6 +335,9 @@ static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd)
        cmdr = stop->opcode | SDMMC_CMD_STOP |
                SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP;
 
+       if (!test_bit(DW_MMC_CARD_NO_USE_HOLD, &host->cur_slot->flags))
+               cmdr |= SDMMC_CMD_USE_HOLD_REG;
+
        return cmdr;
 }
 
@@ -380,7 +383,7 @@ static void dw_mci_start_command(struct dw_mci *host,
 
 static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data)
 {
-       struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort;
+       struct mmc_command *stop = &host->stop_abort;
 
        dw_mci_start_command(host, stop, host->stop_cmdr);
 }
@@ -409,12 +412,13 @@ static void dw_mci_dma_cleanup(struct dw_mci *host)
 {
        struct mmc_data *data = host->data;
 
-       if (data)
-               if (!data->host_cookie)
-                       dma_unmap_sg(host->dev,
-                                    data->sg,
-                                    data->sg_len,
-                                    dw_mci_get_dma_dir(data));
+       if (data && data->host_cookie == COOKIE_MAPPED) {
+               dma_unmap_sg(host->dev,
+                            data->sg,
+                            data->sg_len,
+                            dw_mci_get_dma_dir(data));
+               data->host_cookie = COOKIE_UNMAPPED;
+       }
 }
 
 static void dw_mci_idmac_reset(struct dw_mci *host)
@@ -612,7 +616,7 @@ static inline int dw_mci_prepare_desc64(struct dw_mci *host,
        return 0;
 err_own_bit:
        /* restore the descriptor chain as it's polluted */
-       dev_dbg(host->dev, "desciptor is still owned by IDMAC.\n");
+       dev_dbg(host->dev, "descriptor is still owned by IDMAC.\n");
        memset(host->sg_cpu, 0, DESC_RING_BUF_SZ);
        dw_mci_idmac_init(host);
        return -EINVAL;
@@ -688,7 +692,7 @@ static inline int dw_mci_prepare_desc32(struct dw_mci *host,
        return 0;
 err_own_bit:
        /* restore the descriptor chain as it's polluted */
-       dev_dbg(host->dev, "desciptor is still owned by IDMAC.\n");
+       dev_dbg(host->dev, "descriptor is still owned by IDMAC.\n");
        memset(host->sg_cpu, 0, DESC_RING_BUF_SZ);
        dw_mci_idmac_init(host);
        return -EINVAL;
@@ -845,13 +849,13 @@ static const struct dw_mci_dma_ops dw_mci_edmac_ops = {
 
 static int dw_mci_pre_dma_transfer(struct dw_mci *host,
                                   struct mmc_data *data,
-                                  bool next)
+                                  int cookie)
 {
        struct scatterlist *sg;
        unsigned int i, sg_len;
 
-       if (!next && data->host_cookie)
-               return data->host_cookie;
+       if (data->host_cookie == COOKIE_PRE_MAPPED)
+               return data->sg_len;
 
        /*
         * We don't do DMA on "complex" transfers, i.e. with
@@ -876,8 +880,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
        if (sg_len == 0)
                return -EINVAL;
 
-       if (next)
-               data->host_cookie = sg_len;
+       data->host_cookie = cookie;
 
        return sg_len;
 }
@@ -892,13 +895,12 @@ static void dw_mci_pre_req(struct mmc_host *mmc,
        if (!slot->host->use_dma || !data)
                return;
 
-       if (data->host_cookie) {
-               data->host_cookie = 0;
-               return;
-       }
+       /* This data might be unmapped at this time */
+       data->host_cookie = COOKIE_UNMAPPED;
 
-       if (dw_mci_pre_dma_transfer(slot->host, mrq->data, 1) < 0)
-               data->host_cookie = 0;
+       if (dw_mci_pre_dma_transfer(slot->host, mrq->data,
+                               COOKIE_PRE_MAPPED) < 0)
+               data->host_cookie = COOKIE_UNMAPPED;
 }
 
 static void dw_mci_post_req(struct mmc_host *mmc,
@@ -911,12 +913,12 @@ static void dw_mci_post_req(struct mmc_host *mmc,
        if (!slot->host->use_dma || !data)
                return;
 
-       if (data->host_cookie)
+       if (data->host_cookie != COOKIE_UNMAPPED)
                dma_unmap_sg(slot->host->dev,
                             data->sg,
                             data->sg_len,
                             dw_mci_get_dma_dir(data));
-       data->host_cookie = 0;
+       data->host_cookie = COOKIE_UNMAPPED;
 }
 
 static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
@@ -1022,7 +1024,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
        if (!host->use_dma)
                return -ENODEV;
 
-       sg_len = dw_mci_pre_dma_transfer(host, data, 0);
+       sg_len = dw_mci_pre_dma_transfer(host, data, COOKIE_MAPPED);
        if (sg_len < 0) {
                host->dma_ops->stop(host);
                return sg_len;
@@ -1273,10 +1275,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
                spin_unlock_irqrestore(&host->irq_lock, irqflags);
        }
 
-       if (mrq->stop)
-               host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
-       else
-               host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
+       host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
 }
 
 static void dw_mci_start_request(struct dw_mci *host,
@@ -1536,13 +1535,10 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
                        == 0 ? 1 : 0;
 
        spin_lock_bh(&host->lock);
-       if (present) {
-               set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+       if (present && !test_and_set_bit(DW_MMC_CARD_PRESENT, &slot->flags))
                dev_dbg(&mmc->class_dev, "card is present\n");
-       } else {
-               clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+       else if (!test_and_clear_bit(DW_MMC_CARD_PRESENT, &slot->flags))
                dev_dbg(&mmc->class_dev, "card is not present\n");
-       }
        spin_unlock_bh(&host->lock);
 
        return present;
@@ -1889,8 +1885,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
                        if (test_and_clear_bit(EVENT_DATA_ERROR,
                                               &host->pending_events)) {
                                dw_mci_stop_dma(host);
-                               if (data->stop ||
-                                   !(host->data_status & (SDMMC_INT_DRTO |
+                               if (!(host->data_status & (SDMMC_INT_DRTO |
                                                           SDMMC_INT_EBE)))
                                        send_stop_abort(host, data);
                                state = STATE_DATA_ERROR;
@@ -1926,8 +1921,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
                        if (test_and_clear_bit(EVENT_DATA_ERROR,
                                               &host->pending_events)) {
                                dw_mci_stop_dma(host);
-                               if (data->stop ||
-                                   !(host->data_status & (SDMMC_INT_DRTO |
+                               if (!(host->data_status & (SDMMC_INT_DRTO |
                                                           SDMMC_INT_EBE)))
                                        send_stop_abort(host, data);
                                state = STATE_DATA_ERROR;
@@ -2003,7 +1997,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
                        host->cmd = NULL;
                        host->data = NULL;
 
-                       if (mrq->stop)
+                       if (!mrq->sbc && mrq->stop)
                                dw_mci_command_complete(host, mrq->stop);
                        else
                                host->cmd_status = 0;
@@ -2615,6 +2609,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                mmc->f_min = DW_MCI_FREQ_MIN;
                mmc->f_max = DW_MCI_FREQ_MAX;
        } else {
+               dev_info(host->dev,
+                       "'clock-freq-min-max' property was deprecated.\n");
                mmc->f_min = freq[0];
                mmc->f_max = freq[1];
        }
@@ -3267,28 +3263,42 @@ EXPORT_SYMBOL(dw_mci_remove);
 
 
 
-#ifdef CONFIG_PM_SLEEP
-/*
- * TODO: we should probably disable the clock to the card in the suspend path.
- */
-int dw_mci_suspend(struct dw_mci *host)
+#ifdef CONFIG_PM
+int dw_mci_runtime_suspend(struct device *dev)
 {
+       struct dw_mci *host = dev_get_drvdata(dev);
+
        if (host->use_dma && host->dma_ops->exit)
                host->dma_ops->exit(host);
 
+       clk_disable_unprepare(host->ciu_clk);
+
+       if (host->cur_slot &&
+           (mmc_can_gpio_cd(host->cur_slot->mmc) ||
+            !mmc_card_is_removable(host->cur_slot->mmc)))
+               clk_disable_unprepare(host->biu_clk);
+
        return 0;
 }
-EXPORT_SYMBOL(dw_mci_suspend);
+EXPORT_SYMBOL(dw_mci_runtime_suspend);
 
-int dw_mci_resume(struct dw_mci *host)
+int dw_mci_runtime_resume(struct device *dev)
 {
-       int i, ret;
+       int i, ret = 0;
+       struct dw_mci *host = dev_get_drvdata(dev);
 
-       if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) {
-               ret = -ENODEV;
-               return ret;
+       if (host->cur_slot &&
+           (mmc_can_gpio_cd(host->cur_slot->mmc) ||
+            !mmc_card_is_removable(host->cur_slot->mmc))) {
+               ret = clk_prepare_enable(host->biu_clk);
+               if (ret)
+                       return ret;
        }
 
+       ret = clk_prepare_enable(host->ciu_clk);
+       if (ret)
+               return ret;
+
        if (host->use_dma && host->dma_ops->init)
                host->dma_ops->init(host);
 
@@ -3296,8 +3306,8 @@ int dw_mci_resume(struct dw_mci *host)
         * Restore the initial value at FIFOTH register
         * And Invalidate the prev_blksz with zero
         */
-       mci_writel(host, FIFOTH, host->fifoth_val);
-       host->prev_blksz = 0;
+        mci_writel(host, FIFOTH, host->fifoth_val);
+        host->prev_blksz = 0;
 
        /* Put in max timeout */
        mci_writel(host, TMOUT, 0xFFFFFFFF);
@@ -3322,10 +3332,10 @@ int dw_mci_resume(struct dw_mci *host)
        /* Now that slots are all setup, we can enable card detect */
        dw_mci_enable_cd(host);
 
-       return 0;
+       return ret;
 }
-EXPORT_SYMBOL(dw_mci_resume);
-#endif /* CONFIG_PM_SLEEP */
+EXPORT_SYMBOL(dw_mci_runtime_resume);
+#endif /* CONFIG_PM */
 
 static int __init dw_mci_init(void)
 {