1 #include <linux/kernel.h>
2 #include <linux/types.h>
3 #include <linux/module.h>
4 #include <linux/init.h>
5 #include <linux/gpio.h>
6 #include <linux/err.h>
7 #include <linux/device.h>
8 #include <linux/delay.h>
9 #include <linux/of_gpio.h>
10 #include <linux/clk.h>
11 #include <linux/rfkill.h>
12 #include <linux/regulator/consumer.h>
13 #include <linux/platform_device.h>
14 #include "internal.h"
15 #include "sunxi-rfkill.h"
16
17 static struct sunxi_bt_platdata *bluetooth_data;
18 static const struct of_device_id sunxi_bt_ids[];
19
20 static int sunxi_bt_on(struct sunxi_bt_platdata *data, bool on_off);
21 static DEFINE_MUTEX(sunxi_bluetooth_mutex);
22
sunxi_bluetooth_set_power(bool on_off)23 void sunxi_bluetooth_set_power(bool on_off)
24 {
25 struct platform_device *pdev;
26 int ret = 0;
27
28 if (!bluetooth_data)
29 return;
30
31 pdev = bluetooth_data->pdev;
32 mutex_lock(&sunxi_bluetooth_mutex);
33 rfkill_poweren_set(WL_DEV_BLUETOOTH, on_off);
34 if (on_off != bluetooth_data->power_state) {
35 ret = sunxi_bt_on(bluetooth_data, on_off);
36 if (ret)
37 dev_err(&pdev->dev, "set power failed\n");
38 }
39 rfkill_chipen_set(WL_DEV_BLUETOOTH, on_off);
40 mutex_unlock(&sunxi_bluetooth_mutex);
41 }
42 EXPORT_SYMBOL_GPL(sunxi_bluetooth_set_power);
43
sunxi_bt_on(struct sunxi_bt_platdata * data,bool on_off)44 static int sunxi_bt_on(struct sunxi_bt_platdata *data, bool on_off)
45 {
46 struct platform_device *pdev = data->pdev;
47 struct device *dev = &pdev->dev;
48 int ret = 0, i;
49
50 if (on_off) {
51 for (i = 0; i < CLK_MAX; i++) {
52 if (!IS_ERR_OR_NULL(data->clk[i]))
53 clk_prepare_enable(data->clk[i]);
54 }
55
56 for (i = 0; i < PWR_MAX; i++) {
57 if (!IS_ERR_OR_NULL(data->power[i])) {
58 if (data->power_vol[i]) {
59 ret = regulator_set_voltage(data->power[i],
60 data->power_vol[i], data->power_vol[i]);
61 if (ret < 0) {
62 dev_err(dev, "bt power[%d] (%s) set voltage failed\n",
63 i, data->power_name[i]);
64 return ret;
65 }
66
67 ret = regulator_get_voltage(data->power[i]);
68 if (ret != data->power_vol[i]) {
69 dev_err(dev, "bt power[%d] (%s) get voltage failed\n",
70 i, data->power_name[i]);
71 return ret;
72 }
73 }
74
75 ret = regulator_enable(data->power[i]);
76 if (ret < 0) {
77 dev_err(dev, "bt power[%d] (%s) enable failed\n",
78 i, data->power_name[i]);
79 return ret;
80 }
81 }
82 }
83
84 if (gpio_is_valid(data->gpio_bt_rst)) {
85 mdelay(10);
86 gpio_set_value(data->gpio_bt_rst, !data->gpio_bt_rst_assert);
87 }
88 } else {
89 if (gpio_is_valid(data->gpio_bt_rst))
90 gpio_set_value(data->gpio_bt_rst, data->gpio_bt_rst_assert);
91
92 for (i = 0; i < PWR_MAX; i++) {
93 if (!IS_ERR_OR_NULL(data->power[i])) {
94 ret = regulator_disable(data->power[i]);
95 if (ret < 0) {
96 dev_err(dev, "bt power[%d] (%s) disable failed\n",
97 i, data->power_name[i]);
98 return ret;
99 }
100 }
101 }
102
103 for (i = 0; i < CLK_MAX; i++) {
104 if (!IS_ERR_OR_NULL(data->clk[i]))
105 clk_disable_unprepare(data->clk[i]);
106 }
107 }
108
109 data->power_state = on_off;
110 dev_info(dev, "bt power %s success\n", on_off ? "on" : "off");
111
112 return 0;
113 }
114
sunxi_bt_set_block(void * data,bool blocked)115 static int sunxi_bt_set_block(void *data, bool blocked)
116 {
117 struct sunxi_bt_platdata *platdata = data;
118 struct platform_device *pdev = platdata->pdev;
119 int ret;
120
121 if (!bluetooth_data)
122 return 0;
123
124 if (blocked != platdata->power_state) {
125 dev_warn(&pdev->dev, "block state already is %d\n", blocked);
126 return 0;
127 }
128
129 dev_info(&pdev->dev, "set block: %d\n", blocked);
130 rfkill_poweren_set(WL_DEV_BLUETOOTH, !blocked);
131 ret = sunxi_bt_on(platdata, !blocked);
132 if (ret) {
133 dev_err(&pdev->dev, "set block failed\n");
134 return ret;
135 }
136
137 rfkill_chipen_set(WL_DEV_BLUETOOTH, !blocked);
138
139 return 0;
140 }
141
142 static const struct rfkill_ops sunxi_bt_rfkill_ops = {
143 .set_block = sunxi_bt_set_block,
144 };
145
sunxi_bt_init(struct platform_device * pdev)146 int sunxi_bt_init(struct platform_device *pdev)
147 {
148 struct device_node *np = of_find_matching_node(pdev->dev.of_node, sunxi_bt_ids);
149 struct device *dev = &pdev->dev;
150 struct sunxi_bt_platdata *data;
151 enum of_gpio_flags config;
152 int ret = 0;
153 int count, i;
154
155 if (!dev)
156 return -ENOMEM;
157
158 if (!np)
159 return 0;
160
161 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
162 data->pdev = pdev;
163
164 count = of_property_count_strings(np, "bt_power");
165 if (count <= 0) {
166 dev_warn(dev, "Missing bt_power.\n");
167 } else {
168 if (count > PWR_MAX) {
169 dev_warn(dev, "bt power count large than max(%d).\n", PWR_MAX);
170 count = PWR_MAX;
171 }
172 ret = of_property_read_string_array(np, "bt_power",
173 (const char **)data->power_name, count);
174 if (ret < 0)
175 return -ENOMEM;
176
177 ret = of_property_read_u32_array(np, "bt_power_vol",
178 (u32 *)data->power_vol, count);
179 if (ret < 0)
180 dev_warn(dev, "Missing bt_power_vol config.\n");
181
182 for (i = 0; i < count; i++) {
183 data->power[i] = regulator_get(dev, data->power_name[i]);
184 if (IS_ERR_OR_NULL(data->power[i]))
185 return -ENOMEM;
186
187 dev_info(dev, "bt power[%d] (%s) voltage: %dmV\n",
188 i, data->power_name[i], data->power_vol[i] / 1000);
189 }
190 }
191
192 count = of_property_count_strings(np, "clock-names");
193 if (count <= 0) {
194 count = CLK_MAX;
195 for (i = 0; i < count; i++) {
196 data->clk[i] = of_clk_get(np, i);
197 if (IS_ERR_OR_NULL(data->clk[i]))
198 break;
199 data->clk_name[i] = devm_kzalloc(dev, 16, GFP_KERNEL);
200 sprintf(data->clk_name[i], "clk%d", i);
201 dev_info(dev, "bt clock[%d] (%s)\n", i, data->clk_name[i]);
202 }
203 } else {
204 if (count > CLK_MAX) {
205 dev_warn(dev, "bt clocks count large than max(%d > %d).\n",
206 count, CLK_MAX);
207 count = CLK_MAX;
208 }
209 ret = of_property_read_string_array(np, "clock-names",
210 (const char **)data->clk_name, count);
211 if (ret < 0)
212 return -ENOMEM;
213
214 for (i = 0; i < count; i++) {
215 data->clk[i] = of_clk_get(np, i);
216 if (IS_ERR_OR_NULL(data->clk[i]))
217 return -ENOMEM;
218 dev_info(dev, "bt clock[%d] (%s)\n", i, data->clk_name[i]);
219 }
220 }
221
222 data->gpio_bt_rst = of_get_named_gpio_flags(np, "bt_rst_n", 0, &config);
223 if (!gpio_is_valid(data->gpio_bt_rst)) {
224 dev_err(dev, "get gpio bt_rst failed\n");
225 } else {
226 data->gpio_bt_rst_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1;
227 dev_info(dev, "bt_rst gpio=%d assert=%d\n", data->gpio_bt_rst, data->gpio_bt_rst_assert);
228
229 ret = devm_gpio_request(dev, data->gpio_bt_rst, "bt_rst");
230 if (ret < 0) {
231 dev_err(dev, "can't request bt_rst gpio %d\n",
232 data->gpio_bt_rst);
233 return ret;
234 }
235
236 ret = gpio_direction_output(data->gpio_bt_rst, data->gpio_bt_rst_assert);
237 if (ret < 0) {
238 dev_err(dev, "can't request output direction bt_rst gpio %d\n",
239 data->gpio_bt_rst);
240 return ret;
241 }
242 }
243
244 data->rfkill = rfkill_alloc("sunxi-bt", dev, RFKILL_TYPE_BLUETOOTH,
245 &sunxi_bt_rfkill_ops, data);
246 if (!data->rfkill)
247 return -ENOMEM;
248
249 rfkill_set_states(data->rfkill, true, false);
250
251 ret = rfkill_register(data->rfkill);
252 if (ret)
253 goto fail_rfkill;
254
255 data->power_state = 0;
256 bluetooth_data = data;
257 return 0;
258
259 fail_rfkill:
260 if (data->rfkill)
261 rfkill_destroy(data->rfkill);
262
263 return ret;
264 }
265
sunxi_bt_deinit(struct platform_device * pdev)266 int sunxi_bt_deinit(struct platform_device *pdev)
267 {
268 struct sunxi_bt_platdata *data = bluetooth_data;
269 struct rfkill *rfk;
270 int i;
271
272 if (!data)
273 return 0;
274
275 rfk = data->rfkill;
276 if (rfk) {
277 rfkill_unregister(rfk);
278 rfkill_destroy(rfk);
279 }
280
281 if (data->power_state)
282 sunxi_bluetooth_set_power(0);
283
284 for (i = 0; i < PWR_MAX; i++) {
285 if (!IS_ERR_OR_NULL(data->power[i]))
286 regulator_put(data->power[i]);
287 }
288
289 bluetooth_data = NULL;
290
291 return 0;
292 }
293
294 static const struct of_device_id sunxi_bt_ids[] = {
295 { .compatible = "allwinner,sunxi-bt" },
296 { /* Sentinel */ }
297 };
298
299 MODULE_DESCRIPTION("sunxi bluetooth driver");
300 MODULE_LICENSE("GPL");
301