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