Loquate: Add bt sleep and wakeup host function
authorwdc <wdc@rock-chips.com>
Fri, 25 May 2012 10:13:16 +0000 (18:13 +0800)
committerwdc <wdc@rock-chips.com>
Fri, 25 May 2012 10:14:54 +0000 (18:14 +0800)
arch/arm/configs/rk30_phone_loquat_defconfig
arch/arm/mach-rk30/board-rk30-phone-loquat-rfkill.c

index cbeec3c1e802f88db62459b6c304cf3ad13ee839..ee58a15b94a481419e6a0d89cfc48cc567feda55 100755 (executable)
@@ -176,6 +176,7 @@ CONFIG_BT_HIDP=y
 CONFIG_BT_HCIUART=y
 CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIBCM4325=y
+CONFIG_BT_AUTOSLEEP=y
 CONFIG_RFKILL=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
index 0fd33698476857f014eab4f3c979932dcf620dfb..d2e353aca7522ceef04863722fa096c065196007 100755 (executable)
 #include <mach/iomux.h>
 #include <linux/wakelock.h>
 #include <linux/timer.h>
+#include <mach/board.h>
 
 #if 0
-#define DBG(x...)   printk(KERN_INFO x)
+#define DBG(x...)   printk(KERN_INFO "[BT_RFKILL]: "x)
 #else
 #define DBG(x...)
 #endif
 
-#define BT_WAKE_HOST_SUPPORT 1
+#define LOG(x...)   printk(KERN_INFO "[BT_RFKILL]: "x)
 
-struct bt_ctrl
-{
-    struct rfkill *bt_rfk;
-#if BT_WAKE_HOST_SUPPORT
-    struct timer_list tl;
-    bool b_HostWake;
-    struct wake_lock bt_wakelock;
+#ifdef CONFIG_BCM4329
+#define WIFI_BT_POWER_TOGGLE   1
+#else
+#define WIFI_BT_POWER_TOGGLE   0
 #endif
-};
 
+#define BT_WAKE_LOCK_TIMEOUT    10 //s
+
+#define BT_AUTO_SLEEP_TIMEOUT   3
+
+/*
+ * IO Configuration for RK29
+ */
+#ifdef CONFIG_ARCH_RK29
+
+#define BT_WAKE_HOST_SUPPORT    0
+
+/* IO configuration */
+// BT power pin
+#define BT_GPIO_POWER           RK29_PIN5_PD6
+#define IOMUX_BT_GPIO_POWER()     rk29_mux_api_set(GPIO5D6_SDMMC1PWREN_NAME, GPIO5H_GPIO5D6);
+
+// BT reset pin
+#define BT_GPIO_RESET           RK29_PIN6_PC4
+#define IOMUX_BT_GPIO_RESET()
+
+// BT wakeup pin
+#define BT_GPIO_WAKE_UP         RK29_PIN6_PC5
+#define IOMUX_BT_GPIO_WAKE_UP()
+
+// BT wakeup host pin
+#define BT_GPIO_WAKE_UP_HOST
+#define IOMUX_BT_GPIO_WAKE_UP_HOST()
+
+//bt cts paired to uart rts
+#define UART_RTS                RK29_PIN2_PA7
+#define IOMUX_UART_RTS_GPIO()   rk29_mux_api_set(GPIO2A7_UART2RTSN_NAME, GPIO2L_GPIO2A7)
+#define IOMUX_UART_RTS()        rk29_mux_api_set(GPIO2A7_UART2RTSN_NAME, GPIO2L_UART2_RTS_N)
+
+/*
+ * IO Configuration for RK30
+ */
+#elif defined (CONFIG_ARCH_RK30)
+
+#define BT_WAKE_HOST_SUPPORT    1
+
+/* IO configuration */
+// BT power pin
 #define BT_GPIO_POWER           RK30_PIN4_PD5
