Blame view

drivers/bluetooth/hci_bcm.c 19.5 KB
e9a2dd261   Marcel Holtmann   Bluetooth: hci_ua...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  /*
   *
   *  Bluetooth HCI UART driver for Broadcom devices
   *
   *  Copyright (C) 2015  Intel Corporation
   *
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or
   *  (at your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; if not, write to the Free Software
   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/skbuff.h>
18aeb4445   Frederic Danis   Bluetooth: btbcm:...
27
  #include <linux/firmware.h>
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
28
29
30
31
32
33
  #include <linux/module.h>
  #include <linux/acpi.h>
  #include <linux/platform_device.h>
  #include <linux/clk.h>
  #include <linux/gpio/consumer.h>
  #include <linux/tty.h>
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
34
  #include <linux/interrupt.h>
5cebdfea3   Frederic Danis   Bluetooth: hci_bc...
35
  #include <linux/dmi.h>
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
36
  #include <linux/pm_runtime.h>
e9a2dd261   Marcel Holtmann   Bluetooth: hci_ua...
37
38
39
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
40
  #include "btbcm.h"
e9a2dd261   Marcel Holtmann   Bluetooth: hci_ua...
41
  #include "hci_uart.h"
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
42

94c58132c   Marcel Holtmann   Bluetooth: hci_bc...
43
44
  #define BCM_LM_DIAG_PKT 0x07
  #define BCM_LM_DIAG_SIZE 63
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
45
  #define BCM_AUTOSUSPEND_DELAY	5000 /* default autosleep delay */
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
46
47
48
49
50
51
52
53
54
55
56
  struct bcm_device {
  	struct list_head	list;
  
  	struct platform_device	*pdev;
  
  	const char		*name;
  	struct gpio_desc	*device_wakeup;
  	struct gpio_desc	*shutdown;
  
  	struct clk		*clk;
  	bool			clk_enabled;
ae0569088   Frederic Danis   Bluetooth: hci_bc...
57
58
  
  	u32			init_speed;
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
59
60
  	int			irq;
  	u8			irq_polarity;
118612fb9   Frederic Danis   Bluetooth: hci_bc...
61

b7a622a24   Frederic Danis   Bluetooth: hci_bc...
62
  #ifdef CONFIG_PM
118612fb9   Frederic Danis   Bluetooth: hci_bc...
63
64
65
  	struct hci_uart		*hu;
  	bool			is_suspended; /* suspend/resume flag */
  #endif
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
66
  };
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
67
  struct bcm_data {
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
68
69
70
71
  	struct sk_buff		*rx_skb;
  	struct sk_buff_head	txq;
  
  	struct bcm_device	*dev;
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
72
  };
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
73
  /* List of BCM BT UART devices */
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
74
  static DEFINE_MUTEX(bcm_device_lock);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
75
  static LIST_HEAD(bcm_device_list);
61b2fc2bb   Frederic Danis   Bluetooth: hci_ua...
76
77
78
79
80
81
82
83
84
85
  static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
  {
  	struct hci_dev *hdev = hu->hdev;
  	struct sk_buff *skb;
  	struct bcm_update_uart_baud_rate param;
  
  	if (speed > 3000000) {
  		struct bcm_write_uart_clock_setting clock;
  
  		clock.type = BCM_UART_CLOCK_48MHZ;
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
86
  		bt_dev_dbg(hdev, "Set Controller clock (%d)", clock.type);
61b2fc2bb   Frederic Danis   Bluetooth: hci_ua...
87
88
89
90
91
92
93
  
  		/* This Broadcom specific command changes the UART's controller
  		 * clock for baud rate > 3000000.
  		 */
  		skb = __hci_cmd_sync(hdev, 0xfc45, 1, &clock, HCI_INIT_TIMEOUT);
  		if (IS_ERR(skb)) {
  			int err = PTR_ERR(skb);
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
94
95
  			bt_dev_err(hdev, "BCM: failed to write clock (%d)",
  				   err);
61b2fc2bb   Frederic Danis   Bluetooth: hci_ua...
96
97
98
99
100
  			return err;
  		}
  
  		kfree_skb(skb);
  	}
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
101
  	bt_dev_dbg(hdev, "Set Controller UART speed to %d bit/s", speed);
61b2fc2bb   Frederic Danis   Bluetooth: hci_ua...
102
103
104
105
106
107
108
109
110
111
112
  
  	param.zero = cpu_to_le16(0);
  	param.baud_rate = cpu_to_le32(speed);
  
  	/* This Broadcom specific command changes the UART's controller baud
  	 * rate.
  	 */
  	skb = __hci_cmd_sync(hdev, 0xfc18, sizeof(param), &param,
  			     HCI_INIT_TIMEOUT);
  	if (IS_ERR(skb)) {
  		int err = PTR_ERR(skb);
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
113
114
  		bt_dev_err(hdev, "BCM: failed to write update baudrate (%d)",
  			   err);
61b2fc2bb   Frederic Danis   Bluetooth: hci_ua...
115
116
117
118
119
120
121
  		return err;
  	}
  
  	kfree_skb(skb);
  
  	return 0;
  }
