mmc: rk3126: add wakeup event for SD insert/remove in deep sleep
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / host / rk_sdmmc.c
index 899bf5a6eb3a25386ebfd83ef0f029a8d8c9daf8..fd72bcac5e7639c25a3fa8cd0200a2b8c5e2ebd2 100755 (executable)
@@ -33,6 +33,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sd.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/rk_mmc.h>
 #include <linux/bitops.h>
 #include <linux/regulator/rockchip_io_vol_domain.h>
 #include "../../clk/rockchip/clk-ops.h"
 
-/*
-        Fixme: 3036: RK_GRF_VIRT compatitable?
-*/
-#define grf_writel(v, offset)   do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
-
-#define RK_SDMMC_DRIVER_VERSION "Ver 1.11 2014-06-05" 
+#define RK_SDMMC_DRIVER_VERSION "Ver 1.13 2014-09-05"
 
 /* Common flag combinations */
 #define DW_MCI_DATA_ERROR_FLAGS        (SDMMC_INT_DRTO | SDMMC_INT_DCRC | \
@@ -457,25 +453,26 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host)
 static void dw_mci_idmac_complete_dma(void *arg)
 {
         struct dw_mci *host = arg;
-       struct mmc_data *data = host->data;
+        struct mmc_data *data = host->data;
 
-       dev_vdbg(host->dev, "DMA complete\n");
+        dev_vdbg(host->dev, "DMA complete\n");
 
-    /*
-    MMC_DBG_CMD_FUNC(host->mmc," DMA complete cmd=%d(arg=0x%x), blocks=%d,blksz=%d[%s]", \
-        host->mrq->cmd->opcode,host->mrq->cmd->arg,data->blocks,data->blksz,mmc_hostname(host->mmc));
-    */
-    
-       host->dma_ops->cleanup(host);
+        /*
+        MMC_DBG_CMD_FUNC(host->mmc," DMA complete cmd=%d(arg=0x%x), blocks=%d,blksz=%d[%s]", \
+                host->mrq->cmd->opcode,host->mrq->cmd->arg,
+                data->blocks,data->blksz,mmc_hostname(host->mmc));
+        */
+
+        host->dma_ops->cleanup(host);
 
        /*
         * If the card was removed, data will be NULL. No point in trying to
         * send the stop command or waiting for NBUSY in this case.
         */
-       if (data) {
-               set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
-               tasklet_schedule(&host->tasklet);
-       }
+        if(data){
+                set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
+                tasklet_schedule(&host->tasklet);
+        }
 }
 
 static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
@@ -567,9 +564,8 @@ static const struct dw_mci_dma_ops dw_mci_idmac_ops = {
        .complete = dw_mci_idmac_complete_dma,
        .cleanup = dw_mci_dma_cleanup,
 };
-#endif /* CONFIG_MMC_DW_IDMAC */
 
