1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * |
4 | * Bluetooth support for Broadcom devices |
5 | * |
6 | * Copyright (C) 2015 Intel Corporation |
7 | */ |
8 | |
9 | #include <linux/efi.h> |
10 | #include <linux/module.h> |
11 | #include <linux/firmware.h> |
12 | #include <linux/dmi.h> |
13 | #include <linux/of.h> |
14 | #include <linux/string.h> |
15 | #include <asm/unaligned.h> |
16 | |
17 | #include <net/bluetooth/bluetooth.h> |
18 | #include <net/bluetooth/hci_core.h> |
19 | |
20 | #include "btbcm.h" |
21 | |
22 | #define VERSION "0.1" |
23 | |
24 | #define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) |
25 | #define BDADDR_BCM20702A1 (&(bdaddr_t) {{0x00, 0x00, 0xa0, 0x02, 0x70, 0x20}}) |
26 | #define BDADDR_BCM2076B1 (&(bdaddr_t) {{0x79, 0x56, 0x00, 0xa0, 0x76, 0x20}}) |
27 | #define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}}) |
28 | #define BDADDR_BCM43430A1 (&(bdaddr_t) {{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}}) |
29 | #define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}}) |
30 | #define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}}) |
31 | #define BDADDR_BCM4334B0 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb0, 0x34, 0x43}}) |
32 | #define BDADDR_BCM4345C5 (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0xc5, 0x45, 0x43}}) |
33 | #define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}}) |
34 | |
35 | #define BCM_FW_NAME_LEN 64 |
36 | #define BCM_FW_NAME_COUNT_MAX 4 |
37 | /* For kmalloc-ing the fw-name array instead of putting it on the stack */ |
38 | typedef char bcm_fw_name[BCM_FW_NAME_LEN]; |
39 | |
40 | #ifdef CONFIG_EFI |
41 | static int btbcm_set_bdaddr_from_efi(struct hci_dev *hdev) |
42 | { |
43 | efi_guid_t guid = EFI_GUID(0x74b00bd9, 0x805a, 0x4d61, 0xb5, 0x1f, |
44 | 0x43, 0x26, 0x81, 0x23, 0xd1, 0x13); |
45 | bdaddr_t efi_bdaddr, bdaddr; |
46 | efi_status_t status; |
47 | unsigned long len; |
48 | int ret; |
49 | |
50 | if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) |
51 | return -EOPNOTSUPP; |
52 | |
53 | len = sizeof(efi_bdaddr); |
54 | status = efi.get_variable(L"BDADDR" , &guid, NULL, &len, &efi_bdaddr); |
55 | if (status != EFI_SUCCESS) |
56 | return -ENXIO; |
57 | |
58 | if (len != sizeof(efi_bdaddr)) |
59 | return -EIO; |
60 | |
61 | baswap(dst: &bdaddr, src: &efi_bdaddr); |
62 | |
63 | ret = btbcm_set_bdaddr(hdev, bdaddr: &bdaddr); |
64 | if (ret) |
65 | return ret; |
66 | |
67 | bt_dev_info(hdev, "BCM: Using EFI device address (%pMR)" , &bdaddr); |
68 | return 0; |
69 | } |
70 | #else |
71 | static int btbcm_set_bdaddr_from_efi(struct hci_dev *hdev) |
72 | { |
73 | return -EOPNOTSUPP; |
74 | } |
75 | #endif |
76 | |
77 | int btbcm_check_bdaddr(struct hci_dev *hdev) |
78 | { |
79 | struct hci_rp_read_bd_addr *bda; |
80 | struct sk_buff *skb; |
81 | |
82 | skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, plen: 0, NULL, |
83 | HCI_INIT_TIMEOUT); |
84 | if (IS_ERR(ptr: skb)) { |
85 | int err = PTR_ERR(ptr: skb); |
86 | |
87 | bt_dev_err(hdev, "BCM: Reading device address failed (%d)" , err); |
88 | return err; |
89 | } |
90 | |
91 | if (skb->len != sizeof(*bda)) { |
92 | bt_dev_err(hdev, "BCM: Device address length mismatch" ); |
93 | kfree_skb(skb); |
94 | return -EIO; |
95 | } |
96 | |
97 | bda = (struct hci_rp_read_bd_addr *)skb->data; |
98 | |
99 | /* Check if the address indicates a controller with either an |
100 | * invalid or default address. In both cases the device needs |
101 | * to be marked as not having a valid address. |
102 | * |
103 | * The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller |
104 | * with no configured address. |
105 | * |
106 | * The address 20:70:02:A0:00:00 indicates a BCM20702A1 controller |
107 | * with no configured address. |
108 | * |
109 | * The address 20:76:A0:00:56:79 indicates a BCM2076B1 controller |
110 | * with no configured address. |
111 | * |
112 | * The address 43:24:B3:00:00:00 indicates a BCM4324B3 controller |
113 | * with waiting for configuration state. |
114 | * |
115 | * The address 43:30:B1:00:00:00 indicates a BCM4330B1 controller |
116 | * with waiting for configuration state. |
117 | * |
118 | * The address 43:43:A0:12:1F:AC indicates a BCM43430A0 controller |
119 | * with no configured address. |
120 | * |
121 | * The address AA:AA:AA:AA:AA:AA indicates a BCM43430A1 controller |
122 | * with no configured address. |
123 | */ |
124 | if (!bacmp(ba1: &bda->bdaddr, BDADDR_BCM20702A0) || |
125 | !bacmp(ba1: &bda->bdaddr, BDADDR_BCM20702A1) || |
126 | !bacmp(ba1: &bda->bdaddr, BDADDR_BCM2076B1) || |
127 | !bacmp(ba1: &bda->bdaddr, BDADDR_BCM4324B3) || |
128 | !bacmp(ba1: &bda->bdaddr, BDADDR_BCM4330B1) || |
129 | !bacmp(ba1: &bda->bdaddr, BDADDR_BCM4334B0) || |
130 | !bacmp(ba1: &bda->bdaddr, BDADDR_BCM4345C5) || |
131 | !bacmp(ba1: &bda->bdaddr, BDADDR_BCM43430A0) || |
132 | !bacmp(ba1: &bda->bdaddr, BDADDR_BCM43430A1) || |
133 | !bacmp(ba1: &bda->bdaddr, BDADDR_BCM43341B)) { |
134 | /* Try falling back to BDADDR EFI variable */ |
135 | if (btbcm_set_bdaddr_from_efi(hdev) != 0) { |
136 | bt_dev_info(hdev, "BCM: Using default device address (%pMR)" , |
137 | &bda->bdaddr); |
138 | set_bit(nr: HCI_QUIRK_INVALID_BDADDR, addr: &hdev->quirks); |
139 | } |
140 | } |
141 | |
142 | kfree_skb(skb); |
143 | |
144 | return 0; |
145 | } |
146 | EXPORT_SYMBOL_GPL(btbcm_check_bdaddr); |
147 | |
148 | int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) |
149 | { |
150 | struct sk_buff *skb; |
151 | int err; |
152 | |
153 | skb = __hci_cmd_sync(hdev, opcode: 0xfc01, plen: 6, param: bdaddr, HCI_INIT_TIMEOUT); |
154 | if (IS_ERR(ptr: skb)) { |
155 | err = PTR_ERR(ptr: skb); |
156 | bt_dev_err(hdev, "BCM: Change address command failed (%d)" , err); |
157 | return err; |
158 | } |
159 | kfree_skb(skb); |
160 | |
161 | return 0; |
162 | } |
163 | EXPORT_SYMBOL_GPL(btbcm_set_bdaddr); |
164 | |
165 | int btbcm_read_pcm_int_params(struct hci_dev *hdev, |
166 | struct bcm_set_pcm_int_params *params) |
167 | { |
168 | struct sk_buff *skb; |
169 | int err = 0; |
170 | |
171 | skb = __hci_cmd_sync(hdev, opcode: 0xfc1d, plen: 0, NULL, HCI_INIT_TIMEOUT); |
172 | if (IS_ERR(ptr: skb)) { |
173 | err = PTR_ERR(ptr: skb); |
174 | bt_dev_err(hdev, "BCM: Read PCM int params failed (%d)" , err); |
175 | return err; |
176 | } |
177 | |
178 | if (skb->len != 6 || skb->data[0]) { |
179 | bt_dev_err(hdev, "BCM: Read PCM int params length mismatch" ); |
180 | kfree_skb(skb); |
181 | return -EIO; |
182 | } |
183 | |
184 | if (params) |
185 | memcpy(params, skb->data + 1, 5); |
186 | |
187 | kfree_skb(skb); |
188 | |
189 | return 0; |
190 | } |
191 | EXPORT_SYMBOL_GPL(btbcm_read_pcm_int_params); |
192 | |
193 | int btbcm_write_pcm_int_params(struct hci_dev *hdev, |
194 | const struct bcm_set_pcm_int_params *params) |
195 | { |
196 | struct sk_buff *skb; |
197 | int err; |
198 | |
199 | skb = __hci_cmd_sync(hdev, opcode: 0xfc1c, plen: 5, param: params, HCI_INIT_TIMEOUT); |
200 | if (IS_ERR(ptr: skb)) { |
201 | err = PTR_ERR(ptr: skb); |
202 | bt_dev_err(hdev, "BCM: Write PCM int params failed (%d)" , err); |
203 | return err; |
204 | } |
205 | kfree_skb(skb); |
206 | |
207 | return 0; |
208 | } |
209 | EXPORT_SYMBOL_GPL(btbcm_write_pcm_int_params); |
210 | |
211 | int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw) |
212 | { |
213 | const struct hci_command_hdr *cmd; |
214 | const u8 *fw_ptr; |
215 | size_t fw_size; |
216 | struct sk_buff *skb; |
217 | u16 opcode; |
218 | int err = 0; |
219 | |
220 | /* Start Download */ |
221 | skb = __hci_cmd_sync(hdev, opcode: 0xfc2e, plen: 0, NULL, HCI_INIT_TIMEOUT); |
222 | if (IS_ERR(ptr: skb)) { |
223 | err = PTR_ERR(ptr: skb); |
224 | bt_dev_err(hdev, "BCM: Download Minidrv command failed (%d)" , |
225 | err); |
226 | goto done; |
227 | } |
228 | kfree_skb(skb); |
229 | |
230 | /* 50 msec delay after Download Minidrv completes */ |
231 | msleep(msecs: 50); |
232 | |
233 | fw_ptr = fw->data; |
234 | fw_size = fw->size; |
235 | |
236 | while (fw_size >= sizeof(*cmd)) { |
237 | const u8 *cmd_param; |
238 | |
239 | cmd = (struct hci_command_hdr *)fw_ptr; |
240 | fw_ptr += sizeof(*cmd); |
241 | fw_size -= sizeof(*cmd); |
242 | |
243 | if (fw_size < cmd->plen) { |
244 | bt_dev_err(hdev, "BCM: Patch is corrupted" ); |
245 | err = -EINVAL; |
246 | goto done; |
247 | } |
248 | |
249 | cmd_param = fw_ptr; |
250 | fw_ptr += cmd->plen; |
251 | fw_size -= cmd->plen; |
252 | |
253 | opcode = le16_to_cpu(cmd->opcode); |
254 | |
255 | skb = __hci_cmd_sync(hdev, opcode, plen: cmd->plen, param: cmd_param, |
256 | HCI_INIT_TIMEOUT); |
257 | if (IS_ERR(ptr: skb)) { |
258 | err = PTR_ERR(ptr: skb); |
259 | bt_dev_err(hdev, "BCM: Patch command %04x failed (%d)" , |
260 | opcode, err); |
261 | goto done; |
262 | } |
263 | kfree_skb(skb); |
264 | } |
265 | |
266 | /* 250 msec delay after Launch Ram completes */ |
267 | msleep(msecs: 250); |
268 | |
269 | done: |
270 | return err; |
271 | } |
272 | EXPORT_SYMBOL(btbcm_patchram); |
273 | |
274 | static int btbcm_reset(struct hci_dev *hdev) |
275 | { |
276 | struct sk_buff *skb; |
277 | |
278 | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, plen: 0, NULL, HCI_INIT_TIMEOUT); |
279 | if (IS_ERR(ptr: skb)) { |
280 | int err = PTR_ERR(ptr: skb); |
281 | |
282 | bt_dev_err(hdev, "BCM: Reset failed (%d)" , err); |
283 | return err; |
284 | } |
285 | kfree_skb(skb); |
286 | |
287 | /* 100 msec delay for module to complete reset process */ |
288 | msleep(msecs: 100); |
289 | |
290 | return 0; |
291 | } |
292 | |
293 | static struct sk_buff *btbcm_read_local_name(struct hci_dev *hdev) |
294 | { |
295 | struct sk_buff *skb; |
296 | |
297 | skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_NAME, plen: 0, NULL, |
298 | HCI_INIT_TIMEOUT); |
299 | if (IS_ERR(ptr: skb)) { |
300 | bt_dev_err(hdev, "BCM: Reading local name failed (%ld)" , |
301 | PTR_ERR(skb)); |
302 | return skb; |
303 | } |
304 | |
305 | if (skb->len != sizeof(struct hci_rp_read_local_name)) { |
306 | bt_dev_err(hdev, "BCM: Local name length mismatch" ); |
307 | kfree_skb(skb); |
308 | return ERR_PTR(error: -EIO); |
309 | } |
310 | |
311 | return skb; |
312 | } |
313 | |
314 | static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev) |
315 | { |
316 | struct sk_buff *skb; |
317 | |
318 | skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, plen: 0, NULL, |
319 | HCI_INIT_TIMEOUT); |
320 | if (IS_ERR(ptr: skb)) { |
321 | bt_dev_err(hdev, "BCM: Reading local version info failed (%ld)" , |
322 | PTR_ERR(skb)); |
323 | return skb; |
324 | } |
325 | |
326 | if (skb->len != sizeof(struct hci_rp_read_local_version)) { |
327 | bt_dev_err(hdev, "BCM: Local version length mismatch" ); |
328 | kfree_skb(skb); |
329 | return ERR_PTR(error: -EIO); |
330 | } |
331 | |
332 | return skb; |
333 | } |
334 | |
335 | static struct sk_buff *btbcm_read_verbose_config(struct hci_dev *hdev) |
336 | { |
337 | struct sk_buff *skb; |
338 | |
339 | skb = __hci_cmd_sync(hdev, opcode: 0xfc79, plen: 0, NULL, HCI_INIT_TIMEOUT); |
340 | if (IS_ERR(ptr: skb)) { |
341 | bt_dev_err(hdev, "BCM: Read verbose config info failed (%ld)" , |
342 | PTR_ERR(skb)); |
343 | return skb; |
344 | } |
345 | |
346 | if (skb->len != 7) { |
347 | bt_dev_err(hdev, "BCM: Verbose config length mismatch" ); |
348 | kfree_skb(skb); |
349 | return ERR_PTR(error: -EIO); |
350 | } |
351 | |
352 | return skb; |
353 | } |
354 | |
355 | static struct sk_buff *btbcm_read_controller_features(struct hci_dev *hdev) |
356 | { |
357 | struct sk_buff *skb; |
358 | |
359 | skb = __hci_cmd_sync(hdev, opcode: 0xfc6e, plen: 0, NULL, HCI_INIT_TIMEOUT); |
360 | if (IS_ERR(ptr: skb)) { |
361 | bt_dev_err(hdev, "BCM: Read controller features failed (%ld)" , |
362 | PTR_ERR(skb)); |
363 | return skb; |
364 | } |
365 | |
366 | if (skb->len != 9) { |
367 | bt_dev_err(hdev, "BCM: Controller features length mismatch" ); |
368 | kfree_skb(skb); |
369 | return ERR_PTR(error: -EIO); |
370 | } |
371 | |
372 | return skb; |
373 | } |
374 | |
375 | static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev) |
376 | { |
377 | struct sk_buff *skb; |
378 | |
379 | skb = __hci_cmd_sync(hdev, opcode: 0xfc5a, plen: 0, NULL, HCI_INIT_TIMEOUT); |
380 | if (IS_ERR(ptr: skb)) { |
381 | bt_dev_err(hdev, "BCM: Read USB product info failed (%ld)" , |
382 | PTR_ERR(skb)); |
383 | return skb; |
384 | } |
385 | |
386 | if (skb->len != 5) { |
387 | bt_dev_err(hdev, "BCM: USB product length mismatch" ); |
388 | kfree_skb(skb); |
389 | return ERR_PTR(error: -EIO); |
390 | } |
391 | |
392 | return skb; |
393 | } |
394 | |
395 | static const struct dmi_system_id disable_broken_read_transmit_power[] = { |
396 | { |
397 | .matches = { |
398 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc." ), |
399 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,1" ), |
400 | }, |
401 | }, |
402 | { |
403 | .matches = { |
404 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc." ), |
405 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,2" ), |
406 | }, |
407 | }, |
408 | { |
409 | .matches = { |
410 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc." ), |
411 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,4" ), |
412 | }, |
413 | }, |
414 | { |
415 | .matches = { |
416 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc." ), |
417 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir8,1" ), |
418 | }, |
419 | }, |
420 | { |
421 | .matches = { |
422 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc." ), |
423 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir8,2" ), |
424 | }, |
425 | }, |
426 | { |
427 | .matches = { |
428 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc." ), |
429 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,1" ), |
430 | }, |
431 | }, |
432 | { |
433 | .matches = { |
434 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple Inc." ), |
435 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac20,2" ), |
436 | }, |
437 | }, |
438 | { } |
439 | }; |
440 | |
441 | static int btbcm_read_info(struct hci_dev *hdev) |
442 | { |
443 | struct sk_buff *skb; |
444 | |
445 | /* Read Verbose Config Version Info */ |
446 | skb = btbcm_read_verbose_config(hdev); |
447 | if (IS_ERR(ptr: skb)) |
448 | return PTR_ERR(ptr: skb); |
449 | |
450 | bt_dev_info(hdev, "BCM: chip id %u" , skb->data[1]); |
451 | kfree_skb(skb); |
452 | |
453 | return 0; |
454 | } |
455 | |
456 | static int btbcm_print_controller_features(struct hci_dev *hdev) |
457 | { |
458 | struct sk_buff *skb; |
459 | |
460 | /* Read Controller Features */ |
461 | skb = btbcm_read_controller_features(hdev); |
462 | if (IS_ERR(ptr: skb)) |
463 | return PTR_ERR(ptr: skb); |
464 | |
465 | bt_dev_info(hdev, "BCM: features 0x%2.2x" , skb->data[1]); |
466 | kfree_skb(skb); |
467 | |
468 | /* Read DMI and disable broken Read LE Min/Max Tx Power */ |
469 | if (dmi_first_match(list: disable_broken_read_transmit_power)) |
470 | set_bit(nr: HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, addr: &hdev->quirks); |
471 | |
472 | return 0; |
473 | } |
474 | |
475 | static int btbcm_print_local_name(struct hci_dev *hdev) |
476 | { |
477 | struct sk_buff *skb; |
478 | |
479 | /* Read Local Name */ |
480 | skb = btbcm_read_local_name(hdev); |
481 | if (IS_ERR(ptr: skb)) |
482 | return PTR_ERR(ptr: skb); |
483 | |
484 | bt_dev_info(hdev, "%s" , (char *)(skb->data + 1)); |
485 | kfree_skb(skb); |
486 | |
487 | return 0; |
488 | } |
489 | |
490 | struct bcm_subver_table { |
491 | u16 subver; |
492 | const char *name; |
493 | }; |
494 | |
495 | static const struct bcm_subver_table bcm_uart_subver_table[] = { |
496 | { 0x1111, "BCM4362A2" }, /* 000.017.017 */ |
497 | { 0x4103, "BCM4330B1" }, /* 002.001.003 */ |
498 | { 0x410d, "BCM4334B0" }, /* 002.001.013 */ |
499 | { 0x410e, "BCM43341B0" }, /* 002.001.014 */ |
500 | { 0x4204, "BCM2076B1" }, /* 002.002.004 */ |
501 | { 0x4406, "BCM4324B3" }, /* 002.004.006 */ |
502 | { 0x4606, "BCM4324B5" }, /* 002.006.006 */ |
503 | { 0x6109, "BCM4335C0" }, /* 003.001.009 */ |
504 | { 0x610c, "BCM4354" }, /* 003.001.012 */ |
505 | { 0x2122, "BCM4343A0" }, /* 001.001.034 */ |
506 | { 0x2209, "BCM43430A1" }, /* 001.002.009 */ |
507 | { 0x6119, "BCM4345C0" }, /* 003.001.025 */ |
508 | { 0x6606, "BCM4345C5" }, /* 003.006.006 */ |
509 | { 0x230f, "BCM4356A2" }, /* 001.003.015 */ |
510 | { 0x220e, "BCM20702A1" }, /* 001.002.014 */ |
511 | { 0x420d, "BCM4349B1" }, /* 002.002.013 */ |
512 | { 0x420e, "BCM4349B1" }, /* 002.002.014 */ |
513 | { 0x4217, "BCM4329B1" }, /* 002.002.023 */ |
514 | { 0x6106, "BCM4359C0" }, /* 003.001.006 */ |
515 | { 0x4106, "BCM4335A0" }, /* 002.001.006 */ |
516 | { 0x410c, "BCM43430B0" }, /* 002.001.012 */ |
517 | { 0x2119, "BCM4373A0" }, /* 001.001.025 */ |
518 | { } |
519 | }; |
520 | |
521 | static const struct bcm_subver_table bcm_usb_subver_table[] = { |
522 | { 0x2105, "BCM20703A1" }, /* 001.001.005 */ |
523 | { 0x210b, "BCM43142A0" }, /* 001.001.011 */ |
524 | { 0x2112, "BCM4314A0" }, /* 001.001.018 */ |
525 | { 0x2118, "BCM20702A0" }, /* 001.001.024 */ |
526 | { 0x2126, "BCM4335A0" }, /* 001.001.038 */ |
527 | { 0x220e, "BCM20702A1" }, /* 001.002.014 */ |
528 | { 0x230f, "BCM4356A2" }, /* 001.003.015 */ |
529 | { 0x4106, "BCM4335B0" }, /* 002.001.006 */ |
530 | { 0x410e, "BCM20702B0" }, /* 002.001.014 */ |
531 | { 0x6109, "BCM4335C0" }, /* 003.001.009 */ |
532 | { 0x610c, "BCM4354" }, /* 003.001.012 */ |
533 | { 0x6607, "BCM4350C5" }, /* 003.006.007 */ |
534 | { } |
535 | }; |
536 | |
537 | /* |
538 | * This currently only looks up the device tree board appendix, |
539 | * but can be expanded to other mechanisms. |
540 | */ |
541 | static const char *btbcm_get_board_name(struct device *dev) |
542 | { |
543 | #ifdef CONFIG_OF |
544 | struct device_node *root; |
545 | char *board_type; |
546 | const char *tmp; |
547 | |
548 | root = of_find_node_by_path(path: "/" ); |
549 | if (!root) |
550 | return NULL; |
551 | |
552 | if (of_property_read_string_index(np: root, propname: "compatible" , index: 0, output: &tmp)) |
553 | return NULL; |
554 | |
555 | /* get rid of any '/' in the compatible string */ |
556 | board_type = devm_kstrdup(dev, s: tmp, GFP_KERNEL); |
557 | strreplace(str: board_type, old: '/', new: '-'); |
558 | of_node_put(node: root); |
559 | |
560 | return board_type; |
561 | #else |
562 | return NULL; |
563 | #endif |
564 | } |
565 | |
566 | int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode) |
567 | { |
568 | u16 subver, rev, pid, vid; |
569 | struct sk_buff *skb; |
570 | struct hci_rp_read_local_version *ver; |
571 | const struct bcm_subver_table *bcm_subver_table; |
572 | const char *hw_name = NULL; |
573 | const char *board_name; |
574 | char postfix[16] = "" ; |
575 | int fw_name_count = 0; |
576 | bcm_fw_name *fw_name; |
577 | const struct firmware *fw; |
578 | int i, err; |
579 | |
580 | board_name = btbcm_get_board_name(dev: &hdev->dev); |
581 | |
582 | /* Reset */ |
583 | err = btbcm_reset(hdev); |
584 | if (err) |
585 | return err; |
586 | |
587 | /* Read Local Version Info */ |
588 | skb = btbcm_read_local_version(hdev); |
589 | if (IS_ERR(ptr: skb)) |
590 | return PTR_ERR(ptr: skb); |
591 | |
592 | ver = (struct hci_rp_read_local_version *)skb->data; |
593 | rev = le16_to_cpu(ver->hci_rev); |
594 | subver = le16_to_cpu(ver->lmp_subver); |
595 | kfree_skb(skb); |
596 | |
597 | /* Read controller information */ |
598 | if (!(*fw_load_done)) { |
599 | err = btbcm_read_info(hdev); |
600 | if (err) |
601 | return err; |
602 | } |
603 | |
604 | if (!use_autobaud_mode) { |
605 | err = btbcm_print_controller_features(hdev); |
606 | if (err) |
607 | return err; |
608 | |
609 | err = btbcm_print_local_name(hdev); |
610 | if (err) |
611 | return err; |
612 | } |
613 | |
614 | bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table : |
615 | bcm_uart_subver_table; |
616 | |
617 | for (i = 0; bcm_subver_table[i].name; i++) { |
618 | if (subver == bcm_subver_table[i].subver) { |
619 | hw_name = bcm_subver_table[i].name; |
620 | break; |
621 | } |
622 | } |
623 | |
624 | bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u" , |
625 | hw_name ? hw_name : "BCM" , (subver & 0xe000) >> 13, |
626 | (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); |
627 | |
628 | if (*fw_load_done) |
629 | return 0; |
630 | |
631 | if (hdev->bus == HCI_USB) { |
632 | /* Read USB Product Info */ |
633 | skb = btbcm_read_usb_product(hdev); |
634 | if (IS_ERR(ptr: skb)) |
635 | return PTR_ERR(ptr: skb); |
636 | |
637 | vid = get_unaligned_le16(p: skb->data + 1); |
638 | pid = get_unaligned_le16(p: skb->data + 3); |
639 | kfree_skb(skb); |
640 | |
641 | snprintf(buf: postfix, size: sizeof(postfix), fmt: "-%4.4x-%4.4x" , vid, pid); |
642 | } |
643 | |
644 | fw_name = kmalloc(BCM_FW_NAME_COUNT_MAX * BCM_FW_NAME_LEN, GFP_KERNEL); |
645 | if (!fw_name) |
646 | return -ENOMEM; |
647 | |
648 | if (hw_name) { |
649 | if (board_name) { |
650 | snprintf(buf: fw_name[fw_name_count], BCM_FW_NAME_LEN, |
651 | fmt: "brcm/%s%s.%s.hcd" , hw_name, postfix, board_name); |
652 | fw_name_count++; |
653 | } |
654 | snprintf(buf: fw_name[fw_name_count], BCM_FW_NAME_LEN, |
655 | fmt: "brcm/%s%s.hcd" , hw_name, postfix); |
656 | fw_name_count++; |
657 | } |
658 | |
659 | if (board_name) { |
660 | snprintf(buf: fw_name[fw_name_count], BCM_FW_NAME_LEN, |
661 | fmt: "brcm/BCM%s.%s.hcd" , postfix, board_name); |
662 | fw_name_count++; |
663 | } |
664 | snprintf(buf: fw_name[fw_name_count], BCM_FW_NAME_LEN, |
665 | fmt: "brcm/BCM%s.hcd" , postfix); |
666 | fw_name_count++; |
667 | |
668 | for (i = 0; i < fw_name_count; i++) { |
669 | err = firmware_request_nowarn(fw: &fw, name: fw_name[i], device: &hdev->dev); |
670 | if (err == 0) { |
671 | bt_dev_info(hdev, "%s '%s' Patch" , |
672 | hw_name ? hw_name : "BCM" , fw_name[i]); |
673 | *fw_load_done = true; |
674 | break; |
675 | } |
676 | } |
677 | |
678 | if (*fw_load_done) { |
679 | err = btbcm_patchram(hdev, fw); |
680 | if (err) |
681 | bt_dev_info(hdev, "BCM: Patch failed (%d)" , err); |
682 | |
683 | release_firmware(fw); |
684 | } else { |
685 | bt_dev_err(hdev, "BCM: firmware Patch file not found, tried:" ); |
686 | for (i = 0; i < fw_name_count; i++) |
687 | bt_dev_err(hdev, "BCM: '%s'" , fw_name[i]); |
688 | } |
689 | |
690 | kfree(objp: fw_name); |
691 | return 0; |
692 | } |
693 | EXPORT_SYMBOL_GPL(btbcm_initialize); |
694 | |
695 | int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode) |
696 | { |
697 | int err; |
698 | |
699 | /* Re-initialize if necessary */ |
700 | if (*fw_load_done) { |
701 | err = btbcm_initialize(hdev, fw_load_done, use_autobaud_mode); |
702 | if (err) |
703 | return err; |
704 | } |
705 | |
706 | btbcm_check_bdaddr(hdev); |
707 | |
708 | set_bit(nr: HCI_QUIRK_STRICT_DUPLICATE_FILTER, addr: &hdev->quirks); |
709 | |
710 | return 0; |
711 | } |
712 | EXPORT_SYMBOL_GPL(btbcm_finalize); |
713 | |
714 | int btbcm_setup_patchram(struct hci_dev *hdev) |
715 | { |
716 | bool fw_load_done = false; |
717 | bool use_autobaud_mode = false; |
718 | int err; |
719 | |
720 | /* Initialize */ |
721 | err = btbcm_initialize(hdev, &fw_load_done, use_autobaud_mode); |
722 | if (err) |
723 | return err; |
724 | |
725 | /* Re-initialize after loading Patch */ |
726 | return btbcm_finalize(hdev, &fw_load_done, use_autobaud_mode); |
727 | } |
728 | EXPORT_SYMBOL_GPL(btbcm_setup_patchram); |
729 | |
730 | int btbcm_setup_apple(struct hci_dev *hdev) |
731 | { |
732 | struct sk_buff *skb; |
733 | int err; |
734 | |
735 | /* Reset */ |
736 | err = btbcm_reset(hdev); |
737 | if (err) |
738 | return err; |
739 | |
740 | /* Read Verbose Config Version Info */ |
741 | skb = btbcm_read_verbose_config(hdev); |
742 | if (!IS_ERR(ptr: skb)) { |
743 | bt_dev_info(hdev, "BCM: chip id %u build %4.4u" , |
744 | skb->data[1], get_unaligned_le16(skb->data + 5)); |
745 | kfree_skb(skb); |
746 | } |
747 | |
748 | /* Read USB Product Info */ |
749 | skb = btbcm_read_usb_product(hdev); |
750 | if (!IS_ERR(ptr: skb)) { |
751 | bt_dev_info(hdev, "BCM: product %4.4x:%4.4x" , |
752 | get_unaligned_le16(skb->data + 1), |
753 | get_unaligned_le16(skb->data + 3)); |
754 | kfree_skb(skb); |
755 | } |
756 | |
757 | /* Read Controller Features */ |
758 | skb = btbcm_read_controller_features(hdev); |
759 | if (!IS_ERR(ptr: skb)) { |
760 | bt_dev_info(hdev, "BCM: features 0x%2.2x" , skb->data[1]); |
761 | kfree_skb(skb); |
762 | } |
763 | |
764 | /* Read Local Name */ |
765 | skb = btbcm_read_local_name(hdev); |
766 | if (!IS_ERR(ptr: skb)) { |
767 | bt_dev_info(hdev, "%s" , (char *)(skb->data + 1)); |
768 | kfree_skb(skb); |
769 | } |
770 | |
771 | set_bit(nr: HCI_QUIRK_STRICT_DUPLICATE_FILTER, addr: &hdev->quirks); |
772 | |
773 | return 0; |
774 | } |
775 | EXPORT_SYMBOL_GPL(btbcm_setup_apple); |
776 | |
777 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>" ); |
778 | MODULE_DESCRIPTION("Bluetooth support for Broadcom devices ver " VERSION); |
779 | MODULE_VERSION(VERSION); |
780 | MODULE_LICENSE("GPL" ); |
781 | |