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>
20 #include <linux/module.h>
21 #include <linux/pci.h>
30 #include <bcmsrom_tbl.h>
42 #include <sbsdpcmdev.h>
45 #include <linux/if_ether.h>
47 #define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
48 (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
49 ((u8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
50 ((u8 *)curmap + PCI_BAR0_SPROM_OFFSET))
53 #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
54 #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
57 typedef struct varbuf {
58 char *base; /* pointer to buffer base */
59 char *buf; /* pointer to current position */
60 unsigned int size; /* current (residual) size in bytes */
65 static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *count);
66 static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b);
67 static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count);
68 static int initvars_flash_si(si_t *sih, char **vars, uint *count);
70 static int initvars_cis_sdio(char **vars, uint *count);
71 static int sprom_cmd_sdio(u8 cmd);
72 static int sprom_read_sdio(u16 addr, u16 *data);
74 static int sprom_read_pci(si_t *sih, u16 *sprom,
75 uint wordoff, u16 *buf, uint nwords, bool check_crc);
76 #if defined(BCMNVRAMR)
77 static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz);
79 static u16 srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
80 uint wordoff, u16 data);
82 static int initvars_table(char *start, char *end,
83 char **vars, uint *count);
84 static int initvars_flash(si_t *sih, char **vp,
87 /* Initialization of varbuf structure */
88 static void varbuf_init(varbuf_t *b, char *buf, uint size)
91 b->base = b->buf = buf;
94 /* append a null terminated var=value string */
95 static int varbuf_append(varbuf_t *b, const char *fmt, ...)
106 r = vsnprintf(b->buf, b->size, fmt, ap);
109 /* C99 snprintf behavior returns r >= size on overflow,
110 * others return -1 on overflow.
111 * All return -1 on format error.
112 * We need to leave room for 2 null terminations, one for the current var
113 * string, and one for final null of the var table. So check that the
114 * strlen written, r, leaves room for 2 chars.
116 if ((r == -1) || (r > (int)(b->size - 2))) {
121 /* Remove any earlier occurrence of the same variable */
122 s = strchr(b->buf, '=');
124 len = (size_t) (s - b->buf);
125 for (s = b->base; s < b->buf;) {
126 if ((memcmp(s, b->buf, len) == 0) && s[len] == '=') {
128 memmove(s, (s + len),
129 ((b->buf + r + 1) - (s + len)));
131 b->size += (unsigned int)len;
140 /* skip over this string's null termination */
149 * Initialize local vars from the right source for this platform.
150 * Return 0 on success, nonzero on error.
152 int srom_var_init(si_t *sih, uint bustype, void *curmap,
153 char **vars, uint *count)
159 ASSERT(bustype == bustype);
160 if (vars == NULL || count == NULL)
169 return initvars_srom_si(sih, curmap, vars, count);
172 ASSERT(curmap != NULL);
176 return initvars_srom_pci(sih, curmap, vars, count);
180 return initvars_cis_sdio(vars, count);
189 /* support only 16-bit word read from srom */
191 srom_read(si_t *sih, uint bustype, void *curmap,
192 uint byteoff, uint nbytes, u16 *buf, bool check_crc)
199 ASSERT(bustype == bustype);
201 /* check input - 16-bit access only */
202 if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX)
208 if (bustype == PCI_BUS) {
212 if (si_is_sprom_available(sih)) {
215 srom = (u16 *) SROM_OFFSET(sih);
220 (sih, srom, off, buf, nw, check_crc))
223 #if defined(BCMNVRAMR)
225 if (otp_read_pci(sih, buf, SROM_MAX))
230 } else if (bustype == SDIO_BUS) {
233 for (i = 0; i < nw; i++) {
235 ((u16) (off + i), (u16 *) (buf + i)))
239 } else if (bustype == SI_BUS) {
248 static const char vstr_manf[] = "manf=%s";
249 static const char vstr_productname[] = "productname=%s";
250 static const char vstr_manfid[] = "manfid=0x%x";
251 static const char vstr_prodid[] = "prodid=0x%x";
253 static const char vstr_sdmaxspeed[] = "sdmaxspeed=%d";
254 static const char vstr_sdmaxblk[][13] = {
255 "sdmaxblk0=%d", "sdmaxblk1=%d", "sdmaxblk2=%d"};
257 static const char vstr_regwindowsz[] = "regwindowsz=%d";
258 static const char vstr_sromrev[] = "sromrev=%d";
259 static const char vstr_chiprev[] = "chiprev=%d";
260 static const char vstr_subvendid[] = "subvendid=0x%x";
261 static const char vstr_subdevid[] = "subdevid=0x%x";
262 static const char vstr_boardrev[] = "boardrev=0x%x";
263 static const char vstr_aa2g[] = "aa2g=0x%x";
264 static const char vstr_aa5g[] = "aa5g=0x%x";
265 static const char vstr_ag[] = "ag%d=0x%x";
266 static const char vstr_cc[] = "cc=%d";
267 static const char vstr_opo[] = "opo=%d";
268 static const char vstr_pa0b[][9] = {
269 "pa0b0=%d", "pa0b1=%d", "pa0b2=%d"};
271 static const char vstr_pa0itssit[] = "pa0itssit=%d";
272 static const char vstr_pa0maxpwr[] = "pa0maxpwr=%d";
273 static const char vstr_pa1b[][9] = {
274 "pa1b0=%d", "pa1b1=%d", "pa1b2=%d"};
276 static const char vstr_pa1lob[][11] = {
277 "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d"};
279 static const char vstr_pa1hib[][11] = {
280 "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d"};
282 static const char vstr_pa1itssit[] = "pa1itssit=%d";
283 static const char vstr_pa1maxpwr[] = "pa1maxpwr=%d";
284 static const char vstr_pa1lomaxpwr[] = "pa1lomaxpwr=%d";
285 static const char vstr_pa1himaxpwr[] = "pa1himaxpwr=%d";
286 static const char vstr_oem[] =
287 "oem=%02x%02x%02x%02x%02x%02x%02x%02x";
288 static const char vstr_boardflags[] = "boardflags=0x%x";
289 static const char vstr_boardflags2[] = "boardflags2=0x%x";
290 static const char vstr_ledbh[] = "ledbh%d=0x%x";
291 static const char vstr_noccode[] = "ccode=0x0";
292 static const char vstr_ccode[] = "ccode=%c%c";
293 static const char vstr_cctl[] = "cctl=0x%x";
294 static const char vstr_cckpo[] = "cckpo=0x%x";
295 static const char vstr_ofdmpo[] = "ofdmpo=0x%x";
296 static const char vstr_rdlid[] = "rdlid=0x%x";
297 static const char vstr_rdlrndis[] = "rdlrndis=%d";
298 static const char vstr_rdlrwu[] = "rdlrwu=%d";
299 static const char vstr_usbfs[] = "usbfs=%d";
300 static const char vstr_wpsgpio[] = "wpsgpio=%d";
301 static const char vstr_wpsled[] = "wpsled=%d";
302 static const char vstr_rdlsn[] = "rdlsn=%d";
303 static const char vstr_rssismf2g[] = "rssismf2g=%d";
304 static const char vstr_rssismc2g[] = "rssismc2g=%d";
305 static const char vstr_rssisav2g[] = "rssisav2g=%d";
306 static const char vstr_bxa2g[] = "bxa2g=%d";
307 static const char vstr_rssismf5g[] = "rssismf5g=%d";
308 static const char vstr_rssismc5g[] = "rssismc5g=%d";
309 static const char vstr_rssisav5g[] = "rssisav5g=%d";
310 static const char vstr_bxa5g[] = "bxa5g=%d";
311 static const char vstr_tri2g[] = "tri2g=%d";
312 static const char vstr_tri5gl[] = "tri5gl=%d";
313 static const char vstr_tri5g[] = "tri5g=%d";
314 static const char vstr_tri5gh[] = "tri5gh=%d";
315 static const char vstr_rxpo2g[] = "rxpo2g=%d";
316 static const char vstr_rxpo5g[] = "rxpo5g=%d";
317 static const char vstr_boardtype[] = "boardtype=0x%x";
318 static const char vstr_leddc[] = "leddc=0x%04x";
319 static const char vstr_vendid[] = "vendid=0x%x";
320 static const char vstr_devid[] = "devid=0x%x";
321 static const char vstr_xtalfreq[] = "xtalfreq=%d";
322 static const char vstr_txchain[] = "txchain=0x%x";
323 static const char vstr_rxchain[] = "rxchain=0x%x";
324 static const char vstr_antswitch[] = "antswitch=0x%x";
325 static const char vstr_regrev[] = "regrev=0x%x";
326 static const char vstr_antswctl2g[] = "antswctl2g=0x%x";
327 static const char vstr_triso2g[] = "triso2g=0x%x";
328 static const char vstr_pdetrange2g[] = "pdetrange2g=0x%x";
329 static const char vstr_extpagain2g[] = "extpagain2g=0x%x";
330 static const char vstr_tssipos2g[] = "tssipos2g=0x%x";
331 static const char vstr_antswctl5g[] = "antswctl5g=0x%x";
332 static const char vstr_triso5g[] = "triso5g=0x%x";
333 static const char vstr_pdetrange5g[] = "pdetrange5g=0x%x";
334 static const char vstr_extpagain5g[] = "extpagain5g=0x%x";
335 static const char vstr_tssipos5g[] = "tssipos5g=0x%x";
336 static const char vstr_maxp2ga0[] = "maxp2ga0=0x%x";
337 static const char vstr_itt2ga0[] = "itt2ga0=0x%x";
338 static const char vstr_pa[] = "pa%dgw%da%d=0x%x";
339 static const char vstr_pahl[] = "pa%dg%cw%da%d=0x%x";
340 static const char vstr_maxp5ga0[] = "maxp5ga0=0x%x";
341 static const char vstr_itt5ga0[] = "itt5ga0=0x%x";
342 static const char vstr_maxp5gha0[] = "maxp5gha0=0x%x";
343 static const char vstr_maxp5gla0[] = "maxp5gla0=0x%x";
344 static const char vstr_maxp2ga1[] = "maxp2ga1=0x%x";
345 static const char vstr_itt2ga1[] = "itt2ga1=0x%x";
346 static const char vstr_maxp5ga1[] = "maxp5ga1=0x%x";
347 static const char vstr_itt5ga1[] = "itt5ga1=0x%x";
348 static const char vstr_maxp5gha1[] = "maxp5gha1=0x%x";
349 static const char vstr_maxp5gla1[] = "maxp5gla1=0x%x";
350 static const char vstr_cck2gpo[] = "cck2gpo=0x%x";
351 static const char vstr_ofdm2gpo[] = "ofdm2gpo=0x%x";
352 static const char vstr_ofdm5gpo[] = "ofdm5gpo=0x%x";
353 static const char vstr_ofdm5glpo[] = "ofdm5glpo=0x%x";
354 static const char vstr_ofdm5ghpo[] = "ofdm5ghpo=0x%x";
355 static const char vstr_cddpo[] = "cddpo=0x%x";
356 static const char vstr_stbcpo[] = "stbcpo=0x%x";
357 static const char vstr_bw40po[] = "bw40po=0x%x";
358 static const char vstr_bwduppo[] = "bwduppo=0x%x";
359 static const char vstr_mcspo[] = "mcs%dgpo%d=0x%x";
360 static const char vstr_mcspohl[] = "mcs%dg%cpo%d=0x%x";
361 static const char vstr_custom[] = "customvar%d=0x%x";
362 static const char vstr_cckdigfilttype[] = "cckdigfilttype=%d";
363 static const char vstr_boardnum[] = "boardnum=%d";
364 static const char vstr_macaddr[] = "macaddr=%s";
365 static const char vstr_usbepnum[] = "usbepnum=0x%x";
366 static const char vstr_end[] = "END\0";
370 /* For dongle HW, accept partial calibration parameters */
371 #define BCMDONGLECASE(n)
373 int srom_parsecis(u8 *pcis[], uint ciscnt, char **vars,
379 u8 *cis, tup, tlen, sromrev = 1;
381 bool ag_init = false;
389 ASSERT(vars != NULL);
390 ASSERT(count != NULL);
394 base = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
395 ASSERT(base != NULL);
399 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
400 memset(base, 0, MAXSZ_NVRAM_VARS);
402 for (cisnum = 0; cisnum < ciscnt; cisnum++) {
410 if (tup == CISTPL_NULL || tup == CISTPL_END)
415 if (cis[i] == CISTPL_NULL
416 || cis[i] == CISTPL_END) {
421 tup = CISTPL_BRCM_HNBU;
425 if ((i + tlen) >= CIS_SIZE)
430 /* assume the strings are good if the version field checks out */
431 if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) {
432 varbuf_append(&b, vstr_manf,
434 varbuf_append(&b, vstr_productname,
443 varbuf_append(&b, vstr_manfid,
444 (cis[i + 1] << 8) + cis[i]);
445 varbuf_append(&b, vstr_prodid,
446 (cis[i + 3] << 8) + cis[i + 2]);
455 case CISTPL_FID_SDIO:
459 static int base[] = {
460 -1, 10, 12, 13, 15, 20,
462 35, 40, 45, 50, 55, 60,
465 static int mult[] = {
466 10, 100, 1000, 10000,
469 ASSERT((mult[spd & 0x7] != -1)
472 [(spd >> 3) & 0x0f]));
482 } else if (cis[i] == 1) {
493 /* set macaddr if HNBU_MACADDR not seen yet */
494 if (eabuf[0] == '\0' &&
496 !is_zero_ether_addr(&cis[i + 2]) &&
497 !is_multicast_ether_addr(&cis[i + 2])) {
500 snprintf(eabuf, sizeof(eabuf),
503 /* set boardnum if HNBU_BOARDNUM not seen yet */
514 varbuf_append(&b, vstr_regwindowsz,
515 (cis[i + 7] << 8) | cis[i + 6]);
518 case CISTPL_BRCM_HNBU:
521 sromrev = cis[i + 1];
522 varbuf_append(&b, vstr_sromrev,
527 varbuf_append(&b, vstr_xtalfreq,
535 varbuf_append(&b, vstr_vendid,
538 varbuf_append(&b, vstr_devid,
542 varbuf_append(&b, vstr_chiprev,
553 varbuf_append(&b, vstr_subdevid,
556 /* subdevid doubles for boardtype */
566 (cis[i + 2] << 8) + cis[i + 1];
574 /* retrieve the patch pairs
575 * from tlen/6; where 6 is
576 * sizeof(patch addr(2)) +
577 * sizeof(patch data(4)).
579 patch_pair = tlen / 6;
581 for (j = 0; j < patch_pair; j++) {
636 varbuf_append(&b, vstr_boardrev,
639 varbuf_append(&b, vstr_boardrev,
644 case HNBU_BOARDFLAGS:
645 w32 = (cis[i + 2] << 8) + cis[i + 1];
648 ((cis[i + 4] << 24) +
650 varbuf_append(&b, vstr_boardflags, w32);
654 (cis[i + 6] << 8) + cis[i +
669 varbuf_append(&b, vstr_usbfs,
674 varbuf_append(&b, vstr_boardtype,
681 * what follows is a nonstandard HNBU CIS
682 * that lacks CISTPL_BRCM_HNBU tags
684 * skip 0xff (end of standard CIS)
688 standard_cis = false;
692 varbuf_append(&b, vstr_usbepnum,
693 (cis[i + 2] << 8) | cis[i
699 varbuf_append(&b, vstr_aa2g,
702 varbuf_append(&b, vstr_aa5g,
707 varbuf_append(&b, vstr_ag, 0,
710 varbuf_append(&b, vstr_ag, 1,
713 varbuf_append(&b, vstr_ag, 2,
716 varbuf_append(&b, vstr_ag, 3,
722 varbuf_append(&b, vstr_aa5g,
724 varbuf_append(&b, vstr_ag, 1,
729 ASSERT(sromrev == 1);
730 varbuf_append(&b, vstr_cc, cis[i + 1]);
736 ASSERT(sromrev == 1);
742 ASSERT(sromrev >= 2);
743 varbuf_append(&b, vstr_opo,
757 for (j = 0; j < 3; j++) {
782 ASSERT((sromrev == 2)
802 for (j = 0; j < 3; j++) {
817 for (j = 3; j < 6; j++) {
832 for (j = 6; j < 9; j++) {
849 ASSERT((tlen == 19) ||
857 ASSERT(sromrev == 1);
858 varbuf_append(&b, vstr_oem,
859 cis[i + 1], cis[i + 2],
860 cis[i + 3], cis[i + 4],
861 cis[i + 5], cis[i + 6],
862 cis[i + 7], cis[i + 8]);
866 for (j = 1; j <= 4; j++) {
867 if (cis[i + j] != 0xff) {
879 if ((cis[i + 1] == 0)
880 || (cis[i + 2] == 0))
881 varbuf_append(&b, vstr_noccode);
883 varbuf_append(&b, vstr_ccode,
886 varbuf_append(&b, vstr_cctl,
892 varbuf_append(&b, vstr_cckpo,
893 (cis[i + 2] << 8) | cis[i
900 varbuf_append(&b, vstr_ofdmpo,
908 varbuf_append(&b, vstr_wpsgpio,
911 varbuf_append(&b, vstr_wpsled,
915 case HNBU_RSSISMBXA2G:
916 ASSERT(sromrev == 3);
917 varbuf_append(&b, vstr_rssismf2g,
919 varbuf_append(&b, vstr_rssismc2g,
920 (cis[i + 1] >> 4) & 0xf);
921 varbuf_append(&b, vstr_rssisav2g,
923 varbuf_append(&b, vstr_bxa2g,
924 (cis[i + 2] >> 3) & 0x3);
927 case HNBU_RSSISMBXA5G:
928 ASSERT(sromrev == 3);
929 varbuf_append(&b, vstr_rssismf5g,
931 varbuf_append(&b, vstr_rssismc5g,
932 (cis[i + 1] >> 4) & 0xf);
933 varbuf_append(&b, vstr_rssisav5g,
935 varbuf_append(&b, vstr_bxa5g,
936 (cis[i + 2] >> 3) & 0x3);
940 ASSERT(sromrev == 3);
941 varbuf_append(&b, vstr_tri2g,
946 ASSERT(sromrev == 3);
947 varbuf_append(&b, vstr_tri5gl,
949 varbuf_append(&b, vstr_tri5g,
951 varbuf_append(&b, vstr_tri5gh,
956 ASSERT(sromrev == 3);
957 varbuf_append(&b, vstr_rxpo2g,
962 ASSERT(sromrev == 3);
963 varbuf_append(&b, vstr_rxpo5g,
968 if (!is_zero_ether_addr(&cis[i + 1]) &&
969 !is_multicast_ether_addr(&cis[i + 1])) {
970 snprintf(eabuf, sizeof(eabuf),
973 /* set boardnum if HNBU_BOARDNUM not seen yet */
982 /* CIS leddc only has 16bits, convert it to 32bits */
983 w32 = ((cis[i + 2] << 24) | /* oncount */
984 (cis[i + 1] << 8)); /* offcount */
985 varbuf_append(&b, vstr_leddc, w32);
988 case HNBU_CHAINSWITCH:
989 varbuf_append(&b, vstr_txchain,
991 varbuf_append(&b, vstr_rxchain,
993 varbuf_append(&b, vstr_antswitch,
999 varbuf_append(&b, vstr_regrev,
1005 (cis[i + 2] << 8) + cis[i +
1010 SROM8_FEM_ANTSWLUT_MASK)
1012 SROM8_FEM_ANTSWLUT_SHIFT);
1013 varbuf_append(&b, vstr_triso2g,
1015 SROM8_FEM_TR_ISO_MASK)
1017 SROM8_FEM_TR_ISO_SHIFT);
1021 SROM8_FEM_PDET_RANGE_MASK)
1023 SROM8_FEM_PDET_RANGE_SHIFT);
1027 SROM8_FEM_EXTPA_GAIN_MASK)
1029 SROM8_FEM_EXTPA_GAIN_SHIFT);
1033 SROM8_FEM_TSSIPOS_MASK)
1035 SROM8_FEM_TSSIPOS_SHIFT);
1040 (cis[i + 4] << 8) + cis[i +
1045 SROM8_FEM_ANTSWLUT_MASK)
1047 SROM8_FEM_ANTSWLUT_SHIFT);
1048 varbuf_append(&b, vstr_triso5g,
1050 SROM8_FEM_TR_ISO_MASK)
1052 SROM8_FEM_TR_ISO_SHIFT);
1056 SROM8_FEM_PDET_RANGE_MASK)
1058 SROM8_FEM_PDET_RANGE_SHIFT);
1062 SROM8_FEM_EXTPA_GAIN_MASK)
1064 SROM8_FEM_EXTPA_GAIN_SHIFT);
1068 SROM8_FEM_TSSIPOS_MASK)
1070 SROM8_FEM_TSSIPOS_SHIFT);
1074 case HNBU_PAPARMS_C0:
1075 varbuf_append(&b, vstr_maxp2ga0,
1077 varbuf_append(&b, vstr_itt2ga0,
1079 varbuf_append(&b, vstr_pa, 2, 0, 0,
1082 varbuf_append(&b, vstr_pa, 2, 1, 0,
1085 varbuf_append(&b, vstr_pa, 2, 2, 0,
1091 varbuf_append(&b, vstr_maxp5ga0,
1093 varbuf_append(&b, vstr_itt5ga0,
1095 varbuf_append(&b, vstr_maxp5gha0,
1097 varbuf_append(&b, vstr_maxp5gla0,
1099 varbuf_append(&b, vstr_pa, 5, 0, 0,
1100 (cis[i + 14] << 8) +
1102 varbuf_append(&b, vstr_pa, 5, 1, 0,
1103 (cis[i + 16] << 8) +
1105 varbuf_append(&b, vstr_pa, 5, 2, 0,
1106 (cis[i + 18] << 8) +
1108 varbuf_append(&b, vstr_pahl, 5, 'l', 0,
1110 (cis[i + 20] << 8) +
1112 varbuf_append(&b, vstr_pahl, 5, 'l', 1,
1114 (cis[i + 22] << 8) +
1116 varbuf_append(&b, vstr_pahl, 5, 'l', 2,
1118 (cis[i + 24] << 8) +
1120 varbuf_append(&b, vstr_pahl, 5, 'h', 0,
1122 (cis[i + 26] << 8) +
1124 varbuf_append(&b, vstr_pahl, 5, 'h', 1,
1126 (cis[i + 28] << 8) +
1128 varbuf_append(&b, vstr_pahl, 5, 'h', 2,
1130 (cis[i + 30] << 8) +
1134 case HNBU_PAPARMS_C1:
1135 varbuf_append(&b, vstr_maxp2ga1,
1137 varbuf_append(&b, vstr_itt2ga1,
1139 varbuf_append(&b, vstr_pa, 2, 0, 1,
1142 varbuf_append(&b, vstr_pa, 2, 1, 1,
1145 varbuf_append(&b, vstr_pa, 2, 2, 1,
1151 varbuf_append(&b, vstr_maxp5ga1,
1153 varbuf_append(&b, vstr_itt5ga1,
1155 varbuf_append(&b, vstr_maxp5gha1,
1157 varbuf_append(&b, vstr_maxp5gla1,
1159 varbuf_append(&b, vstr_pa, 5, 0, 1,
1160 (cis[i + 14] << 8) +
1162 varbuf_append(&b, vstr_pa, 5, 1, 1,
1163 (cis[i + 16] << 8) +
1165 varbuf_append(&b, vstr_pa, 5, 2, 1,
1166 (cis[i + 18] << 8) +
1168 varbuf_append(&b, vstr_pahl, 5, 'l', 0,
1170 (cis[i + 20] << 8) +
1172 varbuf_append(&b, vstr_pahl, 5, 'l', 1,
1174 (cis[i + 22] << 8) +
1176 varbuf_append(&b, vstr_pahl, 5, 'l', 2,
1178 (cis[i + 24] << 8) +
1180 varbuf_append(&b, vstr_pahl, 5, 'h', 0,
1182 (cis[i + 26] << 8) +
1184 varbuf_append(&b, vstr_pahl, 5, 'h', 1,
1186 (cis[i + 28] << 8) +
1188 varbuf_append(&b, vstr_pahl, 5, 'h', 2,
1190 (cis[i + 30] << 8) +
1194 case HNBU_PO_CCKOFDM:
1195 varbuf_append(&b, vstr_cck2gpo,
1198 varbuf_append(&b, vstr_ofdm2gpo,
1199 (cis[i + 6] << 24) +
1200 (cis[i + 5] << 16) +
1206 varbuf_append(&b, vstr_ofdm5gpo,
1207 (cis[i + 10] << 24) +
1208 (cis[i + 9] << 16) +
1211 varbuf_append(&b, vstr_ofdm5glpo,
1212 (cis[i + 14] << 24) +
1213 (cis[i + 13] << 16) +
1214 (cis[i + 12] << 8) +
1216 varbuf_append(&b, vstr_ofdm5ghpo,
1217 (cis[i + 18] << 24) +
1218 (cis[i + 17] << 16) +
1219 (cis[i + 16] << 8) +
1224 for (j = 0; j <= (tlen / 2); j++) {
1225 varbuf_append(&b, vstr_mcspo, 2,
1235 case HNBU_PO_MCS5GM:
1236 for (j = 0; j <= (tlen / 2); j++) {
1237 varbuf_append(&b, vstr_mcspo, 5,
1247 case HNBU_PO_MCS5GLH:
1248 for (j = 0; j <= (tlen / 4); j++) {
1249 varbuf_append(&b, vstr_mcspohl,
1258 for (j = 0; j <= (tlen / 4); j++) {
1259 varbuf_append(&b, vstr_mcspohl,
1274 varbuf_append(&b, vstr_cddpo,
1280 varbuf_append(&b, vstr_stbcpo,
1286 varbuf_append(&b, vstr_bw40po,
1291 case HNBU_PO_40MDUP:
1292 varbuf_append(&b, vstr_bwduppo,
1298 varbuf_append(&b, vstr_ofdm5gpo,
1299 (cis[i + 4] << 24) +
1300 (cis[i + 3] << 16) +
1303 varbuf_append(&b, vstr_ofdm5glpo,
1304 (cis[i + 8] << 24) +
1305 (cis[i + 7] << 16) +
1308 varbuf_append(&b, vstr_ofdm5ghpo,
1309 (cis[i + 12] << 24) +
1310 (cis[i + 11] << 16) +
1311 (cis[i + 10] << 8) +
1316 varbuf_append(&b, vstr_custom, 1,
1317 ((cis[i + 4] << 24) +
1318 (cis[i + 3] << 16) +
1323 #if defined(BCMSDIO)
1324 case HNBU_SROM3SWRGN:
1327 u8 srev = cis[i + 1 + 70];
1329 /* make tuple value 16-bit aligned and parse it */
1330 memcpy(srom, &cis[i + 1],
1332 _initvars_srom_pci(srev, srom,
1335 /* 2.4G antenna gain is included in SROM */
1337 /* Ethernet MAC address is included in SROM */
1341 /* create extra variables */
1343 varbuf_append(&b, vstr_vendid,
1349 varbuf_append(&b, vstr_devid,
1355 varbuf_append(&b, vstr_xtalfreq,
1361 #endif /* defined(BCMSDIO) */
1363 case HNBU_CCKFILTTYPE:
1364 varbuf_append(&b, vstr_cckdigfilttype,
1372 } while (tup != CISTPL_END);
1375 if (boardnum != -1) {
1376 varbuf_append(&b, vstr_boardnum, boardnum);
1380 varbuf_append(&b, vstr_macaddr, eabuf);
1383 /* if there is no antenna gain field, set default */
1384 if (getvar(NULL, "ag0") == NULL && ag_init == false) {
1385 varbuf_append(&b, vstr_ag, 0, 0xff);
1388 /* final nullbyte terminator */
1389 ASSERT(b.size >= 1);
1392 ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS);
1393 err = initvars_table(base, b.buf, vars, count);
1399 /* In chips with chipcommon rev 32 and later, the srom is in chipcommon,
1400 * not in the bus cores.
1403 srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
1404 uint wordoff, u16 data)
1406 chipcregs_t *cc = (chipcregs_t *) ccregs;
1407 uint wait_cnt = 1000;
1409 if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
1410 W_REG(&cc->sromaddress, wordoff * 2);
1411 if (cmd == SRC_OP_WRITE)
1412 W_REG(&cc->sromdata, data);
1415 W_REG(&cc->sromcontrol, SRC_START | cmd);
1417 while (wait_cnt--) {
1418 if ((R_REG(&cc->sromcontrol) & SRC_BUSY) == 0)
1425 if (cmd == SRC_OP_READ)
1426 return (u16) R_REG(&cc->sromdata);
1431 static inline void ltoh16_buf(u16 *buf, unsigned int size)
1433 for (size /= 2; size; size--)
1434 *(buf + size) = le16_to_cpu(*(buf + size));
1437 static inline void htol16_buf(u16 *buf, unsigned int size)
1439 for (size /= 2; size; size--)
1440 *(buf + size) = cpu_to_le16(*(buf + size));
1444 * Read in and validate sprom.
1445 * Return 0 on success, nonzero on error.
1448 sprom_read_pci(si_t *sih, u16 *sprom, uint wordoff,
1449 u16 *buf, uint nwords, bool check_crc)
1453 void *ccregs = NULL;
1455 /* read the sprom */
1456 for (i = 0; i < nwords; i++) {
1458 if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
1459 /* use indirect since direct is too slow on QT */
1460 if ((sih->cccaps & CC_CAP_SROM) == 0)
1463 ccregs = (void *)((u8 *) sprom - CC_SROM_OTP);
1465 srom_cc_cmd(sih, ccregs, SRC_OP_READ,
1469 if (ISSIM_ENAB(sih))
1470 buf[i] = R_REG(&sprom[wordoff + i]);
1472 buf[i] = R_REG(&sprom[wordoff + i]);
1477 /* bypass crc checking for simulation to allow srom hack */
1478 if (ISSIM_ENAB(sih))
1483 if (buf[0] == 0xffff) {
1484 /* The hardware thinks that an srom that starts with 0xffff
1485 * is blank, regardless of the rest of the content, so declare
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 */
1498 /* now correct the endianness of the byte array */
1499 ltoh16_buf(buf, nwords * 2);
1504 #if defined(BCMNVRAMR)
1505 static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz)
1508 uint sz = OTP_SZ_MAX / 2; /* size in words */
1511 ASSERT(bufsz <= OTP_SZ_MAX);
1513 otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
1518 err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
1520 memcpy(buf, otp, bufsz);
1525 if (buf[0] == 0xffff) {
1526 /* The hardware thinks that an srom that starts with 0xffff
1527 * is blank, regardless of the rest of the content, so declare
1533 /* fixup the endianness so crc8 will pass */
1534 htol16_buf(buf, bufsz);
1535 if (hndcrc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
1539 /* now correct the endianness of the byte array */
1540 ltoh16_buf(buf, bufsz);
1544 #endif /* defined(BCMNVRAMR) */
1546 * Create variable table from memory.
1547 * Return 0 on success, nonzero on error.
1549 static int initvars_table(char *start, char *end,
1550 char **vars, uint *count)
1552 int c = (int)(end - start);
1554 /* do it only when there is more than just the null string */
1556 char *vp = kmalloc(c, GFP_ATOMIC);
1560 memcpy(vp, start, c);
1572 * Find variables with <devpath> from flash. 'base' points to the beginning
1573 * of the table upon enter and to the end of the table upon exit when success.
1574 * Return 0 on success, nonzero on error.
1576 static int initvars_flash(si_t *sih, char **base, uint len)
1582 uint l, dl, copy_len;
1583 char devpath[SI_DEVPATH_BUFSZ];
1585 /* allocate memory and read in flash */
1586 flash = kmalloc(NVRAM_SPACE, GFP_ATOMIC);
1589 err = nvram_getall(flash, NVRAM_SPACE);
1593 si_devpath(sih, devpath, sizeof(devpath));
1595 /* grab vars with the <devpath> prefix in name */
1596 dl = strlen(devpath);
1597 for (s = flash; s && *s; s += l + 1) {
1600 /* skip non-matching variable */
1601 if (strncmp(s, devpath, dl))
1604 /* is there enough room to copy? */
1605 copy_len = l - dl + 1;
1606 if (len < copy_len) {
1607 err = BCME_BUFTOOSHORT;
1611 /* no prefix, just the name=value */
1612 strncpy(vp, &s[dl], copy_len);
1617 /* add null string as terminator */
1619 err = BCME_BUFTOOSHORT;
1631 * Initialize nonvolatile variable table from flash.
1632 * Return 0 on success, nonzero on error.
1634 static int initvars_flash_si(si_t *sih, char **vars, uint *count)
1639 ASSERT(vars != NULL);
1640 ASSERT(count != NULL);
1642 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
1647 err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
1649 err = initvars_table(base, vp, vars, count);
1656 /* Parse SROM and create name=value pairs. 'srom' points to
1657 * the SROM word array. 'off' specifies the offset of the
1658 * first word 'srom' points to, which should be either 0 or
1659 * SROM3_SWRG_OFF (full SROM or software region).
1662 static uint mask_shift(u16 mask)
1665 for (i = 0; i < (sizeof(mask) << 3); i++) {
1666 if (mask & (1 << i))
1673 static uint mask_width(u16 mask)
1676 for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
1677 if (mask & (1 << i))
1678 return (uint) (i - mask_shift(mask) + 1);
1685 static bool mask_valid(u16 mask)
1687 uint shift = mask_shift(mask);
1688 uint width = mask_width(mask);
1689 return mask == ((~0 << shift) & ~(~0 << (shift + width)));
1693 static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b)
1697 const sromvar_t *srv;
1700 u32 sr = (1 << sromrev);
1702 varbuf_append(b, "sromrev=%d", sromrev);
1704 for (srv = pci_sromvars; srv->name != NULL; srv++) {
1707 if ((srv->revmask & sr) == 0)
1716 /* This entry is for mfgc only. Don't generate param for it, */
1717 if (flags & SRFL_NOVAR)
1720 if (flags & SRFL_ETHADDR) {
1723 ea[0] = (srom[srv->off - off] >> 8) & 0xff;
1724 ea[1] = srom[srv->off - off] & 0xff;
1725 ea[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
1726 ea[3] = srom[srv->off + 1 - off] & 0xff;
1727 ea[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
1728 ea[5] = srom[srv->off + 2 - off] & 0xff;
1730 varbuf_append(b, "%s=%pM", name, ea);
1732 ASSERT(mask_valid(srv->mask));
1733 ASSERT(mask_width(srv->mask));
1735 w = srom[srv->off - off];
1736 val = (w & srv->mask) >> mask_shift(srv->mask);
1737 width = mask_width(srv->mask);
1739 while (srv->flags & SRFL_MORE) {
1741 ASSERT(srv->name != NULL);
1743 if (srv->off == 0 || srv->off < off)
1746 ASSERT(mask_valid(srv->mask));
1747 ASSERT(mask_width(srv->mask));
1749 w = srom[srv->off - off];
1751 ((w & srv->mask) >> mask_shift(srv->
1754 width += mask_width(srv->mask);
1757 if ((flags & SRFL_NOFFS)
1758 && ((int)val == (1 << width) - 1))
1761 if (flags & SRFL_CCODE) {
1763 varbuf_append(b, "ccode=");
1765 varbuf_append(b, "ccode=%c%c",
1766 (val >> 8), (val & 0xff));
1768 /* LED Powersave duty cycle has to be scaled:
1769 *(oncount >> 24) (offcount >> 8)
1771 else if (flags & SRFL_LEDDC) {
1772 u32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
1773 (((val & 0xff)) << 8); /* offcount */
1774 varbuf_append(b, "leddc=%d", w32);
1775 } else if (flags & SRFL_PRHEX)
1776 varbuf_append(b, "%s=0x%x", name, val);
1777 else if ((flags & SRFL_PRSIGN)
1778 && (val & (1 << (width - 1))))
1779 varbuf_append(b, "%s=%d", name,
1780 (int)(val | (~0 << width)));
1782 varbuf_append(b, "%s=%u", name, val);
1787 /* Do per-path variables */
1792 psz = SROM8_PATH1 - SROM8_PATH0;
1795 psz = SROM4_PATH1 - SROM4_PATH0;
1798 for (p = 0; p < MAX_PATH_SROM; p++) {
1799 for (srv = perpath_pci_sromvars; srv->name != NULL;
1801 if ((srv->revmask & sr) == 0)
1804 if (pb + srv->off < off)
1807 /* This entry is for mfgc only. Don't generate param for it, */
1808 if (srv->flags & SRFL_NOVAR)
1811 w = srom[pb + srv->off - off];
1813 ASSERT(mask_valid(srv->mask));
1814 val = (w & srv->mask) >> mask_shift(srv->mask);
1815 width = mask_width(srv->mask);
1817 /* Cheating: no per-path var is more than 1 word */
1819 if ((srv->flags & SRFL_NOFFS)
1820 && ((int)val == (1 << width) - 1))
1823 if (srv->flags & SRFL_PRHEX)
1824 varbuf_append(b, "%s%d=0x%x", srv->name,
1827 varbuf_append(b, "%s%d=%d", srv->name,
1836 * Initialize nonvolatile variable table from sprom.
1837 * Return 0 on success, nonzero on error.
1839 static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
1841 u16 *srom, *sromwindow;
1845 char *vp, *base = NULL;
1850 * Apply CRC over SROM content regardless SROM is present or not,
1851 * and use variable <devpath>sromrev's existance in flash to decide
1852 * if we should return an error when CRC fails or read SROM variables
1855 srom = kmalloc(SROM_MAX, GFP_ATOMIC);
1856 ASSERT(srom != NULL);
1860 sromwindow = (u16 *) SROM_OFFSET(sih);
1861 if (si_is_sprom_available(sih)) {
1863 sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
1866 if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
1867 (((sih->buscoretype == PCIE_CORE_ID)
1868 && (sih->buscorerev >= 6))
1869 || ((sih->buscoretype == PCI_CORE_ID)
1870 && (sih->buscorerev >= 0xe)))) {
1871 /* sromrev >= 4, read more */
1873 sprom_read_pci(sih, sromwindow, 0, srom,
1875 sromrev = srom[SROM4_CRCREV] & 0xff;
1876 } else if (err == 0) {
1877 /* srom is good and is rev < 4 */
1878 /* top word of sprom contains version and crc8 */
1879 sromrev = srom[SROM_CRCREV] & 0xff;
1880 /* bcm4401 sroms misprogrammed */
1881 if (sromrev == 0x10)
1885 #if defined(BCMNVRAMR)
1886 /* Use OTP if SPROM not available */
1888 err = otp_read_pci(sih, srom, SROM_MAX);
1890 /* OTP only contain SROM rev8/rev9 for now */
1891 sromrev = srom[SROM4_CRCREV] & 0xff;
1901 * We want internal/wltest driver to come up with default
1902 * sromvars so we can program a blank SPROM/OTP.
1909 value = si_getdevpathvar(sih, "sromrev");
1911 sromrev = (u8) simple_strtoul(value, NULL, 0);
1916 value = si_getnvramflvar(sih, "sromrev");
1929 /* Bitmask for the sromrev */
1932 /* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */
1933 if ((sr & 0x33e) == 0) {
1938 ASSERT(vars != NULL);
1939 ASSERT(count != NULL);
1941 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
1948 /* read variables from flash */
1950 err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
1956 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
1958 /* parse SROM into name=value pairs. */
1959 _initvars_srom_pci(sromrev, srom, 0, &b);
1961 /* final nullbyte terminator */
1962 ASSERT(b.size >= 1);
1966 ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
1969 err = initvars_table(base, vp, vars, count);
1981 * Read the SDIO cis and call parsecis to initialize the vars.
1982 * Return 0 on success, nonzero on error.
1984 static int initvars_cis_sdio(char **vars, uint *count)
1986 u8 *cis[SBSDIO_NUM_FUNCTION + 1];
1990 numfn = bcmsdh_query_iofnum(NULL);
1991 ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
1993 for (fn = 0; fn <= numfn; fn++) {
1994 cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
1995 if (cis[fn] == NULL) {
2000 if (bcmsdh_cis_read(NULL, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT) !=
2009 rc = srom_parsecis(cis, fn, vars, count);
2017 /* set SDIO sprom command register */
2018 static int sprom_cmd_sdio(u8 cmd)
2021 uint wait_cnt = 1000;
2023 /* write sprom command register */
2024 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, cmd, NULL);
2027 while (wait_cnt--) {
2029 bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, NULL);
2030 if (status & SBSDIO_SPROM_DONE)
2037 /* read a word from the SDIO srom */
2038 static int sprom_read_sdio(u16 addr, u16 *data)
2040 u8 addr_l, addr_h, data_l, data_h;
2042 addr_l = (u8) ((addr * 2) & 0xff);
2043 addr_h = (u8) (((addr * 2) >> 8) & 0xff);
2046 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h,
2048 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l,
2052 if (sprom_cmd_sdio(SBSDIO_SPROM_READ))
2057 bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, NULL);
2059 bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, NULL);
2061 *data = (data_h << 8) | data_l;
2064 #endif /* BCMSDIO */
2066 static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *varsz)
2068 /* Search flash nvram section for srom variables */
2069 return initvars_flash_si(sih, vars, varsz);