-#ifdef CONFIG_MMC_DW_EDMAC
+
 static void dw_mci_edma_cleanup(struct dw_mci *host)
 {
        struct mmc_data *data = host->data;
@@ -593,7 +589,13 @@ static void dw_mci_edmac_complete_dma(void *arg)
 
         dev_vdbg(host->dev, "DMA complete\n");
 
-       host->dma_ops->cleanup(host);
+        if(data)
+                if(data->flags & MMC_DATA_READ)
+                        /* Invalidate cache after read */
+                        dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
+                                data->sg_len, DMA_FROM_DEVICE);
+
+        host->dma_ops->cleanup(host);
 
        /*
         * If the card was removed, data will be NULL. No point in trying to
@@ -610,96 +612,114 @@ static void dw_mci_edmac_start_dma(struct dw_mci *host, unsigned int sg_len)
         struct dma_slave_config slave_config;
         struct dma_async_tx_descriptor *desc = NULL;
         struct scatterlist *sgl = host->data->sg;
+        u32 sg_elems = host->data->sg_len;
         int ret = 0;
 
-       /* set external dma config: burst size, burst width*/
-       if(host->data->flags & MMC_DATA_WRITE){
-                slave_config.direction = DMA_MEM_TO_DEV;
-                slave_config.dst_addr = (dma_addr_t)(host->regs + host->data_offset);
-                slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-                slave_config.dst_maxburst = 16;
+        /* Set external dma config: burst size, burst width*/
+        slave_config.dst_addr = (dma_addr_t)(host->phy_regs + host->data_offset);
+        slave_config.src_addr = slave_config.dst_addr;
+        slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+        slave_config.src_addr_width = slave_config.dst_addr_width;
+
+        /* Match FIFO dma burst MSIZE with external dma config*/
+        slave_config.dst_maxburst = ((host->fifoth_val) >> 28) && 0x7;
+        slave_config.src_maxburst = slave_config.dst_maxburst;
 
+        if(host->data->flags & MMC_DATA_WRITE){
+                slave_config.direction = DMA_MEM_TO_DEV;
                 ret = dmaengine_slave_config(host->dms->ch, &slave_config);
-                if (ret) {
+                if(ret){
                         dev_err(host->dev, "error in dw_mci edma configuration.\n");
                         return;
                 }
 
                 desc = dmaengine_prep_slave_sg(host->dms->ch, sgl, sg_len,
-                                DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
-                if (!desc) {
-                       dev_err(host->dev, "We cannot prepare for the dw_mci slave edma!\n");
-                       return;
-               }
-                /* set dw_mci_edmac_complete_dma as callback */
-               desc->callback = dw_mci_edmac_complete_dma;
-               desc->callback_param = (void *)host;
-               dmaengine_submit(desc);
-               /* flush cache before write & Invalidate cache after read ??? */
-                //dma_sync_single_for_device(host->dms->ch->device->dev, host->sg_dma,
-                //                        sg_len, DMA_TO_DEVICE);
+                                DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+                if(!desc){
+                        dev_err(host->dev, "We cannot prepare for the dw_mci slave edma!\n");
+                        return;
+                }
+                /* Set dw_mci_edmac_complete_dma as callback */
+                desc->callback = dw_mci_edmac_complete_dma;
+                desc->callback_param = (void *)host;
+                dmaengine_submit(desc);
+
+                /* Flush cache before write */
+                dma_sync_sg_for_device(mmc_dev(host->mmc), sgl,
+                                        sg_elems, DMA_TO_DEVICE);
                 dma_async_issue_pending(host->dms->ch);
-       }else{
+        }else{
                 /* MMC_DATA_READ*/
                 slave_config.direction = DMA_DEV_TO_MEM;
-                slave_config.src_addr = (dma_addr_t)(host->regs + host->data_offset);
-                slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-                slave_config.src_maxburst = 16;
-
                 ret = dmaengine_slave_config(host->dms->ch, &slave_config);
-                if (ret) {
+                if(ret){
                         dev_err(host->dev, "error in dw_mci edma configuration.\n");
                         return;
                 }
                 desc = dmaengine_prep_slave_sg(host->dms->ch, sgl, sg_len,
-                       DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
-                if (!desc) {
-                       dev_err(host->dev, "We cannot prepare for the dw_mci slave edma!\n");
-                       return;
-               }
-                /* set dw_mci_edmac_complete_dma as callback */
-               desc->callback = dw_mci_edmac_complete_dma;
-               desc->callback_param = (void *)host;
-               dmaengine_submit(desc);
-               dma_async_issue_pending(host->dms->ch);
-       }
-
-       return;
+                                DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+                if(!desc){
+                        dev_err(host->dev, "We cannot prepare for the dw_mci slave edma!\n");
+                        return;
+                }
+                /* set dw_mci_edmac_complete_dma as callback */
+                desc->callback = dw_mci_edmac_complete_dma;
+                desc->callback_param = (void *)host;
+                dmaengine_submit(desc);
+                dma_async_issue_pending(host->dms->ch);
+        }
 }
 
 static int dw_mci_edmac_init(struct dw_mci *host)
 {
-        MMC_DBG_BOOT_FUNC(host->mmc,"dw_mci_edmac_init: Soc is 0x%x [%s]\n",
-                                (unsigned int)(rockchip_soc_id & ROCKCHIP_CPU_MASK), mmc_hostname(host->mmc));
+        /* Request external dma channel, SHOULD decide chn in dts */
+        host->dms = NULL;
+        host->dms = (struct dw_mci_dma_slave *)kmalloc
+                                (sizeof(struct dw_mci_dma_slave), GFP_KERNEL);
+        if (NULL == host->dms) {
+                dev_err(host->dev, "No enough memory to alloc dms.\n");
+                goto err_exit;
+        }
 
-        /* 1) request external dma channel, SHOULD decide chn in dts */
         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: channel id = %d\n",
-                               host->dms->ch->chan_id);
-               goto err_exit;
-       }
-
-        /* anything? */
+        if (!host->dms->ch) {
+                dev_err(host->dev, "Failed to get external DMA channel: channel id = %d\n",
+                                host->dms->ch->chan_id);
+                goto err_exit;
+        }
 
-       return 0;
+        return 0;
 
 err_exit:
-        return -ENODEV;
+        if (NULL != host->dms) {
+                kfree(host->dms);
+                host->dms = NULL;
+        }
+        return -ENXIO;
 
 }
 
-
+static void dw_mci_edmac_exit(struct dw_mci *host)
+{
+        if (NULL != host->dms) {
+                if (NULL != host->dms->ch) {
+                        dma_release_channel(host->dms->ch);
+                        host->dms->ch = NULL;
+                }
+                kfree(host->dms);
+                host->dms = NULL;
+        }
+}
 
 static const struct dw_mci_dma_ops dw_mci_edmac_ops = {
         .init = dw_mci_edmac_init,
+        .exit = dw_mci_edmac_exit,
         .start = dw_mci_edmac_start_dma,
-       .stop = dw_mci_edmac_stop_dma,
-       .complete = dw_mci_edmac_complete_dma,
-       .cleanup = dw_mci_edma_cleanup,
+        .stop = dw_mci_edmac_stop_dma,
+        .complete = dw_mci_edmac_complete_dma,
+        .cleanup = dw_mci_edma_cleanup,
 };
-#endif
+#endif /* CONFIG_MMC_DW_IDMAC */
 
 static int dw_mci_pre_dma_transfer(struct dw_mci *host,
                                   struct mmc_data *data,
@@ -1051,7 +1071,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
                        MMC_DBG_BOOT_FUNC(host->mmc,
                                 "dw_mci_setup_bus: argue clk_mmc workaround out %dHz for init[%s]",
                                 clock * 2, mmc_hostname(host->mmc)); 
-                        /* RK3288 clk_mmc will change parents to 24MHz xtal*/
+                        /* clk_mmc will change parents to 24MHz xtal*/
                        clk_set_rate(host->clk_mmc, clock * 2);                
 
                        div = 0;
@@ -1088,9 +1108,19 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
                            mmcblk0: retrying using single block read
                            mmcblk0: error -110 sending status command, retrying
 
-                           How to: If eMMC HW version < 4.51, or > 4.51 but no caps2-mmc-hs200 support in dts
-                                   Please set dts emmc clk to 100M or 150M, I will workaround it!
+                           We assume all eMMC in RK platform with 3.10 kernel, at least version 4.5
                          */
+                        if ((div == 0) &&
+                                (host->mmc->caps & (MMC_CAP_1_8V_DDR | MMC_CAP_1_2V_DDR)) &&
+                                !(host->mmc->caps2 & MMC_CAP2_HS200)) {
+                                /*  Fixup DDR MMC */
+                                div = 1;
+                                host->set_div = div;
+                                host->bus_hz = host->set_speed * 2;
+                                MMC_DBG_BOOT_FUNC(host->mmc,
+                                        "dw_mci_setup_bus: workaround div = %d, host->bus_hz = %d [%s]",
+                                        div, host->bus_hz, mmc_hostname(host->mmc));
+                        }
 
                        if (host->verid < DW_MMC_240A)
                                clk_set_rate(host->clk_mmc,(host->bus_hz));
@@ -1140,29 +1170,47 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
        mci_writel(host, CTYPE, (slot->ctype << slot->id));
 }
 
+extern struct mmc_card *this_card;
 static void dw_mci_wait_unbusy(struct dw_mci *host)
 {
    
-    unsigned int    timeout= SDMMC_DATA_TIMEOUT_SDIO;
-    unsigned long   time_loop;
-    unsigned int    status;
+        unsigned int    timeout= SDMMC_DATA_TIMEOUT_SDIO;
+        unsigned long   time_loop;
+        unsigned int    status;
+        u32 se_flag = 0;
 
-    MMC_DBG_INFO_FUNC(host->mmc, "dw_mci_wait_unbusy, status=0x%x ", mci_readl(host, STATUS));
+        MMC_DBG_INFO_FUNC(host->mmc, "dw_mci_wait_unbusy, status=0x%x ", mci_readl(host, STATUS));
     
-    if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC)
-        timeout = SDMMC_DATA_TIMEOUT_EMMC;
-    else if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)
-        timeout = SDMMC_DATA_TIMEOUT_SD;
+        if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC) {
+                if (host->cmd && (host->cmd->opcode == MMC_ERASE)) {
+                /* Special care for (secure)erase timeout calculation */
+                        if(this_card){
+                                if((host->cmd->arg & (0x1 << 31)) == 1) /* secure erase */
+                                        se_flag = 0x1;
+
+                                if (((this_card->ext_csd.erase_group_def) & 0x1) == 1) ;
+                                        se_flag ? (timeout = (this_card->ext_csd.hc_erase_timeout) *
+                                                        300000 * (this_card->ext_csd.sec_erase_mult)) :
+                                                        (timeout = (this_card->ext_csd.hc_erase_timeout) * 300000);
+                        }
+                }
         
-    time_loop = jiffies + msecs_to_jiffies(timeout);
-    do {
-       status = mci_readl(host, STATUS);
-       if (!(status & (SDMMC_STAUTS_DATA_BUSY | SDMMC_STAUTS_MC_BUSY)))
-               break;
-    } while (time_before(jiffies, time_loop));
+                if(timeout < SDMMC_DATA_TIMEOUT_EMMC)
+                        timeout = SDMMC_DATA_TIMEOUT_EMMC;
+        } else if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) {
+                timeout = SDMMC_DATA_TIMEOUT_SD;
+        }
+
+        time_loop = jiffies + msecs_to_jiffies(timeout);
+        do {
+                status = mci_readl(host, STATUS);
+                if (!(status & (SDMMC_STAUTS_DATA_BUSY | SDMMC_STAUTS_MC_BUSY)))
+                        break;
+        } while (time_before(jiffies, time_loop));
 }
 
 
