1 /*
2 * Copyright 2024 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8 #include <stddef.h>
9 #include <string.h>
10
11 #include <zephyr/kernel.h>
12 #include <zephyr/arch/cpu.h>
13
14 #include <zephyr/init.h>
15 #include <zephyr/drivers/uart.h>
16 #include <zephyr/drivers/gpio.h>
17 #include <zephyr/sys/util.h>
18 #include <zephyr/sys/byteorder.h>
19 #include <zephyr/sys/crc.h>
20
21 #include <zephyr/bluetooth/bluetooth.h>
22 #include <zephyr/bluetooth/hci.h>
23
24 #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL
25 #include <zephyr/logging/log.h>
26 LOG_MODULE_REGISTER(bt_nxp_ctlr);
27
28 #include "common/bt_str.h"
29
30 #include "bt_nxp_ctlr_fw.h"
31
32 #define DT_DRV_COMPAT nxp_bt_hci_uart
33
34 #define FW_UPLOAD_CHANGE_TIMEOUT_RETRY_COUNT 6
35
36 static const struct device *uart_dev = DEVICE_DT_GET(DT_INST_GPARENT(0));
37
38 #if DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios)
39 struct gpio_dt_spec sdio_reset = GPIO_DT_SPEC_GET(DT_DRV_INST(0), sdio_reset_gpios);
40 #endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) */
41 #if DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios)
42 struct gpio_dt_spec w_disable = GPIO_DT_SPEC_GET(DT_DRV_INST(0), w_disable_gpios);
43 #endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) */
44
45 struct nxp_ctlr_dev_data {
46 uint32_t primary_speed;
47 bool primary_flowcontrol;
48 uint32_t secondary_speed;
49 bool secondary_flowcontrol;
50 };
51
52 static struct nxp_ctlr_dev_data uart_dev_data;
53
54 #define DI 0x07U
55 #define POLYNOMIAL 0x04c11db7UL
56
57 #define CRC32_LEN 4
58
59 static unsigned long crc_table[256U];
60 static bool made_table;
61
fw_upload_gen_crc32_table(void)62 static void fw_upload_gen_crc32_table(void)
63 {
64 int i, j;
65 unsigned long crc_accum;
66
67 for (i = 0; i < 256; i++) {
68 crc_accum = ((unsigned long)i << 24);
69 for (j = 0; j < 8; j++) {
70 if (crc_accum & 0x80000000L) {
71 crc_accum = (crc_accum << 1) ^ POLYNOMIAL;
72 } else {
73 crc_accum = (crc_accum << 1);
74 }
75 }
76 crc_table[i] = crc_accum;
77 }
78 }
79
fw_upload_crc8(unsigned char * array,unsigned char len)80 static unsigned char fw_upload_crc8(unsigned char *array, unsigned char len)
81 {
82 unsigned char crc_8 = 0xff;
83
84 crc_8 = crc8(array, len, DI, crc_8, false);
85
86 return crc_8;
87 }
88
fw_upload_update_crc32(unsigned long crc_accum,char * data_blk_ptr,int data_blk_size)89 static unsigned long fw_upload_update_crc32(unsigned long crc_accum, char *data_blk_ptr,
90 int data_blk_size)
91 {
92 unsigned int i, j;
93
94 for (j = 0; j < data_blk_size; j++) {
95 i = ((unsigned int)(crc_accum >> 24) ^ *data_blk_ptr++) & 0xff;
96 crc_accum = (crc_accum << 8) ^ crc_table[i];
97 }
98 return crc_accum;
99 }
100
101 #define CMD4 0x4U
102 #define CMD6 0x6U
103 #define CMD7 0x7U
104
105 #define V1_HEADER_DATA_REQ 0xa5U
106 #define V1_START_INDICATION 0xaaU
107 #define V1_REQUEST_ACK 0x5aU
108
109 #define V3_START_INDICATION 0xabU
110 #define V3_HEADER_DATA_REQ 0xa7U
111 #define V3_REQUEST_ACK 0x7aU
112 #define V3_TIMEOUT_ACK 0x7bU
113 #define V3_CRC_ERROR 0x7cU
114
115 #define REQ_HEADER_LEN 1U
116 #define A6REQ_PAYLOAD_LEN 8U
117 #define AbREQ_PAYLOAD_LEN 3U
118
119 #define CRC_ERR_BIT BIT(0)
120 #define NAK_REC_BIT BIT(1)
121 #define TIMEOUT_REC_ACK_BIT BIT(2)
122 #define TIMEOUT_REC_HEAD_BIT BIT(3)
123 #define TIMEOUT_REC_DATA_BIT BIT(4)
124 #define INVALID_CMD_REC_BIT BIT(5)
125 #define WIFI_MIC_FAIL_BIT BIT(6)
126 #define BT_MIC_FAIL_BIT BIT(7)
127
128 #define CMD_HDR_LEN 16
129
130 /* CMD5 Header to change bootloader baud rate */
131 static uint8_t cmd5_hdrData[CMD_HDR_LEN] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x2c, 0x00, 0x00, 0x00, 0x77, 0xdb, 0xfd, 0xe0};
133 /* CMD7 Header to change timeout of bootloader */
134 static uint8_t cmd7_hdrData[CMD_HDR_LEN] = {0x07, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x5b, 0x88, 0xf8, 0xba};
136
137 enum bt_nxp_ctlr_version {
138 VER1 = 1,
139 VER2,
140 VER3,
141 };
142
143 struct change_speed_config {
144 uint32_t clk_div_addr;
145 uint32_t clk_div_val;
146 uint32_t uart_clk_div_addr;
147 uint32_t uart_clk_div_val;
148 uint32_t mcr_addr;
149 uint32_t mcr_val;
150 uint32_t reinit_addr;
151 uint32_t reinit_val;
152 uint32_t icr_addr;
153 uint32_t icr_val;
154 uint32_t fcr_addr;
155 uint32_t fcr_val;
156 };
157
158 #define SEND_BUFFER_MAX_LENGTH 0xFFFFU /* Maximum 2 byte value */
159 #define RECV_RING_BUFFER_LENGTH 1024
160
161 struct nxp_ctlr_fw_upload_state {
162 uint8_t version;
163 uint8_t hdr_sig;
164
165 uint8_t buffer[A6REQ_PAYLOAD_LEN + REQ_HEADER_LEN + 1];
166
167 uint8_t send_buffer[SEND_BUFFER_MAX_LENGTH + 1];
168
169 struct {
170 uint8_t buffer[RECV_RING_BUFFER_LENGTH];
171 uint32_t head;
172 uint32_t tail;
173 struct k_sem sem;
174 } rx;
175
176 uint16_t length;
177 uint32_t offset;
178 uint16_t error;
179 uint8_t crc8;
180
181 uint32_t last_offset;
182 uint8_t change_speed_buffer[sizeof(struct change_speed_config) + CRC32_LEN];
183
184 uint32_t fw_length;
185 uint32_t current_length;
186 const uint8_t *fw;
187
188 uint32_t cmd7_change_timeout_len;
189 uint32_t change_speed_buffer_len;
190
191 bool wait_hdr_sig;
192
193 bool is_hdr_data;
194 bool is_error_case;
195 bool is_cmd7_req;
196 bool is_entry_point_req;
197
198 uint8_t last_5bytes_buffer[6];
199 };
200
201 static struct nxp_ctlr_fw_upload_state fw_upload;
202
fw_upload_read_data(uint8_t * buffer,uint32_t len)203 static int fw_upload_read_data(uint8_t *buffer, uint32_t len)
204 {
205 int err;
206
207 while (len > 0) {
208 err = k_sem_take(&fw_upload.rx.sem,
209 K_MSEC(CONFIG_BT_H4_NXP_CTLR_WAIT_HDR_SIG_TIMEOUT));
210 if (err < 0) {
211 LOG_ERR("Fail to read data");
212 return err;
213 }
214 *buffer = fw_upload.rx.buffer[fw_upload.rx.tail];
215 buffer++;
216 fw_upload.rx.tail++;
217 fw_upload.rx.tail = fw_upload.rx.tail % sizeof(fw_upload.rx.buffer);
218 len--;
219 }
220 return 0;
221 }
222
fw_upload_read_to_clear(void)223 static void fw_upload_read_to_clear(void)
224 {
225 uint32_t key;
226
227 key = irq_lock();
228 k_sem_reset(&fw_upload.rx.sem);
229 fw_upload.rx.head = 0;
230 fw_upload.rx.tail = 0;
231 irq_unlock(key);
232 }
233
fw_upload_wait_for_hdr_sig(void)234 static int fw_upload_wait_for_hdr_sig(void)
235 {
236 int err;
237 int64_t end;
238 char c;
239
240 end = k_uptime_get() + CONFIG_BT_H4_NXP_CTLR_WAIT_HDR_SIG_TIMEOUT;
241 fw_upload.hdr_sig = 0xFF;
242
243 while (k_uptime_get() < end) {
244 err = fw_upload_read_data(&c, 1);
245 if (err < 0) {
246 k_msleep(1);
247 continue;
248 }
249 if ((c == V1_HEADER_DATA_REQ) || (c == V1_START_INDICATION) ||
250 (c == V3_START_INDICATION) || (c == V3_HEADER_DATA_REQ)) {
251 LOG_DBG("HDR SIG found 0x%02X", c);
252 fw_upload.hdr_sig = c;
253 if (fw_upload.version == 0) {
254 if ((c == V3_START_INDICATION) || (c == V3_HEADER_DATA_REQ)) {
255 fw_upload.version = VER3;
256 } else {
257 fw_upload.version = VER1;
258 }
259 }
260 return 0;
261 }
262 }
263 LOG_ERR("HDR SIG not found");
264 return -EIO;
265 }
266
fw_upload_write_data(const uint8_t * buffer,uint32_t len)267 static void fw_upload_write_data(const uint8_t *buffer, uint32_t len)
268 {
269 for (int i = 0; i < len; i++) {
270 uart_poll_out(uart_dev, buffer[i]);
271 }
272 }
273
fw_upload_request_check_crc(uint8_t * buffer,uint8_t request)274 static int fw_upload_request_check_crc(uint8_t *buffer, uint8_t request)
275 {
276 uint8_t crc;
277
278 if (request == V3_HEADER_DATA_REQ) {
279 crc = fw_upload_crc8(buffer, A6REQ_PAYLOAD_LEN + REQ_HEADER_LEN);
280 if (crc != buffer[A6REQ_PAYLOAD_LEN + REQ_HEADER_LEN]) {
281 LOG_ERR("Request %d, CRC check failed", request);
282 return -EINVAL;
283 }
284 } else if (request == V3_START_INDICATION) {
285 crc = fw_upload_crc8(buffer, AbREQ_PAYLOAD_LEN + REQ_HEADER_LEN);
286 if (crc != buffer[AbREQ_PAYLOAD_LEN + REQ_HEADER_LEN]) {
287 LOG_ERR("Request %d, CRC check failed", request);
288 return -EINVAL;
289 }
290 } else {
291 LOG_ERR("Invalid request %d", request);
292 }
293
294 return 0;
295 }
296
fw_upload_send_ack(uint8_t ack)297 static void fw_upload_send_ack(uint8_t ack)
298 {
299 if ((ack == V3_REQUEST_ACK) || (ack == V3_CRC_ERROR)) {
300 /* prepare crc for 0x7A or 0x7C */
301 fw_upload.buffer[0] = ack;
302 fw_upload.buffer[1] = fw_upload_crc8(fw_upload.buffer, 1);
303 fw_upload_write_data(fw_upload.buffer, 2);
304 LOG_DBG("ACK = %x, CRC = %x", ack, fw_upload.buffer[1]);
305 } else if (ack == V3_TIMEOUT_ACK) {
306 /* prepare crc for 0x7B */
307 fw_upload.buffer[0] = ack;
308 sys_put_le32(fw_upload.offset, &fw_upload.buffer[1]);
309 fw_upload.buffer[5] = fw_upload_crc8(fw_upload.buffer, 5);
310 fw_upload_write_data(fw_upload.buffer, 6);
311 LOG_DBG("ACK = %x, CRC = %x", ack, fw_upload.buffer[5]);
312 } else {
313 LOG_ERR("Invalid ack");
314 }
315 }
316
fw_upload_wait_req(bool secondary_speed)317 static int fw_upload_wait_req(bool secondary_speed)
318 {
319 int err;
320 uint32_t len;
321 uint8_t buffer[10];
322
323 buffer[0] = fw_upload.hdr_sig;
324 if (fw_upload.hdr_sig == V3_HEADER_DATA_REQ) {
325 /* CMD LINE: 0xA7 <len><offset><error><CRC8> */
326 len = A6REQ_PAYLOAD_LEN + 1;
327 } else if (fw_upload.hdr_sig == V3_START_INDICATION) {
328 /* CMD LINE: 0xAB <CHIP ID><SW loader REV 1 byte><CRC8> */
329 len = AbREQ_PAYLOAD_LEN + 1;
330 } else {
331 return -EINVAL;
332 }
333
334 err = fw_upload_read_data(&buffer[1], len);
335 if (err < 0) {
336 LOG_ERR("Fail to read req");
337 return err;
338 }
339
340 err = fw_upload_request_check_crc(buffer, fw_upload.hdr_sig);
341 if (err != 0) {
342 LOG_ERR("Fail to check CRC");
343 fw_upload_send_ack(V3_CRC_ERROR);
344 return err;
345 }
346
347 if (fw_upload.hdr_sig == V3_HEADER_DATA_REQ) {
348 fw_upload.length = sys_get_le16(&buffer[1]);
349 fw_upload.offset = sys_get_le32(&buffer[3]);
350 fw_upload.error = sys_get_le16(&buffer[7]);
351 fw_upload.crc8 = buffer[9];
352 LOG_DBG("Req: %hhd, %hd, %d, %hd, %hhd", fw_upload.hdr_sig, fw_upload.length,
353 fw_upload.offset, fw_upload.error, fw_upload.crc8);
354 } else if (fw_upload.hdr_sig == V3_START_INDICATION) {
355 uint16_t chip_id;
356
357 fw_upload_send_ack(V3_REQUEST_ACK);
358 chip_id = sys_get_le16(&buffer[1]);
359 LOG_DBG("Indicate: %hhd, %hd, %hhd, %hhd", fw_upload.hdr_sig, chip_id, buffer[3],
360 buffer[4]);
361
362 if (!secondary_speed) {
363 return -EINVAL;
364 }
365 }
366
367 return 0;
368 }
369
fw_upload_change_timeout(void)370 static int fw_upload_change_timeout(void)
371 {
372 int err = 0;
373 bool first = true;
374 uint8_t retry = FW_UPLOAD_CHANGE_TIMEOUT_RETRY_COUNT;
375
376 LOG_DBG("");
377
378 fw_upload_gen_crc32_table();
379
380 while (true) {
381 err = fw_upload_wait_for_hdr_sig();
382 if (err) {
383 continue;
384 }
385
386 if (fw_upload.version == VER1) {
387 return 0;
388 } else if (fw_upload.version == VER3) {
389 err = fw_upload_wait_req(true);
390 if (err) {
391 continue;
392 }
393
394 if (fw_upload.length == 0) {
395 continue;
396 }
397
398 if (fw_upload.error == 0) {
399 if (first || (fw_upload.last_offset == fw_upload.offset)) {
400 fw_upload_send_ack(V3_REQUEST_ACK);
401 fw_upload_write_data(cmd7_hdrData,
402 fw_upload.length > CMD_HDR_LEN
403 ? CMD_HDR_LEN
404 : fw_upload.length);
405 fw_upload.last_offset = fw_upload.offset;
406 first = false;
407 } else {
408 fw_upload.cmd7_change_timeout_len = CMD_HDR_LEN;
409 fw_upload.wait_hdr_sig = false;
410 return 0;
411 }
412 } else {
413 if (retry > 0) {
414 retry--;
415 fw_upload_send_ack(V3_TIMEOUT_ACK);
416 } else {
417 LOG_ERR("Fail to change timeout with response err %d",
418 fw_upload.error);
419 return -ENOTSUP;
420 }
421 }
422 } else {
423 LOG_ERR("Unsupported version %d", fw_upload.version);
424 return -ENOTSUP;
425 }
426 }
427
428 return -EINVAL;
429 }
430
431 typedef struct {
432 uint32_t uartBaudRate;
433 uint32_t uartDivisio;
434 uint32_t uartClkDivisor;
435 } uart_baudrate_clkDiv_map_t;
436
437 static const uart_baudrate_clkDiv_map_t clk_div_map[] = {
438 {115200U, 16U, 0x0075F6FDU},
439 {1000000U, 2U, 0x00800000U},
440 {3000000U, 1U, 0x00C00000U},
441 };
442
fw_upload_change_speed_config(struct change_speed_config * config,uint32_t speed)443 static int fw_upload_change_speed_config(struct change_speed_config *config, uint32_t speed)
444 {
445 config->clk_div_addr = 0x7f00008fU;
446 config->uart_clk_div_addr = 0x7f000090U;
447 config->mcr_addr = 0x7f000091U;
448 config->reinit_addr = 0x7f000092U;
449 config->icr_addr = 0x7f000093U;
450 config->fcr_addr = 0x7f000094U;
451
452 config->mcr_val = 0x00000022U;
453 config->reinit_val = 0x00000001U;
454 config->icr_val = 0x000000c7U;
455 config->fcr_val = 0x000000c7U;
456
457 for (int i = 0; i < ARRAY_SIZE(clk_div_map); i++) {
458 if (speed == clk_div_map[i].uartBaudRate) {
459 config->clk_div_val = clk_div_map[i].uartClkDivisor;
460 config->uart_clk_div_val = clk_div_map[i].uartDivisio;
461 return 0;
462 }
463 }
464 return -ENOTSUP;
465 }
466
fw_upload_wait_length(uint8_t flag)467 static uint16_t fw_upload_wait_length(uint8_t flag)
468 {
469 uint8_t buffer[4];
470 uint16_t len;
471 uint16_t len_comp;
472 int err;
473 uint8_t ack;
474
475 err = fw_upload_read_data(buffer, sizeof(buffer));
476 if (err < 0) {
477 return 0;
478 }
479
480 len = sys_get_le16(buffer);
481 len_comp = sys_get_le16(buffer);
482
483 if ((len ^ len_comp) == 0xFFFF) {
484 LOG_DBG("remote asks for %d bytes", len);
485
486 /* Successful. Send back the ack. */
487 if ((fw_upload.hdr_sig == V1_HEADER_DATA_REQ) ||
488 (fw_upload.hdr_sig == V1_START_INDICATION)) {
489 ack = V1_REQUEST_ACK;
490 fw_upload_write_data(&ack, 1);
491 if (fw_upload.hdr_sig == V1_START_INDICATION) {
492 /* Eliminated longjmp(resync, 1); returning restart status */
493 return (uint16_t)V1_START_INDICATION;
494 }
495 }
496 } else {
497 LOG_ERR("remote asks len %d bytes", len);
498 LOG_ERR("remote asks len_comp %d bytes", len_comp);
499 /* Failure due to mismatch. */
500 ack = 0xbf;
501 fw_upload_write_data(&ack, 1);
502 /* Start all over again. */
503 if (flag) {
504 /* Eliminated longjmp(resync, 1); returning restart status */
505 return (uint16_t)V1_START_INDICATION;
506 }
507 len = 0;
508 }
509 return len;
510 }
511
fw_upload_get_payload_length(uint8_t * cmd)512 static uint32_t fw_upload_get_payload_length(uint8_t *cmd)
513 {
514 uint32_t len;
515
516 len = sys_get_le32(&cmd[8]);
517
518 return len;
519 }
520
fw_upload_get_hdr_start(uint8_t * buffer)521 static void fw_upload_get_hdr_start(uint8_t *buffer)
522 {
523 int err;
524 bool done = false;
525 uint32_t count = 0;
526
527 while (!done) {
528 err = fw_upload_read_data(&fw_upload.hdr_sig, 1);
529 if (err >= 0) {
530 if (fw_upload.hdr_sig == V1_HEADER_DATA_REQ) {
531 buffer[count++] = fw_upload.hdr_sig;
532 done = true;
533 LOG_DBG("Found header %x", fw_upload.hdr_sig);
534 }
535 } else {
536 LOG_ERR("Fail to read HDR sig %d", err);
537 return;
538 }
539 }
540 err = fw_upload_read_data(&buffer[count], 4);
541 if (err < 0) {
542 LOG_ERR("Fail to read HDR payload %d", err);
543 }
544 }
545
fw_upload_len_valid(uint8_t * buffer,uint16_t * length)546 static int fw_upload_len_valid(uint8_t *buffer, uint16_t *length)
547 {
548 uint16_t len;
549 uint16_t len_comp;
550
551 len = sys_get_le16(&buffer[1]);
552 len_comp = sys_get_le16(&buffer[3]);
553
554 if ((len ^ len_comp) == 0xFFFFU) {
555 *length = len;
556 return 0;
557 } else {
558 return -EINVAL;
559 }
560 }
561
fw_upload_get_last_5bytes(uint8_t * buffer)562 static int fw_upload_get_last_5bytes(uint8_t *buffer)
563 {
564 int err;
565 uint32_t payload_len;
566 uint16_t len = 0;
567
568 memset(fw_upload.last_5bytes_buffer, 0, sizeof(fw_upload.last_5bytes_buffer));
569
570 fw_upload_get_hdr_start(fw_upload.last_5bytes_buffer);
571 err = fw_upload_len_valid(fw_upload.last_5bytes_buffer, &len);
572 if (err >= 0) {
573 LOG_DBG("Valid len %d", len);
574 } else {
575 LOG_ERR("Invalid HDR");
576 return err;
577 }
578
579 payload_len = fw_upload_get_payload_length(buffer);
580
581 if ((len == CMD_HDR_LEN) || ((uint32_t)len == payload_len)) {
582 LOG_DBG("Len valid");
583 fw_upload.is_error_case = false;
584 return 0;
585 }
586
587 LOG_DBG("Len invalid");
588 fw_upload.is_error_case = true;
589
590 return -EINVAL;
591 }
592
fw_upload_update_result(uint32_t payload_len,uint16_t * sending_len,bool * first_chunk_sent)593 static void fw_upload_update_result(uint32_t payload_len, uint16_t *sending_len,
594 bool *first_chunk_sent)
595 {
596 if (fw_upload.is_cmd7_req || fw_upload.is_entry_point_req) {
597 *sending_len = CMD_HDR_LEN;
598 *first_chunk_sent = true;
599 } else {
600 *sending_len = payload_len;
601 *first_chunk_sent = false;
602 if (*sending_len == CMD_HDR_LEN) {
603 fw_upload.is_hdr_data = true;
604 }
605 }
606 }
607
fw_upload_write_hdr_and_payload(uint16_t len_to_send,uint8_t * buffer,bool new_speed)608 static int fw_upload_write_hdr_and_payload(uint16_t len_to_send, uint8_t *buffer, bool new_speed)
609 {
610 int err;
611 uint32_t payload_len;
612 bool send_done = false;
613 uint16_t sending_len = CMD_HDR_LEN;
614 bool first_chunk_sent = false;
615
616 LOG_DBG("");
617
618 payload_len = fw_upload_get_payload_length(buffer);
619
620 while (!send_done) {
621 if (sending_len == len_to_send) {
622 if ((sending_len == CMD_HDR_LEN) && (!fw_upload.is_hdr_data)) {
623 if ((first_chunk_sent == false) ||
624 (first_chunk_sent && fw_upload.is_error_case)) {
625 LOG_DBG("Send first chunk: len %d", sending_len);
626 fw_upload_write_data(buffer, sending_len);
627 fw_upload_update_result(payload_len, &sending_len,
628 &first_chunk_sent);
629 } else {
630 send_done = true;
631 break;
632 }
633 } else {
634 LOG_DBG("Send data: len %d", sending_len);
635 if (sending_len) {
636 fw_upload_write_data(&buffer[CMD_HDR_LEN], sending_len);
637 first_chunk_sent = true;
638 sending_len = CMD_HDR_LEN;
639 fw_upload.is_hdr_data = false;
640 if (new_speed) {
641 return 0;
642 }
643 } else {
644 LOG_DBG("Download Complete");
645 return 0;
646 }
647 }
648 } else {
649 if ((len_to_send & 0x01) == 0x01) {
650 if (len_to_send == (CMD_HDR_LEN + 1)) {
651 LOG_DBG("Resending first chunk...");
652 fw_upload_write_data(buffer, len_to_send - 1);
653 sending_len = payload_len;
654 first_chunk_sent = false;
655 } else if (len_to_send == (payload_len + 1)) {
656 LOG_DBG("Resending second chunk...");
657 fw_upload_write_data(&buffer[CMD_HDR_LEN], len_to_send - 1);
658 sending_len = CMD_HDR_LEN;
659 first_chunk_sent = true;
660 }
661 } else if (len_to_send == CMD_HDR_LEN) {
662 LOG_DBG("Resending send buffer...");
663 fw_upload_write_data(buffer, len_to_send);
664 sending_len = payload_len;
665 first_chunk_sent = false;
666 } else if (len_to_send == payload_len) {
667 LOG_DBG("Resending second chunk...");
668 fw_upload_write_data(&buffer[CMD_HDR_LEN], len_to_send);
669 sending_len = CMD_HDR_LEN;
670 first_chunk_sent = true;
671 }
672 }
673
674 err = fw_upload_get_last_5bytes(buffer);
675 if (err < 0) {
676 LOG_ERR("Fail to get response");
677 return err;
678 }
679
680 if (fw_upload_len_valid(fw_upload.last_5bytes_buffer, &len_to_send) == 0) {
681 fw_upload_send_ack(V1_REQUEST_ACK);
682 LOG_DBG("BOOT_HEADER_ACK 0x5a sent");
683 }
684 }
685 return len_to_send;
686 }
687
fw_upload_uart_reconfig(uint32_t speed,bool flow_control)688 static int fw_upload_uart_reconfig(uint32_t speed, bool flow_control)
689 {
690 struct uart_config config;
691 int err;
692
693 config.baudrate = speed;
694 config.data_bits = UART_CFG_DATA_BITS_8;
695 config.flow_ctrl = flow_control ? UART_CFG_FLOW_CTRL_RTS_CTS : UART_CFG_FLOW_CTRL_NONE;
696 config.parity = UART_CFG_PARITY_NONE;
697 config.stop_bits = UART_CFG_STOP_BITS_1;
698
699 uart_irq_rx_disable(uart_dev);
700 uart_irq_tx_disable(uart_dev);
701 fw_upload_read_to_clear();
702 err = uart_configure(uart_dev, &config);
703 uart_irq_rx_enable(uart_dev);
704
705 return err;
706 }
707
fw_upload_change_speed(uint8_t hdr)708 static int fw_upload_change_speed(uint8_t hdr)
709 {
710 int err;
711 uint32_t hdr_len;
712 bool load_payload = false;
713 bool recovery = false;
714 uint16_t len_to_send;
715 uint32_t crc;
716
717 err = fw_upload_change_speed_config(
718 (struct change_speed_config *)fw_upload.change_speed_buffer,
719 uart_dev_data.secondary_speed);
720 if (err) {
721 return err;
722 }
723
724 hdr_len = sizeof(fw_upload.change_speed_buffer);
725
726 fw_upload_gen_crc32_table();
727 crc = sys_cpu_to_le32(hdr_len);
728 memcpy(cmd5_hdrData + 8, &crc, 4);
729 crc = fw_upload_update_crc32(0, (char *)cmd5_hdrData, 12);
730 crc = sys_cpu_to_be32(crc);
731 memcpy(cmd5_hdrData + 12, &crc, CRC32_LEN);
732 crc = fw_upload_update_crc32(0, (char *)fw_upload.change_speed_buffer,
733 (int)sizeof(struct change_speed_config));
734 crc = sys_cpu_to_be32(crc);
735 memcpy(&fw_upload.change_speed_buffer[sizeof(struct change_speed_config)], &crc, CRC32_LEN);
736
737 while (true) {
738 err = fw_upload_wait_for_hdr_sig();
739
740 if (hdr && (err == 0)) {
741 if (load_payload) {
742 if (fw_upload.version == VER3) {
743 fw_upload.change_speed_buffer_len =
744 CMD_HDR_LEN + fw_upload.length;
745 }
746 return 0;
747 }
748 } else {
749 if (recovery) {
750 return -ETIME;
751 }
752
753 if (load_payload) {
754 LOG_ERR("HDR cannot be received by using second speed. receovery "
755 "speed");
756
757 err = fw_upload_uart_reconfig(uart_dev_data.primary_speed,
758 uart_dev_data.primary_flowcontrol);
759 if (err) {
760 return err;
761 }
762
763 load_payload = false;
764 recovery = true;
765 continue;
766 }
767 }
768
769 if (fw_upload.version == VER1) {
770 len_to_send = fw_upload_wait_length(0);
771 if (len_to_send == V1_START_INDICATION) {
772 return -EINVAL;
773 } else if (len_to_send == 0) {
774 continue;
775 } else if (len_to_send == CMD_HDR_LEN) {
776 memcpy(fw_upload.send_buffer, cmd5_hdrData, CMD_HDR_LEN);
777 memcpy(&fw_upload.send_buffer[CMD_HDR_LEN],
778 fw_upload.change_speed_buffer, hdr_len);
779
780 err = fw_upload_write_hdr_and_payload(len_to_send,
781 fw_upload.send_buffer, true);
782 if (err < 0) {
783 return err;
784 }
785
786 LOG_DBG("Change speed to %d", uart_dev_data.secondary_speed);
787
788 err = fw_upload_uart_reconfig(uart_dev_data.secondary_speed,
789 uart_dev_data.secondary_flowcontrol);
790 if (err) {
791 return err;
792 }
793 load_payload = true;
794 } else {
795 fw_upload_write_data(fw_upload.change_speed_buffer, hdr_len);
796
797 LOG_DBG("Change speed to %d", uart_dev_data.secondary_speed);
798
799 err = fw_upload_uart_reconfig(uart_dev_data.secondary_speed,
800 uart_dev_data.secondary_flowcontrol);
801 if (err) {
802 return err;
803 }
804 load_payload = true;
805 }
806 } else if (fw_upload.version == VER3) {
807 err = fw_upload_wait_req(true);
808 if (!(!hdr || (err == 0))) {
809 continue;
810 }
811 if (fw_upload.length && (fw_upload.hdr_sig == V3_HEADER_DATA_REQ)) {
812 if (fw_upload.error != 0) {
813 fw_upload_send_ack(V3_TIMEOUT_ACK);
814 continue;
815 }
816
817 fw_upload_send_ack(V3_REQUEST_ACK);
818 hdr = true;
819
820 if (fw_upload.length == CMD_HDR_LEN) {
821 LOG_DBG("Send CMD5");
822 fw_upload_write_data(cmd5_hdrData, fw_upload.length);
823 fw_upload.last_offset = fw_upload.offset;
824 } else {
825 LOG_DBG("Send UA RT config");
826 fw_upload_write_data(fw_upload.change_speed_buffer,
827 fw_upload.length);
828
829 LOG_DBG("Change speed to %d",
830 uart_dev_data.secondary_speed);
831
832 err = fw_upload_uart_reconfig(
833 uart_dev_data.secondary_speed,
834 uart_dev_data.secondary_flowcontrol);
835 if (err) {
836 return err;
837 }
838 load_payload = true;
839 }
840 }
841 }
842 }
843
844 return 0;
845 }
846
fw_upload_v1_send_data(uint16_t len)847 static int fw_upload_v1_send_data(uint16_t len)
848 {
849 uint32_t cmd;
850 uint32_t data_len;
851 int ret_len;
852
853 memset(fw_upload.send_buffer, 0, sizeof(fw_upload.send_buffer));
854
855 fw_upload.is_cmd7_req = false;
856 fw_upload.is_entry_point_req = false;
857
858 if ((fw_upload.fw_length - fw_upload.current_length) < len) {
859 len = fw_upload.fw_length - fw_upload.current_length;
860 }
861
862 memcpy(fw_upload.send_buffer, fw_upload.fw + fw_upload.current_length, len);
863 fw_upload.current_length += len;
864 cmd = sys_get_le32(fw_upload.send_buffer);
865 if (cmd == CMD7) {
866 fw_upload.is_cmd7_req = true;
867 data_len = 0;
868 } else {
869 data_len = fw_upload_get_payload_length(fw_upload.send_buffer);
870 if ((data_len > (sizeof(fw_upload.send_buffer) - len)) ||
871 ((data_len + fw_upload.current_length) > fw_upload.fw_length)) {
872 LOG_ERR("Invalid FW at %d/%d", fw_upload.current_length,
873 fw_upload.fw_length);
874 return -EINVAL;
875 }
876 memcpy(&fw_upload.send_buffer[len], fw_upload.fw + fw_upload.current_length,
877 data_len);
878 fw_upload.current_length += data_len;
879 if ((fw_upload.current_length < fw_upload.fw_length) &&
880 ((cmd == CMD6) || (cmd == CMD4))) {
881 fw_upload.is_entry_point_req = true;
882 }
883 }
884
885 ret_len = fw_upload_write_hdr_and_payload(len, fw_upload.send_buffer, false);
886 LOG_DBG("FW upload %d/%d", fw_upload.current_length, fw_upload.fw_length);
887
888 return ret_len;
889 }
890
fw_upload_v3_send_data(void)891 static int fw_upload_v3_send_data(void)
892 {
893 uint32_t start;
894
895 LOG_DBG("Sending offset %d", fw_upload.offset);
896 if (fw_upload.offset == fw_upload.last_offset) {
897 LOG_WRN("Resending offset %d ...", fw_upload.offset);
898 fw_upload_write_data(fw_upload.send_buffer, fw_upload.length);
899 return fw_upload.length;
900 }
901 memset(fw_upload.send_buffer, 0, sizeof(fw_upload.send_buffer));
902 start = fw_upload.offset - fw_upload.cmd7_change_timeout_len -
903 fw_upload.change_speed_buffer_len;
904 if (start >= fw_upload.fw_length) {
905 LOG_ERR("Invalid fw offset");
906 return -EINVAL;
907 }
908
909 if ((fw_upload.length + start) > fw_upload.fw_length) {
910 fw_upload.length = fw_upload.fw_length - start;
911 }
912 memcpy(fw_upload.send_buffer, fw_upload.fw + start, fw_upload.length);
913 fw_upload.current_length = start + fw_upload.length;
914
915 fw_upload_write_data(fw_upload.send_buffer, fw_upload.length);
916 fw_upload.last_offset = fw_upload.offset;
917
918 return fw_upload.length;
919 }
920
fw_uploading(const uint8_t * fw,uint32_t fw_length)921 static int fw_uploading(const uint8_t *fw, uint32_t fw_length)
922 {
923 int err;
924 bool secondary_speed = false;
925 uint16_t len_to_send;
926
927 fw_upload.wait_hdr_sig = true;
928 fw_upload.is_hdr_data = false;
929 fw_upload.is_error_case = false;
930 fw_upload.is_cmd7_req = false;
931 fw_upload.is_entry_point_req = false;
932 fw_upload.last_offset = 0xFFFFU;
933
934 err = fw_upload_change_timeout();
935 LOG_DBG("Change timeout hdr flag %d (err %d)", fw_upload.wait_hdr_sig, err);
936 if (err) {
937 return err;
938 }
939
940 fw_upload_read_to_clear();
941
942 if (uart_dev_data.secondary_speed &&
943 (uart_dev_data.secondary_speed != uart_dev_data.primary_speed)) {
944 LOG_DBG("Change speed to %d", uart_dev_data.secondary_speed);
945 err = fw_upload_change_speed(fw_upload.wait_hdr_sig);
946 if (err != 0) {
947 LOG_ERR("Fail to change speed");
948 return err;
949 }
950 secondary_speed = true;
951 }
952
953 fw_upload.fw_length = fw_length;
954 fw_upload.current_length = 0;
955 fw_upload.fw = fw;
956
957 while (true) {
958 err = fw_upload_wait_for_hdr_sig();
959 if (secondary_speed && (err != 0)) {
960 return -ETIME;
961 }
962
963 secondary_speed = false;
964
965 if (fw_upload.version == VER1) {
966 len_to_send = fw_upload_wait_length(true);
967
968 if (len_to_send == V1_START_INDICATION) {
969 continue;
970 }
971 while (len_to_send > 0) {
972 len_to_send = fw_upload_v1_send_data(len_to_send);
973 }
974 if (fw_upload.current_length >= fw_upload.fw_length) {
975 LOG_DBG("FW download done");
976 return 0;
977 }
978 LOG_ERR("FW download failed");
979 return len_to_send;
980 } else if (fw_upload.version == VER3) {
981 if (fw_upload.hdr_sig == V3_START_INDICATION) {
982 fw_upload_wait_req(false);
983 continue;
984 }
985 err = fw_upload_wait_req(false);
986 if (err) {
987 LOG_ERR("Fail to wait req");
988 return err;
989 }
990 if (fw_upload.length) {
991 if (fw_upload.error == 0) {
992 fw_upload_send_ack(V3_REQUEST_ACK);
993 err = fw_upload_v3_send_data();
994 if (err < 0) {
995 LOG_ERR("FW download failed");
996 return err;
997 }
998 } else {
999 LOG_DBG("Error occurs %d", fw_upload.error);
1000 fw_upload_send_ack(V3_TIMEOUT_ACK);
1001 if (fw_upload.error & BT_MIC_FAIL_BIT) {
1002 fw_upload.change_speed_buffer_len = 0;
1003 fw_upload.current_length = 0;
1004 fw_upload.last_offset = 0;
1005 }
1006 }
1007 } else {
1008 if (fw_upload.error == 0) {
1009 fw_upload_send_ack(V3_REQUEST_ACK);
1010 LOG_DBG("FW download done");
1011 return 0;
1012 }
1013 LOG_DBG("Error occurs %d", fw_upload.error);
1014 fw_upload_send_ack(V3_TIMEOUT_ACK);
1015 if (fw_upload.error & BT_MIC_FAIL_BIT) {
1016 fw_upload.change_speed_buffer_len = 0;
1017 fw_upload.current_length = 0;
1018 fw_upload.last_offset = 0;
1019 }
1020 }
1021 } else {
1022 return -ENOTSUP;
1023 }
1024 }
1025 return -EINVAL;
1026 }
1027
bt_nxp_ctlr_uart_isr(const struct device * unused,void * user_data)1028 static void bt_nxp_ctlr_uart_isr(const struct device *unused, void *user_data)
1029 {
1030 int err = 0;
1031 int count = 0;
1032
1033 ARG_UNUSED(unused);
1034 ARG_UNUSED(user_data);
1035
1036 while (uart_irq_update(uart_dev) && uart_irq_is_pending(uart_dev)) {
1037 err = uart_poll_in(uart_dev, &fw_upload.rx.buffer[fw_upload.rx.head]);
1038 if (err >= 0) {
1039 fw_upload.rx.head++;
1040 fw_upload.rx.head = fw_upload.rx.head % sizeof(fw_upload.rx.buffer);
1041 count++;
1042 }
1043 }
1044
1045 while (count > 0) {
1046 k_sem_give(&fw_upload.rx.sem);
1047 count--;
1048 }
1049 }
1050
bt_nxp_ctlr_init(void)1051 static int bt_nxp_ctlr_init(void)
1052 {
1053 int err;
1054 uint32_t speed;
1055 bool flowcontrol_of_hci;
1056
1057 if (!device_is_ready(uart_dev)) {
1058 return -ENODEV;
1059 }
1060
1061 speed = DT_PROP(DT_INST_GPARENT(0), current_speed);
1062 uart_dev_data.primary_speed = DT_PROP_OR(DT_DRV_INST(0), fw_download_primary_speed, speed);
1063 uart_dev_data.secondary_speed =
1064 DT_PROP_OR(DT_DRV_INST(0), fw_download_secondary_speed, speed);
1065
1066 flowcontrol_of_hci = (bool)DT_PROP_OR(DT_DRV_INST(0), hw_flow_control, false);
1067 uart_dev_data.primary_flowcontrol =
1068 (bool)DT_PROP_OR(DT_DRV_INST(0), fw_download_primary_flowcontrol, false);
1069 uart_dev_data.secondary_flowcontrol =
1070 (bool)DT_PROP_OR(DT_DRV_INST(0), fw_download_secondary_flowcontrol, false);
1071
1072 #if DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) || \
1073 DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios)
1074 #if DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios)
1075 /* Check BT REG_ON gpio instance */
1076 if (!gpio_is_ready_dt(&sdio_reset)) {
1077 LOG_ERR("Error: failed to configure sdio_reset %s pin %d", sdio_reset.port->name,
1078 sdio_reset.pin);
1079 return -EIO;
1080 }
1081
1082 /* Configure sdio_reset as output */
1083 err = gpio_pin_configure_dt(&sdio_reset, GPIO_OUTPUT);
1084 if (err) {
1085 LOG_ERR("Error %d: failed to configure sdio_reset %s pin %d", err,
1086 sdio_reset.port->name, sdio_reset.pin);
1087 return err;
1088 }
1089 err = gpio_pin_set_dt(&sdio_reset, 0);
1090 if (err) {
1091 return err;
1092 }
1093 #endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) */
1094
1095 #if DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios)
1096 /* Check BT REG_ON gpio instance */
1097 if (!gpio_is_ready_dt(&w_disable)) {
1098 LOG_ERR("Error: failed to configure w_disable %s pin %d", w_disable.port->name,
1099 w_disable.pin);
1100 return -EIO;
1101 }
1102
1103 /* Configure w_disable as output */
1104 err = gpio_pin_configure_dt(&w_disable, GPIO_OUTPUT);
1105 if (err) {
1106 LOG_ERR("Error %d: failed to configure w_disable %s pin %d", err,
1107 w_disable.port->name, w_disable.pin);
1108 return err;
1109 }
1110 err = gpio_pin_set_dt(&w_disable, 0);
1111 if (err) {
1112 return err;
1113 }
1114 #endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) */
1115
1116 /* wait for reset done */
1117 k_sleep(K_MSEC(100));
1118
1119 #if DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios)
1120 err = gpio_pin_set_dt(&sdio_reset, 1);
1121 if (err) {
1122 return err;
1123 }
1124 #endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) */
1125
1126 #if DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios)
1127 err = gpio_pin_set_dt(&w_disable, 1);
1128 if (err) {
1129 return err;
1130 }
1131 #endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) */
1132 #endif
1133
1134 uart_irq_rx_disable(uart_dev);
1135 uart_irq_tx_disable(uart_dev);
1136
1137 fw_upload.rx.head = 0;
1138 fw_upload.rx.tail = 0;
1139
1140 k_sem_init(&fw_upload.rx.sem, 0, sizeof(fw_upload.rx.buffer));
1141
1142 uart_irq_callback_set(uart_dev, bt_nxp_ctlr_uart_isr);
1143
1144 made_table = false;
1145
1146 err = fw_upload_uart_reconfig(uart_dev_data.primary_speed,
1147 uart_dev_data.primary_flowcontrol);
1148 if (err) {
1149 LOG_ERR("Fail to config uart");
1150 return err;
1151 }
1152
1153 uart_irq_rx_enable(uart_dev);
1154
1155 err = fw_uploading(bt_fw_bin, bt_fw_bin_len);
1156
1157 if (err) {
1158 LOG_ERR("Fail to upload firmware");
1159 return err;
1160 }
1161
1162 (void)fw_upload_uart_reconfig(speed, flowcontrol_of_hci);
1163
1164 uart_irq_rx_disable(uart_dev);
1165 uart_irq_tx_disable(uart_dev);
1166
1167 k_sleep(K_MSEC(CONFIG_BT_H4_NXP_CTLR_WAIT_TIME_AFTER_UPLOAD));
1168
1169 return 0;
1170 }
1171
bt_hci_transport_setup(const struct device * dev)1172 int bt_hci_transport_setup(const struct device *dev)
1173 {
1174 if (dev != uart_dev) {
1175 return -EINVAL;
1176 }
1177
1178 return bt_nxp_ctlr_init();
1179 }
1180
1181 #define BT_HCI_VSC_BAUDRATE_UPDATE_LENGTH 4
1182 #define BT_HCI_VSC_BAUDRATE_UPDATE_OPCODE BT_OP(BT_OGF_VS, 0x09)
1183
bt_hci_baudrate_update(const struct device * dev,uint32_t baudrate)1184 static int bt_hci_baudrate_update(const struct device *dev, uint32_t baudrate)
1185 {
1186 int err;
1187 struct net_buf *buf;
1188
1189 buf = bt_hci_cmd_create(BT_HCI_VSC_BAUDRATE_UPDATE_OPCODE,
1190 BT_HCI_VSC_BAUDRATE_UPDATE_LENGTH);
1191 if (!buf) {
1192 LOG_ERR("Fail to allocate buffer");
1193 return -ENOBUFS;
1194 }
1195
1196 /* Add new baudrate to the buffer */
1197 net_buf_add_le32(buf, baudrate);
1198
1199 err = bt_hci_cmd_send_sync(BT_HCI_VSC_BAUDRATE_UPDATE_OPCODE, buf, NULL);
1200 if (err) {
1201 LOG_ERR("Fail to send baudrate update cmd");
1202 return err;
1203 }
1204
1205 return 0;
1206 }
1207
bt_h4_vnd_setup(const struct device * dev)1208 int bt_h4_vnd_setup(const struct device *dev)
1209 {
1210 int err;
1211 uint32_t default_speed;
1212 uint32_t operation_speed;
1213 bool flowcontrol_of_hci;
1214
1215 if (dev != uart_dev) {
1216 return -EINVAL;
1217 }
1218
1219 if (!device_is_ready(uart_dev)) {
1220 return -ENODEV;
1221 }
1222
1223 default_speed = DT_PROP(DT_INST_GPARENT(0), current_speed);
1224 operation_speed = DT_PROP_OR(DT_DRV_INST(0), hci_operation_speed, default_speed);
1225 flowcontrol_of_hci = (bool)DT_PROP_OR(DT_DRV_INST(0), hw_flow_control, false);
1226
1227 if (operation_speed == default_speed) {
1228 return 0;
1229 }
1230
1231 err = bt_hci_baudrate_update(dev, operation_speed);
1232 if (err) {
1233 return err;
1234 }
1235
1236 /* BT waiting time after controller bandrate updated */
1237 (void)k_msleep(CONFIG_BT_H4_NXP_CTLR_WAIT_TIME_AFTER_BAUDRATE_UPDATE);
1238
1239 err = fw_upload_uart_reconfig(operation_speed, flowcontrol_of_hci);
1240 if (err) {
1241 LOG_ERR("Fail to update uart bandrate");
1242 return err;
1243 }
1244
1245 return 0;
1246 }
1247