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