+
 #ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
 /*
 *   result: 
@@ -1467,12 +1515,39 @@ static int dw_mci_set_sdio_status(struct mmc_host *mmc, int val)
 
 static int dw_mci_get_cd(struct mmc_host *mmc)
 {
-       int present;
-       struct dw_mci_slot *slot = mmc_priv(mmc);
-       struct dw_mci_board *brd = slot->host->pdata;
-       struct dw_mci *host = slot->host;
-       int gpio_cd = mmc_gpio_get_cd(mmc);
-       
+        int present;
+        struct dw_mci_slot *slot = mmc_priv(mmc);
+        struct dw_mci_board *brd = slot->host->pdata;
+        struct dw_mci *host = slot->host;
+        int gpio_cd = mmc_gpio_get_cd(mmc);
+        int gpio_val;
+
+        if (cpu_is_rk312x() &&
+                soc_is_rk3126() &&
+                (mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)) {
+                gpio_cd = slot->cd_gpio;
+                if (gpio_is_valid(gpio_cd)) {
+                        gpio_val = gpio_get_value_cansleep(gpio_cd);
+                        msleep(10);
+                        if (gpio_val == gpio_get_value_cansleep(gpio_cd)) {
+                                gpio_cd = gpio_get_value_cansleep(gpio_cd) == 0 ? 1 : 0;
+                                if (gpio_cd == 0) {
+                                        /* Enable force_jtag wihtout card in slot, ONLY for NCD-package */
+                                        grf_writel((0x1 << 24) | (1 << 8), RK312X_GRF_SOC_CON0);
+                                        dw_mci_ctrl_all_reset(host);
+                                } else {
+                                        /* Really card detected: SHOULD disable force_jtag */
+                                        grf_writel((0x1 << 24) | (0 << 8), RK312X_GRF_SOC_CON0);
+                                }
+                        } else {
+                                /* Jitter */
+                                return slot->last_detect_state;
+                        }
+                } else {
+                        dev_err(host->dev, "dw_mci_get_cd: invalid gpio_cd!\n");
+                }
+        }
+
         if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)
                 return test_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 
@@ -1629,9 +1704,12 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
        struct dw_mci *host = slot->host;
+       //unsigned long flags;
        u32 int_mask;
        u32 sdio_int;
 
