mt6622 bluetooth: support wake up host
authorhwg <hwg@rock-chips.com>
Thu, 25 Apr 2013 01:12:38 +0000 (09:12 +0800)
committerhwg <hwg@rock-chips.com>
Thu, 25 Apr 2013 01:13:37 +0000 (09:13 +0800)
drivers/mtk_wcn_bt/bt_eirq_handler.c
drivers/mtk_wcn_bt/bt_hwctl.h
drivers/mtk_wcn_bt/bt_hwctl_dev.c
drivers/mtk_wcn_bt/bt_plat_smdk.c
include/linux/rfkill-rk.h

index 7e628304813ac33504481168d4972e5497e3a007..4beca42a009efe7f794ffea6e8ea2941310c7c8b 100755 (executable)
@@ -53,8 +53,17 @@ irqreturn_t mt_bt_eirq_handler(int i, void *arg)
     mt_bt_disable_irq();
 
 #ifdef CONFIG_BT_HCIUART
-    if(mtk_wcn_bt_workqueue)
-        queue_work(mtk_wcn_bt_workqueue, &mtk_wcn_bt_event_work);
+    /* BlueZ stack, hci_uart driver */
+    hdev = hci_dev_get(0);
+    if(hdev == NULL){
+        /* Avoid the early interrupt before hci0 registered */
+        //BT_HWCTL_ALERT("hdev is NULL\n");
+    }else{
+        //BT_HWCTL_ALERT("EINT arrives! notify host wakeup\n");
+        //printk("Send host wakeup command\n");
+        hci_send_cmd(hdev, 0xFCC1, 0, NULL);
+        /* enable irq after receiving host wakeup command's event */
+    }
 #else
     /* Maybe handle the interrupt in user space? */
     eint_gen = 1;
@@ -62,5 +71,6 @@ irqreturn_t mt_bt_eirq_handler(int i, void *arg)
     /* Send host wakeup command in user space, enable irq then */
 #endif
 
+    mt_bt_enable_irq();
     return IRQ_HANDLED;
-}
\ No newline at end of file
+}
index 3149033007c4391e2fcd48878af7b8ea110f7d26..e1fa8143280a35f81f2d1254b5fce54ed7f35c34 100755 (executable)
@@ -59,4 +59,7 @@ extern void mt_bt_enable_irq(void);
 extern void mt_bt_disable_irq(void);
 extern void *mt_bt_get_platform_data(void);
 
-#endif
\ No newline at end of file
+extern int mt6622_suspend(struct platform_device *pdev, pm_message_t state);
+extern int mt6622_resume(struct platform_device *pdev);
+
+#endif
index d073bbc28a727154ff22ed77ec271e3583a39177..8e3c9f2dfd7092cf102d6656c6ba510fe25a0100 100755 (executable)
@@ -245,7 +245,7 @@ static int mt6622_probe(struct platform_device *pdev)
                if(pdata->power_gpio.io != INVALID_GPIO) {
                        if (gpio_request(pdata->power_gpio.io, "BT_PWR_EN")){
                                printk("mt6622 power_gpio is busy!\n");
-                               return -1;
+                               //return -1;
                        }
                }
                
@@ -253,7 +253,7 @@ static int mt6622_probe(struct platform_device *pdev)
                        if (gpio_request(pdata->reset_gpio.io, "BT_RESET")){
                                printk("mt6622 reset_gpio is busy!\n");
                                gpio_free(pdata->power_gpio.io);
-                               return -1;
+                               //return -1;
                        }
                }
                
@@ -262,7 +262,7 @@ static int mt6622_probe(struct platform_device *pdev)
                                printk("mt6622 irq_gpio is busy!\n");
                                gpio_free(pdata->power_gpio.io);
                                gpio_free(pdata->reset_gpio.io);
-                               return -1;
+                               //return -1;
                        }
                }
                
