mmc: host: rk_sdmmc:
authorlin tao <lt@mid-server3.(none)>
Mon, 16 Jun 2014 02:40:18 +0000 (10:40 +0800)
committerlin tao <lt@mid-server3.(none)>
Mon, 16 Jun 2014 02:56:00 +0000 (10:56 +0800)
Support physical level three transfer.

drivers/mmc/core/sdio.c [changed mode: 0644->0755]
drivers/mmc/host/Kconfig
drivers/mmc/host/dw_mmc-rockchip.c
drivers/mmc/host/rk_sdmmc.c
include/linux/mmc/rk_mmc.h

old mode 100644 (file)
new mode 100755 (executable)
index dc2178c..9a9995f
@@ -673,6 +673,17 @@ try_again:
         * systems that claim 1.8v signalling in fact do not support
         * it.
         */
+
+        /*
+         * Fixme: ap6335 should not set S18A=1 if mmc I/F voltage
+         *        has been 1.8v yet.
+         */
+        #ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
+        #ifdef CONFIG_AP6335
+        rocr &= ~R4_18V_PRESENT;
+        #endif
+        #endif
+        
        if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
                err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
                                        ocr);
@@ -688,7 +699,12 @@ try_again:
                }
                err = 0;
        } else {
-               ocr &= ~R4_18V_PRESENT;
+               #ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
+               #ifdef CONFIG_AP6335
+               #else
+               ocr &= ~R4_18V_PRESENT;
+               #endif
+               #endif
        }
 
        /*
index cae55137680183eaa93fd6859ad65694ba6b485c..761e0808dcf08eb7b2c1bce7ab831ded5f56e5ff 100755 (executable)
@@ -556,6 +556,15 @@ config MMC_DW_ROCKCHIP
          Synopsys DesignWare Memory Card Interface driver. Select this option
          for platforms based on RK32XX SoC's.
 
+config MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
+       tristate "Supoort voltage switch for higher level standard"
+       depends on MMC_DW_ROCKCHIP
+       default n 
+       help
+          This selects support for Rockchip RK32XX Soc specific extensions to voltage
+         switch squence
+
+
 config MMC_DW_EXYNOS
        tristate "Exynos specific extensions for Synopsys DW Memory Card Interface"
        depends on MMC_DW
index 215936af1724559fb29e6003b7dfc4fef4f18549..9982c2807d09950fd504e9ef2101ad3a25ebd604 100755 (executable)
@@ -464,10 +464,12 @@ static int dw_mci_rockchip_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
                goto done;  
                 #endif            
         }else{
-              MMC_DBG_ERR_FUNC(host->mmc,
+                MMC_DBG_ERR_FUNC(host->mmc,
                                 "execute tuning: candidates_degree beyong limited case! [%s]",
-                                mmc_hostname(host->mmc)); 
-              BUG();
+                                mmc_hostname(host->mmc));
+                if(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC)
+                        BUG();
+                return -EAGAIN;
         }
 
 delayline:
index fedd50d61a2ae3e5808d025b41896c17bf4ea5ed..a377af3813100f7148c2353c9f11b1e00dc169d8 100755 (executable)
 #define DW_MCI_FREQ_MAX        50000000//200000000     /* unit: HZ */
 #define DW_MCI_FREQ_MIN        300000//400000          /* unit: HZ */
 
-#define SDMMC_DATA_TIMEOUT_SD  500; /*max is 250ms showed in Spec; Maybe adapt the value for the sick card.*/
+/*max is 250ms showed in Spec; Maybe adapt the value for the sick card.*/
+#define SDMMC_DATA_TIMEOUT_SD  500
 #define SDMMC_DATA_TIMEOUT_SDIO        250
 #define SDMMC_DATA_TIMEOUT_EMMC        2500
 
-#define SDMMC_CMD_RTO_MAX_HOLD 200 
+#define SDMMC_CMD_RTO_MAX_HOLD  200
 #define SDMMC_WAIT_FOR_UNBUSY  2500
 
 #ifdef CONFIG_MMC_DW_IDMAC
@@ -867,15 +868,18 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
        u32 div;
        u32 clk_en_a;
        u32 sdio_int;
-       
+
        MMC_DBG_INFO_FUNC(host->mmc,"%d..%s: clock=%d, current_speed=%d, bus_hz=%d,forc=%d[%s]\n", 
                 __LINE__, __FUNCTION__, clock, host->current_speed,host->bus_hz,force_clkinit,mmc_hostname(host->mmc));
 
        if (!clock) {
                mci_writel(host, CLKENA, 0);
-               mci_send_cmd(slot,
-                            SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
-
+               #ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
+                if(host->svi_flags == 0)
+                        mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
+                #else
+                mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
+                #endif
        } else if (clock != host->current_speed || force_clkinit) {
                div = host->bus_hz / clock;
                if (host->bus_hz % clock && host->bus_hz > clock)
@@ -1016,12 +1020,13 @@ static void dw_mci_wait_unbusy(struct dw_mci *host)
     time_loop = jiffies + msecs_to_jiffies(timeout);
     do {
        status = mci_readl(host, STATUS);
-       if (!(status & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY)))
+       if (!(status & (SDMMC_STAUTS_DATA_BUSY | SDMMC_STAUTS_MC_BUSY)))
                break;
-       //MMC_DBG_INFO_FUNC("dw_mci_wait_unbusy, waiting for......");   
     } while (time_before(jiffies, time_loop));
 }
 