+        //spin_lock_irqsave(&host->lock, flags);
+
        /* Enable/disable Slot Specific SDIO interrupt */
        int_mask = mci_readl(host, INTMASK);
 
@@ -1655,6 +1733,8 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
                mci_writel(host, INTMASK,
                           (int_mask & ~sdio_int));
        }
+
+       //spin_unlock_irqrestore(&host->lock, flags);
 }
 
 #ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
@@ -1664,26 +1744,32 @@ enum{
         IO_DOMAIN_33 = 3300,
 };
 static void dw_mci_do_grf_io_domain_switch(struct dw_mci *host, u32 voltage)
-{       
-        /*
-                Fixme: 3036:  RK3288_GRF_IO_VSEL compatitable?
-        */
-
-        if(cpu_is_rk3288()){
-               if(voltage == IO_DOMAIN_33)
+{
+        switch(voltage){
+                case IO_DOMAIN_33:
                         voltage = 0;
-                else if(voltage == IO_DOMAIN_18)
+                        break;
+                case IO_DOMAIN_18:
                         voltage = 1;
-                else
-                     MMC_DBG_ERR_FUNC(host->mmc,"%s : err io domain voltage [%s]\n", 
-                          __FUNCTION__, mmc_hostname(host->mmc));
+                        break;
+                case IO_DOMAIN_12:
+                        MMC_DBG_ERR_FUNC(host->mmc,"%s : Not support io domain voltage [%s]\n",
+                                                        __FUNCTION__, mmc_hostname(host->mmc));
+                        break;
+                default:
+                        MMC_DBG_ERR_FUNC(host->mmc,"%s : Err io domain voltage [%s]\n",
+                                                        __FUNCTION__, mmc_hostname(host->mmc));
+                        break;
+        }
+
+        if(cpu_is_rk3288()){
                 if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)      
                         grf_writel((voltage << 7) | (1 << 23), RK3288_GRF_IO_VSEL);
                 else
                         return ;
         }else{
-                 MMC_DBG_ERR_FUNC(host->mmc,"%s : unknown chip [%s]\n", 
-                          __FUNCTION__, mmc_hostname(host->mmc));
+                MMC_DBG_ERR_FUNC(host->mmc,"%s : unknown chip [%s]\n",
+                                        __FUNCTION__, mmc_hostname(host->mmc));
         }
 }
 
@@ -1819,6 +1905,10 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
        struct dw_mci_tuning_data tuning_data;
        int err = -ENOSYS;
 
+        /* Fixme: 3036/3126 doesn't support 1.8 io domain, no sense exe tuning */
+        if(cpu_is_rk3036() || cpu_is_rk312x())
+                return err;
+
        if (opcode == MMC_SEND_TUNING_BLOCK_HS200) {
                if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
                        tuning_data.blk_pattern = tuning_blk_pattern_8bit;
@@ -1931,7 +2021,8 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
        struct mmc_host *prev_mmc = host->cur_slot->mmc;
 
        WARN_ON(host->cmd || host->data);
-       
+
+       del_timer_sync(&host->dto_timer);
         dw_mci_deal_data_end(host, mrq);
 
         if(mrq->cmd)
@@ -1992,22 +2083,26 @@ static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd
        {
            if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)
                host->cmd_rto += 1;
-               
-               cmd->error = -ETIMEDOUT;
-       }
-       else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC))
+
+               cmd->error = -ETIMEDOUT;
+                del_timer_sync(&host->dto_timer);
+       }else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC)){
+                del_timer_sync(&host->dto_timer);
                cmd->error = -EILSEQ;
-       else if (status & SDMMC_INT_RESP_ERR)
+        }else if (status & SDMMC_INT_RESP_ERR){
+                del_timer_sync(&host->dto_timer);
                cmd->error = -EIO;
-       else
+        }else{
                cmd->error = 0;
+       }
         MMC_DBG_CMD_FUNC(host->mmc, " command complete, cmd=%d,cmdError=%d [%s]",
                                 cmd->opcode, cmd->error,mmc_hostname(host->mmc));
 
        if (cmd->error) {
+                del_timer_sync(&host->dto_timer);
            if(MMC_SEND_STATUS != cmd->opcode)
                if(host->cmd_rto >= SDMMC_CMD_RTO_MAX_HOLD){
-                       MMC_DBG_ERR_FUNC(host->mmc, " command complete, cmd=%d,cmdError=%d [%s]",\
+                       MMC_DBG_CMD_FUNC(host->mmc, " command complete, cmd=%d,cmdError=%d [%s]",\
                                 cmd->opcode, cmd->error,mmc_hostname(host->mmc));
                         host->cmd_rto = 0;
                }
@@ -2059,21 +2154,23 @@ static void dw_mci_tasklet_func(unsigned long priv)
                                goto unlock;
                        }
                        
-            if (cmd->data && cmd->error) {
+                        if (cmd->data && cmd->error) {
+                                del_timer_sync(&host->dto_timer); /* delete the timer for INT_DTO */
                                dw_mci_stop_dma(host);
                                #if 1
-                if (data->stop) {
-                    send_stop_cmd(host, data);
-                    state = STATE_SENDING_STOP;
-                    break;
-                } else {
-                    host->data = NULL;
-                }
+                                if (data->stop) {
+                                        send_stop_cmd(host, data);
+                                        state = STATE_SENDING_STOP;
+                                        break;
+                                }else{
+                                        host->data = NULL;
+                                }
                                #else
                                send_stop_abort(host, data);
                                state = STATE_SENDING_STOP;
                                break;
                                #endif
+                                set_bit(EVENT_DATA_COMPLETE, &host->completed_events);
                        }
 
                        if (!host->mrq->data || cmd->error) {
@@ -2145,6 +2242,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
                                break;
                                
                        dw_mci_deal_data_end(host, host->mrq);                  
+                       del_timer_sync(&host->dto_timer); //delete the timer for INT_DTO
                         MMC_DBG_INFO_FUNC(host->mmc, 
                                "Pre-state[%d]-->NowState[%d]: STATE_DATA_BUSY, after EVENT_DATA_COMPLETE. [%s]", \
                                           prev_state,state,mmc_hostname(host->mmc));
@@ -2689,12 +2787,25 @@ host_put:
 
 static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
 {
-       if (!host->cmd_status)
+        u32 multi, unit = SZ_2M;
+
+        if (!host->cmd_status)
            host->cmd_status = status;
            
-       smp_wmb();
+        if (!host->cmd)
+               goto cmd_exit;
+
+        if ((MMC_STOP_TRANSMISSION != host->cmd->opcode)) {
+                multi = (mci_readl(host, BYTCNT) / unit) +
+                        ((mci_readl(host, BYTCNT) % unit) ? 1 :0 ) +
+                        ((host->cmd->retries > 2) ? 2 : host->cmd->retries);
+                /* Max limit time: 8s for dto */
+                mod_timer(&host->dto_timer, jiffies + msecs_to_jiffies(4000 * multi));
+        }
 
-       set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
+cmd_exit:
+        smp_wmb();
+        set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
        tasklet_schedule(&host->tasklet);
 }
 
@@ -2705,13 +2816,12 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
        int i;
 
        pending = mci_readl(host, MINTSTS); /* read-only mask reg */
-       //if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)
-       //      printk("%s pending: 0x%08x\n",__func__,pending);        
+
        /*
-                * DTO fix - version 2.10a and below, and only if internal DMA
-                * is configured.
-                */
-               if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
+       * DTO fix - version 2.10a and below, and only if internal DMA
+       * is configured.
+        */
+        if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
                        if (!pending &&
                            ((mci_readl(host, STATUS) >> 17) & 0x1fff))
                                pending |= SDMMC_INT_DATA_OVER;
@@ -2742,6 +2852,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
                if (pending & SDMMC_INT_DATA_OVER) {
                        mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER);
+                       del_timer(&host->dto_timer); /* delete the timer for INT_DTO */
                        MMC_DBG_CMD_FUNC(host->mmc, "SDMMC_INT_DATA_OVER, INT-pending=0x%x. [%s]",pending,mmc_hostname(host->mmc));
                        if (!host->data_status)
                                host->data_status = pending;
@@ -2809,13 +2920,16 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
        }
 
 #ifdef CONFIG_MMC_DW_IDMAC
-       /* Handle DMA interrupts */
-       pending = mci_readl(host, IDSTS);
-       if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
-               mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
-               mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
-               host->dma_ops->complete((void *)host);
-       }
+        /* External DMA Soc platform NOT need to ack interrupt IDSTS */
+        if(!(cpu_is_rk3036() || cpu_is_rk312x())){
+                /* Handle DMA interrupts */
+                pending = mci_readl(host, IDSTS);
+                if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+                        mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
+                        mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
+                        host->dma_ops->complete((void *)host);
+                }
+        }
 #endif
 
        return IRQ_HANDLED;
