2
* Copyright (c) 2010 Broadcom Corporation
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.
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.
16
#include <linux/kernel.h>
17
#include <linux/string.h>
18
#include <linux/etherdevice.h>
21
#include <linux/module.h>
22
#include <linux/pci.h>
28
#include <bcmendian.h>
32
#include <bcmsrom_tbl.h>
44
#include <sbsdpcmdev.h>
47
#include <proto/ethernet.h> /* for sprom content groking */
49
#define BS_ERROR(args)
51
#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
52
(((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
53
((u8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
54
((u8 *)curmap + PCI_BAR0_SPROM_OFFSET))
57
#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
58
#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
61
typedef struct varbuf {
62
char *base; /* pointer to buffer base */
63
char *buf; /* pointer to current position */
64
unsigned int size; /* current (residual) size in bytes */
69
#define SROM_CIS_SINGLE 1
71
static int initvars_srom_si(si_t *sih, struct osl_info *osh, void *curmap,
72
char **vars, uint *count);
73
static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off,
75
static int initvars_srom_pci(si_t *sih, void *curmap, char **vars,
77
static int initvars_flash_si(si_t *sih, char **vars, uint *count);
79
static int initvars_cis_sdio(struct osl_info *osh, char **vars, uint *count);
80
static int sprom_cmd_sdio(struct osl_info *osh, u8 cmd);
81
static int sprom_read_sdio(struct osl_info *osh, u16 addr, u16 *data);
83
static int sprom_read_pci(struct osl_info *osh, si_t *sih, u16 *sprom,
84
uint wordoff, u16 *buf, uint nwords, bool check_crc);
85
#if defined(BCMNVRAMR)
86
static int otp_read_pci(struct osl_info *osh, si_t *sih, u16 *buf, uint bufsz);
88
static u16 srom_cc_cmd(si_t *sih, struct osl_info *osh, void *ccregs, u32 cmd,
89
uint wordoff, u16 data);
91
static int initvars_table(struct osl_info *osh, char *start, char *end,
92
char **vars, uint *count);
93
static int initvars_flash(si_t *sih, struct osl_info *osh, char **vp,
96
/* Initialization of varbuf structure */
97
static void varbuf_init(varbuf_t *b, char *buf, uint size)
100
b->base = b->buf = buf;
103
/* append a null terminated var=value string */
104
static int varbuf_append(varbuf_t *b, const char *fmt, ...)
115
r = vsnprintf(b->buf, b->size, fmt, ap);
118
/* C99 snprintf behavior returns r >= size on overflow,
119
* others return -1 on overflow.
120
* All return -1 on format error.
121
* We need to leave room for 2 null terminations, one for the current var
122
* string, and one for final null of the var table. So check that the
123
* strlen written, r, leaves room for 2 chars.
125
if ((r == -1) || (r > (int)(b->size - 2))) {
130
/* Remove any earlier occurrence of the same variable */
131
s = strchr(b->buf, '=');
133
len = (size_t) (s - b->buf);
134
for (s = b->base; s < b->buf;) {
135
if ((memcmp(s, b->buf, len) == 0) && s[len] == '=') {
137
memmove(s, (s + len),
138
((b->buf + r + 1) - (s + len)));
140
b->size += (unsigned int)len;
149
/* skip over this string's null termination */
158
* Initialize local vars from the right source for this platform.
159
* Return 0 on success, nonzero on error.
161
int srom_var_init(si_t *sih, uint bustype, void *curmap, struct osl_info *osh,
162
char **vars, uint *count)
168
ASSERT(bustype == bustype);
169
if (vars == NULL || count == NULL)
178
return initvars_srom_si(sih, osh, curmap, vars, count);
181
ASSERT(curmap != NULL);
185
return initvars_srom_pci(sih, curmap, vars, count);
189
return initvars_cis_sdio(osh, vars, count);
198
/* support only 16-bit word read from srom */
200
srom_read(si_t *sih, uint bustype, void *curmap, struct osl_info *osh,
201
uint byteoff, uint nbytes, u16 *buf, bool check_crc)
208
ASSERT(bustype == bustype);
210
/* check input - 16-bit access only */
211
if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX)
217
if (bustype == PCI_BUS) {
221
if (si_is_sprom_available(sih)) {
224
srom = (u16 *) SROM_OFFSET(sih);
229
(osh, sih, srom, off, buf, nw, check_crc))
232
#if defined(BCMNVRAMR)
234
if (otp_read_pci(osh, sih, buf, SROM_MAX))
239
} else if (bustype == SDIO_BUS) {
242
for (i = 0; i < nw; i++) {
244
(osh, (u16) (off + i), (u16 *) (buf + i)))
248
} else if (bustype == SI_BUS) {
257
static const char vstr_manf[] = "manf=%s";
258
static const char vstr_productname[] = "productname=%s";
259
static const char vstr_manfid[] = "manfid=0x%x";
260
static const char vstr_prodid[] = "prodid=0x%x";
262
static const char vstr_sdmaxspeed[] = "sdmaxspeed=%d";
263
static const char vstr_sdmaxblk[][13] = {
264
"sdmaxblk0=%d", "sdmaxblk1=%d", "sdmaxblk2=%d"};
266
static const char vstr_regwindowsz[] = "regwindowsz=%d";
267
static const char vstr_sromrev[] = "sromrev=%d";
268
static const char vstr_chiprev[] = "chiprev=%d";
269
static const char vstr_subvendid[] = "subvendid=0x%x";
270
static const char vstr_subdevid[] = "subdevid=0x%x";
271
static const char vstr_boardrev[] = "boardrev=0x%x";
272
static const char vstr_aa2g[] = "aa2g=0x%x";
273
static const char vstr_aa5g[] = "aa5g=0x%x";
274
static const char vstr_ag[] = "ag%d=0x%x";
275
static const char vstr_cc[] = "cc=%d";
276
static const char vstr_opo[] = "opo=%d";
277
static const char vstr_pa0b[][9] = {
278
"pa0b0=%d", "pa0b1=%d", "pa0b2=%d"};
280
static const char vstr_pa0itssit[] = "pa0itssit=%d";
281
static const char vstr_pa0maxpwr[] = "pa0maxpwr=%d";
282
static const char vstr_pa1b[][9] = {
283
"pa1b0=%d", "pa1b1=%d", "pa1b2=%d"};
285
static const char vstr_pa1lob[][11] = {
286
"pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d"};
288
static const char vstr_pa1hib[][11] = {
289
"pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d"};
291
static const char vstr_pa1itssit[] = "pa1itssit=%d";
292
static const char vstr_pa1maxpwr[] = "pa1maxpwr=%d";
293
static const char vstr_pa1lomaxpwr[] = "pa1lomaxpwr=%d";
294
static const char vstr_pa1himaxpwr[] = "pa1himaxpwr=%d";
295
static const char vstr_oem[] =
296
"oem=%02x%02x%02x%02x%02x%02x%02x%02x";
297
static const char vstr_boardflags[] = "boardflags=0x%x";
298
static const char vstr_boardflags2[] = "boardflags2=0x%x";
299
static const char vstr_ledbh[] = "ledbh%d=0x%x";
300
static const char vstr_noccode[] = "ccode=0x0";
301
static const char vstr_ccode[] = "ccode=%c%c";
302
static const char vstr_cctl[] = "cctl=0x%x";
303
static const char vstr_cckpo[] = "cckpo=0x%x";
304
static const char vstr_ofdmpo[] = "ofdmpo=0x%x";
305
static const char vstr_rdlid[] = "rdlid=0x%x";
306
static const char vstr_rdlrndis[] = "rdlrndis=%d";
307
static const char vstr_rdlrwu[] = "rdlrwu=%d";
308
static const char vstr_usbfs[] = "usbfs=%d";
309
static const char vstr_wpsgpio[] = "wpsgpio=%d";
310
static const char vstr_wpsled[] = "wpsled=%d";
311
static const char vstr_rdlsn[] = "rdlsn=%d";
312
static const char vstr_rssismf2g[] = "rssismf2g=%d";
313
static const char vstr_rssismc2g[] = "rssismc2g=%d";
314
static const char vstr_rssisav2g[] = "rssisav2g=%d";
315
static const char vstr_bxa2g[] = "bxa2g=%d";
316
static const char vstr_rssismf5g[] = "rssismf5g=%d";
317
static const char vstr_rssismc5g[] = "rssismc5g=%d";
318
static const char vstr_rssisav5g[] = "rssisav5g=%d";
319
static const char vstr_bxa5g[] = "bxa5g=%d";
320
static const char vstr_tri2g[] = "tri2g=%d";
321
static const char vstr_tri5gl[] = "tri5gl=%d";
322
static const char vstr_tri5g[] = "tri5g=%d";
323
static const char vstr_tri5gh[] = "tri5gh=%d";
324
static const char vstr_rxpo2g[] = "rxpo2g=%d";
325
static const char vstr_rxpo5g[] = "rxpo5g=%d";
326
static const char vstr_boardtype[] = "boardtype=0x%x";
327
static const char vstr_leddc[] = "leddc=0x%04x";
328
static const char vstr_vendid[] = "vendid=0x%x";
329
static const char vstr_devid[] = "devid=0x%x";
330
static const char vstr_xtalfreq[] = "xtalfreq=%d";
331
static const char vstr_txchain[] = "txchain=0x%x";
332
static const char vstr_rxchain[] = "rxchain=0x%x";
333
static const char vstr_antswitch[] = "antswitch=0x%x";
334
static const char vstr_regrev[] = "regrev=0x%x";
335
static const char vstr_antswctl2g[] = "antswctl2g=0x%x";
336
static const char vstr_triso2g[] = "triso2g=0x%x";
337
static const char vstr_pdetrange2g[] = "pdetrange2g=0x%x";
338
static const char vstr_extpagain2g[] = "extpagain2g=0x%x";
339
static const char vstr_tssipos2g[] = "tssipos2g=0x%x";
340
static const char vstr_antswctl5g[] = "antswctl5g=0x%x";
341
static const char vstr_triso5g[] = "triso5g=0x%x";
342
static const char vstr_pdetrange5g[] = "pdetrange5g=0x%x";
343
static const char vstr_extpagain5g[] = "extpagain5g=0x%x";
344
static const char vstr_tssipos5g[] = "tssipos5g=0x%x";
345
static const char vstr_maxp2ga0[] = "maxp2ga0=0x%x";
346
static const char vstr_itt2ga0[] = "itt2ga0=0x%x";
347
static const char vstr_pa[] = "pa%dgw%da%d=0x%x";
348
static const char vstr_pahl[] = "pa%dg%cw%da%d=0x%x";
349
static const char vstr_maxp5ga0[] = "maxp5ga0=0x%x";
350
static const char vstr_itt5ga0[] = "itt5ga0=0x%x";
351
static const char vstr_maxp5gha0[] = "maxp5gha0=0x%x";
352
static const char vstr_maxp5gla0[] = "maxp5gla0=0x%x";
353
static const char vstr_maxp2ga1[] = "maxp2ga1=0x%x";
354
static const char vstr_itt2ga1[] = "itt2ga1=0x%x";
355
static const char vstr_maxp5ga1[] = "maxp5ga1=0x%x";
356
static const char vstr_itt5ga1[] = "itt5ga1=0x%x";
357
static const char vstr_maxp5gha1[] = "maxp5gha1=0x%x";
358
static const char vstr_maxp5gla1[] = "maxp5gla1=0x%x";
359
static const char vstr_cck2gpo[] = "cck2gpo=0x%x";
360
static const char vstr_ofdm2gpo[] = "ofdm2gpo=0x%x";
361
static const char vstr_ofdm5gpo[] = "ofdm5gpo=0x%x";
362
static const char vstr_ofdm5glpo[] = "ofdm5glpo=0x%x";
363
static const char vstr_ofdm5ghpo[] = "ofdm5ghpo=0x%x";
364
static const char vstr_cddpo[] = "cddpo=0x%x";
365
static const char vstr_stbcpo[] = "stbcpo=0x%x";
366
static const char vstr_bw40po[] = "bw40po=0x%x";
367
static const char vstr_bwduppo[] = "bwduppo=0x%x";
368
static const char vstr_mcspo[] = "mcs%dgpo%d=0x%x";
369
static const char vstr_mcspohl[] = "mcs%dg%cpo%d=0x%x";
370
static const char vstr_custom[] = "customvar%d=0x%x";
371
static const char vstr_cckdigfilttype[] = "cckdigfilttype=%d";
372
static const char vstr_boardnum[] = "boardnum=%d";
373
static const char vstr_macaddr[] = "macaddr=%s";
374
static const char vstr_usbepnum[] = "usbepnum=0x%x";
375
static const char vstr_end[] = "END\0";
379
/* For dongle HW, accept partial calibration parameters */
380
#define BCMDONGLECASE(n)
382
int srom_parsecis(struct osl_info *osh, u8 *pcis[], uint ciscnt, char **vars,
388
u8 *cis, tup, tlen, sromrev = 1;
390
bool ag_init = false;
398
ASSERT(vars != NULL);
399
ASSERT(count != NULL);
403
base = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
404
ASSERT(base != NULL);
408
varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
409
memset(base, 0, MAXSZ_NVRAM_VARS);
411
for (cisnum = 0; cisnum < ciscnt; cisnum++) {
419
if (tup == CISTPL_NULL || tup == CISTPL_END)
424
if (cis[i] == CISTPL_NULL
425
|| cis[i] == CISTPL_END) {
430
tup = CISTPL_BRCM_HNBU;
434
if ((i + tlen) >= CIS_SIZE)
439
/* assume the strings are good if the version field checks out */
440
if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) {
441
varbuf_append(&b, vstr_manf,
443
varbuf_append(&b, vstr_productname,
452
varbuf_append(&b, vstr_manfid,
453
(cis[i + 1] << 8) + cis[i]);
454
varbuf_append(&b, vstr_prodid,
455
(cis[i + 3] << 8) + cis[i + 2]);
464
case CISTPL_FID_SDIO:
468
static int base[] = {
469
-1, 10, 12, 13, 15, 20,
471
35, 40, 45, 50, 55, 60,
474
static int mult[] = {
475
10, 100, 1000, 10000,
478
ASSERT((mult[spd & 0x7] != -1)
481
[(spd >> 3) & 0x0f]));
491
} else if (cis[i] == 1) {
502
/* set macaddr if HNBU_MACADDR not seen yet */
503
if (eabuf[0] == '\0' &&
505
!is_zero_ether_addr(&cis[i + 2]) &&
506
!is_multicast_ether_addr(&cis[i + 2])) {
509
snprintf(eabuf, sizeof(eabuf),
512
/* set boardnum if HNBU_BOARDNUM not seen yet */
523
varbuf_append(&b, vstr_regwindowsz,
524
(cis[i + 7] << 8) | cis[i + 6]);
527
case CISTPL_BRCM_HNBU:
530
sromrev = cis[i + 1];
531
varbuf_append(&b, vstr_sromrev,
536
varbuf_append(&b, vstr_xtalfreq,
544
varbuf_append(&b, vstr_vendid,
547
varbuf_append(&b, vstr_devid,
551
varbuf_append(&b, vstr_chiprev,
562
varbuf_append(&b, vstr_subdevid,
565
/* subdevid doubles for boardtype */
575
(cis[i + 2] << 8) + cis[i + 1];
583
/* retrieve the patch pairs
584
* from tlen/6; where 6 is
585
* sizeof(patch addr(2)) +
586
* sizeof(patch data(4)).
588
patch_pair = tlen / 6;
590
for (j = 0; j < patch_pair; j++) {
645
varbuf_append(&b, vstr_boardrev,
648
varbuf_append(&b, vstr_boardrev,
653
case HNBU_BOARDFLAGS:
654
w32 = (cis[i + 2] << 8) + cis[i + 1];
657
((cis[i + 4] << 24) +
659
varbuf_append(&b, vstr_boardflags, w32);
663
(cis[i + 6] << 8) + cis[i +
678
varbuf_append(&b, vstr_usbfs,
683
varbuf_append(&b, vstr_boardtype,
690
* what follows is a nonstandard HNBU CIS
691
* that lacks CISTPL_BRCM_HNBU tags
693
* skip 0xff (end of standard CIS)
697
standard_cis = false;
701
varbuf_append(&b, vstr_usbepnum,
702
(cis[i + 2] << 8) | cis[i
708
varbuf_append(&b, vstr_aa2g,
711
varbuf_append(&b, vstr_aa5g,
716
varbuf_append(&b, vstr_ag, 0,
719
varbuf_append(&b, vstr_ag, 1,
722
varbuf_append(&b, vstr_ag, 2,
725
varbuf_append(&b, vstr_ag, 3,
731
varbuf_append(&b, vstr_aa5g,
733
varbuf_append(&b, vstr_ag, 1,
738
ASSERT(sromrev == 1);
739
varbuf_append(&b, vstr_cc, cis[i + 1]);
745
ASSERT(sromrev == 1);
751
ASSERT(sromrev >= 2);
752
varbuf_append(&b, vstr_opo,
766
for (j = 0; j < 3; j++) {
791
ASSERT((sromrev == 2)
811
for (j = 0; j < 3; j++) {
826
for (j = 3; j < 6; j++) {
841
for (j = 6; j < 9; j++) {
858
ASSERT((tlen == 19) ||
866
ASSERT(sromrev == 1);
867
varbuf_append(&b, vstr_oem,
868
cis[i + 1], cis[i + 2],
869
cis[i + 3], cis[i + 4],
870
cis[i + 5], cis[i + 6],
871
cis[i + 7], cis[i + 8]);
875
for (j = 1; j <= 4; j++) {
876
if (cis[i + j] != 0xff) {
888
if ((cis[i + 1] == 0)
889
|| (cis[i + 2] == 0))
890
varbuf_append(&b, vstr_noccode);
892
varbuf_append(&b, vstr_ccode,
895
varbuf_append(&b, vstr_cctl,
901
varbuf_append(&b, vstr_cckpo,
902
(cis[i + 2] << 8) | cis[i
909
varbuf_append(&b, vstr_ofdmpo,
917
varbuf_append(&b, vstr_wpsgpio,
920
varbuf_append(&b, vstr_wpsled,
924
case HNBU_RSSISMBXA2G:
925
ASSERT(sromrev == 3);
926
varbuf_append(&b, vstr_rssismf2g,
928
varbuf_append(&b, vstr_rssismc2g,
929
(cis[i + 1] >> 4) & 0xf);
930
varbuf_append(&b, vstr_rssisav2g,
932
varbuf_append(&b, vstr_bxa2g,
933
(cis[i + 2] >> 3) & 0x3);
936
case HNBU_RSSISMBXA5G:
937
ASSERT(sromrev == 3);
938
varbuf_append(&b, vstr_rssismf5g,
940
varbuf_append(&b, vstr_rssismc5g,
941
(cis[i + 1] >> 4) & 0xf);
942
varbuf_append(&b, vstr_rssisav5g,
944
varbuf_append(&b, vstr_bxa5g,
945
(cis[i + 2] >> 3) & 0x3);
949
ASSERT(sromrev == 3);
950
varbuf_append(&b, vstr_tri2g,
955
ASSERT(sromrev == 3);
956
varbuf_append(&b, vstr_tri5gl,
958
varbuf_append(&b, vstr_tri5g,
960
varbuf_append(&b, vstr_tri5gh,
965
ASSERT(sromrev == 3);
966
varbuf_append(&b, vstr_rxpo2g,
971
ASSERT(sromrev == 3);
972
varbuf_append(&b, vstr_rxpo5g,
977
if (!is_zero_ether_addr(&cis[i + 1]) &&
978
!is_multicast_ether_addr(&cis[i + 1])) {
979
snprintf(eabuf, sizeof(eabuf),
982
/* set boardnum if HNBU_BOARDNUM not seen yet */
991
/* CIS leddc only has 16bits, convert it to 32bits */
992
w32 = ((cis[i + 2] << 24) | /* oncount */
993
(cis[i + 1] << 8)); /* offcount */
994
varbuf_append(&b, vstr_leddc, w32);
997
case HNBU_CHAINSWITCH:
998
varbuf_append(&b, vstr_txchain,
1000
varbuf_append(&b, vstr_rxchain,
1002
varbuf_append(&b, vstr_antswitch,
1008
varbuf_append(&b, vstr_regrev,
1014
(cis[i + 2] << 8) + cis[i +
1019
SROM8_FEM_ANTSWLUT_MASK)
1021
SROM8_FEM_ANTSWLUT_SHIFT);
1022
varbuf_append(&b, vstr_triso2g,
1024
SROM8_FEM_TR_ISO_MASK)
1026
SROM8_FEM_TR_ISO_SHIFT);
1030
SROM8_FEM_PDET_RANGE_MASK)
1032
SROM8_FEM_PDET_RANGE_SHIFT);
1036
SROM8_FEM_EXTPA_GAIN_MASK)
1038
SROM8_FEM_EXTPA_GAIN_SHIFT);
1042
SROM8_FEM_TSSIPOS_MASK)
1044
SROM8_FEM_TSSIPOS_SHIFT);
1049
(cis[i + 4] << 8) + cis[i +
1054
SROM8_FEM_ANTSWLUT_MASK)
1056
SROM8_FEM_ANTSWLUT_SHIFT);
1057
varbuf_append(&b, vstr_triso5g,
1059
SROM8_FEM_TR_ISO_MASK)
1061
SROM8_FEM_TR_ISO_SHIFT);
1065
SROM8_FEM_PDET_RANGE_MASK)
1067
SROM8_FEM_PDET_RANGE_SHIFT);
1071
SROM8_FEM_EXTPA_GAIN_MASK)
1073
SROM8_FEM_EXTPA_GAIN_SHIFT);
1077
SROM8_FEM_TSSIPOS_MASK)
1079
SROM8_FEM_TSSIPOS_SHIFT);
1083
case HNBU_PAPARMS_C0:
1084
varbuf_append(&b, vstr_maxp2ga0,
1086
varbuf_append(&b, vstr_itt2ga0,
1088
varbuf_append(&b, vstr_pa, 2, 0, 0,
1091
varbuf_append(&b, vstr_pa, 2, 1, 0,
1094
varbuf_append(&b, vstr_pa, 2, 2, 0,
1100
varbuf_append(&b, vstr_maxp5ga0,
1102
varbuf_append(&b, vstr_itt5ga0,
1104
varbuf_append(&b, vstr_maxp5gha0,
1106
varbuf_append(&b, vstr_maxp5gla0,
1108
varbuf_append(&b, vstr_pa, 5, 0, 0,
1109
(cis[i + 14] << 8) +
1111
varbuf_append(&b, vstr_pa, 5, 1, 0,
1112
(cis[i + 16] << 8) +
1114
varbuf_append(&b, vstr_pa, 5, 2, 0,
1115
(cis[i + 18] << 8) +
1117
varbuf_append(&b, vstr_pahl, 5, 'l', 0,
1119
(cis[i + 20] << 8) +
1121
varbuf_append(&b, vstr_pahl, 5, 'l', 1,
1123
(cis[i + 22] << 8) +
1125
varbuf_append(&b, vstr_pahl, 5, 'l', 2,
1127
(cis[i + 24] << 8) +
1129
varbuf_append(&b, vstr_pahl, 5, 'h', 0,
1131
(cis[i + 26] << 8) +
1133
varbuf_append(&b, vstr_pahl, 5, 'h', 1,
1135
(cis[i + 28] << 8) +
1137
varbuf_append(&b, vstr_pahl, 5, 'h', 2,
1139
(cis[i + 30] << 8) +
1143
case HNBU_PAPARMS_C1:
1144
varbuf_append(&b, vstr_maxp2ga1,
1146
varbuf_append(&b, vstr_itt2ga1,
1148
varbuf_append(&b, vstr_pa, 2, 0, 1,
1151
varbuf_append(&b, vstr_pa, 2, 1, 1,
1154
varbuf_append(&b, vstr_pa, 2, 2, 1,
1160
varbuf_append(&b, vstr_maxp5ga1,
1162
varbuf_append(&b, vstr_itt5ga1,
1164
varbuf_append(&b, vstr_maxp5gha1,
1166
varbuf_append(&b, vstr_maxp5gla1,
1168
varbuf_append(&b, vstr_pa, 5, 0, 1,
1169
(cis[i + 14] << 8) +
1171
varbuf_append(&b, vstr_pa, 5, 1, 1,
1172
(cis[i + 16] << 8) +
1174
varbuf_append(&b, vstr_pa, 5, 2, 1,
1175
(cis[i + 18] << 8) +
1177
varbuf_append(&b, vstr_pahl, 5, 'l', 0,
1179
(cis[i + 20] << 8) +
1181
varbuf_append(&b, vstr_pahl, 5, 'l', 1,
1183
(cis[i + 22] << 8) +
1185
varbuf_append(&b, vstr_pahl, 5, 'l', 2,
1187
(cis[i + 24] << 8) +
1189
varbuf_append(&b, vstr_pahl, 5, 'h', 0,
1191
(cis[i + 26] << 8) +
1193
varbuf_append(&b, vstr_pahl, 5, 'h', 1,
1195
(cis[i + 28] << 8) +
1197
varbuf_append(&b, vstr_pahl, 5, 'h', 2,
1199
(cis[i + 30] << 8) +
1203
case HNBU_PO_CCKOFDM:
1204
varbuf_append(&b, vstr_cck2gpo,
1207
varbuf_append(&b, vstr_ofdm2gpo,
1208
(cis[i + 6] << 24) +
1209
(cis[i + 5] << 16) +
1215
varbuf_append(&b, vstr_ofdm5gpo,
1216
(cis[i + 10] << 24) +
1217
(cis[i + 9] << 16) +
1220
varbuf_append(&b, vstr_ofdm5glpo,
1221
(cis[i + 14] << 24) +
1222
(cis[i + 13] << 16) +
1223
(cis[i + 12] << 8) +
1225
varbuf_append(&b, vstr_ofdm5ghpo,
1226
(cis[i + 18] << 24) +
1227
(cis[i + 17] << 16) +
1228
(cis[i + 16] << 8) +
1233
for (j = 0; j <= (tlen / 2); j++) {
1234
varbuf_append(&b, vstr_mcspo, 2,
1244
case HNBU_PO_MCS5GM:
1245
for (j = 0; j <= (tlen / 2); j++) {
1246
varbuf_append(&b, vstr_mcspo, 5,
1256
case HNBU_PO_MCS5GLH:
1257
for (j = 0; j <= (tlen / 4); j++) {
1258
varbuf_append(&b, vstr_mcspohl,
1267
for (j = 0; j <= (tlen / 4); j++) {
1268
varbuf_append(&b, vstr_mcspohl,
1283
varbuf_append(&b, vstr_cddpo,
1289
varbuf_append(&b, vstr_stbcpo,
1295
varbuf_append(&b, vstr_bw40po,
1300
case HNBU_PO_40MDUP:
1301
varbuf_append(&b, vstr_bwduppo,
1307
varbuf_append(&b, vstr_ofdm5gpo,
1308
(cis[i + 4] << 24) +
1309
(cis[i + 3] << 16) +
1312
varbuf_append(&b, vstr_ofdm5glpo,
1313
(cis[i + 8] << 24) +
1314
(cis[i + 7] << 16) +
1317
varbuf_append(&b, vstr_ofdm5ghpo,
1318
(cis[i + 12] << 24) +
1319
(cis[i + 11] << 16) +
1320
(cis[i + 10] << 8) +
1325
varbuf_append(&b, vstr_custom, 1,
1326
((cis[i + 4] << 24) +
1327
(cis[i + 3] << 16) +
1332
#if defined(BCMSDIO)
1333
case HNBU_SROM3SWRGN:
1336
u8 srev = cis[i + 1 + 70];
1338
/* make tuple value 16-bit aligned and parse it */
1339
bcopy(&cis[i + 1], srom,
1341
_initvars_srom_pci(srev, srom,
1344
/* 2.4G antenna gain is included in SROM */
1346
/* Ethernet MAC address is included in SROM */
1350
/* create extra variables */
1352
varbuf_append(&b, vstr_vendid,
1358
varbuf_append(&b, vstr_devid,
1364
varbuf_append(&b, vstr_xtalfreq,
1370
#endif /* defined(BCMSDIO) */
1372
case HNBU_CCKFILTTYPE:
1373
varbuf_append(&b, vstr_cckdigfilttype,
1381
} while (tup != CISTPL_END);
1384
if (boardnum != -1) {
1385
varbuf_append(&b, vstr_boardnum, boardnum);
1389
varbuf_append(&b, vstr_macaddr, eabuf);
1392
/* if there is no antenna gain field, set default */
1393
if (getvar(NULL, "ag0") == NULL && ag_init == false) {
1394
varbuf_append(&b, vstr_ag, 0, 0xff);
1397
/* final nullbyte terminator */
1398
ASSERT(b.size >= 1);
1401
ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS);
1402
err = initvars_table(osh, base, b.buf, vars, count);
1408
/* In chips with chipcommon rev 32 and later, the srom is in chipcommon,
1409
* not in the bus cores.
1412
srom_cc_cmd(si_t *sih, struct osl_info *osh, void *ccregs, u32 cmd,
1413
uint wordoff, u16 data)
1415
chipcregs_t *cc = (chipcregs_t *) ccregs;
1416
uint wait_cnt = 1000;
1418
if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
1419
W_REG(osh, &cc->sromaddress, wordoff * 2);
1420
if (cmd == SRC_OP_WRITE)
1421
W_REG(osh, &cc->sromdata, data);
1424
W_REG(osh, &cc->sromcontrol, SRC_START | cmd);
1426
while (wait_cnt--) {
1427
if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0)
1432
BS_ERROR(("%s: Command 0x%x timed out\n", __func__, cmd));
1435
if (cmd == SRC_OP_READ)
1436
return (u16) R_REG(osh, &cc->sromdata);
1442
* Read in and validate sprom.
1443
* Return 0 on success, nonzero on error.
1446
sprom_read_pci(struct osl_info *osh, si_t *sih, u16 *sprom, uint wordoff,
1447
u16 *buf, uint nwords, bool check_crc)
1451
void *ccregs = NULL;
1453
/* read the sprom */
1454
for (i = 0; i < nwords; i++) {
1456
if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
1457
/* use indirect since direct is too slow on QT */
1458
if ((sih->cccaps & CC_CAP_SROM) == 0)
1461
ccregs = (void *)((u8 *) sprom - CC_SROM_OTP);
1463
srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ,
1467
if (ISSIM_ENAB(sih))
1468
buf[i] = R_REG(osh, &sprom[wordoff + i]);
1470
buf[i] = R_REG(osh, &sprom[wordoff + i]);
1475
/* bypass crc checking for simulation to allow srom hack */
1476
if (ISSIM_ENAB(sih))
1481
if (buf[0] == 0xffff) {
1482
/* The hardware thinks that an srom that starts with 0xffff
1483
* is blank, regardless of the rest of the content, so declare
1486
BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n",
1491
/* fixup the endianness so crc8 will pass */
1492
htol16_buf(buf, nwords * 2);
1493
if (hndcrc8((u8 *) buf, nwords * 2, CRC8_INIT_VALUE) !=
1495
/* DBG only pci always read srom4 first, then srom8/9 */
1496
/* BS_ERROR(("%s: bad crc\n", __func__)); */
1499
/* now correct the endianness of the byte array */
1500
ltoh16_buf(buf, nwords * 2);
1505
#if defined(BCMNVRAMR)
1506
static int otp_read_pci(struct osl_info *osh, si_t *sih, u16 *buf, uint bufsz)
1509
uint sz = OTP_SZ_MAX / 2; /* size in words */
1512
ASSERT(bufsz <= OTP_SZ_MAX);
1514
otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
1519
err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
1521
bcopy(otp, buf, bufsz);
1527
if (buf[0] == 0xffff) {
1528
/* The hardware thinks that an srom that starts with 0xffff
1529
* is blank, regardless of the rest of the content, so declare
1532
BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __func__,
1537
/* fixup the endianness so crc8 will pass */
1538
htol16_buf(buf, bufsz);
1539
if (hndcrc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
1541
BS_ERROR(("%s: bad crc\n", __func__));
1544
/* now correct the endianness of the byte array */
1545
ltoh16_buf(buf, bufsz);
1549
#endif /* defined(BCMNVRAMR) */
1551
* Create variable table from memory.
1552
* Return 0 on success, nonzero on error.
1554
static int initvars_table(struct osl_info *osh, char *start, char *end,
1555
char **vars, uint *count)
1557
int c = (int)(end - start);
1559
/* do it only when there is more than just the null string */
1561
char *vp = kmalloc(c, GFP_ATOMIC);
1565
bcopy(start, vp, c);
1577
* Find variables with <devpath> from flash. 'base' points to the beginning
1578
* of the table upon enter and to the end of the table upon exit when success.
1579
* Return 0 on success, nonzero on error.
1581
static int initvars_flash(si_t *sih, struct osl_info *osh, char **base,
1588
uint l, dl, copy_len;
1589
char devpath[SI_DEVPATH_BUFSZ];
1591
/* allocate memory and read in flash */
1592
flash = kmalloc(NVRAM_SPACE, GFP_ATOMIC);
1595
err = nvram_getall(flash, NVRAM_SPACE);
1599
si_devpath(sih, devpath, sizeof(devpath));
1601
/* grab vars with the <devpath> prefix in name */
1602
dl = strlen(devpath);
1603
for (s = flash; s && *s; s += l + 1) {
1606
/* skip non-matching variable */
1607
if (strncmp(s, devpath, dl))
1610
/* is there enough room to copy? */
1611
copy_len = l - dl + 1;
1612
if (len < copy_len) {
1613
err = BCME_BUFTOOSHORT;
1617
/* no prefix, just the name=value */
1618
strncpy(vp, &s[dl], copy_len);
1623
/* add null string as terminator */
1625
err = BCME_BUFTOOSHORT;
1637
* Initialize nonvolatile variable table from flash.
1638
* Return 0 on success, nonzero on error.
1640
static int initvars_flash_si(si_t *sih, char **vars, uint *count)
1642
struct osl_info *osh = si_osh(sih);
1646
ASSERT(vars != NULL);
1647
ASSERT(count != NULL);
1649
base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
1654
err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS);
1656
err = initvars_table(osh, base, vp, vars, count);
1663
/* Parse SROM and create name=value pairs. 'srom' points to
1664
* the SROM word array. 'off' specifies the offset of the
1665
* first word 'srom' points to, which should be either 0 or
1666
* SROM3_SWRG_OFF (full SROM or software region).
1669
static uint mask_shift(u16 mask)
1672
for (i = 0; i < (sizeof(mask) << 3); i++) {
1673
if (mask & (1 << i))
1680
static uint mask_width(u16 mask)
1683
for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
1684
if (mask & (1 << i))
1685
return (uint) (i - mask_shift(mask) + 1);
1692
static bool mask_valid(u16 mask)
1694
uint shift = mask_shift(mask);
1695
uint width = mask_width(mask);
1696
return mask == ((~0 << shift) & ~(~0 << (shift + width)));
1700
static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b)
1704
const sromvar_t *srv;
1707
u32 sr = (1 << sromrev);
1709
varbuf_append(b, "sromrev=%d", sromrev);
1711
for (srv = pci_sromvars; srv->name != NULL; srv++) {
1714
if ((srv->revmask & sr) == 0)
1723
/* This entry is for mfgc only. Don't generate param for it, */
1724
if (flags & SRFL_NOVAR)
1727
if (flags & SRFL_ETHADDR) {
1728
struct ether_addr ea;
1730
ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff;
1731
ea.octet[1] = srom[srv->off - off] & 0xff;
1732
ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
1733
ea.octet[3] = srom[srv->off + 1 - off] & 0xff;
1734
ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
1735
ea.octet[5] = srom[srv->off + 2 - off] & 0xff;
1737
varbuf_append(b, "%s=%pM", name, ea.octet);
1739
ASSERT(mask_valid(srv->mask));
1740
ASSERT(mask_width(srv->mask));
1742
w = srom[srv->off - off];
1743
val = (w & srv->mask) >> mask_shift(srv->mask);
1744
width = mask_width(srv->mask);
1746
while (srv->flags & SRFL_MORE) {
1748
ASSERT(srv->name != NULL);
1750
if (srv->off == 0 || srv->off < off)
1753
ASSERT(mask_valid(srv->mask));
1754
ASSERT(mask_width(srv->mask));
1756
w = srom[srv->off - off];
1758
((w & srv->mask) >> mask_shift(srv->
1761
width += mask_width(srv->mask);
1764
if ((flags & SRFL_NOFFS)
1765
&& ((int)val == (1 << width) - 1))
1768
if (flags & SRFL_CCODE) {
1770
varbuf_append(b, "ccode=");
1772
varbuf_append(b, "ccode=%c%c",
1773
(val >> 8), (val & 0xff));
1775
/* LED Powersave duty cycle has to be scaled:
1776
*(oncount >> 24) (offcount >> 8)
1778
else if (flags & SRFL_LEDDC) {
1779
u32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
1780
(((val & 0xff)) << 8); /* offcount */
1781
varbuf_append(b, "leddc=%d", w32);
1782
} else if (flags & SRFL_PRHEX)
1783
varbuf_append(b, "%s=0x%x", name, val);
1784
else if ((flags & SRFL_PRSIGN)
1785
&& (val & (1 << (width - 1))))
1786
varbuf_append(b, "%s=%d", name,
1787
(int)(val | (~0 << width)));
1789
varbuf_append(b, "%s=%u", name, val);
1794
/* Do per-path variables */
1799
psz = SROM8_PATH1 - SROM8_PATH0;
1802
psz = SROM4_PATH1 - SROM4_PATH0;
1805
for (p = 0; p < MAX_PATH_SROM; p++) {
1806
for (srv = perpath_pci_sromvars; srv->name != NULL;
1808
if ((srv->revmask & sr) == 0)
1811
if (pb + srv->off < off)
1814
/* This entry is for mfgc only. Don't generate param for it, */
1815
if (srv->flags & SRFL_NOVAR)
1818
w = srom[pb + srv->off - off];
1820
ASSERT(mask_valid(srv->mask));
1821
val = (w & srv->mask) >> mask_shift(srv->mask);
1822
width = mask_width(srv->mask);
1824
/* Cheating: no per-path var is more than 1 word */
1826
if ((srv->flags & SRFL_NOFFS)
1827
&& ((int)val == (1 << width) - 1))
1830
if (srv->flags & SRFL_PRHEX)
1831
varbuf_append(b, "%s%d=0x%x", srv->name,
1834
varbuf_append(b, "%s%d=%d", srv->name,
1843
* Initialize nonvolatile variable table from sprom.
1844
* Return 0 on success, nonzero on error.
1846
static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
1848
u16 *srom, *sromwindow;
1852
char *vp, *base = NULL;
1853
struct osl_info *osh = si_osh(sih);
1858
* Apply CRC over SROM content regardless SROM is present or not,
1859
* and use variable <devpath>sromrev's existance in flash to decide
1860
* if we should return an error when CRC fails or read SROM variables
1863
srom = kmalloc(SROM_MAX, GFP_ATOMIC);
1864
ASSERT(srom != NULL);
1868
sromwindow = (u16 *) SROM_OFFSET(sih);
1869
if (si_is_sprom_available(sih)) {
1871
sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM_WORDS,
1874
if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
1875
(((sih->buscoretype == PCIE_CORE_ID)
1876
&& (sih->buscorerev >= 6))
1877
|| ((sih->buscoretype == PCI_CORE_ID)
1878
&& (sih->buscorerev >= 0xe)))) {
1879
/* sromrev >= 4, read more */
1881
sprom_read_pci(osh, sih, sromwindow, 0, srom,
1883
sromrev = srom[SROM4_CRCREV] & 0xff;
1885
BS_ERROR(("%s: srom %d, bad crc\n", __func__,
1888
} else if (err == 0) {
1889
/* srom is good and is rev < 4 */
1890
/* top word of sprom contains version and crc8 */
1891
sromrev = srom[SROM_CRCREV] & 0xff;
1892
/* bcm4401 sroms misprogrammed */
1893
if (sromrev == 0x10)
1897
#if defined(BCMNVRAMR)
1898
/* Use OTP if SPROM not available */
1899
else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) {
1900
/* OTP only contain SROM rev8/rev9 for now */
1901
sromrev = srom[SROM4_CRCREV] & 0xff;
1906
BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
1909
/* We want internal/wltest driver to come up with default sromvars so we can
1910
* program a blank SPROM/OTP.
1917
value = si_getdevpathvar(sih, "sromrev");
1919
sromrev = (u8) simple_strtoul(value, NULL, 0);
1924
BS_ERROR(("%s, SROM CRC Error\n", __func__));
1926
value = si_getnvramflvar(sih, "sromrev");
1939
/* Bitmask for the sromrev */
1942
/* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */
1943
if ((sr & 0x33e) == 0) {
1948
ASSERT(vars != NULL);
1949
ASSERT(count != NULL);
1951
base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
1958
/* read variables from flash */
1960
err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS);
1966
varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
1968
/* parse SROM into name=value pairs. */
1969
_initvars_srom_pci(sromrev, srom, 0, &b);
1971
/* final nullbyte terminator */
1972
ASSERT(b.size >= 1);
1976
ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
1979
err = initvars_table(osh, base, vp, vars, count);
1991
* Read the SDIO cis and call parsecis to initialize the vars.
1992
* Return 0 on success, nonzero on error.
1994
static int initvars_cis_sdio(struct osl_info *osh, char **vars, uint *count)
1996
u8 *cis[SBSDIO_NUM_FUNCTION + 1];
2000
numfn = bcmsdh_query_iofnum(NULL);
2001
ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
2003
for (fn = 0; fn <= numfn; fn++) {
2004
cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
2005
if (cis[fn] == NULL) {
2010
if (bcmsdh_cis_read(NULL, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT) !=
2019
rc = srom_parsecis(osh, cis, fn, vars, count);
2027
/* set SDIO sprom command register */
2028
static int sprom_cmd_sdio(struct osl_info *osh, u8 cmd)
2031
uint wait_cnt = 1000;
2033
/* write sprom command register */
2034
bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, cmd, NULL);
2037
while (wait_cnt--) {
2039
bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, NULL);
2040
if (status & SBSDIO_SPROM_DONE)
2047
/* read a word from the SDIO srom */
2048
static int sprom_read_sdio(struct osl_info *osh, u16 addr, u16 *data)
2050
u8 addr_l, addr_h, data_l, data_h;
2052
addr_l = (u8) ((addr * 2) & 0xff);
2053
addr_h = (u8) (((addr * 2) >> 8) & 0xff);
2056
bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h,
2058
bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l,
2062
if (sprom_cmd_sdio(osh, SBSDIO_SPROM_READ))
2067
bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, NULL);
2069
bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, NULL);
2071
*data = (data_h << 8) | data_l;
2074
#endif /* BCMSDIO */
2076
static int initvars_srom_si(si_t *sih, struct osl_info *osh, void *curmap,
2077
char **vars, uint *varsz)
2079
/* Search flash nvram section for srom variables */
2080
return initvars_flash_si(sih, vars, varsz);