#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
 
        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;
                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);
                        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;
                }
                        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);
        }
 
        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;
        }
        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)
        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);