Merge tag 'nfs-for-4.20-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[sfrench/cifs-2.6.git] / drivers / net / wireless / ath / ath10k / core.c
index c40cd129afe7b2c006fff3d8b270add0a3843d32..da607febfd8200fffbdd5cfa575866a7f99cd04b 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/of.h>
+#include <linux/property.h>
 #include <linux/dmi.h>
 #include <linux/ctype.h>
 #include <asm/byteorder.h>
@@ -63,6 +64,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
        {
                .id = QCA988X_HW_2_0_VERSION,
                .dev_id = QCA988X_2_0_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca988x hw2.0",
                .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
                .uart_pin = 7,
@@ -84,13 +86,14 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 8,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
                .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA988X_HW_2_0_VERSION,
@@ -116,7 +119,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 8,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -124,10 +126,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA9887_HW_1_0_VERSION,
                .dev_id = QCA9887_1_0_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca9887 hw1.0",
                .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
                .uart_pin = 7,
@@ -149,7 +154,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 8,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -157,10 +161,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA6174_HW_2_1_VERSION,
                .dev_id = QCA6164_2_1_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca6164 hw2.1",
                .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
                .uart_pin = 6,
@@ -181,7 +188,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 8,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -189,10 +195,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA6174_HW_2_1_VERSION,
                .dev_id = QCA6174_2_1_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca6174 hw2.1",
                .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
                .uart_pin = 6,
@@ -213,7 +222,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 8,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -221,10 +229,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA6174_HW_3_0_VERSION,
                .dev_id = QCA6174_2_1_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca6174 hw3.0",
                .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
                .uart_pin = 6,
@@ -245,7 +256,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 8,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -253,10 +263,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA6174_HW_3_2_VERSION,
                .dev_id = QCA6174_2_1_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca6174 hw3.2",
                .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
                .uart_pin = 6,
@@ -280,7 +293,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 8,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -288,10 +300,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = true,
        },
        {
                .id = QCA99X0_HW_2_0_DEV_VERSION,
                .dev_id = QCA99X0_2_0_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca99x0 hw2.0",
                .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
                .uart_pin = 7,
@@ -318,7 +333,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 11,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -326,10 +340,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA9984_HW_1_0_DEV_VERSION,
                .dev_id = QCA9984_1_0_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca9984/qca9994 hw1.0",
                .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
                .uart_pin = 7,
@@ -346,8 +363,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .fw = {
                        .dir = QCA9984_HW_1_0_FW_DIR,
                        .board = QCA9984_HW_1_0_BOARD_DATA_FILE,
+                       .eboard = QCA9984_HW_1_0_EBOARD_DATA_FILE,
                        .board_size = QCA99X0_BOARD_DATA_SZ,
                        .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
+                       .ext_board_size = QCA99X0_EXT_BOARD_DATA_SZ,
                },
                .sw_decrypt_mcast_mgmt = true,
                .hw_ops = &qca99x0_ops,
@@ -361,7 +380,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 1560,
                .vht160_mcs_tx_highest = 1560,
                .n_cipher_suites = 11,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -369,10 +387,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA9888_HW_2_0_DEV_VERSION,
                .dev_id = QCA9888_2_0_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca9888 hw2.0",
                .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
                .uart_pin = 7,
@@ -403,7 +424,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 780,
                .vht160_mcs_tx_highest = 780,
                .n_cipher_suites = 11,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -411,10 +431,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA9377_HW_1_0_DEV_VERSION,
                .dev_id = QCA9377_1_0_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca9377 hw1.0",
                .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
                .uart_pin = 6,
@@ -435,7 +458,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 8,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -443,10 +465,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = QCA9377_HW_1_1_DEV_VERSION,
                .dev_id = QCA9377_1_0_DEVICE_ID,
+               .bus = ATH10K_BUS_PCI,
                .name = "qca9377 hw1.1",
                .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
                .uart_pin = 6,
@@ -469,7 +494,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 8,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -477,10 +501,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = true,
        },
        {
                .id = QCA4019_HW_1_0_DEV_VERSION,
                .dev_id = 0,
+               .bus = ATH10K_BUS_AHB,
                .name = "qca4019 hw1.0",
                .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR,
                .uart_pin = 7,
@@ -508,7 +535,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .vht160_mcs_rx_highest = 0,
                .vht160_mcs_tx_highest = 0,
                .n_cipher_suites = 11,
-               .num_peers = TARGET_TLV_NUM_PEERS,
                .ast_skid_limit = 0x10,
                .num_wds_entries = 0x20,
                .target_64bit = false,
@@ -516,10 +542,13 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = false,
                .shadow_reg_support = false,
                .rri_on_ddr = false,
+               .hw_filter_reset_required = true,
+               .fw_diag_ce_download = false,
        },
        {
                .id = WCN3990_HW_1_0_DEV_VERSION,
                .dev_id = 0,
+               .bus = ATH10K_BUS_PCI,
                .name = "wcn3990 hw1.0",
                .continuous_frag_desc = true,
                .tx_chain_mask = 0x7,
@@ -539,6 +568,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .per_ce_irq = true,
                .shadow_reg_support = true,
                .rri_on_ddr = true,
+               .hw_filter_reset_required = false,
+               .fw_diag_ce_download = false,
        },
 };
 