+
+#ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
 /*
 *   result: 
 *   0--status is busy. 
@@ -1031,34 +1036,24 @@ int dw_mci_card_busy(struct mmc_host *mmc)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
        struct dw_mci *host = slot->host;
-    unsigned int    timeout= SDMMC_DATA_TIMEOUT_SDIO;
-    unsigned long   time_loop;
-    unsigned int    status;
-    int ret= 0;
+
+        MMC_DBG_INFO_FUNC(host->mmc, "dw_mci_card_busy: svi_flags = %d [%s]", \
+                                host->svi_flags, mmc_hostname(host->mmc));     
     
-    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;  
-    timeout = 250*1000;//test    
-    time_loop = jiffies + msecs_to_jiffies(timeout);
+        /* svi toggle*/
+        if(host->svi_flags == 0){
+                /*first svi*/
+                host->svi_flags = 1;
+                return host->svi_flags;           
     
-    MMC_DBG_INFO_FUNC(host->mmc, "line%d: dw_mci_wait_unbusy,timeloop=%lu, status=0x%x ",
-        __LINE__, time_loop, mci_readl(host, STATUS));
-    do {
-       status = mci_readl(host, STATUS);
-       if (!(status & (SDMMC_STAUTS_DATA_BUSY|SDMMC_STAUTS_MC_BUSY))){
-           ret = 1;//card is unbusy.
-               break;
+        }else{
+                host->svi_flags = 0;
+                return host->svi_flags;   
        }
-       //MMC_DBG_INFO_FUNC("dw_mci_wait_unbusy, waiting for......");   
-    } while (time_before(jiffies, time_loop));
-    MMC_DBG_INFO_FUNC(host->mmc, "line%d: dw_mci_wait_unbusy,ret=%d,  status=0x%x ",
-        __LINE__,ret,mci_readl(host, STATUS));
+       
 
-    return ret;
 }
-
+#endif
 static void __dw_mci_start_request(struct dw_mci *host,
                                   struct dw_mci_slot *slot,
                                   struct mmc_command *cmd)
@@ -1073,15 +1068,8 @@ static void __dw_mci_start_request(struct dw_mci *host,
 
        host->cur_slot = slot;
        host->mrq = mrq;
-#if 0 //add by xbw,at 2014-03-12
-       /*clean FIFO if it is a new request*/
-    if(!(mrq->cmd->opcode & SDMMC_CMD_STOP)) {
-        MMC_DBG_INFO_FUNC("%d..%s: reset the ctrl.", __LINE__, __FUNCTION__);  
-        mci_writel(host, CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET |
-                               SDMMC_CTRL_DMA_RESET));
-    }
- #endif   
-    dw_mci_wait_unbusy(host);
+
+        dw_mci_wait_unbusy(host);
     
        host->pending_events = 0;
        host->completed_events = 0;