917522aae   Frederic Danis   Bluetooth: hci_bc...
122
  /* bcm_device_exists should be protected by bcm_device_lock */
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  static bool bcm_device_exists(struct bcm_device *device)
  {
  	struct list_head *p;
  
  	list_for_each(p, &bcm_device_list) {
  		struct bcm_device *dev = list_entry(p, struct bcm_device, list);
  
  		if (device == dev)
  			return true;
  	}
  
  	return false;
  }
  
  static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
  {
  	if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled)
  		clk_enable(dev->clk);
2af0a7091   Loic Poulain   Bluetooth: hci_bc...
141
142
  	gpiod_set_value(dev->shutdown, powered);
  	gpiod_set_value(dev->device_wakeup, powered);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
143
144
145
146
147
148
149
150
  
  	if (!powered && !IS_ERR(dev->clk) && dev->clk_enabled)
  		clk_disable(dev->clk);
  
  	dev->clk_enabled = powered;
  
  	return 0;
  }
b7a622a24   Frederic Danis   Bluetooth: hci_bc...
151
  #ifdef CONFIG_PM
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
152
153
154
155
156
  static irqreturn_t bcm_host_wake(int irq, void *data)
  {
  	struct bcm_device *bdev = data;
  
  	bt_dev_dbg(bdev, "Host wake IRQ");
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
157
158
159
  	pm_runtime_get(&bdev->pdev->dev);
  	pm_runtime_mark_last_busy(&bdev->pdev->dev);
  	pm_runtime_put_autosuspend(&bdev->pdev->dev);
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  	return IRQ_HANDLED;
  }
  
  static int bcm_request_irq(struct bcm_data *bcm)
  {
  	struct bcm_device *bdev = bcm->dev;
  	int err = 0;
  
  	/* If this is not a platform device, do not enable PM functionalities */
  	mutex_lock(&bcm_device_lock);
  	if (!bcm_device_exists(bdev)) {
  		err = -ENODEV;
  		goto unlock;
  	}
  
  	if (bdev->irq > 0) {
  		err = devm_request_irq(&bdev->pdev->dev, bdev->irq,
  				       bcm_host_wake, IRQF_TRIGGER_RISING,
  				       "host_wake", bdev);
  		if (err)
  			goto unlock;
  
  		device_init_wakeup(&bdev->pdev->dev, true);
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
183
184
185
186
187
188
  
  		pm_runtime_set_autosuspend_delay(&bdev->pdev->dev,
  						 BCM_AUTOSUSPEND_DELAY);
  		pm_runtime_use_autosuspend(&bdev->pdev->dev);
  		pm_runtime_set_active(&bdev->pdev->dev);
  		pm_runtime_enable(&bdev->pdev->dev);
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  	}
  
  unlock:
  	mutex_unlock(&bcm_device_lock);
  
  	return err;
  }
  
  static const struct bcm_set_sleep_mode default_sleep_params = {
  	.sleep_mode = 1,	/* 0=Disabled, 1=UART, 2=Reserved, 3=USB */
  	.idle_host = 2,		/* idle threshold HOST, in 300ms */
  	.idle_dev = 2,		/* idle threshold device, in 300ms */
  	.bt_wake_active = 1,	/* BT_WAKE active mode: 1 = high, 0 = low */
  	.host_wake_active = 0,	/* HOST_WAKE active mode: 1 = high, 0 = low */
  	.allow_host_sleep = 1,	/* Allow host sleep in SCO flag */
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
204
  	.combine_modes = 1,	/* Combine sleep and LPM flag */
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  	.tristate_control = 0,	/* Allow tri-state control of UART tx flag */
  	/* Irrelevant USB flags */
  	.usb_auto_sleep = 0,
  	.usb_resume_timeout = 0,
  	.pulsed_host_wake = 0,
  	.break_to_host = 0
  };
  
  static int bcm_setup_sleep(struct hci_uart *hu)
  {
  	struct bcm_data *bcm = hu->priv;
  	struct sk_buff *skb;
  	struct bcm_set_sleep_mode sleep_params = default_sleep_params;
  
  	sleep_params.host_wake_active = !bcm->dev->irq_polarity;
  
  	skb = __hci_cmd_sync(hu->hdev, 0xfc27, sizeof(sleep_params),
  			     &sleep_params, HCI_INIT_TIMEOUT);
  	if (IS_ERR(skb)) {
  		int err = PTR_ERR(skb);
  		bt_dev_err(hu->hdev, "Sleep VSC failed (%d)", err);
  		return err;
  	}
  	kfree_skb(skb);
  
  	bt_dev_dbg(hu->hdev, "Set Sleep Parameters VSC succeeded");
  
  	return 0;
  }
  #else
  static inline int bcm_request_irq(struct bcm_data *bcm) { return 0; }
  static inline int bcm_setup_sleep(struct hci_uart *hu) { return 0; }
  #endif
