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