rda5876BT: fix commit error
[firefly-linux-kernel-4.4.55.git] / drivers / misc / tcc_bt_dev.c
1 /*\r
2  *  Copyright (C) 2010-2011  RDA Micro <anli@rdamicro.com>\r
3  *  This file belong to RDA micro\r
4  * File:        drivers/char/tcc_bt_dev.c\r
5  */\r
6 \r
7 #include <linux/kernel.h>\r
8 #include <linux/module.h>\r
9 #include <linux/fs.h>\r
10 #include <asm/uaccess.h>\r
11 #include <linux/ioctl.h>\r
12 #include <linux/device.h>\r
13 \r
14 //#include <mach/bsp.h>\r
15 #include <asm/io.h>\r
16 #include <linux/delay.h>\r
17 \r
18 //#include <linux/tcc_bt_dev.h>\r
19 //#include <mach/tcc_pca953x.h>\r
20 \r
21 #include <linux/gpio.h>\r
22 #include <mach/gpio.h>\r
23 #include <asm/mach-types.h>\r
24 \r
25 #include <mach/iomux.h>\r
26 #include <linux/interrupt.h>\r
27 #include <asm/irq.h>\r
28 #include <linux/wakelock.h>\r
29 \r
30 #ifndef ON\r
31 #define ON              1\r
32 #endif\r
33 \r
34 #ifndef OFF\r
35 #define OFF     0\r
36 #endif\r
37 \r
38 #define LDO_ON_PIN             RK2928_PIN3_PC0\r
39 #define RDA_BT_HOST_WAKE_PIN   RK2928_PIN0_PC5\r
40 \r
41 #define BT_DEV_ON                                       1\r
42 #define BT_DEV_OFF                                      0\r
43 \r
44 #define BT_DEV_MAJOR_NUM                        234\r
45 #define BT_DEV_MINOR_NUM                        0\r
46 \r
47 //#define IOCTL_BT_DEV_POWER                    _IO(BT_DEV_MAJOR_NUM, 100)\r
48 //#define IOCTL_BT_DEV_SPECIFIC         _IO(BT_DEV_MAJOR_NUM, 101)\r
49 //#define IOCTL_BT_DEV_IS_POWER                 _IO(BT_DEV_MAJOR_NUM, 102)\r
50 \r
51 \r
52 #define IOCTL_BT_DEV_POWER              _IO(BT_DEV_MAJOR_NUM, 100)\r
53 #define IOCTL_BT_DEV_CTRL               _IO(BT_DEV_MAJOR_NUM, 101)\r
54 #define IOCTL_BT_SET_EINT               _IO(BT_DEV_MAJOR_NUM, 102)\r
55 #define IOCTL_BT_DEV_SPECIFIC           _IO(BT_DEV_MAJOR_NUM, 103)\r
56 \r
57 \r
58 static int bt_is_power = 0;\r
59 static int rda_bt_irq = 0;\r
60 static int irq_mask = 0;\r
61 extern void export_bt_hci_wakeup_chip(void);\r
62 \r
63 #define DEV_NAME "tcc_bt_dev"\r
64 static struct class *bt_dev_class;\r
65 \r
66 typedef struct {\r
67         int module;  // 0x12:CSR, 0x34:Broadcom\r
68         int TMP1;\r
69         int TMP2;\r
70 } tcc_bt_info_t;\r
71 \r
72 static int tcc_bt_dev_open(struct inode *inode, struct file *file)\r
73 {\r
74         printk("[## BT ##] tcc_bt_dev_open\n");\r
75         return 0;\r
76 }\r
77 \r
78 static int tcc_bt_dev_release(struct inode *inode, struct file *file)\r
79 {\r
80         printk("[## BT ##] tcc_bt_dev_release\n");\r
81         return 0;\r
82 }\r
83 \r
84 static int tcc_bt_power_control(int on_off)\r
85 {\r
86 //      volatile PGPIO pGPIO = (volatile PGPIO)tcc_p2v(HwGPIO_BASE);\r
87     \r
88         printk("[## BT ##] tcc_bt_power_control input[%d]\n", on_off);\r
89         \r
90         if(on_off == BT_DEV_ON)\r
91         {           \r
92                 gpio_direction_output(LDO_ON_PIN, GPIO_HIGH);\r
93                 bt_is_power = on_off;\r
94                 msleep(500);\r
95         }\r
96         else if(on_off == BT_DEV_OFF)\r
97         {\r
98                 gpio_direction_output(LDO_ON_PIN, GPIO_LOW);\r
99                 bt_is_power = BT_DEV_OFF;\r
100                 msleep(500);\r
101         }\r
102         else\r
103         {\r
104                 printk("[## BT_ERR ##] input_error On[%d] Off[%d]\n", BT_DEV_ON, BT_DEV_OFF);\r
105         }\r
106 \r
107         return 0;\r
108 }\r
109 \r
110 \r
111 static int tcc_bt_get_info(tcc_bt_info_t* arg)\r
112 {\r
113         tcc_bt_info_t *info_t;\r
114         int module_t;\r
115         \r
116         info_t = (tcc_bt_info_t *)arg;\r
117         copy_from_user(info_t, (tcc_bt_info_t *)arg, sizeof(tcc_bt_info_t));\r
118 \r
119         module_t = 0x56;        \r
120 \r
121         printk("[## BT ##] module[0x%x]\n", module_t);\r
122 \r
123         info_t->module = module_t;\r
124 \r
125         copy_to_user((tcc_bt_info_t *)arg, info_t, sizeof(tcc_bt_info_t));\r
126 \r
127         return 0;\r
128 }\r
129 \r
130 static long  tcc_bt_dev_ioctl(struct file *file, unsigned int cmd,unsigned long arg)\r
131 {\r
132         void __user *argp = (void __user *)arg;\r
133         char msg[14];\r
134         int ret = -1;\r
135         char rate;\r
136         //printk("[## BT ##] tcc_bt_dev_ioctl cmd[%d] arg[%d]\n", cmd, arg);\r
137         switch(cmd)\r
138         {\r
139                 case IOCTL_BT_DEV_POWER:                        \r
140                         if (copy_from_user(&rate, argp, sizeof(rate)))\r
141                         return -EFAULT;\r
142                         printk("[## BT ##] IOCTL_BT_DEV_POWER cmd[%d] parm1[%d]\n", cmd, rate);\r
143                         tcc_bt_power_control(rate);\r
144                         // GPIO Control\r
145                         break;\r
146                         \r
147                 case IOCTL_BT_DEV_SPECIFIC:\r
148                         printk("[## BT ##] IOCTL_BT_DEV_SPECIFIC cmd[%d]\n", cmd);\r
149                         tcc_bt_get_info((tcc_bt_info_t*)arg);\r
150                         break;\r
151 \r
152                 //case IOCTL_BT_DEV_IS_POWER:\r
153                         //if (copy_to_user(argp, &bt_is_power, sizeof(bt_is_power)))\r
154                         //return -EFAULT;\r
155                 case IOCTL_BT_SET_EINT:\r
156                      printk("[## BT ##] IOCTL_BT_SET_EINT cmd[%d]\n", cmd);\r
157                      if (irq_mask)\r
158                      {\r
159                          irq_mask = 0;\r
160                          enable_irq(rda_bt_irq);\r
161                      }\r
162                      break;\r
163                 default :\r
164                         printk("[## BT ##] tcc_bt_dev_ioctl cmd[%d]\n", cmd);\r
165                         break;\r
166         }\r
167 \r
168         return 0;\r
169 }\r
170 \r
171 \r
172 struct file_operations tcc_bt_dev_ops = {\r
173     .owner      = THIS_MODULE,\r
174     .unlocked_ioctl      = tcc_bt_dev_ioctl,\r
175     .open       = tcc_bt_dev_open,\r
176     .release    = tcc_bt_dev_release,\r
177 };\r
178 \r
179 struct wake_lock rda_bt_wakelock;\r
180 static irqreturn_t rda_5876_host_wake_irq(int irq, void *dev)\r
181 {\r
182         printk("rda_5876_host_wake_irq\n");\r
183         //export_bt_hci_wakeup_chip();\r
184         wake_lock_timeout(&rda_bt_wakelock, 3 * HZ); \r
185         disable_irq(rda_bt_irq);\r
186         irq_mask = 1;       \r
187         return IRQ_HANDLED;\r
188 }\r
189 \r
190 static int tcc_bt_init_module(void)\r
191 {\r
192     int ret;\r
193 \r
194         wake_lock_init(&rda_bt_wakelock, WAKE_LOCK_SUSPEND, "rda_bt_wake");\r
195         ret=gpio_request(LDO_ON_PIN, "ldoonpin");\r
196         if(ret < 0) {\r
197                 printk("%s:fail to request gpio %d\n",__func__,LDO_ON_PIN);\r
198                 return ret;\r
199         }\r
200         gpio_set_value(LDO_ON_PIN, GPIO_LOW);//GPIO_LOW\r
201         gpio_direction_output(LDO_ON_PIN, GPIO_LOW);//GPIO_LOW\r
202 \r
203         if(rda_bt_irq == 0){\r
204                 if(gpio_request(RDA_BT_HOST_WAKE_PIN, "bt_wake") != 0){\r
205                         printk("RDA_BT_HOST_WAKE_PIN request fail!\n");\r
206                         return -EIO;\r
207                 }\r
208                 gpio_direction_input(RDA_BT_HOST_WAKE_PIN);\r
209 \r
210                 rda_bt_irq = gpio_to_irq(RDA_BT_HOST_WAKE_PIN);\r
211                 ret = request_irq(rda_bt_irq, rda_5876_host_wake_irq, IRQF_TRIGGER_RISING, "bt_host_wake",NULL);\r
212                 if(ret){\r
213                         printk("bt_host_wake irq request fail\n");\r
214                         rda_bt_irq = 0;\r
215                         gpio_free(RDA_BT_HOST_WAKE_PIN);\r
216                         return -EIO;\r
217                 }\r
218                 enable_irq_wake(rda_bt_irq); //bt irq can wakeup host when host sleep\r
219                 disable_irq(rda_bt_irq);\r
220                 irq_mask = 1;\r
221             printk("request_irq bt_host_wake\n");\r
222         }\r
223 \r
224         \r
225         printk("[## BT ##] init_module\n");\r
226         ret = register_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME, &tcc_bt_dev_ops);\r
227 \r
228         bt_dev_class = class_create(THIS_MODULE, DEV_NAME);\r
229         device_create(bt_dev_class, NULL, MKDEV(BT_DEV_MAJOR_NUM, BT_DEV_MINOR_NUM), NULL, DEV_NAME);\r
230 #if 0\r
231         if(machine_is_tcc8900()){\r
232             gpio_request(TCC_GPB(25), "bt_power");\r
233             gpio_request(TCC_GPEXT2(9), "bt_reset");\r
234                 gpio_direction_output(TCC_GPB(25), 0); // output\r
235                 gpio_direction_output(TCC_GPEXT2(9), 0);\r
236         }else if(machine_is_tcc9300() || machine_is_tcc8800()) {      // #elif defined (CONFIG_MACH_TCC9300)\r
237                         //gpio_set_value(TCC_GPEXT1(7), 0);   /* BT-ON Disable */\r
238                 gpio_request(TCC_GPEXT3(2), "bt_wake");\r
239             gpio_request(TCC_GPEXT2(4), "bt_reset");\r
240                 gpio_direction_output(TCC_GPEXT3(2), 0); // output\r
241                 gpio_direction_output(TCC_GPEXT2(4), 0);\r
242         }\r
243         else if(machine_is_m801_88())\r
244         {\r
245                 gpio_request(TCC_GPA(13), "bt_reset");\r
246                 gpio_request(TCC_GPB(22), "BT WAKE");\r
247                 gpio_direction_output(TCC_GPA(13), 0); // output\r
248                 gpio_direction_output(TCC_GPB(22), 0); // output\r
249         }\r
250 #endif  \r
251     if(ret < 0){\r
252         printk("[## BT ##] [%d]fail to register the character device\n", ret);\r
253         return ret;\r
254     }\r
255 \r
256     return 0;\r
257 }\r
258 \r
259 static void tcc_bt_cleanup_module(void)\r
260 {\r
261         printk("[## BT ##] cleanup_module\n");\r
262     unregister_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME);\r
263     wake_lock_destroy(&rda_bt_wakelock);\r
264 }\r
265 \r
266 \r
267 late_initcall(tcc_bt_init_module);\r
268 module_exit(tcc_bt_cleanup_module);\r
269 \r
270 \r
271 MODULE_AUTHOR("Telechips Inc. linux@telechips.com");\r
272 MODULE_DESCRIPTION("TCC_BT_DEV");\r
273 MODULE_LICENSE("GPL");\r
274 \r
275 \r