net:wireless:Support eswin usb wifi ECR6600U
[platform/kernel/linux-starfive.git] / drivers / net / wireless / eswin / ecrnx_cfgfile.c
1 /**
2  ****************************************************************************************
3  *
4  * @file ecrnx_configparse.c
5  *
6  * Copyright (C) ESWIN 2015-2020
7  *
8  ****************************************************************************************
9  */
10 #include <linux/firmware.h>
11 #include <linux/if_ether.h>
12
13 #include "ecrnx_defs.h"
14 #include "ecrnx_cfgfile.h"
15 #include "ecrnx_debug.h"
16 #include "ecrnx_debugfs_func.h"
17
18 /**
19  *
20  */
21 static const char *ecrnx_find_tag(const u8 *file_data, unsigned int file_size,
22                                  const char *tag_name, unsigned int tag_len)
23 {
24     unsigned int curr, line_start = 0, line_size;
25
26     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
27
28     /* Walk through all the lines of the configuration file */
29     while (line_start < file_size) {
30         /* Search the end of the current line (or the end of the file) */
31         for (curr = line_start; curr < file_size; curr++)
32             if (file_data[curr] == '\n')
33                 break;
34
35         /* Compute the line size */
36         line_size = curr - line_start;
37
38         /* Check if this line contains the expected tag */
39         if ((line_size == (strlen(tag_name) + tag_len)) &&
40             (!strncmp(&file_data[line_start], tag_name, strlen(tag_name))))
41             return (&file_data[line_start + strlen(tag_name)]);
42
43         /* Move to next line */
44         line_start = curr + 1;
45     }
46
47     /* Tag not found */
48     return NULL;
49 }
50
51 /**
52  * Parse the Config file used at init time
53  */
54 int ecrnx_parse_configfile(struct ecrnx_hw *ecrnx_hw, const char *filename)
55 {
56     const struct firmware *config_fw;
57     u8 dflt_mac[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x5f };
58     int ret;
59     const u8 *tag_ptr;
60     bool mac_flag = false, dbg_level_flag = false, fw_log_lv_flag = false, fw_log_type_flag = false;
61
62     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
63 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
64     ret = firmware_request_nowarn(&config_fw, filename, ecrnx_hw->dev); //avoid the files not exit error
65 #else
66     ret = request_firmware(&config_fw, filename, ecrnx_hw->dev);
67 #endif
68
69     if (ret == 0) {
70         /* Get MAC Address */
71         tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size, "MAC_ADDR=", strlen("00:00:00:00:00:00"));
72         if (tag_ptr != NULL) {
73             u8 *addr = ecrnx_hw->conf_param.mac_addr;
74             if (sscanf(tag_ptr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
75                         addr + 0, addr + 1, addr + 2,
76                         addr + 3, addr + 4, addr + 5) == ETH_ALEN){
77                 mac_flag = true;
78             }
79         }
80
81         tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size, "DRIVER_LOG_LEVEL=", strlen("0"));
82         if (tag_ptr != NULL){
83             if(sscanf(tag_ptr, "%hhx", &ecrnx_hw->conf_param.host_driver_log_level) == 1){
84                 ecrnx_dbg_level = ecrnx_hw->conf_param.host_driver_log_level;
85                 dbg_level_flag = true;
86             }
87         }
88
89         tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size, "FW_LOG_LEVEL=", strlen("0"));
90         if (tag_ptr != NULL){
91             if(sscanf(tag_ptr, "%hhx", &ecrnx_hw->conf_param.fw_log_level) == 1){
92                 fw_log_lv_flag = true;
93             }
94         }
95
96         tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size, "FW_LOG_TYPE=", strlen("0"));
97         if (tag_ptr != NULL){
98             if(sscanf(tag_ptr, "%hhx", &ecrnx_hw->conf_param.fw_log_type) == 1){
99                 fw_log_type_flag = true;
100             }
101         }
102
103         /* Release the configuration file */
104         release_firmware(config_fw);
105     }
106
107     if(!mac_flag){
108         memcpy(ecrnx_hw->conf_param.mac_addr, dflt_mac, ETH_ALEN);
109     }
110
111     if(!dbg_level_flag){
112         ecrnx_hw->conf_param.host_driver_log_level = ecrnx_dbg_level;
113     }
114
115     if(!fw_log_lv_flag){
116         ecrnx_hw->conf_param.fw_log_level = log_ctl.level;
117     }
118
119     if(!fw_log_type_flag){
120         ecrnx_hw->conf_param.fw_log_type = log_ctl.dir;
121     }
122
123     ECRNX_PRINT("MAC Address is:%pM\n", ecrnx_hw->conf_param.mac_addr);
124     ECRNX_PRINT("host driver log level is:%d \n", ecrnx_hw->conf_param.host_driver_log_level);
125     ECRNX_PRINT("firmware log level is:%d \n", ecrnx_hw->conf_param.fw_log_level);
126
127     if(0 == ecrnx_hw->conf_param.fw_log_type){
128         ECRNX_PRINT("firmware log level type:%d (print to chip's uart) \n", ecrnx_hw->conf_param.fw_log_type);
129     }else if(1 == ecrnx_hw->conf_param.fw_log_type){
130         ECRNX_PRINT("firmware log level type:%d (print to host debugfs) \n", ecrnx_hw->conf_param.fw_log_type);
131     }else if(2 == ecrnx_hw->conf_param.fw_log_type){
132         ECRNX_PRINT("firmware log level type:%d (print to host kernel) \n", ecrnx_hw->conf_param.fw_log_type);
133     }else{
134         ECRNX_ERR("firmware log level type error;\n");
135     }
136     return 0;
137 }
138
139 /**
140  * Parse the Config file used at init time
141  */
142 int ecrnx_parse_phy_configfile(struct ecrnx_hw *ecrnx_hw, const char *filename,
143                               struct ecrnx_phy_conf_file *config, int path)
144 {
145     const struct firmware *config_fw;
146     int ret;
147     const u8 *tag_ptr;
148
149     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
150
151     if ((ret = request_firmware(&config_fw, filename, ecrnx_hw->dev))) {
152         ECRNX_ERR(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret);
153         return ret;
154     }
155
156     /* Get Trident path mapping */
157     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
158                             "TRD_PATH_MAPPING=", strlen("00"));
159     if (tag_ptr != NULL) {
160         u8 val;
161         if (sscanf(tag_ptr, "%hhx", &val) == 1)
162             config->trd.path_mapping = val;
163         else
164             config->trd.path_mapping = path;
165     } else
166         config->trd.path_mapping = path;
167
168     ECRNX_DBG("Trident path mapping is: %d\n", config->trd.path_mapping);
169
170     /* Get DC offset compensation */
171     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
172                             "TX_DC_OFF_COMP=", strlen("00000000"));
173     if (tag_ptr != NULL) {
174         if (sscanf(tag_ptr, "%08x", &config->trd.tx_dc_off_comp) != 1)
175             config->trd.tx_dc_off_comp = 0;
176     } else
177         config->trd.tx_dc_off_comp = 0;
178
179     ECRNX_DBG("TX DC offset compensation is: %08X\n", config->trd.tx_dc_off_comp);
180
181     /* Get Karst TX IQ compensation value for path0 on 2.4GHz */
182     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
183                             "KARST_TX_IQ_COMP_2_4G_PATH_0=", strlen("00000000"));
184     if (tag_ptr != NULL) {
185         if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[0]) != 1)
186             config->karst.tx_iq_comp_2_4G[0] = 0x01000000;
187     } else
188         config->karst.tx_iq_comp_2_4G[0] = 0x01000000;
189
190     ECRNX_DBG("Karst TX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[0]);
191
192     /* Get Karst TX IQ compensation value for path1 on 2.4GHz */
193     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
194                             "KARST_TX_IQ_COMP_2_4G_PATH_1=", strlen("00000000"));
195     if (tag_ptr != NULL) {
196         if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[1]) != 1)
197             config->karst.tx_iq_comp_2_4G[1] = 0x01000000;
198     } else
199         config->karst.tx_iq_comp_2_4G[1] = 0x01000000;
200
201     ECRNX_DBG("Karst TX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[1]);
202
203     /* Get Karst RX IQ compensation value for path0 on 2.4GHz */
204     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
205                             "KARST_RX_IQ_COMP_2_4G_PATH_0=", strlen("00000000"));
206     if (tag_ptr != NULL) {
207         if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[0]) != 1)
208             config->karst.rx_iq_comp_2_4G[0] = 0x01000000;
209     } else
210         config->karst.rx_iq_comp_2_4G[0] = 0x01000000;
211
212     ECRNX_DBG("Karst RX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[0]);
213
214     /* Get Karst RX IQ compensation value for path1 on 2.4GHz */
215     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
216                             "KARST_RX_IQ_COMP_2_4G_PATH_1=", strlen("00000000"));
217     if (tag_ptr != NULL) {
218         if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[1]) != 1)
219             config->karst.rx_iq_comp_2_4G[1] = 0x01000000;
220     } else
221         config->karst.rx_iq_comp_2_4G[1] = 0x01000000;
222
223     ECRNX_DBG("Karst RX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[1]);
224
225     /* Get Karst TX IQ compensation value for path0 on 5GHz */
226     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
227                             "KARST_TX_IQ_COMP_5G_PATH_0=", strlen("00000000"));
228     if (tag_ptr != NULL) {
229         if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[0]) != 1)
230             config->karst.tx_iq_comp_5G[0] = 0x01000000;
231     } else
232         config->karst.tx_iq_comp_5G[0] = 0x01000000;
233
234     ECRNX_DBG("Karst TX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[0]);
235
236     /* Get Karst TX IQ compensation value for path1 on 5GHz */
237     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
238                             "KARST_TX_IQ_COMP_5G_PATH_1=", strlen("00000000"));
239     if (tag_ptr != NULL) {
240         if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[1]) != 1)
241             config->karst.tx_iq_comp_5G[1] = 0x01000000;
242     } else
243         config->karst.tx_iq_comp_5G[1] = 0x01000000;
244
245     ECRNX_DBG("Karst TX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[1]);
246
247     /* Get Karst RX IQ compensation value for path0 on 5GHz */
248     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
249                             "KARST_RX_IQ_COMP_5G_PATH_0=", strlen("00000000"));
250     if (tag_ptr != NULL) {
251         if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[0]) != 1)
252             config->karst.rx_iq_comp_5G[0] = 0x01000000;
253     } else
254         config->karst.rx_iq_comp_5G[0] = 0x01000000;
255
256     ECRNX_DBG("Karst RX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[0]);
257
258     /* Get Karst RX IQ compensation value for path1 on 5GHz */
259     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
260                             "KARST_RX_IQ_COMP_5G_PATH_1=", strlen("00000000"));
261     if (tag_ptr != NULL) {
262         if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[1]) != 1)
263             config->karst.rx_iq_comp_5G[1] = 0x01000000;
264     } else
265         config->karst.rx_iq_comp_5G[1] = 0x01000000;
266
267     ECRNX_DBG("Karst RX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[1]);
268
269     /* Get Karst default path */
270     tag_ptr = ecrnx_find_tag(config_fw->data, config_fw->size,
271                             "KARST_DEFAULT_PATH=", strlen("00"));
272     if (tag_ptr != NULL) {
273         u8 val;
274         if (sscanf(tag_ptr, "%hhx", &val) == 1)
275             config->karst.path_used = val;
276         else
277             config->karst.path_used = path;
278     } else
279         config->karst.path_used = path;
280
281     ECRNX_DBG("Karst default path is: %d\n", config->karst.path_used);
282
283     /* Release the configuration file */
284     release_firmware(config_fw);
285
286     return 0;
287 }
288