@@ -1116,9 +1104,9 @@ static void dw_mci_start_request(struct dw_mci *host,
 {
        struct mmc_request *mrq = slot->mrq;
        struct mmc_command *cmd;
-       
-    MMC_DBG_INFO_FUNC(host->mmc, " Begin to start the new request. cmd=%d(arg=0x%x)[%s]", \
-        mrq->cmd->opcode, mrq->cmd->arg, mmc_hostname(host->mmc));
+
+       MMC_DBG_INFO_FUNC(host->mmc, " Begin to start the new request. cmd=%d(arg=0x%x)[%s]", \
+                mrq->cmd->opcode, mrq->cmd->arg, mmc_hostname(host->mmc));
         
        cmd = mrq->sbc ? mrq->sbc : mrq->cmd;
        __dw_mci_start_request(host, slot, cmd);
@@ -1164,8 +1152,9 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
                mmc_request_done(mmc, mrq);
                return;
        }
-    MMC_DBG_CMD_FUNC(host->mmc, "======>\n    pull a new request from MMC-frame to dw_mci_queue. cmd=%d(arg=0x%x)[%s]", \
-        mrq->cmd->opcode, mrq->cmd->arg, mmc_hostname(host->mmc));
+
+       MMC_DBG_CMD_FUNC(host->mmc, "======>\n    pull a new request from MMC-frame to dw_mci_queue. cmd=%d(arg=0x%x)[%s]", \
+                                mrq->cmd->opcode, mrq->cmd->arg, mmc_hostname(host->mmc));
 
        dw_mci_queue_request(host, slot, mrq);
 
@@ -1175,12 +1164,25 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
+       #ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
+        struct dw_mci *host = slot->host;
+        #endif
        const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
        u32 regs;
-#ifdef SDMMC_WAIT_FOR_UNBUSY
-       unsigned long   time_loop = jiffies + msecs_to_jiffies(SDMMC_WAIT_FOR_UNBUSY);
+       
+        #ifdef SDMMC_WAIT_FOR_UNBUSY
+       unsigned long   time_loop;
        bool ret = true;
 
+        #ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
+        if(host->svi_flags == 1)
+                time_loop = jiffies + msecs_to_jiffies(SDMMC_DATA_TIMEOUT_SD);
+        else
+                time_loop = jiffies + msecs_to_jiffies(SDMMC_WAIT_FOR_UNBUSY);
+        #else
+                time_loop = jiffies + msecs_to_jiffies(SDMMC_WAIT_FOR_UNBUSY);
+        #endif
+        
        if(!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)){
                printk("%d..%s:  no card. [%s]\n", \
                        __LINE__, __FUNCTION__, mmc_hostname(mmc));
@@ -1197,11 +1199,15 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        if(false == ret)
        {
                printk("slot->flags = %lu ", slot->flags);
-               dump_stack();
+               #ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
+                if(host->svi_flags != 1)
+                #endif
+                        dump_stack();
                printk("%d..%s:  wait for unbusy timeout....... STATUS = 0x%x [%s]\n", \
                        __LINE__, __FUNCTION__, regs, mmc_hostname(mmc));
        }
-#endif
+        #endif
+        
        switch (ios->bus_width) {
        case MMC_BUS_WIDTH_4:
                slot->ctype = SDMMC_CTYPE_4BIT;
@@ -1241,25 +1247,25 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 EXIT_POWER:
        switch (ios->power_mode) {
-       case MMC_POWER_UP:
-               set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
-               /* Power up slot */
-               if (slot->host->pdata->setpower)
-                       slot->host->pdata->setpower(slot->id, mmc->ocr_avail);
-               regs = mci_readl(slot->host, PWREN);
-               regs |= (1 << slot->id);
-               mci_writel(slot->host, PWREN, regs);
-               break;
-       case MMC_POWER_OFF:
-               /* Power down slot */
-               if (slot->host->pdata->setpower)
-                       slot->host->pdata->setpower(slot->id, 0);
-               regs = mci_readl(slot->host, PWREN);
-               regs &= ~(1 << slot->id);
-               mci_writel(slot->host, PWREN, regs);            
-               break;
-       default:
-               break;
+               case MMC_POWER_UP:
+                        set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
+                        /* Power up slot */
+                       if (slot->host->pdata->setpower)
+                               slot->host->pdata->setpower(slot->id, mmc->ocr_avail);
+                       regs = mci_readl(slot->host, PWREN);
+                       regs |= (1 << slot->id);
+                       mci_writel(slot->host, PWREN, regs);
+                       break;
+                case MMC_POWER_OFF:
+                       /* Power down slot */
+                       if(slot->host->pdata->setpower)
+                               slot->host->pdata->setpower(slot->id, 0);
+                       regs = mci_readl(slot->host, PWREN);
+                       regs &= ~(1 << slot->id);
+                       mci_writel(slot->host, PWREN, regs);            
+                       break;
+               default:
+                       break;
        }
 }
 
@@ -1270,11 +1276,11 @@ static int dw_mci_get_ro(struct mmc_host *mmc)
        struct dw_mci_board *brd = slot->host->pdata;
 
        /* Use platform get_ro function, else try on board write protect */
-       if (slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT)
+       if(slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT)
                read_only = 0;
-       else if (brd->get_ro)
+       else if(brd->get_ro)
                read_only = brd->get_ro(slot->id);
-       else if (gpio_is_valid(slot->wp_gpio))
+       else if(gpio_is_valid(slot->wp_gpio))
                read_only = gpio_get_value(slot->wp_gpio);
        else
                read_only =
@@ -1324,8 +1330,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
        struct dw_mci *host = slot->host;
        int gpio_cd = mmc_gpio_get_cd(mmc);
        
-    if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)
-        return test_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+        if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)
+                return test_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 
        /* Use platform get_cd function, else try onboard card detect */
        if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
@@ -1477,7 +1483,7 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
        /* Enable/disable Slot Specific SDIO interrupt */
        int_mask = mci_readl(host, INTMASK);
 
-    if (host->verid < DW_MMC_240A)
+        if (host->verid < DW_MMC_240A)
                sdio_int = SDMMC_INT_SDIO(slot->id);
        else
                sdio_int = SDMMC_INT_SDIO((slot->id) + 8);
@@ -1499,7 +1505,32 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
        }
 }
 
