video: backlight: pwm_bl: fix backlight polarity
[firefly-linux-kernel-4.4.55.git] / drivers / mtk_wcn_bt / bt_hwctl_dev.c
1 /* Copyright Statement:
2  *
3  * This software/firmware and related documentation ("MediaTek Software") are
4  * protected under relevant copyright laws. The information contained herein is
5  * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
6  * the prior written permission of MediaTek inc. and/or its licensors, any
7  * reproduction, modification, use or disclosure of MediaTek Software, and
8  * information contained herein, in whole or in part, shall be strictly
9  * prohibited.
10  * 
11  * MediaTek Inc. (C) 2010. All rights reserved.
12  * 
13  * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
14  * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
15  * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
16  * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
17  * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
19  * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
20  * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
21  * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
22  * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
23  * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
24  * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
25  * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
26  * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
27  * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
28  * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
29  * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
30  * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
31  * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
32  *
33  * The following software/firmware and/or related documentation ("MediaTek
34  * Software") have been modified by MediaTek Inc. All revisions are subject to
35  * any receiver's applicable license agreements with MediaTek Inc.
36  */
37
38 #include <linux/kernel.h>
39 #include <linux/module.h>
40 #include <linux/init.h>
41 #include <linux/types.h>
42 #include <linux/wait.h>
43 #include <linux/slab.h>
44 #include <linux/fs.h>
45 #include <linux/sched.h>
46 #include <linux/poll.h>
47 #include <linux/device.h>
48 #include <linux/platform_device.h>
49 #include <linux/cdev.h>
50 #include <linux/errno.h>
51 #include <asm/io.h>
52 #include <asm/uaccess.h>
53 #include <net/bluetooth/bluetooth.h>
54 #include <net/bluetooth/hci_core.h>
55 #include <linux/gpio.h>
56 #include <mach/gpio.h>
57
58 #include "bt_hwctl.h"
59
60
61 #define BT_HWCTL_DEBUG_EN     0
62
63 #define BT_HWCTL_ALERT(f, s...) \
64     printk(KERN_ALERT "BTHWCTL " f, ## s)
65
66 #if BT_HWCTL_DEBUG_EN
67 #define BT_HWCTL_DEBUG(f, s...) \
68     printk(KERN_INFO "BTHWCTL " f, ## s)
69 #else
70 #define BT_HWCTL_DEBUG(f, s...) \
71     ((void)0)
72 #endif
73
74 /**************************************************************************
75  *                        D E F I N I T I O N S                           *
76 ***************************************************************************/
77
78 #define BTHWCTL_NAME                 "bthwctl"
79 #define BTHWCTL_DEV_NAME             "/dev/bthwctl"
80 #define BTHWCTL_IOC_MAGIC            0xf6
81 #define BTHWCTL_IOCTL_SET_POWER      _IOWR(BTHWCTL_IOC_MAGIC, 0, uint32_t)
82 #define BTHWCTL_IOCTL_SET_EINT       _IOWR(BTHWCTL_IOC_MAGIC, 1, uint32_t)
83
84 wait_queue_head_t eint_wait;
85 int eint_gen;
86 int eint_mask;
87 int eint_handle_method = 0; // 0: for 4.1; 1: for 4.2 
88 struct wake_lock mt6622_irq_wakelock;
89 int mt6622_suspend_flag;
90
91 struct bt_hwctl {
92     bool powerup;
93     dev_t dev_t;
94     struct class *cls;
95     struct device *dev;
96     struct cdev cdev;
97     struct mutex sem;
98 };
99 static struct bt_hwctl *bh = NULL;
100
101 static struct mt6622_platform_data *mt6622_pdata;
102
103 /*****************************************************************************
104  *  bt_hwctl_open
105 *****************************************************************************/
106 static int bt_hwctl_open(struct inode *inode, struct file *file)
107 {
108     BT_HWCTL_DEBUG("bt_hwctl_open\n");
109     eint_gen = 0;
110     eint_mask = 0;
111     return 0;
112 }
113
114 /*****************************************************************************
115  *  bt_hwctl_ioctl
116 *****************************************************************************/
117 static long bt_hwctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
118 {
119     int ret = 0;
120      
121     BT_HWCTL_DEBUG("bt_hwctl_ioctl\n");
122     
123     if(!bh) {
124         BT_HWCTL_ALERT("bt_hwctl struct not initialized\n");
125         return -EFAULT;
126     }
127     
128     switch(cmd)
129     {
130         case BTHWCTL_IOCTL_SET_POWER:
131         {
132             unsigned long pwr = 0;
133             if (copy_from_user(&pwr, (void*)arg, sizeof(unsigned long)))
134                 return -EFAULT;
135                 
136             BT_HWCTL_DEBUG("BTHWCTL_IOCTL_SET_POWER: %d\n", (int)pwr);
137             
138             mutex_lock(&bh->sem);
139             if (pwr){
140                 ret = mt_bt_power_on();
141             }
142             else{
143                 mt_bt_power_off();
144             }
145             mutex_unlock(&bh->sem);
146             
147             break;
148         }
149         case BTHWCTL_IOCTL_SET_EINT:
150         {
151             unsigned long eint = 0;
152             if (copy_from_user(&eint, (void*)arg, sizeof(unsigned long)))
153                 return -EFAULT;
154                 
155             BT_HWCTL_DEBUG("BTHWCTL_IOCTL_SET_EINT: %d\n", (int)eint);
156             
157             mutex_lock(&bh->sem);
158             if (eint){
159                 /* Enable irq from user space */ 
160                 BT_HWCTL_DEBUG("Set BT EINT enable\n");
161                 mt_bt_enable_irq();
162             }
163             else{
164                 /* Disable irq from user space, maybe time to close driver */
165                 BT_HWCTL_DEBUG("Set BT EINT disable\n");
166                 mt_bt_disable_irq();
167                 eint_mask = 1;
168                 wake_up_interruptible(&eint_wait);
169             }
170             mutex_unlock(&bh->sem);
171             
172             break;
173         }    
174         default:
175             BT_HWCTL_ALERT("BTHWCTL_IOCTL not support\n");
176             return -EPERM;
177     }
178     
179     return ret;
180 }
181
182 /*****************************************************************************
183  *  bt_hwctl_release
184 *****************************************************************************/
185 static int bt_hwctl_release(struct inode *inode, struct file *file)
186 {
187     BT_HWCTL_DEBUG("bt_hwctl_release\n");
188     eint_gen = 0;
189     eint_mask = 0;
190     return 0;
191 }
192
193 /*****************************************************************************
194  *  bt_hwctl_poll
195 *****************************************************************************/
196 static unsigned int bt_hwctl_poll(struct file *file, poll_table *wait)
197 {
198     uint32_t mask = 0;
199    
200     eint_handle_method = 1;
201          
202     BT_HWCTL_DEBUG("bt_hwctl_poll eint_gen %d, eint_mask %d ++\n", eint_gen, eint_mask);
203     //poll_wait(file, &eint_wait, wait);
204     wait_event_interruptible(eint_wait, (eint_gen == 1 || eint_mask == 1));
205     BT_HWCTL_DEBUG("bt_hwctl_poll eint_gen %d, eint_mask %d --\n", eint_gen, eint_mask);
206     
207     if(mt6622_suspend_flag == 1) {
208         printk("mt6622 wake lock 5000ms\n");
209         mt6622_suspend_flag = 0;
210         wake_lock_timeout(&mt6622_irq_wakelock, msecs_to_jiffies(5000));
211     }
212     
213     if(eint_gen == 1){
214         mask = POLLIN|POLLRDNORM;
215         eint_gen = 0;
216     }
217     else if (eint_mask == 1){
218         mask = POLLERR;
219         eint_mask = 0;
220     }
221     
222     return mask;
223 }
224
225 static void mtk_wcn_bt_work_fun(struct work_struct *work)
226 {
227     struct hci_dev *hdev = NULL;
228
229     /* BlueZ stack, hci_uart driver */
230     hdev = hci_dev_get(0);
231     if(hdev == NULL){
232         /* Avoid the early interrupt before hci0 registered */
233         //printk(KERN_ALERT "hdev is NULL\n ");
234     }else{
235         //printk(KERN_ALERT "Send host wakeup command\n");
236         hci_send_cmd(hdev, 0xFCC1, 0, NULL);
237     }
238     
239     mt_bt_enable_irq();
240 }
241
242 static int mt6622_probe(struct platform_device *pdev)
243 {
244     struct mt6622_platform_data *pdata = pdev->dev.platform_data;
245     
246     printk("mt6622_probe.\n");
247     
248     mt6622_pdata = pdata;
249     if(pdata == NULL) {
250         printk("mt6622_probe failed.\n");
251         return -1;
252     }
253     
254                 if(pdata->power_gpio.io != INVALID_GPIO) {
255                         if (gpio_request(pdata->power_gpio.io, "BT_PWR_EN")){
256                                 printk("mt6622 power_gpio is busy!\n");
257                                 //return -1;
258                         }
259                 }
260                 
261                 if(pdata->reset_gpio.io != INVALID_GPIO) {
262                         if (gpio_request(pdata->reset_gpio.io, "BT_RESET")){
263                                 printk("mt6622 reset_gpio is busy!\n");
264                                 gpio_free(pdata->power_gpio.io);
265                                 //return -1;
266                         }
267                 }
268                 
269                 if(pdata->irq_gpio.io != INVALID_GPIO) {
270                         if (gpio_request(pdata->irq_gpio.io, "BT_EINT")){
271                                 printk("mt6622 irq_gpio is busy!\n");
272                                 gpio_free(pdata->power_gpio.io);
273                                 gpio_free(pdata->reset_gpio.io);
274                                 //return -1;
275                         }
276                 }
277                 
278                 mt_bt_power_init();
279                 
280                 return 0;
281 }
282
283 static int mt6622_remove(struct platform_device *pdev)
284 {
285         struct mt6622_platform_data *pdata = pdev->dev.platform_data;
286         
287         printk("mt6622_remove.\n");
288         
289         if(pdata) {
290           if(pdata->power_gpio.io != INVALID_GPIO)
291                 gpio_free(pdata->power_gpio.io);
292           if(pdata->reset_gpio.io != INVALID_GPIO)
293                 gpio_free(pdata->reset_gpio.io);
294           if(pdata->irq_gpio.io != INVALID_GPIO)
295                 gpio_free(pdata->irq_gpio.io);
296   }
297         
298         return 0;
299 }
300
301 void *mt_bt_get_platform_data(void)
302 {
303         return (void *)mt6622_pdata;
304 }
305
306 /**************************************************************************
307  *                K E R N E L   I N T E R F A C E S                       *
308 ***************************************************************************/
309 static struct file_operations bt_hwctl_fops = {
310     .owner      = THIS_MODULE,
311 //    .ioctl      = bt_hwctl_ioctl,
312     .unlocked_ioctl = bt_hwctl_ioctl,
313     .open       = bt_hwctl_open,
314     .release    = bt_hwctl_release,
315     .poll       = bt_hwctl_poll,
316 };
317
318 static struct platform_driver mt6622_driver = {
319     .probe = mt6622_probe,
320     .remove = mt6622_remove,
321     .suspend = mt6622_suspend,
322     .resume = mt6622_resume,
323     .driver = {
324         .name = "mt6622",
325         .owner = THIS_MODULE,
326     },
327 };
328
329 /*****************************************************************************/
330 static int __init bt_hwctl_init(void)
331 {
332     int ret = -1, err = -1;
333     
334     BT_HWCTL_DEBUG("bt_hwctl_init\n");
335     
336     platform_driver_register(&mt6622_driver);
337     
338     if (!(bh = kzalloc(sizeof(struct bt_hwctl), GFP_KERNEL)))
339     {
340         BT_HWCTL_ALERT("bt_hwctl_init allocate dev struct failed\n");
341         err = -ENOMEM;
342         goto ERR_EXIT;
343     }
344     
345     ret = alloc_chrdev_region(&bh->dev_t, 0, 1, BTHWCTL_NAME);
346     if (ret) {
347         BT_HWCTL_ALERT("alloc chrdev region failed\n");
348         goto ERR_EXIT;
349     }
350     
351     BT_HWCTL_DEBUG("alloc %s:%d:%d\n", BTHWCTL_NAME, MAJOR(bh->dev_t), MINOR(bh->dev_t));
352     
353     cdev_init(&bh->cdev, &bt_hwctl_fops);
354     
355     bh->cdev.owner = THIS_MODULE;
356     bh->cdev.ops = &bt_hwctl_fops;
357     
358     err = cdev_add(&bh->cdev, bh->dev_t, 1);
359     if (err) {
360         BT_HWCTL_ALERT("add chrdev failed\n");
361         goto ERR_EXIT;
362     }
363     
364     bh->cls = class_create(THIS_MODULE, BTHWCTL_NAME);
365     if (IS_ERR(bh->cls)) {
366         err = PTR_ERR(bh->cls);
367         BT_HWCTL_ALERT("class_create failed, errno:%d\n", err);
368         goto ERR_EXIT;
369     }
370     
371     bh->dev = device_create(bh->cls, NULL, bh->dev_t, NULL, BTHWCTL_NAME);
372     mutex_init(&bh->sem);
373     
374     init_waitqueue_head(&eint_wait);
375     
376     wake_lock_init(&mt6622_irq_wakelock, WAKE_LOCK_SUSPEND, "mt6622_irq_wakelock");
377     
378     /*INIT_WORK(&mtk_wcn_bt_event_work, mtk_wcn_bt_work_fun);
379     mtk_wcn_bt_workqueue = create_singlethread_workqueue("mtk_wcn_bt");
380     if (!mtk_wcn_bt_workqueue) {
381         printk("create_singlethread_workqueue failed.\n");
382         err = -ESRCH;
383         goto ERR_EXIT;
384     }*/    
385     
386     /* request gpio used by BT */
387     //mt_bt_gpio_init();
388     
389     BT_HWCTL_DEBUG("bt_hwctl_init ok\n");
390     
391     return 0;
392     
393 ERR_EXIT:
394     if (err == 0)
395         cdev_del(&bh->cdev);
396     if (ret == 0)
397         unregister_chrdev_region(bh->dev_t, 1);
398         
399     if (bh){
400         kfree(bh);
401         bh = NULL;
402     }     
403     return -1;
404 }
405
406 /*****************************************************************************/
407 static void __exit bt_hwctl_exit(void)
408 {
409     BT_HWCTL_DEBUG("bt_hwctl_exit\n");
410     
411     wake_lock_destroy(&mt6622_irq_wakelock);
412     
413     platform_driver_unregister(&mt6622_driver);
414     
415     if (bh){
416         cdev_del(&bh->cdev);
417         
418         unregister_chrdev_region(bh->dev_t, 1);
419         device_destroy(bh->cls, bh->dev_t);
420         
421         class_destroy(bh->cls);
422         mutex_destroy(&bh->sem);
423         
424         kfree(bh);
425         bh = NULL;
426     }
427     
428     /* release gpio used by BT */
429     //mt_bt_gpio_release();
430 }
431
432 EXPORT_SYMBOL(mt_bt_get_platform_data);
433 EXPORT_SYMBOL(eint_wait);
434 EXPORT_SYMBOL(eint_gen);
435 //EXPORT_SYMBOL(mtk_wcn_bt_event_work);
436 //EXPORT_SYMBOL(mtk_wcn_bt_workqueue);
437
438 module_init(bt_hwctl_init);
439 module_exit(bt_hwctl_exit);
440 MODULE_AUTHOR("Tingting Lei <tingting.lei@mediatek.com>");
441 MODULE_DESCRIPTION("Bluetooth hardware control driver");
442 MODULE_LICENSE("GPL");