@@ -2842,6 +2956,7 @@ static void dw_mci_work_routine_card(struct work_struct *work)
                        rk_send_wakeup_key();//wake up system
                        spin_lock_bh(&host->lock);
 
+                        del_timer(&host->dto_timer); /* delete the timer for INT_DTO */
                        /* Card change detected */
                        slot->last_detect_state = present;
 
@@ -2885,7 +3000,8 @@ static void dw_mci_work_routine_card(struct work_struct *work)
                                        if (mrq->stop)
                                                mrq->stop->error = -ENOMEDIUM;
                                                
-                    MMC_DBG_CMD_FUNC(host->mmc, "dw_mci_work--reqeuest done, cmd=%d [%s]",mrq->cmd->opcode, mmc_hostname(mmc));
+                                        MMC_DBG_CMD_FUNC(host->mmc, "dw_mci_work--reqeuest done, cmd=%d [%s]",
+                                                        mrq->cmd->opcode, mmc_hostname(mmc));
 
                                        spin_unlock(&host->lock);
                                        mmc_request_done(slot->mmc, mrq);
@@ -2898,7 +3014,8 @@ static void dw_mci_work_routine_card(struct work_struct *work)
                                /* Clear down the FIFO */
                                dw_mci_fifo_reset(host);
 #ifdef CONFIG_MMC_DW_IDMAC
-                               dw_mci_idmac_reset(host);
+                                if(!(cpu_is_rk3036() || cpu_is_rk312x()))
+                                       dw_mci_idmac_reset(host);
 #endif
 
                        }
@@ -2909,7 +3026,7 @@ static void dw_mci_work_routine_card(struct work_struct *work)
                }
 
                mmc_detect_change(slot->mmc,
-                       msecs_to_jiffies(host->pdata->detect_delay_ms));
+                msecs_to_jiffies(host->pdata->detect_delay_ms));
        }
 }
 
@@ -3042,6 +3159,65 @@ static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
        if (mmc_gpio_request_cd(mmc, gpio, 0))
                dev_warn(dev, "gpio [%d] request failed\n", gpio);
 }
