2 * Copyright (C) 2010 ROCKCHIP, Inc.
3 * Author: roger_chen <cz@rock-chips.com>
5 * This program is the bluetooth device bcm4330'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_PIN4_PD5
86 #define IOMUX_BT_GPIO_POWER rk30_mux_api_set(GPIO4D5_SMCDATA13_TRACEDATA13_NAME, GPIO4D_GPIO4D5)
89 #define BT_GPIO_RESET RK30_PIN3_PD1
90 #define IOMUX_BT_GPIO_RESET rk30_mux_api_set(GPIO3D1_SDMMC1BACKENDPWR_NAME, GPIO3D_GPIO3D1)
94 #define BT_GPIO_WAKE_UP RK30_PIN3_PC6
95 #define IOMUX_BT_GPIO_WAKE_UP() rk29_mux_api_set(GPIO3C6_SDMMC1DETECTN_NAME, GPIO3C_GPIO3C6);
98 #define BT_GPIO_WAKE_UP_HOST RK30_PIN3_PD2
99 #define IOMUX_BT_GPIO_WAKE_UP_HOST() rk29_mux_api_set(GPIO3D2_SDMMC1INTN_NAME, GPIO3D_GPIO3D2)
100 #define BT_IRQ_WAKE_UP_HOST gpio_to_irq(BT_GPIO_WAKE_UP_HOST)
102 //bt cts paired to uart rts
103 #define UART_RTS RK30_PIN1_PA3
104 #define IOMUX_UART_RTS_GPIO() rk29_mux_api_set(GPIO1A3_UART0RTSN_NAME, GPIO1A_GPIO1A3)
105 #define IOMUX_UART_RTS() rk29_mux_api_set(GPIO1A3_UART0RTSN_NAME, GPIO1A_UART0_RTS_N)
111 struct rfkill *bt_rfk;
112 #if BT_WAKE_HOST_SUPPORT
113 struct timer_list tl;
115 struct wake_lock bt_wakelock;
119 static const char bt_name[] =
120 #if defined(CONFIG_RKWIFI)
121 #if defined(CONFIG_RKWIFI_26M)
126 #elif defined(CONFIG_BCM4329)
128 #elif defined(CONFIG_MV8787)
135 #if WIFI_BT_POWER_TOGGLE
136 extern int rk29sdk_bt_power_state;
137 extern int rk29sdk_wifi_power_state;
140 struct bt_ctrl gBtCtrl;
141 struct timer_list bt_sleep_tl;
144 #if BT_WAKE_HOST_SUPPORT
145 void resetBtHostSleepTimer(void)
147 mod_timer(&(gBtCtrl.tl),jiffies + BT_WAKE_LOCK_TIMEOUT*HZ);//ÔÙÖØÐÂÉèÖó¬Ê±Öµ¡£
150 void btWakeupHostLock(void)
152 if(gBtCtrl.b_HostWake == false){
154 wake_lock(&(gBtCtrl.bt_wakelock));
155 gBtCtrl.b_HostWake = true;
159 void btWakeupHostUnlock(void)
161 if(gBtCtrl.b_HostWake == true){
162 DBG("** UnLock **\n");
163 wake_unlock(&(gBtCtrl.bt_wakelock)); //ÈÃϵͳ˯Ãß
164 gBtCtrl.b_HostWake = false;
168 static void timer_hostSleep(unsigned long arg)
170 DBG("b_HostWake=%d\n", gBtCtrl.b_HostWake);
171 btWakeupHostUnlock();
174 void bcm4325_sleep(unsigned long bSleep);
177 static irqreturn_t bcm4329_wake_host_irq(int irq, void *dev)
179 DBG("%s\n",__FUNCTION__);
182 resetBtHostSleepTimer();
186 static void rfkill_do_wakeup(struct work_struct *work)
188 // disable bt wakeup host
189 DBG("** free irq\n");
190 free_irq(BT_IRQ_WAKE_UP_HOST, NULL);
192 DBG("Enable UART_RTS\n");
193 gpio_set_value(UART_RTS, GPIO_LOW);
197 static DECLARE_DELAYED_WORK(wakeup_work, rfkill_do_wakeup);
199 static int bcm4329_rfkill_suspend(struct platform_device *pdev, pm_message_t state)
201 DBG("%s\n",__FUNCTION__);
203 cancel_delayed_work(&wakeup_work);
205 #ifdef CONFIG_BT_AUTOSLEEP
209 DBG("Disable UART_RTS\n");
210 //To prevent uart to receive bt data when suspended
211 IOMUX_UART_RTS_GPIO();
212 gpio_request(UART_RTS, "uart_rts");
213 gpio_set_value(UART_RTS, GPIO_HIGH);
215 // enable bt wakeup host
216 DBG("Request irq for bt wakeup host\n");
217 if (0 == request_irq(BT_IRQ_WAKE_UP_HOST,
218 bcm4329_wake_host_irq,
219 IRQF_TRIGGER_FALLING,
222 enable_irq_wake(BT_IRQ_WAKE_UP_HOST);
224 LOG("Failed to request BT_WAKE_UP_HOST irq\n");
226 #ifdef CONFIG_RFKILL_RESET
227 extern void rfkill_set_block(struct rfkill *rfkill, bool blocked);
228 rfkill_set_block(gBtCtrl.bt_rfk, true);
234 static int bcm4329_rfkill_resume(struct platform_device *pdev)
236 DBG("%s\n",__FUNCTION__);
238 // ϵͳÍ˳ö¶þ¼¶Ë¯ÃߺóÐèÒªÀµÍRTS£¬´Ó¶ø²ÅÔÊÐíBT·¢Êý¾Ý¹ýÀ´
239 // µ«ÊÇÄ¿Ç°·¢ÏÖÔÚresumeº¯ÊýÖÐÖ±½ÓÀµÍRTS»áµ¼ÖÂBTÊý¾Ý¶ªÊ§
240 // ËùÒÔÑÓ³Ù1sºóÔÙÀµÍRTS
241 // ϵͳÍ˳ö¶þ¼¶Ë¯ÃßʱÊͷŵôBT_IRQ_WAKE_UP_HOST£¬ÔÚ˯ÃßʱºòÔÙ
242 // ´ÎÉêÇ룬Ŀǰ·¢ÏÖÖжϻص÷º¯Êý±Èresume¸üÍíÖ´ÐУ¬Èç¹ûresume
243 // ʱֱ½ÓfreeµôIRQ£¬»áµ¼ÖÂÖжϻص÷º¯Êý²»»á±»Ö´ÐУ¬
245 schedule_delayed_work(&wakeup_work, HZ);
250 #define bcm4329_rfkill_suspend NULL
251 #define bcm4329_rfkill_resume NULL
256 void bcm4325_sleep(unsigned long bSleep)
258 DBG("*** bt sleep: %d ***\n", bSleep);
259 #ifdef CONFIG_BT_AUTOSLEEP
260 del_timer(&bt_sleep_tl);// cmy: È·±£ÔÚ»½ÐÑBTʱ£¬²»»áÒò´¥·¢bt_sleep_tl¶øÂíÉÏ˯Ãß
263 IOMUX_BT_GPIO_WAKE_UP();
264 gpio_set_value(BT_GPIO_WAKE_UP, bSleep?GPIO_LOW:GPIO_HIGH);
266 #ifdef CONFIG_BT_AUTOSLEEP
268 mod_timer(&bt_sleep_tl, jiffies + BT_AUTO_SLEEP_TIMEOUT*HZ);//ÔÙÖØÐÂÉèÖó¬Ê±Öµ¡£
272 static int bcm4329_set_block(void *data, bool blocked)
274 DBG("set blocked :%d\n", blocked);
279 if (false == blocked) {
280 gpio_set_value(BT_GPIO_POWER, GPIO_HIGH); /* bt power on */
283 gpio_set_value(BT_GPIO_RESET, GPIO_LOW);
285 gpio_set_value(BT_GPIO_RESET, GPIO_HIGH); /* bt reset deactive*/
288 bcm4325_sleep(0); // ensure bt is wakeup
290 pr_info("bt turn on power\n");
292 #if WIFI_BT_POWER_TOGGLE
293 if (!rk29sdk_wifi_power_state) {
295 gpio_set_value(BT_GPIO_POWER, GPIO_LOW); /* bt power off */
297 pr_info("bt shut off power\n");
298 #if WIFI_BT_POWER_TOGGLE
300 pr_info("bt shouldn't shut off power, wifi is using it!\n");
304 gpio_set_value(BT_GPIO_RESET, GPIO_LOW); /* bt reset active*/
308 #if WIFI_BT_POWER_TOGGLE
309 rk29sdk_bt_power_state = !blocked;
314 static const struct rfkill_ops bcm4329_rfk_ops = {
315 .set_block = bcm4329_set_block,
318 static int __devinit bcm4329_rfkill_probe(struct platform_device *pdev)
321 bool default_state = true;
323 DBG("Enter %s\n",__FUNCTION__);
325 /* default to bluetooth off */
326 bcm4329_set_block(NULL, default_state); /* blocked -> bt off */
328 gBtCtrl.bt_rfk = rfkill_alloc(bt_name,
330 RFKILL_TYPE_BLUETOOTH,
336 LOG("fail to rfkill_allocate\n");
340 rfkill_set_states(gBtCtrl.bt_rfk, default_state, false);
342 rc = rfkill_register(gBtCtrl.bt_rfk);
345 LOG("failed to rfkill_register,rc=0x%x\n",rc);
346 rfkill_destroy(gBtCtrl.bt_rfk);
349 gpio_request(BT_GPIO_POWER, NULL);
350 gpio_request(BT_GPIO_RESET, NULL);
351 gpio_request(BT_GPIO_WAKE_UP, NULL);
353 #ifdef CONFIG_BT_AUTOSLEEP
354 init_timer(&bt_sleep_tl);
355 bt_sleep_tl.expires = 0;
356 bt_sleep_tl.function = bcm4325_sleep;
357 bt_sleep_tl.data = 1;
358 add_timer(&bt_sleep_tl);
361 #if BT_WAKE_HOST_SUPPORT
362 init_timer(&(gBtCtrl.tl));
363 gBtCtrl.tl.expires = 0;
364 gBtCtrl.tl.function = timer_hostSleep;
365 add_timer(&(gBtCtrl.tl));
366 gBtCtrl.b_HostWake = false;
368 wake_lock_init(&(gBtCtrl.bt_wakelock), WAKE_LOCK_SUSPEND, "bt_wake");
370 rc = gpio_request(BT_GPIO_WAKE_UP_HOST, "bt_wake");
372 LOG("Failed to request BT_WAKE_UP_HOST\n");
375 IOMUX_BT_GPIO_WAKE_UP_HOST();
376 gpio_pull_updown(BT_GPIO_WAKE_UP_HOST,GPIOPullUp);
379 LOG("bcm4329 module has been initialized,rc=0x%x\n",rc);
385 static int __devexit bcm4329_rfkill_remove(struct platform_device *pdev)
388 rfkill_unregister(gBtCtrl.bt_rfk);
389 gBtCtrl.bt_rfk = NULL;
390 #if BT_WAKE_HOST_SUPPORT
391 del_timer(&(gBtCtrl.tl));//ɾµô¶¨Ê±Æ÷
392 btWakeupHostUnlock();
393 wake_lock_destroy(&(gBtCtrl.bt_wakelock));
395 #ifdef CONFIG_BT_AUTOSLEEP
396 del_timer(&bt_sleep_tl);
399 platform_set_drvdata(pdev, NULL);
401 DBG("Enter %s\n",__FUNCTION__);
405 static struct platform_driver bcm4329_rfkill_driver = {
406 .probe = bcm4329_rfkill_probe,
407 .remove = __devexit_p(bcm4329_rfkill_remove),
409 .name = "rk29sdk_rfkill",
410 .owner = THIS_MODULE,
412 #if BT_WAKE_HOST_SUPPORT
413 .suspend = bcm4329_rfkill_suspend,
414 .resume = bcm4329_rfkill_resume,
419 * Module initialization
421 static int __init bcm4329_mod_init(void)
424 DBG("Enter %s\n",__FUNCTION__);
425 ret = platform_driver_register(&bcm4329_rfkill_driver);
426 LOG("ret=0x%x\n", ret);
430 static void __exit bcm4329_mod_exit(void)
432 platform_driver_unregister(&bcm4329_rfkill_driver);
435 module_init(bcm4329_mod_init);
436 module_exit(bcm4329_mod_exit);
437 MODULE_DESCRIPTION("bcm4329 Bluetooth driver");
438 MODULE_AUTHOR("roger_chen cz@rock-chips.com, cmy@rock-chips.com");
439 MODULE_LICENSE("GPL");