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 0238bb94e86f1510e2de4d0e71472eb6b6de4ec4..fd72bcac5e7639c25a3fa8cd0200a2b8c5e2ebd2 100755 (executable)
@@ -50,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 | \
@@ -672,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 = {
@@ -1092,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));
@@ -1678,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);
 
@@ -1704,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
@@ -2756,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:
@@ -3169,6 +3198,9 @@ static void dw_mci_of_set_cd_gpio_irq(struct device *dev, u32 gpio,
                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);
@@ -3239,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;    
@@ -3258,6 +3289,10 @@ 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() &&