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