OSDN Git Service

mac80211: ath10k: backport bus and device specific API 1 BDF selection
[immortalwrt/immortalwrt.git] / package / kernel / mac80211 / patches / ath10k / 120-ath10k-fetch-calibration-data-via-nvmem-subsystem.patch
1 From e2333703373e8b81294da5d1c73c30154f75b082 Mon Sep 17 00:00:00 2001
2 From: Christian Lamparter <chunkeey@gmail.com>
3 Date: Fri, 15 Oct 2021 18:56:33 +0200
4 Subject: [PATCH] ath10k: fetch (pre-)calibration data via nvmem subsystem
5
6 On most embedded ath10k devices (like range extenders,
7 routers, accesspoints, ...) the calibration data is
8 stored in a easily accessible MTD partitions named
9 "ART", "caldata", "calibration", etc...
10
11 Since commit 4b361cfa8624 ("mtd: core: add OTP nvmem provider support"):
12 MTD partitions and portions of them can be specified
13 as potential nvmem-cells which are accessible through
14 the nvmem subsystem.
15
16 This feature - together with an nvmem cell definition either
17 in the platform data or via device-tree allows drivers to get
18 the (pre-)calibration data which is required for initializing
19 the WIFI.
20
21 Tested with Netgear EX6150v2 (IPQ4018)
22
23 Cc: Robert Marko <robimarko@gmail.com>
24 Cc: Thibaut Varene <hacks@slashdirt.org>
25 Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
26 ---
27 --- a/drivers/net/wireless/ath/ath10k/core.c
28 +++ b/drivers/net/wireless/ath/ath10k/core.c
29 @@ -12,6 +12,7 @@
30  #include <linux/dmi.h>
31  #include <linux/ctype.h>
32  #include <linux/pm_qos.h>
33 +#include <linux/nvmem-consumer.h>
34  #include <asm/byteorder.h>
35  
36  #include "core.h"
37 @@ -952,7 +953,8 @@ static int ath10k_core_get_board_id_from
38         }
39  
40         if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
41 -           ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
42 +           ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
43 +           ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
44                 bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID;
45         else
46                 bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID;
47 @@ -1754,7 +1756,8 @@ static int ath10k_download_and_run_otp(s
48  
49         /* As of now pre-cal is valid for 10_4 variants */
50         if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
51 -           ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
52 +           ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
53 +           ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
54                 bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;
55  
56         ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
57 @@ -1881,6 +1884,39 @@ out_free:
58         return ret;
59  }
60  
61 +static int ath10k_download_cal_nvmem(struct ath10k *ar, const char *cell_name)
62 +{
63 +       struct nvmem_cell *cell;
64 +       void *buf;
65 +       size_t len;
66 +       int ret;
67 +
68 +       cell = devm_nvmem_cell_get(ar->dev, cell_name);
69 +       if (IS_ERR(cell)) {
70 +               ret = PTR_ERR(cell);
71 +               return ret;
72 +       }
73 +
74 +       buf = nvmem_cell_read(cell, &len);
75 +       if (IS_ERR(buf))
76 +               return PTR_ERR(buf);
77 +
78 +       if (ar->hw_params.cal_data_len != len) {
79 +               kfree(buf);
80 +               ath10k_warn(ar, "invalid calibration data length in nvmem-cell '%s': %zu != %u\n",
81 +                           cell_name, len, ar->hw_params.cal_data_len);
82 +               return -EMSGSIZE;
83 +       }
84 +
85 +       ret = ath10k_download_board_data(ar, buf, len);
86 +       kfree(buf);
87 +       if (ret)
88 +               ath10k_warn(ar, "failed to download calibration data from nvmem-cell '%s': %d\n",
89 +                           cell_name, ret);
90 +
91 +       return ret;
92 +}
93 +
94  int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
95                                      struct ath10k_fw_file *fw_file)
96  {
97 @@ -2115,6 +2151,18 @@ static int ath10k_core_pre_cal_download(
98  {
99         int ret;
100  
101 +       ret = ath10k_download_cal_nvmem(ar, "pre-calibration");
102 +       if (ret == 0) {
103 +               ar->cal_mode = ATH10K_PRE_CAL_MODE_NVMEM;
104 +               goto success;
105 +       } else if (ret == -EPROBE_DEFER) {
106 +               return ret;
107 +       }
108 +
109 +       ath10k_dbg(ar, ATH10K_DBG_BOOT,
110 +                  "boot did not find a pre-calibration nvmem-cell, try file next: %d\n",
111 +                  ret);
112 +
113         ret = ath10k_download_cal_file(ar, ar->pre_cal_file);
114         if (ret == 0) {
115                 ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;
116 @@ -2181,6 +2229,18 @@ static int ath10k_download_cal_data(stru
117                    "pre cal download procedure failed, try cal file: %d\n",
118                    ret);
119  
120 +       ret = ath10k_download_cal_nvmem(ar, "calibration");
121 +       if (ret == 0) {
122 +               ar->cal_mode = ATH10K_CAL_MODE_NVMEM;
123 +               goto done;
124 +       } else if (ret == -EPROBE_DEFER) {
125 +               return ret;
126 +       }
127 +
128 +       ath10k_dbg(ar, ATH10K_DBG_BOOT,
129 +                  "boot did not find a calibration nvmem-cell, try file next: %d\n",
130 +                  ret);
131 +
132         ret = ath10k_download_cal_file(ar, ar->cal_file);
133         if (ret == 0) {
134                 ar->cal_mode = ATH10K_CAL_MODE_FILE;
135 --- a/drivers/net/wireless/ath/ath10k/core.h
136 +++ b/drivers/net/wireless/ath/ath10k/core.h
137 @@ -877,8 +877,10 @@ enum ath10k_cal_mode {
138         ATH10K_CAL_MODE_FILE,
139         ATH10K_CAL_MODE_OTP,
140         ATH10K_CAL_MODE_DT,
141 +       ATH10K_CAL_MODE_NVMEM,
142         ATH10K_PRE_CAL_MODE_FILE,
143         ATH10K_PRE_CAL_MODE_DT,
144 +       ATH10K_PRE_CAL_MODE_NVMEM,
145         ATH10K_CAL_MODE_EEPROM,
146  };
147  
148 @@ -898,10 +900,14 @@ static inline const char *ath10k_cal_mod
149                 return "otp";
150         case ATH10K_CAL_MODE_DT:
151                 return "dt";
152 +       case ATH10K_CAL_MODE_NVMEM:
153 +               return "nvmem";
154         case ATH10K_PRE_CAL_MODE_FILE:
155                 return "pre-cal-file";
156         case ATH10K_PRE_CAL_MODE_DT:
157                 return "pre-cal-dt";
158 +       case ATH10K_PRE_CAL_MODE_NVMEM:
159 +               return "pre-cal-nvmem";
160         case ATH10K_CAL_MODE_EEPROM:
161                 return "eeprom";
162         }