@@ -762,153 +793,11 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
        return 0;
 }
 
-static int ath10k_download_board_data(struct ath10k *ar, const void *data,
-                                     size_t data_len)
-{
-       u32 board_data_size = ar->hw_params.fw.board_size;
-       u32 address;
-       int ret;
-
-       ret = ath10k_push_board_ext_data(ar, data, data_len);
-       if (ret) {
-               ath10k_err(ar, "could not push board ext data (%d)\n", ret);
-               goto exit;
-       }
-
-       ret = ath10k_bmi_read32(ar, hi_board_data, &address);
-       if (ret) {
-               ath10k_err(ar, "could not read board data addr (%d)\n", ret);
-               goto exit;
-       }
-
-       ret = ath10k_bmi_write_memory(ar, address, data,
-                                     min_t(u32, board_data_size,
-                                           data_len));
-       if (ret) {
-               ath10k_err(ar, "could not write board data (%d)\n", ret);
-               goto exit;
-       }
-
-       ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1);
-       if (ret) {
-               ath10k_err(ar, "could not write board data bit (%d)\n", ret);
-               goto exit;
-       }
-
-exit:
-       return ret;
-}
-
-static int ath10k_download_cal_file(struct ath10k *ar,
-                                   const struct firmware *file)
-{
-       int ret;
-
-       if (!file)
-               return -ENOENT;
-
-       if (IS_ERR(file))
-               return PTR_ERR(file);
-
-       ret = ath10k_download_board_data(ar, file->data, file->size);
-       if (ret) {
-               ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
-               return ret;
-       }
-
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");
-
-       return 0;
-}
-
-static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
-{
-       struct device_node *node;
-       int data_len;
-       void *data;
-       int ret;
-
-       node = ar->dev->of_node;
-       if (!node)
-               /* Device Tree is optional, don't print any warnings if
-                * there's no node for ath10k.
-                */
-               return -ENOENT;
-
-       if (!of_get_property(node, dt_name, &data_len)) {
-               /* The calibration data node is optional */
-               return -ENOENT;
-       }
-
-       if (data_len != ar->hw_params.cal_data_len) {
-               ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
-                           data_len);
-               ret = -EMSGSIZE;
-               goto out;
-       }
-
-       data = kmalloc(data_len, GFP_KERNEL);
-       if (!data) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       ret = of_property_read_u8_array(node, dt_name, data, data_len);
-       if (ret) {
-               ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
-                           ret);
-               goto out_free;
-       }
-
-       ret = ath10k_download_board_data(ar, data, data_len);
-       if (ret) {
-               ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n",
-                           ret);
-               goto out_free;
-       }
-
-       ret = 0;
-
-out_free:
-       kfree(data);
-
-out:
-       return ret;
-}
-
-static int ath10k_download_cal_eeprom(struct ath10k *ar)
-{
-       size_t data_len;
-       void *data = NULL;
-       int ret;
-
-       ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len);
-       if (ret) {
-               if (ret != -EOPNOTSUPP)
-                       ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n",
-                                   ret);
-               goto out_free;
-       }
-
-       ret = ath10k_download_board_data(ar, data, data_len);
-       if (ret) {
-               ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n",
-                           ret);
-               goto out_free;
-       }
-
-       ret = 0;
-
-out_free:
-       kfree(data);
-
-       return ret;
-}
-
 static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
 {
        u32 result, address;
        u8 board_id, chip_id;
+       bool ext_bid_support;
        int ret, bmi_board_id_param;
 
        address = ar->hw_params.patch_load_addr;
@@ -948,10 +837,13 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
 
        board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP);
        chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP);
+       ext_bid_support = (result & ATH10K_BMI_EXT_BOARD_ID_SUPPORT);
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT,
-                  "boot get otp board id result 0x%08x board_id %d chip_id %d\n",
-                  result, board_id, chip_id);
+                  "boot get otp board id result 0x%08x board_id %d chip_id %d ext_bid_support %d\n",
+                  result, board_id, chip_id, ext_bid_support);
+
+       ar->id.ext_bid_supported = ext_bid_support;
 
        if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 ||
            (board_id == 0)) {
@@ -1055,64 +947,6 @@ static int ath10k_core_check_dt(struct ath10k *ar)
        return 0;
 }
 
