aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2015-04-06 01:52:14 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-04-07 12:47:11 -0400
commitc2bfb10092ece07f9e9cf5096cfeec0ef92a97c5 (patch)
treef139dd133baf45e16ab84ea8d2104b74a922725f /drivers/bluetooth
parent1c8ba6d013c553bd13c50c139d652daac3348685 (diff)
Bluetooth: btusb: Add option for Broadcom protocol support
With the generic Broadcom Bluetooth support module, it is possible to turn support for firmware and patchram download into an optional feature. To keep backwards compatibility with previous kernel configurations, the new option defaults to enabled. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/Kconfig12
-rw-r--r--drivers/bluetooth/btusb.c211
2 files changed, 15 insertions, 208 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 0801649a3b41..ea76031eb93f 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -9,7 +9,6 @@ config BT_BCM
9config BT_HCIBTUSB 9config BT_HCIBTUSB
10 tristate "HCI USB driver" 10 tristate "HCI USB driver"
11 depends on USB 11 depends on USB
12 select BT_BCM
13 help 12 help
14 Bluetooth HCI USB driver. 13 Bluetooth HCI USB driver.
15 This driver is required if you want to use Bluetooth devices with 14 This driver is required if you want to use Bluetooth devices with
@@ -18,6 +17,17 @@ config BT_HCIBTUSB
18 Say Y here to compile support for Bluetooth USB devices into the 17 Say Y here to compile support for Bluetooth USB devices into the
19 kernel or say M to compile it as module (btusb). 18 kernel or say M to compile it as module (btusb).
20 19
20config BT_HCIBTUSB_BCM
21 bool "Broadcom protocol support"
22 depends on BT_HCIBTUSB
23 select BT_BCM
24 default y
25 help
26 The Broadcom protocol support enables firmware and patchram
27 download support for Broadcom Bluetooth controllers.
28
29 Say Y here to compile support for Broadcom protocol.
30
21config BT_HCIBTSDIO 31config BT_HCIBTSDIO
22 tristate "HCI SDIO driver" 32 tristate "HCI SDIO driver"
23 depends on MMC 33 depends on MMC
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 08561ad7a638..53275c55c782 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -24,7 +24,6 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/usb.h> 25#include <linux/usb.h>
26#include <linux/firmware.h> 26#include <linux/firmware.h>
27#include <asm/unaligned.h>
28 27
29#include <net/bluetooth/bluetooth.h> 28#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h> 29#include <net/bluetooth/hci_core.h>
@@ -2403,210 +2402,6 @@ static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
2403 return 0; 2402 return 0;
2404} 2403}
2405 2404
2406static const struct {
2407 u16 subver;
2408 const char *name;
2409} bcm_subver_table[] = {
2410 { 0x210b, "BCM43142A0" }, /* 001.001.011 */
2411 { 0x2112, "BCM4314A0" }, /* 001.001.018 */
2412 { 0x2118, "BCM20702A0" }, /* 001.001.024 */
2413 { 0x2126, "BCM4335A0" }, /* 001.001.038 */
2414 { 0x220e, "BCM20702A1" }, /* 001.002.014 */
2415 { 0x230f, "BCM4354A2" }, /* 001.003.015 */
2416 { 0x4106, "BCM4335B0" }, /* 002.001.006 */
2417 { 0x410e, "BCM20702B0" }, /* 002.001.014 */
2418 { 0x6109, "BCM4335C0" }, /* 003.001.009 */
2419 { 0x610c, "BCM4354" }, /* 003.001.012 */
2420 { }
2421};
2422
2423static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
2424{
2425 struct btusb_data *data = hci_get_drvdata(hdev);
2426 struct usb_device *udev = data->udev;
2427 char fw_name[64];
2428 const struct firmware *fw;
2429 const u8 *fw_ptr;
2430 size_t fw_size;
2431 const struct hci_command_hdr *cmd;
2432 const u8 *cmd_param;
2433 u16 opcode, subver, rev;
2434 const char *hw_name = NULL;
2435 struct sk_buff *skb;
2436 struct hci_rp_read_local_version *ver;
2437 long ret;
2438 int i;
2439
2440 /* Reset */
2441 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
2442 if (IS_ERR(skb)) {
2443 ret = PTR_ERR(skb);
2444 BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret);
2445 return ret;
2446 }
2447 kfree_skb(skb);
2448
2449 /* Read Local Version Info */
2450 skb = btusb_read_local_version(hdev);
2451 if (IS_ERR(skb))
2452 return PTR_ERR(skb);
2453
2454 ver = (struct hci_rp_read_local_version *)skb->data;
2455 rev = le16_to_cpu(ver->hci_rev);
2456 subver = le16_to_cpu(ver->lmp_subver);
2457 kfree_skb(skb);
2458
2459 /* Read Verbose Config Version Info */
2460 skb = __hci_cmd_sync(hdev, 0xfc79, 0, NULL, HCI_INIT_TIMEOUT);
2461 if (IS_ERR(skb)) {
2462 ret = PTR_ERR(skb);
2463 BT_ERR("%s: BCM: Read Verbose Version failed (%ld)",
2464 hdev->name, ret);
2465 return ret;
2466 }
2467
2468 if (skb->len != 7) {
2469 BT_ERR("%s: BCM: Read Verbose Version event length mismatch",
2470 hdev->name);
2471 kfree_skb(skb);
2472 return -EIO;
2473 }
2474
2475 BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
2476 kfree_skb(skb);
2477
2478 for (i = 0; bcm_subver_table[i].name; i++) {
2479 if (subver == bcm_subver_table[i].subver) {
2480 hw_name = bcm_subver_table[i].name;
2481 break;
2482 }
2483 }
2484
2485 BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
2486 hw_name ? : "BCM", (subver & 0x7000) >> 13,
2487 (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
2488
2489 snprintf(fw_name, sizeof(fw_name), "brcm/%s-%4.4x-%4.4x.hcd",
2490 hw_name ? : "BCM",
2491 le16_to_cpu(udev->descriptor.idVendor),
2492 le16_to_cpu(udev->descriptor.idProduct));
2493
2494 ret = request_firmware(&fw, fw_name, &hdev->dev);
2495 if (ret < 0) {
2496 BT_INFO("%s: BCM: patch %s not found", hdev->name, fw_name);
2497 return 0;
2498 }
2499
2500 /* Start Download */
2501 skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT);
2502 if (IS_ERR(skb)) {
2503 ret = PTR_ERR(skb);
2504 BT_ERR("%s: BCM: Download Minidrv command failed (%ld)",
2505 hdev->name, ret);
2506 goto reset_fw;
2507 }
2508 kfree_skb(skb);
2509
2510 /* 50 msec delay after Download Minidrv completes */
2511 msleep(50);
2512
2513 fw_ptr = fw->data;
2514 fw_size = fw->size;
2515
2516 while (fw_size >= sizeof(*cmd)) {
2517 cmd = (struct hci_command_hdr *)fw_ptr;
2518 fw_ptr += sizeof(*cmd);
2519 fw_size -= sizeof(*cmd);
2520
2521 if (fw_size < cmd->plen) {
2522 BT_ERR("%s: BCM: patch %s is corrupted",
2523 hdev->name, fw_name);
2524 ret = -EINVAL;
2525 goto reset_fw;
2526 }
2527
2528 cmd_param = fw_ptr;
2529 fw_ptr += cmd->plen;
2530 fw_size -= cmd->plen;
2531
2532 opcode = le16_to_cpu(cmd->opcode);
2533
2534 skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param,
2535 HCI_INIT_TIMEOUT);
2536 if (IS_ERR(skb)) {
2537 ret = PTR_ERR(skb);
2538 BT_ERR("%s: BCM: patch command %04x failed (%ld)",
2539 hdev->name, opcode, ret);
2540 goto reset_fw;
2541 }
2542 kfree_skb(skb);
2543 }
2544
2545 /* 250 msec delay after Launch Ram completes */
2546 msleep(250);
2547
2548reset_fw:
2549 /* Reset */
2550 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
2551 if (IS_ERR(skb)) {
2552 ret = PTR_ERR(skb);
2553 BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret);
2554 goto done;
2555 }
2556 kfree_skb(skb);
2557
2558 /* Read Local Version Info */
2559 skb = btusb_read_local_version(hdev);
2560 if (IS_ERR(skb)) {
2561 ret = PTR_ERR(skb);
2562 goto done;
2563 }
2564
2565 ver = (struct hci_rp_read_local_version *)skb->data;
2566 rev = le16_to_cpu(ver->hci_rev);
2567 subver = le16_to_cpu(ver->lmp_subver);
2568 kfree_skb(skb);
2569
2570 BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
2571 hw_name ? : "BCM", (subver & 0x7000) >> 13,
2572 (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
2573
2574 btbcm_check_bdaddr(hdev);
2575
2576done:
2577 release_firmware(fw);
2578
2579 return ret;
2580}
2581
2582static int btusb_setup_bcm_apple(struct hci_dev *hdev)
2583{
2584 struct sk_buff *skb;
2585 int err;
2586
2587 /* Read Verbose Config Version Info */
2588 skb = __hci_cmd_sync(hdev, 0xfc79, 0, NULL, HCI_INIT_TIMEOUT);
2589 if (IS_ERR(skb)) {
2590 err = PTR_ERR(skb);
2591 BT_ERR("%s: BCM: Read Verbose Version failed (%d)",
2592 hdev->name, err);
2593 return err;
2594 }
2595
2596 if (skb->len != 7) {
2597 BT_ERR("%s: BCM: Read Verbose Version event length mismatch",
2598 hdev->name);
2599 kfree_skb(skb);
2600 return -EIO;
2601 }
2602
2603 BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1],
2604 get_unaligned_le16(skb->data + 5));
2605 kfree_skb(skb);
2606
2607 return 0;
2608}
2609
2610static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev, 2405static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
2611 const bdaddr_t *bdaddr) 2406 const bdaddr_t *bdaddr)
2612{ 2407{
@@ -3000,16 +2795,18 @@ static int btusb_probe(struct usb_interface *intf,
3000 if (id->driver_info & BTUSB_BCM92035) 2795 if (id->driver_info & BTUSB_BCM92035)
3001 hdev->setup = btusb_setup_bcm92035; 2796 hdev->setup = btusb_setup_bcm92035;
3002 2797
2798#ifdef CONFIG_BT_HCIBTUSB_BCM
3003 if (id->driver_info & BTUSB_BCM_PATCHRAM) { 2799 if (id->driver_info & BTUSB_BCM_PATCHRAM) {
3004 hdev->setup = btusb_setup_bcm_patchram; 2800 hdev->setup = btbcm_setup_patchram;
3005 hdev->set_bdaddr = btbcm_set_bdaddr; 2801 hdev->set_bdaddr = btbcm_set_bdaddr;
3006 set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); 2802 set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
3007 } 2803 }
3008 2804
3009 if (id->driver_info & BTUSB_BCM_APPLE) { 2805 if (id->driver_info & BTUSB_BCM_APPLE) {
3010 hdev->setup = btusb_setup_bcm_apple; 2806 hdev->setup = btbcm_setup_apple;
3011 set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); 2807 set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
3012 } 2808 }
2809#endif
3013 2810
3014 if (id->driver_info & BTUSB_INTEL) { 2811 if (id->driver_info & BTUSB_INTEL) {
3015 hdev->setup = btusb_setup_intel; 2812 hdev->setup = btusb_setup_intel;