|
@@ -17,6 +17,7 @@
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/firmware.h>
|
|
|
+#include <linux/of.h>
|
|
|
|
|
|
#include "core.h"
|
|
|
#include "mac.h"
|
|
@@ -249,6 +250,63 @@ static int ath10k_download_cal_file(struct ath10k *ar)
|
|
|
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;
|
|
@@ -662,7 +720,17 @@ static int ath10k_download_cal_data(struct ath10k *ar)
|
|
|
}
|
|
|
|
|
|
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);
|