075e1f5e6   Marcel Holtmann   Bluetooth: hci_bc...
238
239
240
241
242
243
244
245
246
247
  static int bcm_set_diag(struct hci_dev *hdev, bool enable)
  {
  	struct hci_uart *hu = hci_get_drvdata(hdev);
  	struct bcm_data *bcm = hu->priv;
  	struct sk_buff *skb;
  
  	if (!test_bit(HCI_RUNNING, &hdev->flags))
  		return -ENETDOWN;
  
  	skb = bt_skb_alloc(3, GFP_KERNEL);
a1857390e   Dan Carpenter   Bluetooth: hci_bc...
248
249
  	if (!skb)
  		return -ENOMEM;
075e1f5e6   Marcel Holtmann   Bluetooth: hci_bc...
250
251
252
253
254
255
256
257
258
259
  
  	*skb_put(skb, 1) = BCM_LM_DIAG_PKT;
  	*skb_put(skb, 1) = 0xf0;
  	*skb_put(skb, 1) = enable;
  
  	skb_queue_tail(&bcm->txq, skb);
  	hci_uart_tx_wakeup(hu);
  
  	return 0;
  }
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
260
261
262
  static int bcm_open(struct hci_uart *hu)
  {
  	struct bcm_data *bcm;
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
263
  	struct list_head *p;
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
264

65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
265
  	bt_dev_dbg(hu->hdev, "hu %p", hu);
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
266
267
268
269
270
271
272
273
  
  	bcm = kzalloc(sizeof(*bcm), GFP_KERNEL);
  	if (!bcm)
  		return -ENOMEM;
  
  	skb_queue_head_init(&bcm->txq);
  
  	hu->priv = bcm;
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
274

bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
275
  	mutex_lock(&bcm_device_lock);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
276
277
278
279
280
281
282
283
284
  	list_for_each(p, &bcm_device_list) {
  		struct bcm_device *dev = list_entry(p, struct bcm_device, list);
  
  		/* Retrieve saved bcm_device based on parent of the
  		 * platform device (saved during device probe) and
  		 * parent of tty device used by hci_uart
  		 */
  		if (hu->tty->dev->parent == dev->pdev->dev.parent) {
  			bcm->dev = dev;
ae0569088   Frederic Danis   Bluetooth: hci_bc...
285
  			hu->init_speed = dev->init_speed;
b7a622a24   Frederic Danis   Bluetooth: hci_bc...
286
  #ifdef CONFIG_PM
118612fb9   Frederic Danis   Bluetooth: hci_bc...
287
288
  			dev->hu = hu;
  #endif
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
289
  			bcm_gpio_set_power(bcm->dev, true);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
290
291
292
  			break;
  		}
  	}
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
293
  	mutex_unlock(&bcm_device_lock);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
294

bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
295
296
297
298
299
300
  	return 0;
  }
  
  static int bcm_close(struct hci_uart *hu)
  {
  	struct bcm_data *bcm = hu->priv;
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
301
  	struct bcm_device *bdev = bcm->dev;
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
302

65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
303
  	bt_dev_dbg(hu->hdev, "hu %p", hu);
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
304

0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
305
  	/* Protect bcm->dev against removal of the device or driver */
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
306
  	mutex_lock(&bcm_device_lock);
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
307
308
  	if (bcm_device_exists(bdev)) {
  		bcm_gpio_set_power(bdev, false);
b7a622a24   Frederic Danis   Bluetooth: hci_bc...
309
  #ifdef CONFIG_PM
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
310
311
  		pm_runtime_disable(&bdev->pdev->dev);
  		pm_runtime_set_suspended(&bdev->pdev->dev);
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
312
313
314
315
316
317
  		if (device_can_wakeup(&bdev->pdev->dev)) {
  			devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev);
  			device_init_wakeup(&bdev->pdev->dev, false);
  		}
  
  		bdev->hu = NULL;
118612fb9   Frederic Danis   Bluetooth: hci_bc...
318
319
  #endif
  	}
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
320
  	mutex_unlock(&bcm_device_lock);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
321

bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
322
323
324
325
326
327
328
329
330
331
332
  	skb_queue_purge(&bcm->txq);
  	kfree_skb(bcm->rx_skb);
  	kfree(bcm);
  
  	hu->priv = NULL;
  	return 0;
  }
  
  static int bcm_flush(struct hci_uart *hu)
  {
  	struct bcm_data *bcm = hu->priv;
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
333
  	bt_dev_dbg(hu->hdev, "hu %p", hu);
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
334
335
336
337
338
339
340
341
  
  	skb_queue_purge(&bcm->txq);
  
  	return 0;
  }
  
  static int bcm_setup(struct hci_uart *hu)
  {
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
342
  	struct bcm_data *bcm = hu->priv;
6be09b48a   Frederic Danis   Bluetooth: hci_ua...
343
344
  	char fw_name[64];
  	const struct firmware *fw;
960ef1d72   Frederic Danis   Bluetooth: hci_ua...
345
  	unsigned int speed;
6be09b48a   Frederic Danis   Bluetooth: hci_ua...
346
  	int err;
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
347
  	bt_dev_dbg(hu->hdev, "hu %p", hu);
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
348

075e1f5e6   Marcel Holtmann   Bluetooth: hci_bc...
349
  	hu->hdev->set_diag = bcm_set_diag;
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
350
  	hu->hdev->set_bdaddr = btbcm_set_bdaddr;
6be09b48a   Frederic Danis   Bluetooth: hci_ua...
351
352
353
354
355
356
  	err = btbcm_initialize(hu->hdev, fw_name, sizeof(fw_name));
  	if (err)
  		return err;
  
  	err = request_firmware(&fw, fw_name, &hu->hdev->dev);
  	if (err < 0) {
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
357
  		bt_dev_info(hu->hdev, "BCM: Patch %s not found", fw_name);
6be09b48a   Frederic Danis   Bluetooth: hci_ua...
358
359
360
361
362
  		return 0;
  	}
  
  	err = btbcm_patchram(hu->hdev, fw);
  	if (err) {
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
363
  		bt_dev_info(hu->hdev, "BCM: Patch failed (%d)", err);
6be09b48a   Frederic Danis   Bluetooth: hci_ua...
364
365
  		goto finalize;
  	}
960ef1d72   Frederic Danis   Bluetooth: hci_ua...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  	/* Init speed if any */
  	if (hu->init_speed)
  		speed = hu->init_speed;
  	else if (hu->proto->init_speed)
  		speed = hu->proto->init_speed;
  	else
  		speed = 0;
  
  	if (speed)
  		hci_uart_set_baudrate(hu, speed);
  
  	/* Operational speed if any */
  	if (hu->oper_speed)
  		speed = hu->oper_speed;
  	else if (hu->proto->oper_speed)
  		speed = hu->proto->oper_speed;
  	else
  		speed = 0;
  
  	if (speed) {
  		err = bcm_set_baudrate(hu, speed);
61b2fc2bb   Frederic Danis   Bluetooth: hci_ua...
387
  		if (!err)
960ef1d72   Frederic Danis   Bluetooth: hci_ua...
388
  			hci_uart_set_baudrate(hu, speed);
61b2fc2bb   Frederic Danis   Bluetooth: hci_ua...
389
  	}
6be09b48a   Frederic Danis   Bluetooth: hci_ua...
390
391
392
393
  finalize:
  	release_firmware(fw);
  
  	err = btbcm_finalize(hu->hdev);
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
394
395
396
397
398
399
  	if (err)
  		return err;
  
  	err = bcm_request_irq(bcm);
  	if (!err)
  		err = bcm_setup_sleep(hu);
6be09b48a   Frederic Danis   Bluetooth: hci_ua...
400
401
  
  	return err;
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
402
  }
94c58132c   Marcel Holtmann   Bluetooth: hci_bc...
403
404
405
406
407
408
  #define BCM_RECV_LM_DIAG \
  	.type = BCM_LM_DIAG_PKT, \
  	.hlen = BCM_LM_DIAG_SIZE, \
  	.loff = 0, \
  	.lsize = 0, \
  	.maxlen = BCM_LM_DIAG_SIZE
