#define SDMMC_USE_INT_UNBUSY 0///1
#endif
+/*
+** You can set the macro to true, if some module wants to use this feature, which is about SDIO suspend-resume.
+** As the following example.
+** added by xbw at 2013-05-08
+*/
+#if defined(CONFIG_MTK_COMBO_DRIVER_VERSION_JB2)
+#define RK_SDMMC_USE_SDIO_SUSPEND_RESUME 1
+#else
+#define RK_SDMMC_USE_SDIO_SUSPEND_RESUME 0
+#endif
+
#define RK29_SDMMC_ERROR_FLAGS (SDMMC_INT_FRUN | SDMMC_INT_HLE )
#if defined(CONFIG_SDMMC0_RK29_SDCARD_DET_FROM_GPIO)
#define RK29_SDMMC_WAIT_DTO_INTERNVAL 4500 //The time interval from the CMD_DONE_INT to DTO_INT
#define RK29_SDMMC_REMOVAL_DELAY 2000 //The time interval from the CD_INT to detect_timer react.
-#define RK29_SDMMC_VERSION "Ver.5.03 The last modify date is 2013-02-21"
+#define RK29_SDMMC_VERSION "Ver.5.05 The last modify date is 2013-05-08"
#if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD)
#define RK29_CTRL_SDMMC_ID 0 //mainly used by SDMMC
#ifdef CONFIG_RK29_SDIO_IRQ_FROM_GPIO
unsigned int sdio_INT_gpio;
unsigned int sdio_irq;
+ unsigned long trigger_level;
#endif
#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) || defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT)
if (sg->offset & 3 || sg->length & 3)
{
data->error = -EILSEQ;
+ printk("%s..%d..CMD%d(arg=0x%x), data->blksz=%d, data->blocks=%d [%s]\n", \
+ __FUNCTION__, __LINE__, host->cmd->opcode,\
+ host->cmd->arg,data->blksz, data->blocks, host->dma_name);
return ;
}
}
{
struct rk29_sdmmc *host = mmc_priv(mmc);
u32 cdetect=1;
-
+#if defined(CONFIG_SDMMC0_RK29_SDCARD_DET_FROM_GPIO)
+ int i=0,cdetect1=0, cdetect2=0;
+#endif
switch(host->pdev->id)
{
case 0:
if(host->det_pin.io == INVALID_GPIO)
return 1;
- cdetect = gpio_get_value(host->det_pin.io);
+ for(i=0;i<5;i++)
+ {
+ udelay(10);
+ cdetect1 = gpio_get_value(host->det_pin.io);
+ udelay(10);
+ cdetect2 = gpio_get_value(host->det_pin.io);
+ if(cdetect1 == cdetect2)
+ break;
+ }
+ cdetect = cdetect2;
if(host->det_pin.enable)
cdetect = cdetect?1:0;
else
}
-
+extern void rk29_sdmmc_gpio_open(int device_id, int on);
static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
int timeout = 250;
rk29_sdmmc_reset_controller(host);
}
- //power-off
- gpio_direction_output(host->gpio_power_en, !(host->gpio_power_en_level));
+
+ rk29_sdmmc_gpio_open(0, 0);
+ //power-off
+ gpio_direction_output(host->gpio_power_en, !(host->gpio_power_en_level));
+ goto out;
}
break;
}
- if(!(test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags) || (RK29_CTRL_SDIO1_ID != host->pdev->id)))
+ if((!(test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags))|| !rk29_sdmmc_get_cd(host->mmc))
+ &&(RK29_CTRL_SDIO1_ID != host->pdev->id))
goto out; //exit the set_ios directly if the SDIO is not present.
if(host->ctype != ios->bus_width)
struct rk29_sdmmc *host = mmc_priv(mmc);
#if defined(CONFIG_RK29_SDIO_IRQ_FROM_GPIO)
- if(enable)
+ if(enable)
+ {
enable_irq(host->sdio_irq);
- //enable_irq_wake(host->sdio_irq);
- else
+
+ #if !defined(CONFIG_MTK_COMBO_DRIVER_VERSION_JB2)
+ enable_irq_wake(host->sdio_irq);
+ #endif
+ }
+ else
+ {
disable_irq_nosync(host->sdio_irq);
+
+ #if !defined(CONFIG_MTK_COMBO_DRIVER_VERSION_JB2)
+ disable_irq_wake(host->sdio_irq);
+ #endif
+ }
#else
spin_lock_irqsave(&host->lock, flags);
{
if (status)
{
+ #if RK_SDMMC_USE_SDIO_SUSPEND_RESUME
+ if(host->pdev->id == RK29_CTRL_SDIO1_ID)
+ host->mmc->pm_caps |= (MMC_PM_KEEP_POWER|MMC_PM_WAKE_SDIO_IRQ);
+ #endif
+
rk29_sdmmc_hw_init(host);
set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(200));
if(RK29_CTRL_SDIO1_ID == host->pdev->id)
{
host->sdio_INT_gpio = pdata->sdio_INT_gpio;
+ #ifdef USE_SDIO_INT_LEVEL
+ host->trigger_level = pdata->sdio_INT_level;
+ #endif
}
#endif
gpio_pull_updown(host->sdio_INT_gpio, 0); //disable default internal pull-down
host->sdio_irq = gpio_to_irq(host->sdio_INT_gpio);
+ #ifdef USE_SDIO_INT_LEVEL
+ trigger_flags = (host->trigger_level==GPIO_HIGH)?IRQF_TRIGGER_HIGH:IRQF_TRIGGER_LOW;
+ #else
trigger_flags = IRQF_TRIGGER_LOW;
+ #endif
//printk("%d..%s sdio interrupt gpio level=%lu ====[%s]====\n", __LINE__, __FUNCTION__, trigger_flags, host->dma_name);
ret = request_irq(host->sdio_irq, rk29_sdmmc_sdio_irq_cb,
trigger_flags,
__FUNCTION__, __LINE__, ret, host->dma_name);
host->errorstep = 0x8D;
goto err_dmaunmap;
- }
- disable_irq_nosync(host->sdio_irq);
+ }
+
+ disable_irq_nosync(host->sdio_irq);
+ enable_irq_wake(host->sdio_irq);
}
#endif
dev_info(&host->pdev->dev, "rk29_sdmmc_sdcard_suspend error\n");
#endif
}
+#if RK_SDMMC_USE_SDIO_SUSPEND_RESUME
+ else if(host && host->pdev && (RK29_CTRL_SDIO1_ID == host->pdev->id))
+ {
+ if (mmc)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
+ ret = mmc_suspend_host(mmc);
+#else
+ ret = mmc_suspend_host(mmc, state);
+#endif
+ if(!ret)
+ {
+ clk_disable(host->clk);
+ clk_disable(clk_get(&pdev->dev, "hclk_mmc"));
+ }
+ }
+#endif // --#if RK_SDMMC_USE_SDIO_SUSPEND_RESUME
return ret;
}
ret = mmc_resume_host(mmc);
}
- }
+ }
+#if RK_SDMMC_USE_SDIO_SUSPEND_RESUME
+ else if(host && host->pdev && (RK29_CTRL_SDIO1_ID == host->pdev->id))
+ {
+ if (mmc)
+ {
+ clk_enable(host->clk);
+ clk_enable(clk_get(&pdev->dev, "hclk_mmc"));
+ mdelay(20);
+ ret = mmc_resume_host(mmc);
+ }
+ }
+#endif // --#if RK_SDMMC_USE_SDIO_SUSPEND_RESUME
return ret;
}