From 665f5cd74aa50217470a3077bff186a973e35727 Mon Sep 17 00:00:00 2001 From: hwg Date: Thu, 25 Apr 2013 09:12:38 +0800 Subject: [PATCH] mt6622 bluetooth: support wake up host --- drivers/mtk_wcn_bt/bt_eirq_handler.c | 16 +++++++++-- drivers/mtk_wcn_bt/bt_hwctl.h | 5 +++- drivers/mtk_wcn_bt/bt_hwctl_dev.c | 12 ++++---- drivers/mtk_wcn_bt/bt_plat_smdk.c | 43 ++++++++++++++++++++++++++-- include/linux/rfkill-rk.h | 1 + 5 files changed, 65 insertions(+), 12 deletions(-) diff --git a/drivers/mtk_wcn_bt/bt_eirq_handler.c b/drivers/mtk_wcn_bt/bt_eirq_handler.c index 7e628304813a..4beca42a009e 100755 --- a/drivers/mtk_wcn_bt/bt_eirq_handler.c +++ b/drivers/mtk_wcn_bt/bt_eirq_handler.c @@ -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 +} diff --git a/drivers/mtk_wcn_bt/bt_hwctl.h b/drivers/mtk_wcn_bt/bt_hwctl.h index 3149033007c4..e1fa8143280a 100755 --- a/drivers/mtk_wcn_bt/bt_hwctl.h +++ b/drivers/mtk_wcn_bt/bt_hwctl.h @@ -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 diff --git a/drivers/mtk_wcn_bt/bt_hwctl_dev.c b/drivers/mtk_wcn_bt/bt_hwctl_dev.c index d073bbc28a72..8e3c9f2dfd70 100755 --- a/drivers/mtk_wcn_bt/bt_hwctl_dev.c +++ b/drivers/mtk_wcn_bt/bt_hwctl_dev.c @@ -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(); diff --git a/drivers/mtk_wcn_bt/bt_plat_smdk.c b/drivers/mtk_wcn_bt/bt_plat_smdk.c index 4948493ba6e7..9df7ccb4d9f6 100755 --- a/drivers/mtk_wcn_bt/bt_plat_smdk.c +++ b/drivers/mtk_wcn_bt/bt_plat_smdk.c @@ -41,6 +41,7 @@ #include #include #include +#include //#include #include "bt_hwctl.h" @@ -52,17 +53,25 @@ static int irq_num = -1; +#ifdef CONFIG_ARCH_RK29 + #define rk_mux_api_set(name,mode) rk29_mux_api_set(name,mode) +#elif defined (CONFIG_ARCH_RK30) + #define rk_mux_api_set(name,mode) rk30_mux_api_set(name,mode) +#else + #define rk_mux_api_set(name,mode) rk30_mux_api_set(name,mode) +#endif + /**************************************************************************** * I R Q F U N C T I O N S * *****************************************************************************/ static int mt_bt_request_irq(void) { int iRet; - int trigger = IRQF_TRIGGER_HIGH; + int trigger = IRQF_TRIGGER_RISING; struct mt6622_platform_data *pdata = (struct mt6622_platform_data *)mt_bt_get_platform_data(); if(pdata->irq_gpio.enable == GPIO_LOW) - trigger = IRQF_TRIGGER_LOW; + trigger = IRQF_TRIGGER_FALLING; iRet = request_irq(irq_num, mt_bt_eirq_handler, trigger, "BT_INT_B", NULL); @@ -86,9 +95,28 @@ static void mt_bt_free_irq(void) } } +int mt6622_suspend(struct platform_device *pdev, pm_message_t state) +{ + if(irq_num != -1) { + printk(KERN_INFO MODULE_TAG "mt6622_suspend\n"); + enable_irq_wake(irq_num); + } + return 0; +} + +int mt6622_resume(struct platform_device *pdev) +{ + if(irq_num != -1) { + printk(KERN_INFO MODULE_TAG "mt6622_resume\n"); + disable_irq_wake(irq_num); + } + return 0; +} + void mt_bt_enable_irq(void) { if(irq_num != -1) { + //printk("mt_bt_enable_irq\n"); enable_irq(irq_num); } } @@ -97,6 +125,7 @@ EXPORT_SYMBOL(mt_bt_enable_irq); void mt_bt_disable_irq(void) { if(irq_num != -1) { + //printk("mt_bt_disable_irq\n"); disable_irq_nosync(irq_num); } } @@ -133,7 +162,7 @@ int mt_bt_power_init(void) if(pdata->reset_gpio.io != INVALID_GPIO) gpio_direction_output(pdata->reset_gpio.io, 1); msleep(1000); - + //pdata->power_gpio.io = INVALID_GPIO; pdata->reset_gpio.io = INVALID_GPIO; } @@ -193,6 +222,14 @@ int mt_bt_power_on(void) if(pdata->reset_gpio.io != INVALID_GPIO) gpio_direction_output(pdata->reset_gpio.io, 1); msleep(1000); + + if(gpio_is_valid(pdata->rts_gpio.io)) { + printk(KERN_INFO MODULE_TAG "mt_bt_power_on rts iomux\n"); + rk_mux_api_set(pdata->rts_gpio.iomux.name, pdata->rts_gpio.iomux.fgpio); + gpio_direction_output(pdata->rts_gpio.io, 0); + msleep(100); + rk_mux_api_set(pdata->rts_gpio.iomux.name, pdata->rts_gpio.iomux.fmux); + } error = mt_bt_request_irq(); if (error){ diff --git a/include/linux/rfkill-rk.h b/include/linux/rfkill-rk.h index 4ff6ab9d4623..8c892b1ad201 100755 --- a/include/linux/rfkill-rk.h +++ b/include/linux/rfkill-rk.h @@ -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 */ -- 2.34.1