Fix common misspellings
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / brcm80211 / util / bcmsrom.c
CommitLineData
a9533e7e
HP
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 */
48c51a8c 16#include <linux/kernel.h>
3327989a 17#include <linux/string.h>
3ca5ada5 18#include <linux/etherdevice.h>
a1c16ed2 19#include <bcmdefs.h>
c6ac24e9
BR
20#include <linux/module.h>
21#include <linux/pci.h>
a9533e7e
HP
22#include <stdarg.h>
23#include <bcmutils.h>
24#include <hndsoc.h>
25#include <sbchipc.h>
26#include <bcmdevs.h>
a9533e7e
HP
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
e2582ad8 45#include <linux/if_ether.h>
a9533e7e
HP
46
47#define BS_ERROR(args)
48
49#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
50 (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
36ef9a1e
GKH
51 ((u8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
52 ((u8 *)curmap + PCI_BAR0_SPROM_OFFSET))
a9533e7e
HP
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
59typedef 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;
64extern char *_vars;
65extern uint _varsz;
66
67#define SROM_CIS_SINGLE 1
68
26bcc181
AS
69static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *count);
70static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b);
71static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count);
7cc4a4c0 72static int initvars_flash_si(si_t *sih, char **vars, uint *count);
a9533e7e 73#ifdef BCMSDIO
26bcc181
AS
74static int initvars_cis_sdio(char **vars, uint *count);
75static int sprom_cmd_sdio(u8 cmd);
76static int sprom_read_sdio(u16 addr, u16 *data);
a9533e7e 77#endif /* BCMSDIO */
26bcc181 78static int sprom_read_pci(si_t *sih, u16 *sprom,
e69284f2 79 uint wordoff, u16 *buf, uint nwords, bool check_crc);
a9533e7e 80#if defined(BCMNVRAMR)
26bcc181 81static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz);
a9533e7e 82#endif
26bcc181 83static u16 srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
7d4df48e 84 uint wordoff, u16 data);
a9533e7e 85
26bcc181 86static int initvars_table(char *start, char *end,
e69284f2 87 char **vars, uint *count);
26bcc181 88static int initvars_flash(si_t *sih, char **vp,
e69284f2 89 uint len);
a9533e7e
HP
90
91/* Initialization of varbuf structure */
0d2f0724 92static void varbuf_init(varbuf_t *b, char *buf, uint size)
a2627bc0 93{
a9533e7e
HP
94 b->size = size;
95 b->base = b->buf = buf;
96}
97
98/* append a null terminated var=value string */
0d2f0724 99static int varbuf_append(varbuf_t *b, const char *fmt, ...)
a2627bc0 100{
a9533e7e
HP
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 */
ca8c1e59
JC
126 s = strchr(b->buf, '=');
127 if (s != NULL) {
a9533e7e
HP
128 len = (size_t) (s - b->buf);
129 for (s = b->base; s < b->buf;) {
a043b266 130 if ((memcmp(s, b->buf, len) == 0) && s[len] == '=') {
a9533e7e
HP
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
62145822
JC
139 while (*s++)
140 ;
a9533e7e
HP
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 */
26bcc181 156int srom_var_init(si_t *sih, uint bustype, void *curmap,
0d2f0724
GKH
157 char **vars, uint *count)
158{
a9533e7e
HP
159 uint len;
160
161 len = 0;
162
fa7a1db2 163 ASSERT(bustype == bustype);
a9533e7e 164 if (vars == NULL || count == NULL)
90ea2296 165 return 0;
a9533e7e
HP
166
167 *vars = NULL;
168 *count = 0;
169
fa7a1db2 170 switch (bustype) {
a9533e7e
HP
171 case SI_BUS:
172 case JTAG_BUS:
26bcc181 173 return initvars_srom_si(sih, curmap, vars, count);
a9533e7e
HP
174
175 case PCI_BUS:
176 ASSERT(curmap != NULL);
177 if (curmap == NULL)
90ea2296 178 return -1;
a9533e7e
HP
179
180 return initvars_srom_pci(sih, curmap, vars, count);
181
182#ifdef BCMSDIO
183 case SDIO_BUS:
26bcc181 184 return initvars_cis_sdio(vars, count);
a9533e7e
HP
185#endif /* BCMSDIO */
186
187 default:
188 ASSERT(0);
189 }
90ea2296 190 return -1;
a9533e7e
HP
191}
192
193/* support only 16-bit word read from srom */
194int
26bcc181 195srom_read(si_t *sih, uint bustype, void *curmap,
7d4df48e 196 uint byteoff, uint nbytes, u16 *buf, bool check_crc)
a9533e7e
HP
197{
198 uint off, nw;
199#ifdef BCMSDIO
200 uint i;
201#endif /* BCMSDIO */
202
fa7a1db2 203 ASSERT(bustype == bustype);
a9533e7e
HP
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
fa7a1db2 212 if (bustype == PCI_BUS) {
a9533e7e
HP
213 if (!curmap)
214 return 1;
215
216 if (si_is_sprom_available(sih)) {
7d4df48e 217 u16 *srom;
a9533e7e 218
7d4df48e 219 srom = (u16 *) SROM_OFFSET(sih);
a9533e7e
HP
220 if (srom == NULL)
221 return 1;
222
223 if (sprom_read_pci
26bcc181 224 (sih, srom, off, buf, nw, check_crc))
a9533e7e
HP
225 return 1;
226 }
227#if defined(BCMNVRAMR)
228 else {
26bcc181 229 if (otp_read_pci(sih, buf, SROM_MAX))
a9533e7e
HP
230 return 1;
231 }
232#endif
233#ifdef BCMSDIO
fa7a1db2 234 } else if (bustype == SDIO_BUS) {
a9533e7e
HP
235 off = byteoff / 2;
236 nw = nbytes / 2;
237 for (i = 0; i < nw; i++) {
238 if (sprom_read_sdio
26bcc181 239 ((u16) (off + i), (u16 *) (buf + i)))
a9533e7e
HP
240 return 1;
241 }
242#endif /* BCMSDIO */
fa7a1db2 243 } else if (bustype == SI_BUS) {
a9533e7e
HP
244 return 1;
245 } else {
246 return 1;
247 }
248
249 return 0;
250}
251
17c4da1e
GKH
252static const char vstr_manf[] = "manf=%s";
253static const char vstr_productname[] = "productname=%s";
254static const char vstr_manfid[] = "manfid=0x%x";
255static const char vstr_prodid[] = "prodid=0x%x";
a9533e7e 256#ifdef BCMSDIO
17c4da1e
GKH
257static const char vstr_sdmaxspeed[] = "sdmaxspeed=%d";
258static const char vstr_sdmaxblk[][13] = {
a9533e7e
HP
259"sdmaxblk0=%d", "sdmaxblk1=%d", "sdmaxblk2=%d"};
260#endif
17c4da1e
GKH
261static const char vstr_regwindowsz[] = "regwindowsz=%d";
262static const char vstr_sromrev[] = "sromrev=%d";
263static const char vstr_chiprev[] = "chiprev=%d";
264static const char vstr_subvendid[] = "subvendid=0x%x";
265static const char vstr_subdevid[] = "subdevid=0x%x";
266static const char vstr_boardrev[] = "boardrev=0x%x";
267static const char vstr_aa2g[] = "aa2g=0x%x";
268static const char vstr_aa5g[] = "aa5g=0x%x";
269static const char vstr_ag[] = "ag%d=0x%x";
270static const char vstr_cc[] = "cc=%d";
271static const char vstr_opo[] = "opo=%d";
272static const char vstr_pa0b[][9] = {
a9533e7e
HP
273"pa0b0=%d", "pa0b1=%d", "pa0b2=%d"};
274
17c4da1e
GKH
275static const char vstr_pa0itssit[] = "pa0itssit=%d";
276static const char vstr_pa0maxpwr[] = "pa0maxpwr=%d";
277static const char vstr_pa1b[][9] = {
a9533e7e
HP
278"pa1b0=%d", "pa1b1=%d", "pa1b2=%d"};
279
17c4da1e 280static const char vstr_pa1lob[][11] = {
a9533e7e
HP
281"pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d"};
282
17c4da1e 283static const char vstr_pa1hib[][11] = {
a9533e7e
HP
284"pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d"};
285
17c4da1e
GKH
286static const char vstr_pa1itssit[] = "pa1itssit=%d";
287static const char vstr_pa1maxpwr[] = "pa1maxpwr=%d";
288static const char vstr_pa1lomaxpwr[] = "pa1lomaxpwr=%d";
289static const char vstr_pa1himaxpwr[] = "pa1himaxpwr=%d";
290static const char vstr_oem[] =
a9533e7e 291 "oem=%02x%02x%02x%02x%02x%02x%02x%02x";
17c4da1e
GKH
292static const char vstr_boardflags[] = "boardflags=0x%x";
293static const char vstr_boardflags2[] = "boardflags2=0x%x";
294static const char vstr_ledbh[] = "ledbh%d=0x%x";
295static const char vstr_noccode[] = "ccode=0x0";
296static const char vstr_ccode[] = "ccode=%c%c";
297static const char vstr_cctl[] = "cctl=0x%x";
298static const char vstr_cckpo[] = "cckpo=0x%x";
299static const char vstr_ofdmpo[] = "ofdmpo=0x%x";
300static const char vstr_rdlid[] = "rdlid=0x%x";
301static const char vstr_rdlrndis[] = "rdlrndis=%d";
302static const char vstr_rdlrwu[] = "rdlrwu=%d";
303static const char vstr_usbfs[] = "usbfs=%d";
304static const char vstr_wpsgpio[] = "wpsgpio=%d";
305static const char vstr_wpsled[] = "wpsled=%d";
306static const char vstr_rdlsn[] = "rdlsn=%d";
307static const char vstr_rssismf2g[] = "rssismf2g=%d";
308static const char vstr_rssismc2g[] = "rssismc2g=%d";
309static const char vstr_rssisav2g[] = "rssisav2g=%d";
310static const char vstr_bxa2g[] = "bxa2g=%d";
311static const char vstr_rssismf5g[] = "rssismf5g=%d";
312static const char vstr_rssismc5g[] = "rssismc5g=%d";
313static const char vstr_rssisav5g[] = "rssisav5g=%d";
314static const char vstr_bxa5g[] = "bxa5g=%d";
315static const char vstr_tri2g[] = "tri2g=%d";
316static const char vstr_tri5gl[] = "tri5gl=%d";
317static const char vstr_tri5g[] = "tri5g=%d";
318static const char vstr_tri5gh[] = "tri5gh=%d";
319static const char vstr_rxpo2g[] = "rxpo2g=%d";
320static const char vstr_rxpo5g[] = "rxpo5g=%d";
321static const char vstr_boardtype[] = "boardtype=0x%x";
322static const char vstr_leddc[] = "leddc=0x%04x";
323static const char vstr_vendid[] = "vendid=0x%x";
324static const char vstr_devid[] = "devid=0x%x";
325static const char vstr_xtalfreq[] = "xtalfreq=%d";
326static const char vstr_txchain[] = "txchain=0x%x";
327static const char vstr_rxchain[] = "rxchain=0x%x";
328static const char vstr_antswitch[] = "antswitch=0x%x";
329static const char vstr_regrev[] = "regrev=0x%x";
330static const char vstr_antswctl2g[] = "antswctl2g=0x%x";
331static const char vstr_triso2g[] = "triso2g=0x%x";
332static const char vstr_pdetrange2g[] = "pdetrange2g=0x%x";
333static const char vstr_extpagain2g[] = "extpagain2g=0x%x";
334static const char vstr_tssipos2g[] = "tssipos2g=0x%x";
335static const char vstr_antswctl5g[] = "antswctl5g=0x%x";
336static const char vstr_triso5g[] = "triso5g=0x%x";
337static const char vstr_pdetrange5g[] = "pdetrange5g=0x%x";
338static const char vstr_extpagain5g[] = "extpagain5g=0x%x";
339static const char vstr_tssipos5g[] = "tssipos5g=0x%x";
340static const char vstr_maxp2ga0[] = "maxp2ga0=0x%x";
341static const char vstr_itt2ga0[] = "itt2ga0=0x%x";
342static const char vstr_pa[] = "pa%dgw%da%d=0x%x";
343static const char vstr_pahl[] = "pa%dg%cw%da%d=0x%x";
344static const char vstr_maxp5ga0[] = "maxp5ga0=0x%x";
345static const char vstr_itt5ga0[] = "itt5ga0=0x%x";
346static const char vstr_maxp5gha0[] = "maxp5gha0=0x%x";
347static const char vstr_maxp5gla0[] = "maxp5gla0=0x%x";
348static const char vstr_maxp2ga1[] = "maxp2ga1=0x%x";
349static const char vstr_itt2ga1[] = "itt2ga1=0x%x";
350static const char vstr_maxp5ga1[] = "maxp5ga1=0x%x";
351static const char vstr_itt5ga1[] = "itt5ga1=0x%x";
352static const char vstr_maxp5gha1[] = "maxp5gha1=0x%x";
353static const char vstr_maxp5gla1[] = "maxp5gla1=0x%x";
354static const char vstr_cck2gpo[] = "cck2gpo=0x%x";
355static const char vstr_ofdm2gpo[] = "ofdm2gpo=0x%x";
356static const char vstr_ofdm5gpo[] = "ofdm5gpo=0x%x";
357static const char vstr_ofdm5glpo[] = "ofdm5glpo=0x%x";
358static const char vstr_ofdm5ghpo[] = "ofdm5ghpo=0x%x";
359static const char vstr_cddpo[] = "cddpo=0x%x";
360static const char vstr_stbcpo[] = "stbcpo=0x%x";
361static const char vstr_bw40po[] = "bw40po=0x%x";
362static const char vstr_bwduppo[] = "bwduppo=0x%x";
363static const char vstr_mcspo[] = "mcs%dgpo%d=0x%x";
364static const char vstr_mcspohl[] = "mcs%dg%cpo%d=0x%x";
365static const char vstr_custom[] = "customvar%d=0x%x";
366static const char vstr_cckdigfilttype[] = "cckdigfilttype=%d";
367static const char vstr_boardnum[] = "boardnum=%d";
368static const char vstr_macaddr[] = "macaddr=%s";
369static const char vstr_usbepnum[] = "usbepnum=0x%x";
370static const char vstr_end[] = "END\0";
a9533e7e 371
36ef9a1e 372u8 patch_pair;
a9533e7e
HP
373
374/* For dongle HW, accept partial calibration parameters */
375#define BCMDONGLECASE(n)
376
26bcc181 377int srom_parsecis(u8 *pcis[], uint ciscnt, char **vars,
e69284f2 378 uint *count)
a9533e7e
HP
379{
380 char eabuf[32];
381 char *base;
382 varbuf_t b;
36ef9a1e 383 u8 *cis, tup, tlen, sromrev = 1;
a9533e7e 384 int i, j;
0965ae88 385 bool ag_init = false;
66cbd3ab 386 u32 w32;
a9533e7e
HP
387 uint funcid;
388 uint cisnum;
3e26416e 389 s32 boardnum;
a9533e7e
HP
390 int err;
391 bool standard_cis;
392
393 ASSERT(vars != NULL);
394 ASSERT(count != NULL);
395
396 boardnum = -1;
397
5fcc1fcb 398 base = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
a9533e7e
HP
399 ASSERT(base != NULL);
400 if (!base)
401 return -2;
402
403 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
9249ede9 404 memset(base, 0, MAXSZ_NVRAM_VARS);
a9533e7e
HP
405 eabuf[0] = '\0';
406 for (cisnum = 0; cisnum < ciscnt; cisnum++) {
407 cis = *pcis++;
408 i = 0;
409 funcid = 0;
0f0881b0 410 standard_cis = true;
a9533e7e
HP
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) {
36ef9a1e 462 u8 spd = cis[i + 3];
a9533e7e
HP
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 */
3ca5ada5
JP
498 if (eabuf[0] == '\0' &&
499 cis[i] == LAN_NID &&
ed956868 500 !is_zero_ether_addr(&cis[i + 2]) &&
3ca5ada5 501 !is_multicast_ether_addr(&cis[i + 2])) {
a9533e7e 502 ASSERT(cis[i + 1] ==
b8d63078 503 ETH_ALEN);
ba07d0cb
AS
504 snprintf(eabuf, sizeof(eabuf),
505 "%pM", &cis[i + 2]);
a9533e7e
HP
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++;
0965ae88 692 standard_cis = false;
a9533e7e
HP
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]);
0f0881b0 722 ag_init = true;
a9533e7e
HP
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:
ed956868 972 if (!is_zero_ether_addr(&cis[i + 1]) &&
3ca5ada5 973 !is_multicast_ether_addr(&cis[i + 1])) {
ba07d0cb
AS
974 snprintf(eabuf, sizeof(eabuf),
975 "%pM", &cis[i + 1]);
a9533e7e
HP
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:{
7d4df48e 1008 u16 fem =
a9533e7e
HP
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) {
7d4df48e 1330 u16 srom[35];
36ef9a1e 1331 u8 srev = cis[i + 1 + 70];
a9533e7e
HP
1332 ASSERT(srev == 3);
1333 /* make tuple value 16-bit aligned and parse it */
02160695
SF
1334 memcpy(srom, &cis[i + 1],
1335 sizeof(srom));
a9533e7e
HP
1336 _initvars_srom_pci(srev, srom,
1337 SROM3_SWRGN_OFF,
1338 &b);
1339 /* 2.4G antenna gain is included in SROM */
0f0881b0 1340 ag_init = true;
a9533e7e
HP
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 */
0965ae88 1388 if (getvar(NULL, "ag0") == NULL && ag_init == false) {
a9533e7e
HP
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);
26bcc181 1397 err = initvars_table(base, b.buf, vars, count);
a9533e7e 1398
182acb3c 1399 kfree(base);
a9533e7e
HP
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 */
7d4df48e 1406static u16
26bcc181 1407srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
e69284f2 1408 uint wordoff, u16 data)
a9533e7e
HP
1409{
1410 chipcregs_t *cc = (chipcregs_t *) ccregs;
1411 uint wait_cnt = 1000;
1412
1413 if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
ff31c54c 1414 W_REG(&cc->sromaddress, wordoff * 2);
a9533e7e 1415 if (cmd == SRC_OP_WRITE)
ff31c54c 1416 W_REG(&cc->sromdata, data);
a9533e7e
HP
1417 }
1418
ff31c54c 1419 W_REG(&cc->sromcontrol, SRC_START | cmd);
a9533e7e
HP
1420
1421 while (wait_cnt--) {
ff31c54c 1422 if ((R_REG(&cc->sromcontrol) & SRC_BUSY) == 0)
a9533e7e
HP
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)
ff31c54c 1431 return (u16) R_REG(&cc->sromdata);
a9533e7e
HP
1432 else
1433 return 0xffff;
1434}
1435
f3171549
SF
1436static 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
1442static 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
a9533e7e
HP
1448/*
1449 * Read in and validate sprom.
1450 * Return 0 on success, nonzero on error.
1451 */
1452static int
26bcc181 1453sprom_read_pci(si_t *sih, u16 *sprom, uint wordoff,
7d4df48e 1454 u16 *buf, uint nwords, bool check_crc)
a9533e7e
HP
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
36ef9a1e 1468 ccregs = (void *)((u8 *) sprom - CC_SROM_OTP);
a9533e7e 1469 buf[i] =
26bcc181 1470 srom_cc_cmd(sih, ccregs, SRC_OP_READ,
a9533e7e
HP
1471 wordoff + i, 0);
1472
1473 } else {
1474 if (ISSIM_ENAB(sih))
ff31c54c 1475 buf[i] = R_REG(&sprom[wordoff + i]);
a9533e7e 1476
ff31c54c 1477 buf[i] = R_REG(&sprom[wordoff + i]);
a9533e7e
HP
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);
36ef9a1e 1500 if (hndcrc8((u8 *) buf, nwords * 2, CRC8_INIT_VALUE) !=
a9533e7e
HP
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)
26bcc181 1513static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz)
a9533e7e 1514{
36ef9a1e 1515 u8 *otp;
a9533e7e
HP
1516 uint sz = OTP_SZ_MAX / 2; /* size in words */
1517 int err = 0;
1518
1519 ASSERT(bufsz <= OTP_SZ_MAX);
1520
5fcc1fcb 1521 otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
ca8c1e59 1522 if (otp == NULL) {
a9533e7e
HP
1523 return BCME_ERROR;
1524 }
1525
7d4df48e 1526 err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
a9533e7e 1527
02160695 1528 memcpy(buf, otp, bufsz);
a9533e7e 1529
46d994b1 1530 kfree(otp);
a9533e7e
HP
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);
36ef9a1e 1545 if (hndcrc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
a9533e7e
HP
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*/
26bcc181 1560static int initvars_table(char *start, char *end,
e69284f2 1561 char **vars, uint *count)
0d2f0724 1562{
a9533e7e
HP
1563 int c = (int)(end - start);
1564
1565 /* do it only when there is more than just the null string */
1566 if (c > 1) {
5fcc1fcb 1567 char *vp = kmalloc(c, GFP_ATOMIC);
a9533e7e
HP
1568 ASSERT(vp != NULL);
1569 if (!vp)
1570 return BCME_NOMEM;
02160695 1571 memcpy(vp, start, c);
a9533e7e
HP
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 */
26bcc181 1587static int initvars_flash(si_t *sih, char **base, uint len)
a2627bc0 1588{
a9533e7e
HP
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 */
5fcc1fcb 1597 flash = kmalloc(NVRAM_SPACE, GFP_ATOMIC);
ca8c1e59 1598 if (!flash)
a9533e7e 1599 return BCME_NOMEM;
ca8c1e59
JC
1600 err = nvram_getall(flash, NVRAM_SPACE);
1601 if (err)
a9533e7e
HP
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
182acb3c 1637 exit: kfree(flash);
a9533e7e
HP
1638 return err;
1639}
1640
1641/*
1642 * Initialize nonvolatile variable table from flash.
1643 * Return 0 on success, nonzero on error.
1644 */
0d2f0724 1645static int initvars_flash_si(si_t *sih, char **vars, uint *count)
a2627bc0 1646{
a9533e7e
HP
1647 char *vp, *base;
1648 int err;
1649
1650 ASSERT(vars != NULL);
1651 ASSERT(count != NULL);
1652
5fcc1fcb 1653 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
a9533e7e
HP
1654 ASSERT(vp != NULL);
1655 if (!vp)
1656 return BCME_NOMEM;
1657
26bcc181 1658 err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
ca8c1e59 1659 if (err == 0)
26bcc181 1660 err = initvars_table(base, vp, vars, count);
a9533e7e 1661
182acb3c 1662 kfree(base);
a9533e7e
HP
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
7d4df48e 1673static uint mask_shift(u16 mask)
a9533e7e
HP
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
7d4df48e 1684static uint mask_width(u16 mask)
a9533e7e
HP
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)
7d4df48e 1696static bool mask_valid(u16 mask)
a9533e7e
HP
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
0d2f0724
GKH
1704static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b)
1705{
7d4df48e 1706 u16 w;
66cbd3ab 1707 u32 val;
a9533e7e
HP
1708 const sromvar_t *srv;
1709 uint width;
1710 uint flags;
66cbd3ab 1711 u32 sr = (1 << sromrev);
a9533e7e
HP
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) {
a44d4236 1732 u8 ea[ETH_ALEN];
a9533e7e 1733
a44d4236
AS
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;
a9533e7e 1740
a44d4236 1741 varbuf_append(b, "%s=%pM", name, ea);
a9533e7e
HP
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) {
66cbd3ab 1783 u32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
a9533e7e
HP
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 */
0d2f0724
GKH
1850static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
1851{
7d4df48e 1852 u16 *srom, *sromwindow;
36ef9a1e 1853 u8 sromrev = 0;
66cbd3ab 1854 u32 sr;
a9533e7e
HP
1855 varbuf_t b;
1856 char *vp, *base = NULL;
0965ae88 1857 bool flash = false;
a9533e7e
HP
1858 int err = 0;
1859
1860 /*
1861 * Apply CRC over SROM content regardless SROM is present or not,
25985edc 1862 * and use variable <devpath>sromrev's existence in flash to decide
a9533e7e
HP
1863 * if we should return an error when CRC fails or read SROM variables
1864 * from flash.
1865 */
5fcc1fcb 1866 srom = kmalloc(SROM_MAX, GFP_ATOMIC);
a9533e7e
HP
1867 ASSERT(srom != NULL);
1868 if (!srom)
1869 return -2;
1870
7d4df48e 1871 sromwindow = (u16 *) SROM_OFFSET(sih);
a9533e7e
HP
1872 if (si_is_sprom_available(sih)) {
1873 err =
26bcc181 1874 sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
0f0881b0 1875 true);
a9533e7e
HP
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 =
26bcc181 1884 sprom_read_pci(sih, sromwindow, 0, srom,
0f0881b0 1885 SROM4_WORDS, true);
a9533e7e
HP
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 */
a9533e7e 1902 else {
26bcc181
AS
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;
a9533e7e 1909 }
26bcc181
AS
1910#else
1911 else
1912 err = 1;
1913#endif
a9533e7e 1914
26bcc181
AS
1915 /*
1916 * We want internal/wltest driver to come up with default
1917 * sromvars so we can program a blank SPROM/OTP.
a9533e7e
HP
1918 */
1919 if (err) {
1920 char *value;
66cbd3ab 1921 u32 val;
a9533e7e
HP
1922 val = 0;
1923
26bcc181 1924 BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
ca8c1e59
JC
1925 value = si_getdevpathvar(sih, "sromrev");
1926 if (value) {
36ef9a1e 1927 sromrev = (u8) simple_strtoul(value, NULL, 0);
0f0881b0 1928 flash = true;
a9533e7e
HP
1929 goto varscont;
1930 }
1931
1932 BS_ERROR(("%s, SROM CRC Error\n", __func__));
1933
ca8c1e59
JC
1934 value = si_getnvramflvar(sih, "sromrev");
1935 if (value) {
a9533e7e
HP
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
5fcc1fcb 1959 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
a9533e7e
HP
1960 ASSERT(vp != NULL);
1961 if (!vp) {
1962 err = -2;
1963 goto errout;
1964 }
1965
1966 /* read variables from flash */
1967 if (flash) {
26bcc181 1968 err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
ca8c1e59 1969 if (err)
a9533e7e
HP
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:
26bcc181 1987 err = initvars_table(base, vp, vars, count);
a9533e7e
HP
1988
1989 errout:
1990 if (base)
182acb3c 1991 kfree(base);
a9533e7e 1992
182acb3c 1993 kfree(srom);
a9533e7e
HP
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 */
26bcc181 2002static int initvars_cis_sdio(char **vars, uint *count)
a2627bc0 2003{
36ef9a1e 2004 u8 *cis[SBSDIO_NUM_FUNCTION + 1];
a9533e7e
HP
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++) {
5fcc1fcb 2012 cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
ca8c1e59 2013 if (cis[fn] == NULL) {
a9533e7e
HP
2014 rc = -1;
2015 break;
2016 }
2017
a9533e7e
HP
2018 if (bcmsdh_cis_read(NULL, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT) !=
2019 0) {
182acb3c 2020 kfree(cis[fn]);
a9533e7e
HP
2021 rc = -2;
2022 break;
2023 }
2024 }
2025
2026 if (!rc)
26bcc181 2027 rc = srom_parsecis(cis, fn, vars, count);
a9533e7e
HP
2028
2029 while (fn-- > 0)
182acb3c 2030 kfree(cis[fn]);
a9533e7e 2031
90ea2296 2032 return rc;
a9533e7e
HP
2033}
2034
2035/* set SDIO sprom command register */
26bcc181 2036static int sprom_cmd_sdio(u8 cmd)
a2627bc0 2037{
36ef9a1e 2038 u8 status = 0;
a9533e7e
HP
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 */
26bcc181 2056static int sprom_read_sdio(u16 addr, u16 *data)
a9533e7e 2057{
36ef9a1e 2058 u8 addr_l, addr_h, data_l, data_h;
a9533e7e 2059
36ef9a1e
GKH
2060 addr_l = (u8) ((addr * 2) & 0xff);
2061 addr_h = (u8) (((addr * 2) >> 8) & 0xff);
a9533e7e
HP
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 */
26bcc181 2070 if (sprom_cmd_sdio(SBSDIO_SPROM_READ))
a9533e7e
HP
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
26bcc181 2084static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *varsz)
0d2f0724 2085{
a9533e7e
HP
2086 /* Search flash nvram section for srom variables */
2087 return initvars_flash_si(sih, vars, varsz);
2088}