]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Bluetooth: btnxpuart: Add support for 4M baudrate
authorNeeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Mon, 23 Jun 2025 09:13:22 +0000 (14:43 +0530)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 23 Jul 2025 14:26:48 +0000 (10:26 -0400)
This adds support for 4000000 as secondary baudrate.

This value is selected from device tree property "max-speed"
which is then used to download FW chunks, and as operational baudrate after
HCI initialization is done.

Earlier, the secondary baudrate was fixed to 3000000 in driver, but now
with "max-speed" property, this secondary baudrate can be set to
4000000.

The secondary baudrate is set by the driver by sending a vendor command
(3F 09) to the firmware, with secondary baudrate parameter, in
nxp_post_init().

Any other value set for max-speed other than 3000000 or 4000000 will
default to 3000000, which is supported by all legacy and new NXP chipsets.

This feature is applicable for all new V3 bootloader chips and w8987 V1
bootloader chip.

This property does not apply for w8997 compatible device, since it
downloads a helper.bin FW file that sets secondary baudrate as 3000000
only.

The switch to 4000000 baudrate is validated using a Saleae Logic Analyzer
and imx8m-mini with AW693 M.2 module.

Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
drivers/bluetooth/btnxpuart.c

index 24f9b52605a1b3a6e79d563211baa8daa30d50f2..7c6592bf773cb1af10aaa4fa818f9879de80617a 100644 (file)
@@ -73,7 +73,8 @@
 #define FW_AUTH_ENC            0xc0
 
 #define HCI_NXP_PRI_BAUDRATE   115200
-#define HCI_NXP_SEC_BAUDRATE   3000000
+#define HCI_NXP_SEC_BAUDRATE_3M        3000000
+#define HCI_NXP_SEC_BAUDRATE_4M        4000000
 
 #define MAX_FW_FILE_NAME_LEN    50
 
@@ -201,6 +202,7 @@ struct btnxpuart_dev {
        u32 new_baudrate;
        u32 current_baudrate;
        u32 fw_init_baudrate;
+       u32 secondary_baudrate;
        enum bootloader_param_change timeout_changed;
        enum bootloader_param_change baudrate_changed;
        bool helper_downloaded;
@@ -802,7 +804,10 @@ static bool nxp_fw_change_baudrate(struct hci_dev *hdev, u16 req_len)
                nxpdev->fw_v3_offset_correction += req_len;
        } else if (req_len == sizeof(uart_config)) {
                uart_config.clkdiv.address = __cpu_to_le32(clkdivaddr);
-               uart_config.clkdiv.value = __cpu_to_le32(0x00c00000);
+               if (nxpdev->new_baudrate == HCI_NXP_SEC_BAUDRATE_4M)
+                       uart_config.clkdiv.value = __cpu_to_le32(0x01000000);
+               else
+                       uart_config.clkdiv.value = __cpu_to_le32(0x00c00000);
                uart_config.uartdiv.address = __cpu_to_le32(uartdivaddr);
                uart_config.uartdiv.value = __cpu_to_le32(1);
                uart_config.mcr.address = __cpu_to_le32(uartmcraddr);
@@ -966,12 +971,13 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
                        goto free_skb;
                }
                if (nxpdev->baudrate_changed != changed) {
+                       nxpdev->new_baudrate = nxpdev->secondary_baudrate;
                        if (nxp_fw_change_baudrate(hdev, len)) {
                                nxpdev->baudrate_changed = changed;
                                serdev_device_set_baudrate(nxpdev->serdev,
-                                                          HCI_NXP_SEC_BAUDRATE);
+                                                          nxpdev->secondary_baudrate);
                                serdev_device_set_flow_control(nxpdev->serdev, true);
-                               nxpdev->current_baudrate = HCI_NXP_SEC_BAUDRATE;
+                               nxpdev->current_baudrate = nxpdev->secondary_baudrate;
                        }
                        goto free_skb;
                }
@@ -992,7 +998,7 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
                        nxpdev->helper_downloaded = true;
                        serdev_device_wait_until_sent(nxpdev->serdev, 0);
                        serdev_device_set_baudrate(nxpdev->serdev,
-                                                  HCI_NXP_SEC_BAUDRATE);
+                                                  HCI_NXP_SEC_BAUDRATE_3M);
                        serdev_device_set_flow_control(nxpdev->serdev, true);
                } else {
                        clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
@@ -1216,12 +1222,13 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
        }
 
        if (nxpdev->baudrate_changed != changed) {
+               nxpdev->new_baudrate = nxpdev->secondary_baudrate;
                if (nxp_fw_change_baudrate(hdev, len)) {
                        nxpdev->baudrate_changed = cmd_sent;
                        serdev_device_set_baudrate(nxpdev->serdev,
-                                                  HCI_NXP_SEC_BAUDRATE);
+                                                  nxpdev->secondary_baudrate);
                        serdev_device_set_flow_control(nxpdev->serdev, true);
-                       nxpdev->current_baudrate = HCI_NXP_SEC_BAUDRATE;
+                       nxpdev->current_baudrate = nxpdev->secondary_baudrate;
                }
                goto free_skb;
        }
@@ -1447,8 +1454,8 @@ static int nxp_post_init(struct hci_dev *hdev)
        struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
        struct ps_data *psdata = &nxpdev->psdata;
 
-       if (nxpdev->current_baudrate != HCI_NXP_SEC_BAUDRATE) {
-               nxpdev->new_baudrate = HCI_NXP_SEC_BAUDRATE;
+       if (nxpdev->current_baudrate != nxpdev->secondary_baudrate) {
+               nxpdev->new_baudrate = nxpdev->secondary_baudrate;
                nxp_set_baudrate_cmd(hdev, NULL);
        }
        if (psdata->cur_h2c_wakeupmode != psdata->h2c_wakeupmode)
@@ -1773,6 +1780,17 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
        if (!nxpdev->fw_init_baudrate)
                nxpdev->fw_init_baudrate = FW_INIT_BAUDRATE;
 
+       device_property_read_u32(&nxpdev->serdev->dev, "max-speed",
+                                &nxpdev->secondary_baudrate);
+       if (!nxpdev->secondary_baudrate ||
+           (nxpdev->secondary_baudrate != HCI_NXP_SEC_BAUDRATE_3M &&
+            nxpdev->secondary_baudrate != HCI_NXP_SEC_BAUDRATE_4M)) {
+               if (nxpdev->secondary_baudrate)
+                       dev_err(&serdev->dev,
+                               "Invalid max-speed. Using default 3000000.");
+               nxpdev->secondary_baudrate = HCI_NXP_SEC_BAUDRATE_3M;
+       }
+
        set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
 
        crc8_populate_msb(crc8_table, POLYNOMIAL8);