[ATH10K_FW_FEATURE_NON_BMI] = "non-bmi",
        [ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL] = "single-chan-info-per-channel",
        [ATH10K_FW_FEATURE_PEER_FIXED_RATE] = "peer-fixed-rate",
+       [ATH10K_FW_FEATURE_IRAM_RECOVERY] = "iram-recovery",
 };
 
 static unsigned int ath10k_core_get_fw_feature_str(char *buf,
        return 0;
 }
 
+#define TGT_IRAM_READ_PER_ITR (8 * 1024)
+
+static int ath10k_core_copy_target_iram(struct ath10k *ar)
+{
+       const struct ath10k_hw_mem_layout *hw_mem;
+       const struct ath10k_mem_region *tmp, *mem_region = NULL;
+       dma_addr_t paddr;
+       void *vaddr = NULL;
+       u8 num_read_itr;
+       int i, ret;
+       u32 len, remaining_len;
+
+       hw_mem = ath10k_coredump_get_mem_layout(ar);
+       if (!hw_mem)
+               return -ENOMEM;
+
+       for (i = 0; i < hw_mem->region_table.size; i++) {
+               tmp = &hw_mem->region_table.regions[i];
+               if (tmp->type == ATH10K_MEM_REGION_TYPE_REG) {
+                       mem_region = tmp;
+                       break;
+               }
+       }
+
+       if (!mem_region)
+               return -ENOMEM;
+
+       for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+               if (ar->wmi.mem_chunks[i].req_id ==
+                   WMI_IRAM_RECOVERY_HOST_MEM_REQ_ID) {
+                       vaddr = ar->wmi.mem_chunks[i].vaddr;
+                       len = ar->wmi.mem_chunks[i].len;
+                       break;
+               }
+       }
+
+       if (!vaddr || !len) {
+               ath10k_warn(ar, "No allocated memory for IRAM back up");
+               return -ENOMEM;
+       }
+
+       len = (len < mem_region->len) ? len : mem_region->len;
+       paddr = mem_region->start;
+       num_read_itr = len / TGT_IRAM_READ_PER_ITR;
+       remaining_len = len % TGT_IRAM_READ_PER_ITR;
+       for (i = 0; i < num_read_itr; i++) {
+               ret = ath10k_hif_diag_read(ar, paddr, vaddr,
+                                          TGT_IRAM_READ_PER_ITR);
+               if (ret) {
+                       ath10k_warn(ar, "failed to copy firmware IRAM contents: %d",
+                                   ret);
+                       return ret;
+               }
+
+               paddr += TGT_IRAM_READ_PER_ITR;
+               vaddr += TGT_IRAM_READ_PER_ITR;
+       }
+
+       if (remaining_len) {
+               ret = ath10k_hif_diag_read(ar, paddr, vaddr, remaining_len);
+               if (ret) {
+                       ath10k_warn(ar, "failed to copy firmware IRAM contents: %d",
+                                   ret);
+                       return ret;
+               }
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "target IRAM back up completed\n");
+
+       return 0;
+}
+
 int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
                      const struct ath10k_fw_components *fw)
 {
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
                   ar->hw->wiphy->fw_version);
 
+       if (test_bit(ATH10K_FW_FEATURE_IRAM_RECOVERY,
+                    ar->running_fw->fw_file.fw_features)) {
+               status = ath10k_core_copy_target_iram(ar);
+               if (status) {
+                       ath10k_warn(ar, "failed to copy target iram contents: %d",
+                                   status);
+                       goto err_hif_stop;
+               }
+       }
+
        if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map) &&
            mode == ATH10K_FIRMWARE_MODE_NORMAL) {
                val = 0;