#include <linux/module.h>
 #include <linux/firmware.h>
+#include <linux/of.h>
 
 #include "core.h"
 #include "mac.h"
        return 0;
 }
 
+static int ath10k_download_cal_dt(struct ath10k *ar)
+{
+       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, "qcom,ath10k-calibration-data",
+                            &data_len)) {
+               /* The calibration data node is optional */
+               return -ENOENT;
+       }
+
+       if (data_len != QCA988X_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, "qcom,ath10k-calibration-data",
+                                       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_and_run_otp(struct ath10k *ar)
 {
        u32 result, address = ar->hw_params.patch_load_addr;
        }
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT,
-                  "boot did not find a calibration file, try OTP next: %d\n",
+                  "boot did not find a calibration file, try DT next: %d\n",
+                  ret);
+
+       ret = ath10k_download_cal_dt(ar);
+       if (ret == 0) {
+               ar->cal_mode = ATH10K_CAL_MODE_DT;
+               goto done;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "boot did not find DT entry, try OTP next: %d\n",
                   ret);
 
        ret = ath10k_download_and_run_otp(ar);