Add baudrate management for Bluetooth UART
PATCH v8 1/1 Add baudrate management for Bluetooth UART
This patch set introduce baudrate management for Bluetooth UART Controller setup and a first implementation for Broadcom BCM4324B3 used in Asus T100.
v7 -> v8:
- Patches 1 to 5 has been integrated
- Rename "struct hci_cp_bcm_set_speed" to "struct bcm_set_speed" and move it to btbcm.h
- Rename parameter "dummy" to "zero" in "struct bcm_set_speed"
- Add comments above vendor commands
- Add "BCM: " in BT_ERR strings
- Assign value of "param" variable above related vendor command
v6 -> v7:
- Fix setup when firmware is missing by moving request/release_firmware() out of btbcm_patchram().
v2 -> v6:
- Fixes for __hci_cmd_sync() has been integrated (patch v5)
- In btbcm_check_bdaddr(), merge controller address tests
- Fix declaration of speeds to use "unsigned int" type
- Rename default_speed to init_speed
- Rename operational_speed to oper_speed
- In case of error during vendor specific set_baudrate(), do not change host baudrate and continue without changing speed
- Discard changes to bcm_setup_patchram() and in btusb.c
- Introduce helper functions btbcm_initialize() and btbcm_finalize() to be used by the UART side of things.
Frederic Danis (1):
Bluetooth: hci_uart: Add bcm_set_baudrate()
drivers/bluetooth/btbcm.h | 5 ++++ drivers/bluetooth/hci_bcm.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+)
Signature · 1 line
1.9.1
PATCH v8 1/1 Bluetooth: hci_uart: Add bcm_set_baudrate()
Add vendor specific command to change controller device speed.
--- drivers/bluetooth/btbcm.h | 5 ++++ drivers/bluetooth/hci_bcm.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+)
drivers/bluetooth/btbcm.h +5 -0
@@ -21,6 +21,11 @@* */ +struct bcm_set_speed { +__le16 zero; +__le32 speed; +} __packed; +#if IS_ENABLED (CONFIG_BT_BCM )int btbcm_check_bdaddr (struct hci_dev *hdev);
drivers/bluetooth/hci_bcm.c +58 -0
91 lines not on this page · raw message
Signature · 1 line
1.9.1
Marcel Holtmann
maintainerRe: [PATCH v8] Bluetooth: hci_uart: Add bcm_set_baudrate()
Hi Fred,
Quoted 13 lines
Add vendor specific command to change controller device speed.
Signed-off-by Frederic Danis <[email protected]>---
drivers/bluetooth/btbcm.h| 5 ++++drivers/bluetooth/hci_bcm.c| 58 +++++++++++++++++++++++++++++++++++++++++++++2 files changed, 63 insertions(+)drivers/bluetooth/btbcm.h +0
-0
drivers/bluetooth/btbcm.h line 28
Quoted 8 lines
drivers/bluetooth/btbcm.h +5
-0@@ -21,6 +21,11 @@* */ +struct bcm_set_speed { +__le16 zero; +__le32 speed; +} __packed; +
I think this should actually be
struct bcm_update_uart_baud_rate {
__le16 zero;
__le32 baud_rate;
} __packed;And lets just add this one as well
struct bcm_write_uart_clock_setting {
__u8 type;
} __packed;Quoted 16 lines
drivers/bluetooth/btbcm.h +0
-0#if IS_ENABLED (CONFIG_BT_BCM )int btbcm_check_bdaddr (struct hci_dev *hdev);drivers/bluetooth/hci_bcm.c +1
-0@@ -25,6 +25,7 @@#include <linux/errno.h> #include <linux/skbuff.h> #include <linux/firmware.h> +#include <linux/tty.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h>
drivers/bluetooth/hci_bcm.c line 38
Quoted 6 lines
drivers/bluetooth/hci_bcm.c +3
-0@@ -32,11 +33,59 @@#include "btbcm.h" #include "hci_uart.h" +#define BCM43XX_CLOCK_48 1 +#define BCM43XX_CLOCK_24 2 +
Lets put these in btbcm.h as well.
#define BCM_UART_CLOCK_48MHZ 0x01
#define BCM_UART_CLOCK_24MHZ 0x02
Quoted 14 lines
drivers/bluetooth/hci_bcm.c +9
-0struct bcm_data {struct sk_buff *rx_skb;struct sk_buff_head txq; }; +static int bcm_set_baudrate (struct hci_uart *hu,unsigned int speed) +{ +struct hci_dev *hdev = hu->hdev; +struct sk_buff *skb; +struct bcm_set_speed param; + +if (speed >3000000 ) { +u8 clock =BCM43XX_CLOCK_48 ; +
drivers/bluetooth/hci_bcm.c line 62
Quoted 10 lines
drivers/bluetooth/hci_bcm.c +10
-0+BT_DBG ("%s: Set Controller clock (%d)" , hdev->name, clock); + +/* 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)) { +BT_ERR ("%s: BCM: failed to write update clock command" +" (%ld)" , hdev->name,PTR_ERR (skb)); +return PTR_ERR (skb);
In many cases we did this:
int err = PTR_ERR(skb);
BT_ERR("%s .. (%d)", hdev->name, err);
return err;I have the feeling that we might want to stick with this. Might be worth while to check how consistent we have actually been.
Quoted 46 lines
drivers/bluetooth/hci_bcm.c +32
-0+ } + +kfree_skb (skb); + } + +BT_DBG ("%s: Set Controller UART speed to %d bit/s" , hdev->name, speed); + + param.zero =cpu_to_le16 (0 ); + param.speed =cpu_to_le32 (speed); + +/* This Broadcom specific command changes the UART's controller baud +* rate. +*/ + skb =__hci_cmd_sync (hdev,0xfc18 ,sizeof (param), ¶m, +HCI_INIT_TIMEOUT ); +if (IS_ERR (skb)) { +BT_ERR ("%s: BCM: failed to write update baudrate command (%ld)" , + hdev->name,PTR_ERR (skb)); +return PTR_ERR (skb); + } + +kfree_skb (skb); + +return 0 ; +} +static int bcm_open (struct hci_uart *hu) {struct bcm_data *bcm;@@ -107,6 +156,12 @@ static int bcm_setup(struct hci_uart *hu)if (hu->proto->init_speed)hci_uart_set_baudrate (hu, hu->proto->init_speed); +if (hu->proto->oper_speed) { + err =bcm_set_baudrate (hu, hu->proto->oper_speed); +if (!err) +hci_uart_set_baudrate (hu, hu->proto->oper_speed); + } +finalize:
release_firmware(fw);drivers/bluetooth/hci_bcm.c +0
-0@@ -162,10 +217,13 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu)static const struct hci_uart_proto bcm_proto = { .id =HCI_UART_BCM , .name ="BCM" ,
drivers/bluetooth/hci_bcm.c static struct sk_buff *bcm_dequeue(struct hci_uart *hu) · line 229
Quoted 10 lines
drivers/bluetooth/hci_bcm.c +3
-0+ .init_speed = 115200, + .oper_speed = 4000000, .open = bcm_open, .close = bcm_close, .flush = bcm_flush, .setup = bcm_setup, + .set_baudrate = bcm_set_baudrate, .recv = bcm_recv, .enqueue = bcm_enqueue, .dequeue = bcm_dequeue,
Rest looks good.
Regards
Marcel