Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: hci_bcm: Add support for FW loading in autobaud mode

Use the presence of a DT property, "brcm,requires-autobaud-mode", to enable
startup in autobaud mode. If the property is present, the device is started
in autobaud mode by asserting RTS (BT_UART_CTS_N) prior to powering on the
device.

Also prevent the use of unsupported commands for devices started in
autobaud mode. Only a limited subset of HCI commands are supported in
autobaud mode.

Some devices (e.g. CYW5557x) require autobaud mode to enable FW loading.
Autobaud mode can also be required on some boards where the controller
device is using a non-standard baud rate in normal mode when first powered
on.

Signed-off-by: Hakan Jansson <hakan.jansson@infineon.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>

authored by

Hakan Jansson and committed by
Luiz Augusto von Dentz
af35e28f 0b4de252

+40 -15
+23 -8
drivers/bluetooth/btbcm.c
··· 403 403 bt_dev_info(hdev, "BCM: chip id %u", skb->data[1]); 404 404 kfree_skb(skb); 405 405 406 + return 0; 407 + } 408 + 409 + static int btbcm_print_controller_features(struct hci_dev *hdev) 410 + { 411 + struct sk_buff *skb; 412 + 406 413 /* Read Controller Features */ 407 414 skb = btbcm_read_controller_features(hdev); 408 415 if (IS_ERR(skb)) ··· 521 514 #endif 522 515 } 523 516 524 - int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) 517 + int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode) 525 518 { 526 519 u16 subver, rev, pid, vid; 527 520 struct sk_buff *skb; ··· 558 551 if (err) 559 552 return err; 560 553 } 561 - err = btbcm_print_local_name(hdev); 562 - if (err) 563 - return err; 554 + 555 + if (!use_autobaud_mode) { 556 + err = btbcm_print_controller_features(hdev); 557 + if (err) 558 + return err; 559 + 560 + err = btbcm_print_local_name(hdev); 561 + if (err) 562 + return err; 563 + } 564 564 565 565 bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table : 566 566 bcm_uart_subver_table; ··· 650 636 } 651 637 EXPORT_SYMBOL_GPL(btbcm_initialize); 652 638 653 - int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done) 639 + int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode) 654 640 { 655 641 int err; 656 642 657 643 /* Re-initialize if necessary */ 658 644 if (*fw_load_done) { 659 - err = btbcm_initialize(hdev, fw_load_done); 645 + err = btbcm_initialize(hdev, fw_load_done, use_autobaud_mode); 660 646 if (err) 661 647 return err; 662 648 } ··· 672 658 int btbcm_setup_patchram(struct hci_dev *hdev) 673 659 { 674 660 bool fw_load_done = false; 661 + bool use_autobaud_mode = false; 675 662 int err; 676 663 677 664 /* Initialize */ 678 - err = btbcm_initialize(hdev, &fw_load_done); 665 + err = btbcm_initialize(hdev, &fw_load_done, use_autobaud_mode); 679 666 if (err) 680 667 return err; 681 668 682 669 /* Re-initialize after loading Patch */ 683 - return btbcm_finalize(hdev, &fw_load_done); 670 + return btbcm_finalize(hdev, &fw_load_done, use_autobaud_mode); 684 671 } 685 672 EXPORT_SYMBOL_GPL(btbcm_setup_patchram); 686 673
+4 -4
drivers/bluetooth/btbcm.h
··· 62 62 int btbcm_setup_patchram(struct hci_dev *hdev); 63 63 int btbcm_setup_apple(struct hci_dev *hdev); 64 64 65 - int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done); 66 - int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done); 65 + int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode); 66 + int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode); 67 67 68 68 #else 69 69 ··· 104 104 return 0; 105 105 } 106 106 107 - static inline int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) 107 + static inline int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode) 108 108 { 109 109 return 0; 110 110 } 111 111 112 - static inline int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done) 112 + static inline int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done, bool use_autobaud_mode) 113 113 { 114 114 return 0; 115 115 }
+13 -3
drivers/bluetooth/hci_bcm.c
··· 99 99 * @no_early_set_baudrate: don't set_baudrate before setup() 100 100 * @drive_rts_on_open: drive RTS signal on ->open() when platform requires it 101 101 * @pcm_int_params: keep the initial PCM configuration 102 + * @use_autobaud_mode: start Bluetooth device in autobaud mode 102 103 */ 103 104 struct bcm_device { 104 105 /* Must be the first member, hci_serdev.c expects this. */ ··· 137 136 #endif 138 137 bool no_early_set_baudrate; 139 138 bool drive_rts_on_open; 139 + bool use_autobaud_mode; 140 140 u8 pcm_int_params[5]; 141 141 }; 142 142 ··· 474 472 475 473 out: 476 474 if (bcm->dev) { 477 - if (bcm->dev->drive_rts_on_open) 475 + if (bcm->dev->use_autobaud_mode) 476 + hci_uart_set_flow_control(hu, false); /* Assert BT_UART_CTS_N */ 477 + else if (bcm->dev->drive_rts_on_open) 478 478 hci_uart_set_flow_control(hu, true); 479 479 480 480 hu->init_speed = bcm->dev->init_speed; ··· 568 564 { 569 565 struct bcm_data *bcm = hu->priv; 570 566 bool fw_load_done = false; 567 + bool use_autobaud_mode = (bcm->dev ? bcm->dev->use_autobaud_mode : 0); 571 568 unsigned int speed; 572 569 int err; 573 570 ··· 577 572 hu->hdev->set_diag = bcm_set_diag; 578 573 hu->hdev->set_bdaddr = btbcm_set_bdaddr; 579 574 580 - err = btbcm_initialize(hu->hdev, &fw_load_done); 575 + err = btbcm_initialize(hu->hdev, &fw_load_done, use_autobaud_mode); 581 576 if (err) 582 577 return err; 583 578 ··· 621 616 btbcm_write_pcm_int_params(hu->hdev, &params); 622 617 } 623 618 624 - err = btbcm_finalize(hu->hdev, &fw_load_done); 619 + err = btbcm_finalize(hu->hdev, &fw_load_done, use_autobaud_mode); 625 620 if (err) 626 621 return err; 627 622 ··· 1202 1197 1203 1198 static int bcm_of_probe(struct bcm_device *bdev) 1204 1199 { 1200 + bdev->use_autobaud_mode = device_property_read_bool(bdev->dev, 1201 + "brcm,requires-autobaud-mode"); 1202 + if (bdev->use_autobaud_mode) 1203 + bdev->no_early_set_baudrate = true; 1204 + 1205 1205 device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed); 1206 1206 device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params", 1207 1207 bdev->pcm_int_params, 5);