]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ath10k: read calibration data from Device Tree
authorToshi Kikuchi <toshik@chromium.org>
Tue, 2 Dec 2014 08:55:54 +0000 (10:55 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Mon, 8 Dec 2014 15:33:29 +0000 (17:33 +0200)
This patch adds support for reading calibration data from Device Tree.
It looks for the calibration data in Device Tree if it can't find it
in a file. If there's no node in Device Tree, ath10k will try to find the
calibration data from OTP.

The node for the calibration data should be defined like this:

pci {
        pcie@0 {
                reg = <0 0 0 0 0>;
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
                device_type = "pci";

                ath10k@0,0 {
                        reg = <0 0 0 0 0>;
                        device_type = "pci";
                        qcom,ath10k-calibration-data = [ 01 02 03 ... ];
                };
        };
};

Signed-off-by: Toshi Kikuchi <toshik@chromium.org>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h

index 7762061a194458b4982326d7edaea90700a57d8b..6165f2735b35c403e634c1e4ce44ddd357e14fa6 100644 (file)
@@ -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);
index 514c219263a5905a11288f842789133c01f49350..69f78bf88023be3d77354243146e739dc54928e9 100644 (file)
@@ -401,6 +401,7 @@ enum ath10k_dev_flags {
 enum ath10k_cal_mode {
        ATH10K_CAL_MODE_FILE,
        ATH10K_CAL_MODE_OTP,
+       ATH10K_CAL_MODE_DT,
 };
 
 static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
@@ -410,6 +411,8 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
                return "file";
        case ATH10K_CAL_MODE_OTP:
                return "otp";
+       case ATH10K_CAL_MODE_DT:
+               return "dt";
        }
 
        return "unknown";