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