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