drm/cma: Cocci spatch "ptr_ret.spatch"
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / bluetooth / brcm_rfkill.c
1 /*
2  * Copyright (C) 2011 Google, Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/delay.h>
17 #include <linux/device.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/rfkill.h>
21 #include <linux/gpio.h>
22 #include <linux/ioport.h>
23 #include <linux/clk.h>
24 #include <soc/sprd/board.h>
25 #include <linux/of_gpio.h>
26
27
28 static struct rfkill *bt_rfk;
29 static const char bt_name[] = "bluetooth";
30
31 static  unsigned long bt_power;
32 static  unsigned long bt_reset;
33
34 static void bt_clk_init(void)
35 {
36         struct clk *bt_clk;
37         bt_clk = clk_get(NULL, "clk_aux0");
38         if (IS_ERR(bt_clk)) {
39                 printk("clock: failed to get clk_aux0\n");
40         }
41         clk_set_rate(bt_clk, 32000);
42         //clk_enable(bt_clk);
43         clk_prepare_enable(bt_clk);
44 }
45
46
47 static void getIoResource(struct platform_device  *pdev)
48 {
49         struct resource *res;
50
51         printk("rfkill get gpio\n");
52
53         res = platform_get_resource_byname(pdev, IORESOURCE_IO,"bt_power");
54         if (!res) {
55                 printk("couldn't bt_power gpio\n");
56         }
57         else
58         bt_power = res->start;
59
60         res = platform_get_resource_byname(pdev, IORESOURCE_IO,"bt_reset");
61         if (!res) {
62                 printk("couldn't find bt_reset gpio\n");
63         }
64         else
65         bt_reset = res->start;
66
67         printk("bt_reset = %ld, bt_power = %ld\n", bt_reset, bt_power);
68 }
69
70 static void getIoResourceDT(struct platform_device  *pdev)
71 {
72         struct device_node *np = pdev->dev.of_node;
73
74         bt_power = of_get_gpio(np, 0);
75         if (bt_power < 0) {
76                 printk("couldn't bt_power gpio\n");
77         }
78         bt_reset = of_get_gpio(np, 1);
79         if (bt_reset < 0) {
80                 printk("couldn't bt_reset gpio\n");
81         }
82
83         printk("bt_reset = %ld, bt_power = %ld\n", bt_reset, bt_power);
84 }
85
86 static int bluetooth_set_power(void *data, bool blocked)
87 {
88         printk("%s: start_block=%d\n",__func__, blocked);
89
90         if (!blocked) {
91                 gpio_direction_output(bt_power, 0);
92                 gpio_direction_output(bt_reset, 0);
93                 mdelay(10);
94                 gpio_direction_output(bt_power, 1);
95                 gpio_direction_output(bt_reset, 1);
96                 mdelay(150);
97                // bt_clk_init();
98         } else {
99                 gpio_direction_output(bt_power, 0);
100                 gpio_direction_output(bt_reset, 0);
101                 mdelay(10);
102         }
103         printk("%s: end_block=%d\n",__func__, blocked);
104         return 0;
105 }
106
107 static struct rfkill_ops rfkill_bluetooth_ops = {
108         .set_block = bluetooth_set_power,
109 };
110
111 static void rfkill_gpio_init(void)
112 {
113         if(gpio_request(bt_power,"bt_power")){
114                 printk("request bt power fail\n");
115         }
116         if(gpio_request(bt_reset,"bt_reset")){
117                 printk("request bt reset fail\n");
118         }
119 }
120
121 static void rfkill_gpio_deinit(void)
122 {
123         gpio_free(bt_power);
124         gpio_free(bt_reset);
125 }
126 static int rfkill_bluetooth_probe(struct platform_device *pdev)
127 {
128
129         int rc = 0;
130         bool default_state = true;
131
132         printk(KERN_INFO "-->%s\n", __func__);
133 #ifndef CONFIG_OF
134         getIoResource(pdev);
135 #else
136         if (pdev->dev.of_node)
137                 getIoResourceDT(pdev);
138 #endif
139         bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
140            &rfkill_bluetooth_ops, NULL);
141         if (!bt_rfk) {
142          rc = -ENOMEM;
143          goto err_rfkill_alloc;
144         }
145         rfkill_gpio_init();
146         /* userspace cannot take exclusive control */
147         rfkill_init_sw_state(bt_rfk,false);
148         rc = rfkill_register(bt_rfk);
149         if (rc)
150                 goto err_rfkill_reg;
151
152         rfkill_set_sw_state(bt_rfk,true);
153         bluetooth_set_power(NULL, default_state);
154         bt_clk_init();
155
156         printk(KERN_INFO "<--%s\n", __func__);
157         return 0;
158
159 err_rfkill_reg:
160         rfkill_destroy(bt_rfk);
161 err_rfkill_alloc:
162         return rc;
163 }
164
165 static int rfkill_bluetooth_remove(struct platform_device *dev)
166 {
167         printk(KERN_INFO "-->%s\n", __func__);
168         rfkill_gpio_deinit();
169         rfkill_unregister(bt_rfk);
170         rfkill_destroy(bt_rfk);
171         printk(KERN_INFO "<--%s\n", __func__);
172         return 0;
173 }
174 #ifdef CONFIG_OF
175 static const struct of_device_id rfkill_of_match[] = {
176        { .compatible = "broadcom,rfkill", },
177        { }
178 };
179
180 MODULE_DEVICE_TABLE(of, rfkill_of_match);
181 #endif
182
183 static struct platform_driver rfkill_bluetooth_driver = {
184         .probe  = rfkill_bluetooth_probe,
185         .remove = rfkill_bluetooth_remove,
186         .driver = {
187                 .name = "rfkill",
188                 .owner = THIS_MODULE,
189 #ifdef CONFIG_OF
190                 .of_match_table = rfkill_of_match,
191 #endif
192         },
193 };
194
195 static int __init rfkill_bluetooth_init(void)
196 {
197         printk(KERN_INFO "-->%s\n", __func__);
198         return platform_driver_register(&rfkill_bluetooth_driver);
199 }
200
201 static void __exit rfkill_bluetooth_exit(void)
202 {
203         printk(KERN_INFO "-->%s\n", __func__);
204         platform_driver_unregister(&rfkill_bluetooth_driver);
205 }
206
207 //late_initcall(rfkill_bluetooth_init);
208 module_init(rfkill_bluetooth_init);
209 module_exit(rfkill_bluetooth_exit);
210 MODULE_DESCRIPTION("bluetooth rfkill");
211 MODULE_AUTHOR("Yale Wu <ye.wu@spreadtrum.com>");
212 MODULE_LICENSE("GPL");
213