-#if 0
+#ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
+enum{
+        IO_DOMAIN_12 = 1200,
+        IO_DOMAIN_18 = 1800,
+        IO_DOMAIN_33 = 3300,
+};
+static void dw_mci_do_grf_io_domain_switch(struct dw_mci *host, u32 voltage)
+{
+        if(cpu_is_rk3288()){
+               if(voltage == IO_DOMAIN_33)
+                        voltage = 0;
+                else if(voltage == IO_DOMAIN_18)
+                        voltage = 1;
+                else
+                     MMC_DBG_ERR_FUNC(host->mmc,"%s : err io domain voltage [%s]\n", 
+                          __FUNCTION__, mmc_hostname(host->mmc));
+                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));
+        }
+}
+
 static int dw_mci_do_start_signal_voltage_switch(struct dw_mci *host,
                                                struct mmc_ios *ios)
 {
@@ -1514,76 +1545,80 @@ static int dw_mci_do_start_signal_voltage_switch(struct dw_mci *host,
                return 0;
 
        uhs_reg = mci_readl(host, UHS_REG);
-    MMC_DBG_SW_VOL_FUNC(host->mmc,"%d..%s: vol=%d.[%s]\n",
-        __LINE__, __FUNCTION__,ios->signal_voltage, mmc_hostname(host->mmc));
+       MMC_DBG_SW_VOL_FUNC(host->mmc,"%d..%s: vol=%d.[%s]\n",
+               __LINE__, __FUNCTION__,ios->signal_voltage, mmc_hostname(host->mmc));
 
        switch (ios->signal_voltage) {
         case MMC_SIGNAL_VOLTAGE_330:
                /* Set 1.8V Signal Enable in the Host Control2 register to 0 */
                if (host->vmmc) {
                        ret = io_domain_regulator_set_voltage(host->vmmc, 3300000, 3300000);
-                       //regulator_put(host->vmmc); //to be done in remove function.
+                       /* regulator_put(host->vmmc); //to be done in remove function. */
                        
                        MMC_DBG_SW_VOL_FUNC(host->mmc,"%s   =%dmV  set 3.3end, ret=%d  \n", 
                            __func__, regulator_get_voltage(host->vmmc), ret);
                        if (ret) {
-                               pr_warning("%s: Switching to 3.3V signalling voltage "
+                               MMC_DBG_SW_VOL_FUNC(host->mmc, "%s: Switching to 3.3V signalling voltage "
                                                " failed\n", mmc_hostname(host->mmc));
                                return -EIO;
                        }
+                       dw_mci_do_grf_io_domain_switch(host, IO_DOMAIN_33);
                }
-            MMC_DBG_SW_VOL_FUNC(host->mmc,"%d..%s: [%s]\n",__LINE__, __FUNCTION__, mmc_hostname(host->mmc));
+               MMC_DBG_SW_VOL_FUNC(host->mmc,"%d..%s: [%s]\n",__LINE__, 
+                                       __FUNCTION__, mmc_hostname(host->mmc));
 
-               //set High-power mode
+               /* set High-power mode */
                value = mci_readl(host, CLKENA);
-               mci_writel(host,CLKENA , value& ~SDMMC_CLKEN_LOW_PWR);
-               //SDMMC_UHS_REG
-               mci_writel(host,UHS_REG , uhs_reg & ~SDMMC_UHS_VOLT_REG_18);
+               value &= ~SDMMC_CLKEN_LOW_PWR;
+               mci_writel(host,CLKENA , value);
+               /* SDMMC_UHS_REG */
+               uhs_reg &= ~SDMMC_UHS_VOLT_REG_18; 
+               mci_writel(host,UHS_REG , uhs_reg);
                
                /* Wait for 5ms */
                usleep_range(5000, 5500);
 
                /* 3.3V regulator output should be stable within 5 ms */
                uhs_reg = mci_readl(host, UHS_REG);
-            if( !(uhs_reg & SDMMC_UHS_VOLT_REG_18))
-                return 0;      
+               if( !(uhs_reg & SDMMC_UHS_VOLT_REG_18))
+                        return 0;      
 
-               pr_warning("%s: 3.3V regulator output did not became stable\n",
+               MMC_DBG_SW_VOL_FUNC(host->mmc, "%s: 3.3V regulator output did not became stable\n",
                                mmc_hostname(host->mmc));
 
                return -EAGAIN;
         case MMC_SIGNAL_VOLTAGE_180:
                if (host->vmmc) {
                        ret = io_domain_regulator_set_voltage(host->vmmc,1800000, 1800000);
-//                     regulator_put(host->vmmc);//to be done in remove function.
+                        /* regulator_put(host->vmmc);//to be done in remove function. */
 
                        MMC_DBG_SW_VOL_FUNC(host->mmc,"%d..%s   =%dmV  set 1.8end, ret=%d . \n",
                            __LINE__, __func__, regulator_get_voltage(host->vmmc), ret);
                        if (ret) {
-                               pr_warning("%s: Switching to 1.8V signalling voltage "
+                               MMC_DBG_SW_VOL_FUNC(host->mmc, "%s: Switching to 1.8V signalling voltage "
                                                " failed\n", mmc_hostname(host->mmc));
                                return -EIO;
                        }
+                       dw_mci_do_grf_io_domain_switch(host, IO_DOMAIN_18);
                }
 
                /*
                 * Enable 1.8V Signal Enable in the Host Control2
                 * register
                 */
-            mci_writel(host,UHS_REG , uhs_reg | SDMMC_UHS_VOLT_REG_18);
+                mci_writel(host,UHS_REG , uhs_reg | SDMMC_UHS_VOLT_REG_18);
 
                /* Wait for 5ms */
                usleep_range(5000, 5500);
-            MMC_DBG_SW_VOL_FUNC(host->mmc,"%d..%s: .[%s]\n",__LINE__, __FUNCTION__,mmc_hostname(host->mmc));
+                MMC_DBG_SW_VOL_FUNC(host->mmc,"%d..%s: .[%s]\n",__LINE__, 
+                                        __FUNCTION__,mmc_hostname(host->mmc));
 
                /* 1.8V regulator output should be stable within 5 ms */
                uhs_reg = mci_readl(host, UHS_REG);
-            if( uhs_reg & SDMMC_UHS_VOLT_REG_18){
-                
-                return 0;
-            }
-
-               pr_warning("%s: 1.8V regulator output did not became stable\n",
+               if(uhs_reg & SDMMC_UHS_VOLT_REG_18)
+                       return 0;
+      
+               MMC_DBG_SW_VOL_FUNC(host->mmc, "%s: 1.8V regulator output did not became stable\n",
                                mmc_hostname(host->mmc));
 
                return -EAGAIN;
@@ -1591,7 +1626,7 @@ static int dw_mci_do_start_signal_voltage_switch(struct dw_mci *host,
                if (host->vmmc) {
                        ret = io_domain_regulator_set_voltage(host->vmmc, 1200000, 1200000);
                        if (ret) {
-                               pr_warning("%s: Switching to 1.2V signalling voltage "
+                               MMC_DBG_SW_VOL_FUNC(host->mmc, "%s: Switching to 1.2V signalling voltage "
                                                " failed\n", mmc_hostname(host->mmc));
                                return -EIO;
                        }
@@ -1613,12 +1648,13 @@ static int dw_mci_start_signal_voltage_switch(struct mmc_host *mmc,
 
        if (host->verid < DW_MMC_240A)
                return 0;
-       //sdhci_runtime_pm_get(host);
+       
        err = dw_mci_do_start_signal_voltage_switch(host, ios);
-       //sdhci_runtime_pm_put(host);
        return err;
 }
+
 #endif
+
 static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
@@ -1680,9 +1716,12 @@ static const struct mmc_host_ops dw_mci_ops = {
        .hw_reset       = dw_mci_hw_reset,
        .enable_sdio_irq        = dw_mci_enable_sdio_irq,
        .execute_tuning         = dw_mci_execute_tuning,
-       //.start_signal_voltage_switch  = dw_mci_start_signal_voltage_switch,
-       //.card_busy  = dw_mci_card_busy,
+        #ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
+        .start_signal_voltage_switch   = dw_mci_start_signal_voltage_switch,
+        .card_busy  = dw_mci_card_busy,
+        #endif
 };
+
 #if 0
 static void dw_mci_enable_irq(struct dw_mci *host, bool irqflag)
 {
@@ -1707,11 +1746,12 @@ static void dw_mci_enable_irq(struct dw_mci *host, bool irqflag)
        local_irq_restore(flags);
 }
 #endif
+
 static void dw_mci_deal_data_end(struct dw_mci *host, struct mmc_request *mrq)
        __releases(&host->lock)
        __acquires(&host->lock)
 {
-       if(DW_MCI_SEND_STATUS == host->dir_status){
+        if(DW_MCI_SEND_STATUS == host->dir_status){
            #if 0
            if( MMC_BUS_TEST_W != host->cmd->opcode){
                if(host->data_status & SDMMC_INT_DCRC)
@@ -1724,8 +1764,7 @@ static void dw_mci_deal_data_end(struct dw_mci *host, struct mmc_request *mrq)
            #else
            dw_mci_wait_unbusy(host);
            #endif
-           
-       }
+        }
 }
 
 static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
@@ -1737,14 +1776,14 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
 
        WARN_ON(host->cmd || host->data);
        
-    dw_mci_deal_data_end(host, mrq);
+        dw_mci_deal_data_end(host, mrq);
 
-       if(mrq->cmd)
-       MMC_DBG_CMD_FUNC(host->mmc, " reqeust end--reqeuest done, cmd=%d, cmderr=%d, host->state=%d [%s]",\
-            mrq->cmd->opcode,mrq->cmd->error, host->state,mmc_hostname(host->mmc));
-       if(mrq->data)
-       MMC_DBG_CMD_FUNC(host->mmc, " reqeust end--reqeuest done, cmd=%d, dataerr=%d, host->state=%d [%s]",\
-            mrq->cmd->opcode,mrq->data->error, host->state, mmc_hostname(host->mmc));
+        if(mrq->cmd)
+                MMC_DBG_CMD_FUNC(host->mmc, " reqeust end--reqeuest done, cmd=%d, cmderr=%d, host->state=%d [%s]",\
+                        mrq->cmd->opcode,mrq->cmd->error, host->state,mmc_hostname(host->mmc));
+        if(mrq->data)
+                MMC_DBG_CMD_FUNC(host->mmc, " reqeust end--reqeuest done, cmd=%d, dataerr=%d, host->state=%d [%s]",\
+                        mrq->cmd->opcode,mrq->data->error, host->state, mmc_hostname(host->mmc));
 
        host->cur_slot->mrq = NULL;
        host->mrq = NULL;
@@ -1762,7 +1801,7 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
                host->state = STATE_IDLE;
        }
 
-       spin_unlock(&host->lock);
+        spin_unlock(&host->lock);
        mmc_request_done(prev_mmc, mrq);
        spin_lock(&host->lock);
 }
@@ -1806,15 +1845,16 @@ static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd
                cmd->error = -EIO;
        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));
+        MMC_DBG_CMD_FUNC(host->mmc, " command complete, cmd=%d,cmdError=%d [%s]",
+                                cmd->opcode, cmd->error,mmc_hostname(host->mmc));
 
        if (cmd->error) {
            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]",\
-                   cmd->opcode, cmd->error,mmc_hostname(host->mmc));
-              host->cmd_rto = 0;
-        }
+                       MMC_DBG_ERR_FUNC(host->mmc, " command complete, cmd=%d,cmdError=%d [%s]",\
+                                cmd->opcode, cmd->error,mmc_hostname(host->mmc));
+                        host->cmd_rto = 0;
+               }
                
                /* newer ip versions need a delay between retries */
                if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY)
@@ -1826,7 +1866,7 @@ static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd
 static void dw_mci_tasklet_func(unsigned long priv)
 {
        struct dw_mci *host = (struct dw_mci *)priv;
-    struct dw_mci_slot *slot = mmc_priv(host->mmc);
+        struct dw_mci_slot *slot = mmc_priv(host->mmc);
        struct mmc_data *data;
        struct mmc_command *cmd;
        enum dw_mci_state state;
@@ -1880,7 +1920,6 @@ static void dw_mci_tasklet_func(unsigned long priv)
                                #endif
                        }
 
-
                        if (!host->mrq->data || cmd->error) {
                                dw_mci_request_end(host, host->mrq);
                                goto unlock;
@@ -1896,32 +1935,32 @@ static void dw_mci_tasklet_func(unsigned long priv)
                                if (data->stop){
                                        send_stop_cmd(host, data);
                                }else{
-                        /*single block read/write, send stop cmd manually to prevent host controller halt*/
-                        MMC_DBG_INFO_FUNC(host->mmc, "%s status 1 0x%08x [%s]\n",
-                        __func__, mci_readl(host, STATUS), mmc_hostname(host->mmc));
+                                        /*single block read/write, send stop cmd manually to prevent host controller halt*/
+                                        MMC_DBG_INFO_FUNC(host->mmc, "%s status 1 0x%08x [%s]\n",
+                                                        __func__, mci_readl(host, STATUS), mmc_hostname(host->mmc));
                         
-                                               mci_writel(host, CMDARG, 0);
-                        wmb();
-                        cmd_flags = SDMMC_CMD_STOP |SDMMC_CMD_RESP_CRC|SDMMC_CMD_RESP_EXP|MMC_STOP_TRANSMISSION;
-                        
-                                               if(host->mmc->hold_reg_flag)
-                           cmd_flags |= SDMMC_CMD_USE_HOLD_REG;
+                                       mci_writel(host, CMDARG, 0);
+                                        wmb();
+                                        cmd_flags = SDMMC_CMD_STOP | SDMMC_CMD_RESP_CRC 
+                                                        | SDMMC_CMD_RESP_EXP | MMC_STOP_TRANSMISSION;
+
+                                        if(host->mmc->hold_reg_flag)
+                                                cmd_flags |= SDMMC_CMD_USE_HOLD_REG;
                                
-                        mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
-                        wmb();
-                        timeout = jiffies + msecs_to_jiffies(500);
+                                        mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
+                                        wmb();
+                                        timeout = jiffies + msecs_to_jiffies(500);
                         
-                                       while(ret){
-                                               ret = time_before(jiffies, timeout);
-                            if(!(mci_readl(host, CMD) & SDMMC_CMD_START))
-                                 break;
-                        }
-                        
-                                       if(false == ret)
-                                               MMC_DBG_ERR_FUNC(host->mmc, 
-                                                       "%s EVENT_DATA_ERROR recovery failed!!! [%s]\n",
-                             __func__, mmc_hostname(host->mmc));
-                }
+                                        while(ret){
+                                                ret = time_before(jiffies, timeout);
+                                                if(!(mci_readl(host, CMD) & SDMMC_CMD_START))
+                                                        break;
+                                        }
+                                        if(false == ret)
+                                                MMC_DBG_ERR_FUNC(host->mmc,
+                                                        "%s EVENT_DATA_ERROR recovery failed!!! [%s]\n",
+                                                        __func__, mmc_hostname(host->mmc));
+                                }
                                #else
                                send_stop_abort(host, data);
                                #endif
@@ -2002,14 +2041,14 @@ static void dw_mci_tasklet_func(unsigned long priv)
                                dw_mci_request_end(host, host->mrq);
                                goto unlock;
                        }
-                   MMC_DBG_CMD_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: begin to stop . [%s]", \
-                prev_state,state,mmc_hostname(host->mmc));
+                        MMC_DBG_CMD_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: begin to stop . [%s]", \
+                                                prev_state,state,mmc_hostname(host->mmc));
 
                        if (host->mrq->sbc && !data->error) {
                                data->stop->error = 0;
                                
-               MMC_DBG_CMD_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: have stop and sbc, exit. [%s]", \
-                    prev_state,state,mmc_hostname(host->mmc));
+                        MMC_DBG_CMD_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: have stop and sbc, exit. [%s]", \
+                                                prev_state,state,mmc_hostname(host->mmc));
 
                                dw_mci_request_end(host, host->mrq);
                                goto unlock;
@@ -2026,31 +2065,31 @@ static void dw_mci_tasklet_func(unsigned long priv)
                        }
                        #endif
                        /* fall through */
-            MMC_DBG_CMD_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: begin to STATE_SENDING_STOP . [%s]", \
-                prev_state,state,mmc_hostname(host->mmc));
+                        MMC_DBG_CMD_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: begin to STATE_SENDING_STOP . [%s]", \
+                                                prev_state,state,mmc_hostname(host->mmc));
 
                case STATE_SENDING_STOP:
-                       if (!test_and_clear_bit(EVENT_CMD_COMPLETE,
-                                               &host->pending_events))
+                       if (!test_and_clear_bit(EVENT_CMD_COMPLETE, &host->pending_events))
                                break;
-            MMC_DBG_CMD_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: begin to send cmd12 . [%s]", \
-                prev_state,state,mmc_hostname(host->mmc));
+
+                        MMC_DBG_CMD_FUNC(host->mmc, "Pre-state[%d]-->NowState[%d]: begin to send cmd12 . [%s]", \
+                                                prev_state, state, mmc_hostname(host->mmc));
                         
-             /* CMD error in data command */
+                        /* CMD error in data command */
                        if (host->mrq->cmd->error && host->mrq->data) {
                                dw_mci_fifo_reset(host);
                        }
 
                        host->cmd = NULL;
                        host->data = NULL;
-            #if 1
-            dw_mci_command_complete(host, host->mrq->stop);
-            #else
+                        #if 1
+                        dw_mci_command_complete(host, host->mrq->stop);
+                        #else
                        if (host->mrq->stop)
                                dw_mci_command_complete(host, host->mrq->stop);
                        else
                                host->cmd_status = 0;
-            #endif
+                        #endif
             
                        dw_mci_request_end(host, host->mrq);
                        goto unlock;
@@ -2955,8 +2994,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        if (drv_data && drv_data->hold_reg_flag)
                mmc->hold_reg_flag |= drv_data->hold_reg_flag[ctrl_id];         
 
-       //set the compatibility of driver.      
-    mmc->caps |= MMC_CAP_UHS_SDR12|MMC_CAP_UHS_SDR25|MMC_CAP_UHS_SDR50|MMC_CAP_UHS_SDR104|MMC_CAP_ERASE ;
+       /* set the compatibility of driver. */
+       mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 
+                       | MMC_CAP_UHS_SDR104 | MMC_CAP_ERASE ;
 
        if (host->pdata->caps2)
                mmc->caps2 = host->pdata->caps2;
@@ -2969,13 +3009,14 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                bus_width = 1;
 
        switch (bus_width) {
-       case 8:
-               mmc->caps |= MMC_CAP_8_BIT_DATA;
-       case 4:
-               mmc->caps |= MMC_CAP_4_BIT_DATA;
+               case 8:
+                       mmc->caps |= MMC_CAP_8_BIT_DATA;
+               case 4:
+                       mmc->caps |= MMC_CAP_4_BIT_DATA;
        }
+       
        if (of_find_property(host->dev->of_node, "cap-power-off-card", NULL))
-               mmc->caps |= MMC_CAP_POWER_OFF_CARD;
+                mmc->caps |= MMC_CAP_POWER_OFF_CARD;
        if (of_find_property(host->dev->of_node, "cap-sdio-irq", NULL))
                mmc->caps |= MMC_CAP_SDIO_IRQ;
        if (of_find_property(host->dev->of_node, "poll-hw-reset", NULL))
@@ -2984,12 +3025,12 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                mmc->caps2 |= MMC_CAP2_FULL_PWR_CYCLE;
        if (of_find_property(host->dev->of_node, "keep-power-in-suspend", NULL))
                mmc->pm_caps |= MMC_PM_KEEP_POWER;
-    if (of_find_property(host->dev->of_node, "ignore-pm-notify", NULL))
-        mmc->pm_caps |= MMC_PM_IGNORE_PM_NOTIFY;
+       if (of_find_property(host->dev->of_node, "ignore-pm-notify", NULL))
+                mmc->pm_caps |= MMC_PM_IGNORE_PM_NOTIFY;
        if (of_find_property(host->dev->of_node, "enable-sdio-wakeup", NULL))
                mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
 
-    /*Assign pm_caps pass to pm_flags*/
+        /*Assign pm_caps pass to pm_flags*/
         mmc->pm_flags = mmc->pm_caps;
 
        if (host->pdata->blk_settings) {
@@ -3014,74 +3055,72 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
                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);
-
-    if (!(mmc->restrict_caps & RESTRICT_CARD_TYPE_SD))//(gpio_is_valid(slot->pwr_en_gpio))
-    {
-        host->vmmc = NULL;
-    }else{
+        /* pwr_en */   
+        slot->pwr_en_gpio = dw_mci_of_get_pwr_en_gpio(host->dev, slot->id);
 
-        if(mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)
+        if (!(mmc->restrict_caps & RESTRICT_CARD_TYPE_SD))
         {
-           host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc");
-       }
-       else
-       {
-           host->vmmc = NULL;
-       }
+                host->vmmc = NULL;
+        }else{
+
+                if(mmc->restrict_caps & RESTRICT_CARD_TYPE_SD)
+                        host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc");
+                else
+                        host->vmmc = NULL;
         
-       if (IS_ERR(host->vmmc)) {
-               pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
-               host->vmmc = NULL;
-       } else {
-               ret = regulator_enable(host->vmmc);
-               if (ret) {
-                       dev_err(host->dev,
-                               "failed to enable regulator: %d\n", ret);
-                       goto err_setup_bus;
-               }
-       }
-    }
+                if (IS_ERR(host->vmmc)) {
+                       pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
+                       host->vmmc = NULL;
+               }else{
+                        ret = regulator_enable(host->vmmc);
+                        if (ret) {
+                               dev_err(host->dev,
+                                       "failed to enable regulator: %d\n", ret);
+                               host->vmmc = NULL;
+                               goto err_setup_bus;
+                        }
+                }
+        }
     
-       slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id);
+        slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id);
        
