staging: brcm80211: replace MFREE with kfree
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / brcm80211 / util / bcmsrom.c
1 /*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <typedefs.h>
18 #include <bcmdefs.h>
19 #include <osl.h>
20 #include <linux/kernel.h>
21 #include <linux/string.h>
22 #include <linuxver.h>
23 #include <stdarg.h>
24 #include <bcmutils.h>
25 #include <hndsoc.h>
26 #include <sbchipc.h>
27 #include <bcmdevs.h>
28 #include <bcmendian.h>
29 #include <pcicfg.h>
30 #include <siutils.h>
31 #include <bcmsrom.h>
32 #include <bcmsrom_tbl.h>
33 #ifdef BCMSDIO
34 #include <bcmsdh.h>
35 #include <sdio.h>
36 #endif
37
38 #include <bcmnvram.h>
39 #include <bcmotp.h>
40
41 #if defined(BCMSDIO)
42 #include <sbsdio.h>
43 #include <sbhnddma.h>
44 #include <sbsdpcmdev.h>
45 #endif
46
47 #include <proto/ethernet.h> /* for sprom content groking */
48
49 #define BS_ERROR(args)
50
51 #define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
52 (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
53 ((u8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
54 ((u8 *)curmap + PCI_BAR0_SPROM_OFFSET))
55
56 #if defined(BCMDBG)
57 #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
58 #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
59 #endif
60
61 typedef struct varbuf {
62 char *base; /* pointer to buffer base */
63 char *buf; /* pointer to current position */
64 unsigned int size; /* current (residual) size in bytes */
65 } varbuf_t;
66 extern char *_vars;
67 extern uint _varsz;
68
69 #define SROM_CIS_SINGLE 1
70
71 static int initvars_srom_si(si_t *sih, osl_t *osh, void *curmap, char **vars,
72 uint *count);
73 static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off,
74 varbuf_t *b);
75 static int initvars_srom_pci(si_t *sih, void *curmap, char **vars,
76 uint *count);
77 static int initvars_flash_si(si_t *sih, char **vars, uint *count);
78 #ifdef BCMSDIO
79 static int initvars_cis_sdio(osl_t *osh, char **vars, uint *count);
80 static int sprom_cmd_sdio(osl_t *osh, u8 cmd);
81 static int sprom_read_sdio(osl_t *osh, u16 addr, u16 *data);
82 #endif /* BCMSDIO */
83 static int sprom_read_pci(osl_t *osh, si_t *sih, u16 *sprom, uint wordoff,
84 u16 *buf, uint nwords, bool check_crc);
85 #if defined(BCMNVRAMR)
86 static int otp_read_pci(osl_t *osh, si_t *sih, u16 *buf, uint bufsz);
87 #endif
88 static u16 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, u32 cmd,
89 uint wordoff, u16 data);
90
91 static int initvars_table(osl_t *osh, char *start, char *end, char **vars,
92 uint *count);
93 static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len);
94
95 /* Initialization of varbuf structure */
96 static void varbuf_init(varbuf_t *b, char *buf, uint size)
97 {
98 b->size = size;
99 b->base = b->buf = buf;
100 }
101
102 /* append a null terminated var=value string */
103 static int varbuf_append(varbuf_t *b, const char *fmt, ...)
104 {
105 va_list ap;
106 int r;
107 size_t len;
108 char *s;
109
110 if (b->size < 2)
111 return 0;
112
113 va_start(ap, fmt);
114 r = vsnprintf(b->buf, b->size, fmt, ap);
115 va_end(ap);
116
117 /* C99 snprintf behavior returns r >= size on overflow,
118 * others return -1 on overflow.
119 * All return -1 on format error.
120 * We need to leave room for 2 null terminations, one for the current var
121 * string, and one for final null of the var table. So check that the
122 * strlen written, r, leaves room for 2 chars.
123 */
124 if ((r == -1) || (r > (int)(b->size - 2))) {
125 b->size = 0;
126 return 0;
127 }
128
129 /* Remove any earlier occurrence of the same variable */
130 s = strchr(b->buf, '=');
131 if (s != NULL) {
132 len = (size_t) (s - b->buf);
133 for (s = b->base; s < b->buf;) {
134 if ((bcmp(s, b->buf, len) == 0) && s[len] == '=') {
135 len = strlen(s) + 1;
136 memmove(s, (s + len),
137 ((b->buf + r + 1) - (s + len)));
138 b->buf -= len;
139 b->size += (unsigned int)len;
140 break;
141 }
142
143 while (*s++)
144 ;
145 }
146 }
147
148 /* skip over this string's null termination */
149 r++;
150 b->size -= r;
151 b->buf += r;
152
153 return r;
154 }
155
156 /*
157 * Initialize local vars from the right source for this platform.
158 * Return 0 on success, nonzero on error.
159 */
160 int srom_var_init(si_t *sih, uint bustype, void *curmap, osl_t *osh,
161 char **vars, uint *count)
162 {
163 uint len;
164
165 len = 0;
166
167 ASSERT(bustype == BUSTYPE(bustype));
168 if (vars == NULL || count == NULL)
169 return 0;
170
171 *vars = NULL;
172 *count = 0;
173
174 switch (BUSTYPE(bustype)) {
175 case SI_BUS:
176 case JTAG_BUS:
177 return initvars_srom_si(sih, osh, curmap, vars, count);
178
179 case PCI_BUS:
180 ASSERT(curmap != NULL);
181 if (curmap == NULL)
182 return -1;
183
184 return initvars_srom_pci(sih, curmap, vars, count);
185
186 #ifdef BCMSDIO
187 case SDIO_BUS:
188 return initvars_cis_sdio(osh, vars, count);
189 #endif /* BCMSDIO */
190
191 default:
192 ASSERT(0);
193 }
194 return -1;
195 }
196
197 /* support only 16-bit word read from srom */
198 int
199 srom_read(si_t *sih, uint bustype, void *curmap, osl_t *osh,
200 uint byteoff, uint nbytes, u16 *buf, bool check_crc)
201 {
202 uint off, nw;
203 #ifdef BCMSDIO
204 uint i;
205 #endif /* BCMSDIO */
206
207 ASSERT(bustype == BUSTYPE(bustype));
208
209 /* check input - 16-bit access only */
210 if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX)
211 return 1;
212
213 off = byteoff / 2;
214 nw = nbytes / 2;
215
216 if (BUSTYPE(bustype) == PCI_BUS) {
217 if (!curmap)
218 return 1;
219
220 if (si_is_sprom_available(sih)) {
221 u16 *srom;
222
223 srom = (u16 *) SROM_OFFSET(sih);
224 if (srom == NULL)
225 return 1;
226
227 if (sprom_read_pci
228 (osh, sih, srom, off, buf, nw, check_crc))
229 return 1;
230 }
231 #if defined(BCMNVRAMR)
232 else {
233 if (otp_read_pci(osh, sih, buf, SROM_MAX))
234 return 1;
235 }
236 #endif
237 #ifdef BCMSDIO
238 } else if (BUSTYPE(bustype) == SDIO_BUS) {
239 off = byteoff / 2;
240 nw = nbytes / 2;
241 for (i = 0; i < nw; i++) {
242 if (sprom_read_sdio
243 (osh, (u16) (off + i), (u16 *) (buf + i)))
244 return 1;
245 }
246 #endif /* BCMSDIO */
247 } else if (BUSTYPE(bustype) == SI_BUS) {
248 return 1;
249 } else {
250 return 1;
251 }
252
253 return 0;
254 }
255
256 static const char vstr_manf[] = "manf=%s";
257 static const char vstr_productname[] = "productname=%s";
258 static const char vstr_manfid[] = "manfid=0x%x";
259 static const char vstr_prodid[] = "prodid=0x%x";
260 #ifdef BCMSDIO
261 static const char vstr_sdmaxspeed[] = "sdmaxspeed=%d";
262 static const char vstr_sdmaxblk[][13] = {
263 "sdmaxblk0=%d", "sdmaxblk1=%d", "sdmaxblk2=%d"};
264 #endif
265 static const char vstr_regwindowsz[] = "regwindowsz=%d";
266 static const char vstr_sromrev[] = "sromrev=%d";
267 static const char vstr_chiprev[] = "chiprev=%d";
268 static const char vstr_subvendid[] = "subvendid=0x%x";
269 static const char vstr_subdevid[] = "subdevid=0x%x";
270 static const char vstr_boardrev[] = "boardrev=0x%x";
271 static const char vstr_aa2g[] = "aa2g=0x%x";
272 static const char vstr_aa5g[] = "aa5g=0x%x";
273 static const char vstr_ag[] = "ag%d=0x%x";
274 static const char vstr_cc[] = "cc=%d";
275 static const char vstr_opo[] = "opo=%d";
276 static const char vstr_pa0b[][9] = {
277 "pa0b0=%d", "pa0b1=%d", "pa0b2=%d"};
278
279 static const char vstr_pa0itssit[] = "pa0itssit=%d";
280 static const char vstr_pa0maxpwr[] = "pa0maxpwr=%d";
281 static const char vstr_pa1b[][9] = {
282 "pa1b0=%d", "pa1b1=%d", "pa1b2=%d"};
283
284 static const char vstr_pa1lob[][11] = {
285 "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d"};
286
287 static const char vstr_pa1hib[][11] = {
288 "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d"};
289
290 static const char vstr_pa1itssit[] = "pa1itssit=%d";
291 static const char vstr_pa1maxpwr[] = "pa1maxpwr=%d";
292 static const char vstr_pa1lomaxpwr[] = "pa1lomaxpwr=%d";
293 static const char vstr_pa1himaxpwr[] = "pa1himaxpwr=%d";
294 static const char vstr_oem[] =
295 "oem=%02x%02x%02x%02x%02x%02x%02x%02x";
296 static const char vstr_boardflags[] = "boardflags=0x%x";
297 static const char vstr_boardflags2[] = "boardflags2=0x%x";
298 static const char vstr_ledbh[] = "ledbh%d=0x%x";
299 static const char vstr_noccode[] = "ccode=0x0";
300 static const char vstr_ccode[] = "ccode=%c%c";
301 static const char vstr_cctl[] = "cctl=0x%x";
302 static const char vstr_cckpo[] = "cckpo=0x%x";
303 static const char vstr_ofdmpo[] = "ofdmpo=0x%x";
304 static const char vstr_rdlid[] = "rdlid=0x%x";
305 static const char vstr_rdlrndis[] = "rdlrndis=%d";
306 static const char vstr_rdlrwu[] = "rdlrwu=%d";
307 static const char vstr_usbfs[] = "usbfs=%d";
308 static const char vstr_wpsgpio[] = "wpsgpio=%d";
309 static const char vstr_wpsled[] = "wpsled=%d";
310 static const char vstr_rdlsn[] = "rdlsn=%d";
311 static const char vstr_rssismf2g[] = "rssismf2g=%d";
312 static const char vstr_rssismc2g[] = "rssismc2g=%d";
313 static const char vstr_rssisav2g[] = "rssisav2g=%d";
314 static const char vstr_bxa2g[] = "bxa2g=%d";
315 static const char vstr_rssismf5g[] = "rssismf5g=%d";
316 static const char vstr_rssismc5g[] = "rssismc5g=%d";
317 static const char vstr_rssisav5g[] = "rssisav5g=%d";
318 static const char vstr_bxa5g[] = "bxa5g=%d";
319 static const char vstr_tri2g[] = "tri2g=%d";
320 static const char vstr_tri5gl[] = "tri5gl=%d";
321 static const char vstr_tri5g[] = "tri5g=%d";
322 static const char vstr_tri5gh[] = "tri5gh=%d";
323 static const char vstr_rxpo2g[] = "rxpo2g=%d";
324 static const char vstr_rxpo5g[] = "rxpo5g=%d";
325 static const char vstr_boardtype[] = "boardtype=0x%x";
326 static const char vstr_leddc[] = "leddc=0x%04x";
327 static const char vstr_vendid[] = "vendid=0x%x";
328 static const char vstr_devid[] = "devid=0x%x";
329 static const char vstr_xtalfreq[] = "xtalfreq=%d";
330 static const char vstr_txchain[] = "txchain=0x%x";
331 static const char vstr_rxchain[] = "rxchain=0x%x";
332 static const char vstr_antswitch[] = "antswitch=0x%x";
333 static const char vstr_regrev[] = "regrev=0x%x";
334 static const char vstr_antswctl2g[] = "antswctl2g=0x%x";
335 static const char vstr_triso2g[] = "triso2g=0x%x";
336 static const char vstr_pdetrange2g[] = "pdetrange2g=0x%x";
337 static const char vstr_extpagain2g[] = "extpagain2g=0x%x";
338 static const char vstr_tssipos2g[] = "tssipos2g=0x%x";
339 static const char vstr_antswctl5g[] = "antswctl5g=0x%x";
340 static const char vstr_triso5g[] = "triso5g=0x%x";
341 static const char vstr_pdetrange5g[] = "pdetrange5g=0x%x";
342 static const char vstr_extpagain5g[] = "extpagain5g=0x%x";
343 static const char vstr_tssipos5g[] = "tssipos5g=0x%x";
344 static const char vstr_maxp2ga0[] = "maxp2ga0=0x%x";
345 static const char vstr_itt2ga0[] = "itt2ga0=0x%x";
346 static const char vstr_pa[] = "pa%dgw%da%d=0x%x";
347 static const char vstr_pahl[] = "pa%dg%cw%da%d=0x%x";
348 static const char vstr_maxp5ga0[] = "maxp5ga0=0x%x";
349 static const char vstr_itt5ga0[] = "itt5ga0=0x%x";
350 static const char vstr_maxp5gha0[] = "maxp5gha0=0x%x";
351 static const char vstr_maxp5gla0[] = "maxp5gla0=0x%x";
352 static const char vstr_maxp2ga1[] = "maxp2ga1=0x%x";
353 static const char vstr_itt2ga1[] = "itt2ga1=0x%x";
354 static const char vstr_maxp5ga1[] = "maxp5ga1=0x%x";
355 static const char vstr_itt5ga1[] = "itt5ga1=0x%x";
356 static const char vstr_maxp5gha1[] = "maxp5gha1=0x%x";
357 static const char vstr_maxp5gla1[] = "maxp5gla1=0x%x";
358 static const char vstr_cck2gpo[] = "cck2gpo=0x%x";
359 static const char vstr_ofdm2gpo[] = "ofdm2gpo=0x%x";
360 static const char vstr_ofdm5gpo[] = "ofdm5gpo=0x%x";
361 static const char vstr_ofdm5glpo[] = "ofdm5glpo=0x%x";
362 static const char vstr_ofdm5ghpo[] = "ofdm5ghpo=0x%x";
363 static const char vstr_cddpo[] = "cddpo=0x%x";
364 static const char vstr_stbcpo[] = "stbcpo=0x%x";
365 static const char vstr_bw40po[] = "bw40po=0x%x";
366 static const char vstr_bwduppo[] = "bwduppo=0x%x";
367 static const char vstr_mcspo[] = "mcs%dgpo%d=0x%x";
368 static const char vstr_mcspohl[] = "mcs%dg%cpo%d=0x%x";
369 static const char vstr_custom[] = "customvar%d=0x%x";
370 static const char vstr_cckdigfilttype[] = "cckdigfilttype=%d";
371 static const char vstr_boardnum[] = "boardnum=%d";
372 static const char vstr_macaddr[] = "macaddr=%s";
373 static const char vstr_usbepnum[] = "usbepnum=0x%x";
374 static const char vstr_end[] = "END\0";
375
376 u8 patch_pair;
377
378 /* For dongle HW, accept partial calibration parameters */
379 #define BCMDONGLECASE(n)
380
381 int srom_parsecis(osl_t *osh, u8 *pcis[], uint ciscnt, char **vars, uint *count)
382 {
383 char eabuf[32];
384 char *base;
385 varbuf_t b;
386 u8 *cis, tup, tlen, sromrev = 1;
387 int i, j;
388 bool ag_init = false;
389 u32 w32;
390 uint funcid;
391 uint cisnum;
392 s32 boardnum;
393 int err;
394 bool standard_cis;
395
396 ASSERT(vars != NULL);
397 ASSERT(count != NULL);
398
399 boardnum = -1;
400
401 base = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
402 ASSERT(base != NULL);
403 if (!base)
404 return -2;
405
406 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
407 bzero(base, MAXSZ_NVRAM_VARS);
408 eabuf[0] = '\0';
409 for (cisnum = 0; cisnum < ciscnt; cisnum++) {
410 cis = *pcis++;
411 i = 0;
412 funcid = 0;
413 standard_cis = true;
414 do {
415 if (standard_cis) {
416 tup = cis[i++];
417 if (tup == CISTPL_NULL || tup == CISTPL_END)
418 tlen = 0;
419 else
420 tlen = cis[i++];
421 } else {
422 if (cis[i] == CISTPL_NULL
423 || cis[i] == CISTPL_END) {
424 tlen = 0;
425 tup = cis[i];
426 } else {
427 tlen = cis[i];
428 tup = CISTPL_BRCM_HNBU;
429 }
430 ++i;
431 }
432 if ((i + tlen) >= CIS_SIZE)
433 break;
434
435 switch (tup) {
436 case CISTPL_VERS_1:
437 /* assume the strings are good if the version field checks out */
438 if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) {
439 varbuf_append(&b, vstr_manf,
440 &cis[i + 2]);
441 varbuf_append(&b, vstr_productname,
442 &cis[i + 3 +
443 strlen((char *)
444 &cis[i +
445 2])]);
446 break;
447 }
448
449 case CISTPL_MANFID:
450 varbuf_append(&b, vstr_manfid,
451 (cis[i + 1] << 8) + cis[i]);
452 varbuf_append(&b, vstr_prodid,
453 (cis[i + 3] << 8) + cis[i + 2]);
454 break;
455
456 case CISTPL_FUNCID:
457 funcid = cis[i];
458 break;
459
460 case CISTPL_FUNCE:
461 switch (funcid) {
462 case CISTPL_FID_SDIO:
463 #ifdef BCMSDIO
464 if (cis[i] == 0) {
465 u8 spd = cis[i + 3];
466 static int base[] = {
467 -1, 10, 12, 13, 15, 20,
468 25, 30,
469 35, 40, 45, 50, 55, 60,
470 70, 80
471 };
472 static int mult[] = {
473 10, 100, 1000, 10000,
474 -1, -1, -1, -1
475 };
476 ASSERT((mult[spd & 0x7] != -1)
477 &&
478 (base
479 [(spd >> 3) & 0x0f]));
480 varbuf_append(&b,
481 vstr_sdmaxblk[0],
482 (cis[i + 2] << 8)
483 + cis[i + 1]);
484 varbuf_append(&b,
485 vstr_sdmaxspeed,
486 (mult[spd & 0x7] *
487 base[(spd >> 3) &
488 0x0f]));
489 } else if (cis[i] == 1) {
490 varbuf_append(&b,
491 vstr_sdmaxblk
492 [cisnum],
493 (cis[i + 13] << 8)
494 | cis[i + 12]);
495 }
496 #endif /* BCMSDIO */
497 funcid = 0;
498 break;
499 default:
500 /* set macaddr if HNBU_MACADDR not seen yet */
501 if (eabuf[0] == '\0'
502 && cis[i] == LAN_NID
503 && !(ETHER_ISNULLADDR(&cis[i + 2]))
504 && !(ETHER_ISMULTI(&cis[i + 2]))) {
505 ASSERT(cis[i + 1] ==
506 ETHER_ADDR_LEN);
507 snprintf(eabuf, sizeof(eabuf),
508 "%pM", &cis[i + 2]);
509
510 /* set boardnum if HNBU_BOARDNUM not seen yet */
511 if (boardnum == -1)
512 boardnum =
513 (cis[i + 6] << 8) +
514 cis[i + 7];
515 }
516 break;
517 }
518 break;
519
520 case CISTPL_CFTABLE:
521 varbuf_append(&b, vstr_regwindowsz,
522 (cis[i + 7] << 8) | cis[i + 6]);
523 break;
524
525 case CISTPL_BRCM_HNBU:
526 switch (cis[i]) {
527 case HNBU_SROMREV:
528 sromrev = cis[i + 1];
529 varbuf_append(&b, vstr_sromrev,
530 sromrev);
531 break;
532
533 case HNBU_XTALFREQ:
534 varbuf_append(&b, vstr_xtalfreq,
535 (cis[i + 4] << 24) |
536 (cis[i + 3] << 16) |
537 (cis[i + 2] << 8) |
538 cis[i + 1]);
539 break;
540
541 case HNBU_CHIPID:
542 varbuf_append(&b, vstr_vendid,
543 (cis[i + 2] << 8) +
544 cis[i + 1]);
545 varbuf_append(&b, vstr_devid,
546 (cis[i + 4] << 8) +
547 cis[i + 3]);
548 if (tlen >= 7) {
549 varbuf_append(&b, vstr_chiprev,
550 (cis[i + 6] << 8)
551 + cis[i + 5]);
552 }
553 if (tlen >= 9) {
554 varbuf_append(&b,
555 vstr_subvendid,
556 (cis[i + 8] << 8)
557 + cis[i + 7]);
558 }
559 if (tlen >= 11) {
560 varbuf_append(&b, vstr_subdevid,
561 (cis[i + 10] << 8)
562 + cis[i + 9]);
563 /* subdevid doubles for boardtype */
564 varbuf_append(&b,
565 vstr_boardtype,
566 (cis[i + 10] << 8)
567 + cis[i + 9]);
568 }
569 break;
570
571 case HNBU_BOARDNUM:
572 boardnum =
573 (cis[i + 2] << 8) + cis[i + 1];
574 break;
575
576 case HNBU_PATCH:
577 {
578 char vstr_paddr[16];
579 char vstr_pdata[16];
580
581 /* retrieve the patch pairs
582 * from tlen/6; where 6 is
583 * sizeof(patch addr(2)) +
584 * sizeof(patch data(4)).
585 */
586 patch_pair = tlen / 6;
587
588 for (j = 0; j < patch_pair; j++) {
589 snprintf(vstr_paddr,
590 sizeof
591 (vstr_paddr),
592 "pa%d=0x%%x",
593 j);
594 snprintf(vstr_pdata,
595 sizeof
596 (vstr_pdata),
597 "pd%d=0x%%x",
598 j);
599
600 varbuf_append(&b,
601 vstr_paddr,
602 (cis
603 [i +
604 (j *
605 6) +
606 2] << 8)
607 | cis[i +
608 (j *
609 6)
610 +
611 1]);
612
613 varbuf_append(&b,
614 vstr_pdata,
615 (cis
616 [i +
617 (j *
618 6) +
619 6] <<
620 24) |
621 (cis
622 [i +
623 (j *
624 6) +
625 5] <<
626 16) |
627 (cis
628 [i +
629 (j *
630 6) +
631 4] << 8)
632 | cis[i +
633 (j *
634 6)
635 +
636 3]);
637 }
638 }
639 break;
640
641 case HNBU_BOARDREV:
642 if (tlen == 2)
643 varbuf_append(&b, vstr_boardrev,
644 cis[i + 1]);
645 else
646 varbuf_append(&b, vstr_boardrev,
647 (cis[i + 2] << 8)
648 + cis[i + 1]);
649 break;
650
651 case HNBU_BOARDFLAGS:
652 w32 = (cis[i + 2] << 8) + cis[i + 1];
653 if (tlen >= 5)
654 w32 |=
655 ((cis[i + 4] << 24) +
656 (cis[i + 3] << 16));
657 varbuf_append(&b, vstr_boardflags, w32);
658
659 if (tlen >= 7) {
660 w32 =
661 (cis[i + 6] << 8) + cis[i +
662 5];
663 if (tlen >= 9)
664 w32 |=
665 ((cis[i + 8] << 24)
666 +
667 (cis[i + 7] <<
668 16));
669 varbuf_append(&b,
670 vstr_boardflags2,
671 w32);
672 }
673 break;
674
675 case HNBU_USBFS:
676 varbuf_append(&b, vstr_usbfs,
677 cis[i + 1]);
678 break;
679
680 case HNBU_BOARDTYPE:
681 varbuf_append(&b, vstr_boardtype,
682 (cis[i + 2] << 8) +
683 cis[i + 1]);
684 break;
685
686 case HNBU_HNBUCIS:
687 /*
688 * what follows is a nonstandard HNBU CIS
689 * that lacks CISTPL_BRCM_HNBU tags
690 *
691 * skip 0xff (end of standard CIS)
692 * after this tuple
693 */
694 tlen++;
695 standard_cis = false;
696 break;
697
698 case HNBU_USBEPNUM:
699 varbuf_append(&b, vstr_usbepnum,
700 (cis[i + 2] << 8) | cis[i
701 +
702 1]);
703 break;
704
705 case HNBU_AA:
706 varbuf_append(&b, vstr_aa2g,
707 cis[i + 1]);
708 if (tlen >= 3)
709 varbuf_append(&b, vstr_aa5g,
710 cis[i + 2]);
711 break;
712
713 case HNBU_AG:
714 varbuf_append(&b, vstr_ag, 0,
715 cis[i + 1]);
716 if (tlen >= 3)
717 varbuf_append(&b, vstr_ag, 1,
718 cis[i + 2]);
719 if (tlen >= 4)
720 varbuf_append(&b, vstr_ag, 2,
721 cis[i + 3]);
722 if (tlen >= 5)
723 varbuf_append(&b, vstr_ag, 3,
724 cis[i + 4]);
725 ag_init = true;
726 break;
727
728 case HNBU_ANT5G:
729 varbuf_append(&b, vstr_aa5g,
730 cis[i + 1]);
731 varbuf_append(&b, vstr_ag, 1,
732 cis[i + 2]);
733 break;
734
735 case HNBU_CC:
736 ASSERT(sromrev == 1);
737 varbuf_append(&b, vstr_cc, cis[i + 1]);
738 break;
739
740 case HNBU_PAPARMS:
741 switch (tlen) {
742 case 2:
743 ASSERT(sromrev == 1);
744 varbuf_append(&b,
745 vstr_pa0maxpwr,
746 cis[i + 1]);
747 break;
748 case 10:
749 ASSERT(sromrev >= 2);
750 varbuf_append(&b, vstr_opo,
751 cis[i + 9]);
752 /* FALLTHROUGH */
753 case 9:
754 varbuf_append(&b,
755 vstr_pa0maxpwr,
756 cis[i + 8]);
757 /* FALLTHROUGH */
758 BCMDONGLECASE(8)
759 varbuf_append(&b,
760 vstr_pa0itssit,
761 cis[i + 7]);
762 /* FALLTHROUGH */
763 BCMDONGLECASE(7)
764 for (j = 0; j < 3; j++) {
765 varbuf_append(&b,
766 vstr_pa0b
767 [j],
768 (cis
769 [i +
770 (j *
771 2) +
772 2] << 8)
773 + cis[i +
774 (j *
775 2)
776 +
777 1]);
778 }
779 break;
780 default:
781 ASSERT((tlen == 2)
782 || (tlen == 9)
783 || (tlen == 10));
784 break;
785 }
786 break;
787
788 case HNBU_PAPARMS5G:
789 ASSERT((sromrev == 2)
790 || (sromrev == 3));
791 switch (tlen) {
792 case 23:
793 varbuf_append(&b,
794 vstr_pa1himaxpwr,
795 cis[i + 22]);
796 varbuf_append(&b,
797 vstr_pa1lomaxpwr,
798 cis[i + 21]);
799 varbuf_append(&b,
800 vstr_pa1maxpwr,
801 cis[i + 20]);
802 /* FALLTHROUGH */
803 case 20:
804 varbuf_append(&b,
805 vstr_pa1itssit,
806 cis[i + 19]);
807 /* FALLTHROUGH */
808 case 19:
809 for (j = 0; j < 3; j++) {
810 varbuf_append(&b,
811 vstr_pa1b
812 [j],
813 (cis
814 [i +
815 (j *
816 2) +
817 2] << 8)
818 + cis[i +
819 (j *
820 2)
821 +
822 1]);
823 }
824 for (j = 3; j < 6; j++) {
825 varbuf_append(&b,
826 vstr_pa1lob
827 [j - 3],
828 (cis
829 [i +
830 (j *
831 2) +
832 2] << 8)
833 + cis[i +
834 (j *
835 2)
836 +
837 1]);
838 }
839 for (j = 6; j < 9; j++) {
840 varbuf_append(&b,
841 vstr_pa1hib
842 [j - 6],
843 (cis
844 [i +
845 (j *
846 2) +
847 2] << 8)
848 + cis[i +
849 (j *
850 2)
851 +
852 1]);
853 }
854 break;
855 default:
856 ASSERT((tlen == 19) ||
857 (tlen == 20)
858 || (tlen == 23));
859 break;
860 }
861 break;
862
863 case HNBU_OEM:
864 ASSERT(sromrev == 1);
865 varbuf_append(&b, vstr_oem,
866 cis[i + 1], cis[i + 2],
867 cis[i + 3], cis[i + 4],
868 cis[i + 5], cis[i + 6],
869 cis[i + 7], cis[i + 8]);
870 break;
871
872 case HNBU_LEDS:
873 for (j = 1; j <= 4; j++) {
874 if (cis[i + j] != 0xff) {
875 varbuf_append(&b,
876 vstr_ledbh,
877 j - 1,
878 cis[i +
879 j]);
880 }
881 }
882 break;
883
884 case HNBU_CCODE:
885 ASSERT(sromrev > 1);
886 if ((cis[i + 1] == 0)
887 || (cis[i + 2] == 0))
888 varbuf_append(&b, vstr_noccode);
889 else
890 varbuf_append(&b, vstr_ccode,
891 cis[i + 1],
892 cis[i + 2]);
893 varbuf_append(&b, vstr_cctl,
894 cis[i + 3]);
895 break;
896
897 case HNBU_CCKPO:
898 ASSERT(sromrev > 2);
899 varbuf_append(&b, vstr_cckpo,
900 (cis[i + 2] << 8) | cis[i
901 +
902 1]);
903 break;
904
905 case HNBU_OFDMPO:
906 ASSERT(sromrev > 2);
907 varbuf_append(&b, vstr_ofdmpo,
908 (cis[i + 4] << 24) |
909 (cis[i + 3] << 16) |
910 (cis[i + 2] << 8) |
911 cis[i + 1]);
912 break;
913
914 case HNBU_WPS:
915 varbuf_append(&b, vstr_wpsgpio,
916 cis[i + 1]);
917 if (tlen >= 3)
918 varbuf_append(&b, vstr_wpsled,
919 cis[i + 2]);
920 break;
921
922 case HNBU_RSSISMBXA2G:
923 ASSERT(sromrev == 3);
924 varbuf_append(&b, vstr_rssismf2g,
925 cis[i + 1] & 0xf);
926 varbuf_append(&b, vstr_rssismc2g,
927 (cis[i + 1] >> 4) & 0xf);
928 varbuf_append(&b, vstr_rssisav2g,
929 cis[i + 2] & 0x7);
930 varbuf_append(&b, vstr_bxa2g,
931 (cis[i + 2] >> 3) & 0x3);
932 break;
933
934 case HNBU_RSSISMBXA5G:
935 ASSERT(sromrev == 3);
936 varbuf_append(&b, vstr_rssismf5g,
937 cis[i + 1] & 0xf);
938 varbuf_append(&b, vstr_rssismc5g,
939 (cis[i + 1] >> 4) & 0xf);
940 varbuf_append(&b, vstr_rssisav5g,
941 cis[i + 2] & 0x7);
942 varbuf_append(&b, vstr_bxa5g,
943 (cis[i + 2] >> 3) & 0x3);
944 break;
945
946 case HNBU_TRI2G:
947 ASSERT(sromrev == 3);
948 varbuf_append(&b, vstr_tri2g,
949 cis[i + 1]);
950 break;
951
952 case HNBU_TRI5G:
953 ASSERT(sromrev == 3);
954 varbuf_append(&b, vstr_tri5gl,
955 cis[i + 1]);
956 varbuf_append(&b, vstr_tri5g,
957 cis[i + 2]);
958 varbuf_append(&b, vstr_tri5gh,
959 cis[i + 3]);
960 break;
961
962 case HNBU_RXPO2G:
963 ASSERT(sromrev == 3);
964 varbuf_append(&b, vstr_rxpo2g,
965 cis[i + 1]);
966 break;
967
968 case HNBU_RXPO5G:
969 ASSERT(sromrev == 3);
970 varbuf_append(&b, vstr_rxpo5g,
971 cis[i + 1]);
972 break;
973
974 case HNBU_MACADDR:
975 if (!(ETHER_ISNULLADDR(&cis[i + 1])) &&
976 !(ETHER_ISMULTI(&cis[i + 1]))) {
977 snprintf(eabuf, sizeof(eabuf),
978 "%pM", &cis[i + 1]);
979
980 /* set boardnum if HNBU_BOARDNUM not seen yet */
981 if (boardnum == -1)
982 boardnum =
983 (cis[i + 5] << 8) +
984 cis[i + 6];
985 }
986 break;
987
988 case HNBU_LEDDC:
989 /* CIS leddc only has 16bits, convert it to 32bits */
990 w32 = ((cis[i + 2] << 24) | /* oncount */
991 (cis[i + 1] << 8)); /* offcount */
992 varbuf_append(&b, vstr_leddc, w32);
993 break;
994
995 case HNBU_CHAINSWITCH:
996 varbuf_append(&b, vstr_txchain,
997 cis[i + 1]);
998 varbuf_append(&b, vstr_rxchain,
999 cis[i + 2]);
1000 varbuf_append(&b, vstr_antswitch,
1001 (cis[i + 4] << 8) +
1002 cis[i + 3]);
1003 break;
1004
1005 case HNBU_REGREV:
1006 varbuf_append(&b, vstr_regrev,
1007 cis[i + 1]);
1008 break;
1009
1010 case HNBU_FEM:{
1011 u16 fem =
1012 (cis[i + 2] << 8) + cis[i +
1013 1];
1014 varbuf_append(&b,
1015 vstr_antswctl2g,
1016 (fem &
1017 SROM8_FEM_ANTSWLUT_MASK)
1018 >>
1019 SROM8_FEM_ANTSWLUT_SHIFT);
1020 varbuf_append(&b, vstr_triso2g,
1021 (fem &
1022 SROM8_FEM_TR_ISO_MASK)
1023 >>
1024 SROM8_FEM_TR_ISO_SHIFT);
1025 varbuf_append(&b,
1026 vstr_pdetrange2g,
1027 (fem &
1028 SROM8_FEM_PDET_RANGE_MASK)
1029 >>
1030 SROM8_FEM_PDET_RANGE_SHIFT);
1031 varbuf_append(&b,
1032 vstr_extpagain2g,
1033 (fem &
1034 SROM8_FEM_EXTPA_GAIN_MASK)
1035 >>
1036 SROM8_FEM_EXTPA_GAIN_SHIFT);
1037 varbuf_append(&b,
1038 vstr_tssipos2g,
1039 (fem &
1040 SROM8_FEM_TSSIPOS_MASK)
1041 >>
1042 SROM8_FEM_TSSIPOS_SHIFT);
1043 if (tlen < 5)
1044 break;
1045
1046 fem =
1047 (cis[i + 4] << 8) + cis[i +
1048 3];
1049 varbuf_append(&b,
1050 vstr_antswctl5g,
1051 (fem &
1052 SROM8_FEM_ANTSWLUT_MASK)
1053 >>
1054 SROM8_FEM_ANTSWLUT_SHIFT);
1055 varbuf_append(&b, vstr_triso5g,
1056 (fem &
1057 SROM8_FEM_TR_ISO_MASK)
1058 >>
1059 SROM8_FEM_TR_ISO_SHIFT);
1060 varbuf_append(&b,
1061 vstr_pdetrange5g,
1062 (fem &
1063 SROM8_FEM_PDET_RANGE_MASK)
1064 >>
1065 SROM8_FEM_PDET_RANGE_SHIFT);
1066 varbuf_append(&b,
1067 vstr_extpagain5g,
1068 (fem &
1069 SROM8_FEM_EXTPA_GAIN_MASK)
1070 >>
1071 SROM8_FEM_EXTPA_GAIN_SHIFT);
1072 varbuf_append(&b,
1073 vstr_tssipos5g,
1074 (fem &
1075 SROM8_FEM_TSSIPOS_MASK)
1076 >>
1077 SROM8_FEM_TSSIPOS_SHIFT);
1078 break;
1079 }
1080
1081 case HNBU_PAPARMS_C0:
1082 varbuf_append(&b, vstr_maxp2ga0,
1083 cis[i + 1]);
1084 varbuf_append(&b, vstr_itt2ga0,
1085 cis[i + 2]);
1086 varbuf_append(&b, vstr_pa, 2, 0, 0,
1087 (cis[i + 4] << 8) +
1088 cis[i + 3]);
1089 varbuf_append(&b, vstr_pa, 2, 1, 0,
1090 (cis[i + 6] << 8) +
1091 cis[i + 5]);
1092 varbuf_append(&b, vstr_pa, 2, 2, 0,
1093 (cis[i + 8] << 8) +
1094 cis[i + 7]);
1095 if (tlen < 31)
1096 break;
1097
1098 varbuf_append(&b, vstr_maxp5ga0,
1099 cis[i + 9]);
1100 varbuf_append(&b, vstr_itt5ga0,
1101 cis[i + 10]);
1102 varbuf_append(&b, vstr_maxp5gha0,
1103 cis[i + 11]);
1104 varbuf_append(&b, vstr_maxp5gla0,
1105 cis[i + 12]);
1106 varbuf_append(&b, vstr_pa, 5, 0, 0,
1107 (cis[i + 14] << 8) +
1108 cis[i + 13]);
1109 varbuf_append(&b, vstr_pa, 5, 1, 0,
1110 (cis[i + 16] << 8) +
1111 cis[i + 15]);
1112 varbuf_append(&b, vstr_pa, 5, 2, 0,
1113 (cis[i + 18] << 8) +
1114 cis[i + 17]);
1115 varbuf_append(&b, vstr_pahl, 5, 'l', 0,
1116 0,
1117 (cis[i + 20] << 8) +
1118 cis[i + 19]);
1119 varbuf_append(&b, vstr_pahl, 5, 'l', 1,
1120 0,
1121 (cis[i + 22] << 8) +
1122 cis[i + 21]);
1123 varbuf_append(&b, vstr_pahl, 5, 'l', 2,
1124 0,
1125 (cis[i + 24] << 8) +
1126 cis[i + 23]);
1127 varbuf_append(&b, vstr_pahl, 5, 'h', 0,
1128 0,
1129 (cis[i + 26] << 8) +
1130 cis[i + 25]);
1131 varbuf_append(&b, vstr_pahl, 5, 'h', 1,
1132 0,
1133 (cis[i + 28] << 8) +
1134 cis[i + 27]);
1135 varbuf_append(&b, vstr_pahl, 5, 'h', 2,
1136 0,
1137 (cis[i + 30] << 8) +
1138 cis[i + 29]);
1139 break;
1140
1141 case HNBU_PAPARMS_C1:
1142 varbuf_append(&b, vstr_maxp2ga1,
1143 cis[i + 1]);
1144 varbuf_append(&b, vstr_itt2ga1,
1145 cis[i + 2]);
1146 varbuf_append(&b, vstr_pa, 2, 0, 1,
1147 (cis[i + 4] << 8) +
1148 cis[i + 3]);
1149 varbuf_append(&b, vstr_pa, 2, 1, 1,
1150 (cis[i + 6] << 8) +
1151 cis[i + 5]);
1152 varbuf_append(&b, vstr_pa, 2, 2, 1,
1153 (cis[i + 8] << 8) +
1154 cis[i + 7]);
1155 if (tlen < 31)
1156 break;
1157
1158 varbuf_append(&b, vstr_maxp5ga1,
1159 cis[i + 9]);
1160 varbuf_append(&b, vstr_itt5ga1,
1161 cis[i + 10]);
1162 varbuf_append(&b, vstr_maxp5gha1,
1163 cis[i + 11]);
1164 varbuf_append(&b, vstr_maxp5gla1,
1165 cis[i + 12]);
1166 varbuf_append(&b, vstr_pa, 5, 0, 1,
1167 (cis[i + 14] << 8) +
1168 cis[i + 13]);
1169 varbuf_append(&b, vstr_pa, 5, 1, 1,
1170 (cis[i + 16] << 8) +
1171 cis[i + 15]);
1172 varbuf_append(&b, vstr_pa, 5, 2, 1,
1173 (cis[i + 18] << 8) +
1174 cis[i + 17]);
1175 varbuf_append(&b, vstr_pahl, 5, 'l', 0,
1176 1,
1177 (cis[i + 20] << 8) +
1178 cis[i + 19]);
1179 varbuf_append(&b, vstr_pahl, 5, 'l', 1,
1180 1,
1181 (cis[i + 22] << 8) +
1182 cis[i + 21]);
1183 varbuf_append(&b, vstr_pahl, 5, 'l', 2,
1184 1,
1185 (cis[i + 24] << 8) +
1186 cis[i + 23]);
1187 varbuf_append(&b, vstr_pahl, 5, 'h', 0,
1188 1,
1189 (cis[i + 26] << 8) +
1190 cis[i + 25]);
1191 varbuf_append(&b, vstr_pahl, 5, 'h', 1,
1192 1,
1193 (cis[i + 28] << 8) +
1194 cis[i + 27]);
1195 varbuf_append(&b, vstr_pahl, 5, 'h', 2,
1196 1,
1197 (cis[i + 30] << 8) +
1198 cis[i + 29]);
1199 break;
1200
1201 case HNBU_PO_CCKOFDM:
1202 varbuf_append(&b, vstr_cck2gpo,
1203 (cis[i + 2] << 8) +
1204 cis[i + 1]);
1205 varbuf_append(&b, vstr_ofdm2gpo,
1206 (cis[i + 6] << 24) +
1207 (cis[i + 5] << 16) +
1208 (cis[i + 4] << 8) +
1209 cis[i + 3]);
1210 if (tlen < 19)
1211 break;
1212
1213 varbuf_append(&b, vstr_ofdm5gpo,
1214 (cis[i + 10] << 24) +
1215 (cis[i + 9] << 16) +
1216 (cis[i + 8] << 8) +
1217 cis[i + 7]);
1218 varbuf_append(&b, vstr_ofdm5glpo,
1219 (cis[i + 14] << 24) +
1220 (cis[i + 13] << 16) +
1221 (cis[i + 12] << 8) +
1222 cis[i + 11]);
1223 varbuf_append(&b, vstr_ofdm5ghpo,
1224 (cis[i + 18] << 24) +
1225 (cis[i + 17] << 16) +
1226 (cis[i + 16] << 8) +
1227 cis[i + 15]);
1228 break;
1229
1230 case HNBU_PO_MCS2G:
1231 for (j = 0; j <= (tlen / 2); j++) {
1232 varbuf_append(&b, vstr_mcspo, 2,
1233 j,
1234 (cis
1235 [i + 2 +
1236 2 * j] << 8) +
1237 cis[i + 1 +
1238 2 * j]);
1239 }
1240 break;
1241
1242 case HNBU_PO_MCS5GM:
1243 for (j = 0; j <= (tlen / 2); j++) {
1244 varbuf_append(&b, vstr_mcspo, 5,
1245 j,
1246 (cis
1247 [i + 2 +
1248 2 * j] << 8) +
1249 cis[i + 1 +
1250 2 * j]);
1251 }
1252 break;
1253
1254 case HNBU_PO_MCS5GLH:
1255 for (j = 0; j <= (tlen / 4); j++) {
1256 varbuf_append(&b, vstr_mcspohl,
1257 5, 'l', j,
1258 (cis
1259 [i + 2 +
1260 2 * j] << 8) +
1261 cis[i + 1 +
1262 2 * j]);
1263 }
1264
1265 for (j = 0; j <= (tlen / 4); j++) {
1266 varbuf_append(&b, vstr_mcspohl,
1267 5, 'h', j,
1268 (cis
1269 [i +
1270 ((tlen / 2) +
1271 2) +
1272 2 * j] << 8) +
1273 cis[i +
1274 ((tlen / 2) +
1275 1) + 2 * j]);
1276 }
1277
1278 break;
1279
1280 case HNBU_PO_CDD:
1281 varbuf_append(&b, vstr_cddpo,
1282 (cis[i + 2] << 8) +
1283 cis[i + 1]);
1284 break;
1285
1286 case HNBU_PO_STBC:
1287 varbuf_append(&b, vstr_stbcpo,
1288 (cis[i + 2] << 8) +
1289 cis[i + 1]);
1290 break;
1291
1292 case HNBU_PO_40M:
1293 varbuf_append(&b, vstr_bw40po,
1294 (cis[i + 2] << 8) +
1295 cis[i + 1]);
1296 break;
1297
1298 case HNBU_PO_40MDUP:
1299 varbuf_append(&b, vstr_bwduppo,
1300 (cis[i + 2] << 8) +
1301 cis[i + 1]);
1302 break;
1303
1304 case HNBU_OFDMPO5G:
1305 varbuf_append(&b, vstr_ofdm5gpo,
1306 (cis[i + 4] << 24) +
1307 (cis[i + 3] << 16) +
1308 (cis[i + 2] << 8) +
1309 cis[i + 1]);
1310 varbuf_append(&b, vstr_ofdm5glpo,
1311 (cis[i + 8] << 24) +
1312 (cis[i + 7] << 16) +
1313 (cis[i + 6] << 8) +
1314 cis[i + 5]);
1315 varbuf_append(&b, vstr_ofdm5ghpo,
1316 (cis[i + 12] << 24) +
1317 (cis[i + 11] << 16) +
1318 (cis[i + 10] << 8) +
1319 cis[i + 9]);
1320 break;
1321
1322 case HNBU_CUSTOM1:
1323 varbuf_append(&b, vstr_custom, 1,
1324 ((cis[i + 4] << 24) +
1325 (cis[i + 3] << 16) +
1326 (cis[i + 2] << 8) +
1327 cis[i + 1]));
1328 break;
1329
1330 #if defined(BCMSDIO)
1331 case HNBU_SROM3SWRGN:
1332 if (tlen >= 73) {
1333 u16 srom[35];
1334 u8 srev = cis[i + 1 + 70];
1335 ASSERT(srev == 3);
1336 /* make tuple value 16-bit aligned and parse it */
1337 bcopy(&cis[i + 1], srom,
1338 sizeof(srom));
1339 _initvars_srom_pci(srev, srom,
1340 SROM3_SWRGN_OFF,
1341 &b);
1342 /* 2.4G antenna gain is included in SROM */
1343 ag_init = true;
1344 /* Ethernet MAC address is included in SROM */
1345 eabuf[0] = 0;
1346 boardnum = -1;
1347 }
1348 /* create extra variables */
1349 if (tlen >= 75)
1350 varbuf_append(&b, vstr_vendid,
1351 (cis[i + 1 + 73]
1352 << 8) + cis[i +
1353 1 +
1354 72]);
1355 if (tlen >= 77)
1356 varbuf_append(&b, vstr_devid,
1357 (cis[i + 1 + 75]
1358 << 8) + cis[i +
1359 1 +
1360 74]);
1361 if (tlen >= 79)
1362 varbuf_append(&b, vstr_xtalfreq,
1363 (cis[i + 1 + 77]
1364 << 8) + cis[i +
1365 1 +
1366 76]);
1367 break;
1368 #endif /* defined(BCMSDIO) */
1369
1370 case HNBU_CCKFILTTYPE:
1371 varbuf_append(&b, vstr_cckdigfilttype,
1372 (cis[i + 1]));
1373 break;
1374 }
1375
1376 break;
1377 }
1378 i += tlen;
1379 } while (tup != CISTPL_END);
1380 }
1381
1382 if (boardnum != -1) {
1383 varbuf_append(&b, vstr_boardnum, boardnum);
1384 }
1385
1386 if (eabuf[0]) {
1387 varbuf_append(&b, vstr_macaddr, eabuf);
1388 }
1389
1390 /* if there is no antenna gain field, set default */
1391 if (getvar(NULL, "ag0") == NULL && ag_init == false) {
1392 varbuf_append(&b, vstr_ag, 0, 0xff);
1393 }
1394
1395 /* final nullbyte terminator */
1396 ASSERT(b.size >= 1);
1397 *b.buf++ = '\0';
1398
1399 ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS);
1400 err = initvars_table(osh, base, b.buf, vars, count);
1401
1402 kfree(base);
1403 return err;
1404 }
1405
1406 /* In chips with chipcommon rev 32 and later, the srom is in chipcommon,
1407 * not in the bus cores.
1408 */
1409 static u16
1410 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, u32 cmd, uint wordoff,
1411 u16 data)
1412 {
1413 chipcregs_t *cc = (chipcregs_t *) ccregs;
1414 uint wait_cnt = 1000;
1415
1416 if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
1417 W_REG(osh, &cc->sromaddress, wordoff * 2);
1418 if (cmd == SRC_OP_WRITE)
1419 W_REG(osh, &cc->sromdata, data);
1420 }
1421
1422 W_REG(osh, &cc->sromcontrol, SRC_START | cmd);
1423
1424 while (wait_cnt--) {
1425 if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0)
1426 break;
1427 }
1428
1429 if (!wait_cnt) {
1430 BS_ERROR(("%s: Command 0x%x timed out\n", __func__, cmd));
1431 return 0xffff;
1432 }
1433 if (cmd == SRC_OP_READ)
1434 return (u16) R_REG(osh, &cc->sromdata);
1435 else
1436 return 0xffff;
1437 }
1438
1439 /*
1440 * Read in and validate sprom.
1441 * Return 0 on success, nonzero on error.
1442 */
1443 static int
1444 sprom_read_pci(osl_t *osh, si_t *sih, u16 *sprom, uint wordoff,
1445 u16 *buf, uint nwords, bool check_crc)
1446 {
1447 int err = 0;
1448 uint i;
1449 void *ccregs = NULL;
1450
1451 /* read the sprom */
1452 for (i = 0; i < nwords; i++) {
1453
1454 if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
1455 /* use indirect since direct is too slow on QT */
1456 if ((sih->cccaps & CC_CAP_SROM) == 0)
1457 return 1;
1458
1459 ccregs = (void *)((u8 *) sprom - CC_SROM_OTP);
1460 buf[i] =
1461 srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ,
1462 wordoff + i, 0);
1463
1464 } else {
1465 if (ISSIM_ENAB(sih))
1466 buf[i] = R_REG(osh, &sprom[wordoff + i]);
1467
1468 buf[i] = R_REG(osh, &sprom[wordoff + i]);
1469 }
1470
1471 }
1472
1473 /* bypass crc checking for simulation to allow srom hack */
1474 if (ISSIM_ENAB(sih))
1475 return err;
1476
1477 if (check_crc) {
1478
1479 if (buf[0] == 0xffff) {
1480 /* The hardware thinks that an srom that starts with 0xffff
1481 * is blank, regardless of the rest of the content, so declare
1482 * it bad.
1483 */
1484 BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n",
1485 __func__, buf[0]));
1486 return 1;
1487 }
1488
1489 /* fixup the endianness so crc8 will pass */
1490 htol16_buf(buf, nwords * 2);
1491 if (hndcrc8((u8 *) buf, nwords * 2, CRC8_INIT_VALUE) !=
1492 CRC8_GOOD_VALUE) {
1493 /* DBG only pci always read srom4 first, then srom8/9 */
1494 /* BS_ERROR(("%s: bad crc\n", __func__)); */
1495 err = 1;
1496 }
1497 /* now correct the endianness of the byte array */
1498 ltoh16_buf(buf, nwords * 2);
1499 }
1500 return err;
1501 }
1502
1503 #if defined(BCMNVRAMR)
1504 static int otp_read_pci(osl_t *osh, si_t *sih, u16 *buf, uint bufsz)
1505 {
1506 u8 *otp;
1507 uint sz = OTP_SZ_MAX / 2; /* size in words */
1508 int err = 0;
1509
1510 ASSERT(bufsz <= OTP_SZ_MAX);
1511
1512 otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
1513 if (otp == NULL) {
1514 return BCME_ERROR;
1515 }
1516
1517 err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
1518
1519 bcopy(otp, buf, bufsz);
1520
1521 if (otp)
1522 kfree(otp);
1523
1524 /* Check CRC */
1525 if (buf[0] == 0xffff) {
1526 /* The hardware thinks that an srom that starts with 0xffff
1527 * is blank, regardless of the rest of the content, so declare
1528 * it bad.
1529 */
1530 BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __func__,
1531 buf[0]));
1532 return 1;
1533 }
1534
1535 /* fixup the endianness so crc8 will pass */
1536 htol16_buf(buf, bufsz);
1537 if (hndcrc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
1538 CRC8_GOOD_VALUE) {
1539 BS_ERROR(("%s: bad crc\n", __func__));
1540 err = 1;
1541 }
1542 /* now correct the endianness of the byte array */
1543 ltoh16_buf(buf, bufsz);
1544
1545 return err;
1546 }
1547 #endif /* defined(BCMNVRAMR) */
1548 /*
1549 * Create variable table from memory.
1550 * Return 0 on success, nonzero on error.
1551 */
1552 static int initvars_table(osl_t *osh, char *start, char *end, char **vars,
1553 uint *count)
1554 {
1555 int c = (int)(end - start);
1556
1557 /* do it only when there is more than just the null string */
1558 if (c > 1) {
1559 char *vp = kmalloc(c, GFP_ATOMIC);
1560 ASSERT(vp != NULL);
1561 if (!vp)
1562 return BCME_NOMEM;
1563 bcopy(start, vp, c);
1564 *vars = vp;
1565 *count = c;
1566 } else {
1567 *vars = NULL;
1568 *count = 0;
1569 }
1570
1571 return 0;
1572 }
1573
1574 /*
1575 * Find variables with <devpath> from flash. 'base' points to the beginning
1576 * of the table upon enter and to the end of the table upon exit when success.
1577 * Return 0 on success, nonzero on error.
1578 */
1579 static int initvars_flash(si_t *sih, osl_t *osh, char **base, uint len)
1580 {
1581 char *vp = *base;
1582 char *flash;
1583 int err;
1584 char *s;
1585 uint l, dl, copy_len;
1586 char devpath[SI_DEVPATH_BUFSZ];
1587
1588 /* allocate memory and read in flash */
1589 flash = kmalloc(NVRAM_SPACE, GFP_ATOMIC);
1590 if (!flash)
1591 return BCME_NOMEM;
1592 err = nvram_getall(flash, NVRAM_SPACE);
1593 if (err)
1594 goto exit;
1595
1596 si_devpath(sih, devpath, sizeof(devpath));
1597
1598 /* grab vars with the <devpath> prefix in name */
1599 dl = strlen(devpath);
1600 for (s = flash; s && *s; s += l + 1) {
1601 l = strlen(s);
1602
1603 /* skip non-matching variable */
1604 if (strncmp(s, devpath, dl))
1605 continue;
1606
1607 /* is there enough room to copy? */
1608 copy_len = l - dl + 1;
1609 if (len < copy_len) {
1610 err = BCME_BUFTOOSHORT;
1611 goto exit;
1612 }
1613
1614 /* no prefix, just the name=value */
1615 strncpy(vp, &s[dl], copy_len);
1616 vp += copy_len;
1617 len -= copy_len;
1618 }
1619
1620 /* add null string as terminator */
1621 if (len < 1) {
1622 err = BCME_BUFTOOSHORT;
1623 goto exit;
1624 }
1625 *vp++ = '\0';
1626
1627 *base = vp;
1628
1629 exit: kfree(flash);
1630 return err;
1631 }
1632
1633 /*
1634 * Initialize nonvolatile variable table from flash.
1635 * Return 0 on success, nonzero on error.
1636 */
1637 static int initvars_flash_si(si_t *sih, char **vars, uint *count)
1638 {
1639 osl_t *osh = si_osh(sih);
1640 char *vp, *base;
1641 int err;
1642
1643 ASSERT(vars != NULL);
1644 ASSERT(count != NULL);
1645
1646 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
1647 ASSERT(vp != NULL);
1648 if (!vp)
1649 return BCME_NOMEM;
1650
1651 err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS);
1652 if (err == 0)
1653 err = initvars_table(osh, base, vp, vars, count);
1654
1655 kfree(base);
1656
1657 return err;
1658 }
1659
1660 /* Parse SROM and create name=value pairs. 'srom' points to
1661 * the SROM word array. 'off' specifies the offset of the
1662 * first word 'srom' points to, which should be either 0 or
1663 * SROM3_SWRG_OFF (full SROM or software region).
1664 */
1665
1666 static uint mask_shift(u16 mask)
1667 {
1668 uint i;
1669 for (i = 0; i < (sizeof(mask) << 3); i++) {
1670 if (mask & (1 << i))
1671 return i;
1672 }
1673 ASSERT(mask);
1674 return 0;
1675 }
1676
1677 static uint mask_width(u16 mask)
1678 {
1679 int i;
1680 for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
1681 if (mask & (1 << i))
1682 return (uint) (i - mask_shift(mask) + 1);
1683 }
1684 ASSERT(mask);
1685 return 0;
1686 }
1687
1688 #if defined(BCMDBG)
1689 static bool mask_valid(u16 mask)
1690 {
1691 uint shift = mask_shift(mask);
1692 uint width = mask_width(mask);
1693 return mask == ((~0 << shift) & ~(~0 << (shift + width)));
1694 }
1695 #endif /* BCMDBG */
1696
1697 static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b)
1698 {
1699 u16 w;
1700 u32 val;
1701 const sromvar_t *srv;
1702 uint width;
1703 uint flags;
1704 u32 sr = (1 << sromrev);
1705
1706 varbuf_append(b, "sromrev=%d", sromrev);
1707
1708 for (srv = pci_sromvars; srv->name != NULL; srv++) {
1709 const char *name;
1710
1711 if ((srv->revmask & sr) == 0)
1712 continue;
1713
1714 if (srv->off < off)
1715 continue;
1716
1717 flags = srv->flags;
1718 name = srv->name;
1719
1720 /* This entry is for mfgc only. Don't generate param for it, */
1721 if (flags & SRFL_NOVAR)
1722 continue;
1723
1724 if (flags & SRFL_ETHADDR) {
1725 struct ether_addr ea;
1726
1727 ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff;
1728 ea.octet[1] = srom[srv->off - off] & 0xff;
1729 ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
1730 ea.octet[3] = srom[srv->off + 1 - off] & 0xff;
1731 ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
1732 ea.octet[5] = srom[srv->off + 2 - off] & 0xff;
1733
1734 varbuf_append(b, "%s=%pM", name, ea.octet);
1735 } else {
1736 ASSERT(mask_valid(srv->mask));
1737 ASSERT(mask_width(srv->mask));
1738
1739 w = srom[srv->off - off];
1740 val = (w & srv->mask) >> mask_shift(srv->mask);
1741 width = mask_width(srv->mask);
1742
1743 while (srv->flags & SRFL_MORE) {
1744 srv++;
1745 ASSERT(srv->name != NULL);
1746
1747 if (srv->off == 0 || srv->off < off)
1748 continue;
1749
1750 ASSERT(mask_valid(srv->mask));
1751 ASSERT(mask_width(srv->mask));
1752
1753 w = srom[srv->off - off];
1754 val +=
1755 ((w & srv->mask) >> mask_shift(srv->
1756 mask)) <<
1757 width;
1758 width += mask_width(srv->mask);
1759 }
1760
1761 if ((flags & SRFL_NOFFS)
1762 && ((int)val == (1 << width) - 1))
1763 continue;
1764
1765 if (flags & SRFL_CCODE) {
1766 if (val == 0)
1767 varbuf_append(b, "ccode=");
1768 else
1769 varbuf_append(b, "ccode=%c%c",
1770 (val >> 8), (val & 0xff));
1771 }
1772 /* LED Powersave duty cycle has to be scaled:
1773 *(oncount >> 24) (offcount >> 8)
1774 */
1775 else if (flags & SRFL_LEDDC) {
1776 u32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
1777 (((val & 0xff)) << 8); /* offcount */
1778 varbuf_append(b, "leddc=%d", w32);
1779 } else if (flags & SRFL_PRHEX)
1780 varbuf_append(b, "%s=0x%x", name, val);
1781 else if ((flags & SRFL_PRSIGN)
1782 && (val & (1 << (width - 1))))
1783 varbuf_append(b, "%s=%d", name,
1784 (int)(val | (~0 << width)));
1785 else
1786 varbuf_append(b, "%s=%u", name, val);
1787 }
1788 }
1789
1790 if (sromrev >= 4) {
1791 /* Do per-path variables */
1792 uint p, pb, psz;
1793
1794 if (sromrev >= 8) {
1795 pb = SROM8_PATH0;
1796 psz = SROM8_PATH1 - SROM8_PATH0;
1797 } else {
1798 pb = SROM4_PATH0;
1799 psz = SROM4_PATH1 - SROM4_PATH0;
1800 }
1801
1802 for (p = 0; p < MAX_PATH_SROM; p++) {
1803 for (srv = perpath_pci_sromvars; srv->name != NULL;
1804 srv++) {
1805 if ((srv->revmask & sr) == 0)
1806 continue;
1807
1808 if (pb + srv->off < off)
1809 continue;
1810
1811 /* This entry is for mfgc only. Don't generate param for it, */
1812 if (srv->flags & SRFL_NOVAR)
1813 continue;
1814
1815 w = srom[pb + srv->off - off];
1816
1817 ASSERT(mask_valid(srv->mask));
1818 val = (w & srv->mask) >> mask_shift(srv->mask);
1819 width = mask_width(srv->mask);
1820
1821 /* Cheating: no per-path var is more than 1 word */
1822
1823 if ((srv->flags & SRFL_NOFFS)
1824 && ((int)val == (1 << width) - 1))
1825 continue;
1826
1827 if (srv->flags & SRFL_PRHEX)
1828 varbuf_append(b, "%s%d=0x%x", srv->name,
1829 p, val);
1830 else
1831 varbuf_append(b, "%s%d=%d", srv->name,
1832 p, val);
1833 }
1834 pb += psz;
1835 }
1836 }
1837 }
1838
1839 /*
1840 * Initialize nonvolatile variable table from sprom.
1841 * Return 0 on success, nonzero on error.
1842 */
1843 static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
1844 {
1845 u16 *srom, *sromwindow;
1846 u8 sromrev = 0;
1847 u32 sr;
1848 varbuf_t b;
1849 char *vp, *base = NULL;
1850 osl_t *osh = si_osh(sih);
1851 bool flash = false;
1852 int err = 0;
1853
1854 /*
1855 * Apply CRC over SROM content regardless SROM is present or not,
1856 * and use variable <devpath>sromrev's existance in flash to decide
1857 * if we should return an error when CRC fails or read SROM variables
1858 * from flash.
1859 */
1860 srom = kmalloc(SROM_MAX, GFP_ATOMIC);
1861 ASSERT(srom != NULL);
1862 if (!srom)
1863 return -2;
1864
1865 sromwindow = (u16 *) SROM_OFFSET(sih);
1866 if (si_is_sprom_available(sih)) {
1867 err =
1868 sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM_WORDS,
1869 true);
1870
1871 if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
1872 (((sih->buscoretype == PCIE_CORE_ID)
1873 && (sih->buscorerev >= 6))
1874 || ((sih->buscoretype == PCI_CORE_ID)
1875 && (sih->buscorerev >= 0xe)))) {
1876 /* sromrev >= 4, read more */
1877 err =
1878 sprom_read_pci(osh, sih, sromwindow, 0, srom,
1879 SROM4_WORDS, true);
1880 sromrev = srom[SROM4_CRCREV] & 0xff;
1881 if (err)
1882 BS_ERROR(("%s: srom %d, bad crc\n", __func__,
1883 sromrev));
1884
1885 } else if (err == 0) {
1886 /* srom is good and is rev < 4 */
1887 /* top word of sprom contains version and crc8 */
1888 sromrev = srom[SROM_CRCREV] & 0xff;
1889 /* bcm4401 sroms misprogrammed */
1890 if (sromrev == 0x10)
1891 sromrev = 1;
1892 }
1893 }
1894 #if defined(BCMNVRAMR)
1895 /* Use OTP if SPROM not available */
1896 else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) {
1897 /* OTP only contain SROM rev8/rev9 for now */
1898 sromrev = srom[SROM4_CRCREV] & 0xff;
1899 }
1900 #endif
1901 else {
1902 err = 1;
1903 BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
1904 }
1905
1906 /* We want internal/wltest driver to come up with default sromvars so we can
1907 * program a blank SPROM/OTP.
1908 */
1909 if (err) {
1910 char *value;
1911 u32 val;
1912 val = 0;
1913
1914 value = si_getdevpathvar(sih, "sromrev");
1915 if (value) {
1916 sromrev = (u8) simple_strtoul(value, NULL, 0);
1917 flash = true;
1918 goto varscont;
1919 }
1920
1921 BS_ERROR(("%s, SROM CRC Error\n", __func__));
1922
1923 value = si_getnvramflvar(sih, "sromrev");
1924 if (value) {
1925 err = 0;
1926 goto errout;
1927 }
1928
1929 {
1930 err = -1;
1931 goto errout;
1932 }
1933 }
1934
1935 varscont:
1936 /* Bitmask for the sromrev */
1937 sr = 1 << sromrev;
1938
1939 /* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */
1940 if ((sr & 0x33e) == 0) {
1941 err = -2;
1942 goto errout;
1943 }
1944
1945 ASSERT(vars != NULL);
1946 ASSERT(count != NULL);
1947
1948 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
1949 ASSERT(vp != NULL);
1950 if (!vp) {
1951 err = -2;
1952 goto errout;
1953 }
1954
1955 /* read variables from flash */
1956 if (flash) {
1957 err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS);
1958 if (err)
1959 goto errout;
1960 goto varsdone;
1961 }
1962
1963 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
1964
1965 /* parse SROM into name=value pairs. */
1966 _initvars_srom_pci(sromrev, srom, 0, &b);
1967
1968 /* final nullbyte terminator */
1969 ASSERT(b.size >= 1);
1970 vp = b.buf;
1971 *vp++ = '\0';
1972
1973 ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
1974
1975 varsdone:
1976 err = initvars_table(osh, base, vp, vars, count);
1977
1978 errout:
1979 if (base)
1980 kfree(base);
1981
1982 kfree(srom);
1983 return err;
1984 }
1985
1986 #ifdef BCMSDIO
1987 /*
1988 * Read the SDIO cis and call parsecis to initialize the vars.
1989 * Return 0 on success, nonzero on error.
1990 */
1991 static int initvars_cis_sdio(osl_t *osh, char **vars, uint *count)
1992 {
1993 u8 *cis[SBSDIO_NUM_FUNCTION + 1];
1994 uint fn, numfn;
1995 int rc = 0;
1996
1997 numfn = bcmsdh_query_iofnum(NULL);
1998 ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
1999
2000 for (fn = 0; fn <= numfn; fn++) {
2001 cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
2002 if (cis[fn] == NULL) {
2003 rc = -1;
2004 break;
2005 }
2006
2007 if (bcmsdh_cis_read(NULL, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT) !=
2008 0) {
2009 kfree(cis[fn]);
2010 rc = -2;
2011 break;
2012 }
2013 }
2014
2015 if (!rc)
2016 rc = srom_parsecis(osh, cis, fn, vars, count);
2017
2018 while (fn-- > 0)
2019 kfree(cis[fn]);
2020
2021 return rc;
2022 }
2023
2024 /* set SDIO sprom command register */
2025 static int sprom_cmd_sdio(osl_t *osh, u8 cmd)
2026 {
2027 u8 status = 0;
2028 uint wait_cnt = 1000;
2029
2030 /* write sprom command register */
2031 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, cmd, NULL);
2032
2033 /* wait status */
2034 while (wait_cnt--) {
2035 status =
2036 bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, NULL);
2037 if (status & SBSDIO_SPROM_DONE)
2038 return 0;
2039 }
2040
2041 return 1;
2042 }
2043
2044 /* read a word from the SDIO srom */
2045 static int sprom_read_sdio(osl_t *osh, u16 addr, u16 *data)
2046 {
2047 u8 addr_l, addr_h, data_l, data_h;
2048
2049 addr_l = (u8) ((addr * 2) & 0xff);
2050 addr_h = (u8) (((addr * 2) >> 8) & 0xff);
2051
2052 /* set address */
2053 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h,
2054 NULL);
2055 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l,
2056 NULL);
2057
2058 /* do read */
2059 if (sprom_cmd_sdio(osh, SBSDIO_SPROM_READ))
2060 return 1;
2061
2062 /* read data */
2063 data_h =
2064 bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, NULL);
2065 data_l =
2066 bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, NULL);
2067
2068 *data = (data_h << 8) | data_l;
2069 return 0;
2070 }
2071 #endif /* BCMSDIO */
2072
2073 static int initvars_srom_si(si_t *sih, osl_t *osh, void *curmap, char **vars,
2074 uint *varsz)
2075 {
2076 /* Search flash nvram section for srom variables */
2077 return initvars_flash_si(sih, vars, varsz);
2078 }