wifi: add wifi virtual card detect support
authorlbt <lbt@rock-chips.com>
Tue, 14 Dec 2010 06:22:47 +0000 (14:22 +0800)
committerlbt <lbt@rock-chips.com>
Tue, 14 Dec 2010 06:25:48 +0000 (14:25 +0800)
arch/arm/mach-rk29/board-rk29sdk.c
drivers/mmc/host/rk29_sdmmc.c

index 22862eafeab50f8fb139f794b84229e80631b795..ac5969ed337f4520e39157b64677ed6440345a0d 100755 (executable)
@@ -840,7 +840,9 @@ struct rk29_sdmmc_platform_data default_sdmmc1_data = {
         .status = rk29sdk_wifi_status,
         .register_status_notify = rk29sdk_wifi_status_register,
 #endif
+#if 0
         .detect_irq = RK29SDK_WIFI_SDIO_CARD_DETECT_N,
+#endif
 };\r
 #endif\r
 
index 8c60ffb12a6f2ad6534ab02581b91331e521b5c1..09ee6933d246e72e75b985f314308fe246bc3015 100755 (executable)
@@ -111,6 +111,7 @@ struct rk29_sdmmc {
        int                     id;
        int                     irq;
        struct timer_list       detect_timer;
+        unsigned int            oldstatus;
 };
 
 #define rk29_sdmmc_test_and_clear_pending(host, event)         \
@@ -450,8 +451,10 @@ static int rk29_sdmmc_submit_data_dma(struct rk29_sdmmc *host, struct mmc_data *
         * non-word-aligned buffers or lengths. Also, we don't bother
         * with all the DMA setup overhead for short transfers.
         */
+#if 0
        if (data->blocks * data->blksz < RK29_SDMMC_DMA_THRESHOLD)
                return -EINVAL;
+#endif
        if (data->blksz & 3)
                return -EINVAL;
        for_each_sg(data->sg, sg, data->sg_len, i) {
@@ -1099,6 +1102,7 @@ static void rk29_sdmmc_cmd_interrupt(struct rk29_sdmmc *host, u32 status)
        tasklet_schedule(&host->tasklet);
 }
 
+#if 0
 static int rk29_sdmmc1_card_get_cd(struct mmc_host *mmc)
 {
         struct rk29_sdmmc *host = mmc_priv(mmc);
@@ -1134,6 +1138,7 @@ static irqreturn_t rk29_sdmmc1_card_detect_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 
 }
+#endif
 
 static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id)
 {
@@ -1288,6 +1293,37 @@ static void rk29_sdmmc_detect_change(unsigned long data)
        mmc_detect_change(host->mmc, 0);        
 }
 
+static void rk29_sdmmc1_check_status(unsigned long data)
+{
+        struct rk29_sdmmc *host = (struct rk29_sdmmc *)data;
+        struct rk29_sdmmc_platform_data *pdata = host->pdev->dev.platform_data;
+        unsigned int status;
+
+        status = pdata->status(mmc_dev(host->mmc));
+
+        if (status ^ host->oldstatus)
+        {
+                pr_info("%s: slot status change detected(%d-%d)\n",mmc_hostname(host->mmc), host->oldstatus, status);
+                if (status) {
+                    set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+                    mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(200));
+                }
+                else {
+                    clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+                    rk29_sdmmc_detect_change((unsigned long)host);
+                }
+        }
+
+        host->oldstatus = status;
+}
+
+static void rk29_sdmmc1_status_notify_cb(int card_present, void *dev_id)
+{
+        struct rk29_sdmmc *host = dev_id;
+        printk(KERN_INFO "%s, card_present %d\n", mmc_hostname(host->mmc), card_present);
+        rk29_sdmmc1_check_status((unsigned long)host);
+}
+
 static int rk29_sdmmc_probe(struct platform_device *pdev)
 {
        struct mmc_host                 *mmc;
@@ -1365,22 +1401,45 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
        ret = request_irq(irq, rk29_sdmmc_interrupt, 0, dev_name(&pdev->dev), host);
        if (ret)
            goto err_dmaunmap;
-        
+       
+#if 0 
         /* register sdmmc1 card detect interrupt route */ 
-    if ((pdev->id == 1) && (pdata->detect_irq != 0)) {
-        irq = gpio_to_irq(pdata->detect_irq);
-        if (irq < 0)  {
-           printk("%s: request gpio irq failed\n", __FUNCTION__);
-           goto err_dmaunmap;
-        }
+        if ((pdev->id == 1) && (pdata->detect_irq != 0)) {
+               irq = gpio_to_irq(pdata->detect_irq);
+               if (irq < 0)  {
+                       printk("%s: request gpio irq failed\n", __FUNCTION__);
+                       goto err_dmaunmap;
+               }
         
-        ret = request_irq(irq, rk29_sdmmc1_card_detect_interrupt, IRQF_TRIGGER_RISING, dev_name(&pdev->dev), host);
-        if (ret) {
-           printk("%s: sdmmc1 request detect interrupt failed\n", __FUNCTION__);
-           goto err_dmaunmap;
-        }
+               ret = request_irq(irq, rk29_sdmmc1_card_detect_interrupt, IRQF_TRIGGER_RISING, dev_name(&pdev->dev), host);
+               if (ret) {
+                       printk("%s: sdmmc1 request detect interrupt failed\n", __FUNCTION__);
+                       goto err_dmaunmap;
+               }
          
-    }
+       }
+#endif
+        /* setup sdmmc1 wifi card detect change */
+        if (pdata->register_status_notify) {
+            pdata->register_status_notify(rk29_sdmmc1_status_notify_cb, host);
+        }
+
+        /* Assume card is present initially */
+        if(rk29_sdmmc_get_cd(host->mmc))
+                set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+        else
+                clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+
+        /* sdmmc1 wifi card slot status initially */
+        if (pdata->status) {
+            host->oldstatus = pdata->status(mmc_dev(host->mmc));
+            if (host->oldstatus)  {
+                set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+            }else {
+                clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
+            }
+        }
+
        platform_set_drvdata(pdev, host);       
        mmc->ops = &rk29_sdmmc_ops[pdev->id];
        mmc->f_min = host->bus_hz/510;
@@ -1393,11 +1452,6 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
        mmc->max_blk_count = 65535;  ///512;
        mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
        mmc->max_seg_size = mmc->max_req_size;  
-       /* Assume card is present initially */
-       if(rk29_sdmmc_get_cd(host->mmc))
-               set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
-       else
-               clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags);
         
        mmc_add_host(mmc);
 #if defined (CONFIG_DEBUG_FS)