@@ -309,6 +309,8 @@ static struct file_operations bt_hwctl_fops = {
 static struct platform_driver mt6622_driver = {
     .probe = mt6622_probe,
     .remove = mt6622_remove,
+    .suspend = mt6622_suspend,
+    .resume = mt6622_resume,
     .driver = {
         .name = "mt6622",
         .owner = THIS_MODULE,
@@ -362,13 +364,13 @@ static int __init bt_hwctl_init(void)
     
     init_waitqueue_head(&eint_wait);
     
-    INIT_WORK(&mtk_wcn_bt_event_work, mtk_wcn_bt_work_fun);
+    /*INIT_WORK(&mtk_wcn_bt_event_work, mtk_wcn_bt_work_fun);
     mtk_wcn_bt_workqueue = create_singlethread_workqueue("mtk_wcn_bt");
     if (!mtk_wcn_bt_workqueue) {
         printk("create_singlethread_workqueue failed.\n");
         err = -ESRCH;
         goto ERR_EXIT;
-    }    
+    }*/    
     
     /* request gpio used by BT */
     //mt_bt_gpio_init();
index 4948493ba6e7636157f561637922fd21edf845e0..9df7ccb4d9f6728f93a296b131b47196bf99169e 100755 (executable)
@@ -41,6 +41,7 @@
 #include <linux/interrupt.h>\r
 #include <linux/gpio.h>\r
 #include <mach/gpio.h>\r
+#include <mach/iomux.h>\r
 //#include <plat/gpio-cfg.h>\r
 \r
 #include "bt_hwctl.h"\r
 \r
 static int irq_num = -1;\r
 \r
+#ifdef CONFIG_ARCH_RK29\r
+    #define rk_mux_api_set(name,mode)      rk29_mux_api_set(name,mode)\r
+#elif defined (CONFIG_ARCH_RK30)\r
+    #define rk_mux_api_set(name,mode)      rk30_mux_api_set(name,mode)\r
+#else\r
+    #define rk_mux_api_set(name,mode)      rk30_mux_api_set(name,mode)\r
+#endif\r
+\r
 /****************************************************************************\r
  *                       I R Q   F U N C T I O N S                          *\r
 *****************************************************************************/\r
 static int mt_bt_request_irq(void)\r
 {\r
     int iRet;\r
-    int trigger = IRQF_TRIGGER_HIGH;\r
+    int trigger = IRQF_TRIGGER_RISING;\r
     struct mt6622_platform_data *pdata = (struct mt6622_platform_data *)mt_bt_get_platform_data();\r
                \r
     if(pdata->irq_gpio.enable == GPIO_LOW)\r
-       trigger = IRQF_TRIGGER_LOW;\r
+       trigger = IRQF_TRIGGER_FALLING;\r
     \r
     iRet = request_irq(irq_num, mt_bt_eirq_handler, \r
         trigger, "BT_INT_B", NULL);\r
@@ -86,9 +95,28 @@ static void mt_bt_free_irq(void)
     }\r
 }\r
 \r
+int mt6622_suspend(struct platform_device *pdev, pm_message_t state)\r
+{\r
+    if(irq_num != -1) {\r
+        printk(KERN_INFO MODULE_TAG "mt6622_suspend\n");\r
+        enable_irq_wake(irq_num);\r
+    }\r
+       return 0;\r
+}\r
+\r
+int mt6622_resume(struct platform_device *pdev)\r
+{\r
+    if(irq_num != -1) {\r
+        printk(KERN_INFO MODULE_TAG "mt6622_resume\n");\r
+        disable_irq_wake(irq_num);\r
+    }\r
+       return 0;\r
+}\r
+\r
 void mt_bt_enable_irq(void)\r
 {\r
     if(irq_num != -1) {\r
+        //printk("mt_bt_enable_irq\n");\r
         enable_irq(irq_num);\r
     }\r
 }\r
@@ -97,6 +125,7 @@ EXPORT_SYMBOL(mt_bt_enable_irq);
 void mt_bt_disable_irq(void)\r
 {\r
     if(irq_num != -1) {        \r
+        //printk("mt_bt_disable_irq\n");\r
         disable_irq_nosync(irq_num);\r
     }        \r
 }\r
@@ -133,7 +162,7 @@ int mt_bt_power_init(void)
            if(pdata->reset_gpio.io != INVALID_GPIO)\r
                gpio_direction_output(pdata->reset_gpio.io, 1);\r
            msleep(1000);\r
-           \r
+\r
            //pdata->power_gpio.io = INVALID_GPIO;\r
            pdata->reset_gpio.io = INVALID_GPIO;\r
        }\r
@@ -193,6 +222,14 @@ int mt_bt_power_on(void)
            if(pdata->reset_gpio.io != INVALID_GPIO)\r
                gpio_direction_output(pdata->reset_gpio.io, 1);\r
            msleep(1000);\r
+\r
+        if(gpio_is_valid(pdata->rts_gpio.io)) {\r
+            printk(KERN_INFO MODULE_TAG "mt_bt_power_on rts iomux\n");\r
+            rk_mux_api_set(pdata->rts_gpio.iomux.name, pdata->rts_gpio.iomux.fgpio);\r
+            gpio_direction_output(pdata->rts_gpio.io, 0);\r
+            msleep(100);\r
+            rk_mux_api_set(pdata->rts_gpio.iomux.name, pdata->rts_gpio.iomux.fmux);\r
+        }\r
            \r
            error = mt_bt_request_irq();\r
            if (error){\r
index 4ff6ab9d4623fb7ebdec769144ff9bf310c122f1..8c892b1ad201a15a9b142bb9c767dd37ecea6321 100755 (executable)
@@ -66,6 +66,7 @@ struct mt6622_platform_data {
     struct rfkill_rk_gpio   power_gpio;
     struct rfkill_rk_gpio   reset_gpio;
     struct rfkill_rk_gpio   irq_gpio;
+    struct rfkill_rk_gpio   rts_gpio;
 };
 
 #endif /* __RFKILL_GPIO_H */