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