input: keyboard: rk_keys: add rk_keys.h
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / host / rk_sdmmc.c
index 7f8012ead0cdd76d5e3bc94209b7f42b4e37cb2e..27b114179fe264a5fdbfdd9a3b79426b331e9d23 100755 (executable)
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 #include <linux/log2.h>
+#include <asm-generic/dma-mapping-common.h>
 #include "rk_sdmmc.h"
 #include "rk_sdmmc_dbg.h"
 #include <linux/regulator/rockchip_io_vol_domain.h>
 #include "../../clk/rockchip/clk-ops.h"
+#include <linux/rk_keys.h>
 
 #define RK_SDMMC_DRIVER_VERSION "Ver 2.00 2015-06-10"
 
@@ -110,7 +112,6 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host);
 static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host);
 static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset);
 static void dw_mci_disable_low_power(struct dw_mci_slot *slot);
-extern void rk_send_wakeup_key(void);
 
 #if defined(CONFIG_DEBUG_FS)
 static int dw_mci_req_show(struct seq_file *s, void *v)
@@ -637,8 +638,7 @@ static int dw_mci_edmac_init(struct dw_mci *host)
         host->dms->ch = dma_request_slave_channel(host->dev, "dw_mci");
         if (!host->dms->ch) {
                 dev_err(host->dev,
-                       "Failed to get external DMA channel %d\n",
-                       host->dms->ch->chan_id);
+                       "Failed to get external DMA channel\n");
                kfree(host->dms);
                host->dms = NULL;
                return -ENXIO;
@@ -669,12 +669,17 @@ static const struct dw_mci_dma_ops dw_mci_edmac_ops = {
 };
 #endif /* CONFIG_MMC_DW_IDMAC */
 
+static struct dma_attrs dw_mci_direct_attrs;
+
 static int dw_mci_pre_dma_transfer(struct dw_mci *host,
                                   struct mmc_data *data,
                                   bool next)
 {
        struct scatterlist *sg;
        unsigned int i, sg_len;
+#ifdef CONFIG_MMC_DW_SKIP_CACHE_OP
+       struct dma_attrs *attrs;
+#endif
 
        if (!next && data->host_cookie)
                return data->host_cookie;
@@ -694,11 +699,19 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
                if (sg->offset & 3 || sg->length & 3)
                        return -EINVAL;
        }
+#ifdef CONFIG_MMC_DW_SKIP_CACHE_OP
+       attrs = (data->flags & MMC_DATA_DIRECT) ? &dw_mci_direct_attrs : NULL;
+       sg_len = dma_map_sg_attrs(host->dev,
+                                data->sg,
+                                data->sg_len,
+                                dw_mci_get_dma_dir(data), attrs);
+#else
 
        sg_len = dma_map_sg(host->dev,
                            data->sg,
                            data->sg_len,
                            dw_mci_get_dma_dir(data));
+#endif
        if (sg_len == 0)
                return -EINVAL;
 
@@ -1228,6 +1241,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
        host->pending_events = 0;
        host->completed_events = 0;
        host->data_status = 0;
+       host->cmd_status = 0;
 
        data = cmd->data;
        if (data) {
@@ -1955,27 +1969,34 @@ static void dw_mci_post_tmo(struct mmc_host *mmc)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
        struct dw_mci *host = slot->host;
-       struct mmc_data *data;
-       u32 ret, i, regs, cmd_flags;
+       u32 i, regs, cmd_flags;
        u32 sdio_int;
        unsigned long timeout = 0;
-       bool ret_timeout = true;
-       u32 opcode;
+       bool ret_timeout = true, is_retry = false;
+       u32 opcode, offset;
 
+       if (host->cur_slot->mrq->data)
+               dw_mci_stop_dma(host);
+
+       offset = host->cru_reset_offset;
        opcode = host->mrq->cmd->opcode;
        host->cur_slot->mrq = NULL;
        host->mrq = NULL;
        host->state = STATE_IDLE;
+       host->data = NULL;
 
-       data = host->data;
-
-       if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
+       if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) ||
            (opcode == MMC_SEND_TUNING_BLOCK))
-           return;
+               return;
 
        printk("[%s] -- Timeout recovery procedure start --\n",
                mmc_hostname(host->mmc));
 
+       /* unmask irq */
+       mci_writel(host, INTMASK, 0x0);
+
+retry_stop:
+       /* send stop cmd */
        mci_writel(host, CMDARG, 0);
        wmb();
        cmd_flags = SDMMC_CMD_STOP | SDMMC_CMD_RESP_CRC |
@@ -1986,7 +2007,7 @@ static void dw_mci_post_tmo(struct mmc_host *mmc)
 
        mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
        wmb();
-       timeout = jiffies + msecs_to_jiffies(500);
+       timeout = jiffies + msecs_to_jiffies(10);
 
        while(ret_timeout) {
                ret_timeout = time_before(jiffies, timeout);
@@ -1994,13 +2015,29 @@ static void dw_mci_post_tmo(struct mmc_host *mmc)
                        break;
        }
 
