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