From de451c76c86dfc2f5e39ac6e1b762270b0292eb1 Mon Sep 17 00:00:00 2001 From: wdc Date: Fri, 25 May 2012 18:13:16 +0800 Subject: [PATCH] Loquate: Add bt sleep and wakeup host function --- arch/arm/configs/rk30_phone_loquat_defconfig | 1 + .../board-rk30-phone-loquat-rfkill.c | 330 ++++++++++++------ 2 files changed, 229 insertions(+), 102 deletions(-) diff --git a/arch/arm/configs/rk30_phone_loquat_defconfig b/arch/arm/configs/rk30_phone_loquat_defconfig index cbeec3c1e802..ee58a15b94a4 100755 --- a/arch/arm/configs/rk30_phone_loquat_defconfig +++ b/arch/arm/configs/rk30_phone_loquat_defconfig @@ -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 diff --git a/arch/arm/mach-rk30/board-rk30-phone-loquat-rfkill.c b/arch/arm/mach-rk30/board-rk30-phone-loquat-rfkill.c index 0fd336984768..d2e353aca752 100755 --- a/arch/arm/mach-rk30/board-rk30-phone-loquat-rfkill.c +++ b/arch/arm/mach-rk30/board-rk30-phone-loquat-rfkill.c @@ -24,44 +24,105 @@ #include #include #include +#include #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"); -- 2.34.1