79b8df936   Marcel Holtmann   Bluetooth: hci_ua...
409
  static const struct h4_recv_pkt bcm_recv_pkts[] = {
94c58132c   Marcel Holtmann   Bluetooth: hci_bc...
410
411
412
413
  	{ H4_RECV_ACL,      .recv = hci_recv_frame },
  	{ H4_RECV_SCO,      .recv = hci_recv_frame },
  	{ H4_RECV_EVENT,    .recv = hci_recv_frame },
  	{ BCM_RECV_LM_DIAG, .recv = hci_recv_diag  },
79b8df936   Marcel Holtmann   Bluetooth: hci_ua...
414
  };
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
415
416
417
418
419
420
  static int bcm_recv(struct hci_uart *hu, const void *data, int count)
  {
  	struct bcm_data *bcm = hu->priv;
  
  	if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
  		return -EUNATCH;
79b8df936   Marcel Holtmann   Bluetooth: hci_ua...
421
422
  	bcm->rx_skb = h4_recv_buf(hu->hdev, bcm->rx_skb, data, count,
  				  bcm_recv_pkts, ARRAY_SIZE(bcm_recv_pkts));
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
423
424
  	if (IS_ERR(bcm->rx_skb)) {
  		int err = PTR_ERR(bcm->rx_skb);
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
425
  		bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
371341676   Chan-yeol Park   Bluetooth: hci_ua...
426
  		bcm->rx_skb = NULL;
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
427
  		return err;
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
428
429
430
431
432
433
434
435
436
  	} else if (!bcm->rx_skb) {
  		/* Delay auto-suspend when receiving completed packet */
  		mutex_lock(&bcm_device_lock);
  		if (bcm->dev && bcm_device_exists(bcm->dev)) {
  			pm_runtime_get(&bcm->dev->pdev->dev);
  			pm_runtime_mark_last_busy(&bcm->dev->pdev->dev);
  			pm_runtime_put_autosuspend(&bcm->dev->pdev->dev);
  		}
  		mutex_unlock(&bcm_device_lock);
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
437
438
439
440
441
442
443
444
  	}
  
  	return count;
  }
  
  static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
  {
  	struct bcm_data *bcm = hu->priv;
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
445
  	bt_dev_dbg(hu->hdev, "hu %p skb %p", hu, skb);
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
446
447
  
  	/* Prepend skb with frame type */
618e8bc22   Marcel Holtmann   Bluetooth: Use ne...
448
  	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
449
450
451
452
453
454
455
456
  	skb_queue_tail(&bcm->txq, skb);
  
  	return 0;
  }
  
  static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
  {
  	struct bcm_data *bcm = hu->priv;
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  	struct sk_buff *skb = NULL;
  	struct bcm_device *bdev = NULL;
  
  	mutex_lock(&bcm_device_lock);
  
  	if (bcm_device_exists(bcm->dev)) {
  		bdev = bcm->dev;
  		pm_runtime_get_sync(&bdev->pdev->dev);
  		/* Shall be resumed here */
  	}
  
  	skb = skb_dequeue(&bcm->txq);
  
  	if (bdev) {
  		pm_runtime_mark_last_busy(&bdev->pdev->dev);
  		pm_runtime_put_autosuspend(&bdev->pdev->dev);
  	}
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
474

e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
475
476
477
  	mutex_unlock(&bcm_device_lock);
  
  	return skb;
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
478
  }
b7a622a24   Frederic Danis   Bluetooth: hci_bc...
479
480
  #ifdef CONFIG_PM
  static int bcm_suspend_device(struct device *dev)
