audio: a2220: remove compile warnings
[linux-3.10.git] / drivers / misc / bcm4329_rfkill.c
1 /*
2  * drivers/misc/bcm4329_rfkill.c
3  *
4  * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/err.h>
22 #include <linux/types.h>
23 #include <linux/uaccess.h>
24 #include <linux/fs.h>
25 #include <linux/gpio.h>
26 #include <linux/init.h>
27 #include <linux/kernel.h>
28 #include <linux/miscdevice.h>
29 #include <linux/module.h>
30 #include <linux/rfkill.h>
31 #include <linux/platform_device.h>
32 #include <linux/clk.h>
33 #include <linux/slab.h>
34 #include <linux/delay.h>
35
36 struct bcm4329_rfkill_data {
37         int gpio_reset;
38         int gpio_shutdown;
39         int delay;
40         struct clk *bt_32k_clk;
41 };
42
43 static struct bcm4329_rfkill_data *bcm4329_rfkill;
44
45 static int bcm4329_bt_rfkill_set_power(void *data, bool blocked)
46 {
47         /*
48          * check if BT gpio_shutdown line status and current request are same.
49          * If same, then return, else perform requested operation.
50          */
51         if (gpio_get_value_cansleep(bcm4329_rfkill->gpio_shutdown) && !blocked)
52                 return 0;
53
54         if (blocked) {
55                 if (bcm4329_rfkill->gpio_shutdown)
56                         gpio_direction_output(bcm4329_rfkill->gpio_shutdown, 0);
57                 if (bcm4329_rfkill->gpio_reset)
58                         gpio_direction_output(bcm4329_rfkill->gpio_reset, 0);
59                 if (bcm4329_rfkill->bt_32k_clk)
60                         clk_disable_unprepare(bcm4329_rfkill->bt_32k_clk);
61         } else {
62                 if (bcm4329_rfkill->bt_32k_clk)
63                         clk_prepare_enable(bcm4329_rfkill->bt_32k_clk);
64                 if (bcm4329_rfkill->gpio_shutdown)
65                 {
66                         gpio_direction_output(bcm4329_rfkill->gpio_shutdown, 0);
67                         msleep(100);
68                         gpio_direction_output(bcm4329_rfkill->gpio_shutdown, 1);
69                         msleep(100);
70                 }
71                 if (bcm4329_rfkill->gpio_reset)
72                 {
73                         gpio_direction_output(bcm4329_rfkill->gpio_reset, 0);
74                         msleep(100);
75                         gpio_direction_output(bcm4329_rfkill->gpio_reset, 1);
76                         msleep(100);
77                 }
78         }
79
80         return 0;
81 }
82
83 static const struct rfkill_ops bcm4329_bt_rfkill_ops = {
84         .set_block = bcm4329_bt_rfkill_set_power,
85 };
86
87 static int bcm4329_rfkill_probe(struct platform_device *pdev)
88 {
89         struct rfkill *bt_rfkill;
90         struct resource *res;
91         int ret;
92         bool enable = false;  /* off */
93         bool default_sw_block_state;
94
95         bcm4329_rfkill = kzalloc(sizeof(*bcm4329_rfkill), GFP_KERNEL);
96         if (!bcm4329_rfkill)
97                 return -ENOMEM;
98
99         bcm4329_rfkill->bt_32k_clk = clk_get(&pdev->dev, "bcm4329_32k_clk");
100         if (IS_ERR(bcm4329_rfkill->bt_32k_clk)) {
101                 pr_warn("%s: can't find bcm4329_32k_clk.\
102                                 assuming 32k clock to chip\n", __func__);
103                 bcm4329_rfkill->bt_32k_clk = NULL;
104         }
105
106         res = platform_get_resource_byname(pdev, IORESOURCE_IO,
107                                                 "bcm4329_nreset_gpio");
108         if (res) {
109                 bcm4329_rfkill->gpio_reset = res->start;
110                 ret = gpio_request(bcm4329_rfkill->gpio_reset,
111                                                 "bcm4329_nreset_gpio");
112         } else {
113                 pr_warn("%s : can't find reset gpio. "
114                         "reset gpio may not be defined for "
115                         "this platform \n", __func__);
116                 bcm4329_rfkill->gpio_reset = 0;
117         }
118
119         res = platform_get_resource_byname(pdev, IORESOURCE_IO,
120                                                 "bcm4329_nshutdown_gpio");
121         if (res) {
122                 bcm4329_rfkill->gpio_shutdown = res->start;
123                 ret = gpio_request(bcm4329_rfkill->gpio_shutdown,
124                                                 "bcm4329_nshutdown_gpio");
125         } else {
126                 pr_warn("%s : can't find shutdown gpio "
127                         "shutdown gpio may not be defined for "
128                         "this platform \n", __func__);
129                 bcm4329_rfkill->gpio_shutdown = 0;
130         }
131
132         /* make sure at-least one of the GPIO is defined */
133         if (!bcm4329_rfkill->gpio_reset && !bcm4329_rfkill->gpio_shutdown)
134                 goto free_bcm_res;
135
136         if (bcm4329_rfkill->bt_32k_clk && enable)
137                 clk_prepare_enable(bcm4329_rfkill->bt_32k_clk);
138         if (bcm4329_rfkill->gpio_shutdown)
139                 gpio_direction_output(bcm4329_rfkill->gpio_shutdown, enable);
140         if (bcm4329_rfkill->gpio_reset)
141                 gpio_direction_output(bcm4329_rfkill->gpio_reset, enable);
142
143         bt_rfkill = rfkill_alloc("bcm4329 Bluetooth", &pdev->dev,
144                                 RFKILL_TYPE_BLUETOOTH, &bcm4329_bt_rfkill_ops,
145                                 NULL);
146
147         if (unlikely(!bt_rfkill))
148                 goto free_bcm_res;
149
150         default_sw_block_state = !enable;
151         rfkill_set_states(bt_rfkill, default_sw_block_state, false);
152
153         ret = rfkill_register(bt_rfkill);
154
155         if (unlikely(ret)) {
156                 rfkill_destroy(bt_rfkill);
157                 goto free_bcm_res;
158         }
159
160         return 0;
161
162 free_bcm_res:
163         if (bcm4329_rfkill->gpio_shutdown)
164                 gpio_free(bcm4329_rfkill->gpio_shutdown);
165         if (bcm4329_rfkill->gpio_reset)
166                 gpio_free(bcm4329_rfkill->gpio_reset);
167         if (bcm4329_rfkill->bt_32k_clk && enable)
168                 clk_disable_unprepare(bcm4329_rfkill->bt_32k_clk);
169         if (bcm4329_rfkill->bt_32k_clk)
170                 clk_put(bcm4329_rfkill->bt_32k_clk);
171         kfree(bcm4329_rfkill);
172         return -ENODEV;
173 }
174
175 static int bcm4329_rfkill_remove(struct platform_device *pdev)
176 {
177         struct rfkill *bt_rfkill = platform_get_drvdata(pdev);
178
179         if (bcm4329_rfkill->bt_32k_clk)
180                 clk_put(bcm4329_rfkill->bt_32k_clk);
181         rfkill_unregister(bt_rfkill);
182         rfkill_destroy(bt_rfkill);
183         if (bcm4329_rfkill->gpio_shutdown)
184                 gpio_free(bcm4329_rfkill->gpio_shutdown);
185         if (bcm4329_rfkill->gpio_reset)
186                 gpio_free(bcm4329_rfkill->gpio_reset);
187         kfree(bcm4329_rfkill);
188
189         return 0;
190 }
191
192 static struct platform_driver bcm4329_rfkill_driver = {
193         .probe = bcm4329_rfkill_probe,
194         .remove = bcm4329_rfkill_remove,
195         .driver = {
196                    .name = "bcm4329_rfkill",
197                    .owner = THIS_MODULE,
198         },
199 };
200
201 static int __init bcm4329_rfkill_init(void)
202 {
203         return platform_driver_register(&bcm4329_rfkill_driver);
204 }
205
206 static void __exit bcm4329_rfkill_exit(void)
207 {
208         platform_driver_unregister(&bcm4329_rfkill_driver);
209 }
210
211 module_init(bcm4329_rfkill_init);
212 module_exit(bcm4329_rfkill_exit);
213
214 MODULE_DESCRIPTION("BCM4329 rfkill");
215 MODULE_AUTHOR("NVIDIA");
216 MODULE_LICENSE("GPL");