-       if (false == ret_timeout)
+       if (false == ret_timeout) {
                MMC_DBG_ERR_FUNC(host->mmc, "stop recovery failed![%s]",
                                 mmc_hostname(host->mmc));
-
-       if (!dw_mci_ctrl_all_reset(host)) {
-               ret = -ENODEV;
-               return ;
+               if (host->cid == DW_MCI_TYPE_RK3368) {
+                       /* pd_peri mmc AHB bus software reset request */
+                       regmap_write(host->cru, host->cru_regsbase,
+                                       (0x1<<offset)<<16 | (0x1 << offset));
+                       mdelay(1);
+                       regmap_write(host->cru, host->cru_regsbase,
+                                       (0x1<<offset)<<16 | (0x0 << offset));
+               } else {
+                       /* pd_peri mmc AHB bus software reset request */
+                       cru_writel(((0x1<<offset)<<16) | (0x1 << offset),
+                                       host->cru_regsbase);
+                       mdelay(1);
+                       cru_writel(((0x1<<offset)<<16) | (0x0 << offset),
+                                       host->cru_regsbase);
+               }
+       } else {
+               if (!dw_mci_ctrl_all_reset(host))
+                       return;
+               if (is_retry == true)
+                       goto recovery_end;
        }
 
 #ifdef CONFIG_MMC_DW_IDMAC
@@ -2010,15 +2047,16 @@ static void dw_mci_post_tmo(struct mmc_host *mmc)
 #endif
 
        /*
-       * Restore the initial value at FIFOTH register
-       * And Invalidate the prev_blksz with zero
-       */
+        * 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, TMOUT, 0xFFFFFFFF);
        mci_writel(host, RINTSTS, 0xFFFFFFFF);
-       regs = SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | SDMMC_INT_TXDR
-                       | SDMMC_INT_RXDR | SDMMC_INT_VSI | DW_MCI_ERROR_FLAGS;
+       regs = SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+               SDMMC_INT_TXDR | SDMMC_INT_RXDR | SDMMC_INT_VSI |
+               DW_MCI_ERROR_FLAGS;
        if (!(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO))
                regs |= SDMMC_INT_CD;
 
@@ -2044,7 +2082,13 @@ static void dw_mci_post_tmo(struct mmc_host *mmc)
                }
        }
        mci_writel(host, RINTSTS, 0xFFFFFFFF);
+       if (ret_timeout == false) {
+               ret_timeout = true;
+               is_retry = true;
+               goto retry_stop;
+       }
 
+recovery_end:
        printk("[%s] -- Timeout recovery procedure finished --\n",
                mmc_hostname(host->mmc));
 }
@@ -3522,6 +3566,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                        regmap_write(host->grf, 0x43c, (1<<13)<<16 | (0 << 13));
        } else if (cpu_is_rk3288()) {
                grf_writel(((1 << 12) << 16) | (0 << 12), RK3288_GRF_SOC_CON0);
+       } else if (host->cid == DW_MCI_TYPE_RK3228) {
+               grf_writel(((1 << 8) << 16) | (0 << 8), RK3228_GRF_SOC_CON6);
        }
 
        /* We assume only low-level chip use gpio_cd */
@@ -3624,9 +3670,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 #ifdef CONFIG_MMC_DW_IDMAC
                mmc->max_segs = host->ring_size;
                mmc->max_blk_size = 65536;
-               mmc->max_blk_count = host->ring_size;
                mmc->max_seg_size = 0x1000;
-               mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count;
+               mmc->max_req_size = mmc->max_seg_size * host->ring_size;
+               mmc->max_blk_count = mmc->max_req_size / 512;
+
                if(cpu_is_rk3036() || cpu_is_rk312x()){
                         /* fixup for external dmac setting */
                         mmc->max_segs = 64;
@@ -3935,6 +3982,20 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
        if (of_get_property(np, "assume_removable", NULL))
                mmc_assume_removable = 0;
 
+       if (!of_property_read_u32(np, "cru_regsbase", &host->cru_regsbase)) {
+               printk("dw cru_regsbase addr 0x%03x.\n", host->cru_regsbase);
+       } else {
+               pr_err("dw cru_regsbase addr is missing!\n");
+               return ERR_PTR(-1);
+       }
+
+       if (!of_property_read_u32(np, "cru_reset_offset", &host->cru_reset_offset)) {
+               printk("dw cru_reset_offset val %d.\n", host->cru_reset_offset);
+       } else {
+               pr_err("dw cru_reset_offset val is missing!\n");
+               return ERR_PTR(-1);
+       }
+
        return pdata;
 }
 
@@ -4073,6 +4134,9 @@ int dw_mci_probe(struct dw_mci *host)
        if (!dw_mci_ctrl_all_reset(host))
                return -ENODEV;
 
+       init_dma_attrs(&dw_mci_direct_attrs);
+       dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &dw_mci_direct_attrs);
+
        host->dma_ops = host->pdata->dma_ops;
        dw_mci_init_dma(host);