118612fb9   Frederic Danis   Bluetooth: hci_bc...
481
482
  {
  	struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
b7a622a24   Frederic Danis   Bluetooth: hci_bc...
483
  	bt_dev_dbg(bdev, "");
917522aae   Frederic Danis   Bluetooth: hci_bc...
484

b7a622a24   Frederic Danis   Bluetooth: hci_bc...
485
  	if (!bdev->is_suspended && bdev->hu) {
118612fb9   Frederic Danis   Bluetooth: hci_bc...
486
  		hci_uart_set_flow_control(bdev->hu, true);
b7a622a24   Frederic Danis   Bluetooth: hci_bc...
487
  		/* Once this returns, driver suspends BT via GPIO */
118612fb9   Frederic Danis   Bluetooth: hci_bc...
488
489
490
491
492
493
  		bdev->is_suspended = true;
  	}
  
  	/* Suspend the device */
  	if (bdev->device_wakeup) {
  		gpiod_set_value(bdev->device_wakeup, false);
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
494
  		bt_dev_dbg(bdev, "suspend, delaying 15 ms");
118612fb9   Frederic Danis   Bluetooth: hci_bc...
495
496
  		mdelay(15);
  	}
b7a622a24   Frederic Danis   Bluetooth: hci_bc...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
  	return 0;
  }
  
  static int bcm_resume_device(struct device *dev)
  {
  	struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
  
  	bt_dev_dbg(bdev, "");
  
  	if (bdev->device_wakeup) {
  		gpiod_set_value(bdev->device_wakeup, true);
  		bt_dev_dbg(bdev, "resume, delaying 15 ms");
  		mdelay(15);
  	}
  
  	/* When this executes, the device has woken up already */
  	if (bdev->is_suspended && bdev->hu) {
  		bdev->is_suspended = false;
  
  		hci_uart_set_flow_control(bdev->hu, false);
  	}
  
  	return 0;
  }
  #endif
  
  #ifdef CONFIG_PM_SLEEP
  /* Platform suspend callback */
  static int bcm_suspend(struct device *dev)
  {
  	struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
  	int error;
  
  	bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
  
  	/* bcm_suspend can be called at any time as long as platform device is
  	 * bound, so it should use bcm_device_lock to protect access to hci_uart
  	 * and device_wake-up GPIO.
  	 */
  	mutex_lock(&bcm_device_lock);
  
  	if (!bdev->hu)
  		goto unlock;
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
540
541
  	if (pm_runtime_active(dev))
  		bcm_suspend_device(dev);
b7a622a24   Frederic Danis   Bluetooth: hci_bc...
542

6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
543
544
545
546
547
  	if (device_may_wakeup(&bdev->pdev->dev)) {
  		error = enable_irq_wake(bdev->irq);
  		if (!error)
  			bt_dev_dbg(bdev, "BCM irq: enabled");
  	}
917522aae   Frederic Danis   Bluetooth: hci_bc...
548
  unlock:
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
549
  	mutex_unlock(&bcm_device_lock);
917522aae   Frederic Danis   Bluetooth: hci_bc...
550

118612fb9   Frederic Danis   Bluetooth: hci_bc...
551
552
553
554
555
556
557
  	return 0;
  }
  
  /* Platform resume callback */
  static int bcm_resume(struct device *dev)
  {
  	struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
65ad07c9e   Frederic Danis   Bluetooth: hci_bc...
558
  	bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
118612fb9   Frederic Danis   Bluetooth: hci_bc...
559

b7a622a24   Frederic Danis   Bluetooth: hci_bc...
560
561
562
563
  	/* bcm_resume can be called at any time as long as platform device is
  	 * bound, so it should use bcm_device_lock to protect access to hci_uart
  	 * and device_wake-up GPIO.
  	 */
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
564
  	mutex_lock(&bcm_device_lock);
917522aae   Frederic Danis   Bluetooth: hci_bc...
565
566
567
  
  	if (!bdev->hu)
  		goto unlock;
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
568
569
570
571
  	if (device_may_wakeup(&bdev->pdev->dev)) {
  		disable_irq_wake(bdev->irq);
  		bt_dev_dbg(bdev, "BCM irq: disabled");
  	}
b7a622a24   Frederic Danis   Bluetooth: hci_bc...
572
  	bcm_resume_device(dev);
118612fb9   Frederic Danis   Bluetooth: hci_bc...
573

917522aae   Frederic Danis   Bluetooth: hci_bc...
574
  unlock:
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
575
  	mutex_unlock(&bcm_device_lock);
917522aae   Frederic Danis   Bluetooth: hci_bc...
576

e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
577
578
579
  	pm_runtime_disable(dev);
  	pm_runtime_set_active(dev);
  	pm_runtime_enable(dev);
118612fb9   Frederic Danis   Bluetooth: hci_bc...
580
581
582
  	return 0;
  }
  #endif
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
583
584
  static const struct acpi_gpio_params device_wakeup_gpios = { 0, 0, false };
  static const struct acpi_gpio_params shutdown_gpios = { 1, 0, false };
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
585
  static const struct acpi_gpio_params host_wakeup_gpios = { 2, 0, false };
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
586
587
588
589
  
  static const struct acpi_gpio_mapping acpi_bcm_default_gpios[] = {
  	{ "device-wakeup-gpios", &device_wakeup_gpios, 1 },
  	{ "shutdown-gpios", &shutdown_gpios, 1 },
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
590
  	{ "host-wakeup-gpios", &host_wakeup_gpios, 1 },
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
591
592
  	{ },
  };
50d78bcf5   Frederic Danis   Bluetooth: hci_bc...
593
  #ifdef CONFIG_ACPI
5cebdfea3   Frederic Danis   Bluetooth: hci_bc...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
  static u8 acpi_active_low = ACPI_ACTIVE_LOW;
  
  /* IRQ polarity of some chipsets are not defined correctly in ACPI table. */
  static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = {
  	{
  		.ident = "Asus T100TA",
  		.matches = {
  			DMI_EXACT_MATCH(DMI_SYS_VENDOR,
  					"ASUSTeK COMPUTER INC."),
  			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
  		},
  		.driver_data = &acpi_active_low,
  	},
  	{ }
  };
