• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * PLT utility for wireless chip supported by TI's driver wl12xx
3  *
4  * See README and COPYING for more details.
5  */
6 
7 #include <sys/ioctl.h>
8 #include <errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <stdbool.h>
16 
17 #include <netlink/genl/genl.h>
18 #include <netlink/genl/family.h>
19 #include <netlink/genl/ctrl.h>
20 #include <netlink/msg.h>
21 #include <netlink/attr.h>
22 #include <linux/wireless.h>
23 #include "nl80211.h"
24 
25 #include "calibrator.h"
26 #include "plt.h"
27 #include "ini.h"
28 #include "nvs.h"
29 
ini_get_line(char * s,int size,FILE * stream,int * line,char ** _pos)30 static char *ini_get_line(char *s, int size, FILE *stream, int *line,
31 				  char **_pos)
32 {
33 	char *pos, *end, *sstart;
34 
35 	while (fgets(s, size, stream)) {
36 		s[size - 1] = '\0';
37 		pos = s;
38 
39 		/* Skip white space from the beginning of line. */
40 		while (*pos == ' ' || *pos == '\t' || *pos == '\r') {
41 			pos++;
42                 }
43 
44 		/* Skip comment lines and empty lines */
45 		if (*pos == '#' || *pos == '\n' || *pos == '\0') {
46 			continue;
47                 }
48 
49 		/*
50 		 * Remove # comments unless they are within a double quoted
51 		 * string.
52 		 */
53 		sstart = strchr(pos, '"');
54 		if (sstart) {
55 			sstart = strrchr(sstart + 1, '"');
56                 }
57 		if (!sstart) {
58 			sstart = pos;
59                 }
60 		end = strchr(sstart, '#');
61 		if (end) {
62 			*end-- = '\0';
63                 } else {
64 			end = pos + strlen(pos) - 1;
65                 }
66 
67 		/* Remove trailing white space. */
68 		while (end > pos &&
69 		       (*end == '\n' || *end == ' ' || *end == '\t' ||
70 			*end == '\r')) {
71 			*end-- = '\0';
72                 }
73 
74 		if (*pos == '\0') {
75 			continue;
76                 }
77 
78 		(*line)++;
79 
80 		if (_pos) {
81 			*_pos = pos;
82                 }
83 		return pos;
84 	}
85 
86 	if (_pos) {
87 		*_pos = NULL;
88         }
89 
90 	return NULL;
91 }
92 
split_line(char * line,char ** name,char ** value)93 static int split_line(char *line, char **name, char **value)
94 {
95 	char *pos = line;
96 
97 	*value = strchr(pos, '=');
98 	if (!*value) {
99 		fprintf(stderr, "Wrong format of line\n");
100 		return 1;
101 	}
102 
103 	*name = *value;
104 
105 	(*name)--;
106 	while (**name == ' ' || **name == '\t' || **name == '\r') {
107 		(*name)--;
108         }
109 
110 	*++(*name) = '\0';
111 
112 	(*value)++;
113 	while (**value == ' ' || **value == '\t' || **value == '\r') {
114 		(*value)++;
115         }
116 
117 	return 0;
118 }
119 
120 #define COMPARE_N_ADD(temp, str, val, ptr, size)		\
121 	if (strncmp(temp, str, sizeof(temp)) == 0) {		\
122 		int i;						\
123 		unsigned char *p = ptr;				\
124 		for (i = 0; i < size; i++) {			\
125 			*p = strtol(val, NULL, 16);		\
126 			if (i != sizeof(ptr)-1) {		\
127 				val += 3; p++;			\
128 			}					\
129 		}						\
130 		return 0;					\
131 	}
132 
133 #define DBG_COMPARE_N_ADD(temp, str, val, ptr, size)		\
134 	if (strncmp(temp, str, sizeof(temp)) == 0) {		\
135 		int i;						\
136 		unsigned char *p = ptr;				\
137 		for (i = 0; i < size; i++) {			\
138 			*p = strtol(val, NULL, 16);		\
139 			if (i != sizeof(ptr)-1) {		\
140 				val += 3; p++;			\
141 			}					\
142 		}						\
143 		p = ptr;					\
144 		printf("%s ", temp);				\
145 		for (i = 0; i < size; i++) {			\
146 			printf("%02X ", *p);			\
147 			p++;					\
148 		}						\
149 		printf("\n");					\
150 		return 0;					\
151 	}
152 
153 #define COMPARE_N_ADD2(temp, str, val, ptr, size)		\
154 	if (strncmp(temp, str, sizeof(temp)) == 0) {		\
155 		int i;						\
156 		unsigned short *p = ptr;			\
157 		for (i = 0; i < size; i++) {			\
158 			*p = strtol(val, NULL, 16);		\
159 			if (i != sizeof(ptr)-1) {		\
160 				val += 5; p++;			\
161 			}					\
162 		}						\
163 		return 0;					\
164 	}
165 
166 #define DBG_COMPARE_N_ADD2(temp, str, val, ptr, size)		\
167 	if (strncmp(temp, str, sizeof(temp)) == 0) {		\
168 		int i;						\
169 		unsigned short *p = ptr;			\
170 		for (i = 0; i < size; i++) {			\
171 			*p = strtol(val, NULL, 16);		\
172 			if (i != sizeof(ptr)-1) {		\
173 				val += 5; p++;			\
174 			}					\
175 		}						\
176 		p = ptr;					\
177 		printf("%s ", temp);				\
178 		for (i = 0; i < size; i++) {			\
179 			printf("%04X ", *p);			\
180 			p++;					\
181 		}						\
182 		printf("\n");					\
183 		return 0;					\
184 	}
185 
parse_general_prms(char * l,struct wl12xx_common * cmn,struct wl12xx_ini * p)186 static int parse_general_prms(char *l, struct wl12xx_common *cmn,
187 	struct wl12xx_ini *p)
188 {
189 	char *name, *val;
190 	struct wl1271_ini_general_params *gp = &(p->ini1271.general_params);
191 
192 	if (split_line(l, &name, &val)) {
193 		return 1;
194         }
195 
196 	COMPARE_N_ADD("TXBiPFEMAutoDetect", l, val,
197 		&gp->tx_bip_fem_auto_detect, 1);
198 
199 	COMPARE_N_ADD("TXBiPFEMManufacturer", l, val,
200 		&gp->tx_bip_fem_manufacturer, 1);
201 
202 	COMPARE_N_ADD("RefClk", l, val, &gp->ref_clock, 1);
203 
204 	COMPARE_N_ADD("SettlingTime", l, val, &gp->settling_time, 1);
205 
206 	COMPARE_N_ADD("ClockValidOnWakeup", l, val,
207 		&gp->clk_valid_on_wakeup, 1);
208 
209 	COMPARE_N_ADD("DC2DCMode", l, val, &gp->dc2dc_mode, 1);
210 
211 	COMPARE_N_ADD("Single_Dual_Band_Solution", l, val,
212 		&gp->dual_mode_select, 1);
213 
214 	if (cmn->dual_mode == DUAL_MODE_UNSET) {
215 		cmn->dual_mode = gp->dual_mode_select;
216         }
217 	else if (cmn->dual_mode != gp->dual_mode_select) {
218 		fprintf(stderr, "Error, FEMs with different dual modes\n");
219 		return 1;
220 	}
221 
222 	COMPARE_N_ADD("Settings", l, val, &gp->general_settings, 1);
223 
224 	COMPARE_N_ADD("SRState", l, val, &gp->sr_state, 1);
225 
226 	COMPARE_N_ADD("SRF1", l, val,
227 		gp->srf1, WL1271_INI_MAX_SMART_REFLEX_PARAM);
228 
229 	COMPARE_N_ADD("SRF2", l, val,
230 		gp->srf2, WL1271_INI_MAX_SMART_REFLEX_PARAM);
231 
232 	COMPARE_N_ADD("SRF3", l, val,
233 		gp->srf3, WL1271_INI_MAX_SMART_REFLEX_PARAM);
234 
235 	fprintf(stderr, "Unable to parse: (%s)\n", l);
236 
237 	return 1;
238 }
239 
parse_general_prms_128x(char * l,struct wl12xx_common * cmn,struct wl12xx_ini * p)240 static int parse_general_prms_128x(char *l, struct wl12xx_common *cmn,
241 	struct wl12xx_ini *p)
242 {
243 	char *name, *val;
244 	struct wl128x_ini_general_params *gp =
245 		&(p->ini128x.general_params);
246 
247 	if (split_line(l, &name, &val)) {
248 		return 1;
249         }
250 
251 	COMPARE_N_ADD("TXBiPFEMAutoDetect", l, val,
252 		&gp->tx_bip_fem_auto_detect, 1);
253 
254 	COMPARE_N_ADD("TXBiPFEMManufacturer", l, val,
255 		&gp->tx_bip_fem_manufacturer, 1);
256 
257 	COMPARE_N_ADD("RefClk", l, val, &gp->ref_clock, 1);
258 
259 	COMPARE_N_ADD("SettlingTime", l, val, &gp->settling_time, 1);
260 
261 	COMPARE_N_ADD("ClockValidOnWakeup", l, val,
262 		&gp->clk_valid_on_wakeup, 1);
263 
264 	COMPARE_N_ADD("TCXO_Clk", l, val, &gp->tcxo_ref_clock, 1);
265 
266 	COMPARE_N_ADD("TCXO_SettlingTime", l, val, &gp->tcxo_settling_time, 1);
267 
268 	COMPARE_N_ADD("TCXO_ClockValidOnWakeup", l, val,
269 		&gp->tcxo_valid_on_wakeup, 1);
270 
271 	COMPARE_N_ADD("TCXO_LDO_Voltage", l, val,
272 		&gp->tcxo_ldo_voltage, 1);
273 
274 	COMPARE_N_ADD("Platform_configuration", l, val,
275 		&gp->platform_conf, 1);
276 
277 	COMPARE_N_ADD("Single_Dual_Band_Solution", l, val,
278 		&gp->dual_mode_select, 1);
279 
280 	if (cmn->dual_mode == DUAL_MODE_UNSET) {
281 		cmn->dual_mode = gp->dual_mode_select;
282         } else if (cmn->dual_mode != gp->dual_mode_select) {
283 		fprintf(stderr, "Error, FEMs with diferent dual modes\n");
284 		return 1;
285 	}
286 
287 	COMPARE_N_ADD("Settings", l, val,
288 		gp->general_settings, WL128X_INI_MAX_SETTINGS_PARAM);
289 
290 	COMPARE_N_ADD("XTALItrimVal", l, val, &gp->xtal_itrim_val, 1);
291 
292 	COMPARE_N_ADD("SRState", l, val, &gp->sr_state, 1);
293 
294 	COMPARE_N_ADD("SRF1", l, val,
295 		gp->srf1, WL1271_INI_MAX_SMART_REFLEX_PARAM);
296 
297 	COMPARE_N_ADD("SRF2", l, val,
298 		gp->srf2, WL1271_INI_MAX_SMART_REFLEX_PARAM);
299 
300 	COMPARE_N_ADD("SRF3", l, val,
301 		gp->srf3, WL1271_INI_MAX_SMART_REFLEX_PARAM);
302 
303 	fprintf(stderr, "Unable to parse: (%s)\n", l);
304 
305 	return 1;
306 }
307 
parse_band2_prms(char * l,struct wl12xx_ini * p)308 static int parse_band2_prms(char *l, struct wl12xx_ini *p)
309 {
310 	char *name, *val;
311 	struct wl1271_ini_band_params_2 *gp =
312 		&(p->ini1271.stat_radio_params_2);
313 
314 	if (split_line(l, &name, &val)) {
315 		return 1;
316         }
317 
318 	COMPARE_N_ADD("RxTraceInsertionLoss_2_4G", l, val,
319 		&gp->rx_trace_insertion_loss, 1);
320 
321 	COMPARE_N_ADD("TXTraceLoss_2_4G", l, val,
322 		&gp->tx_trace_loss, 1);
323 
324 	COMPARE_N_ADD("RxRssiAndProcessCompensation_2_4G", l, val,
325 		gp->rx_rssi_process_compens,
326 		WL1271_INI_RSSI_PROCESS_COMPENS_SIZE);
327 
328 	fprintf(stderr, "Unable to parse: (%s)\n", l);
329 
330 	return 1;
331 }
332 
parse_band2_prms_128x(char * l,struct wl12xx_ini * p)333 static int parse_band2_prms_128x(char *l, struct wl12xx_ini *p)
334 {
335 	char *name, *val;
336 	struct wl128x_ini_band_params_2 *gp = &(p->ini128x.stat_radio_params_2);
337 
338 	if (split_line(l, &name, &val)) {
339 		return 1;
340         }
341 
342 	COMPARE_N_ADD("RxTraceInsertionLoss_2_4G", l, val,
343 		&gp->rx_trace_insertion_loss, 1);
344 
345 	COMPARE_N_ADD("TxTraceLoss_2_4G", l, val,
346 		gp->tx_trace_loss, WL1271_INI_CHANNEL_COUNT_2);
347 
348 	fprintf(stderr, "Unable to parse: (%s)\n", l);
349 
350 	return 1;
351 }
352 
parse_band5_prms(char * l,struct wl12xx_ini * p)353 static int parse_band5_prms(char *l, struct wl12xx_ini *p)
354 {
355 	char *name, *val;
356 	struct wl1271_ini_band_params_5 *gp =
357 		&(p->ini1271.stat_radio_params_5);
358 
359 	if (split_line(l, &name, &val)) {
360 		return 1;
361         }
362 
363 	COMPARE_N_ADD("RxTraceInsertionLoss_5G", l, val,
364 		gp->rx_trace_insertion_loss, 7);
365 
366 	COMPARE_N_ADD("TXTraceLoss_5G", l, val,
367 		gp->tx_trace_loss, 7);
368 
369 	COMPARE_N_ADD("RxRssiAndProcessCompensation_5G", l, val,
370 		gp->rx_rssi_process_compens,
371 		WL1271_INI_RSSI_PROCESS_COMPENS_SIZE);
372 
373 	fprintf(stderr, "Unable to parse: (%s)\n", l);
374 
375 	return 1;
376 }
377 
parse_band5_prms_128x(char * l,struct wl12xx_ini * p)378 static int parse_band5_prms_128x(char *l, struct wl12xx_ini *p)
379 {
380 	char *name, *val;
381 	struct wl128x_ini_band_params_5 *gp = &(p->ini128x.stat_radio_params_5);
382 
383 	if (split_line(l, &name, &val)) {
384 		return 1;
385         }
386 
387 	COMPARE_N_ADD("RxTraceInsertionLoss_5G", l, val,
388 		gp->rx_trace_insertion_loss, 7);
389 
390 	COMPARE_N_ADD("TxTraceLoss_5G", l, val,
391 		gp->tx_trace_loss, 7);
392 
393 	fprintf(stderr, "Unable to parse: (%s)\n", l);
394 
395 	return 1;
396 }
397 
parse_fem0_band2_prms(char * l,struct wl12xx_ini * p)398 static int parse_fem0_band2_prms(char *l, struct wl12xx_ini *p)
399 {
400 	char *name, *val;
401 	struct wl1271_ini_fem_params_2 *gp =
402 		&(p->ini1271.dyn_radio_params_2[0].params);
403 
404 	if (split_line(l, &name, &val)) {
405 		return 1;
406         }
407 
408 	COMPARE_N_ADD2("FEM0_TXBiPReferencePDvoltage_2_4G", l, val,
409 		&gp->tx_bip_ref_pd_voltage, 1);
410 
411 	COMPARE_N_ADD("FEM0_TxBiPReferencePower_2_4G", l, val,
412 		&gp->tx_bip_ref_power, 1);
413 
414 	COMPARE_N_ADD("FEM0_TxBiPOffsetdB_2_4G", l, val,
415 		&gp->tx_bip_ref_offset, 1);
416 
417 	COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Normal", l, val,
418 		gp->tx_per_rate_pwr_limits_normal,
419 		WL1271_INI_RATE_GROUP_COUNT);
420 
421 	COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Degraded", l, val,
422 		gp->tx_per_rate_pwr_limits_degraded,
423 		WL1271_INI_RATE_GROUP_COUNT);
424 
425 	COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Extreme", l, val,
426 		gp->tx_per_rate_pwr_limits_extreme,
427 		WL1271_INI_RATE_GROUP_COUNT);
428 
429 	COMPARE_N_ADD("FEM0_DegradedLowToNormalThr_2_4G", l, val,
430 		&gp->degraded_low_to_normal_thr, 1);
431 
432 	COMPARE_N_ADD("FEM0_NormalToDegradedHighThr_2_4G", l, val,
433 		&gp->normal_to_degraded_high_thr, 1);
434 
435 	COMPARE_N_ADD("FEM0_TxPerChannelPowerLimits_2_4G_11b", l, val,
436 		gp->tx_per_chan_pwr_limits_11b,
437 		WL1271_INI_CHANNEL_COUNT_2);
438 
439 	COMPARE_N_ADD("FEM0_TxPerChannelPowerLimits_2_4G_OFDM", l, val,
440 		gp->tx_per_chan_pwr_limits_ofdm,
441 		WL1271_INI_CHANNEL_COUNT_2);
442 
443 	COMPARE_N_ADD("FEM0_TxPDVsRateOffsets_2_4G", l, val,
444 		gp->tx_pd_vs_rate_offsets,
445 		WL1271_INI_RATE_GROUP_COUNT);
446 
447 	COMPARE_N_ADD("FEM0_TxIbiasTable_2_4G", l, val,
448 		gp->tx_ibias,
449 		WL1271_INI_RATE_GROUP_COUNT);
450 
451 	COMPARE_N_ADD("FEM0_RxFemInsertionLoss_2_4G", l, val,
452 		&gp->rx_fem_insertion_loss, 1);
453 
454 	fprintf(stderr, "Unable to parse: (%s)\n", l);
455 
456 	return 1;
457 }
458 
parse_fem0_band2_prms_128x(char * l,struct wl12xx_ini * p)459 static int parse_fem0_band2_prms_128x(char *l, struct wl12xx_ini *p)
460 {
461 	char *name, *val;
462 	struct wl128x_ini_fem_params_2 *gp =
463 		&(p->ini128x.dyn_radio_params_2[0].params);
464 
465 	if (split_line(l, &name, &val)) {
466 		return 1;
467         }
468 
469 	COMPARE_N_ADD2("FEM0_TxBiPReferencePDvoltage_2_4G", l, val,
470 		&gp->tx_bip_ref_pd_voltage, 1);
471 
472 	COMPARE_N_ADD("FEM0_TxBiPReferencePower_2_4G", l, val,
473 		&gp->tx_bip_ref_power, 1);
474 
475 	COMPARE_N_ADD("FEM0_TxBiPOffsetdB_2_4G", l, val,
476 		&gp->tx_bip_ref_offset, 1);
477 
478 	COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Normal", l, val,
479 		gp->tx_per_rate_pwr_limits_normal,
480 		WL1271_INI_RATE_GROUP_COUNT);
481 
482 	COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Degraded", l, val,
483 		gp->tx_per_rate_pwr_limits_degraded,
484 		WL1271_INI_RATE_GROUP_COUNT);
485 
486 	COMPARE_N_ADD("FEM0_TxPerRatePowerLimits_2_4G_Extreme", l, val,
487 		gp->tx_per_rate_pwr_limits_extreme,
488 		WL1271_INI_RATE_GROUP_COUNT);
489 
490 	COMPARE_N_ADD("FEM0_DegradedLowToNormalThr_2_4G", l, val,
491 		&gp->degraded_low_to_normal_thr, 1);
492 
493 	COMPARE_N_ADD("FEM0_NormalToDegradedHighThr_2_4G", l, val,
494 		&gp->normal_to_degraded_high_thr, 1);
495 
496 	COMPARE_N_ADD("FEM0_TxPerChannelPowerLimits_2_4G_11b", l, val,
497 		gp->tx_per_chan_pwr_limits_11b,
498 		WL1271_INI_CHANNEL_COUNT_2);
499 
500 	COMPARE_N_ADD("FEM0_TxPerChannelPowerLimits_2_4G_OFDM", l, val,
501 		gp->tx_per_chan_pwr_limits_ofdm,
502 		WL1271_INI_CHANNEL_COUNT_2);
503 
504 	COMPARE_N_ADD("FEM0_TxPDVsRateOffsets_2_4G", l, val,
505 		gp->tx_pd_vs_rate_offsets,
506 		WL1271_INI_RATE_GROUP_COUNT);
507 
508 	COMPARE_N_ADD("FEM0_TxPDVsChannelOffsets_2_4G", l, val,
509 		gp->tx_pd_vs_chan_offsets,
510 		WL1271_INI_CHANNEL_COUNT_2);
511 
512 	COMPARE_N_ADD("FEM0_TxPDVsTemperature_2_4G", l, val,
513 		gp->tx_pd_vs_temperature,
514 		WL128X_INI_PD_VS_TEMPERATURE_RANGES);
515 
516 	COMPARE_N_ADD("FEM0_TxIbiasTable_2_4G", l, val,
517 		gp->tx_ibias,
518 		WL1271_INI_RATE_GROUP_COUNT);
519 
520 	COMPARE_N_ADD("FEM0_RxFemInsertionLoss_2_4G", l, val,
521 		&gp->rx_fem_insertion_loss, 1);
522 
523 	fprintf(stderr, "Unable to parse: (%s)\n", l);
524 
525 	return 1;
526 }
527 
parse_fem1_band2_prms(char * l,struct wl12xx_ini * p)528 static int parse_fem1_band2_prms(char *l, struct wl12xx_ini *p)
529 {
530 	char *name, *val;
531 	struct wl1271_ini_fem_params_2 *gp =
532 		&(p->ini1271.dyn_radio_params_2[1].params);
533 
534 	if (split_line(l, &name, &val)) {
535 		return 1;
536         }
537 
538 	COMPARE_N_ADD2("FEM1_TXBiPReferencePDvoltage_2_4G", l, val,
539 		&gp->tx_bip_ref_pd_voltage, 1);
540 
541 	COMPARE_N_ADD("FEM1_TxBiPReferencePower_2_4G", l, val,
542 		&gp->tx_bip_ref_power, 1);
543 
544 	COMPARE_N_ADD("FEM1_TxBiPOffsetdB_2_4G", l, val,
545 		&gp->tx_bip_ref_offset, 1);
546 
547 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Normal", l, val,
548 		gp->tx_per_rate_pwr_limits_normal,
549 		WL1271_INI_RATE_GROUP_COUNT);
550 
551 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Degraded", l, val,
552 		gp->tx_per_rate_pwr_limits_degraded,
553 		WL1271_INI_RATE_GROUP_COUNT);
554 
555 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Extreme", l, val,
556 		gp->tx_per_rate_pwr_limits_extreme,
557 		WL1271_INI_RATE_GROUP_COUNT);
558 
559 	COMPARE_N_ADD("FEM1_DegradedLowToNormalThr_2_4G", l, val,
560 		&gp->degraded_low_to_normal_thr, 1);
561 
562 	COMPARE_N_ADD("FEM1_NormalToDegradedHighThr_2_4G", l, val,
563 		&gp->normal_to_degraded_high_thr, 1);
564 
565 	COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_2_4G_11b", l, val,
566 		gp->tx_per_chan_pwr_limits_11b,
567 		WL1271_INI_CHANNEL_COUNT_2);
568 
569 	COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_2_4G_OFDM", l, val,
570 		gp->tx_per_chan_pwr_limits_ofdm,
571 		WL1271_INI_CHANNEL_COUNT_2);
572 
573 	COMPARE_N_ADD("FEM1_TxPDVsRateOffsets_2_4G", l, val,
574 		gp->tx_pd_vs_rate_offsets,
575 		WL1271_INI_RATE_GROUP_COUNT);
576 
577 	COMPARE_N_ADD("FEM1_TxIbiasTable_2_4G", l, val,
578 		gp->tx_ibias,
579 		WL1271_INI_RATE_GROUP_COUNT);
580 
581 	COMPARE_N_ADD("FEM1_RxFemInsertionLoss_2_4G", l, val,
582 		&gp->rx_fem_insertion_loss, 1);
583 
584 	fprintf(stderr, "Unable to parse: (%s)\n", l);
585 
586 	return 1;
587 }
588 
parse_fem1_band2_prms_128x(char * l,struct wl12xx_ini * p)589 static int parse_fem1_band2_prms_128x(char *l, struct wl12xx_ini *p)
590 {
591 	char *name, *val;
592 	struct wl128x_ini_fem_params_2 *gp =
593 		&(p->ini128x.dyn_radio_params_2[1].params);
594 
595 	if (split_line(l, &name, &val)) {
596 		return 1;
597         }
598 
599 	COMPARE_N_ADD2("FEM1_TxBiPReferencePDvoltage_2_4G", l, val,
600 		&gp->tx_bip_ref_pd_voltage, 1);
601 
602 	COMPARE_N_ADD("FEM1_TxBiPReferencePower_2_4G", l, val,
603 		&gp->tx_bip_ref_power, 1);
604 
605 	COMPARE_N_ADD("FEM1_TxBiPOffsetdB_2_4G", l, val,
606 		&gp->tx_bip_ref_offset, 1);
607 
608 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Normal", l, val,
609 		gp->tx_per_rate_pwr_limits_normal,
610 		WL128X_INI_RATE_GROUP_COUNT);
611 
612 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Degraded", l, val,
613 		gp->tx_per_rate_pwr_limits_degraded,
614 		WL128X_INI_RATE_GROUP_COUNT);
615 
616 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_2_4G_Extreme", l, val,
617 		gp->tx_per_rate_pwr_limits_extreme,
618 		WL128X_INI_RATE_GROUP_COUNT);
619 
620 	COMPARE_N_ADD("FEM1_DegradedLowToNormalThr_2_4G", l, val,
621 		&gp->degraded_low_to_normal_thr, 1);
622 
623 	COMPARE_N_ADD("FEM1_NormalToDegradedHighThr_2_4G", l, val,
624 		&gp->normal_to_degraded_high_thr, 1);
625 
626 	COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_2_4G_11b", l, val,
627 		gp->tx_per_chan_pwr_limits_11b,
628 		WL1271_INI_CHANNEL_COUNT_2);
629 
630 	COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_2_4G_OFDM", l, val,
631 		gp->tx_per_chan_pwr_limits_ofdm,
632 		WL1271_INI_CHANNEL_COUNT_2);
633 
634 	COMPARE_N_ADD("FEM1_TxPDVsRateOffsets_2_4G", l, val,
635 		gp->tx_pd_vs_rate_offsets,
636 		WL128X_INI_RATE_GROUP_COUNT);
637 
638 	COMPARE_N_ADD("FEM1_TxPDVsChannelOffsets_2_4G", l, val,
639 		gp->tx_pd_vs_chan_offsets,
640 		WL1271_INI_CHANNEL_COUNT_2);
641 
642 	COMPARE_N_ADD("FEM1_TxPDVsTemperature_2_4G", l, val,
643 		gp->tx_pd_vs_temperature,
644 		WL128X_INI_PD_VS_TEMPERATURE_RANGES);
645 
646 	COMPARE_N_ADD("FEM1_TxIbiasTable_2_4G", l, val,
647 		gp->tx_ibias,
648 		WL128X_INI_RATE_GROUP_COUNT);
649 
650 	COMPARE_N_ADD("FEM1_RxFemInsertionLoss_2_4G", l, val,
651 		&gp->rx_fem_insertion_loss, 1);
652 
653 	fprintf(stderr, "Unable to parse: (%s)\n", l);
654 
655 	return 1;
656 }
657 
parse_fem1_band5_prms(char * l,struct wl12xx_ini * p)658 static int parse_fem1_band5_prms(char *l, struct wl12xx_ini *p)
659 {
660 	char *name, *val;
661 	struct wl1271_ini_fem_params_5 *gp =
662 		&(p->ini1271.dyn_radio_params_5[1].params);
663 
664 	if (split_line(l, &name, &val)) {
665 		return 1;
666         }
667 
668 	COMPARE_N_ADD2("FEM1_TXBiPReferencePDvoltage_5G", l, val,
669 		gp->tx_bip_ref_pd_voltage, WL1271_INI_SUB_BAND_COUNT_5);
670 
671 	COMPARE_N_ADD("FEM1_TxBiPReferencePower_5G", l, val,
672 		gp->tx_bip_ref_power, WL1271_INI_SUB_BAND_COUNT_5);
673 
674 	COMPARE_N_ADD("FEM1_TxBiPOffsetdB_5G", l, val,
675 		gp->tx_bip_ref_offset, WL1271_INI_SUB_BAND_COUNT_5);
676 
677 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Normal", l, val,
678 		gp->tx_per_rate_pwr_limits_normal,
679 		WL1271_INI_RATE_GROUP_COUNT);
680 
681 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Degraded", l, val,
682 		gp->tx_per_rate_pwr_limits_degraded,
683 		WL1271_INI_RATE_GROUP_COUNT);
684 
685 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Extreme", l, val,
686 		gp->tx_per_rate_pwr_limits_extreme,
687 		WL1271_INI_RATE_GROUP_COUNT);
688 
689 	COMPARE_N_ADD("FEM1_DegradedLowToNormalThr_5G", l, val,
690 		&gp->degraded_low_to_normal_thr, 1);
691 
692 	COMPARE_N_ADD("FEM1_NormalToDegradedHighThr_5G", l, val,
693 		&gp->normal_to_degraded_high_thr, 1);
694 
695 	COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_5G_OFDM", l, val,
696 		gp->tx_per_chan_pwr_limits_ofdm,
697 		WL1271_INI_CHANNEL_COUNT_5);
698 
699 	COMPARE_N_ADD("FEM1_TxPDVsRateOffsets_5G", l, val,
700 		gp->tx_pd_vs_rate_offsets,
701 		WL1271_INI_RATE_GROUP_COUNT);
702 
703 	COMPARE_N_ADD("FEM1_TxIbiasTable_5G", l, val,
704 		gp->tx_ibias,
705 		WL1271_INI_RATE_GROUP_COUNT);
706 
707 	COMPARE_N_ADD("FEM1_RxFemInsertionLoss_5G", l, val,
708 		gp->rx_fem_insertion_loss, WL1271_INI_SUB_BAND_COUNT_5);
709 
710 	fprintf(stderr, "Unable to parse: (%s)\n", l);
711 
712 	return 1;
713 }
714 
parse_fem1_band5_prms_128x(char * l,struct wl12xx_ini * p)715 static int parse_fem1_band5_prms_128x(char *l, struct wl12xx_ini *p)
716 {
717 	char *name, *val;
718 	struct wl128x_ini_fem_params_5 *gp =
719 		&(p->ini128x.dyn_radio_params_5[1].params);
720 
721 	if (split_line(l, &name, &val)) {
722 		return 1;
723         }
724 
725 	COMPARE_N_ADD2("FEM1_TxBiPReferencePDvoltage_5G", l, val,
726 		gp->tx_bip_ref_pd_voltage, WL1271_INI_SUB_BAND_COUNT_5);
727 
728 	COMPARE_N_ADD("FEM1_TxBiPReferencePower_5G", l, val,
729 		gp->tx_bip_ref_power, WL1271_INI_SUB_BAND_COUNT_5);
730 
731 	COMPARE_N_ADD("FEM1_TxBiPOffsetdB_5G", l, val,
732 		gp->tx_bip_ref_offset, WL1271_INI_SUB_BAND_COUNT_5);
733 
734 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Normal", l, val,
735 		gp->tx_per_rate_pwr_limits_normal,
736 		WL128X_INI_RATE_GROUP_COUNT);
737 
738 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Degraded", l, val,
739 		gp->tx_per_rate_pwr_limits_degraded,
740 		WL128X_INI_RATE_GROUP_COUNT);
741 
742 	COMPARE_N_ADD("FEM1_TxPerRatePowerLimits_5G_Extreme", l, val,
743 		gp->tx_per_rate_pwr_limits_extreme,
744 		WL128X_INI_RATE_GROUP_COUNT);
745 
746 	COMPARE_N_ADD("FEM1_DegradedLowToNormalThr_5G", l, val,
747 		&gp->degraded_low_to_normal_thr, 1);
748 
749 	COMPARE_N_ADD("FEM1_NormalToDegradedHighThr_5G", l, val,
750 		&gp->normal_to_degraded_high_thr, 1);
751 
752 	COMPARE_N_ADD("FEM1_TxPerChannelPowerLimits_5G_OFDM", l, val,
753 		gp->tx_per_chan_pwr_limits_ofdm,
754 		WL1271_INI_CHANNEL_COUNT_5);
755 
756 	COMPARE_N_ADD("FEM1_TxPDVsRateOffsets_5G", l, val,
757 		gp->tx_pd_vs_rate_offsets,
758 		WL128X_INI_RATE_GROUP_COUNT);
759 
760 	COMPARE_N_ADD("FEM1_TxPDVsChannelOffsets_5G", l, val,
761 		gp->tx_pd_vs_chan_offsets,
762 		WL1271_INI_CHANNEL_COUNT_5);
763 
764 	COMPARE_N_ADD("FEM1_TxPDVsTemperature_5G", l, val,
765 		gp->tx_pd_vs_temperature,
766 		WL1271_INI_SUB_BAND_COUNT_5 * WL128X_INI_PD_VS_TEMPERATURE_RANGES);
767 
768 	COMPARE_N_ADD("FEM1_TxIbiasTable_5G", l, val,
769 		gp->tx_ibias,
770 		WL128X_INI_RATE_GROUP_COUNT);
771 
772 	COMPARE_N_ADD("FEM1_RxFemInsertionLoss_5G", l, val,
773 		gp->rx_fem_insertion_loss, WL1271_INI_SUB_BAND_COUNT_5);
774 
775 	fprintf(stderr, "Unable to parse: (%s)\n", l);
776 
777 	return 1;
778 }
779 
parse_fem_prms_128x(char * l,struct wl12xx_ini * p)780 static int parse_fem_prms_128x(char *l, struct wl12xx_ini *p)
781 {
782 	char *name, *val;
783 	struct wl128x_ini *gp = &p->ini128x;
784 
785 	if (split_line(l, &name, &val)) {
786 		return 1;
787         }
788 
789 	COMPARE_N_ADD("FemVendorAndOptions", l, val,
790 		&gp->fem_vendor_and_options, 1);
791 
792 	fprintf(stderr, "Unable to parse: (%s)\n", l);
793 
794 	return 1;
795 }
796 
find_section(const char * l,enum wl1271_ini_section * st,int * cntr,enum wl12xx_arch arch)797 static int find_section(const char *l, enum wl1271_ini_section *st, int *cntr,
798 	enum wl12xx_arch arch)
799 {
800 	if (strncmp("TXBiPFEMAutoDetect", l, 18) == 0) {
801 		*st = GENERAL_PRMS;
802 		if (arch == WL128X_ARCH) {
803 			*cntr = 17;
804                 } else {
805 			*cntr = 12;
806                 }
807 
808 		return 0;
809 	}
810 
811 	if (strncmp("RxTraceInsertionLoss_2_4G", l, 25) == 0) {
812 		*st = BAND2_PRMS;
813 		if (arch == WL128X_ARCH){
814 			*cntr = 2;
815                 } else {
816 			*cntr = 3;
817                 }
818 
819 		return 0;
820 	}
821 
822 	if (strncmp("FemVendorAndOptions", l, 19) == 0) {
823 		*st = FEM_PRMS;
824 		*cntr = 1;
825 		return 0;
826 	}
827 
828 	if (strncmp("RxTraceInsertionLoss_5G", l, 23) == 0) {
829 		*st = BAND5_PRMS;
830 		if (arch == WL128X_ARCH) {
831 			*cntr = 2;
832 		} else {
833 			*cntr = 3;
834                 }
835 
836 		return 0;
837 	}
838 
839 	if (strncmp("FEM0_TXBiPReferencePDvoltage_2_4G", l, 33) == 0 ||
840 		strncmp("FEM0_TxBiPReferencePDvoltage_2_4G", l, 33) == 0) {
841 		*st = FEM0_BAND2_PRMS;
842 		if (arch == WL128X_ARCH) {
843 			*cntr = 15;
844 		} else {
845 			*cntr = 13;
846                 }
847 
848 		return 0;
849 	}
850 
851 	if (strncmp("FEM1_TXBiPReferencePDvoltage_2_4G", l, 33) == 0 ||
852 		strncmp("FEM1_TxBiPReferencePDvoltage_2_4G", l, 33) == 0) {
853 		*st = FEM1_BAND2_PRMS;
854 		if (arch == WL128X_ARCH) {
855 			*cntr = 15;
856                 } else {
857 			*cntr = 13;
858                 }
859 
860 		return 0;
861 	}
862 
863 	if (strncmp("FEM1_TXBiPReferencePDvoltage_5G", l, 31) == 0 ||
864 		strncmp("FEM1_TxBiPReferencePDvoltage_5G", l, 31) == 0) {
865 		*st = FEM1_BAND5_PRMS;
866 		if (arch == WL128X_ARCH) {
867 			*cntr = 14;
868 		} else {
869 			*cntr = 12;
870                 }
871 
872 		return 0;
873 	}
874 
875 	return 1;
876 }
877 
ini_parse_line(char * l,int nbr,struct wl12xx_common * cmn)878 static int ini_parse_line(char *l, int nbr, struct wl12xx_common *cmn)
879 {
880 	static enum wl1271_ini_section status;
881 	static int cntr;
882 
883 	if (!cntr && find_section(l, &status, &cntr, cmn->arch)) {
884 		fprintf(stderr, "Uknown ini section %s\n", l);
885 		return 1;
886 	}
887 
888 	switch (status) {
889 	case GENERAL_PRMS:	/* general parameters */
890 		cntr--;
891 		return cmn->parse_ops->prs_general_prms(l, cmn, &cmn->ini);
892 	case FEM_PRMS:	/* FEM parameters */
893 		if (cmn->arch == WL1271_ARCH) {
894 			fprintf(stderr, "The parameter not from 127x architecture\n");
895 			return 1;
896 		}
897 		cntr--;
898 		return parse_fem_prms_128x(l, &cmn->ini);
899 	case BAND2_PRMS:	/* band 2.4GHz parameters */
900 		cntr--;
901 		return cmn->parse_ops->prs_band2_prms(l, &cmn->ini);
902 	case BAND5_PRMS:	/* band 5GHz parameters */
903 		cntr--;
904 		return cmn->parse_ops->prs_band5_prms(l, &cmn->ini);
905 	case FEM0_BAND2_PRMS:	/* FEM0 band 2.4GHz parameters */
906 		cntr--;
907 		return cmn->parse_ops->prs_fem0_band2_prms(l, &cmn->ini);
908 	case FEM1_BAND2_PRMS:	/* FEM1 band 2.4GHz parameters */
909 		cntr--;
910 		return cmn->parse_ops->prs_fem1_band2_prms(l, &cmn->ini);
911 	case FEM1_BAND5_PRMS:	/* FEM1 band 5GHz parameters */
912 		cntr--;
913 		return cmn->parse_ops->prs_fem1_band5_prms(l, &cmn->ini);
914 	case UKNOWN_SECTION:
915 		/* added because of compilation warning. handeled in find_section() */
916 		break;
917 	}
918 
919 	return 1;
920 }
921 
922 #if 0
923 static void ini_dump(struct wl1271_ini *ini)
924 {
925 	int i;
926 
927 	printf("\n");
928 	printf("General params:\n");
929 	printf("ref clock:                 %02X\n",
930 		ini->general_params.ref_clock);
931 	printf("settling time:             %02X\n",
932 		ini->general_params.settling_time);
933 	printf("clk valid on wakeup:       %02X\n",
934 		ini->general_params.clk_valid_on_wakeup);
935 	printf("dc2dc mode:                %02X\n",
936 		ini->general_params.dc2dc_mode);
937 	printf("dual band mode:            %02X\n",
938 		ini->general_params.dual_mode_select);
939 	printf("tx bip fem auto detect:    %02X\n",
940 		ini->general_params.tx_bip_fem_auto_detect);
941 	printf("tx bip fem manufacturer:   %02X\n",
942 		ini->general_params.tx_bip_fem_manufacturer);
943 	printf("general settings:          %02X\n",
944 		ini->general_params.general_settings);
945 	printf("sr state:                  %02X\n",
946 		ini->general_params.sr_state);
947 
948 	printf("srf1:");
949 	for (i = 0; i < WL1271_INI_MAX_SMART_REFLEX_PARAM; i++)
950 		printf(" %02X", ini->general_params.srf1[i]);
951 	printf("\n");
952 
953 	printf("srf2:");
954 	for (i = 0; i < WL1271_INI_MAX_SMART_REFLEX_PARAM; i++)
955 		printf(" %02X", ini->general_params.srf2[i]);
956 	printf("\n");
957 
958 	printf("srf3:");
959 	for (i = 0; i < WL1271_INI_MAX_SMART_REFLEX_PARAM; i++)
960 		printf(" %02X", ini->general_params.srf3[i]);
961 	printf("\n");
962 
963 	printf("Static 2.4 band params:\n");
964 
965 	printf("rx trace insertion loss: %02X\n",
966 		ini->stat_radio_params_2.rx_trace_insertion_loss);
967 
968 	printf("rx rssi n process compensation:");
969 	for (i = 0; i < WL1271_INI_RSSI_PROCESS_COMPENS_SIZE; i++)
970 		printf(" %02X",
971 			ini->stat_radio_params_2.rx_rssi_process_compens[i]);
972 	printf("\n");
973 
974 	printf("tx trace: %02X\n",
975 		ini->stat_radio_params_2.tx_trace_loss);
976 
977 	printf("Dynamic 2.4 band params for FEM\n");
978 
979 	printf("Static 5 band params:\n");
980 
981 	printf("rx trace insertion loss:");
982 	for (i = 0; i < WL1271_INI_SUB_BAND_COUNT_5; i++)
983 		printf(" %02X",
984 			ini->stat_radio_params_5.rx_rssi_process_compens[i]);
985 	printf("\n");
986 
987 	printf("rx rssi n process compensation:");
988 	for (i = 0; i < WL1271_INI_RSSI_PROCESS_COMPENS_SIZE; i++)
989 		printf(" %02X",
990 			ini->stat_radio_params_5.rx_rssi_process_compens[i]);
991 	printf("\n");
992 
993 	printf("tx trace:");
994 	for (i = 0; i < WL1271_INI_SUB_BAND_COUNT_5; i++)
995 		printf(" %02X",
996 			ini->stat_radio_params_5.tx_trace_loss[i]);
997 	printf("\n");
998 
999 	printf("Dynamic 5 band params for FEM\n");
1000 
1001 }
1002 #endif
1003 
1004 static struct wl12xx_parse_ops wl1271_parse_ops = {
1005 	.prs_general_prms       = parse_general_prms,
1006 	.prs_band2_prms         = parse_band2_prms,
1007 	.prs_band5_prms         = parse_band5_prms,
1008 	.prs_fem0_band2_prms    = parse_fem0_band2_prms,
1009 	.prs_fem1_band2_prms    = parse_fem1_band2_prms,
1010 	.prs_fem1_band5_prms    = parse_fem1_band5_prms,
1011 };
1012 
1013 static struct wl12xx_parse_ops wl128x_parse_ops = {
1014 	.prs_general_prms       = parse_general_prms_128x,
1015 	.prs_band2_prms         = parse_band2_prms_128x,
1016 	.prs_band5_prms         = parse_band5_prms_128x,
1017 	.prs_fem0_band2_prms    = parse_fem0_band2_prms_128x,
1018 	.prs_fem1_band2_prms    = parse_fem1_band2_prms_128x,
1019 	.prs_fem1_band5_prms    = parse_fem1_band5_prms_128x,
1020 };
1021 
nvs_get_arch(int file_size,struct wl12xx_common * cmn)1022 int nvs_get_arch(int file_size, struct wl12xx_common *cmn)
1023 {
1024 	enum wl12xx_arch arch = UNKNOWN_ARCH;
1025 
1026 	switch (file_size) {
1027 		case WL127X_NVS_FILE_SZ:
1028 			arch = WL1271_ARCH;
1029 			cmn->parse_ops = &wl1271_parse_ops;
1030 			break;
1031 		case WL128X_NVS_FILE_SZ:
1032 			arch = WL128X_ARCH;
1033 			cmn->parse_ops = &wl128x_parse_ops;
1034 			break;
1035 	}
1036 
1037 	if (cmn->arch != UNKNOWN_ARCH && cmn->arch != arch) {
1038 		cmn->parse_ops = NULL;
1039 		return 1;
1040 	}
1041 
1042 	cmn->arch = arch;
1043 
1044 	return 0;
1045 }
1046 
ini_get_arch(FILE * f,struct wl12xx_common * cmn)1047 static int ini_get_arch(FILE *f, struct wl12xx_common *cmn)
1048 {
1049 	char buf[1024], *pos;
1050 	int line = 0;
1051 	enum wl12xx_arch arch = UNKNOWN_ARCH;
1052 
1053 	while (ini_get_line(buf, sizeof(buf), f, &line, &pos)) {
1054 		if (strncmp("TCXO_Clk", pos, 8) == 0) {
1055 			arch = WL128X_ARCH;
1056 			break;
1057 		}
1058 	}
1059 
1060 	if (arch == UNKNOWN_ARCH) {
1061 		arch = WL1271_ARCH;
1062         }
1063 
1064 	if (cmn->arch != UNKNOWN_ARCH && cmn->arch != arch) {
1065 		return 1;
1066         }
1067 
1068 	cmn->arch = arch;
1069 
1070 	if (cmn->arch == WL1271_ARCH) {
1071 		cmn->parse_ops = &wl1271_parse_ops;
1072         } else {
1073 		cmn->parse_ops = &wl128x_parse_ops;
1074         }
1075 
1076 	fseek(f, 0L, SEEK_SET);
1077 
1078 	return 0;
1079 }
1080 
read_ini(const char * filename,struct wl12xx_common * cmn)1081 int read_ini(const char *filename, struct wl12xx_common *cmn)
1082 {
1083 	FILE *f;
1084 	char buf[1024], *pos;
1085 	int ret = 0, line = 0;
1086 
1087 	f = fopen(filename, "r");
1088 	if (f == NULL) {
1089 		fprintf(stderr, "Unable to open file %s (%s)\n",
1090 			filename, strerror(errno));
1091 		return 1;
1092 	}
1093 
1094 	/* check if it 127x or 128x */
1095 	if (ini_get_arch(f, cmn)) {
1096 		fprintf(stderr, "Unable to define wireless architecture\n");
1097 		ret = 1;
1098 		goto out;
1099 	}
1100 
1101 	/* start parsing */
1102 	while (ini_get_line(buf, sizeof(buf), f, &line, &pos)) {
1103 		ret = ini_parse_line(pos, line, cmn);
1104 		if (ret) break;
1105 	}
1106 
1107 out:
1108 	fclose(f);
1109 #if 0
1110 	ini_dump(ini);
1111 #endif
1112 	return ret;
1113 }
1114