-static int ath10k_download_and_run_otp(struct ath10k *ar)
-{
-       u32 result, address = ar->hw_params.patch_load_addr;
-       u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param;
-       int ret;
-
-       ret = ath10k_download_board_data(ar,
-                                        ar->running_fw->board_data,
-                                        ar->running_fw->board_len);
-       if (ret) {
-               ath10k_err(ar, "failed to download board data: %d\n", ret);
-               return ret;
-       }
-
-       /* OTP is optional */
-
-       if (!ar->running_fw->fw_file.otp_data ||
-           !ar->running_fw->fw_file.otp_len) {
-               ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n",
-                           ar->running_fw->fw_file.otp_data,
-                           ar->running_fw->fw_file.otp_len);
-               return 0;
-       }
-
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
-                  address, ar->running_fw->fw_file.otp_len);
-
-       ret = ath10k_bmi_fast_download(ar, address,
-                                      ar->running_fw->fw_file.otp_data,
-                                      ar->running_fw->fw_file.otp_len);
-       if (ret) {
-               ath10k_err(ar, "could not write otp (%d)\n", ret);
-               return ret;
-       }
-
-       /* As of now pre-cal is valid for 10_4 variants */
-       if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
-           ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
-               bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
-
-       ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
-       if (ret) {
-               ath10k_err(ar, "could not execute otp (%d)\n", ret);
-               return ret;
-       }
-
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
-
-       if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
-                                  ar->running_fw->fw_file.fw_features)) &&
-           result != 0) {
-               ath10k_err(ar, "otp calibration failed: %d", result);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int ath10k_download_fw(struct ath10k *ar)
 {
        u32 address, data_len;
@@ -1135,25 +969,42 @@ static int ath10k_download_fw(struct ath10k *ar)
                   "boot uploading firmware image %pK len %d\n",
                   data, data_len);
 
-       ret = ath10k_bmi_fast_download(ar, address, data, data_len);
-       if (ret) {
-               ath10k_err(ar, "failed to download firmware: %d\n",
-                          ret);
-               return ret;
+       /* Check if device supports to download firmware via
+        * diag copy engine. Downloading firmware via diag CE
+        * greatly reduces the time to download firmware.
+        */
+       if (ar->hw_params.fw_diag_ce_download) {
+               ret = ath10k_hw_diag_fast_download(ar, address,
+                                                  data, data_len);
+               if (ret == 0)
+                       /* firmware upload via diag ce was successful */
+                       return 0;
+
+               ath10k_warn(ar,
+                           "failed to upload firmware via diag ce, trying BMI: %d",
+                           ret);
        }
 
-       return ret;
+       return ath10k_bmi_fast_download(ar, address,
+                                       data, data_len);
 }
 
-static void ath10k_core_free_board_files(struct ath10k *ar)
+void ath10k_core_free_board_files(struct ath10k *ar)
 {
        if (!IS_ERR(ar->normal_mode_fw.board))
                release_firmware(ar->normal_mode_fw.board);
 
+       if (!IS_ERR(ar->normal_mode_fw.ext_board))
+               release_firmware(ar->normal_mode_fw.ext_board);
+
        ar->normal_mode_fw.board = NULL;
        ar->normal_mode_fw.board_data = NULL;
        ar->normal_mode_fw.board_len = 0;
+       ar->normal_mode_fw.ext_board = NULL;
+       ar->normal_mode_fw.ext_board_data = NULL;
+       ar->normal_mode_fw.ext_board_len = 0;
 }
+EXPORT_SYMBOL(ath10k_core_free_board_files);
 
 static void ath10k_core_free_firmware_files(struct ath10k *ar)
 {
@@ -1206,28 +1057,47 @@ success:
        return 0;
 }
 
-static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar)
+static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
 {
-       if (!ar->hw_params.fw.board) {
-               ath10k_err(ar, "failed to find board file fw entry\n");
-               return -EINVAL;
-       }
+       const struct firmware *fw;
 
-       ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
-                                                       ar->hw_params.fw.dir,
-                                                       ar->hw_params.fw.board);
-       if (IS_ERR(ar->normal_mode_fw.board))
-               return PTR_ERR(ar->normal_mode_fw.board);
+       if (bd_ie_type == ATH10K_BD_IE_BOARD) {
+               if (!ar->hw_params.fw.board) {
+                       ath10k_err(ar, "failed to find board file fw entry\n");
+                       return -EINVAL;
+               }
+
+               ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
+                                                               ar->hw_params.fw.dir,
+                                                               ar->hw_params.fw.board);
+               if (IS_ERR(ar->normal_mode_fw.board))
+                       return PTR_ERR(ar->normal_mode_fw.board);
+
+               ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data;
+               ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size;
+       } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
+               if (!ar->hw_params.fw.eboard) {
+                       ath10k_err(ar, "failed to find eboard file fw entry\n");
+                       return -EINVAL;
+               }
 
-       ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data;
-       ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size;
+               fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
+                                         ar->hw_params.fw.eboard);
+               ar->normal_mode_fw.ext_board = fw;
+               if (IS_ERR(ar->normal_mode_fw.ext_board))
+                       return PTR_ERR(ar->normal_mode_fw.ext_board);
+
+               ar->normal_mode_fw.ext_board_data = ar->normal_mode_fw.ext_board->data;
+               ar->normal_mode_fw.ext_board_len = ar->normal_mode_fw.ext_board->size;
+       }
 
        return 0;
 }
 
 static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,
                                         const void *buf, size_t buf_len,