ae0569088   Frederic Danis   Bluetooth: hci_bc...
609
610
611
  static int bcm_resource(struct acpi_resource *ares, void *data)
  {
  	struct bcm_device *dev = data;
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
  	struct acpi_resource_extended_irq *irq;
  	struct acpi_resource_gpio *gpio;
  	struct acpi_resource_uart_serialbus *sb;
  
  	switch (ares->type) {
  	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
  		irq = &ares->data.extended_irq;
  		dev->irq_polarity = irq->polarity;
  		break;
  
  	case ACPI_RESOURCE_TYPE_GPIO:
  		gpio = &ares->data.gpio;
  		if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
  			dev->irq_polarity = gpio->polarity;
  		break;
  
  	case ACPI_RESOURCE_TYPE_SERIAL_BUS:
ae0569088   Frederic Danis   Bluetooth: hci_bc...
629
630
631
  		sb = &ares->data.uart_serial_bus;
  		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART)
  			dev->init_speed = sb->default_baud_rate;
6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
632
633
634
635
  		break;
  
  	default:
  		break;
ae0569088   Frederic Danis   Bluetooth: hci_bc...
636
637
638
639
640
  	}
  
  	/* Always tell the ACPI core to skip this resource */
  	return 1;
  }
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
641
642
643
  static int bcm_acpi_probe(struct bcm_device *dev)
  {
  	struct platform_device *pdev = dev->pdev;
ae0569088   Frederic Danis   Bluetooth: hci_bc...
644
  	LIST_HEAD(resources);
5cebdfea3   Frederic Danis   Bluetooth: hci_bc...
645
  	const struct dmi_system_id *dmi_id;
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
646
  	int ret;
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
647
648
649
650
651
652
653
654
  	/* Retrieve GPIO data */
  	dev->name = dev_name(&pdev->dev);
  	ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
  					acpi_bcm_default_gpios);
  	if (ret)
  		return ret;
  
  	dev->clk = devm_clk_get(&pdev->dev, NULL);
62aaefa7d   Uwe Kleine-König   Bluetooth: hci_bc...
655
656
657
658
659
  	dev->device_wakeup = devm_gpiod_get_optional(&pdev->dev,
  						     "device-wakeup",
  						     GPIOD_OUT_LOW);
  	if (IS_ERR(dev->device_wakeup))
  		return PTR_ERR(dev->device_wakeup);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
660

62aaefa7d   Uwe Kleine-König   Bluetooth: hci_bc...
661
662
663
664
  	dev->shutdown = devm_gpiod_get_optional(&pdev->dev, "shutdown",
  						GPIOD_OUT_LOW);
  	if (IS_ERR(dev->shutdown))
  		return PTR_ERR(dev->shutdown);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
665

