2 * Copyright (C) 2010 ROCKCHIP, Inc.
3 * Author: roger_chen <cz@rock-chips.com>
5 * This program is the bluetooth device bcm4329's driver,
9 #include <linux/kernel.h>
10 #include <linux/platform_device.h>
11 #include <linux/module.h>
12 #include <linux/device.h>
13 #include <linux/rfkill.h>
14 #include <linux/delay.h>
15 #include <linux/i2c.h>
16 #include <linux/init.h>
17 #include <linux/slab.h>
18 #include <linux/interrupt.h>
19 #include <linux/wakelock.h>
21 #include <asm/uaccess.h>
22 #include <mach/gpio.h>
24 #include <mach/iomux.h>
25 #include <linux/wakelock.h>
26 #include <linux/timer.h>
27 #include <mach/board.h>
30 #define DBG(x...) printk(KERN_INFO "[BT_RFKILL]: "x)
35 #define LOG(x...) printk(KERN_INFO "[BT_RFKILL]: "x)
38 #define WIFI_BT_POWER_TOGGLE 1
40 #define WIFI_BT_POWER_TOGGLE 0
43 #define BT_WAKE_LOCK_TIMEOUT 10 //s
45 #define BT_AUTO_SLEEP_TIMEOUT 3
48 * IO Configuration for RK29
50 #ifdef CONFIG_ARCH_RK29
52 #define BT_WAKE_HOST_SUPPORT 0
54 /* IO configuration */
56 #define BT_GPIO_POWER RK29_PIN5_PD6
57 #define IOMUX_BT_GPIO_POWER() rk29_mux_api_set(GPIO5D6_SDMMC1PWREN_NAME, GPIO5H_GPIO5D6);
60 #define BT_GPIO_RESET RK29_PIN6_PC4
61 #define IOMUX_BT_GPIO_RESET()
64 #define BT_GPIO_WAKE_UP RK29_PIN6_PC5
65 #define IOMUX_BT_GPIO_WAKE_UP()
68 #define BT_GPIO_WAKE_UP_HOST
69 #define IOMUX_BT_GPIO_WAKE_UP_HOST()
71 //bt cts paired to uart rts
72 #define UART_RTS RK29_PIN2_PA7
73 #define IOMUX_UART_RTS_GPIO() rk29_mux_api_set(GPIO2A7_UART2RTSN_NAME, GPIO2L_GPIO2A7)
74 #define IOMUX_UART_RTS() rk29_mux_api_set(GPIO2A7_UART2RTSN_NAME, GPIO2L_UART2_RTS_N)
77 * IO Configuration for RK30
79 #elif defined (CONFIG_ARCH_RK30)
81 #define BT_WAKE_HOST_SUPPORT 1
83 /* IO configuration */
85 #define BT_GPIO_POWER RK30_PIN3_PC7
86 #define IOMUX_BT_GPIO_POWER() rk30_mux_api_set(GPIO3C7_SDMMC1WRITEPRT_NAME, GPIO3C_GPIO3C7);
89 #define BT_GPIO_RESET RK30_PIN3_PD1
90 #define IOMUX_BT_GPIO_RESET() rk30_mux_api_set(GPIO3D1_SDMMC1BACKENDPWR_NAME, GPIO3D_GPIO3D1);
93 #define BT_GPIO_WAKE_UP RK30_PIN3_PC6
94 #define IOMUX_BT_GPIO_WAKE_UP() rk30_mux_api_set(GPIO3C6_SDMMC1DETECTN_NAME, GPIO3C_GPIO3C6);
97 #define BT_GPIO_WAKE_UP_HOST RK30_PIN6_PA7
98 #define BT_IRQ_WAKE_UP_HOST gpio_to_irq(BT_GPIO_WAKE_UP_HOST)
99 #define IOMUX_BT_GPIO_WAKE_UP_HOST()
101 //bt cts paired to uart rts
102 #define UART_RTS RK30_PIN1_PA3
103 #define IOMUX_UART_RTS_GPIO() rk30_mux_api_set(GPIO1A3_UART0RTSN_NAME, GPIO1A_GPIO1A3)
104 #define IOMUX_UART_RTS() rk30_mux_api_set(GPIO1A3_UART0RTSN_NAME, GPIO1A_UART0_RTS_N)
110 struct rfkill *bt_rfk;
111 #if BT_WAKE_HOST_SUPPORT
112 struct timer_list tl;
114 struct wake_lock bt_wakelock;
118 static const char bt_name[] =
119 #if defined(CONFIG_RKWIFI)
120 #if defined(CONFIG_RKWIFI_26M)
125 #elif defined(CONFIG_BCM4329)
127 #elif defined(CONFIG_MV8787)
134 #if WIFI_BT_POWER_TOGGLE
135 extern int rk29sdk_bt_power_state;
136 extern int rk29sdk_wifi_power_state;
139 struct bt_ctrl gBtCtrl;
140 struct timer_list bt_sleep_tl;
143 #if BT_WAKE_HOST_SUPPORT
144 void resetBtHostSleepTimer(void)
146 mod_timer(&(gBtCtrl.tl),jiffies + BT_WAKE_LOCK_TIMEOUT*HZ);//ÔÙÖØÐÂÉèÖó¬Ê±Öµ¡£
149 void btWakeupHostLock(void)
151 if(gBtCtrl.b_HostWake == false){
153 wake_lock(&(gBtCtrl.bt_wakelock));
154 gBtCtrl.b_HostWake = true;
158 void btWakeupHostUnlock(void)
160 if(gBtCtrl.b_HostWake == true){
161 DBG("** UnLock **\n");
162 wake_unlock(&(gBtCtrl.bt_wakelock)); //ÈÃϵͳ˯Ãß
163 gBtCtrl.b_HostWake = false;
167 static void timer_hostSleep(unsigned long arg)
169 DBG("b_HostWake=%d\n", gBtCtrl.b_HostWake);
170 btWakeupHostUnlock();
173 void bcm4325_sleep(unsigned long bSleep);
176 static irqreturn_t bcm4329_wake_host_irq(int irq, void *dev)
178 DBG("%s\n",__FUNCTION__);
181 resetBtHostSleepTimer();
185 static void rfkill_do_wakeup(struct work_struct *work)
187 // disable bt wakeup host
188 DBG("** free irq\n");
189 free_irq(BT_IRQ_WAKE_UP_HOST, NULL);
191 DBG("Enable UART_RTS\n");
192 gpio_set_value(UART_RTS, GPIO_LOW);
196 static DECLARE_DELAYED_WORK(wakeup_work, rfkill_do_wakeup);
198 static int bcm4329_rfkill_suspend(struct platform_device *pdev, pm_message_t state)
200 DBG("%s\n",__FUNCTION__);
202 cancel_delayed_work(&wakeup_work);
204 #ifdef CONFIG_BT_AUTOSLEEP
208 DBG("Disable UART_RTS\n");
209 //To prevent uart to receive bt data when suspended
210 IOMUX_UART_RTS_GPIO();
211 gpio_request(UART_RTS, "uart_rts");
212 gpio_set_value(UART_RTS, GPIO_HIGH);
214 // enable bt wakeup host
215 DBG("Request irq for bt wakeup host\n");
216 if (0 == request_irq(BT_IRQ_WAKE_UP_HOST,
217 bcm4329_wake_host_irq,
218 IRQF_TRIGGER_FALLING,
221 enable_irq_wake(BT_IRQ_WAKE_UP_HOST);
223 LOG("Failed to request BT_WAKE_UP_HOST irq\n");
225 #ifdef CONFIG_RFKILL_RESET
226 extern void rfkill_set_block(struct rfkill *rfkill, bool blocked);
227 rfkill_set_block(gBtCtrl.bt_rfk, true);
233 static int bcm4329_rfkill_resume(struct platform_device *pdev)
235 DBG("%s\n",__FUNCTION__);
237 // ϵͳÍ˳ö¶þ¼¶Ë¯ÃߺóÐèÒªÀµÍRTS£¬´Ó¶ø²ÅÔÊÐíBT·¢Êý¾Ý¹ýÀ´
238 // µ«ÊÇÄ¿Ç°·¢ÏÖÔÚresumeº¯ÊýÖÐÖ±½ÓÀµÍRTS»áµ¼ÖÂBTÊý¾Ý¶ªÊ§
239 // ËùÒÔÑÓ³Ù1sºóÔÙÀµÍRTS
240 // ϵͳÍ˳ö¶þ¼¶Ë¯ÃßʱÊͷŵôBT_IRQ_WAKE_UP_HOST£¬ÔÚ˯ÃßʱºòÔÙ
241 // ´ÎÉêÇ룬Ŀǰ·¢ÏÖÖжϻص÷º¯Êý±Èresume¸üÍíÖ´ÐУ¬Èç¹ûresume
242 // ʱֱ½ÓfreeµôIRQ£¬»áµ¼ÖÂÖжϻص÷º¯Êý²»»á±»Ö´ÐУ¬
244 schedule_delayed_work(&wakeup_work, HZ);
249 #define bcm4329_rfkill_suspend NULL
250 #define bcm4329_rfkill_resume NULL
255 void bcm4325_sleep(unsigned long bSleep)
257 DBG("*** bt sleep: %d ***\n", bSleep);
258 #ifdef CONFIG_BT_AUTOSLEEP
259 del_timer(&bt_sleep_tl);// cmy: È·±£ÔÚ»½ÐÑBTʱ£¬²»»áÒò´¥·¢bt_sleep_tl¶øÂíÉÏ˯Ãß
262 IOMUX_BT_GPIO_WAKE_UP();
263 gpio_set_value(BT_GPIO_WAKE_UP, bSleep?GPIO_LOW:GPIO_HIGH);
265 #ifdef CONFIG_BT_AUTOSLEEP
267 mod_timer(&bt_sleep_tl, jiffies + BT_AUTO_SLEEP_TIMEOUT*HZ);//ÔÙÖØÐÂÉèÖó¬Ê±Öµ¡£
271 static int bcm4329_set_block(void *data, bool blocked)
273 DBG("set blocked :%d\n", blocked);
275 IOMUX_BT_GPIO_POWER();
276 IOMUX_BT_GPIO_RESET();
278 if (false == blocked) {
279 gpio_set_value(BT_GPIO_POWER, GPIO_HIGH); /* bt power on */
282 gpio_set_value(BT_GPIO_RESET, GPIO_LOW);
284 gpio_set_value(BT_GPIO_RESET, GPIO_HIGH); /* bt reset deactive*/
287 bcm4325_sleep(0); // ensure bt is wakeup
289 pr_info("bt turn on power\n");
291 #if WIFI_BT_POWER_TOGGLE
292 if (!rk29sdk_wifi_power_state) {
294 gpio_set_value(BT_GPIO_POWER, GPIO_LOW); /* bt power off */
296 pr_info("bt shut off power\n");
297 #if WIFI_BT_POWER_TOGGLE
299 pr_info("bt shouldn't shut off power, wifi is using it!\n");
303 gpio_set_value(BT_GPIO_RESET, GPIO_LOW); /* bt reset active*/
307 #if WIFI_BT_POWER_TOGGLE
308 rk29sdk_bt_power_state = !blocked;
313 static const struct rfkill_ops bcm4329_rfk_ops = {
314 .set_block = bcm4329_set_block,
317 static int __devinit bcm4329_rfkill_probe(struct platform_device *pdev)
320 bool default_state = true;
322 DBG("Enter %s\n",__FUNCTION__);
324 /* default to bluetooth off */
325 bcm4329_set_block(NULL, default_state); /* blocked -> bt off */
327 gBtCtrl.bt_rfk = rfkill_alloc(bt_name,
329 RFKILL_TYPE_BLUETOOTH,
335 LOG("fail to rfkill_allocate\n");
339 rfkill_set_states(gBtCtrl.bt_rfk, default_state, false);
341 rc = rfkill_register(gBtCtrl.bt_rfk);
344 LOG("failed to rfkill_register,rc=0x%x\n",rc);
345 rfkill_destroy(gBtCtrl.bt_rfk);
348 gpio_request(BT_GPIO_POWER, NULL);
349 gpio_request(BT_GPIO_RESET, NULL);
350 gpio_request(BT_GPIO_WAKE_UP, NULL);
352 #ifdef CONFIG_BT_AUTOSLEEP
353 init_timer(&bt_sleep_tl);
354 bt_sleep_tl.expires = 0;
355 bt_sleep_tl.function = bcm4325_sleep;
356 bt_sleep_tl.data = 1;
357 add_timer(&bt_sleep_tl);
360 #if BT_WAKE_HOST_SUPPORT
361 init_timer(&(gBtCtrl.tl));
362 gBtCtrl.tl.expires = 0;
363 gBtCtrl.tl.function = timer_hostSleep;
364 add_timer(&(gBtCtrl.tl));
365 gBtCtrl.b_HostWake = false;
367 wake_lock_init(&(gBtCtrl.bt_wakelock), WAKE_LOCK_SUSPEND, "bt_wake");
369 rc = gpio_request(BT_GPIO_WAKE_UP_HOST, "bt_wake");
371 LOG("Failed to request BT_WAKE_UP_HOST\n");
374 IOMUX_BT_GPIO_WAKE_UP_HOST();
375 gpio_pull_updown(BT_GPIO_WAKE_UP_HOST,GPIOPullUp);
378 LOG("bcm4329 module has been initialized,rc=0x%x\n",rc);
384 static int __devexit bcm4329_rfkill_remove(struct platform_device *pdev)
387 rfkill_unregister(gBtCtrl.bt_rfk);
388 gBtCtrl.bt_rfk = NULL;
389 #if BT_WAKE_HOST_SUPPORT
390 del_timer(&(gBtCtrl.tl));//ɾµô¶¨Ê±Æ÷
391 btWakeupHostUnlock();
392 wake_lock_destroy(&(gBtCtrl.bt_wakelock));
394 #ifdef CONFIG_BT_AUTOSLEEP
395 del_timer(&bt_sleep_tl);
398 platform_set_drvdata(pdev, NULL);
400 DBG("Enter %s\n",__FUNCTION__);
404 static struct platform_driver bcm4329_rfkill_driver = {
405 .probe = bcm4329_rfkill_probe,
406 .remove = __devexit_p(bcm4329_rfkill_remove),
408 .name = "rk29sdk_rfkill",
409 .owner = THIS_MODULE,
411 #if BT_WAKE_HOST_SUPPORT
412 .suspend = bcm4329_rfkill_suspend,
413 .resume = bcm4329_rfkill_resume,
418 * Module initialization
420 static int __init bcm4329_mod_init(void)
423 DBG("Enter %s\n",__FUNCTION__);
424 ret = platform_driver_register(&bcm4329_rfkill_driver);
425 LOG("ret=0x%x\n", ret);
429 static void __exit bcm4329_mod_exit(void)
431 platform_driver_unregister(&bcm4329_rfkill_driver);
434 module_init(bcm4329_mod_init);
435 module_exit(bcm4329_mod_exit);
436 MODULE_DESCRIPTION("bcm4329 Bluetooth driver");
437 MODULE_AUTHOR("roger_chen cz@rock-chips.com, cmy@rock-chips.com");
438 MODULE_LICENSE("GPL");