-                                        const char *boardname)
+                                        const char *boardname,
+                                        int bd_ie_type)
 {
        const struct ath10k_fw_ie *hdr;
        bool name_match_found;
@@ -1276,12 +1146,21 @@ static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,
                                /* no match found */
                                break;
 
-                       ath10k_dbg(ar, ATH10K_DBG_BOOT,
-                                  "boot found board data for '%s'",
-                                  boardname);
+                       if (bd_ie_type == ATH10K_BD_IE_BOARD) {
+                               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                                          "boot found board data for '%s'",
+                                               boardname);
+
+                               ar->normal_mode_fw.board_data = board_ie_data;
+                               ar->normal_mode_fw.board_len = board_ie_len;
+                       } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
+                               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                                          "boot found eboard data for '%s'",
+                                               boardname);
 
-                       ar->normal_mode_fw.board_data = board_ie_data;
-                       ar->normal_mode_fw.board_len = board_ie_len;
+                               ar->normal_mode_fw.ext_board_data = board_ie_data;
+                               ar->normal_mode_fw.ext_board_len = board_ie_len;
+                       }
 
                        ret = 0;
                        goto out;
@@ -1322,172 +1201,506 @@ static int ath10k_core_search_bd(struct ath10k *ar,
                len -= sizeof(*hdr);
                data = hdr->data;
 
-               if (len < ALIGN(ie_len, 4)) {
-                       ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n",
-                                  ie_id, ie_len, len);
-                       return -EINVAL;
-               }
+               if (len < ALIGN(ie_len, 4)) {
+                       ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n",
+                                  ie_id, ie_len, len);
+                       return -EINVAL;
+               }
+
+               switch (ie_id) {
+               case ATH10K_BD_IE_BOARD:
+                       ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
+                                                           boardname,
+                                                           ATH10K_BD_IE_BOARD);
+                       if (ret == -ENOENT)
+                               /* no match found, continue */
+                               break;
+
+                       /* either found or error, so stop searching */
+                       goto out;
+               case ATH10K_BD_IE_BOARD_EXT:
+                       ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
+                                                           boardname,
+                                                           ATH10K_BD_IE_BOARD_EXT);
+                       if (ret == -ENOENT)
+                               /* no match found, continue */
+                               break;
+
+                       /* either found or error, so stop searching */
+                       goto out;
+               }
+
+               /* jump over the padding */
+               ie_len = ALIGN(ie_len, 4);
+
+               len -= ie_len;
+               data += ie_len;
+       }
+
+out:
+       /* return result of parse_bd_ie_board() or -ENOENT */
+       return ret;
+}
+
+static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
+                                             const char *boardname,
+                                             const char *fallback_boardname,
+                                             const char *filename)
+{
+       size_t len, magic_len;
+       const u8 *data;
+       int ret;
+
+       /* Skip if already fetched during board data download */
+       if (!ar->normal_mode_fw.board)
+               ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
+                                                               ar->hw_params.fw.dir,
+                                                               filename);
+       if (IS_ERR(ar->normal_mode_fw.board))
+               return PTR_ERR(ar->normal_mode_fw.board);
+
+       data = ar->normal_mode_fw.board->data;
+       len = ar->normal_mode_fw.board->size;
+
+       /* magic has extra null byte padded */
+       magic_len = strlen(ATH10K_BOARD_MAGIC) + 1;
+       if (len < magic_len) {
+               ath10k_err(ar, "failed to find magic value in %s/%s, file too short: %zu\n",
+                          ar->hw_params.fw.dir, filename, len);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (memcmp(data, ATH10K_BOARD_MAGIC, magic_len)) {
+               ath10k_err(ar, "found invalid board magic\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* magic is padded to 4 bytes */
+       magic_len = ALIGN(magic_len, 4);
+       if (len < magic_len) {
+               ath10k_err(ar, "failed: %s/%s too small to contain board data, len: %zu\n",
+                          ar->hw_params.fw.dir, filename, len);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       data += magic_len;
+       len -= magic_len;
+
+       /* attempt to find boardname in the IE list */
+       ret = ath10k_core_search_bd(ar, boardname, data, len);
+
+       /* if we didn't find it and have a fallback name, try that */
+       if (ret == -ENOENT && fallback_boardname)
+               ret = ath10k_core_search_bd(ar, fallback_boardname, data, len);
+
+       if (ret == -ENOENT) {
+               ath10k_err(ar,
+                          "failed to fetch board data for %s from %s/%s\n",
+                          boardname, ar->hw_params.fw.dir, filename);
+               ret = -ENODATA;
+       }
+
+       if (ret)
+               goto err;
+
+       return 0;
+
+err:
+       ath10k_core_free_board_files(ar);
+       return ret;
+}
+
+static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
+                                        size_t name_len, bool with_variant)
+{
+       /* strlen(',variant=') + strlen(ar->id.bdf_ext) */
+       char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };
+
+       if (with_variant && ar->id.bdf_ext[0] != '\0')
+               scnprintf(variant, sizeof(variant), ",variant=%s",
+                         ar->id.bdf_ext);
+
+       if (ar->id.bmi_ids_valid) {
+               scnprintf(name, name_len,
+                         "bus=%s,bmi-chip-id=%d,bmi-board-id=%d%s",
+                         ath10k_bus_str(ar->hif.bus),
+                         ar->id.bmi_chip_id,
+                         ar->id.bmi_board_id, variant);
+               goto out;
+       }
+
+       if (ar->id.qmi_ids_valid) {
+               scnprintf(name, name_len,
+                         "bus=%s,qmi-board-id=%x",
+                         ath10k_bus_str(ar->hif.bus),
+                         ar->id.qmi_board_id);
+               goto out;
+       }
+
+       scnprintf(name, name_len,
+                 "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
+                 ath10k_bus_str(ar->hif.bus),
+                 ar->id.vendor, ar->id.device,
+                 ar->id.subsystem_vendor, ar->id.subsystem_device, variant);
+out:
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name);
+
+       return 0;
+}
+
+static int ath10k_core_create_eboard_name(struct ath10k *ar, char *name,
+                                         size_t name_len)
+{
+       if (ar->id.bmi_ids_valid) {
+               scnprintf(name, name_len,
+                         "bus=%s,bmi-chip-id=%d,bmi-eboard-id=%d",
+                         ath10k_bus_str(ar->hif.bus),
+                         ar->id.bmi_chip_id,
+                         ar->id.bmi_eboard_id);
+
+               ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using eboard name '%s'\n", name);
+               return 0;
+       }
+       /* Fallback if returned board id is zero */
+       return -1;
+}
+
+int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type)
+{
+       char boardname[100], fallback_boardname[100];
+       int ret;
+
+       if (bd_ie_type == ATH10K_BD_IE_BOARD) {
+               ret = ath10k_core_create_board_name(ar, boardname,
+                                                   sizeof(boardname), true);
+               if (ret) {
+                       ath10k_err(ar, "failed to create board name: %d", ret);
+                       return ret;
+               }
+
+               ret = ath10k_core_create_board_name(ar, fallback_boardname,
+                                                   sizeof(boardname), false);
+               if (ret) {
+                       ath10k_err(ar, "failed to create fallback board name: %d", ret);
+                       return ret;
+               }
+       } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {
+               ret = ath10k_core_create_eboard_name(ar, boardname,
+                                                    sizeof(boardname));
+               if (ret) {
+                       ath10k_err(ar, "fallback to eboard.bin since board id 0");
+                       goto fallback;
+               }
+       }
+
+       ar->bd_api = 2;
+       ret = ath10k_core_fetch_board_data_api_n(ar, boardname,
+                                                fallback_boardname,
+                                                ATH10K_BOARD_API2_FILE);
+       if (!ret)
+               goto success;
+
+fallback:
+       ar->bd_api = 1;
+       ret = ath10k_core_fetch_board_data_api_1(ar, bd_ie_type);
+       if (ret) {
+               ath10k_err(ar, "failed to fetch board-2.bin or board.bin from %s\n",
+                          ar->hw_params.fw.dir);
+               return ret;
+       }
+
+success:
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api);
+       return 0;
+}
+EXPORT_SYMBOL(ath10k_core_fetch_board_file);
+
+static int ath10k_core_get_ext_board_id_from_otp(struct ath10k *ar)
+{
+       u32 result, address;
+       u8 ext_board_id;
+       int ret;
+
+       address = ar->hw_params.patch_load_addr;
+
+       if (!ar->normal_mode_fw.fw_file.otp_data ||
+           !ar->normal_mode_fw.fw_file.otp_len) {
+               ath10k_warn(ar,
+                           "failed to retrieve extended board id due to otp binary missing\n");
+               return -ENODATA;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "boot upload otp to 0x%x len %zd for ext board id\n",
+                  address, ar->normal_mode_fw.fw_file.otp_len);
+
+       ret = ath10k_bmi_fast_download(ar, address,
+                                      ar->normal_mode_fw.fw_file.otp_data,
+                                      ar->normal_mode_fw.fw_file.otp_len);
+       if (ret) {
+               ath10k_err(ar, "could not write otp for ext board id check: %d\n",
+                          ret);
+               return ret;
+       }
+
+       ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EXT_BOARD_ID, &result);
+       if (ret) {
+               ath10k_err(ar, "could not execute otp for ext board id check: %d\n",
+                          ret);
+               return ret;
+       }
+
+       if (!result) {
+               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                          "ext board id does not exist in otp, ignore it\n");
+               return -EOPNOTSUPP;
+       }
+
+       ext_board_id = result & ATH10K_BMI_EBOARD_ID_STATUS_MASK;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "boot get otp ext board id result 0x%08x ext_board_id %d\n",
+                  result, ext_board_id);
+
+       ar->id.bmi_eboard_id = ext_board_id;
+
+       return 0;
+}
+
+static int ath10k_download_board_data(struct ath10k *ar, const void *data,
+                                     size_t data_len)
+{
+       u32 board_data_size = ar->hw_params.fw.board_size;
+       u32 eboard_data_size = ar->hw_params.fw.ext_board_size;
+       u32 board_address;
+       u32 ext_board_address;
+       int ret;
+
+       ret = ath10k_push_board_ext_data(ar, data, data_len);
+       if (ret) {
+               ath10k_err(ar, "could not push board ext data (%d)\n", ret);
+               goto exit;
+       }
+
+       ret = ath10k_bmi_read32(ar, hi_board_data, &board_address);
+       if (ret) {
+               ath10k_err(ar, "could not read board data addr (%d)\n", ret);
+               goto exit;
+       }
+
+       ret = ath10k_bmi_write_memory(ar, board_address, data,
+                                     min_t(u32, board_data_size,
+                                           data_len));
+       if (ret) {
+               ath10k_err(ar, "could not write board data (%d)\n", ret);
+               goto exit;
+       }
 
-               switch (ie_id) {
-               case ATH10K_BD_IE_BOARD:
-                       ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
-                                                           boardname);
-                       if (ret == -ENOENT)
-                               /* no match found, continue */
-                               break;
+       ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1);
+       if (ret) {
+               ath10k_err(ar, "could not write board data bit (%d)\n", ret);
+               goto exit;
+       }
 
