[PATCH v1 1/3] Bluetooth: btnxpuart: Add correct bootloader error codes

From: Neeraj Sanjay Kale
Date: Wed Mar 05 2025 - 08:47:27 EST


This corrects the bootloader error codes for NXP chipsets.
Since we have a common handling for all error codes, there is no backward
compatibility issue.
Added error handling for CRC error code in V3 bootloader signature.

Fixes: 27489364299a ("Bluetooth: btnxpuart: Add handling for boot-signature timeout errors")
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@xxxxxxx>
---
drivers/bluetooth/btnxpuart.c | 57 +++++++++++++++++++++--------------
1 file changed, 35 insertions(+), 22 deletions(-)

diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 021983686cb3..b8a00bf062e2 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -204,10 +204,11 @@ struct btnxpuart_dev {
#define NXP_NAK_V3 0x7b
#define NXP_CRC_ERROR_V3 0x7c

-/* Bootloader signature error codes */
-#define NXP_ACK_RX_TIMEOUT 0x0002 /* ACK not received from host */
-#define NXP_HDR_RX_TIMEOUT 0x0003 /* FW Header chunk not received */
-#define NXP_DATA_RX_TIMEOUT 0x0004 /* FW Data chunk not received */
+/* Bootloader signature error codes: Refer AN12820 from nxp.com */
+#define NXP_CRC_RX_ERROR BIT(0) /* CRC error in previous packet */
+#define NXP_ACK_RX_TIMEOUT BIT(2) /* ACK not received from host */
+#define NXP_HDR_RX_TIMEOUT BIT(3) /* FW Header chunk not received */
+#define NXP_DATA_RX_TIMEOUT BIT(4) /* FW Data chunk not received */

#define HDR_LEN 16

@@ -310,6 +311,16 @@ union nxp_v3_rx_timeout_nak_u {
u8 buf[6];
};

+struct nxp_v3_crc_nak {
+ u8 nak;
+ u8 crc;
+} __packed;
+
+union nxp_v3_crc_nak_u {
+ struct nxp_v3_crc_nak pkt;
+ u8 buf[2];
+};
+
static u8 crc8_table[CRC8_TABLE_SIZE];

/* Default configurations */
@@ -1059,25 +1070,27 @@ static void nxp_handle_fw_download_error(struct hci_dev *hdev, struct v3_data_re
struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
__u32 offset = __le32_to_cpu(req->offset);
__u16 err = __le16_to_cpu(req->error);
- union nxp_v3_rx_timeout_nak_u nak_tx_buf;
-
- switch (err) {
- case NXP_ACK_RX_TIMEOUT:
- case NXP_HDR_RX_TIMEOUT:
- case NXP_DATA_RX_TIMEOUT:
- nak_tx_buf.pkt.nak = NXP_NAK_V3;
- nak_tx_buf.pkt.offset = __cpu_to_le32(offset);
- nak_tx_buf.pkt.crc = crc8(crc8_table, nak_tx_buf.buf,
- sizeof(nak_tx_buf) - 1, 0xff);
- serdev_device_write_buf(nxpdev->serdev, nak_tx_buf.buf,
- sizeof(nak_tx_buf));
- break;
- default:
- bt_dev_dbg(hdev, "Unknown bootloader error code: %d", err);
- break;
-
+ union nxp_v3_rx_timeout_nak_u timeout_nak_buf;
+ union nxp_v3_crc_nak_u crc_nak_buf;
+
+ if (err & NXP_CRC_RX_ERROR) {
+ crc_nak_buf.pkt.nak = NXP_CRC_ERROR_V3;
+ crc_nak_buf.pkt.crc = crc8(crc8_table, crc_nak_buf.buf,
+ sizeof(crc_nak_buf) - 1, 0xff);
+ serdev_device_write_buf(nxpdev->serdev, crc_nak_buf.buf,
+ sizeof(crc_nak_buf));
+ } else if (err & NXP_ACK_RX_TIMEOUT ||
+ err & NXP_HDR_RX_TIMEOUT ||
+ err & NXP_DATA_RX_TIMEOUT) {
+ timeout_nak_buf.pkt.nak = NXP_NAK_V3;
+ timeout_nak_buf.pkt.offset = __cpu_to_le32(offset);
+ timeout_nak_buf.pkt.crc = crc8(crc8_table, timeout_nak_buf.buf,
+ sizeof(timeout_nak_buf) - 1, 0xff);
+ serdev_device_write_buf(nxpdev->serdev, timeout_nak_buf.buf,
+ sizeof(timeout_nak_buf));
+ } else {
+ bt_dev_err(hdev, "Unknown bootloader error code: %d", err);
}
-
}

static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
--
2.25.1