Merge tag 'v4.4-rc5'
[firefly-linux-kernel-4.4.55.git] / drivers / misc / tcc_bt_dev.c
index 840b17d0158c8101452ff2bc57f647643b87dbd5..c8137d0bfa2382b1e10477420f967ee364e85c85 100755 (executable)
@@ -41,7 +41,7 @@
 \r
 static wait_queue_head_t        eint_wait;\r
 static struct work_struct       rda_bt_event_work;\r
-static struct workqueue_struct *rda_bt_workqueue;
+//static struct workqueue_struct *rda_bt_workqueue;
 \r
 static int irq_num  = -1;
 static int eint_gen;\r
@@ -49,24 +49,28 @@ static int eint_mask;
 static struct class *bt_dev_class;\r
 static struct mutex  sem;\r
 static struct tcc_bt_platform_data *tcc_bt_pdata = NULL;\r
-\r
-\r
+static int irq_flag = 0;
+
+
 static void rda_bt_enable_irq(void)\r
-{\r
-    if(irq_num != -1) \r
-    {\r
-        enable_irq(irq_num);\r
-    }\r
-}\r
-\r
+{
+    if((irq_num != -1) && (irq_flag == 0))
+    {
+        enable_irq(irq_num);
+        irq_flag = 1;
+    }
+}
+
 static void rda_bt_disable_irq(void)\r
-{\r
-    if(irq_num != -1)\r
-    {  \r
-        disable_irq_nosync(irq_num);\r
-    }        \r
-}\r
-\r
+{
+    if((irq_num != -1) && (irq_flag == 1))
+    {  
+        disable_irq_nosync(irq_num);
+        irq_flag = 0;
+    }       
+}
+
+#if 0
 static void rda_bt_work_fun(struct work_struct *work)\r
 {\r
     struct hci_dev *hdev = NULL;\r
@@ -86,9 +90,9 @@ static void rda_bt_work_fun(struct work_struct *work)
     }\r
     \r
     rda_bt_enable_irq();\r
-}\r
-\r
-\r
+}
+#endif
+
 static int tcc_bt_dev_open(struct inode *inode, struct file *file)\r
 {\r
     printk("[## BT ##] tcc_bt_dev_open.\n");\r
@@ -141,13 +145,13 @@ static int tcc_bt_power_control(int on_off)
     {      \r
         gpio_direction_output(tcc_bt_pdata->power_gpio.io, tcc_bt_pdata->power_gpio.enable);\r
         msleep(500);
-        enable_irq(irq_num); \r
+         rda_bt_enable_irq();
     }\r
     else\r
     {\r
        gpio_direction_output(tcc_bt_pdata->power_gpio.io, !tcc_bt_pdata->power_gpio.enable);\r
-       disable_irq(irq_num);
-       msleep(500);\r
+       rda_bt_disable_irq();
+        msleep(500);\r
     }\r
 \r
     return 0;\r
@@ -176,7 +180,7 @@ static long  tcc_bt_dev_ioctl(struct file *file, unsigned int cmd,unsigned long
                \r
         case IOCTL_BT_SET_EINT:\r
         {\r
-               if (copy_from_user(&rate, argp, sizeof(rate)))\r
+           if (copy_from_user(&rate, argp, sizeof(rate)))\r
                 return -EFAULT;\r
             printk("[## BT ##] IOCTL_BT_SET_EINT cmd[%d].\n", cmd);\r
             mutex_lock(&sem); \r
@@ -223,29 +227,25 @@ struct wake_lock rda_bt_wakelock;
 static irqreturn_t rda_bt_host_wake_irq(int irq, void *dev)\r
 {\r
     printk("rda_bt_host_wake_irq.\n");\r
-       \r
+    rda_bt_disable_irq();      
+
 #ifdef HOST_WAKE_DELAY\r
     wake_lock_timeout(&rda_bt_wakelock, 3 * HZ); \r
 #endif
 
-    if(irq_num != -1) \r
-    {  \r
-        disable_irq_nosync(irq_num);\r
-    }   \r
-\r
-#ifdef CONFIG_BT_HCIUART\r
-    if(rda_bt_workqueue)\r
+#if 0 //CONFIG_BT_HCIUART
+    if(rda_bt_workqueue)
         queue_work(rda_bt_workqueue, &rda_bt_event_work);\r
 #else\r
     /* Maybe handle the interrupt in user space? */\r
     eint_gen = 1;\r
     wake_up_interruptible(&eint_wait);\r
     /* Send host wakeup command in user space, enable irq then */\r
-#endif\r
-   \r
-    return IRQ_HANDLED;\r
-}\r
-\r
+#endif
+    
+    return IRQ_HANDLED;
+}
+
 static int tcc_bt_probe(struct platform_device *pdev)\r
 {\r
     int ret;\r
@@ -254,7 +254,7 @@ static int tcc_bt_probe(struct platform_device *pdev)
     \r
     printk("tcc_bt_probe.\n");\r
     if(pdata == NULL) {\r
-       printk("mt6622_probe failed.\n");\r
+       printk("tcc_bt_probe failed.\n");\r
        return -1;\r
     }\r
     tcc_bt_pdata = pdata;\r
@@ -288,8 +288,11 @@ static int tcc_bt_probe(struct platform_device *pdev)
          irq_num = -1;\r
         goto error;\r
     }\r
-\r
-\r
+
+    enable_irq_wake(irq_num);
+    irq_flag = 1;
+    rda_bt_disable_irq();
+
     mutex_init(&sem);  \r
     printk("[## BT ##] init_module\n");\r
        \r
@@ -310,18 +313,18 @@ static int tcc_bt_probe(struct platform_device *pdev)
     device_create(bt_dev_class, NULL, MKDEV(BT_DEV_MAJOR_NUM, BT_DEV_MINOR_NUM), NULL, DEV_NAME);\r
 
     init_waitqueue_head(&eint_wait);\r
-    \r
+   
+    /*
     INIT_WORK(&rda_bt_event_work, rda_bt_work_fun);\r
-    \r
-    rda_bt_workqueue = create_singlethread_workqueue("rda_bt");\r
-    \r
-    if (!rda_bt_workqueue)\r
-    {\r
+    rda_bt_workqueue = create_singlethread_workqueue("rda_bt");
+    if (!rda_bt_workqueue)
+    {
         printk("create_singlethread_workqueue failed.\n");\r
         ret = -ESRCH;\r
         goto error;\r
-    }  
-\r
+    } 
+    */
     return 0;\r
     \r
 error:\r
@@ -332,13 +335,14 @@ error:
 \r
 static int tcc_bt_remove(struct platform_device *pdev)\r
 {\r
-    printk("[## BT ##] cleanup_module.\n");\r
+    printk("[## BT ##] cleanup_module.\n");
+    free_irq(irq_num, NULL);
     unregister_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME);\r
     if(tcc_bt_pdata)\r
         tcc_bt_pdata = NULL;
 
     cancel_work_sync(&rda_bt_event_work);\r
-    destroy_workqueue(rda_bt_workqueue);    \r
+    //destroy_workqueue(rda_bt_workqueue);    \r
     \r
 #ifdef HOST_WAKE_DELAY    \r
     wake_lock_destroy(&rda_bt_wakelock);\r