3 * Copyright (C) 2010-2011 RDA Micro <anli@rdamicro.com>
\r
4 * This file belong to RDA micro
\r
5 * File: drivers/char/tcc_bt_dev.c
\r
8 #include <linux/kernel.h>
\r
9 #include <linux/module.h>
\r
10 #include <linux/fs.h>
\r
11 #include <asm/uaccess.h>
\r
12 #include <linux/ioctl.h>
\r
13 #include <linux/device.h>
\r
15 #include <linux/delay.h>
\r
16 #include <linux/gpio.h>
\r
17 #include <mach/gpio.h>
\r
18 #include <asm/mach-types.h>
\r
19 #include <mach/iomux.h>
\r
20 #include <linux/interrupt.h>
\r
21 #include <asm/irq.h>
\r
22 #include <linux/wakelock.h>
\r
23 #include <linux/rfkill-rk.h>
\r
24 #include <linux/platform_device.h>
\r
26 #include <net/bluetooth/bluetooth.h>
\r
27 #include <net/bluetooth/hci_core.h>
\r
30 #ifndef HOST_WAKE_DELAY
\r
31 #define HOST_WAKE_DELAY
\r
34 #define DEV_NAME "tcc_bt_dev"
\r
36 #define BT_DEV_MAJOR_NUM 234
\r
37 #define BT_DEV_MINOR_NUM 0
\r
39 #define IOCTL_BT_DEV_POWER _IO(BT_DEV_MAJOR_NUM, 100)
\r
40 #define IOCTL_BT_SET_EINT _IO(BT_DEV_MAJOR_NUM, 101)
\r
42 static wait_queue_head_t eint_wait;
\r
43 static struct work_struct rda_bt_event_work;
\r
44 //static struct workqueue_struct *rda_bt_workqueue;
46 static int irq_num = -1;
47 static int eint_gen;
\r
48 static int eint_mask;
\r
49 static struct class *bt_dev_class;
\r
50 static struct mutex sem;
\r
51 static struct tcc_bt_platform_data *tcc_bt_pdata = NULL;
\r
52 static int irq_flag = 0;
55 static void rda_bt_enable_irq(void)
\r
57 if((irq_num != -1) && (irq_flag == 0))
64 static void rda_bt_disable_irq(void)
\r
66 if((irq_num != -1) && (irq_flag == 1))
68 disable_irq_nosync(irq_num);
74 static void rda_bt_work_fun(struct work_struct *work)
\r
76 struct hci_dev *hdev = NULL;
\r
78 /* BlueZ stack, hci_uart driver */
\r
79 hdev = hci_dev_get(0);
\r
83 /* Avoid the early interrupt before hci0 registered */
\r
84 //printk(KERN_ALERT "hdev is NULL\n ");
\r
88 printk(KERN_ALERT "Send host wakeup command.\n");
\r
89 hci_send_cmd(hdev, 0xC0FC, 0, NULL);
\r
92 rda_bt_enable_irq();
\r
96 static int tcc_bt_dev_open(struct inode *inode, struct file *file)
\r
98 printk("[## BT ##] tcc_bt_dev_open.\n");
\r
104 static int tcc_bt_dev_release(struct inode *inode, struct file *file)
\r
106 printk("[## BT ##] tcc_bt_dev_release.\n");
\r
112 /*****************************************************************************
\r
114 *****************************************************************************/
\r
116 static unsigned int tcc_bt_dev_poll(struct file *file, poll_table *wait)
\r
120 printk("[## BT ##] tcc_bt_poll eint_gen %d, eint_mask %d ++\n", eint_gen, eint_mask);
\r
122 wait_event_interruptible(eint_wait, (eint_gen == 1 || eint_mask == 1));
\r
124 printk("[## BT ##] tcc_bt_poll eint_gen %d, eint_mask %d --\n", eint_gen, eint_mask);
\r
128 mask = POLLIN|POLLRDNORM;
\r
131 else if (eint_mask == 1)
\r
140 static int tcc_bt_power_control(int on_off)
\r
142 printk("[## BT ##] tcc_bt_power_control input[%d].\n", on_off);
\r
146 gpio_direction_output(tcc_bt_pdata->power_gpio.io, tcc_bt_pdata->power_gpio.enable);
\r
152 gpio_direction_output(tcc_bt_pdata->power_gpio.io, !tcc_bt_pdata->power_gpio.enable);
\r
153 rda_bt_disable_irq();
161 static long tcc_bt_dev_ioctl(struct file *file, unsigned int cmd,unsigned long arg)
\r
163 void __user *argp = (void __user *)arg;
\r
169 case IOCTL_BT_DEV_POWER:
\r
171 printk("[## BT ##] IOCTL_BT_DEV_POWER cmd[%d] parm1[%d].\n", cmd, rate);
\r
172 if (copy_from_user(&rate, argp, sizeof(rate)))
\r
176 ret = tcc_bt_power_control(rate);
\r
177 mutex_unlock(&sem);
\r
181 case IOCTL_BT_SET_EINT:
\r
183 if (copy_from_user(&rate, argp, sizeof(rate)))
\r
185 printk("[## BT ##] IOCTL_BT_SET_EINT cmd[%d].\n", cmd);
\r
190 rda_bt_enable_irq();
\r
194 rda_bt_disable_irq();
\r
196 wake_up_interruptible(&eint_wait);
\r
198 mutex_unlock(&sem);
\r
205 printk("[## BT ##] tcc_bt_dev_ioctl cmd[%d].\n", cmd);
\r
214 struct file_operations tcc_bt_dev_ops =
\r
216 .owner = THIS_MODULE,
\r
217 .unlocked_ioctl = tcc_bt_dev_ioctl,
\r
218 .open = tcc_bt_dev_open,
\r
219 .release = tcc_bt_dev_release,
\r
220 .poll = tcc_bt_dev_poll,
\r
223 #ifdef HOST_WAKE_DELAY
\r
224 struct wake_lock rda_bt_wakelock;
\r
227 static irqreturn_t rda_bt_host_wake_irq(int irq, void *dev)
\r
229 printk("rda_bt_host_wake_irq.\n");
\r
230 rda_bt_disable_irq();
232 #ifdef HOST_WAKE_DELAY
\r
233 wake_lock_timeout(&rda_bt_wakelock, 3 * HZ);
\r
236 #if 0 //CONFIG_BT_HCIUART
238 queue_work(rda_bt_workqueue, &rda_bt_event_work);
\r
240 /* Maybe handle the interrupt in user space? */
\r
242 wake_up_interruptible(&eint_wait);
\r
243 /* Send host wakeup command in user space, enable irq then */
\r
249 static int tcc_bt_probe(struct platform_device *pdev)
\r
253 struct tcc_bt_platform_data *pdata = pdev->dev.platform_data;
\r
255 printk("tcc_bt_probe.\n");
\r
256 if(pdata == NULL) {
\r
257 printk("tcc_bt_probe failed.\n");
\r
260 tcc_bt_pdata = pdata;
\r
262 if(pdata->power_gpio.io != INVALID_GPIO) {
\r
263 if (gpio_request(pdata->power_gpio.io, "ldoonpin")){
\r
264 printk("tcc bt ldoonpin is busy!\n");
\r
268 gpio_direction_output(pdata->power_gpio.io, !pdata->power_gpio.enable);//GPIO_LOW
\r
270 #ifdef HOST_WAKE_DELAY
\r
271 wake_lock_init(&rda_bt_wakelock, WAKE_LOCK_SUSPEND, "rda_bt_wake");
\r
274 if(pdata->wake_host_gpio.io != INVALID_GPIO) {
\r
275 if (gpio_request(pdata->wake_host_gpio.io, "tcc_bt_wake")){
\r
276 printk("tcc bt wakeis busy!\n");
\r
277 gpio_free(pdata->wake_host_gpio.io);
\r
282 gpio_direction_input(pdata->wake_host_gpio.io);
\r
283 irq_num = gpio_to_irq(pdata->wake_host_gpio.io);
\r
284 ret = request_irq(irq_num, rda_bt_host_wake_irq, pdata->wake_host_gpio.enable, "tcc_bt_host_wake",NULL);
\r
287 printk("bt_host_wake irq request fail.\n");
\r
292 enable_irq_wake(irq_num);
294 rda_bt_disable_irq();
297 printk("[## BT ##] init_module\n");
\r
299 ret = register_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME, &tcc_bt_dev_ops);
\r
302 printk("[## BT ##] [%d]fail to register the character device.\n", ret);
\r
306 bt_dev_class = class_create(THIS_MODULE, DEV_NAME);
\r
307 if (IS_ERR(bt_dev_class))
\r
309 printk("BT RDA class_create failed\n");
\r
313 device_create(bt_dev_class, NULL, MKDEV(BT_DEV_MAJOR_NUM, BT_DEV_MINOR_NUM), NULL, DEV_NAME);
\r
315 init_waitqueue_head(&eint_wait);
\r
318 INIT_WORK(&rda_bt_event_work, rda_bt_work_fun);
\r
319 rda_bt_workqueue = create_singlethread_workqueue("rda_bt");
320 if (!rda_bt_workqueue)
322 printk("create_singlethread_workqueue failed.\n");
\r
331 gpio_free(pdata->power_gpio.io);
\r
332 gpio_free(pdata->wake_host_gpio.io);
\r
336 static int tcc_bt_remove(struct platform_device *pdev)
\r
338 printk("[## BT ##] cleanup_module.\n");
339 free_irq(irq_num, NULL);
340 unregister_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME);
\r
344 cancel_work_sync(&rda_bt_event_work);
\r
345 //destroy_workqueue(rda_bt_workqueue);
\r
347 #ifdef HOST_WAKE_DELAY
\r
348 wake_lock_destroy(&rda_bt_wakelock);
\r
354 static struct platform_driver tcc_bt_driver = {
\r
355 .probe = tcc_bt_probe,
\r
356 .remove = tcc_bt_remove,
\r
358 .name = "tcc_bt_dev",
\r
359 .owner = THIS_MODULE,
\r
363 static int __init tcc_bt_init_module(void)
\r
365 printk("Enter %s\n", __func__);
\r
366 return platform_driver_register(&tcc_bt_driver);
\r
369 static void __exit tcc_bt_cleanup_module(void)
\r
371 printk("Enter %s\n", __func__);
\r
372 platform_driver_unregister(&tcc_bt_driver);
\r
375 module_init(tcc_bt_init_module);
\r
376 module_exit(tcc_bt_cleanup_module);
\r
379 MODULE_AUTHOR("Telechips Inc. linux@telechips.com");
\r
380 MODULE_DESCRIPTION("TCC_BT_DEV");
\r
381 MODULE_LICENSE("GPL");
\r