6cc4396c8   Frederic Danis   Bluetooth: hci_bc...
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
  	/* IRQ can be declared in ACPI table as Interrupt or GpioInt */
  	dev->irq = platform_get_irq(pdev, 0);
  	if (dev->irq <= 0) {
  		struct gpio_desc *gpio;
  
  		gpio = devm_gpiod_get_optional(&pdev->dev, "host-wakeup",
  					       GPIOD_IN);
  		if (IS_ERR(gpio))
  			return PTR_ERR(gpio);
  
  		dev->irq = gpiod_to_irq(gpio);
  	}
  
  	dev_info(&pdev->dev, "BCM irq: %d
  ", dev->irq);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
681
682
683
684
685
686
687
688
  	/* Make sure at-least one of the GPIO is defined and that
  	 * a name is specified for this instance
  	 */
  	if ((!dev->device_wakeup && !dev->shutdown) || !dev->name) {
  		dev_err(&pdev->dev, "invalid platform data
  ");
  		return -EINVAL;
  	}
ae0569088   Frederic Danis   Bluetooth: hci_bc...
689
  	/* Retrieve UART ACPI info */
e98d6d620   Jarkko Nikula   Bluetooth: hci_bc...
690
691
  	ret = acpi_dev_get_resources(ACPI_COMPANION(&dev->pdev->dev),
  				     &resources, bcm_resource, dev);
5be00284d   Jarkko Nikula   Bluetooth: hci_bc...
692
693
  	if (ret < 0)
  		return ret;
09dbf1b78   Jarkko Nikula   Bluetooth: hci_bc...
694
  	acpi_dev_free_resource_list(&resources);
ae0569088   Frederic Danis   Bluetooth: hci_bc...
695

5cebdfea3   Frederic Danis   Bluetooth: hci_bc...
696
697
698
699
700
701
  	dmi_id = dmi_first_match(bcm_wrong_irq_dmi_table);
  	if (dmi_id) {
  		bt_dev_warn(dev, "%s: Overwriting IRQ polarity to active low",
  			    dmi_id->ident);
  		dev->irq_polarity = *(u8 *)dmi_id->driver_data;
  	}
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
702
703
  	return 0;
  }
50d78bcf5   Frederic Danis   Bluetooth: hci_bc...
704
705
706
707
708
709
  #else
  static int bcm_acpi_probe(struct bcm_device *dev)
  {
  	return -EINVAL;
  }
  #endif /* CONFIG_ACPI */
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
710
711
712
713
  
  static int bcm_probe(struct platform_device *pdev)
  {
  	struct bcm_device *dev;
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
714
715
716
717
718
719
720
  	int ret;
  
  	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
  	if (!dev)
  		return -ENOMEM;
  
  	dev->pdev = pdev;
4d1c45580   Jarkko Nikula   Bluetooth: hci_bc...
721
722
723
  	ret = bcm_acpi_probe(dev);
  	if (ret)
  		return ret;
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
724
725
726
727
728
729
730
  
  	platform_set_drvdata(pdev, dev);
  
  	dev_info(&pdev->dev, "%s device registered.
  ", dev->name);
  
  	/* Place this instance on the device list */
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
731
  	mutex_lock(&bcm_device_lock);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
732
  	list_add_tail(&dev->list, &bcm_device_list);
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
733
  	mutex_unlock(&bcm_device_lock);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
734
735
736
737
738
739
740
741
742
  
  	bcm_gpio_set_power(dev, false);
  
  	return 0;
  }
  
  static int bcm_remove(struct platform_device *pdev)
  {
  	struct bcm_device *dev = platform_get_drvdata(pdev);
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
743
  	mutex_lock(&bcm_device_lock);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
744
  	list_del(&dev->list);
bb3ea16a4   Frederic Danis   Bluetooth: hci_bc...
745
  	mutex_unlock(&bcm_device_lock);
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
746
747
748
749
750
751
752
753
  
  	acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev));
  
  	dev_info(&pdev->dev, "%s device unregistered.
  ", dev->name);
  
  	return 0;
  }
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
754
755
756
  static const struct hci_uart_proto bcm_proto = {
  	.id		= HCI_UART_BCM,
  	.name		= "BCM",
aee61f7aa   Marcel Holtmann   Bluetooth: hci_ua...
757
  	.manufacturer	= 15,
61b2fc2bb   Frederic Danis   Bluetooth: hci_ua...
758
759
  	.init_speed	= 115200,
  	.oper_speed	= 4000000,
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
760
761
762
763
  	.open		= bcm_open,
  	.close		= bcm_close,
  	.flush		= bcm_flush,
  	.setup		= bcm_setup,
61b2fc2bb   Frederic Danis   Bluetooth: hci_ua...
764
  	.set_baudrate	= bcm_set_baudrate,
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
765
766
767
768
  	.recv		= bcm_recv,
  	.enqueue	= bcm_enqueue,
  	.dequeue	= bcm_dequeue,
  };
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
769
770
  #ifdef CONFIG_ACPI
  static const struct acpi_device_id bcm_acpi_match[] = {
d3d207254   Heikki Krogerus   Bluetooth: hci_bc...
771
  	{ "BCM2E1A", 0 },
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
772
  	{ "BCM2E39", 0 },
adbdeae5c   Heikki Krogerus   Bluetooth: hci_bc...
773
  	{ "BCM2E3A", 0 },
d3d207254   Heikki Krogerus   Bluetooth: hci_bc...
774
  	{ "BCM2E3D", 0 },
adbdeae5c   Heikki Krogerus   Bluetooth: hci_bc...
775
  	{ "BCM2E3F", 0 },
d3d207254   Heikki Krogerus   Bluetooth: hci_bc...
776
777
  	{ "BCM2E40", 0 },
  	{ "BCM2E64", 0 },
806f50c72   Luka Karinja   Bluetooth: hci_bc...
778
  	{ "BCM2E65", 0 },
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
779
  	{ "BCM2E67", 0 },
adbdeae5c   Heikki Krogerus   Bluetooth: hci_bc...
780
  	{ "BCM2E7B", 0 },
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
781
782
783
784
  	{ },
  };
  MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);
  #endif
118612fb9   Frederic Danis   Bluetooth: hci_bc...
785
  /* Platform suspend and resume callbacks */
e88ab30d3   Frederic Danis   Bluetooth: hci_bc...
786
787
788
789
  static const struct dev_pm_ops bcm_pm_ops = {
  	SET_SYSTEM_SLEEP_PM_OPS(bcm_suspend, bcm_resume)
  	SET_RUNTIME_PM_OPS(bcm_suspend_device, bcm_resume_device, NULL)
  };
118612fb9   Frederic Danis   Bluetooth: hci_bc...
790

0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
791
792
793
794
795
796
  static struct platform_driver bcm_driver = {
  	.probe = bcm_probe,
  	.remove = bcm_remove,
  	.driver = {
  		.name = "hci_bcm",
  		.acpi_match_table = ACPI_PTR(bcm_acpi_match),
118612fb9   Frederic Danis   Bluetooth: hci_bc...
797
  		.pm = &bcm_pm_ops,
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
798
799
  	},
  };
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
800
801
  int __init bcm_init(void)
  {
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
802
  	platform_driver_register(&bcm_driver);
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
803
804
805
806
807
  	return hci_uart_register_proto(&bcm_proto);
  }
  
  int __exit bcm_deinit(void)
  {
0395ffc1e   Frederic Danis   Bluetooth: hci_bc...
808
  	platform_driver_unregister(&bcm_driver);
bdd8818e0   Marcel Holtmann   Bluetooth: hci_ua...
809
810
  	return hci_uart_unregister_proto(&bcm_proto);
  }