-#define IOMUX_BT_GPIO_POWER     rk29_mux_api_set(GPIO4D5_SMCDATA13_TRACEDATA13_NAME, GPIO4D_GPIO4D5);
-#define BT_GPIO_RESET                  RK30_PIN3_PD1
-#define IOMUX_BT_GPIO_RESET     rk29_mux_api_set(GPIO3D1_SDMMC1BACKENDPWR_NAME, GPIO3D_GPIO3D1);
+#define IOMUX_BT_GPIO_POWER     rk30_mux_api_set(GPIO4D5_SMCDATA13_TRACEDATA13_NAME, GPIO4D_GPIO4D5)
+
+// BT reset pin
+#define BT_GPIO_RESET           RK30_PIN3_PD1
+#define IOMUX_BT_GPIO_RESET     rk30_mux_api_set(GPIO3D1_SDMMC1BACKENDPWR_NAME, GPIO3D_GPIO3D1)
+
 
-#ifdef CONFIG_BT_HCIBCM4325
+// BT wakeup pin
 #define BT_GPIO_WAKE_UP         RK30_PIN3_PC6
-#endif
+#define IOMUX_BT_GPIO_WAKE_UP() rk29_mux_api_set(GPIO3C6_SDMMC1DETECTN_NAME, GPIO3C_GPIO3C6);
 
-#if BT_WAKE_HOST_SUPPORT
+// BT wakeup host pin
 #define BT_GPIO_WAKE_UP_HOST    RK30_PIN3_PD2
-#define IOMUX_BT_GPIO_WAKE_UP_HOST() rk29_mux_api_set(GPIO3D2_SDMMC1INTN_NAME, GPIO3D_GPIO3D2);
+#define IOMUX_BT_GPIO_WAKE_UP_HOST() rk29_mux_api_set(GPIO3D2_SDMMC1INTN_NAME, GPIO3D_GPIO3D2)
+#define BT_IRQ_WAKE_UP_HOST     gpio_to_irq(BT_GPIO_WAKE_UP_HOST)
 
-#define BT_WAKE_LOCK_TIMEOUT    10 //s
+//bt cts paired to uart rts
+#define UART_RTS                RK30_PIN1_PA3
+#define IOMUX_UART_RTS_GPIO()     rk29_mux_api_set(GPIO1A3_UART0RTSN_NAME, GPIO1A_GPIO1A3)
+#define IOMUX_UART_RTS()          rk29_mux_api_set(GPIO1A3_UART0RTSN_NAME, GPIO1A_UART0_RTS_N)
+
+#endif
+
+struct bt_ctrl
+{
+    struct rfkill *bt_rfk;
+#if BT_WAKE_HOST_SUPPORT
+    struct timer_list tl;
+    bool b_HostWake;
+    struct wake_lock bt_wakelock;
 #endif
+};
 
 static const char bt_name[] = 
 #if defined(CONFIG_RKWIFI)
-    "rk903"
+    #if defined(CONFIG_RKWIFI_26M)
+        "rk903_26M"
+    #else
+        "rk903"
+    #endif
 #elif defined(CONFIG_BCM4329)
     "bcm4329"
 #elif defined(CONFIG_MV8787)
@@ -71,11 +132,15 @@ static const char bt_name[] =
 #endif
 ;
 
+#if WIFI_BT_POWER_TOGGLE
 extern int rk29sdk_bt_power_state;
 extern int rk29sdk_wifi_power_state;
+#endif
 
 struct bt_ctrl gBtCtrl;
