Skip to content

Commit ff28955

Browse files
Loic Poulainholtmann
authored andcommitted
Bluetooth: hci_intel: Add Intel baudrate configuration support
Implement the set_baudrate callback for hci_intel. - Controller requires a read Intel version command before updating its baudrate. - The operation consists in an async cmd since the controller does not respond at the same speed. - Wait 100ms to let the controller change its baudrate. - Clear RTS until we change our own UART speed Manage speed change in the setup function, we need to restore the oper speed once chip has booted on patched firmware. Signed-off-by: Loic Poulain <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent e549916 commit ff28955

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

drivers/bluetooth/hci_intel.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,38 @@ struct intel_data {
4545
unsigned long flags;
4646
};
4747

48+
static u8 intel_convert_speed(unsigned int speed)
49+
{
50+
switch (speed) {
51+
case 9600:
52+
return 0x00;
53+
case 19200:
54+
return 0x01;
55+
case 38400:
56+
return 0x02;
57+
case 57600:
58+
return 0x03;
59+
case 115200:
60+
return 0x04;
61+
case 230400:
62+
return 0x05;
63+
case 460800:
64+
return 0x06;
65+
case 921600:
66+
return 0x07;
67+
case 1843200:
68+
return 0x08;
69+
case 3250000:
70+
return 0x09;
71+
case 2000000:
72+
return 0x0a;
73+
case 3000000:
74+
return 0x0b;
75+
default:
76+
return 0xff;
77+
}
78+
}
79+
4880
static int intel_open(struct hci_uart *hu)
4981
{
5082
struct intel_data *intel;
@@ -111,6 +143,56 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)
111143
return hci_recv_frame(hdev, skb);
112144
}
113145

146+
static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)
147+
{
148+
struct intel_data *intel = hu->priv;
149+
struct hci_dev *hdev = hu->hdev;
150+
u8 speed_cmd[] = { 0x06, 0xfc, 0x01, 0x00 };
151+
struct sk_buff *skb;
152+
153+
BT_INFO("%s: Change controller speed to %d", hdev->name, speed);
154+
155+
speed_cmd[3] = intel_convert_speed(speed);
156+
if (speed_cmd[3] == 0xff) {
157+
BT_ERR("%s: Unsupported speed", hdev->name);
158+
return -EINVAL;
159+
}
160+
161+
/* Device will not accept speed change if Intel version has not been
162+
* previously requested.
163+
*/
164+
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT);
165+
if (IS_ERR(skb)) {
166+
BT_ERR("%s: Reading Intel version information failed (%ld)",
167+
hdev->name, PTR_ERR(skb));
168+
return PTR_ERR(skb);
169+
}
170+
kfree_skb(skb);
171+
172+
skb = bt_skb_alloc(sizeof(speed_cmd), GFP_KERNEL);
173+
if (!skb) {
174+
BT_ERR("%s: Failed to allocate memory for baudrate packet",
175+
hdev->name);
176+
return -ENOMEM;
177+
}
178+
179+
memcpy(skb_put(skb, sizeof(speed_cmd)), speed_cmd, sizeof(speed_cmd));
180+
bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
181+
182+
hci_uart_set_flow_control(hu, true);
183+
184+
skb_queue_tail(&intel->txq, skb);
185+
hci_uart_tx_wakeup(hu);
186+
187+
/* wait 100ms to change baudrate on controller side */
188+
msleep(100);
189+
190+
hci_uart_set_baudrate(hu, speed);
191+
hci_uart_set_flow_control(hu, false);
192+
193+
return 0;
194+
}
195+
114196
static int intel_setup(struct hci_uart *hu)
115197
{
116198
static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
@@ -126,6 +208,8 @@ static int intel_setup(struct hci_uart *hu)
126208
u32 frag_len;
127209
ktime_t calltime, delta, rettime;
128210
unsigned long long duration;
211+
unsigned int init_speed, oper_speed;
212+
int speed_change = 0;
129213
int err;
130214

131215
BT_DBG("%s", hdev->name);
@@ -134,6 +218,19 @@ static int intel_setup(struct hci_uart *hu)
134218

135219
calltime = ktime_get();
136220

221+
if (hu->init_speed)
222+
init_speed = hu->init_speed;
223+
else
224+
init_speed = hu->proto->init_speed;
225+
226+
if (hu->oper_speed)
227+
oper_speed = hu->oper_speed;
228+
else
229+
oper_speed = hu->proto->oper_speed;
230+
231+
if (oper_speed && init_speed && oper_speed != init_speed)
232+
speed_change = 1;
233+
137234
set_bit(STATE_BOOTLOADER, &intel->flags);
138235

139236
/* Read the Intel version information to determine if the device
@@ -416,6 +513,13 @@ static int intel_setup(struct hci_uart *hu)
416513
if (err < 0)
417514
return err;
418515

516+
/* We need to restore the default speed before Intel reset */
517+
if (speed_change) {
518+
err = intel_set_baudrate(hu, init_speed);
519+
if (err)
520+
return err;
521+
}
522+
419523
calltime = ktime_get();
420524

421525
set_bit(STATE_BOOTING, &intel->flags);
@@ -456,6 +560,19 @@ static int intel_setup(struct hci_uart *hu)
456560

457561
BT_INFO("%s: Device booted in %llu usecs", hdev->name, duration);
458562

563+
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_CMD_TIMEOUT);
564+
if (IS_ERR(skb))
565+
return PTR_ERR(skb);
566+
kfree_skb(skb);
567+
568+
if (speed_change) {
569+
err = intel_set_baudrate(hu, oper_speed);
570+
if (err)
571+
return err;
572+
}
573+
574+
BT_INFO("%s: Setup complete", hdev->name);
575+
459576
clear_bit(STATE_BOOTLOADER, &intel->flags);
460577

461578
return 0;
@@ -572,10 +689,12 @@ static const struct hci_uart_proto intel_proto = {
572689
.id = HCI_UART_INTEL,
573690
.name = "Intel",
574691
.init_speed = 115200,
692+
.oper_speed = 3000000,
575693
.open = intel_open,
576694
.close = intel_close,
577695
.flush = intel_flush,
578696
.setup = intel_setup,
697+
.set_baudrate = intel_set_baudrate,
579698
.recv = intel_recv,
580699
.enqueue = intel_enqueue,
581700
.dequeue = intel_dequeue,

0 commit comments

Comments
 (0)