Skip to content

Commit 61b2fc2

Browse files
Frederic Danisholtmann
authored andcommitted
Bluetooth: hci_uart: Add bcm_set_baudrate()
Add vendor specific command to change controller device speed. Signed-off-by: Frederic Danis <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent c9d4420 commit 61b2fc2

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

drivers/bluetooth/btbcm.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@
2121
*
2222
*/
2323

24+
#define BCM_UART_CLOCK_48MHZ 0x01
25+
#define BCM_UART_CLOCK_24MHZ 0x02
26+
27+
struct bcm_update_uart_baud_rate {
28+
__le16 zero;
29+
__le32 baud_rate;
30+
} __packed;
31+
32+
struct bcm_write_uart_clock_setting {
33+
__u8 type;
34+
} __packed;
35+
2436
#if IS_ENABLED(CONFIG_BT_BCM)
2537

2638
int btbcm_check_bdaddr(struct hci_dev *hdev);

drivers/bluetooth/hci_bcm.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,55 @@ struct bcm_data {
3737
struct sk_buff_head txq;
3838
};
3939

40+
static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed)
41+
{
42+
struct hci_dev *hdev = hu->hdev;
43+
struct sk_buff *skb;
44+
struct bcm_update_uart_baud_rate param;
45+
46+
if (speed > 3000000) {
47+
struct bcm_write_uart_clock_setting clock;
48+
49+
clock.type = BCM_UART_CLOCK_48MHZ;
50+
51+
BT_DBG("%s: Set Controller clock (%d)", hdev->name, clock.type);
52+
53+
/* This Broadcom specific command changes the UART's controller
54+
* clock for baud rate > 3000000.
55+
*/
56+
skb = __hci_cmd_sync(hdev, 0xfc45, 1, &clock, HCI_INIT_TIMEOUT);
57+
if (IS_ERR(skb)) {
58+
int err = PTR_ERR(skb);
59+
BT_ERR("%s: BCM: failed to write clock command (%d)",
60+
hdev->name, err);
61+
return err;
62+
}
63+
64+
kfree_skb(skb);
65+
}
66+
67+
BT_DBG("%s: Set Controller UART speed to %d bit/s", hdev->name, speed);
68+
69+
param.zero = cpu_to_le16(0);
70+
param.baud_rate = cpu_to_le32(speed);
71+
72+
/* This Broadcom specific command changes the UART's controller baud
73+
* rate.
74+
*/
75+
skb = __hci_cmd_sync(hdev, 0xfc18, sizeof(param), &param,
76+
HCI_INIT_TIMEOUT);
77+
if (IS_ERR(skb)) {
78+
int err = PTR_ERR(skb);
79+
BT_ERR("%s: BCM: failed to write update baudrate command (%d)",
80+
hdev->name, err);
81+
return err;
82+
}
83+
84+
kfree_skb(skb);
85+
86+
return 0;
87+
}
88+
4089
static int bcm_open(struct hci_uart *hu)
4190
{
4291
struct bcm_data *bcm;
@@ -107,6 +156,12 @@ static int bcm_setup(struct hci_uart *hu)
107156
if (hu->proto->init_speed)
108157
hci_uart_set_baudrate(hu, hu->proto->init_speed);
109158

159+
if (hu->proto->oper_speed) {
160+
err = bcm_set_baudrate(hu, hu->proto->oper_speed);
161+
if (!err)
162+
hci_uart_set_baudrate(hu, hu->proto->oper_speed);
163+
}
164+
110165
finalize:
111166
release_firmware(fw);
112167

@@ -162,10 +217,13 @@ static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
162217
static const struct hci_uart_proto bcm_proto = {
163218
.id = HCI_UART_BCM,
164219
.name = "BCM",
220+
.init_speed = 115200,
221+
.oper_speed = 4000000,
165222
.open = bcm_open,
166223
.close = bcm_close,
167224
.flush = bcm_flush,
168225
.setup = bcm_setup,
226+
.set_baudrate = bcm_set_baudrate,
169227
.recv = bcm_recv,
170228
.enqueue = bcm_enqueue,
171229
.dequeue = bcm_dequeue,

0 commit comments

Comments
 (0)