-    
+struct timer_list bt_sleep_tl;
+
+
 #if BT_WAKE_HOST_SUPPORT
 void resetBtHostSleepTimer(void)
 {
@@ -85,7 +150,7 @@ void resetBtHostSleepTimer(void)
 void btWakeupHostLock(void)
 {
     if(gBtCtrl.b_HostWake == false){
-        DBG("*************************Lock\n");
+        DBG("** Lock **\n");
         wake_lock(&(gBtCtrl.bt_wakelock));
         gBtCtrl.b_HostWake = true;
     }
@@ -94,7 +159,7 @@ void btWakeupHostLock(void)
 void btWakeupHostUnlock(void)
 {
     if(gBtCtrl.b_HostWake == true){        
-        DBG("*************************UnLock\n");
+        DBG("** UnLock **\n");
         wake_unlock(&(gBtCtrl.bt_wakelock));  //ÈÃϵͳ˯Ãß    
         gBtCtrl.b_HostWake = false;
     }    
@@ -102,23 +167,83 @@ void btWakeupHostUnlock(void)
 
 static void timer_hostSleep(unsigned long arg)
 {     
-       DBG("%s---b_HostWake=%d\n",__FUNCTION__,gBtCtrl.b_HostWake);
+       DBG("b_HostWake=%d\n", gBtCtrl.b_HostWake);
     btWakeupHostUnlock();
 }
 
+void bcm4325_sleep(unsigned long bSleep);
 
 #ifdef CONFIG_PM
+static irqreturn_t bcm4329_wake_host_irq(int irq, void *dev)
+{
+    DBG("%s\n",__FUNCTION__);
+
+    btWakeupHostLock();
+    resetBtHostSleepTimer();
+       return IRQ_HANDLED;
+}
+
+static void rfkill_do_wakeup(struct work_struct *work)
+{
+    // disable bt wakeup host
+    DBG("** free irq\n");
+    free_irq(BT_IRQ_WAKE_UP_HOST, NULL);
+
+    DBG("Enable UART_RTS\n");
+    gpio_set_value(UART_RTS, GPIO_LOW);
+    IOMUX_UART_RTS();
+}
+
+static DECLARE_DELAYED_WORK(wakeup_work, rfkill_do_wakeup);
+
 static int bcm4329_rfkill_suspend(struct platform_device *pdev, pm_message_t state)
-{   
-    DBG("%s\n",__FUNCTION__);          
+{
+    DBG("%s\n",__FUNCTION__);
+
+    cancel_delayed_work(&wakeup_work);
+
+#ifdef CONFIG_BT_AUTOSLEEP
+    bcm4325_sleep(1);
+#endif
+
+    DBG("Disable UART_RTS\n");
+       //To prevent uart to receive bt data when suspended
+       IOMUX_UART_RTS_GPIO();
+       gpio_request(UART_RTS, "uart_rts");
+       gpio_set_value(UART_RTS, GPIO_HIGH);
+
+    // enable bt wakeup host
+    DBG("Request irq for bt wakeup host\n");
+       if (0 == request_irq(BT_IRQ_WAKE_UP_HOST,
+                    bcm4329_wake_host_irq,
+                    IRQF_TRIGGER_FALLING,
+                    "bt_wake",
+                    NULL))
+        enable_irq_wake(BT_IRQ_WAKE_UP_HOST);
+    else
+               LOG("Failed to request BT_WAKE_UP_HOST irq\n");
+
+#ifdef CONFIG_RFKILL_RESET
+    extern void rfkill_set_block(struct rfkill *rfkill, bool blocked);
+    rfkill_set_block(gBtCtrl.bt_rfk, true);
+#endif
+
     return 0;
 }
 
 static int bcm4329_rfkill_resume(struct platform_device *pdev)
 {  
-    DBG("%s\n",__FUNCTION__);     
-    btWakeupHostLock();
-    resetBtHostSleepTimer();
+    DBG("%s\n",__FUNCTION__);
+
+    // ÏµÍ³Í˳ö¶þ¼¶Ë¯ÃߺóÐèÒªÀ­µÍRTS£¬´Ó¶ø²ÅÔÊÐíBT·¢Êý¾Ý¹ýÀ´
+    // µ«ÊÇÄ¿Ç°·¢ÏÖÔÚresumeº¯ÊýÖÐÖ±½ÓÀ­µÍRTS»áµ¼ÖÂBTÊý¾Ý¶ªÊ§
+    // ËùÒÔÑÓ³Ù1sºóÔÙÀ­µÍRTS
+    // ÏµÍ³Í˳ö¶þ¼¶Ë¯ÃßʱÊͷŵôBT_IRQ_WAKE_UP_HOST£¬ÔÚ˯ÃßʱºòÔÙ
+    // ´ÎÉêÇ룬Ŀǰ·¢ÏÖÖжϻص÷º¯Êý±Èresume¸üÍíÖ´ÐУ¬Èç¹ûresume
+    // Ê±Ö±½ÓfreeµôIRQ£¬»áµ¼ÖÂÖжϻص÷º¯Êý²»»á±»Ö´ÐУ¬
+    DBG("delay 1s\n");
+    schedule_delayed_work(&wakeup_work, HZ);
+
     return 0;
 }
 #else
@@ -126,67 +251,65 @@ static int bcm4329_rfkill_resume(struct platform_device *pdev)
 #define bcm4329_rfkill_resume  NULL
 #endif
 
-static irqreturn_t bcm4329_wake_host_irq(int irq, void *dev)
-{
-    btWakeupHostLock();
-    resetBtHostSleepTimer();
-       return IRQ_HANDLED;
-}
 #endif
 
-#ifdef CONFIG_BT_HCIBCM4325
-int bcm4325_sleep(int bSleep)
+void bcm4325_sleep(unsigned long bSleep)
 {
-    DBG("*************bt enter sleep***************\n");
-    if (bSleep)
-    gpio_set_value(BT_GPIO_WAKE_UP, GPIO_LOW);   //low represent bt device may enter sleep  
-    else
-    gpio_set_value(BT_GPIO_WAKE_UP, GPIO_HIGH);  //high represent bt device must be awake 
-    DBG("sleep=%d\n",bSleep);
-    return 0;
-}
+    DBG("*** bt sleep: %d ***\n", bSleep);
+#ifdef CONFIG_BT_AUTOSLEEP
+    del_timer(&bt_sleep_tl);// cmy: È·±£ÔÚ»½ÐÑBTʱ£¬²»»áÒò´¥·¢bt_sleep_tl¶øÂíÉÏ˯Ãß
+#endif
+
+    IOMUX_BT_GPIO_WAKE_UP();
+    gpio_set_value(BT_GPIO_WAKE_UP, bSleep?GPIO_LOW:GPIO_HIGH);
+
+#ifdef CONFIG_BT_AUTOSLEEP
+    if(!bSleep)
+        mod_timer(&bt_sleep_tl, jiffies + BT_AUTO_SLEEP_TIMEOUT*HZ);//ÔÙÖØÐÂÉèÖó¬Ê±Öµ¡£
 #endif
-  
+}
+
 static int bcm4329_set_block(void *data, bool blocked)
 {
-       DBG("%s---blocked :%d\n", __FUNCTION__, blocked);
-
-        IOMUX_BT_GPIO_POWER;
-        IOMUX_BT_GPIO_RESET;
-
-       if (false == blocked) {
-                       gpio_set_value(BT_GPIO_POWER, GPIO_HIGH);  /* bt power on */
-            
-              gpio_set_value(BT_GPIO_RESET, GPIO_LOW);
-              mdelay(20);
-               gpio_set_value(BT_GPIO_RESET, GPIO_HIGH);  /* bt reset deactive*/
-               mdelay(20);
+       DBG("set blocked :%d\n", blocked);
+
+    IOMUX_BT_GPIO_POWER;
+    IOMUX_BT_GPIO_RESET;
+
+       if (false == blocked) { 
+               gpio_set_value(BT_GPIO_POWER, GPIO_HIGH);  /* bt power on */
+               mdelay(20);
+
+        gpio_set_value(BT_GPIO_RESET, GPIO_LOW);
+        mdelay(20);
+               gpio_set_value(BT_GPIO_RESET, GPIO_HIGH);  /* bt reset deactive*/
+
+        mdelay(20);
+        bcm4325_sleep(0); // ensure bt is wakeup
         
-#if BT_WAKE_HOST_SUPPORT     
-            btWakeupHostLock();
-#endif         
-               pr_info("bt turn on power\n");
-       }
-       else {
-#if BT_WAKE_HOST_SUPPORT     
-            btWakeupHostUnlock();
+       pr_info("bt turn on power\n");
+       } else {
+#if WIFI_BT_POWER_TOGGLE
+               if (!rk29sdk_wifi_power_state) {
 #endif
-               if (!rk29sdk_wifi_power_state) {
-                       gpio_set_value(BT_GPIO_POWER, GPIO_LOW);  /* bt power off */
-                       mdelay(20);     
-                       pr_info("bt shut off power\n");
-               }else {
-                       pr_info("bt shouldn't shut off power, wifi is using it!\n");
-               }
-
-               gpio_set_value(BT_GPIO_RESET, GPIO_LOW);  /* bt reset active*/
-               mdelay(20);
-       }
-
-       rk29sdk_bt_power_state = !blocked;
-       return 0;
-}
+                       gpio_set_value(BT_GPIO_POWER, GPIO_LOW);  /* bt power off */
+               mdelay(20);     
+               pr_info("bt shut off power\n");
+#if WIFI_BT_POWER_TOGGLE
+               }else {
+                       pr_info("bt shouldn't shut off power, wifi is using it!\n");
+               }
+#endif
+
+        gpio_set_value(BT_GPIO_RESET, GPIO_LOW);  /* bt reset active*/
+        mdelay(20);
+       }
 
+#if WIFI_BT_POWER_TOGGLE
+       rk29sdk_bt_power_state = !blocked;
+#endif
+       return 0;
+}
 
 static const struct rfkill_ops bcm4329_rfk_ops = {
        .set_block = bcm4329_set_block,
@@ -197,7 +320,7 @@ static int __devinit bcm4329_rfkill_probe(struct platform_device *pdev)
        int rc = 0;
        bool default_state = true;
        
-       DBG("Enter::%s,line=%d\n",__FUNCTION__,__LINE__);
+       DBG("Enter %s\n",__FUNCTION__);
        
        /* default to bluetooth off */
        bcm4329_set_block(NULL, default_state); /* blocked -> bt off */
@@ -210,7 +333,7 @@ static int __devinit bcm4329_rfkill_probe(struct platform_device *pdev)
 
        if (!gBtCtrl.bt_rfk)
        {
-               printk("fail to rfkill_allocate************\n");
+               LOG("fail to rfkill_allocate\n");
                return -ENOMEM;
        }
        
@@ -219,20 +342,26 @@ static int __devinit bcm4329_rfkill_probe(struct platform_device *pdev)
        rc = rfkill_register(gBtCtrl.bt_rfk);
        if (rc)
        {
-               printk("failed to rfkill_register,rc=0x%x\n",rc);
+               LOG("failed to rfkill_register,rc=0x%x\n",rc);
                rfkill_destroy(gBtCtrl.bt_rfk);
        }
        
        gpio_request(BT_GPIO_POWER, NULL);
        gpio_request(BT_GPIO_RESET, NULL);
-#ifdef CONFIG_BT_HCIBCM4325
        gpio_request(BT_GPIO_WAKE_UP, NULL);
+    
+#ifdef CONFIG_BT_AUTOSLEEP
+    init_timer(&bt_sleep_tl);
+    bt_sleep_tl.expires = 0;
+    bt_sleep_tl.function = bcm4325_sleep;
+    bt_sleep_tl.data = 1;
+    add_timer(&bt_sleep_tl);
 #endif
 
 #if BT_WAKE_HOST_SUPPORT
     init_timer(&(gBtCtrl.tl));
-    gBtCtrl.tl.expires = jiffies + BT_WAKE_LOCK_TIMEOUT*HZ;        
-    gBtCtrl.tl.function = timer_hostSleep;        
+    gBtCtrl.tl.expires = 0;
+    gBtCtrl.tl.function = timer_hostSleep;
     add_timer(&(gBtCtrl.tl));
     gBtCtrl.b_HostWake = false;
     
@@ -240,22 +369,15 @@ static int __devinit bcm4329_rfkill_probe(struct platform_device *pdev)
        
        rc = gpio_request(BT_GPIO_WAKE_UP_HOST, "bt_wake");
        if (rc) {
-               printk("%s:failed to request RAHO_BT_WAKE_UP_HOST\n",__FUNCTION__);
+               LOG("Failed to request BT_WAKE_UP_HOST\n");
        }
        
        IOMUX_BT_GPIO_WAKE_UP_HOST();
        gpio_pull_updown(BT_GPIO_WAKE_UP_HOST,GPIOPullUp);
-       rc = request_irq(gpio_to_irq(BT_GPIO_WAKE_UP_HOST),bcm4329_wake_host_irq,IRQF_TRIGGER_FALLING,NULL,NULL);
-       if(rc)
-       {
-               printk("%s:failed to request RAHO_BT_WAKE_UP_HOST irq\n",__FUNCTION__);
-               gpio_free(BT_GPIO_WAKE_UP_HOST);
-       }
-       enable_irq_wake(gpio_to_irq(BT_GPIO_WAKE_UP_HOST)); // so RAHO_BT_WAKE_UP_HOST can wake up system
-
-       printk(KERN_INFO "bcm4329 module has been initialized,rc=0x%x\n",rc);
  #endif
  
+    LOG("bcm4329 module has been initialized,rc=0x%x\n",rc);
        return rc;
 }
 
@@ -265,14 +387,18 @@ static int __devexit bcm4329_rfkill_remove(struct platform_device *pdev)
        if (gBtCtrl.bt_rfk)
                rfkill_unregister(gBtCtrl.bt_rfk);
        gBtCtrl.bt_rfk = NULL;
-#if BT_WAKE_HOST_SUPPORT       
+#if BT_WAKE_HOST_SUPPORT
     del_timer(&(gBtCtrl.tl));//ɾµô¶¨Ê±Æ÷
     btWakeupHostUnlock();
     wake_lock_destroy(&(gBtCtrl.bt_wakelock));
-#endif    
+#endif
+#ifdef CONFIG_BT_AUTOSLEEP
+    del_timer(&bt_sleep_tl);
+#endif
+
        platform_set_drvdata(pdev, NULL);
 
-       DBG("Enter::%s,line=%d\n",__FUNCTION__,__LINE__);
+       DBG("Enter %s\n",__FUNCTION__);
        return 0;
 }
 
@@ -295,9 +421,9 @@ static struct platform_driver bcm4329_rfkill_driver = {
 static int __init bcm4329_mod_init(void)
 {
        int ret;
-       DBG("Enter::%s,line=%d\n",__FUNCTION__,__LINE__);
+       DBG("Enter %s\n",__FUNCTION__);
        ret = platform_driver_register(&bcm4329_rfkill_driver);
-       printk("ret=0x%x\n", ret);
+       LOG("ret=0x%x\n", ret);
        return ret;
 }
 
@@ -308,7 +434,7 @@ static void __exit bcm4329_mod_exit(void)
 
 module_init(bcm4329_mod_init);
 module_exit(bcm4329_mod_exit);
-MODULE_DESCRIPTION("bcm4330 Bluetooth driver");
+MODULE_DESCRIPTION("bcm4329 Bluetooth driver");
 MODULE_AUTHOR("roger_chen cz@rock-chips.com, cmy@rock-chips.com");
 MODULE_LICENSE("GPL");