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 bbf2266bdcbda688ea2734e6cd568e321b5b6408..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>
@@ -49,7 +50,7 @@
 #include <linux/regulator/rockchip_io_vol_domain.h>
 #include "../../clk/rockchip/clk-ops.h"
 
-#define RK_SDMMC_DRIVER_VERSION "Ver 1.12 2014-07-08"
+#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 | \
@@ -671,27 +672,43 @@ static void dw_mci_edmac_start_dma(struct dw_mci *host, unsigned int sg_len)
 
 static int dw_mci_edmac_init(struct dw_mci *host)
 {
-        /* 1) request external dma channel, SHOULD decide chn in dts */
-        host->dms = (struct dw_mci_dma_slave *)kmalloc(sizeof(struct dw_mci_dma_slave),GFP_KERNEL);
+        /* 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;
+        }
+
         host->dms->ch = dma_request_slave_channel(host->dev, "dw_mci");
-        if (!host->dms->ch){
+        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? */
-
         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)
 {
-        dma_release_channel(host->dms->ch);
+        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 = {
@@ -1091,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));
@@ -1143,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: 
@@ -1470,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);
 
@@ -1489,6 +1561,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
        else
                present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
                        == 0 ? 1 : 0;
+
        spin_lock_bh(&host->lock);
        if (present) {
                set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
@@ -1631,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);
 
@@ -1657,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
@@ -1827,12 +1905,9 @@ 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_3036() || cpu_is_3126())
-                return ENOSYS;
-        AND
-                what about audi-b?
-        */
+        /* 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) {
@@ -2027,7 +2102,7 @@ static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd
                 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;
                }
@@ -2712,22 +2787,20 @@ host_put:
 
 static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
 {
-        u32 multi, unit;
+        u32 multi, unit = SZ_2M;
 
         if (!host->cmd_status)
            host->cmd_status = status;
            
-       if(!host->cmd)
+        if (!host->cmd)
                goto cmd_exit;
 
-       if((MMC_STOP_TRANSMISSION != host->cmd->opcode))
-        {
-                unit = 2*1024*1024;
-                multi = mci_readl(host, BYTCNT)/unit;
-                multi += ((mci_readl(host, BYTCNT) % unit) ? 1 :0 );
-                multi = (multi > 0) ? multi : 1;
-                multi += (host->cmd->retries > 2)? 2 : host->cmd->retries;
-                mod_timer(&host->dto_timer, jiffies + msecs_to_jiffies(4500 * multi));//max wait 8s larger
+        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));
         }
 
 cmd_exit:
@@ -2848,7 +2921,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
 #ifdef CONFIG_MMC_DW_IDMAC
         /* External DMA Soc platform NOT need to ack interrupt IDSTS */
-        if(!cpu_is_rk3036()){
+        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)) {
@@ -2941,7 +3014,7 @@ 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
-                                if(!cpu_is_rk3036())
+                                if(!(cpu_is_rk3036() || cpu_is_rk312x()))
                                        dw_mci_idmac_reset(host);
 #endif
 
@@ -3086,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)
 {
@@ -3139,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;    
@@ -3158,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);
@@ -3247,11 +3396,11 @@ 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()){
+               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 = 512;
+                       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; 
                 }
@@ -3342,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;
 }
@@ -3371,7 +3522,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
 
        /* Determine which DMA interface to use */
 #if defined(CONFIG_MMC_DW_IDMAC)
-        if(cpu_is_rk3036()){
+        if(cpu_is_rk3036() || cpu_is_rk312x()){
                 host->dma_ops = &dw_mci_edmac_ops;
                 dev_info(host->dev, "Using external DMA controller.\n");
         }else{
@@ -3564,7 +3715,7 @@ static void dw_mci_dealwith_timeout(struct dw_mci *host)
 
                         /* NO requirement to reclaim slave chn using external dmac */
                         #ifdef CONFIG_MMC_DW_IDMAC
-                        if(!cpu_is_rk3036())
+                        if(!(cpu_is_rk3036() || cpu_is_rk312x()))
                                 if (host->use_dma && host->dma_ops->init)
                                        host->dma_ops->init(host);
                         #endif
@@ -3852,7 +4003,10 @@ 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;
+
        del_timer_sync(&host->dto_timer);
 
         mci_writel(host, RINTSTS, 0xFFFFFFFF);
@@ -3873,6 +4027,9 @@ void dw_mci_remove(struct dw_mci *host)
         if(host->use_dma && host->dma_ops->exit)
                 host->dma_ops->exit(host);
 
+        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);
@@ -3900,20 +4057,25 @@ int dw_mci_suspend(struct dw_mci *host)
                 host->dma_ops->exit(host);
 
         /*only for sdmmc controller*/
-        if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD){
+        if (host->mmc->restrict_caps & RESTRICT_CARD_TYPE_SD) {
                 host->mmc->rescan_disable = 1;
-                if(cancel_delayed_work_sync(&host->mmc->detect))
+                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)
+                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));
-                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);
+
+                /* 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;
 }
@@ -3933,8 +4095,11 @@ 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)
                         MMC_DBG_ERR_FUNC(host->mmc, "Default pinctrl setting failed! [%s]",
                                                 mmc_hostname(host->mmc));
@@ -3942,14 +4107,11 @@ int dw_mci_resume(struct dw_mci *host)
                /* 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_rk3126())
-                        TODO;
-                else if audi-b
-                        TODO;
-                */
+                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){
                ret = regulator_enable(host->vmmc);