Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[pandora-kernel.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 }