+
+static irqreturn_t dw_mci_gpio_cd_irqt(int irq, void *dev_id)
+{
+        struct mmc_host *mmc = dev_id;
+        struct dw_mci_slot *slot = mmc_priv(mmc);
+        struct dw_mci *host = slot->host;
+
+        #if 0
+        if (mmc->ops->card_event)
+                mmc->ops->card_event(mmc);
+
+        mmc_detect_change(mmc, msecs_to_jiffies(200));
+        #endif
+
+        queue_work(host->card_workqueue, &host->card_work);
+        return IRQ_HANDLED;
+}
+
+static void dw_mci_of_set_cd_gpio_irq(struct device *dev, u32 gpio,
+                                        struct mmc_host *mmc)
+{
+       struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct dw_mci *host = slot->host;
+       int irq;
+       int ret;
+
+       /* Having a missing entry is valid; return silently */
+       if (!gpio_is_valid(gpio))
+               return;
+
+       irq = gpio_to_irq(gpio);
+       if (irq >= 0) {
+               ret = devm_request_threaded_irq(&mmc->class_dev, irq,
+                                               NULL, dw_mci_gpio_cd_irqt,
+                                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                               "dw_mci_cd", mmc);
+               if (ret < 0) {
+                       irq = ret;
+                       dev_err(host->dev, "Request cd-gpio %d interrupt error!\n", gpio);
+               } else{
+                       /* enable wakeup event for gpio-cd in idle or deep suspend*/
+                       enable_irq_wake(irq);
+               }
+       } else {
+               dev_err(host->dev, "Cannot convert gpio %d to irq!\n", gpio);
+       }
+}
+
+static void dw_mci_of_free_cd_gpio_irq(struct device *dev, u32 gpio,
+                                        struct mmc_host *mmc)
+{
+        if (!gpio_is_valid(gpio))
+                return;
+
+        if (gpio_to_irq(gpio) >= 0) {
+                devm_free_irq(&mmc->class_dev, gpio_to_irq(gpio), mmc);
+                devm_gpio_free(&mmc->class_dev, gpio);
+        }
+}
 #else /* CONFIG_OF */
 static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
 {
@@ -3095,18 +3271,17 @@ 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;
                
-        printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__,__FUNCTION__,
-                mmc->f_min, mmc->f_max, mmc_hostname(mmc));    
+                printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__, __FUNCTION__,
+                        mmc->f_min, mmc->f_max, mmc_hostname(mmc));
        } else {
                mmc->f_min = freq[0];
                mmc->f_max = freq[1];
                
-        printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__,__FUNCTION__,
-                mmc->f_min, mmc->f_max,  mmc_hostname(mmc));    
+                printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__, __FUNCTION__,
+                        mmc->f_min, mmc->f_max,  mmc_hostname(mmc));
        }
-       
-    if(strstr("mmc0",mmc_hostname(mmc)))
-        printk("Line%d..%s: The rk_sdmmc %s",__LINE__, __FUNCTION__,RK_SDMMC_DRIVER_VERSION);
+
+       printk("%s : Rockchip specific MHSC: %s\n", mmc_hostname(mmc), RK_SDMMC_DRIVER_VERSION);
         
        if (of_find_property(host->dev->of_node, "supports-sd", NULL))
                mmc->restrict_caps |= RESTRICT_CARD_TYPE_SD;    
@@ -3114,6 +3289,24 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                mmc->restrict_caps |= RESTRICT_CARD_TYPE_SDIO;  
        if (of_find_property(host->dev->of_node, "supports-emmc", NULL))
                mmc->restrict_caps |= RESTRICT_CARD_TYPE_EMMC;
+       /* Fixup for tSD */
+        if (of_find_property(host->dev->of_node, "supports-tSD", NULL))
+               mmc->restrict_caps |= RESTRICT_CARD_TYPE_TSD;
+
+
+        /* We assume only low-level chip use gpio_cd */
+        if (cpu_is_rk312x() &&
+                soc_is_rk3126() &&
+                (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)) {
+                slot->cd_gpio = of_get_named_gpio(host->dev->of_node, "cd-gpios", 0);
+                if (gpio_is_valid(slot->cd_gpio)) {
+                        /* Request gpio int for card detection */
+                        dw_mci_of_set_cd_gpio_irq(host->dev, slot->cd_gpio,host->mmc);
+                } else {
+                        slot->cd_gpio = -ENODEV;
+                        dev_err(host->dev, "failed to get your cd-gpios!\n");
+                }
+        }
 
        if (host->pdata->get_ocr)
                mmc->ocr_avail = host->pdata->get_ocr(id);
@@ -3203,6 +3396,14 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                mmc->max_blk_count = host->ring_size;
                mmc->max_seg_size = 0x1000;
                mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count;
+               if(cpu_is_rk3036() || cpu_is_rk312x()){
+                        /* fixup for external dmac setting */
+                        mmc->max_segs = 64;
+                       mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */
+                       mmc->max_blk_count = 65535;
+                       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+                       mmc->max_seg_size = mmc->max_req_size; 
+                }
 #else
                mmc->max_segs = 64;
                mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */
@@ -3210,6 +3411,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
                mmc->max_seg_size = mmc->max_req_size;
 #endif /* CONFIG_MMC_DW_IDMAC */
+                
        }
         /* pwr_en */   
         slot->pwr_en_gpio = dw_mci_of_get_pwr_en_gpio(host->dev, slot->id);
@@ -3289,6 +3491,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        return 0;
 
 err_setup_bus:
+        if (gpio_is_valid(slot->cd_gpio))
+                dw_mci_of_free_cd_gpio_irq(host->dev, slot->cd_gpio,host->mmc);
        mmc_free_host(mmc);
        return -EINVAL;
 }
@@ -3318,11 +3522,13 @@ static void dw_mci_init_dma(struct dw_mci *host)
 
        /* Determine which DMA interface to use */
 #if defined(CONFIG_MMC_DW_IDMAC)