-                       /* either found or error, so stop searching */
-                       goto out;
-               }
+       if (!ar->id.ext_bid_supported)
+               goto exit;
 
-               /* jump over the padding */
-               ie_len = ALIGN(ie_len, 4);
+       /* Extended board data download */
+       ret = ath10k_core_get_ext_board_id_from_otp(ar);
+       if (ret == -EOPNOTSUPP) {
+               /* Not fetching ext_board_data if ext board id is 0 */
+               ath10k_dbg(ar, ATH10K_DBG_BOOT, "otp returned ext board id 0\n");
+               return 0;
+       } else if (ret) {
+               ath10k_err(ar, "failed to get extended board id: %d\n", ret);
+               goto exit;
+       }
 
-               len -= ie_len;
-               data += ie_len;
+       ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD_EXT);
+       if (ret)
+               goto exit;
+
+       if (ar->normal_mode_fw.ext_board_data) {
+               ext_board_address = board_address + EXT_BOARD_ADDRESS_OFFSET;
+               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                          "boot writing ext board data to addr 0x%x",
+                          ext_board_address);
+               ret = ath10k_bmi_write_memory(ar, ext_board_address,
+                                             ar->normal_mode_fw.ext_board_data,
+                                             min_t(u32, eboard_data_size, data_len));
+               if (ret)
+                       ath10k_err(ar, "failed to write ext board data: %d\n", ret);
        }
 
