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