-    if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)
-        clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+        if (mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)
+                clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 
-       ret = mmc_add_host(mmc);
-       if (ret)
-               goto err_setup_bus;
-
-    /* Pinctrl set default iomux state to fucntion port.
-     * Fixme: DON'T TOUCH EMMC SETTING!
-     */
-     if(!(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC))
-     {
-        host->pinctrl = devm_pinctrl_get(host->dev);
-        if(IS_ERR(host->pinctrl))
-            printk("%s: Warning : No pinctrl used!\n",mmc_hostname(host->mmc));
-        else
+        ret = mmc_add_host(mmc);
+        if (ret)
+                goto err_setup_bus;
+
+        /* Pinctrl set default iomux state to fucntion port.
+         * Fixme: DON'T TOUCH EMMC SETTING!
+         */
+        if(!(host->mmc->restrict_caps & RESTRICT_CARD_TYPE_EMMC))
         {
-            host->pins_idle= pinctrl_lookup_state(host->pinctrl,PINCTRL_STATE_IDLE);
-            if(IS_ERR(host->pins_default))
-                printk("%s: Warning : No IDLE pinctrl matched!\n", mmc_hostname(host->mmc));
-            else
-            { 
-                if(pinctrl_select_state(host->pinctrl, host->pins_idle) < 0)
-                    printk("%s: Warning :  Idle pinctrl setting failed!\n", mmc_hostname(host->mmc));  
-            }
+                host->pinctrl = devm_pinctrl_get(host->dev);
+                if(IS_ERR(host->pinctrl)){
+                        printk("%s: Warning : No pinctrl used!\n",mmc_hostname(host->mmc));
+                }else{
+                        host->pins_idle= pinctrl_lookup_state(host->pinctrl,PINCTRL_STATE_IDLE);
+                        if(IS_ERR(host->pins_default)){
+                                printk("%s: Warning : No IDLE pinctrl matched!\n", mmc_hostname(host->mmc));
+                        }
+                        else
+                        { 
+                                if(pinctrl_select_state(host->pinctrl, host->pins_idle) < 0)
+                                        printk("%s: Warning :  Idle pinctrl setting failed!\n", mmc_hostname(host->mmc));  
+                        }
         
-            host->pins_default = pinctrl_lookup_state(host->pinctrl,PINCTRL_STATE_DEFAULT);
-            if(IS_ERR(host->pins_default))
-                printk("%s: Warning : No default pinctrl matched!\n", mmc_hostname(host->mmc));
-            else
-            { 
-                if(pinctrl_select_state(host->pinctrl, host->pins_default) < 0)
-                   printk("%s: Warning :  Default pinctrl setting failed!\n", mmc_hostname(host->mmc));  
-            }
-         }
-     }
+                        host->pins_default = pinctrl_lookup_state(host->pinctrl,PINCTRL_STATE_DEFAULT);
+                        if(IS_ERR(host->pins_default)){
+                                printk("%s: Warning : No default pinctrl matched!\n", mmc_hostname(host->mmc));
+                        }
+                        else
+                        {
+                                if(pinctrl_select_state(host->pinctrl, host->pins_default) < 0)
+                                        printk("%s: Warning :  Default pinctrl setting failed!\n", mmc_hostname(host->mmc));
+                        }
+                }
+        }
     
     
 #if defined(CONFIG_DEBUG_FS)
@@ -3375,6 +3414,7 @@ int dw_mci_probe(struct dw_mci *host)
         host->irq_state = true;
         host->set_speed = 0;
         host->set_div = 0;
+        host->svi_flags = 0;
 
        spin_lock_init(&host->lock);
        INIT_LIST_HEAD(&host->queue);
index b51aec791803164fe2d78f00e2085a976f941759..c0b0e344a5548659c59967b5364d0d133cbb4c40 100755 (executable)
@@ -193,7 +193,7 @@ struct dw_mci {
        /* Workaround flags */
        u32                     quirks;
        bool        irq_state;
-
+       u32                     svi_flags; /*switch voltage interrupt flags*/
        struct regulator        *vmmc;  /* Power regulator */
        unsigned long           irq_flags; /* IRQ flags */
        int                     irq;