-out:
-       /* return result of parse_bd_ie_board() or -ENOENT */
+exit:
        return ret;
 }
 
-static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
-                                             const char *boardname,
-                                             const char *fallback_boardname,
-                                             const char *filename)
+static int ath10k_download_and_run_otp(struct ath10k *ar)
 {
-       size_t len, magic_len;
-       const u8 *data;
+       u32 result, address = ar->hw_params.patch_load_addr;
+       u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param;
        int ret;
 
-       ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
-                                                       ar->hw_params.fw.dir,
-                                                       filename);
-       if (IS_ERR(ar->normal_mode_fw.board))
-               return PTR_ERR(ar->normal_mode_fw.board);
+       ret = ath10k_download_board_data(ar,
+                                        ar->running_fw->board_data,
+                                        ar->running_fw->board_len);
+       if (ret) {
+               ath10k_err(ar, "failed to download board data: %d\n", ret);
+               return ret;
+       }
 
-       data = ar->normal_mode_fw.board->data;
-       len = ar->normal_mode_fw.board->size;
+       /* OTP is optional */
 
-       /* magic has extra null byte padded */
-       magic_len = strlen(ATH10K_BOARD_MAGIC) + 1;
-       if (len < magic_len) {
-               ath10k_err(ar, "failed to find magic value in %s/%s, file too short: %zu\n",
-                          ar->hw_params.fw.dir, filename, len);
-               ret = -EINVAL;
-               goto err;
+       if (!ar->running_fw->fw_file.otp_data ||
+           !ar->running_fw->fw_file.otp_len) {
+               ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n",
+                           ar->running_fw->fw_file.otp_data,
+                           ar->running_fw->fw_file.otp_len);
+               return 0;
        }
 
-       if (memcmp(data, ATH10K_BOARD_MAGIC, magic_len)) {
-               ath10k_err(ar, "found invalid board magic\n");
-               ret = -EINVAL;
-               goto err;
-       }
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
+                  address, ar->running_fw->fw_file.otp_len);
 