-       host->dma_ops = &dw_mci_idmac_ops;
-       dev_info(host->dev, "Using internal DMA controller.\n");
-#elif defined(CONFIG_MMC_DW_EDMAC)
-        host->dma_ops = &dw_mci_edmac_ops;
-        dev_info(host->dev, "Using external DMA controller.\n"); 
+        if(cpu_is_rk3036() || cpu_is_rk312x()){
+                host->dma_ops = &dw_mci_edmac_ops;
+                dev_info(host->dev, "Using external DMA controller.\n");
+        }else{
+                host->dma_ops = &dw_mci_idmac_ops;
+                dev_info(host->dev, "Using internal DMA controller.\n");
+        }
 #endif
 
        if (!host->dma_ops)
@@ -3489,6 +3695,73 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 }
 #endif /* CONFIG_OF */
 
+static void dw_mci_dealwith_timeout(struct dw_mci *host)
+{
+        u32 ret, i, regs;
+
+        switch(host->state){
+                case STATE_IDLE:
+                        break;
+                case STATE_SENDING_DATA:
+                case STATE_DATA_BUSY:
+                       host->data_status |= (SDMMC_INT_DCRC|SDMMC_INT_EBE);
+                       mci_writel(host, RINTSTS, SDMMC_INT_DRTO);  // clear interrupt
+                        set_bit(EVENT_DATA_COMPLETE, &host->pending_events);
+                        host->state = STATE_DATA_BUSY;
+                       if (!dw_mci_ctrl_all_reset(host)) {
+                                ret = -ENODEV;
+                                return ;
+                        }
+
+                        /* NO requirement to reclaim slave chn using external dmac */
+                        #ifdef CONFIG_MMC_DW_IDMAC
+                        if(!(cpu_is_rk3036() || cpu_is_rk312x()))
+                                if (host->use_dma && host->dma_ops->init)
+                                       host->dma_ops->init(host);
+                        #endif
+
+                        /*
+                         * 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;
+                        if(!(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO))
+                                regs |= SDMMC_INT_CD;
+                                mci_writel(host, INTMASK, regs);
+                        mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
+                        for (i = 0; i < host->num_slots; i++) {
+                                struct dw_mci_slot *slot = host->slot[i];
+                                if (!slot)
+                                        continue;
+                                if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
+                                        dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
+                                        dw_mci_setup_bus(slot, true);
+                                }
+                        }
+                        mci_writel(host, RINTSTS, 0xFFFFFFFF);
+                        tasklet_schedule(&host->tasklet);
+                        break;
+                default:
+                        break;
+    }
+}
+static void dw_mci_dto_timeout(unsigned long host_data)
+{
+       struct dw_mci *host = (struct dw_mci *) host_data;
+
+       disable_irq(host->irq);
+
+       host->data_status = SDMMC_INT_EBE;
+       mci_writel(host, RINTSTS, 0xFFFFFFFF);
+       dw_mci_dealwith_timeout(host);
+
+       enable_irq(host->irq);
+}
 int dw_mci_probe(struct dw_mci *host)
 {
        const struct dw_mci_drv_data *drv_data = host->drv_data;
@@ -3661,6 +3934,7 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
 
+        setup_timer(&host->dto_timer, dw_mci_dto_timeout, (unsigned long)host);
        /* We need at least one slot to succeed */
        for (i = 0; i < host->num_slots; i++) {
                ret = dw_mci_init_slot(host, i);
@@ -3729,36 +4003,42 @@ EXPORT_SYMBOL(dw_mci_probe);
 
 void dw_mci_remove(struct dw_mci *host)
 {
+        struct mmc_host *mmc = host->mmc;
+        struct dw_mci_slot *slot = mmc_priv(mmc);
        int i;
 
-       mci_writel(host, RINTSTS, 0xFFFFFFFF);
-       mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
+       del_timer_sync(&host->dto_timer);
 
-       for (i = 0; i < host->num_slots; i++) {
-               dev_dbg(host->dev, "remove slot %d\n", i);
-               if (host->slot[i])
-                       dw_mci_cleanup_slot(host->slot[i], i);
-       }
+        mci_writel(host, RINTSTS, 0xFFFFFFFF);
+        mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
 
-       /* disable clock to CIU */
-       mci_writel(host, CLKENA, 0);
-       mci_writel(host, CLKSRC, 0);
+        for(i = 0; i < host->num_slots; i++){
+                dev_dbg(host->dev, "remove slot %d\n", i);
+                if(host->slot[i])
+                        dw_mci_cleanup_slot(host->slot[i], i);
+        }
 
-       destroy_workqueue(host->card_workqueue);
+        /* disable clock to CIU */
+        mci_writel(host, CLKENA, 0);
+        mci_writel(host, CLKSRC, 0);
 
-       if (host->use_dma && host->dma_ops->exit)
-               host->dma_ops->exit(host);
+        destroy_workqueue(host->card_workqueue);
 
-       if (host->vmmc){
-               regulator_disable(host->vmmc);
-               regulator_put(host->vmmc);
-       }
-               
-    if (!IS_ERR(host->clk_mmc))
-               clk_disable_unprepare(host->clk_mmc);
+        if(host->use_dma && host->dma_ops->exit)
+                host->dma_ops->exit(host);
 
-    if (!IS_ERR(host->hclk_mmc))
-               clk_disable_unprepare(host->hclk_mmc);
+        if (gpio_is_valid(slot->cd_gpio))
+                dw_mci_of_free_cd_gpio_irq(host->dev, slot->cd_gpio, host->mmc);
+
+        if(host->vmmc){
+                regulator_disable(host->vmmc);
+                regulator_put(host->vmmc);
+        }
+       if(!IS_ERR(host->clk_mmc))
+                clk_disable_unprepare(host->clk_mmc);
+
+        if(!IS_ERR(host->hclk_mmc))
+                clk_disable_unprepare(host->hclk_mmc);
 }
 EXPORT_SYMBOL(dw_mci_remove);
 
@@ -3770,26 +4050,34 @@ EXPORT_SYMBOL(dw_mci_remove);
  */
 int dw_mci_suspend(struct dw_mci *host)
 {
-       
-       if (host->vmmc)
-               regulator_disable(host->vmmc);
+        if(host->vmmc)
+                regulator_disable(host->vmmc);
 
-       /*only for sdmmc controller*/
-       if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) {
-               host->mmc->rescan_disable = 1;
-               if (cancel_delayed_work_sync(&host->mmc->detect)){
+        if(host->use_dma && host->dma_ops->exit)
+                host->dma_ops->exit(host);
+
+        /*only for sdmmc controller*/
+        if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) {
+                host->mmc->rescan_disable = 1;
+                if (cancel_delayed_work_sync(&host->mmc->detect))
                        wake_unlock(&host->mmc->detect_wake_lock);
-               }
-               disable_irq(host->irq);
-               if(pinctrl_select_state(host->pinctrl, host->pins_idle) < 0)
-                       printk("%s: Warning :  Idle pinctrl setting failed!\n", mmc_hostname(host->mmc));  
-               dw_mci_of_get_cd_gpio(host->dev,0,host->mmc);
-               mci_writel(host, RINTSTS, 0xFFFFFFFF);
-               mci_writel(host, INTMASK, 0x00);
-               mci_writel(host, CTRL, 0x00);
-               enable_irq_wake(host->mmc->slot.cd_irq);
-    }
-       return 0;
+
+                disable_irq(host->irq);
+                if (pinctrl_select_state(host->pinctrl, host->pins_idle) < 0)
+                        MMC_DBG_ERR_FUNC(host->mmc, "Idle pinctrl setting failed! [%s]",
+                                                mmc_hostname(host->mmc));
+
+                mci_writel(host, RINTSTS, 0xFFFFFFFF);
+                mci_writel(host, INTMASK, 0x00);
+                mci_writel(host, CTRL, 0x00);
+
+                /* Soc rk3126 already in gpio_cd mode */
+                if (!(cpu_is_rk312x() && soc_is_rk3126())) {
+                        dw_mci_of_get_cd_gpio(host->dev, 0, host->mmc);
+                        enable_irq_wake(host->mmc->slot.cd_irq);
+                }
+        }
+        return 0;
 }
 EXPORT_SYMBOL(dw_mci_suspend);
 
@@ -3807,33 +4095,39 @@ int dw_mci_resume(struct dw_mci *host)
         }
        /*only for sdmmc controller*/
        if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) {
-               disable_irq_wake(host->mmc->slot.cd_irq);
-               mmc_gpio_free_cd(host->mmc);
+                /* Soc rk3126 already in gpio_cd mode */
+                if (!(cpu_is_rk312x() && soc_is_rk3126())) {
+                        disable_irq_wake(host->mmc->slot.cd_irq);
+                        mmc_gpio_free_cd(host->mmc);
+                }
                if(pinctrl_select_state(host->pinctrl, host->pins_default) < 0)
-                       printk("%s: Warning :  Default pinctrl setting failed!\n", mmc_hostname(host->mmc));  
+                        MMC_DBG_ERR_FUNC(host->mmc, "Default pinctrl setting failed! [%s]",
+                                                mmc_hostname(host->mmc));
                host->mmc->rescan_disable = 0;
-               if(cpu_is_rk3288()) {
-                       /*
-                         Fixme: 3036:  RK3288_GRF_SOC_CON0 compatitable?
-                        */
-                       grf_writel(((1<<12)<<16)|(0<<12), RK3288_GRF_SOC_CON0);//disable jtag
-               }
+               /* Disable jtag*/
+               if(cpu_is_rk3288())
+                        grf_writel(((1 << 12) << 16) | (0 << 12), RK3288_GRF_SOC_CON0);
+                else if(cpu_is_rk3036())
+                        grf_writel(((1 << 11) << 16) | (0 << 11), RK3036_GRF_SOC_CON0);
+                else if(cpu_is_rk312x())
+                        /* RK3036_GRF_SOC_CON0 is compatible with rk312x, tmp setting */
+                        grf_writel(((1 << 8) << 16) | (0 << 8), RK3036_GRF_SOC_CON0);
        }