-       /* magic is padded to 4 bytes */
-       magic_len = ALIGN(magic_len, 4);
-       if (len < magic_len) {
-               ath10k_err(ar, "failed: %s/%s too small to contain board data, len: %zu\n",
-                          ar->hw_params.fw.dir, filename, len);
-               ret = -EINVAL;
-               goto err;
+       ret = ath10k_bmi_fast_download(ar, address,
+                                      ar->running_fw->fw_file.otp_data,
+                                      ar->running_fw->fw_file.otp_len);
+       if (ret) {
+               ath10k_err(ar, "could not write otp (%d)\n", ret);
+               return ret;
        }
 
-       data += magic_len;
-       len -= magic_len;
+       /* As of now pre-cal is valid for 10_4 variants */
+       if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
+           ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
+               bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
 
-       /* attempt to find boardname in the IE list */
-       ret = ath10k_core_search_bd(ar, boardname, data, len);
+       ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
+       if (ret) {
+               ath10k_err(ar, "could not execute otp (%d)\n", ret);
+               return ret;
+       }
 
-       /* if we didn't find it and have a fallback name, try that */
-       if (ret == -ENOENT && fallback_boardname)
-               ret = ath10k_core_search_bd(ar, fallback_boardname, data, len);
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
 
-       if (ret == -ENOENT) {
-               ath10k_err(ar,
-                          "failed to fetch board data for %s from %s/%s\n",
-                          boardname, ar->hw_params.fw.dir, filename);
-               ret = -ENODATA;
+       if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
+                                  ar->running_fw->fw_file.fw_features)) &&
+           result != 0) {
+               ath10k_err(ar, "otp calibration failed: %d", result);
+               return -EINVAL;
        }
 
-       if (ret)
-               goto err;
-
        return 0;
-
-err:
-       ath10k_core_free_board_files(ar);
-       return ret;
 }
 
-static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
-                                        size_t name_len, bool with_variant)
+static int ath10k_download_cal_file(struct ath10k *ar,
+                                   const struct firmware *file)
 {
-       /* strlen(',variant=') + strlen(ar->id.bdf_ext) */
-       char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };
+       int ret;
 
-       if (with_variant && ar->id.bdf_ext[0] != '\0')
-               scnprintf(variant, sizeof(variant), ",variant=%s",
-                         ar->id.bdf_ext);
+       if (!file)
+               return -ENOENT;
 
-       if (ar->id.bmi_ids_valid) {
-               scnprintf(name, name_len,
-                         "bus=%s,bmi-chip-id=%d,bmi-board-id=%d%s",
-                         ath10k_bus_str(ar->hif.bus),
-                         ar->id.bmi_chip_id,
-                         ar->id.bmi_board_id, variant);
-               goto out;
+       if (IS_ERR(file))
+               return PTR_ERR(file);
+
+       ret = ath10k_download_board_data(ar, file->data, file->size);
+       if (ret) {
+               ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
+               return ret;
        }
 
-       scnprintf(name, name_len,
-                 "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
-                 ath10k_bus_str(ar->hif.bus),
-                 ar->id.vendor, ar->id.device,
-                 ar->id.subsystem_vendor, ar->id.subsystem_device, variant);
-out:
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name);
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");
 
        return 0;
 }
 
-static int ath10k_core_fetch_board_file(struct ath10k *ar)
+static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
 {
-       char boardname[100], fallback_boardname[100];
+       struct device_node *node;
+       int data_len;
+       void *data;
        int ret;
 
-       ret = ath10k_core_create_board_name(ar, boardname,
-                                           sizeof(boardname), true);
+       node = ar->dev->of_node;
+       if (!node)
+               /* Device Tree is optional, don't print any warnings if
+                * there's no node for ath10k.
+                */
+               return -ENOENT;
+
+       if (!of_get_property(node, dt_name, &data_len)) {
+               /* The calibration data node is optional */
+               return -ENOENT;
+       }
+
+       if (data_len != ar->hw_params.cal_data_len) {
+               ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
+                           data_len);
+               ret = -EMSGSIZE;
+               goto out;
+       }
+
+       data = kmalloc(data_len, GFP_KERNEL);
+       if (!data) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = of_property_read_u8_array(node, dt_name, data, data_len);
        if (ret) {
-               ath10k_err(ar, "failed to create board name: %d", ret);
-               return ret;
+               ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
+                           ret);
+               goto out_free;
        }
 
-       ret = ath10k_core_create_board_name(ar, fallback_boardname,
-                                           sizeof(boardname), false);
+       ret = ath10k_download_board_data(ar, data, data_len);
        if (ret) {
-               ath10k_err(ar, "failed to create fallback board name: %d", ret);
-               return ret;
+               ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n",
+                           ret);
+               goto out_free;
        }
 
-       ar->bd_api = 2;
-       ret = ath10k_core_fetch_board_data_api_n(ar, boardname,
-                                                fallback_boardname,
-                                                ATH10K_BOARD_API2_FILE);
-       if (!ret)
-               goto success;
+       ret = 0;
 
-       ar->bd_api = 1;
-       ret = ath10k_core_fetch_board_data_api_1(ar);
+out_free:
+       kfree(data);
+
+out:
+       return ret;
+}
+
+static int ath10k_download_cal_eeprom(struct ath10k *ar)
+{
+       size_t data_len;
+       void *data = NULL;
+       int ret;
+
+       ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len);
        if (ret) {
-               ath10k_err(ar, "failed to fetch board-2.bin or board.bin from %s\n",
-                          ar->hw_params.fw.dir);
-               return ret;
+               if (ret != -EOPNOTSUPP)
+                       ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n",
+                                   ret);
+               goto out_free;
        }
 