-       if (host->vmmc) {
+       if(host->vmmc){
                ret = regulator_enable(host->vmmc);
-               if (ret) {
+               if (ret){
                        dev_err(host->dev,
                                "failed to enable regulator: %d\n", ret);
                        return ret;
                }
        }
        
-       if (!dw_mci_ctrl_all_reset(host)) {
+       if(!dw_mci_ctrl_all_reset(host)){
                ret = -ENODEV;
                return ret;
        }
 
-       if (host->use_dma && host->dma_ops->init)
+       if(host->use_dma && host->dma_ops->init)
                host->dma_ops->init(host);
 
        /*
@@ -3853,21 +4147,20 @@ int dw_mci_resume(struct dw_mci *host)
        mci_writel(host, INTMASK, regs);
        mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
        /*only for sdmmc controller*/
-       if((host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)&& (!retry_cnt)) {
+       if((host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)&& (!retry_cnt)){
                enable_irq(host->irq);  
        }   
-       
 
-       for (i = 0; i < host->num_slots; i++) {
+       for(i = 0; i < host->num_slots; i++){
                struct dw_mci_slot *slot = host->slot[i];
-               if (!slot)
+               if(!slot)
                        continue;
-               if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
+               if(slot->mmc->pm_flags & MMC_PM_KEEP_POWER){
                        dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
                        dw_mci_setup_bus(slot, true);
                }
        }
-       
+
        return 0;
 }
 EXPORT_SYMBOL(dw_mci_resume);