-success:
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api);
-       return 0;
+       ret = ath10k_download_board_data(ar, data, data_len);
+       if (ret) {
+               ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n",
+                           ret);
+               goto out_free;
+       }
+
+       ret = 0;
+
+out_free:
+       kfree(data);
+
+       return ret;
 }
 
 int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
@@ -1882,7 +2095,8 @@ static int ath10k_init_hw_params(struct ath10k *ar)
        for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
                hw_params = &ath10k_hw_params_list[i];
 
-               if (hw_params->id == ar->target_version &&
+               if (hw_params->bus == ar->hif.bus &&
+                   hw_params->id == ar->target_version &&
                    hw_params->dev_id == ar->dev_id)
                        break;
        }
@@ -1983,6 +2197,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
 static int ath10k_core_init_firmware_features(struct ath10k *ar)
 {
        struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file;
+       int max_num_peers;
 
        if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) &&
            !test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) {
@@ -2062,7 +2277,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
 
        switch (fw_file->wmi_op_version) {
        case ATH10K_FW_WMI_OP_VERSION_MAIN:
-               ar->max_num_peers = TARGET_NUM_PEERS;
+               max_num_peers = TARGET_NUM_PEERS;
                ar->max_num_stations = TARGET_NUM_STATIONS;
                ar->max_num_vdevs = TARGET_NUM_VDEVS;
                ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;
@@ -2074,10 +2289,10 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
        case ATH10K_FW_WMI_OP_VERSION_10_2:
        case ATH10K_FW_WMI_OP_VERSION_10_2_4:
                if (ath10k_peer_stats_enabled(ar)) {
-                       ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
+                       max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
                        ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
                } else {
-                       ar->max_num_peers = TARGET_10X_NUM_PEERS;
+                       max_num_peers = TARGET_10X_NUM_PEERS;
                        ar->max_num_stations = TARGET_10X_NUM_STATIONS;
                }
                ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
@@ -2086,7 +2301,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
                break;
        case ATH10K_FW_WMI_OP_VERSION_TLV:
-               ar->max_num_peers = TARGET_TLV_NUM_PEERS;
+               max_num_peers = TARGET_TLV_NUM_PEERS;
                ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
                ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
                ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
@@ -2098,7 +2313,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC;
                break;
        case ATH10K_FW_WMI_OP_VERSION_10_4:
-               ar->max_num_peers = TARGET_10_4_NUM_PEERS;
+               max_num_peers = TARGET_10_4_NUM_PEERS;
                ar->max_num_stations = TARGET_10_4_NUM_STATIONS;
                ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;
                ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
@@ -2117,10 +2332,16 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                break;
        case ATH10K_FW_WMI_OP_VERSION_UNSET:
        case ATH10K_FW_WMI_OP_VERSION_MAX:
+       default:
                WARN_ON(1);
                return -EINVAL;
        }
 
+       if (ar->hw_params.num_peers)
+               ar->max_num_peers = ar->hw_params.num_peers;
+       else
+               ar->max_num_peers = max_num_peers;
+
        /* Backwards compatibility for firmwares without
         * ATH10K_FW_IE_HTT_OP_VERSION.
         */
@@ -2370,6 +2591,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
                             ar->wmi.svc_map))
                        val |= WMI_10_4_TDLS_UAPSD_BUFFER_STA;
 
+               if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI,
+                            ar->wmi.svc_map))
+                       val |= WMI_10_4_TX_DATA_ACK_RSSI;
+
                status = ath10k_mac_ext_resource_config(ar, val);
                if (status) {
                        ath10k_err(ar,
@@ -2405,7 +2630,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
         * possible to implicitly make it correct by creating a dummy vdev and
         * then deleting it.
         */
-       if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+       if (ar->hw_params.hw_filter_reset_required &&
+           mode == ATH10K_FIRMWARE_MODE_NORMAL) {
                status = ath10k_core_reset_rx_filter(ar);
                if (status) {
                        ath10k_err(ar,
@@ -2593,7 +2819,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
                if (ret)
                        ath10k_dbg(ar, ATH10K_DBG_BOOT, "DT bdf variant name not set.\n");
 
-               ret = ath10k_core_fetch_board_file(ar);
+               ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD);
                if (ret) {
                        ath10k_err(ar, "failed to fetch board file: %d\n", ret);
                        goto err_free_firmware_files;
@@ -2602,6 +2828,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
                ath10k_debug_print_board_info(ar);
        }
 
+       device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr));
+
        ret = ath10k_core_init_firmware_features(ar);
        if (ret) {
                ath10k_err(ar, "fatal problem with firmware features: %d\n",
@@ -2714,9 +2942,11 @@ err:
        return;
 }
 
-int ath10k_core_register(struct ath10k *ar, u32 chip_id)
+int ath10k_core_register(struct ath10k *ar,
+                        const struct ath10k_bus_params *bus_params)
 {
-       ar->chip_id = chip_id;
+       ar->chip_id = bus_params->chip_id;
+       ar->dev_type = bus_params->dev_type;
        queue_work(ar->workqueue, &ar->register_work);
 
        return 0;