wifi: update ap6356 driver to bcmdhd.101.10.361.x [1/1]
[GitHub/LineageOS/G12/android_hardware_amlogic_kernel-modules_dhd-driver.git] / bcmdhd.101.10.361.x / bcmsrom.c
1 /*
2 * Routines to access SPROM and to parse SROM/CIS variables.
3 *
4 * Despite its file name, OTP contents is also parsed in this file.
5 *
6 * Copyright (C) 2020, Broadcom.
7 *
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed to you
10 * under the terms of the GNU General Public License version 2 (the "GPL"),
11 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
12 * following added to such license:
13 *
14 * As a special exception, the copyright holders of this software give you
15 * permission to link this software with independent modules, and to copy and
16 * distribute the resulting executable under terms of your choice, provided that
17 * you also meet, for each linked independent module, the terms and conditions of
18 * the license of that module. An independent module is a module which is not
19 * derived from this software. The special exception does not apply to any
20 * modifications of the software.
21 *
22 *
23 * <<Broadcom-WL-IPTag/Dual:>>
24 */
25
26 /*
27 * List of non obvious preprocessor defines used in this file and their meaning:
28 * DONGLEBUILD : building firmware that runs on the dongle's CPU
29 * BCM_DONGLEVARS : NVRAM variables can be read from OTP/S(P)ROM.
30 * When host may supply nvram vars in addition to the ones in OTP/SROM:
31 * BCMHOSTVARS : full nic / full dongle
32 * BCMDONGLEHOST : defined when building DHD, code executes on the host in a dongle environment.
33 * DHD_SPROM : defined when building a DHD that supports reading/writing to SPROM
34 */
35
36 #include <typedefs.h>
37 #include <bcmdefs.h>
38 #include <osl.h>
39 #include <stdarg.h>
40 #include <bcmutils.h>
41 #include <hndsoc.h>
42 #include <sbchipc.h>
43 #include <bcmdevs.h>
44 #include <bcmendian.h>
45 #include <sbpcmcia.h>
46 #include <pcicfg.h>
47 #include <siutils.h>
48 #include <bcmsrom.h>
49 #include <bcmsrom_tbl.h>
50 #ifdef BCMSDIO
51 #include <bcmsdh.h>
52 #include <sdio.h>
53 #endif
54 #ifdef BCMSPI
55 #include <spid.h>
56 #endif
57
58 #include <bcmnvram.h>
59 #include <bcmotp.h>
60 #ifndef BCMUSBDEV_COMPOSITE
61 #define BCMUSBDEV_COMPOSITE
62 #endif
63 #if defined(BCMUSBDEV) || defined(BCMSDIO) || defined(BCMSDIODEV)
64 #include <sbsdio.h>
65 #include <sbhnddma.h>
66 #include <sbsdpcmdev.h>
67 #endif
68
69 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
70 #include <sbsprom.h>
71 #endif
72 #include <ethernet.h> /* for sprom content groking */
73
74 #include <sbgci.h>
75 #ifdef EVENT_LOG_COMPILE
76 #include <event_log.h>
77 #endif
78
79 #if defined(EVENT_LOG_COMPILE) && defined(BCMDBG_ERR) && defined(ERR_USE_EVENT_LOG)
80 #if defined(ERR_USE_EVENT_LOG_RA)
81 #define BS_ERROR(args) EVENT_LOG_RA(EVENT_LOG_TAG_BSROM_ERROR, args)
82 #else
83 #define BS_ERROR(args) EVENT_LOG_COMPACT_CAST_PAREN_ARGS(EVENT_LOG_TAG_BSROM_ERROR, args)
84 #endif /* ERR_USE_EVENT_LOG_RA */
85 #elif defined(BCMDBG_ERR) || defined(WLTEST)
86 #define BS_ERROR(args) printf args
87 #else
88 #define BS_ERROR(args)
89 #endif /* defined(BCMDBG_ERR) && defined(ERR_USE_EVENT_LOG) */
90
91 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
92 static bool BCMATTACHDATA(is_caldata_prsnt) = FALSE;
93 static uint16 BCMATTACHDATA(caldata_array)[SROM_MAX / 2];
94 static uint8 BCMATTACHDATA(srom_sromrev);
95 #endif
96
97 static const char BCMATTACHDATA(rstr_uuidstr)[] =
98 "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X";
99 static const char BCMATTACHDATA(rstr_paddr)[] = "pa%d=0x%%x";
100 static const char BCMATTACHDATA(rstr_pdata)[] = "pd%d=0x%%x";
101 static const char BCMATTACHDATA(rstr_pdatah)[] = "pdh%d=0x%%x";
102 static const char BCMATTACHDATA(rstr_pdatal)[] = "pdl%d=0x%%x";
103 static const char BCMATTACHDATA(rstr_gci_ccreg_entry)[] = "gcr%d=0x%%x";
104 static const char BCMATTACHDATA(rstr_hex)[] = "0x%x";
105
106 /** curmap: contains host start address of PCI BAR0 window */
107 static volatile uint8* srom_offset(si_t *sih, volatile void *curmap)
108 {
109 if (sih->ccrev <= 31)
110 return (volatile uint8*)curmap + PCI_BAR0_SPROM_OFFSET;
111 if ((sih->cccaps & CC_CAP_SROM) == 0)
112 return NULL;
113
114 if (BUSTYPE(sih->bustype) == SI_BUS)
115 return (uint8 *)((uintptr)SI_ENUM_BASE(sih) + CC_SROM_OTP);
116
117 return (volatile uint8*)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP;
118 }
119
120 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
121 #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
122 #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
123 #endif
124
125 srom_info_t *sromh = NULL;
126
127 extern char *_vars;
128 extern uint _varsz;
129 #ifdef DONGLEBUILD
130 char * BCMATTACHDATA(_vars_otp) = NULL;
131 #define DONGLE_STORE_VARS_OTP_PTR(v) (_vars_otp = (v))
132 #else
133 #define DONGLE_STORE_VARS_OTP_PTR(v)
134 #endif
135
136 #define SROM_CIS_SINGLE 1
137
138 #if !defined(BCMDONGLEHOST)
139 static int initvars_srom_si(si_t *sih, osl_t *osh, volatile void *curmap, char **vars, uint *count);
140 static void _initvars_srom_pci(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b);
141 static int initvars_srom_pci(si_t *sih, volatile void *curmap, char **vars, uint *count);
142 static int initvars_cis_pci(si_t *sih, osl_t *osh, volatile void *curmap, char **vars, uint *count);
143 #endif /* !defined(BCMDONGLEHOST) */
144 #if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) &&\
145 !defined(BCMDONGLEHOST) && !defined(BCMPCIEDEV_ENABLED)
146 static int initvars_flash_si(si_t *sih, char **vars, uint *count);
147 #endif /* !defined(BCMUSBDEV) && !defined(BCMSDIODEV) && !defined(BCMDONGLEHOST) */
148 #ifdef BCMSDIO
149 #if !defined(BCMDONGLEHOST)
150 static int initvars_cis_sdio(si_t *sih, osl_t *osh, char **vars, uint *count);
151 #endif /* !defined(BCMDONGLEHOST) */
152 static int sprom_cmd_sdio(osl_t *osh, uint8 cmd);
153 static int sprom_read_sdio(osl_t *osh, uint16 addr, uint16 *data);
154 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
155 static int sprom_write_sdio(osl_t *osh, uint16 addr, uint16 data);
156 #endif /* defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) */
157 #endif /* BCMSDIO */
158 #if !defined(BCMDONGLEHOST)
159 #ifdef BCMSPI
160 static int initvars_cis_spi(si_t *sih, osl_t *osh, char **vars, uint *count);
161 #endif /* BCMSPI */
162 #endif /* !defined(BCMDONGLEHOST) */
163 static int sprom_read_pci(osl_t *osh, si_t *sih, volatile uint16 *sprom, uint wordoff, uint16 *buf,
164 uint nwords, bool check_crc);
165 #if !defined(BCMDONGLEHOST)
166 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
167 static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz);
168 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
169 #endif /* !defined(BCMDONGLEHOST) */
170 static uint16 srom_cc_cmd(si_t *sih, osl_t *osh, volatile void *ccregs, uint32 cmd, uint wordoff,
171 uint16 data);
172
173 #if !defined(BCMDONGLEHOST)
174 static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len);
175 int dbushost_initvars_flash(si_t *sih, osl_t *osh, char **base, uint len);
176 static uint get_max_cis_size(si_t *sih);
177 #endif /* !defined(BCMDONGLEHOST) */
178
179 #if defined (BCMHOSTVARS)
180 /* Also used by wl_readconfigdata for vars download */
181 char BCMATTACHDATA(mfgsromvars)[VARS_MAX];
182 int BCMATTACHDATA(defvarslen) = 0;
183 #endif /* defined(BCMHOSTVARS) */
184
185 #if !defined(BCMDONGLEHOST)
186 #if defined (BCMHOSTVARS)
187 /* FIXME: Fake 4331 SROM to boot 4331 driver on QT w/o SPROM/OTP */
188 static char BCMATTACHDATA(defaultsromvars_4331)[] =
189 "sromrev=9\0"
190 "boardrev=0x1104\0"
191 "boardflags=0x200\0"
192 "boardflags2=0x0\0"
193 "boardtype=0x524\0"
194 "boardvendor=0x14e4\0"
195 "boardnum=0x2064\0"
196 "macaddr=00:90:4c:1a:20:64\0"
197 "ccode=0x0\0"
198 "regrev=0x0\0"
199 "opo=0x0\0"
200 "aa2g=0x7\0"
201 "aa5g=0x7\0"
202 "ag0=0x2\0"
203 "ag1=0x2\0"
204 "ag2=0x2\0"
205 "ag3=0xff\0"
206 "pa0b0=0xfe7f\0"
207 "pa0b1=0x15d9\0"
208 "pa0b2=0xfac6\0"
209 "pa0itssit=0x20\0"
210 "pa0maxpwr=0x48\0"
211 "pa1b0=0xfe89\0"
212 "pa1b1=0x14b1\0"
213 "pa1b2=0xfada\0"
214 "pa1lob0=0xffff\0"
215 "pa1lob1=0xffff\0"
216 "pa1lob2=0xffff\0"
217 "pa1hib0=0xfe8f\0"
218 "pa1hib1=0x13df\0"
219 "pa1hib2=0xfafa\0"
220 "pa1itssit=0x3e\0"
221 "pa1maxpwr=0x3c\0"
222 "pa1lomaxpwr=0x3c\0"
223 "pa1himaxpwr=0x3c\0"
224 "bxa2g=0x3\0"
225 "rssisav2g=0x7\0"
226 "rssismc2g=0xf\0"
227 "rssismf2g=0xf\0"
228 "bxa5g=0x3\0"
229 "rssisav5g=0x7\0"
230 "rssismc5g=0xf\0"
231 "rssismf5g=0xf\0"
232 "tri2g=0xff\0"
233 "tri5g=0xff\0"
234 "tri5gl=0xff\0"
235 "tri5gh=0xff\0"
236 "rxpo2g=0xff\0"
237 "rxpo5g=0xff\0"
238 "txchain=0x7\0"
239 "rxchain=0x7\0"
240 "antswitch=0x0\0"
241 "tssipos2g=0x1\0"
242 "extpagain2g=0x2\0"
243 "pdetrange2g=0x4\0"
244 "triso2g=0x3\0"
245 "antswctl2g=0x0\0"
246 "tssipos5g=0x1\0"
247 "elna2g=0xff\0"
248 "extpagain5g=0x2\0"
249 "pdetrange5g=0x4\0"
250 "triso5g=0x3\0"
251 "antswctl5g=0x0\0"
252 "elna5g=0xff\0"
253 "cckbw202gpo=0x0\0"
254 "cckbw20ul2gpo=0x0\0"
255 "legofdmbw202gpo=0x0\0"
256 "legofdmbw20ul2gpo=0x0\0"
257 "legofdmbw205glpo=0x0\0"
258 "legofdmbw20ul5glpo=0x0\0"
259 "legofdmbw205gmpo=0x0\0"
260 "legofdmbw20ul5gmpo=0x0\0"
261 "legofdmbw205ghpo=0x0\0"
262 "legofdmbw20ul5ghpo=0x0\0"
263 "mcsbw202gpo=0x0\0"
264 "mcsbw20ul2gpo=0x0\0"
265 "mcsbw402gpo=0x0\0"
266 "mcsbw205glpo=0x0\0"
267 "mcsbw20ul5glpo=0x0\0"
268 "mcsbw405glpo=0x0\0"
269 "mcsbw205gmpo=0x0\0"
270 "mcsbw20ul5gmpo=0x0\0"
271 "mcsbw405gmpo=0x0\0"
272 "mcsbw205ghpo=0x0\0"
273 "mcsbw20ul5ghpo=0x0\0"
274 "mcsbw405ghpo=0x0\0"
275 "mcs32po=0x0\0"
276 "legofdm40duppo=0x0\0"
277 "maxp2ga0=0x48\0"
278 "itt2ga0=0x20\0"
279 "itt5ga0=0x3e\0"
280 "pa2gw0a0=0xfe7f\0"
281 "pa2gw1a0=0x15d9\0"
282 "pa2gw2a0=0xfac6\0"
283 "maxp5ga0=0x3c\0"
284 "maxp5gha0=0x3c\0"
285 "maxp5gla0=0x3c\0"
286 "pa5gw0a0=0xfe89\0"
287 "pa5gw1a0=0x14b1\0"
288 "pa5gw2a0=0xfada\0"
289 "pa5glw0a0=0xffff\0"
290 "pa5glw1a0=0xffff\0"
291 "pa5glw2a0=0xffff\0"
292 "pa5ghw0a0=0xfe8f\0"
293 "pa5ghw1a0=0x13df\0"
294 "pa5ghw2a0=0xfafa\0"
295 "maxp2ga1=0x48\0"
296 "itt2ga1=0x20\0"
297 "itt5ga1=0x3e\0"
298 "pa2gw0a1=0xfe54\0"
299 "pa2gw1a1=0x1563\0"
300 "pa2gw2a1=0xfa7f\0"
301 "maxp5ga1=0x3c\0"
302 "maxp5gha1=0x3c\0"
303 "maxp5gla1=0x3c\0"
304 "pa5gw0a1=0xfe53\0"
305 "pa5gw1a1=0x14fe\0"
306 "pa5gw2a1=0xfa94\0"
307 "pa5glw0a1=0xffff\0"
308 "pa5glw1a1=0xffff\0"
309 "pa5glw2a1=0xffff\0"
310 "pa5ghw0a1=0xfe6e\0"
311 "pa5ghw1a1=0x1457\0"
312 "pa5ghw2a1=0xfab9\0"
313 "END\0";
314
315 static char BCMATTACHDATA(defaultsromvars_4360)[] =
316 "sromrev=11\0"
317 "boardrev=0x1421\0"
318 "boardflags=0x10401001\0"
319 "boardflags2=0x0\0"
320 "boardtype=0x61b\0"
321 "subvid=0x14e4\0"
322 "boardflags3=0x1\0"
323 "boardnum=62526\0"
324 "macaddr=00:90:4c:0d:f4:3e\0"
325 "ccode=X0\0"
326 "regrev=15\0"
327 "aa2g=7\0"
328 "aa5g=7\0"
329 "agbg0=71\0"
330 "agbg1=71\0"
331 "agbg2=133\0"
332 "aga0=71\0"
333 "aga1=133\0"
334 "aga2=133\0"
335 "antswitch=0\0"
336 "tssiposslope2g=1\0"
337 "epagain2g=0\0"
338 "pdgain2g=9\0"
339 "tworangetssi2g=0\0"
340 "papdcap2g=0\0"
341 "femctrl=2\0"
342 "tssiposslope5g=1\0"
343 "epagain5g=0\0"
344 "pdgain5g=9\0"
345 "tworangetssi5g=0\0"
346 "papdcap5g=0\0"
347 "gainctrlsph=0\0"
348 "tempthresh=255\0"
349 "tempoffset=255\0"
350 "rawtempsense=0x1ff\0"
351 "measpower=0x7f\0"
352 "tempsense_slope=0xff\0"
353 "tempcorrx=0x3f\0"
354 "tempsense_option=0x3\0"
355 "xtalfreq=65535\0"
356 "phycal_tempdelta=255\0"
357 "temps_period=15\0"
358 "temps_hysteresis=15\0"
359 "measpower1=0x7f\0"
360 "measpower2=0x7f\0"
361 "pdoffset2g40ma0=15\0"
362 "pdoffset2g40ma1=15\0"
363 "pdoffset2g40ma2=15\0"
364 "pdoffset2g40mvalid=1\0"
365 "pdoffset40ma0=9010\0"
366 "pdoffset40ma1=12834\0"
367 "pdoffset40ma2=8994\0"
368 "pdoffset80ma0=16\0"
369 "pdoffset80ma1=4096\0"
370 "pdoffset80ma2=0\0"
371 "subband5gver=0x4\0"
372 "cckbw202gpo=0\0"
373 "cckbw20ul2gpo=0\0"
374 "mcsbw202gpo=2571386880\0"
375 "mcsbw402gpo=2571386880\0"
376 "dot11agofdmhrbw202gpo=17408\0"
377 "ofdmlrbw202gpo=0\0"
378 "mcsbw205glpo=4001923072\0"
379 "mcsbw405glpo=4001923072\0"
380 "mcsbw805glpo=4001923072\0"
381 "mcsbw1605glpo=0\0"
382 "mcsbw205gmpo=3431497728\0"
383 "mcsbw405gmpo=3431497728\0"
384 "mcsbw805gmpo=3431497728\0"
385 "mcsbw1605gmpo=0\0"
386 "mcsbw205ghpo=3431497728\0"
387 "mcsbw405ghpo=3431497728\0"
388 "mcsbw805ghpo=3431497728\0"
389 "mcsbw1605ghpo=0\0"
390 "mcslr5glpo=0\0"
391 "mcslr5gmpo=0\0"
392 "mcslr5ghpo=0\0"
393 "sb20in40hrpo=0\0"
394 "sb20in80and160hr5glpo=0\0"
395 "sb40and80hr5glpo=0\0"
396 "sb20in80and160hr5gmpo=0\0"
397 "sb40and80hr5gmpo=0\0"
398 "sb20in80and160hr5ghpo=0\0"
399 "sb40and80hr5ghpo=0\0"
400 "sb20in40lrpo=0\0"
401 "sb20in80and160lr5glpo=0\0"
402 "sb40and80lr5glpo=0\0"
403 "sb20in80and160lr5gmpo=0\0"
404 "sb40and80lr5gmpo=0\0"
405 "sb20in80and160lr5ghpo=0\0"
406 "sb40and80lr5ghpo=0\0"
407 "dot11agduphrpo=0\0"
408 "dot11agduplrpo=0\0"
409 "pcieingress_war=15\0"
410 "sar2g=18\0"
411 "sar5g=15\0"
412 "noiselvl2ga0=31\0"
413 "noiselvl2ga1=31\0"
414 "noiselvl2ga2=31\0"
415 "noiselvl5ga0=31,31,31,31\0"
416 "noiselvl5ga1=31,31,31,31\0"
417 "noiselvl5ga2=31,31,31,31\0"
418 "rxgainerr2ga0=63\0"
419 "rxgainerr2ga1=31\0"
420 "rxgainerr2ga2=31\0"
421 "rxgainerr5ga0=63,63,63,63\0"
422 "rxgainerr5ga1=31,31,31,31\0"
423 "rxgainerr5ga2=31,31,31,31\0"
424 "maxp2ga0=76\0"
425 "pa2ga0=0xff3c,0x172c,0xfd20\0"
426 "rxgains5gmelnagaina0=7\0"
427 "rxgains5gmtrisoa0=15\0"
428 "rxgains5gmtrelnabypa0=1\0"
429 "rxgains5ghelnagaina0=7\0"
430 "rxgains5ghtrisoa0=15\0"
431 "rxgains5ghtrelnabypa0=1\0"
432 "rxgains2gelnagaina0=4\0"
433 "rxgains2gtrisoa0=7\0"
434 "rxgains2gtrelnabypa0=1\0"
435 "rxgains5gelnagaina0=3\0"
436 "rxgains5gtrisoa0=7\0"
437 "rxgains5gtrelnabypa0=1\0"
438 "maxp5ga0=76,76,76,76\0"
439 "pa5ga0=0xff3a,0x14d4,0xfd5f,0xff36,0x1626,0xfd2e,0xff42,0x15bd,0xfd47,0xff39,0x15a3,0xfd3d\0"
440 "maxp2ga1=76\0"
441 "pa2ga1=0xff2a,0x16b2,0xfd28\0"
442 "rxgains5gmelnagaina1=7\0"
443 "rxgains5gmtrisoa1=15\0"
444 "rxgains5gmtrelnabypa1=1\0"
445 "rxgains5ghelnagaina1=7\0"
446 "rxgains5ghtrisoa1=15\0"
447 "rxgains5ghtrelnabypa1=1\0"
448 "rxgains2gelnagaina1=3\0"
449 "rxgains2gtrisoa1=6\0"
450 "rxgains2gtrelnabypa1=1\0"
451 "rxgains5gelnagaina1=3\0"
452 "rxgains5gtrisoa1=6\0"
453 "rxgains5gtrelnabypa1=1\0"
454 "maxp5ga1=76,76,76,76\0"
455 "pa5ga1=0xff4e,0x1530,0xfd53,0xff58,0x15b4,0xfd4d,0xff58,0x1671,0xfd2f,0xff55,0x15e2,0xfd46\0"
456 "maxp2ga2=76\0"
457 "pa2ga2=0xff3c,0x1736,0xfd1f\0"
458 "rxgains5gmelnagaina2=7\0"
459 "rxgains5gmtrisoa2=15\0"
460 "rxgains5gmtrelnabypa2=1\0"
461 "rxgains5ghelnagaina2=7\0"
462 "rxgains5ghtrisoa2=15\0"
463 "rxgains5ghtrelnabypa2=1\0"
464 "rxgains2gelnagaina2=4\0"
465 "rxgains2gtrisoa2=7\0"
466 "rxgains2gtrelnabypa2=1\0"
467 "rxgains5gelnagaina2=3\0"
468 "rxgains5gtrisoa2=7\0"
469 "rxgains5gtrelnabypa2=1\0"
470 "maxp5ga2=76,76,76,76\0"
471 "pa5ga2=0xff2d,0x144a,0xfd63,0xff35,0x15d7,0xfd3b,0xff35,0x1668,0xfd2f,0xff31,0x1664,0xfd27\0"
472 "END\0";
473
474 #endif /* defined(BCMHOSTVARS) */
475 #endif /* !defined(BCMDONGLEHOST) */
476
477 #if !defined(BCMDONGLEHOST)
478 #if defined(BCMHOSTVARS)
479 static char BCMATTACHDATA(defaultsromvars_wltest)[] =
480 "macaddr=00:90:4c:f8:00:01\0"
481 "et0macaddr=00:11:22:33:44:52\0"
482 "et0phyaddr=30\0"
483 "et0mdcport=0\0"
484 "gpio2=robo_reset\0"
485 "boardvendor=0x14e4\0"
486 "boardflags=0x210\0"
487 "boardflags2=0\0"
488 "boardtype=0x04c3\0"
489 "boardrev=0x1100\0"
490 "sromrev=8\0"
491 "devid=0x432c\0"
492 "ccode=0\0"
493 "regrev=0\0"
494 "aa2g=3\0"
495 "ag0=2\0"
496 "ag1=2\0"
497 "aa5g=3\0"
498 "aa0=2\0"
499 "aa1=2\0"
500 "txchain=3\0"
501 "rxchain=3\0"
502 "antswitch=0\0"
503 "itt2ga0=0x20\0"
504 "maxp2ga0=0x48\0"
505 "pa2gw0a0=0xfe9e\0"
506 "pa2gw1a0=0x15d5\0"
507 "pa2gw2a0=0xfae9\0"
508 "itt2ga1=0x20\0"
509 "maxp2ga1=0x48\0"
510 "pa2gw0a1=0xfeb3\0"
511 "pa2gw1a1=0x15c9\0"
512 "pa2gw2a1=0xfaf7\0"
513 "tssipos2g=1\0"
514 "extpagain2g=0\0"
515 "pdetrange2g=0\0"
516 "triso2g=3\0"
517 "antswctl2g=0\0"
518 "tssipos5g=1\0"
519 "extpagain5g=0\0"
520 "pdetrange5g=0\0"
521 "triso5g=3\0"
522 "antswctl5g=0\0"
523 "cck2gpo=0\0"
524 "ofdm2gpo=0\0"
525 "mcs2gpo0=0\0"
526 "mcs2gpo1=0\0"
527 "mcs2gpo2=0\0"
528 "mcs2gpo3=0\0"
529 "mcs2gpo4=0\0"
530 "mcs2gpo5=0\0"
531 "mcs2gpo6=0\0"
532 "mcs2gpo7=0\0"
533 "cddpo=0\0"
534 "stbcpo=0\0"
535 "bw40po=4\0"
536 "bwduppo=0\0"
537 "END\0";
538
539 /**
540 * The contents of this array is a first attempt, is likely incorrect for 43602, needs to be
541 * edited in a later stage.
542 */
543 static char BCMATTACHDATA(defaultsromvars_43602)[] =
544 "sromrev=11\0"
545 "boardrev=0x1421\0"
546 "boardflags=0x10401001\0"
547 "boardflags2=0x00000002\0"
548 "boardflags3=0x00000003\0"
549 "boardtype=0x61b\0"
550 "subvid=0x14e4\0"
551 "boardnum=62526\0"
552 "macaddr=00:90:4c:0d:f4:3e\0"
553 "ccode=X0\0"
554 "regrev=15\0"
555 "aa2g=7\0"
556 "aa5g=7\0"
557 "agbg0=71\0"
558 "agbg1=71\0"
559 "agbg2=133\0"
560 "aga0=71\0"
561 "aga1=133\0"
562 "aga2=133\0"
563 "antswitch=0\0"
564 "tssiposslope2g=1\0"
565 "epagain2g=0\0"
566 "pdgain2g=9\0"
567 "tworangetssi2g=0\0"
568 "papdcap2g=0\0"
569 "femctrl=2\0"
570 "tssiposslope5g=1\0"
571 "epagain5g=0\0"
572 "pdgain5g=9\0"
573 "tworangetssi5g=0\0"
574 "papdcap5g=0\0"
575 "gainctrlsph=0\0"
576 "tempthresh=255\0"
577 "tempoffset=255\0"
578 "rawtempsense=0x1ff\0"
579 "measpower=0x7f\0"
580 "tempsense_slope=0xff\0"
581 "tempcorrx=0x3f\0"
582 "tempsense_option=0x3\0"
583 "xtalfreq=40000\0"
584 "phycal_tempdelta=255\0"
585 "temps_period=15\0"
586 "temps_hysteresis=15\0"
587 "measpower1=0x7f\0"
588 "measpower2=0x7f\0"
589 "pdoffset2g40ma0=15\0"
590 "pdoffset2g40ma1=15\0"
591 "pdoffset2g40ma2=15\0"
592 "pdoffset2g40mvalid=1\0"
593 "pdoffset40ma0=9010\0"
594 "pdoffset40ma1=12834\0"
595 "pdoffset40ma2=8994\0"
596 "pdoffset80ma0=16\0"
597 "pdoffset80ma1=4096\0"
598 "pdoffset80ma2=0\0"
599 "subband5gver=0x4\0"
600 "cckbw202gpo=0\0"
601 "cckbw20ul2gpo=0\0"
602 "mcsbw202gpo=2571386880\0"
603 "mcsbw402gpo=2571386880\0"
604 "dot11agofdmhrbw202gpo=17408\0"
605 "ofdmlrbw202gpo=0\0"
606 "mcsbw205glpo=4001923072\0"
607 "mcsbw405glpo=4001923072\0"
608 "mcsbw805glpo=4001923072\0"
609 "mcsbw1605glpo=0\0"
610 "mcsbw205gmpo=3431497728\0"
611 "mcsbw405gmpo=3431497728\0"
612 "mcsbw805gmpo=3431497728\0"
613 "mcsbw1605gmpo=0\0"
614 "mcsbw205ghpo=3431497728\0"
615 "mcsbw405ghpo=3431497728\0"
616 "mcsbw805ghpo=3431497728\0"
617 "mcsbw1605ghpo=0\0"
618 "mcslr5glpo=0\0"
619 "mcslr5gmpo=0\0"
620 "mcslr5ghpo=0\0"
621 "sb20in40hrpo=0\0"
622 "sb20in80and160hr5glpo=0\0"
623 "sb40and80hr5glpo=0\0"
624 "sb20in80and160hr5gmpo=0\0"
625 "sb40and80hr5gmpo=0\0"
626 "sb20in80and160hr5ghpo=0\0"
627 "sb40and80hr5ghpo=0\0"
628 "sb20in40lrpo=0\0"
629 "sb20in80and160lr5glpo=0\0"
630 "sb40and80lr5glpo=0\0"
631 "sb20in80and160lr5gmpo=0\0"
632 "sb40and80lr5gmpo=0\0"
633 "sb20in80and160lr5ghpo=0\0"
634 "sb40and80lr5ghpo=0\0"
635 "dot11agduphrpo=0\0"
636 "dot11agduplrpo=0\0"
637 "pcieingress_war=15\0"
638 "sar2g=18\0"
639 "sar5g=15\0"
640 "noiselvl2ga0=31\0"
641 "noiselvl2ga1=31\0"
642 "noiselvl2ga2=31\0"
643 "noiselvl5ga0=31,31,31,31\0"
644 "noiselvl5ga1=31,31,31,31\0"
645 "noiselvl5ga2=31,31,31,31\0"
646 "rxgainerr2ga0=63\0"
647 "rxgainerr2ga1=31\0"
648 "rxgainerr2ga2=31\0"
649 "rxgainerr5ga0=63,63,63,63\0"
650 "rxgainerr5ga1=31,31,31,31\0"
651 "rxgainerr5ga2=31,31,31,31\0"
652 "maxp2ga0=76\0"
653 "pa2ga0=0xff3c,0x172c,0xfd20\0"
654 "rxgains5gmelnagaina0=7\0"
655 "rxgains5gmtrisoa0=15\0"
656 "rxgains5gmtrelnabypa0=1\0"
657 "rxgains5ghelnagaina0=7\0"
658 "rxgains5ghtrisoa0=15\0"
659 "rxgains5ghtrelnabypa0=1\0"
660 "rxgains2gelnagaina0=4\0"
661 "rxgains2gtrisoa0=7\0"
662 "rxgains2gtrelnabypa0=1\0"
663 "rxgains5gelnagaina0=3\0"
664 "rxgains5gtrisoa0=7\0"
665 "rxgains5gtrelnabypa0=1\0"
666 "maxp5ga0=76,76,76,76\0"
667 "pa5ga0=0xff3a,0x14d4,0xfd5f,0xff36,0x1626,0xfd2e,0xff42,0x15bd,0xfd47,0xff39,0x15a3,0xfd3d\0"
668 "maxp2ga1=76\0"
669 "pa2ga1=0xff2a,0x16b2,0xfd28\0"
670 "rxgains5gmelnagaina1=7\0"
671 "rxgains5gmtrisoa1=15\0"
672 "rxgains5gmtrelnabypa1=1\0"
673 "rxgains5ghelnagaina1=7\0"
674 "rxgains5ghtrisoa1=15\0"
675 "rxgains5ghtrelnabypa1=1\0"
676 "rxgains2gelnagaina1=3\0"
677 "rxgains2gtrisoa1=6\0"
678 "rxgains2gtrelnabypa1=1\0"
679 "rxgains5gelnagaina1=3\0"
680 "rxgains5gtrisoa1=6\0"
681 "rxgains5gtrelnabypa1=1\0"
682 "maxp5ga1=76,76,76,76\0"
683 "pa5ga1=0xff4e,0x1530,0xfd53,0xff58,0x15b4,0xfd4d,0xff58,0x1671,0xfd2f,0xff55,0x15e2,0xfd46\0"
684 "maxp2ga2=76\0"
685 "pa2ga2=0xff3c,0x1736,0xfd1f\0"
686 "rxgains5gmelnagaina2=7\0"
687 "rxgains5gmtrisoa2=15\0"
688 "rxgains5gmtrelnabypa2=1\0"
689 "rxgains5ghelnagaina2=7\0"
690 "rxgains5ghtrisoa2=15\0"
691 "rxgains5ghtrelnabypa2=1\0"
692 "rxgains2gelnagaina2=4\0"
693 "rxgains2gtrisoa2=7\0"
694 "rxgains2gtrelnabypa2=1\0"
695 "rxgains5gelnagaina2=3\0"
696 "rxgains5gtrisoa2=7\0"
697 "rxgains5gtrelnabypa2=1\0"
698 "maxp5ga2=76,76,76,76\0"
699 "pa5ga2=0xff2d,0x144a,0xfd63,0xff35,0x15d7,0xfd3b,0xff35,0x1668,0xfd2f,0xff31,0x1664,0xfd27\0"
700 "END\0";
701
702 /**
703 * The contents of this array is a first attempt, was copied from 4378, needs to be edited in
704 * a later stage.
705 */
706 static char BCMATTACHDATA(defaultsromvars_4378)[] =
707 "cckdigfilttype=4\0"
708 "sromrev=11\0"
709 "boardrev=0x1102\0"
710 "boardtype=0x0771\0"
711 "boardflags=0x10481201\0"
712 "boardflags2=0x00000000\0"
713 "boardflags3=0x04000080\0"
714 "macaddr=00:90:4c:12:43:47\0"
715 "ccode=0\0"
716 "regrev=0\0"
717 "antswitch=0\0"
718 "pdgain5g=0\0"
719 "pdgain2g=0\0"
720 "tworangetssi2g=0\0"
721 "tworangetssi5g=0\0"
722 "femctrl=16\0"
723 "vendid=0x14e4\0"
724 "devid=0x4425\0"
725 "manfid=0x2d0\0"
726 "nocrc=1\0"
727 "btc_params82=0x1a0\0"
728 "otpimagesize=502\0"
729 "xtalfreq=37400\0"
730 "rxgains2gelnagaina0=3\0"
731 "rxgains2gtrisoa0=7\0"
732 "rxgains2gtrelnabypa0=1\0"
733 "rxgains5gelnagaina0=3\0"
734 "rxgains5gtrisoa0=6\0"
735 "rxgains5gtrelnabypa0=1\0"
736 "rxgains5gmelnagaina0=3\0"
737 "rxgains5gmtrisoa0=6\0"
738 "rxgains5gmtrelnabypa0=1\0"
739 "rxgains5ghelnagaina0=3\0"
740 "rxgains5ghtrisoa0=6\0"
741 "rxgains5ghtrelnabypa0=1\0"
742 "rxgains2gelnagaina1=3\0"
743 "rxgains2gtrisoa1=7\0"
744 "rxgains2gtrelnabypa1=1\0"
745 "rxgains5gelnagaina1=3\0"
746 "rxgains5gtrisoa1=6\0"
747 "rxgains5gtrelnabypa1=1\0"
748 "rxgains5gmelnagaina1=3\0"
749 "rxgains5gmtrisoa1=6\0"
750 "rxgains5gmtrelnabypa1=1\0"
751 "rxgains5ghelnagaina1=3\0"
752 "rxgains5ghtrisoa1=6\0"
753 "rxgains5ghtrelnabypa1=1\0"
754 "rxchain=3\0"
755 "txchain=3\0"
756 "aa2g=3\0"
757 "aa5g=3\0"
758 "agbg0=2\0"
759 "agbg1=2\0"
760 "aga0=2\0"
761 "aga1=2\0"
762 "tssipos2g=1\0"
763 "tssipos5g=1\0"
764 "tempthresh=255\0"
765 "tempoffset=255\0"
766 "rawtempsense=0x1ff\0"
767 "pa2gccka0=-200,7392,-897\0"
768 "pa2gccka1=-198,7522,-907\0"
769 "pa2ga0=-174,7035,-838\0"
770 "pa2ga1=-185,6772,-811\0"
771 "pa5ga0=-175,7296,-887,-164,7553,-910,-155,7801,-936,-149,7908,-951\0"
772 "pa5ga1=-155,7675,-925,-148,7851,-940,-152,7930,-954,-143,8121,-969\0"
773 "pa5gbw4080a0=-178,7872,-959,-173,8107,-986,-165,8398,-1019,-150,8809,-1063\0"
774 "pa5gbw4080a1=-166,8179,-993,-161,8378,-1015,-165,8402,-1019,-155,8757,-1057\0"
775 "maxp2ga0=66\0"
776 "maxp2ga1=66\0"
777 "maxp5ga0=66,66,66,66\0"
778 "maxp5ga1=66,66,66,66\0"
779 "subband5gver=0x4\0"
780 "paparambwver=3\0"
781 "cckpwroffset0=0\0"
782 "cckpwroffset1=0\0"
783 "pdoffset40ma0=0x0000\0"
784 "pdoffset80ma0=0xeeee\0"
785 "pdoffset40ma1=0x0000\0"
786 "pdoffset80ma1=0xeeee\0"
787 "cckbw202gpo=0\0"
788 "cckbw20ul2gpo=0\0"
789 "mcsbw202gpo=0xEC888222\0"
790 "mcsbw402gpo=0xEC888222\0"
791 "dot11agofdmhrbw202gpo=0x6622\0"
792 "ofdmlrbw202gpo=0x0000\0"
793 "mcsbw205glpo=0xCA666000\0"
794 "mcsbw405glpo=0xCA666000\0"
795 "mcsbw805glpo=0xEA666000\0"
796 "mcsbw1605glpo=0\0"
797 "mcsbw205gmpo=0xCA666000\0"
798 "mcsbw405gmpo=0xCA666000\0"
799 "mcsbw805gmpo=0xEA666000\0"
800 "mcsbw1605gmpo=0\0"
801 "mcsbw205ghpo=0xCA666000\0"
802 "mcsbw405ghpo=0xCA666000\0"
803 "mcsbw805ghpo=0xEA666000\0"
804 "mcsbw1605ghpo=0\0"
805 "mcslr5glpo=0x0000\0"
806 "mcslr5gmpo=0x0000\0"
807 "mcslr5ghpo=0x0000\0"
808 "sb20in40hrpo=0x0\0"
809 "sb20in80and160hr5glpo=0x0\0"
810 "sb40and80hr5glpo=0x0\0"
811 "sb20in80and160hr5gmpo=0x0\0"
812 "sb40and80hr5gmpo=0x0\0"
813 "sb20in80and160hr5ghpo=0x0\0"
814 "sb40and80hr5ghpo=0x0\0"
815 "sb20in40lrpo=0x0\0"
816 "sb20in80and160lr5glpo=0x0\0"
817 "sb40and80lr5glpo=0x0\0"
818 "sb20in80and160lr5gmpo=0x0\0"
819 "sb40and80lr5gmpo=0x0\0"
820 "sb20in80and160lr5ghpo=0x0\0"
821 "sb40and80lr5ghpo=0x0\0"
822 "dot11agduphrpo=0x0\0"
823 "dot11agduplrpo=0x0\0"
824 "phycal_tempdelta=15\0"
825 "temps_period=15\0"
826 "temps_hysteresis=15\0"
827 "swctrlmap_2g=0x00000404,0x0a0a0000,0x02020000,0x010a02,0x1fe\0"
828 "swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0"
829 "swctrlmap_5g=0x00001010,0x60600000,0x40400000,0x000000,0x0f0\0"
830 "swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0"
831 "powoffs2gtna0=1,3,3,1,0,0,1,2,2,2,1,1,0,0\0"
832 "powoffs2gtna1=-1,1,1,1,0,0,1,2,3,2,2,0,0,0\0"
833 "END\0";
834
835 /**
836 * The contents of this array is a first attempt, was copied from 4387, needs to be edited in
837 * a later stage.
838 */
839 static char BCMATTACHDATA(defaultsromvars_4387)[] =
840 "cckdigfilttype=4\0"
841 "sromrev=11\0"
842 "boardrev=0x1102\0"
843 "boardtype=0x0771\0"
844 "boardflags=0x10481201\0"
845 "boardflags2=0x00000000\0"
846 "boardflags3=0x04000080\0"
847 "macaddr=00:90:4c:12:43:47\0"
848 "ccode=0\0"
849 "regrev=0\0"
850 "antswitch=0\0"
851 "pdgain5g=0\0"
852 "pdgain2g=0\0"
853 "tworangetssi2g=0\0"
854 "tworangetssi5g=0\0"
855 "femctrl=16\0"
856 "vendid=0x14e4\0"
857 "devid=0x4425\0"
858 "manfid=0x2d0\0"
859 "nocrc=1\0"
860 "btc_params82=0x1a0\0"
861 "otpimagesize=502\0"
862 "xtalfreq=37400\0"
863 "rxgains2gelnagaina0=3\0"
864 "rxgains2gtrisoa0=7\0"
865 "rxgains2gtrelnabypa0=1\0"
866 "rxgains5gelnagaina0=3\0"
867 "rxgains5gtrisoa0=6\0"
868 "rxgains5gtrelnabypa0=1\0"
869 "rxgains5gmelnagaina0=3\0"
870 "rxgains5gmtrisoa0=6\0"
871 "rxgains5gmtrelnabypa0=1\0"
872 "rxgains5ghelnagaina0=3\0"
873 "rxgains5ghtrisoa0=6\0"
874 "rxgains5ghtrelnabypa0=1\0"
875 "rxgains2gelnagaina1=3\0"
876 "rxgains2gtrisoa1=7\0"
877 "rxgains2gtrelnabypa1=1\0"
878 "rxgains5gelnagaina1=3\0"
879 "rxgains5gtrisoa1=6\0"
880 "rxgains5gtrelnabypa1=1\0"
881 "rxgains5gmelnagaina1=3\0"
882 "rxgains5gmtrisoa1=6\0"
883 "rxgains5gmtrelnabypa1=1\0"
884 "rxgains5ghelnagaina1=3\0"
885 "rxgains5ghtrisoa1=6\0"
886 "rxgains5ghtrelnabypa1=1\0"
887 "rxchain=3\0"
888 "txchain=3\0"
889 "aa2g=3\0"
890 "aa5g=3\0"
891 "agbg0=2\0"
892 "agbg1=2\0"
893 "aga0=2\0"
894 "aga1=2\0"
895 "tssipos2g=1\0"
896 "tssipos5g=1\0"
897 "tempthresh=255\0"
898 "tempoffset=255\0"
899 "rawtempsense=0x1ff\0"
900 "pa2gccka0=-200,7392,-897\0"
901 "pa2gccka1=-198,7522,-907\0"
902 "pa2ga0=-174,7035,-838\0"
903 "pa2ga1=-185,6772,-811\0"
904 "pa5ga0=-175,7296,-887,-164,7553,-910,-155,7801,-936,-149,7908,-951\0"
905 "pa5ga1=-155,7675,-925,-148,7851,-940,-152,7930,-954,-143,8121,-969\0"
906 "pa5gbw4080a0=-178,7872,-959,-173,8107,-986,-165,8398,-1019,-150,8809,-1063\0"
907 "pa5gbw4080a1=-166,8179,-993,-161,8378,-1015,-165,8402,-1019,-155,8757,-1057\0"
908 "maxp2ga0=66\0"
909 "maxp2ga1=66\0"
910 "maxp5ga0=66,66,66,66\0"
911 "maxp5ga1=66,66,66,66\0"
912 "subband5gver=0x4\0"
913 "paparambwver=3\0"
914 "cckpwroffset0=0\0"
915 "cckpwroffset1=0\0"
916 "pdoffset40ma0=0x0000\0"
917 "pdoffset80ma0=0xeeee\0"
918 "pdoffset40ma1=0x0000\0"
919 "pdoffset80ma1=0xeeee\0"
920 "cckbw202gpo=0\0"
921 "cckbw20ul2gpo=0\0"
922 "mcsbw202gpo=0xEC888222\0"
923 "mcsbw402gpo=0xEC888222\0"
924 "dot11agofdmhrbw202gpo=0x6622\0"
925 "ofdmlrbw202gpo=0x0000\0"
926 "mcsbw205glpo=0xCA666000\0"
927 "mcsbw405glpo=0xCA666000\0"
928 "mcsbw805glpo=0xEA666000\0"
929 "mcsbw1605glpo=0\0"
930 "mcsbw205gmpo=0xCA666000\0"
931 "mcsbw405gmpo=0xCA666000\0"
932 "mcsbw805gmpo=0xEA666000\0"
933 "mcsbw1605gmpo=0\0"
934 "mcsbw205ghpo=0xCA666000\0"
935 "mcsbw405ghpo=0xCA666000\0"
936 "mcsbw805ghpo=0xEA666000\0"
937 "mcsbw1605ghpo=0\0"
938 "mcslr5glpo=0x0000\0"
939 "mcslr5gmpo=0x0000\0"
940 "mcslr5ghpo=0x0000\0"
941 "sb20in40hrpo=0x0\0"
942 "sb20in80and160hr5glpo=0x0\0"
943 "sb40and80hr5glpo=0x0\0"
944 "sb20in80and160hr5gmpo=0x0\0"
945 "sb40and80hr5gmpo=0x0\0"
946 "sb20in80and160hr5ghpo=0x0\0"
947 "sb40and80hr5ghpo=0x0\0"
948 "sb20in40lrpo=0x0\0"
949 "sb20in80and160lr5glpo=0x0\0"
950 "sb40and80lr5glpo=0x0\0"
951 "sb20in80and160lr5gmpo=0x0\0"
952 "sb40and80lr5gmpo=0x0\0"
953 "sb20in80and160lr5ghpo=0x0\0"
954 "sb40and80lr5ghpo=0x0\0"
955 "dot11agduphrpo=0x0\0"
956 "dot11agduplrpo=0x0\0"
957 "phycal_tempdelta=15\0"
958 "temps_period=15\0"
959 "temps_hysteresis=15\0"
960 "swctrlmap_2g=0x00000404,0x0a0a0000,0x02020000,0x010a02,0x1fe\0"
961 "swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0"
962 "swctrlmap_5g=0x00001010,0x60600000,0x40400000,0x000000,0x0f0\0"
963 "swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0"
964 "powoffs2gtna0=1,3,3,1,0,0,1,2,2,2,1,1,0,0\0"
965 "powoffs2gtna1=-1,1,1,1,0,0,1,2,3,2,2,0,0,0\0"
966 "END\0";
967
968 #endif /* defined(BCMHOSTVARS) */
969 #endif /* !defined(BCMDONGLEHOST) */
970
971 static bool srvars_inited = FALSE; /* Use OTP/SROM as global variables */
972
973 #if (!defined(BCMDONGLEHOST) && defined(BCMHOSTVARS))
974 /* It must end with pattern of "END" */
975 static uint
976 BCMATTACHFN(srom_vars_len)(char *vars)
977 {
978 uint pos = 0;
979 uint len;
980 char *s;
981 char *emark = "END";
982 uint emark_len = strlen(emark) + 1;
983
984 for (s = vars; s && *s;) {
985
986 if (strcmp(s, emark) == 0)
987 break;
988
989 len = strlen(s);
990 s += strlen(s) + 1;
991 pos += len + 1;
992 /* BS_ERROR(("len %d vars[pos] %s\n", pos, s)); */
993 if (pos >= (VARS_MAX - emark_len)) {
994 return 0;
995 }
996 }
997
998 return pos + emark_len; /* include the "END\0" */
999 }
1000 #endif /* BCMHOSTVARS */
1001
1002 #if !defined(BCMDONGLEHOST)
1003 #ifdef BCMNVRAMVARS
1004 static int
1005 BCMATTACHFN(initvars_nvram_vars)(si_t *sih, osl_t *osh, char **vars, uint *vars_sz)
1006 {
1007 int ret;
1008
1009 ASSERT(vars != NULL && vars_sz != NULL);
1010
1011 /* allocate maximum buffer as we don't know big it should be */
1012 *vars = MALLOC(osh, MAXSZ_NVRAM_VARS);
1013 if (*vars == NULL) {
1014 ret = BCME_NOMEM;
1015 goto fail;
1016 }
1017 *vars_sz = MAXSZ_NVRAM_VARS;
1018
1019 /* query the name=value pairs */
1020 if ((ret = nvram_getall(*vars, *vars_sz)) != BCME_OK) {
1021 goto fail;
1022 }
1023
1024 /* treat empty name=value list as an error so that we can indicate
1025 * the condition up throught error code return...
1026 */
1027 if (*vars_sz == 0) {
1028 ret = BCME_ERROR;
1029 goto fail;
1030 }
1031
1032 return BCME_OK;
1033
1034 fail:
1035 if (*vars != NULL) {
1036 MFREE(osh, *vars, MAXSZ_NVRAM_VARS);
1037 }
1038 *vars = NULL;
1039 *vars_sz = 0;
1040 return ret;
1041 }
1042 #endif /* BCMNVRAMVARS */
1043
1044 /**
1045 * Initialize local vars from the right source for this platform. Called from siutils.c.
1046 *
1047 * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
1048 * function set 'vars' to NULL, in that case this function will prematurely return.
1049 *
1050 * Return 0 on success, nonzero on error.
1051 */
1052 int
1053 BCMATTACHFN(srom_var_init)(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh,
1054 char **vars, uint *count)
1055 {
1056 ASSERT(bustype == BUSTYPE(bustype));
1057 if (vars == NULL || count == NULL)
1058 return (0);
1059
1060 *vars = NULL;
1061 *count = 0;
1062
1063 switch (BUSTYPE(bustype)) {
1064 case SI_BUS:
1065 #ifdef BCMPCIEDEV
1066 if (BCMPCIEDEV_ENAB()) {
1067 int ret;
1068
1069 ret = initvars_cis_pci(sih, osh, curmap, vars, count);
1070
1071 #ifdef BCMPCIEDEV_SROM_FORMAT
1072 if (ret)
1073 ret = initvars_srom_pci(sih, curmap, vars, count);
1074 #endif
1075 if (ret)
1076 ret = initvars_srom_si(sih, osh, curmap, vars, count);
1077 return ret;
1078 } else
1079 #endif /* BCMPCIEDEV */
1080 {
1081 return initvars_srom_si(sih, osh, curmap, vars, count);
1082 }
1083 case PCI_BUS: {
1084 int ret;
1085
1086 #ifdef BCMNVRAMVARS
1087 if ((ret = initvars_nvram_vars(sih, osh, vars, count)) == BCME_OK) {
1088 return ret;
1089 } else
1090 #endif
1091 {
1092 ASSERT(curmap != NULL);
1093 if (curmap == NULL)
1094 return (-1);
1095
1096 /* First check for CIS format. if not CIS, try SROM format */
1097 if ((ret = initvars_cis_pci(sih, osh, curmap, vars, count)))
1098 return initvars_srom_pci(sih, curmap, vars, count);
1099 return ret;
1100 }
1101 }
1102
1103 #ifdef BCMSDIO
1104 case SDIO_BUS:
1105 return initvars_cis_sdio(sih, osh, vars, count);
1106 #endif /* BCMSDIO */
1107
1108 #ifdef BCMSPI
1109 case SPI_BUS:
1110 return initvars_cis_spi(sih, osh, vars, count);
1111 #endif /* BCMSPI */
1112
1113 default:
1114 ASSERT(0);
1115 }
1116 return (-1);
1117 }
1118 #endif /* !defined(BCMDONGLEHOST) */
1119
1120 /** support only 16-bit word read from srom */
1121 int
1122 srom_read(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh,
1123 uint byteoff, uint nbytes, uint16 *buf, bool check_crc)
1124 {
1125 uint i, off, nw;
1126
1127 BCM_REFERENCE(i);
1128
1129 ASSERT(bustype == BUSTYPE(bustype));
1130
1131 /* check input - 16-bit access only */
1132 if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX)
1133 return 1;
1134
1135 off = byteoff / 2;
1136 nw = nbytes / 2;
1137
1138 #ifdef BCMPCIEDEV
1139 if ((BUSTYPE(bustype) == SI_BUS) &&
1140 (BCM43602_CHIP(sih->chip) ||
1141 (BCM4369_CHIP(sih->chip)) ||
1142 (BCM4378_CHIP(sih->chip)) ||
1143 (BCM4387_CHIP(sih->chip)) ||
1144 (BCM4388_CHIP(sih->chip)) ||
1145 (BCM4362_CHIP(sih->chip)) ||
1146 (BCM4385_CHIP(sih->chip)) ||
1147 (BCM4389_CHIP(sih->chip)) ||
1148 (BCM4397_CHIP(sih->chip)) ||
1149
1150 #ifdef UNRELEASEDCHIP
1151 #endif
1152
1153 FALSE)) { /* building firmware for chips with a PCIe interface and internal SI bus */
1154 #else
1155 if (BUSTYPE(bustype) == PCI_BUS) {
1156 #endif /* BCMPCIEDEV */
1157 if (!curmap)
1158 return 1;
1159
1160 if (si_is_sprom_available(sih)) {
1161 volatile uint16 *srom;
1162
1163 srom = (volatile uint16 *)srom_offset(sih, curmap);
1164 if (srom == NULL)
1165 return 1;
1166
1167 if (sprom_read_pci(osh, sih, srom, off, buf, nw, check_crc))
1168 return 1;
1169 }
1170 #if !defined(BCMDONGLEHOST) && (defined(BCMNVRAMW) || defined(BCMNVRAMR))
1171 else if (!((BUSTYPE(bustype) == SI_BUS) &&
1172 (BCM43602_CHIP(sih->chip) ||
1173 (BCM4369_CHIP(sih->chip)) ||
1174 (BCM4362_CHIP(sih->chip)) ||
1175 (BCM4378_CHIP(sih->chip)) ||
1176 (BCM4385_CHIP(sih->chip)) ||
1177 (BCM4389_CHIP(sih->chip)) ||
1178 (BCM4387_CHIP(sih->chip)) ||
1179 (BCM4388_CHIP(sih->chip)) ||
1180 (BCM4397_CHIP(sih->chip)) ||
1181 0))) {
1182 if (otp_read_pci(osh, sih, buf, nbytes))
1183 return 1;
1184 }
1185 #endif /* !BCMDONGLEHOST && (BCMNVRAMW||BCMNVRAMR) */
1186 #ifdef BCMSDIO
1187 } else if (BUSTYPE(bustype) == SDIO_BUS) {
1188 off = byteoff / 2;
1189 nw = nbytes / 2;
1190 for (i = 0; i < nw; i++) {
1191 if (sprom_read_sdio(osh, (uint16)(off + i), (uint16 *)(buf + i)))
1192 return 1;
1193 }
1194 #endif /* BCMSDIO */
1195 #ifdef BCMSPI
1196 } else if (BUSTYPE(bustype) == SPI_BUS) {
1197 if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, (uint8 *)buf, byteoff + nbytes) != 0)
1198 return 1;
1199 #endif /* BCMSPI */
1200 } else if (BUSTYPE(bustype) == SI_BUS) {
1201 return 1;
1202 } else {
1203 return 1;
1204 }
1205
1206 return 0;
1207 }
1208
1209 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
1210 /** support only 16-bit word write into srom */
1211 int
1212 srom_write(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh,
1213 uint byteoff, uint nbytes, uint16 *buf)
1214 {
1215 uint i, nw, crc_range;
1216 uint16 *old, *new;
1217 uint8 crc;
1218 volatile uint32 val32;
1219 int rc = 1;
1220
1221 ASSERT(bustype == BUSTYPE(bustype));
1222
1223 /* freed in same function */
1224 old = MALLOC_NOPERSIST(osh, SROM_MAXW * sizeof(uint16));
1225 new = MALLOC_NOPERSIST(osh, SROM_MAXW * sizeof(uint16));
1226
1227 if (old == NULL || new == NULL)
1228 goto done;
1229
1230 /* check input - 16-bit access only. use byteoff 0x55aa to indicate
1231 * srclear
1232 */
1233 if ((byteoff != 0x55aa) && ((byteoff & 1) || (nbytes & 1)))
1234 goto done;
1235
1236 if ((byteoff != 0x55aa) && ((byteoff + nbytes) > SROM_MAX))
1237 goto done;
1238
1239 if (FALSE) {
1240 }
1241 #ifdef BCMSDIO
1242 else if (BUSTYPE(bustype) == SDIO_BUS) {
1243 crc_range = SROM_MAX;
1244 }
1245 #endif
1246 else {
1247 crc_range = srom_size(sih, osh);
1248 }
1249
1250 nw = crc_range / 2;
1251 /* read first small number words from srom, then adjust the length, read all */
1252 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE))
1253 goto done;
1254
1255 BS_ERROR(("srom_write: old[SROM4_SIGN] 0x%x, old[SROM8_SIGN] 0x%x\n",
1256 old[SROM4_SIGN], old[SROM8_SIGN]));
1257 /* Deal with blank srom */
1258 if (old[0] == 0xffff) {
1259 /* Do nothing to blank srom when it's srclear */
1260 if (byteoff == 0x55aa) {
1261 rc = 0;
1262 goto done;
1263 }
1264
1265 /* see if the input buffer is valid SROM image or not */
1266 if (buf[SROM11_SIGN] == SROM11_SIGNATURE) {
1267 BS_ERROR(("srom_write: buf[SROM11_SIGN] 0x%x\n",
1268 buf[SROM11_SIGN]));
1269
1270 /* block invalid buffer size */
1271 if (nbytes < SROM11_WORDS * 2) {
1272 rc = BCME_BUFTOOSHORT;
1273 goto done;
1274 } else if (nbytes > SROM11_WORDS * 2) {
1275 rc = BCME_BUFTOOLONG;
1276 goto done;
1277 }
1278
1279 nw = SROM11_WORDS;
1280
1281 } else if (buf[SROM12_SIGN] == SROM12_SIGNATURE) {
1282 BS_ERROR(("srom_write: buf[SROM12_SIGN] 0x%x\n",
1283 buf[SROM12_SIGN]));
1284
1285 /* block invalid buffer size */
1286 if (nbytes < SROM12_WORDS * 2) {
1287 rc = BCME_BUFTOOSHORT;
1288 goto done;
1289 } else if (nbytes > SROM12_WORDS * 2) {
1290 rc = BCME_BUFTOOLONG;
1291 goto done;
1292 }
1293
1294 nw = SROM12_WORDS;
1295
1296 } else if (buf[SROM13_SIGN] == SROM13_SIGNATURE) {
1297 BS_ERROR(("srom_write: buf[SROM13_SIGN] 0x%x\n",
1298 buf[SROM13_SIGN]));
1299
1300 /* block invalid buffer size */
1301 if (nbytes < SROM13_WORDS * 2) {
1302 rc = BCME_BUFTOOSHORT;
1303 goto done;
1304 } else if (nbytes > SROM13_WORDS * 2) {
1305 rc = BCME_BUFTOOLONG;
1306 goto done;
1307 }
1308
1309 nw = SROM13_WORDS;
1310
1311 } else if (buf[SROM16_SIGN] == SROM16_SIGNATURE) {
1312 BS_ERROR(("srom_write: buf[SROM16_SIGN] 0x%x\n",
1313 buf[SROM16_SIGN]));
1314
1315 /* block invalid buffer size */
1316 if (nbytes < SROM16_WORDS * 2) {
1317 rc = BCME_BUFTOOSHORT;
1318 goto done;
1319 } else if (nbytes > SROM16_WORDS * 2) {
1320 rc = BCME_BUFTOOLONG;
1321 goto done;
1322 }
1323
1324 nw = SROM16_WORDS;
1325
1326 } else if (buf[SROM17_SIGN] == SROM17_SIGNATURE) {
1327 BS_ERROR(("srom_write: buf[SROM17_SIGN] 0x%x\n",
1328 buf[SROM17_SIGN]));
1329
1330 /* block invalid buffer size */
1331 if (nbytes < SROM17_WORDS * 2) {
1332 rc = BCME_BUFTOOSHORT;
1333 goto done;
1334 } else if (nbytes > SROM17_WORDS * 2) {
1335 rc = BCME_BUFTOOLONG;
1336 goto done;
1337 }
1338
1339 nw = SROM17_WORDS;
1340 } else if (buf[SROM18_SIGN] == SROM18_SIGNATURE) {
1341 BS_ERROR(("srom_write: buf[SROM18_SIGN] 0x%x\n",
1342 buf[SROM18_SIGN]));
1343
1344 /* block invalid buffer size */
1345 /* nbytes can be < SROM18 bytes since host limits transfer chunk size
1346 * to 1500 Bytes
1347 */
1348 if (nbytes > SROM18_WORDS * 2) {
1349 rc = BCME_BUFTOOLONG;
1350 goto done;
1351 }
1352
1353 nw = SROM18_WORDS;
1354
1355 } else if (buf[SROM11_SIGN] == SROM15_SIGNATURE) {
1356 BS_ERROR(("srom_write: buf[SROM15_SIGN] 0x%x\n",
1357 buf[SROM11_SIGN]));
1358 /* nbytes can be < SROM15 bytes since host limits trasnfer chunk size
1359 * to 1518 Bytes
1360 */
1361 if (nbytes > SROM15_WORDS * 2) {
1362 rc = BCME_BUFTOOLONG;
1363 goto done;
1364 }
1365 nw = SROM15_WORDS;
1366 } else if ((buf[SROM4_SIGN] == SROM4_SIGNATURE) ||
1367 (buf[SROM8_SIGN] == SROM4_SIGNATURE)) {
1368 BS_ERROR(("srom_write: buf[SROM4_SIGN] 0x%x, buf[SROM8_SIGN] 0x%x\n",
1369 buf[SROM4_SIGN], buf[SROM8_SIGN]));
1370
1371 /* block invalid buffer size */
1372 if (nbytes < SROM4_WORDS * 2) {
1373 rc = BCME_BUFTOOSHORT;
1374 goto done;
1375 } else if (nbytes > SROM4_WORDS * 2) {
1376 rc = BCME_BUFTOOLONG;
1377 goto done;
1378 }
1379
1380 nw = SROM4_WORDS;
1381 } else if (nbytes == SROM_WORDS * 2){ /* the other possible SROM format */
1382 BS_ERROR(("srom_write: Not SROM4 or SROM8.\n"));
1383
1384 nw = SROM_WORDS;
1385 } else {
1386 BS_ERROR(("srom_write: Invalid input file signature\n"));
1387 rc = BCME_BADARG;
1388 goto done;
1389 }
1390 crc_range = nw * 2;
1391 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1392 goto done;
1393 }
1394 } else if (old[SROM18_SIGN] == SROM18_SIGNATURE) {
1395 nw = SROM18_WORDS;
1396 crc_range = nw * 2;
1397 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1398 goto done;
1399 }
1400 } else if (old[SROM17_SIGN] == SROM17_SIGNATURE) {
1401 nw = SROM17_WORDS;
1402 crc_range = nw * 2;
1403 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1404 goto done;
1405 }
1406 } else if (old[SROM16_SIGN] == SROM16_SIGNATURE) {
1407 nw = SROM16_WORDS;
1408 crc_range = nw * 2;
1409 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1410 goto done;
1411 }
1412 } else if (old[SROM15_SIGN] == SROM15_SIGNATURE) {
1413 nw = SROM15_WORDS;
1414 crc_range = nw * 2;
1415 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1416 goto done;
1417 }
1418 } else if (old[SROM13_SIGN] == SROM13_SIGNATURE) {
1419 nw = SROM13_WORDS;
1420 crc_range = nw * 2;
1421 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1422 goto done;
1423 }
1424 } else if (old[SROM12_SIGN] == SROM12_SIGNATURE) {
1425 nw = SROM12_WORDS;
1426 crc_range = nw * 2;
1427 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1428 goto done;
1429 }
1430 } else if (old[SROM11_SIGN] == SROM11_SIGNATURE) {
1431 nw = SROM11_WORDS;
1432 crc_range = nw * 2;
1433 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1434 goto done;
1435 }
1436 } else if ((old[SROM4_SIGN] == SROM4_SIGNATURE) ||
1437 (old[SROM8_SIGN] == SROM4_SIGNATURE)) {
1438 nw = SROM4_WORDS;
1439 crc_range = nw * 2;
1440 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1441 goto done;
1442 }
1443 } else {
1444 /* Assert that we have already read enough for sromrev 2 */
1445 ASSERT(crc_range >= SROM_WORDS * 2);
1446 nw = SROM_WORDS;
1447 crc_range = nw * 2;
1448 }
1449
1450 if (byteoff == 0x55aa) {
1451 /* Erase request */
1452 crc_range = 0;
1453 memset((void *)new, 0xff, nw * 2);
1454 } else {
1455 /* Copy old contents */
1456 bcopy((void *)old, (void *)new, nw * 2);
1457 /* make changes */
1458 bcopy((void *)buf, (void *)&new[byteoff / 2], nbytes);
1459 }
1460
1461 if (crc_range) {
1462 /* calculate crc */
1463 htol16_buf(new, crc_range);
1464 crc = ~hndcrc8((uint8 *)new, crc_range - 1, CRC8_INIT_VALUE);
1465 ltoh16_buf(new, crc_range);
1466 new[nw - 1] = (crc << 8) | (new[nw - 1] & 0xff);
1467 }
1468
1469 #ifdef BCMPCIEDEV
1470 if ((BUSTYPE(bustype) == SI_BUS) &&
1471 (BCM43602_CHIP(sih->chip) ||
1472 (BCM4369_CHIP(sih->chip)) ||
1473 (BCM4362_CHIP(sih->chip)) ||
1474 (BCM4378_CHIP(sih->chip)) ||
1475 (BCM4387_CHIP(sih->chip)) ||
1476 (BCM4388_CHIP(sih->chip)) ||
1477 (BCM4385_CHIP(sih->chip)) ||
1478 (BCM4389_CHIP(sih->chip)) ||
1479 (BCM4397_CHIP(sih->chip)) ||
1480
1481 #ifdef UNRELEASEDCHIP
1482 #endif /* UNRELEASEDCHIP */
1483
1484 FALSE)) {
1485 #else
1486 if (BUSTYPE(bustype) == PCI_BUS) {
1487 #endif /* BCMPCIEDEV */
1488 volatile uint16 *srom = NULL;
1489 volatile void *ccregs = NULL;
1490 uint32 ccval = 0;
1491
1492 if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1493 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1494 (CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
1495 (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
1496 BCM43602_CHIP(sih->chip)) {
1497 /* save current control setting */
1498 ccval = si_chipcontrl_read(sih);
1499 }
1500
1501 if (BCM43602_CHIP(sih->chip) ||
1502 (((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1503 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1504 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
1505 (CHIPREV(sih->chiprev) <= 2))) {
1506 si_chipcontrl_srom4360(sih, TRUE);
1507 }
1508
1509 if (FALSE) {
1510 si_srom_clk_set(sih); /* corrects srom clock frequency */
1511 }
1512
1513 /* enable writes to the SPROM */
1514 if (sih->ccrev > 31) {
1515 if (BUSTYPE(sih->bustype) == SI_BUS)
1516 ccregs = (void *)(uintptr)SI_ENUM_BASE(sih);
1517 else
1518 ccregs = ((volatile uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET);
1519 srom = (volatile uint16 *)((volatile uint8 *)ccregs + CC_SROM_OTP);
1520 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0);
1521 } else {
1522 srom = (volatile uint16 *)
1523 ((volatile uint8 *)curmap + PCI_BAR0_SPROM_OFFSET);
1524 val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
1525 val32 |= SPROM_WRITEEN;
1526 OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
1527 }
1528 bcm_mdelay(WRITE_ENABLE_DELAY);
1529 /* write srom */
1530 for (i = 0; i < nw; i++) {
1531 if (old[i] != new[i]) {
1532 if (sih->ccrev > 31) {
1533 if ((sih->cccaps & CC_CAP_SROM) == 0) {
1534 /* No srom support in this chip */
1535 BS_ERROR(("srom_write, invalid srom, skip\n"));
1536 } else
1537 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE,
1538 i, new[i]);
1539 } else {
1540 W_REG(osh, &srom[i], new[i]);
1541 }
1542 bcm_mdelay(WRITE_WORD_DELAY);
1543 }
1544 }
1545 /* disable writes to the SPROM */
1546 if (sih->ccrev > 31) {
1547 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0);
1548 } else {
1549 OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 &
1550 ~SPROM_WRITEEN);
1551 }
1552
1553 if (BCM43602_CHIP(sih->chip) ||
1554 (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1555 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1556 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
1557 /* Restore config after reading SROM */
1558 si_chipcontrl_restore(sih, ccval);
1559 }
1560 #ifdef BCMSDIO
1561 } else if (BUSTYPE(bustype) == SDIO_BUS) {
1562 /* enable writes to the SPROM */
1563 if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WEN))
1564 goto done;
1565 bcm_mdelay(WRITE_ENABLE_DELAY);
1566 /* write srom */
1567 for (i = 0; i < nw; i++) {
1568 if (old[i] != new[i]) {
1569 sprom_write_sdio(osh, (uint16)(i), new[i]);
1570 bcm_mdelay(WRITE_WORD_DELAY);
1571 }
1572 }
1573 /* disable writes to the SPROM */
1574 if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WDS))
1575 goto done;
1576 #endif /* BCMSDIO */
1577 } else if (BUSTYPE(bustype) == SI_BUS) {
1578 goto done;
1579 } else {
1580 goto done;
1581 }
1582
1583 bcm_mdelay(WRITE_ENABLE_DELAY);
1584 rc = 0;
1585
1586 done:
1587 if (old != NULL)
1588 MFREE(osh, old, SROM_MAXW * sizeof(uint16));
1589 if (new != NULL)
1590 MFREE(osh, new, SROM_MAXW * sizeof(uint16));
1591
1592 return rc;
1593 }
1594
1595 /** support only 16-bit word write into srom */
1596 int
1597 srom_write_short(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh,
1598 uint byteoff, uint16 value)
1599 {
1600 volatile uint32 val32;
1601 int rc = 1;
1602
1603 ASSERT(bustype == BUSTYPE(bustype));
1604
1605 if (byteoff & 1)
1606 goto done;
1607
1608 #ifdef BCMPCIEDEV
1609 if ((BUSTYPE(bustype) == SI_BUS) &&
1610 (BCM43602_CHIP(sih->chip) ||
1611 FALSE)) {
1612 #else
1613 if (BUSTYPE(bustype) == PCI_BUS) {
1614 #endif /* BCMPCIEDEV */
1615 volatile uint16 *srom = NULL;
1616 volatile void *ccregs = NULL;
1617 uint32 ccval = 0;
1618
1619 if (BCM43602_CHIP(sih->chip) ||
1620 (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1621 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1622 (CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
1623 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
1624 /* save current control setting */
1625 ccval = si_chipcontrl_read(sih);
1626 }
1627
1628 if (BCM43602_CHIP(sih->chip) ||
1629 (((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1630 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1631 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
1632 (CHIPREV(sih->chiprev) <= 2))) {
1633 si_chipcontrl_srom4360(sih, TRUE);
1634 }
1635
1636 if (FALSE) {
1637 si_srom_clk_set(sih); /* corrects srom clock frequency */
1638 }
1639
1640 /* enable writes to the SPROM */
1641 if (sih->ccrev > 31) {
1642 if (BUSTYPE(sih->bustype) == SI_BUS)
1643 ccregs = (void *)(uintptr)SI_ENUM_BASE(sih);
1644 else
1645 ccregs = ((volatile uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET);
1646 srom = (volatile uint16 *)((volatile uint8 *)ccregs + CC_SROM_OTP);
1647 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0);
1648 } else {
1649 srom = (volatile uint16 *)
1650 ((volatile uint8 *)curmap + PCI_BAR0_SPROM_OFFSET);
1651 val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
1652 val32 |= SPROM_WRITEEN;
1653 OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
1654 }
1655 bcm_mdelay(WRITE_ENABLE_DELAY);
1656 /* write srom */
1657 if (sih->ccrev > 31) {
1658 if ((sih->cccaps & CC_CAP_SROM) == 0) {
1659 /* No srom support in this chip */
1660 BS_ERROR(("srom_write, invalid srom, skip\n"));
1661 } else
1662 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE,
1663 byteoff/2, value);
1664 } else {
1665 W_REG(osh, &srom[byteoff/2], value);
1666 }
1667 bcm_mdelay(WRITE_WORD_DELAY);
1668
1669 /* disable writes to the SPROM */
1670 if (sih->ccrev > 31) {
1671 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0);
1672 } else {
1673 OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 &
1674 ~SPROM_WRITEEN);
1675 }
1676
1677 if (BCM43602_CHIP(sih->chip) ||
1678 (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1679 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1680 (CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
1681 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
1682 /* Restore config after reading SROM */
1683 si_chipcontrl_restore(sih, ccval);
1684 }
1685 #ifdef BCMSDIO
1686 } else if (BUSTYPE(bustype) == SDIO_BUS) {
1687 /* enable writes to the SPROM */
1688 if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WEN))
1689 goto done;
1690 bcm_mdelay(WRITE_ENABLE_DELAY);
1691 /* write srom */
1692 sprom_write_sdio(osh, (uint16)(byteoff/2), value);
1693 bcm_mdelay(WRITE_WORD_DELAY);
1694
1695 /* disable writes to the SPROM */
1696 if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WDS))
1697 goto done;
1698 #endif /* BCMSDIO */
1699 } else if (BUSTYPE(bustype) == SI_BUS) {
1700 goto done;
1701 } else {
1702 goto done;
1703 }
1704
1705 bcm_mdelay(WRITE_ENABLE_DELAY);
1706 rc = 0;
1707
1708 done:
1709 return rc;
1710 }
1711 #endif /* defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) */
1712
1713 /**
1714 * These 'vstr_*' definitions are used to convert from CIS format to a 'NVRAM var=val' format, the
1715 * NVRAM format is used throughout the rest of the firmware.
1716 */
1717 #if !defined(BCMDONGLEHOST)
1718 static const char BCMATTACHDATA(vstr_manf)[] = "manf=%s";
1719 static const char BCMATTACHDATA(vstr_productname)[] = "productname=%s";
1720 static const char BCMATTACHDATA(vstr_manfid)[] = "manfid=0x%x";
1721 static const char BCMATTACHDATA(vstr_prodid)[] = "prodid=0x%x";
1722 #ifdef BCMSDIO
1723 static const char BCMATTACHDATA(vstr_sdmaxspeed)[] = "sdmaxspeed=%d";
1724 static const char BCMATTACHDATA(vstr_sdmaxblk)[][13] =
1725 { "sdmaxblk0=%d", "sdmaxblk1=%d", "sdmaxblk2=%d" };
1726 #endif
1727 static const char BCMATTACHDATA(vstr_regwindowsz)[] = "regwindowsz=%d";
1728 static const char BCMATTACHDATA(vstr_sromrev)[] = "sromrev=%d";
1729 static const char BCMATTACHDATA(vstr_chiprev)[] = "chiprev=%d";
1730 static const char BCMATTACHDATA(vstr_subvendid)[] = "subvendid=0x%x";
1731 static const char BCMATTACHDATA(vstr_subdevid)[] = "subdevid=0x%x";
1732 static const char BCMATTACHDATA(vstr_boardrev)[] = "boardrev=0x%x";
1733 static const char BCMATTACHDATA(vstr_aa2g)[] = "aa2g=0x%x";
1734 static const char BCMATTACHDATA(vstr_aa5g)[] = "aa5g=0x%x";
1735 static const char BCMATTACHDATA(vstr_ag)[] = "ag%d=0x%x";
1736 static const char BCMATTACHDATA(vstr_cc)[] = "cc=%d";
1737 static const char BCMATTACHDATA(vstr_opo)[] = "opo=%d";
1738 static const char BCMATTACHDATA(vstr_pa0b)[][9] = { "pa0b0=%d", "pa0b1=%d", "pa0b2=%d" };
1739 static const char BCMATTACHDATA(vstr_pa0b_lo)[][12] =
1740 { "pa0b0_lo=%d", "pa0b1_lo=%d", "pa0b2_lo=%d" };
1741 static const char BCMATTACHDATA(vstr_pa0itssit)[] = "pa0itssit=%d";
1742 static const char BCMATTACHDATA(vstr_pa0maxpwr)[] = "pa0maxpwr=%d";
1743 static const char BCMATTACHDATA(vstr_pa1b)[][9] = { "pa1b0=%d", "pa1b1=%d", "pa1b2=%d" };
1744 static const char BCMATTACHDATA(vstr_pa1lob)[][11] =
1745 { "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d" };
1746 static const char BCMATTACHDATA(vstr_pa1hib)[][11] =
1747 { "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d" };
1748 static const char BCMATTACHDATA(vstr_pa1itssit)[] = "pa1itssit=%d";
1749 static const char BCMATTACHDATA(vstr_pa1maxpwr)[] = "pa1maxpwr=%d";
1750 static const char BCMATTACHDATA(vstr_pa1lomaxpwr)[] = "pa1lomaxpwr=%d";
1751 static const char BCMATTACHDATA(vstr_pa1himaxpwr)[] = "pa1himaxpwr=%d";
1752 static const char BCMATTACHDATA(vstr_oem)[] = "oem=%02x%02x%02x%02x%02x%02x%02x%02x";
1753 static const char BCMATTACHDATA(vstr_boardflags)[] = "boardflags=0x%x";
1754 static const char BCMATTACHDATA(vstr_boardflags2)[] = "boardflags2=0x%x";
1755 static const char BCMATTACHDATA(vstr_boardflags3)[] = "boardflags3=0x%x";
1756 static const char BCMATTACHDATA(vstr_boardflags4)[] = "boardflags4=0x%x";
1757 static const char BCMATTACHDATA(vstr_boardflags5)[] = "boardflags5=0x%x";
1758 static const char BCMATTACHDATA(vstr_noccode)[] = "ccode=0x0";
1759 static const char BCMATTACHDATA(vstr_ccode)[] = "ccode=%c%c";
1760 static const char BCMATTACHDATA(vstr_cctl)[] = "cctl=0x%x";
1761 static const char BCMATTACHDATA(vstr_cckpo)[] = "cckpo=0x%x";
1762 static const char BCMATTACHDATA(vstr_ofdmpo)[] = "ofdmpo=0x%x";
1763 static const char BCMATTACHDATA(vstr_rdlid)[] = "rdlid=0x%x";
1764 #ifdef BCM_BOOTLOADER
1765 static const char BCMATTACHDATA(vstr_rdlrndis)[] = "rdlrndis=%d";
1766 static const char BCMATTACHDATA(vstr_rdlrwu)[] = "rdlrwu=%d";
1767 static const char BCMATTACHDATA(vstr_rdlsn)[] = "rdlsn=%d";
1768 #endif /* BCM_BOOTLOADER */
1769 static const char BCMATTACHDATA(vstr_usbfs)[] = "usbfs=%d";
1770 static const char BCMATTACHDATA(vstr_wpsgpio)[] = "wpsgpio=%d";
1771 static const char BCMATTACHDATA(vstr_wpsled)[] = "wpsled=%d";
1772 static const char BCMATTACHDATA(vstr_rssismf2g)[] = "rssismf2g=%d";
1773 static const char BCMATTACHDATA(vstr_rssismc2g)[] = "rssismc2g=%d";
1774 static const char BCMATTACHDATA(vstr_rssisav2g)[] = "rssisav2g=%d";
1775 static const char BCMATTACHDATA(vstr_bxa2g)[] = "bxa2g=%d";
1776 static const char BCMATTACHDATA(vstr_rssismf5g)[] = "rssismf5g=%d";
1777 static const char BCMATTACHDATA(vstr_rssismc5g)[] = "rssismc5g=%d";
1778 static const char BCMATTACHDATA(vstr_rssisav5g)[] = "rssisav5g=%d";
1779 static const char BCMATTACHDATA(vstr_bxa5g)[] = "bxa5g=%d";
1780 static const char BCMATTACHDATA(vstr_tri2g)[] = "tri2g=%d";
1781 static const char BCMATTACHDATA(vstr_tri5gl)[] = "tri5gl=%d";
1782 static const char BCMATTACHDATA(vstr_tri5g)[] = "tri5g=%d";
1783 static const char BCMATTACHDATA(vstr_tri5gh)[] = "tri5gh=%d";
1784 static const char BCMATTACHDATA(vstr_rxpo2g)[] = "rxpo2g=%d";
1785 static const char BCMATTACHDATA(vstr_rxpo5g)[] = "rxpo5g=%d";
1786 static const char BCMATTACHDATA(vstr_boardtype)[] = "boardtype=0x%x";
1787 static const char BCMATTACHDATA(vstr_vendid)[] = "vendid=0x%x";
1788 static const char BCMATTACHDATA(vstr_devid)[] = "devid=0x%x";
1789 static const char BCMATTACHDATA(vstr_xtalfreq)[] = "xtalfreq=%d";
1790 static const char BCMATTACHDATA(vstr_txchain)[] = "txchain=0x%x";
1791 static const char BCMATTACHDATA(vstr_rxchain)[] = "rxchain=0x%x";
1792 static const char BCMATTACHDATA(vstr_elna2g)[] = "elna2g=0x%x";
1793 static const char BCMATTACHDATA(vstr_elna5g)[] = "elna5g=0x%x";
1794 static const char BCMATTACHDATA(vstr_antswitch)[] = "antswitch=0x%x";
1795 static const char BCMATTACHDATA(vstr_regrev)[] = "regrev=0x%x";
1796 static const char BCMATTACHDATA(vstr_antswctl2g)[] = "antswctl2g=0x%x";
1797 static const char BCMATTACHDATA(vstr_triso2g)[] = "triso2g=0x%x";
1798 static const char BCMATTACHDATA(vstr_pdetrange2g)[] = "pdetrange2g=0x%x";
1799 static const char BCMATTACHDATA(vstr_extpagain2g)[] = "extpagain2g=0x%x";
1800 static const char BCMATTACHDATA(vstr_tssipos2g)[] = "tssipos2g=0x%x";
1801 static const char BCMATTACHDATA(vstr_antswctl5g)[] = "antswctl5g=0x%x";
1802 static const char BCMATTACHDATA(vstr_triso5g)[] = "triso5g=0x%x";
1803 static const char BCMATTACHDATA(vstr_pdetrange5g)[] = "pdetrange5g=0x%x";
1804 static const char BCMATTACHDATA(vstr_extpagain5g)[] = "extpagain5g=0x%x";
1805 static const char BCMATTACHDATA(vstr_tssipos5g)[] = "tssipos5g=0x%x";
1806 static const char BCMATTACHDATA(vstr_maxp2ga)[] = "maxp2ga%d=0x%x";
1807 static const char BCMATTACHDATA(vstr_itt2ga0)[] = "itt2ga0=0x%x";
1808 static const char BCMATTACHDATA(vstr_pa)[] = "pa%dgw%da%d=0x%x";
1809 static const char BCMATTACHDATA(vstr_pahl)[] = "pa%dg%cw%da%d=0x%x";
1810 static const char BCMATTACHDATA(vstr_maxp5ga0)[] = "maxp5ga0=0x%x";
1811 static const char BCMATTACHDATA(vstr_itt5ga0)[] = "itt5ga0=0x%x";
1812 static const char BCMATTACHDATA(vstr_maxp5gha0)[] = "maxp5gha0=0x%x";
1813 static const char BCMATTACHDATA(vstr_maxp5gla0)[] = "maxp5gla0=0x%x";
1814 static const char BCMATTACHDATA(vstr_itt2ga1)[] = "itt2ga1=0x%x";
1815 static const char BCMATTACHDATA(vstr_maxp5ga1)[] = "maxp5ga1=0x%x";
1816 static const char BCMATTACHDATA(vstr_itt5ga1)[] = "itt5ga1=0x%x";
1817 static const char BCMATTACHDATA(vstr_maxp5gha1)[] = "maxp5gha1=0x%x";
1818 static const char BCMATTACHDATA(vstr_maxp5gla1)[] = "maxp5gla1=0x%x";
1819 static const char BCMATTACHDATA(vstr_cck2gpo)[] = "cck2gpo=0x%x";
1820 static const char BCMATTACHDATA(vstr_ofdm2gpo)[] = "ofdm2gpo=0x%x";
1821 static const char BCMATTACHDATA(vstr_ofdm5gpo)[] = "ofdm5gpo=0x%x";
1822 static const char BCMATTACHDATA(vstr_ofdm5glpo)[] = "ofdm5glpo=0x%x";
1823 static const char BCMATTACHDATA(vstr_ofdm5ghpo)[] = "ofdm5ghpo=0x%x";
1824 static const char BCMATTACHDATA(vstr_cddpo)[] = "cddpo=0x%x";
1825 static const char BCMATTACHDATA(vstr_stbcpo)[] = "stbcpo=0x%x";
1826 static const char BCMATTACHDATA(vstr_bw40po)[] = "bw40po=0x%x";
1827 static const char BCMATTACHDATA(vstr_bwduppo)[] = "bwduppo=0x%x";
1828 static const char BCMATTACHDATA(vstr_mcspo)[] = "mcs%dgpo%d=0x%x";
1829 static const char BCMATTACHDATA(vstr_mcspohl)[] = "mcs%dg%cpo%d=0x%x";
1830 static const char BCMATTACHDATA(vstr_custom)[] = "customvar%d=0x%x";
1831 static const char BCMATTACHDATA(vstr_cckdigfilttype)[] = "cckdigfilttype=%d";
1832 static const char BCMATTACHDATA(vstr_usbflags)[] = "usbflags=0x%x";
1833 #ifdef BCM_BOOTLOADER
1834 static const char BCMATTACHDATA(vstr_mdio)[] = "mdio%d=0x%%x";
1835 static const char BCMATTACHDATA(vstr_mdioex)[] = "mdioex%d=0x%%x";
1836 static const char BCMATTACHDATA(vstr_brmin)[] = "brmin=0x%x";
1837 static const char BCMATTACHDATA(vstr_brmax)[] = "brmax=0x%x";
1838 static const char BCMATTACHDATA(vstr_pllreg)[] = "pll%d=0x%x";
1839 static const char BCMATTACHDATA(vstr_ccreg)[] = "chipc%d=0x%x";
1840 static const char BCMATTACHDATA(vstr_regctrl)[] = "reg%d=0x%x";
1841 static const char BCMATTACHDATA(vstr_time)[] = "r%dt=0x%x";
1842 static const char BCMATTACHDATA(vstr_depreg)[] = "r%dd=0x%x";
1843 static const char BCMATTACHDATA(vstr_usbpredly)[] = "usbpredly=0x%x";
1844 static const char BCMATTACHDATA(vstr_usbpostdly)[] = "usbpostdly=0x%x";
1845 static const char BCMATTACHDATA(vstr_usbrdy)[] = "usbrdy=0x%x";
1846 static const char BCMATTACHDATA(vstr_hsicphyctrl1)[] = "hsicphyctrl1=0x%x";
1847 static const char BCMATTACHDATA(vstr_hsicphyctrl2)[] = "hsicphyctrl2=0x%x";
1848 static const char BCMATTACHDATA(vstr_usbdevctrl)[] = "usbdevctrl=0x%x";
1849 static const char BCMATTACHDATA(vstr_bldr_reset_timeout)[] = "bldr_to=0x%x";
1850 static const char BCMATTACHDATA(vstr_muxenab)[] = "muxenab=0x%x";
1851 static const char BCMATTACHDATA(vstr_pubkey)[] = "pubkey=%s";
1852 #endif /* BCM_BOOTLOADER */
1853 static const char BCMATTACHDATA(vstr_boardnum)[] = "boardnum=%d";
1854 static const char BCMATTACHDATA(vstr_macaddr)[] = "macaddr=%s";
1855 static const char BCMATTACHDATA(vstr_macaddr2)[] = "macaddr2=%s";
1856 static const char BCMATTACHDATA(vstr_usbepnum)[] = "usbepnum=0x%x";
1857 #ifdef BCMUSBDEV_COMPOSITE
1858 static const char BCMATTACHDATA(vstr_usbdesc_composite)[] = "usbdesc_composite=0x%x";
1859 #endif /* BCMUSBDEV_COMPOSITE */
1860 static const char BCMATTACHDATA(vstr_usbutmi_ctl)[] = "usbutmi_ctl=0x%x";
1861 static const char BCMATTACHDATA(vstr_usbssphy_utmi_ctl0)[] = "usbssphy_utmi_ctl0=0x%x";
1862 static const char BCMATTACHDATA(vstr_usbssphy_utmi_ctl1)[] = "usbssphy_utmi_ctl1=0x%x";
1863 static const char BCMATTACHDATA(vstr_usbssphy_utmi_ctl2)[] = "usbssphy_utmi_ctl2=0x%x";
1864 static const char BCMATTACHDATA(vstr_usbssphy_sleep0)[] = "usbssphy_sleep0=0x%x";
1865 static const char BCMATTACHDATA(vstr_usbssphy_sleep1)[] = "usbssphy_sleep1=0x%x";
1866 static const char BCMATTACHDATA(vstr_usbssphy_sleep2)[] = "usbssphy_sleep2=0x%x";
1867 static const char BCMATTACHDATA(vstr_usbssphy_sleep3)[] = "usbssphy_sleep3=0x%x";
1868 static const char BCMATTACHDATA(vstr_usbssphy_mdio)[] = "usbssmdio%d=0x%x,0x%x,0x%x,0x%x";
1869 static const char BCMATTACHDATA(vstr_usb30phy_noss)[] = "usbnoss=0x%x";
1870 static const char BCMATTACHDATA(vstr_usb30phy_u1u2)[] = "usb30u1u2=0x%x";
1871 static const char BCMATTACHDATA(vstr_usb30phy_regs)[] = "usb30regs%d=0x%x,0x%x,0x%x,0x%x";
1872
1873 /* Power per rate for SROM V9 */
1874 static const char BCMATTACHDATA(vstr_cckbw202gpo)[][21] =
1875 { "cckbw202gpo=0x%x", "cckbw20ul2gpo=0x%x", "cckbw20in802gpo=0x%x" };
1876 static const char BCMATTACHDATA(vstr_legofdmbw202gpo)[][23] =
1877 { "legofdmbw202gpo=0x%x", "legofdmbw20ul2gpo=0x%x" };
1878 static const char BCMATTACHDATA(vstr_legofdmbw205gpo)[][24] =
1879 { "legofdmbw205glpo=0x%x", "legofdmbw20ul5glpo=0x%x",
1880 "legofdmbw205gmpo=0x%x", "legofdmbw20ul5gmpo=0x%x",
1881 "legofdmbw205ghpo=0x%x", "legofdmbw20ul5ghpo=0x%x" };
1882
1883 static const char BCMATTACHDATA(vstr_mcs2gpo)[][19] =
1884 { "mcsbw202gpo=0x%x", "mcsbw20ul2gpo=0x%x", "mcsbw402gpo=0x%x", "mcsbw802gpo=0x%x" };
1885
1886 static const char BCMATTACHDATA(vstr_mcs5glpo)[][20] =
1887 { "mcsbw205glpo=0x%x", "mcsbw20ul5glpo=0x%x", "mcsbw405glpo=0x%x" };
1888
1889 static const char BCMATTACHDATA(vstr_mcs5gmpo)[][20] =
1890 { "mcsbw205gmpo=0x%x", "mcsbw20ul5gmpo=0x%x", "mcsbw405gmpo=0x%x" };
1891
1892 static const char BCMATTACHDATA(vstr_mcs5ghpo)[][20] =
1893 { "mcsbw205ghpo=0x%x", "mcsbw20ul5ghpo=0x%x", "mcsbw405ghpo=0x%x" };
1894
1895 static const char BCMATTACHDATA(vstr_mcs32po)[] = "mcs32po=0x%x";
1896 static const char BCMATTACHDATA(vstr_legofdm40duppo)[] = "legofdm40duppo=0x%x";
1897
1898 /* SROM V11 */
1899 static const char BCMATTACHDATA(vstr_tempthresh)[] = "tempthresh=%d"; /* HNBU_TEMPTHRESH */
1900 static const char BCMATTACHDATA(vstr_temps_period)[] = "temps_period=%d";
1901 static const char BCMATTACHDATA(vstr_temps_hysteresis)[] = "temps_hysteresis=%d";
1902 static const char BCMATTACHDATA(vstr_tempoffset)[] = "tempoffset=%d";
1903 static const char BCMATTACHDATA(vstr_tempsense_slope)[] = "tempsense_slope=%d";
1904 static const char BCMATTACHDATA(vstr_temp_corrx)[] = "tempcorrx=%d";
1905 static const char BCMATTACHDATA(vstr_tempsense_option)[] = "tempsense_option=%d";
1906 static const char BCMATTACHDATA(vstr_phycal_tempdelta)[] = "phycal_tempdelta=%d";
1907 static const char BCMATTACHDATA(vstr_tssiposslopeg)[] = "tssiposslope%dg=%d"; /* HNBU_FEM_CFG */
1908 static const char BCMATTACHDATA(vstr_epagaing)[] = "epagain%dg=%d";
1909 static const char BCMATTACHDATA(vstr_pdgaing)[] = "pdgain%dg=%d";
1910 static const char BCMATTACHDATA(vstr_tworangetssi)[] = "tworangetssi%dg=%d";
1911 static const char BCMATTACHDATA(vstr_papdcap)[] = "papdcap%dg=%d";
1912 static const char BCMATTACHDATA(vstr_femctrl)[] = "femctrl=%d";
1913 static const char BCMATTACHDATA(vstr_gainctrlsph)[] = "gainctrlsph=%d";
1914 static const char BCMATTACHDATA(vstr_subband5gver)[] = "subband5gver=%d"; /* HNBU_ACPA_CX */
1915 static const char BCMATTACHDATA(vstr_pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x";
1916 static const char BCMATTACHDATA(vstr_maxp5ga)[] = "maxp5ga%d=0x%x,0x%x,0x%x,0x%x";
1917 static const char BCMATTACHDATA(vstr_pa5ga)[] = "pa5ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1918 "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1919 static const char BCMATTACHDATA(vstr_subband6gver)[] = "subband6gver=%d"; /* HNBU_ACPA_CX */
1920 static const char BCMATTACHDATA(vstr_maxp6ga)[] = "maxp6ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1921 static const char BCMATTACHDATA(vstr_pa6ga)[] = "pa6ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1922 "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1923 static const char BCMATTACHDATA(vstr_pa2gccka)[] = "pa2gccka%d=0x%x,0x%x,0x%x";
1924 static const char BCMATTACHDATA(vstr_pa5gbw40a)[] = "pa5gbw40a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1925 "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1926 static const char BCMATTACHDATA(vstr_pa5gbw80a)[] = "pa5gbw80a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1927 "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1928 static const char BCMATTACHDATA(vstr_pa5gbw4080a)[] = "pa5gbw4080a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1929 "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1930 static const char BCMATTACHDATA(vstr_rxgainsgelnagaina)[] = "rxgains%dgelnagaina%d=%d";
1931 static const char BCMATTACHDATA(vstr_rxgainsgtrisoa)[] = "rxgains%dgtrisoa%d=%d";
1932 static const char BCMATTACHDATA(vstr_rxgainsgtrelnabypa)[] = "rxgains%dgtrelnabypa%d=%d";
1933 static const char BCMATTACHDATA(vstr_rxgainsgxelnagaina)[] = "rxgains%dg%celnagaina%d=%d";
1934 static const char BCMATTACHDATA(vstr_rxgainsgxtrisoa)[] = "rxgains%dg%ctrisoa%d=%d";
1935 static const char BCMATTACHDATA(vstr_rxgainsgxtrelnabypa)[] = "rxgains%dg%ctrelnabypa%d=%d";
1936 static const char BCMATTACHDATA(vstr_measpower)[] = "measpower=0x%x"; /* HNBU_MEAS_PWR */
1937 static const char BCMATTACHDATA(vstr_measpowerX)[] = "measpower%d=0x%x";
1938 static const char BCMATTACHDATA(vstr_pdoffsetma)[] = "pdoffset%dma%d=0x%x"; /* HNBU_PDOFF */
1939 static const char BCMATTACHDATA(vstr_pdoffset2gma)[] = "pdoffset2g%dma%d=0x%x"; /* HNBU_PDOFF_2G */
1940 static const char BCMATTACHDATA(vstr_pdoffset2gmvalid)[] = "pdoffset2g%dmvalid=0x%x";
1941 static const char BCMATTACHDATA(vstr_rawtempsense)[] = "rawtempsense=0x%x";
1942 /* HNBU_ACPPR_2GPO */
1943 static const char BCMATTACHDATA(vstr_dot11agofdmhrbw202gpo)[] = "dot11agofdmhrbw202gpo=0x%x";
1944 static const char BCMATTACHDATA(vstr_ofdmlrbw202gpo)[] = "ofdmlrbw202gpo=0x%x";
1945 static const char BCMATTACHDATA(vstr_mcsbw805gpo)[] = "mcsbw805g%cpo=0x%x"; /* HNBU_ACPPR_5GPO */
1946 static const char BCMATTACHDATA(vstr_mcsbw1605gpo)[] = "mcsbw1605g%cpo=0x%x";
1947 static const char BCMATTACHDATA(vstr_mcsbw80p805gpo)[] = "mcsbw80p805g%cpo=0x%x";
1948 static const char BCMATTACHDATA(vstr_mcsbw80p805g1po)[] = "mcsbw80p805g%c1po=0x%x";
1949 static const char BCMATTACHDATA(vstr_mcsbw1605g1po)[] = "mcsbw1605g%c1po=0x%x";
1950 static const char BCMATTACHDATA(vstr_mcsbw805g1po)[] = "mcsbw805g%c1po=0x%x";
1951 static const char BCMATTACHDATA(vstr_mcsbw405g1po)[] = "mcsbw405g%c1po=0x%x";
1952 static const char BCMATTACHDATA(vstr_mcsbw205g1po)[] = "mcsbw205g%c1po=0x%x";
1953 static const char BCMATTACHDATA(vstr_mcslr5gpo)[] = "mcslr5g%cpo=0x%x";
1954 static const char BCMATTACHDATA(vstr_mcslr5g1po)[] = "mcslr5g%c1po=0x%x";
1955 static const char BCMATTACHDATA(vstr_mcslr5g80p80po)[] = "mcslr5g80p80po=0x%x";
1956 /* HNBU_ACPPR_SBPO */
1957 static const char BCMATTACHDATA(vstr_sb20in40rpo)[] = "sb20in40%crpo=0x%x";
1958 /* HNBU_ACPPR_SBPO */
1959 static const char BCMATTACHDATA(vstr_sb20in40and80rpo)[] = "sb20in40and80%crpo=0x%x";
1960 static const char BCMATTACHDATA(vstr_sb20in80and160r5gpo)[] = "sb20in80and160%cr5g%cpo=0x%x";
1961 static const char BCMATTACHDATA(vstr_sb20in80and160r5g1po)[] = "sb20in80and160%cr5g%c1po=0x%x";
1962 static const char BCMATTACHDATA(vstr_sb2040and80in80p80r5gpo)[] =
1963 "sb2040and80in80p80%cr5g%cpo=0x%x";
1964 static const char BCMATTACHDATA(vstr_sb2040and80in80p80r5g1po)[] =
1965 "sb2040and80in80p80%cr5g%c1po=0x%x";
1966 static const char BCMATTACHDATA(vstr_sb20in40dot11agofdm2gpo)[] = "sb20in40dot11agofdm2gpo=0x%x";
1967 static const char BCMATTACHDATA(vstr_sb20in80dot11agofdm2gpo)[] = "sb20in80dot11agofdm2gpo=0x%x";
1968 static const char BCMATTACHDATA(vstr_sb20in40ofdmlrbw202gpo)[] = "sb20in40ofdmlrbw202gpo=0x%x";
1969 static const char BCMATTACHDATA(vstr_sb20in80ofdmlrbw202gpo)[] = "sb20in80ofdmlrbw202gpo=0x%x";
1970 static const char BCMATTACHDATA(vstr_sb20in80p80r5gpo)[] = "sb20in80p80%cr5gpo=0x%x";
1971 static const char BCMATTACHDATA(vstr_sb40and80r5gpo)[] = "sb40and80%cr5g%cpo=0x%x";
1972 static const char BCMATTACHDATA(vstr_sb40and80r5g1po)[] = "sb40and80%cr5g%c1po=0x%x";
1973 static const char BCMATTACHDATA(vstr_dot11agduprpo)[] = "dot11agdup%crpo=0x%x";
1974 static const char BCMATTACHDATA(vstr_dot11agduppo)[] = "dot11agduppo=0x%x";
1975 static const char BCMATTACHDATA(vstr_noiselvl2ga)[] = "noiselvl2ga%d=%d"; /* HNBU_NOISELVL */
1976 static const char BCMATTACHDATA(vstr_noiselvl5ga)[] = "noiselvl5ga%d=%d,%d,%d,%d";
1977 /* HNBU_RXGAIN_ERR */
1978 static const char BCMATTACHDATA(vstr_rxgainerr2ga)[] = "rxgainerr2ga%d=0x%x";
1979 static const char BCMATTACHDATA(vstr_rxgainerr5ga)[] = "rxgainerr5ga%d=0x%x,0x%x,0x%x,0x%x";
1980 static const char BCMATTACHDATA(vstr_agbg)[] = "agbg%d=0x%x"; /* HNBU_AGBGA */
1981 static const char BCMATTACHDATA(vstr_aga)[] = "aga%d=0x%x";
1982 static const char BCMATTACHDATA(vstr_txduty_ofdm)[] = "tx_duty_cycle_ofdm_%d_5g=%d";
1983 static const char BCMATTACHDATA(vstr_txduty_thresh)[] = "tx_duty_cycle_thresh_%d_5g=%d";
1984 static const char BCMATTACHDATA(vstr_paparambwver)[] = "paparambwver=%d";
1985
1986 static const char BCMATTACHDATA(vstr_uuid)[] = "uuid=%s";
1987
1988 static const char BCMATTACHDATA(vstr_wowlgpio)[] = "wowl_gpio=%d";
1989 static const char BCMATTACHDATA(vstr_wowlgpiopol)[] = "wowl_gpiopol=%d";
1990
1991 static const char BCMATTACHDATA(rstr_ag0)[] = "ag0";
1992 static const char BCMATTACHDATA(rstr_sromrev)[] = "sromrev";
1993
1994 static const char BCMATTACHDATA(vstr_paparamrpcalvars)[][20] =
1995 {"rpcal2g=0x%x", "rpcal5gb0=0x%x", "rpcal5gb1=0x%x",
1996 "rpcal5gb2=0x%x", "rpcal5gb3=0x%x"};
1997
1998 static const char BCMATTACHDATA(vstr_gpdn)[] = "gpdn=0x%x";
1999
2000 /* SROM V13 PA */
2001 static const char BCMATTACHDATA(vstr_sr13pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x,0x%x";
2002 static const char BCMATTACHDATA(vstr_maxp5gba)[] = "maxp5gb%da%d=0x%x";
2003 static const char BCMATTACHDATA(vstr_sr13pa5ga)[] = "pa5ga%d=%s";
2004 static const char BCMATTACHDATA(vstr_sr13pa5gbwa)[] = "pa5g%da%d=%s";
2005 static const char BCMATTACHDATA(vstr_pa2g40a)[] = "pa2g40a%d=0x%x,0x%x,0x%x,0x%x";
2006
2007 /* RSSI Cal parameters */
2008 static const char BCMATTACHDATA(vstr_rssicalfrqg)[] =
2009 "rssi_cal_freq_grp_2g=0x%x0x%x0x%x0x%x0x%x0x%x0x%x";
2010 static const char BCMATTACHDATA(vstr_rssidelta2g)[] =
2011 "rssi_delta_2gb%d=%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d";
2012 static const char BCMATTACHDATA(vstr_rssidelta5g)[] =
2013 "rssi_delta_5g%s=%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d";
2014
2015 uint8 patch_pair = 0;
2016
2017 /* For dongle HW, accept partial calibration parameters */
2018 #if defined(BCMSDIODEV) || defined(BCMUSBDEV) || defined(BCMDONGLEHOST)
2019 #define BCMDONGLECASE(n) case n:
2020 #else
2021 #define BCMDONGLECASE(n)
2022 #endif
2023
2024 #ifdef BCM_BOOTLOADER
2025 /* The format of the PMUREGS OTP Tuple ->
2026 * 1 byte -> Lower 5 bits has the address of the register
2027 * Higher 3 bits has the mode of the register like
2028 * PLL, ChipCtrl, RegCtrl, UpDwn or Dependency mask
2029 * 4 bytes -> Value of the register to be updated.
2030 */
2031 #define PMUREGS_MODE_MASK 0xE0
2032 #define PMUREGS_MODE_SHIFT 5
2033 #define PMUREGS_ADDR_MASK 0x1F
2034 #define PMUREGS_TPL_SIZE 5
2035
2036 enum {
2037 PMU_PLLREG_MODE,
2038 PMU_CCREG_MODE,
2039 PMU_VOLTREG_MODE,
2040 PMU_RES_TIME_MODE,
2041 PMU_RESDEPEND_MODE
2042 };
2043
2044 #define USBREGS_TPL_SIZE 5
2045 enum {
2046 USB_DEV_CTRL_REG,
2047 HSIC_PHY_CTRL1_REG,
2048 HSIC_PHY_CTRL2_REG
2049 };
2050
2051 #define USBRDY_DLY_TYPE 0x8000 /* Bit indicating if the byte is pre or post delay value */
2052 #define USBRDY_DLY_MASK 0x7FFF /* Bits indicating the amount of delay */
2053 #define USBRDY_MAXOTP_SIZE 5 /* Max size of the OTP parameter */
2054
2055 #endif /* BCM_BOOTLOADER */
2056
2057 static uint
2058 BCMATTACHFN(get_max_cis_size)(si_t *sih)
2059 {
2060 uint max_cis_size;
2061 void *oh;
2062
2063 max_cis_size = (sih && sih->ccrev >= 49) ? CIS_SIZE_12K : CIS_SIZE;
2064 if (sih && (oh = otp_init(sih)) != NULL) {
2065 max_cis_size -= otp_avsbitslen(oh);
2066 }
2067 return max_cis_size;
2068 }
2069
2070 #ifndef BCM_BOOTLOADER
2071 static uint32
2072 BCMATTACHFN(srom_data2value)(uint8 *p, uint8 len)
2073 {
2074 uint8 pos = 0;
2075 uint32 value = 0;
2076
2077 ASSERT(len <= 4);
2078
2079 while (pos < len) {
2080 value += (p[pos] << (pos * 8));
2081 pos++;
2082 }
2083
2084 return value;
2085 }
2086 #endif /* BCM_BOOTLOADER */
2087
2088 /**
2089 * Both SROM and OTP contain variables in 'CIS' format, whereas the rest of the firmware works with
2090 * 'variable/value' string pairs.
2091 */
2092 int
2093 BCMATTACHFN(srom_parsecis)(si_t *sih, osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars,
2094 uint *count)
2095 {
2096 char eabuf[32];
2097 char eabuf2[32];
2098 char *base;
2099 varbuf_t b;
2100 uint8 *cis, tup, tlen, sromrev = 1;
2101 uint i;
2102 uint16 j;
2103 #ifndef BCM_BOOTLOADER
2104 bool ag_init = FALSE;
2105 #endif
2106 uint32 w32;
2107 uint funcid;
2108 uint cisnum;
2109 int32 boardnum;
2110 int err;
2111 bool standard_cis;
2112 uint max_cis_size;
2113 uint var_cis_size = 0;
2114
2115 ASSERT(count != NULL);
2116
2117 if (vars == NULL) {
2118 ASSERT(0); /* crash debug images for investigation */
2119 return BCME_BADARG;
2120 }
2121
2122 boardnum = -1;
2123
2124 /* freed in same function */
2125 max_cis_size = get_max_cis_size(sih);
2126 var_cis_size = *count + ((max_cis_size + 2u) * ciscnt);
2127
2128 ASSERT(var_cis_size <= MAXSZ_NVRAM_VARS);
2129
2130 base = MALLOC_NOPERSIST(osh, var_cis_size);
2131 ASSERT(base != NULL);
2132 if (!base)
2133 return -2;
2134
2135 varbuf_init(&b, base, var_cis_size);
2136 bzero(base, var_cis_size);
2137 /* Append from vars if there's already something inside */
2138 if (*vars && **vars && (*count >= 3)) {
2139 /* back off \0 at the end, leaving only one \0 for the last param */
2140 while (((*vars)[(*count)-1] == '\0') && ((*vars)[(*count)-2] == '\0'))
2141 (*count)--;
2142
2143 bcopy(*vars, base, *count);
2144 b.buf += *count;
2145 }
2146 eabuf[0] = '\0';
2147 eabuf2[0] = '\0';
2148 for (cisnum = 0; cisnum < ciscnt; cisnum++) {
2149 cis = *pcis++;
2150 i = 0;
2151 funcid = 0;
2152 standard_cis = TRUE;
2153 do {
2154 if (standard_cis) {
2155 tup = cis[i++];
2156 if (tup == CISTPL_NULL || tup == CISTPL_END)
2157 tlen = 0;
2158 else
2159 tlen = cis[i++];
2160 } else {
2161 if (cis[i] == CISTPL_NULL || cis[i] == CISTPL_END) {
2162 tlen = 0;
2163 tup = cis[i];
2164 } else {
2165 tlen = cis[i];
2166 tup = CISTPL_BRCM_HNBU;
2167 }
2168 ++i;
2169 }
2170 if ((i + tlen) >= max_cis_size)
2171 break;
2172
2173 switch (tup) {
2174 case CISTPL_VERS_1:
2175 /* assume the strings are good if the version field checks out */
2176 if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) {
2177 varbuf_append(&b, vstr_manf, &cis[i + 2]);
2178 varbuf_append(&b, vstr_productname,
2179 &cis[i + 3 + strlen((char *)&cis[i + 2])]);
2180 break;
2181 }
2182
2183 case CISTPL_MANFID:
2184 varbuf_append(&b, vstr_manfid, (cis[i + 1] << 8) + cis[i]);
2185 varbuf_append(&b, vstr_prodid, (cis[i + 3] << 8) + cis[i + 2]);
2186 break;
2187
2188 case CISTPL_FUNCID:
2189 funcid = cis[i];
2190 break;
2191
2192 case CISTPL_FUNCE:
2193 switch (funcid) {
2194 case CISTPL_FID_SDIO:
2195 #ifdef BCMSDIO
2196 if (cis[i] == 0) {
2197 uint8 spd = cis[i + 3];
2198 static int lbase[] = {
2199 -1, 10, 12, 13, 15, 20, 25, 30,
2200 35, 40, 45, 50, 55, 60, 70, 80
2201 };
2202 static int mult[] = {
2203 10, 100, 1000, 10000,
2204 -1, -1, -1, -1
2205 };
2206 ASSERT((mult[spd & 0x7] != -1) &&
2207 (lbase[(spd >> 3) & 0x0f]));
2208 varbuf_append(&b, vstr_sdmaxblk[0],
2209 (cis[i + 2] << 8) + cis[i + 1]);
2210 varbuf_append(&b, vstr_sdmaxspeed,
2211 (mult[spd & 0x7] *
2212 lbase[(spd >> 3) & 0x0f]));
2213 } else if (cis[i] == 1) {
2214 varbuf_append(&b, vstr_sdmaxblk[cisnum],
2215 (cis[i + 13] << 8) | cis[i + 12]);
2216 }
2217 #endif /* BCMSDIO */
2218 funcid = 0;
2219 break;
2220 default:
2221 /* set macaddr if HNBU_MACADDR not seen yet */
2222 if (eabuf[0] == '\0' && cis[i] == LAN_NID &&
2223 !(ETHER_ISNULLADDR(&cis[i + 2])) &&
2224 !(ETHER_ISMULTI(&cis[i + 2]))) {
2225 ASSERT(cis[i + 1] == ETHER_ADDR_LEN);
2226 bcm_ether_ntoa((struct ether_addr *)&cis[i + 2],
2227 eabuf);
2228
2229 /* set boardnum if HNBU_BOARDNUM not seen yet */
2230 if (boardnum == -1)
2231 boardnum = (cis[i + 6] << 8) + cis[i + 7];
2232 }
2233 break;
2234 }
2235 break;
2236
2237 case CISTPL_CFTABLE:
2238 varbuf_append(&b, vstr_regwindowsz, (cis[i + 7] << 8) | cis[i + 6]);
2239 break;
2240
2241 case CISTPL_BRCM_HNBU:
2242 switch (cis[i]) {
2243 case HNBU_SROMREV:
2244 sromrev = cis[i + 1];
2245 varbuf_append(&b, vstr_sromrev, sromrev);
2246 break;
2247
2248 case HNBU_XTALFREQ:
2249 varbuf_append(&b, vstr_xtalfreq,
2250 (cis[i + 4] << 24) |
2251 (cis[i + 3] << 16) |
2252 (cis[i + 2] << 8) |
2253 cis[i + 1]);
2254 break;
2255
2256 case HNBU_CHIPID:
2257 varbuf_append(&b, vstr_vendid, (cis[i + 2] << 8) +
2258 cis[i + 1]);
2259 varbuf_append(&b, vstr_devid, (cis[i + 4] << 8) +
2260 cis[i + 3]);
2261 if (tlen >= 7) {
2262 varbuf_append(&b, vstr_chiprev,
2263 (cis[i + 6] << 8) + cis[i + 5]);
2264 }
2265 if (tlen >= 9) {
2266 varbuf_append(&b, vstr_subvendid,
2267 (cis[i + 8] << 8) + cis[i + 7]);
2268 }
2269 if (tlen >= 11) {
2270 varbuf_append(&b, vstr_subdevid,
2271 (cis[i + 10] << 8) + cis[i + 9]);
2272 /* subdevid doubles for boardtype */
2273 varbuf_append(&b, vstr_boardtype,
2274 (cis[i + 10] << 8) + cis[i + 9]);
2275 }
2276 break;
2277
2278 case HNBU_BOARDNUM:
2279 boardnum = (cis[i + 2] << 8) + cis[i + 1];
2280 break;
2281
2282 case HNBU_PATCH: {
2283 char vstr_paddr[16];
2284 char vstr_pdata[16];
2285
2286 /* retrieve the patch pairs
2287 * from tlen/6; where 6 is
2288 * sizeof(patch addr(2)) +
2289 * sizeof(patch data(4)).
2290 */
2291 patch_pair = tlen/6;
2292
2293 for (j = 0; j < patch_pair; j++) {
2294 snprintf(vstr_paddr, sizeof(vstr_paddr),
2295 rstr_paddr, j);
2296 snprintf(vstr_pdata, sizeof(vstr_pdata),
2297 rstr_pdata, j);
2298
2299 varbuf_append(&b, vstr_paddr,
2300 (cis[i + (j*6) + 2] << 8) |
2301 cis[i + (j*6) + 1]);
2302
2303 varbuf_append(&b, vstr_pdata,
2304 (cis[i + (j*6) + 6] << 24) |
2305 (cis[i + (j*6) + 5] << 16) |
2306 (cis[i + (j*6) + 4] << 8) |
2307 cis[i + (j*6) + 3]);
2308 }
2309 break;
2310 }
2311
2312 case HNBU_BOARDREV:
2313 if (tlen == 2)
2314 varbuf_append(&b, vstr_boardrev, cis[i + 1]);
2315 else
2316 varbuf_append(&b, vstr_boardrev,
2317 (cis[i + 2] << 8) + cis[i + 1]);
2318 break;
2319
2320 case HNBU_BOARDFLAGS:
2321 w32 = (cis[i + 2] << 8) + cis[i + 1];
2322 if (tlen >= 5)
2323 w32 |= ((cis[i + 4] << 24) + (cis[i + 3] << 16));
2324 varbuf_append(&b, vstr_boardflags, w32);
2325
2326 if (tlen >= 7) {
2327 w32 = (cis[i + 6] << 8) + cis[i + 5];
2328 if (tlen >= 9)
2329 w32 |= ((cis[i + 8] << 24) +
2330 (cis[i + 7] << 16));
2331 varbuf_append(&b, vstr_boardflags2, w32);
2332 }
2333 if (tlen >= 11) {
2334 w32 = (cis[i + 10] << 8) + cis[i + 9];
2335 if (tlen >= 13)
2336 w32 |= ((cis[i + 12] << 24) +
2337 (cis[i + 11] << 16));
2338 varbuf_append(&b, vstr_boardflags3, w32);
2339 }
2340 if (tlen >= 15) {
2341 w32 = (cis[i + 14] << 8) + cis[i + 13];
2342 if (tlen >= 17)
2343 w32 |= ((cis[i + 16] << 24) +
2344 (cis[i + 15] << 16));
2345 varbuf_append(&b, vstr_boardflags4, w32);
2346 }
2347 if (tlen >= 19) {
2348 w32 = (cis[i + 18] << 8) + cis[i + 17];
2349 if (tlen >= 21)
2350 w32 |= ((cis[i + 20] << 24) +
2351 (cis[i + 19] << 16));
2352 varbuf_append(&b, vstr_boardflags5, w32);
2353 }
2354 break;
2355
2356 case HNBU_USBFS:
2357 varbuf_append(&b, vstr_usbfs, cis[i + 1]);
2358 break;
2359
2360 case HNBU_BOARDTYPE:
2361 varbuf_append(&b, vstr_boardtype,
2362 (cis[i + 2] << 8) + cis[i + 1]);
2363 break;
2364
2365 case HNBU_HNBUCIS:
2366 /*
2367 * what follows is a nonstandard HNBU CIS
2368 * that lacks CISTPL_BRCM_HNBU tags
2369 *
2370 * skip 0xff (end of standard CIS)
2371 * after this tuple
2372 */
2373 tlen++;
2374 standard_cis = FALSE;
2375 break;
2376
2377 case HNBU_USBEPNUM:
2378 varbuf_append(&b, vstr_usbepnum,
2379 (cis[i + 2] << 8) | cis[i + 1]);
2380 break;
2381
2382 case HNBU_PATCH_AUTOINC: {
2383 char vstr_paddr[16];
2384 char vstr_pdata[16];
2385 uint32 addr_inc;
2386 uint8 pcnt;
2387
2388 addr_inc = (cis[i + 4] << 24) |
2389 (cis[i + 3] << 16) |
2390 (cis[i + 2] << 8) |
2391 (cis[i + 1]);
2392
2393 pcnt = (tlen - 5)/4;
2394 for (j = 0; j < pcnt; j++) {
2395 snprintf(vstr_paddr, sizeof(vstr_paddr),
2396 rstr_paddr, j + patch_pair);
2397 snprintf(vstr_pdata, sizeof(vstr_pdata),
2398 rstr_pdata, j + patch_pair);
2399
2400 varbuf_append(&b, vstr_paddr, addr_inc);
2401 varbuf_append(&b, vstr_pdata,
2402 (cis[i + (j*4) + 8] << 24) |
2403 (cis[i + (j*4) + 7] << 16) |
2404 (cis[i + (j*4) + 6] << 8) |
2405 cis[i + (j*4) + 5]);
2406 addr_inc += 4;
2407 }
2408 patch_pair += pcnt;
2409 break;
2410 }
2411 case HNBU_PATCH2: {
2412 char vstr_paddr[16];
2413 char vstr_pdata[16];
2414
2415 /* retrieve the patch pairs
2416 * from tlen/8; where 8 is
2417 * sizeof(patch addr(4)) +
2418 * sizeof(patch data(4)).
2419 */
2420 patch_pair = tlen/8;
2421
2422 for (j = 0; j < patch_pair; j++) {
2423 snprintf(vstr_paddr, sizeof(vstr_paddr),
2424 rstr_paddr, j);
2425 snprintf(vstr_pdata, sizeof(vstr_pdata),
2426 rstr_pdata, j);
2427
2428 varbuf_append(&b, vstr_paddr,
2429 (cis[i + (j*8) + 4] << 24) |
2430 (cis[i + (j*8) + 3] << 16) |
2431 (cis[i + (j*8) + 2] << 8) |
2432 cis[i + (j*8) + 1]);
2433
2434 varbuf_append(&b, vstr_pdata,
2435 (cis[i + (j*8) + 8] << 24) |
2436 (cis[i + (j*8) + 7] << 16) |
2437 (cis[i + (j*8) + 6] << 8) |
2438 cis[i + (j*8) + 5]);
2439 }
2440 break;
2441 }
2442 case HNBU_PATCH_AUTOINC8: {
2443 char vstr_paddr[16];
2444 char vstr_pdatah[16];
2445 char vstr_pdatal[16];
2446 uint32 addr_inc;
2447 uint8 pcnt;
2448
2449 addr_inc = (cis[i + 4] << 24) |
2450 (cis[i + 3] << 16) |
2451 (cis[i + 2] << 8) |
2452 (cis[i + 1]);
2453
2454 pcnt = (tlen - 5)/8;
2455 for (j = 0; j < pcnt; j++) {
2456 snprintf(vstr_paddr, sizeof(vstr_paddr),
2457 rstr_paddr, j + patch_pair);
2458 snprintf(vstr_pdatah, sizeof(vstr_pdatah),
2459 rstr_pdatah, j + patch_pair);
2460 snprintf(vstr_pdatal, sizeof(vstr_pdatal),
2461 rstr_pdatal, j + patch_pair);
2462
2463 varbuf_append(&b, vstr_paddr, addr_inc);
2464 varbuf_append(&b, vstr_pdatal,
2465 (cis[i + (j*8) + 8] << 24) |
2466 (cis[i + (j*8) + 7] << 16) |
2467 (cis[i + (j*8) + 6] << 8) |
2468 cis[i + (j*8) + 5]);
2469 varbuf_append(&b, vstr_pdatah,
2470 (cis[i + (j*8) + 12] << 24) |
2471 (cis[i + (j*8) + 11] << 16) |
2472 (cis[i + (j*8) + 10] << 8) |
2473 cis[i + (j*8) + 9]);
2474 addr_inc += 8;
2475 }
2476 patch_pair += pcnt;
2477 break;
2478 }
2479 case HNBU_PATCH8: {
2480 char vstr_paddr[16];
2481 char vstr_pdatah[16];
2482 char vstr_pdatal[16];
2483
2484 /* retrieve the patch pairs
2485 * from tlen/8; where 8 is
2486 * sizeof(patch addr(4)) +
2487 * sizeof(patch data(4)).
2488 */
2489 patch_pair = tlen/12;
2490
2491 for (j = 0; j < patch_pair; j++) {
2492 snprintf(vstr_paddr, sizeof(vstr_paddr),
2493 rstr_paddr, j);
2494 snprintf(vstr_pdatah, sizeof(vstr_pdatah),
2495 rstr_pdatah, j);
2496 snprintf(vstr_pdatal, sizeof(vstr_pdatal),
2497 rstr_pdatal, j);
2498
2499 varbuf_append(&b, vstr_paddr,
2500 (cis[i + (j*12) + 4] << 24) |
2501 (cis[i + (j*12) + 3] << 16) |
2502 (cis[i + (j*12) + 2] << 8) |
2503 cis[i + (j*12) + 1]);
2504
2505 varbuf_append(&b, vstr_pdatal,
2506 (cis[i + (j*12) + 8] << 24) |
2507 (cis[i + (j*12) + 7] << 16) |
2508 (cis[i + (j*12) + 6] << 8) |
2509 cis[i + (j*12) + 5]);
2510
2511 varbuf_append(&b, vstr_pdatah,
2512 (cis[i + (j*12) + 12] << 24) |
2513 (cis[i + (j*12) + 11] << 16) |
2514 (cis[i + (j*12) + 10] << 8) |
2515 cis[i + (j*12) + 9]);
2516 }
2517 break;
2518 }
2519 case HNBU_USBFLAGS:
2520 varbuf_append(&b, vstr_usbflags,
2521 (cis[i + 4] << 24) |
2522 (cis[i + 3] << 16) |
2523 (cis[i + 2] << 8) |
2524 cis[i + 1]);
2525 break;
2526 #ifdef BCM_BOOTLOADER
2527 case HNBU_MDIOEX_REGLIST:
2528 case HNBU_MDIO_REGLIST: {
2529 /* Format: addr (8 bits) | val (16 bits) */
2530 const uint8 msize = 3;
2531 char mdiostr[24];
2532 const char *mdiodesc;
2533 uint8 *st;
2534
2535 mdiodesc = (cis[i] == HNBU_MDIO_REGLIST) ?
2536 vstr_mdio : vstr_mdioex;
2537
2538 ASSERT(((tlen - 1) % msize) == 0);
2539
2540 st = &cis[i + 1]; /* start of reg list */
2541 for (j = 0; j < (tlen - 1); j += msize, st += msize) {
2542 snprintf(mdiostr, sizeof(mdiostr),
2543 mdiodesc, st[0]);
2544 varbuf_append(&b, mdiostr, (st[2] << 8) | st[1]);
2545 }
2546 break;
2547 }
2548 case HNBU_BRMIN:
2549 varbuf_append(&b, vstr_brmin,
2550 (cis[i + 4] << 24) |
2551 (cis[i + 3] << 16) |
2552 (cis[i + 2] << 8) |
2553 cis[i + 1]);
2554 break;
2555
2556 case HNBU_BRMAX:
2557 varbuf_append(&b, vstr_brmax,
2558 (cis[i + 4] << 24) |
2559 (cis[i + 3] << 16) |
2560 (cis[i + 2] << 8) |
2561 cis[i + 1]);
2562 break;
2563 #endif /* BCM_BOOTLOADER */
2564
2565 case HNBU_RDLID:
2566 varbuf_append(&b, vstr_rdlid,
2567 (cis[i + 2] << 8) | cis[i + 1]);
2568 break;
2569
2570 case HNBU_GCI_CCR: {
2571 /* format:
2572 * |0x80| <== brcm
2573 * |len| <== variable, multiple of 5
2574 * |tup| <== tupletype
2575 * |ccreg_ix0| <== ix of ccreg [1byte]
2576 * |ccreg_val0| <== corr value [4bytes]
2577 * ---
2578 * Multiple registers are possible. for eg: we
2579 * can specify reg_ix3val3 and reg_ix5val5, etc
2580 */
2581 char vstr_gci_ccreg_entry[16];
2582 uint8 num_entries = 0;
2583
2584 /* retrieve the index-value pairs
2585 * from tlen/5; where 5 is
2586 * sizeof(ccreg_ix(1)) +
2587 * sizeof(ccreg_val(4)).
2588 */
2589 num_entries = tlen/5;
2590
2591 for (j = 0; j < num_entries; j++) {
2592 snprintf(vstr_gci_ccreg_entry,
2593 sizeof(vstr_gci_ccreg_entry),
2594 rstr_gci_ccreg_entry,
2595 cis[i + (j*5) + 1]);
2596
2597 varbuf_append(&b, vstr_gci_ccreg_entry,
2598 (cis[i + (j*5) + 5] << 24) |
2599 (cis[i + (j*5) + 4] << 16) |
2600 (cis[i + (j*5) + 3] << 8) |
2601 cis[i + (j*5) + 2]);
2602 }
2603 break;
2604 }
2605
2606 #ifdef BCM_BOOTLOADER
2607 case HNBU_RDLRNDIS:
2608 varbuf_append(&b, vstr_rdlrndis, cis[i + 1]);
2609 break;
2610
2611 case HNBU_RDLRWU:
2612 varbuf_append(&b, vstr_rdlrwu, cis[i + 1]);
2613 break;
2614
2615 case HNBU_RDLSN:
2616 if (tlen >= 5)
2617 varbuf_append(&b, vstr_rdlsn,
2618 (cis[i + 4] << 24) |
2619 (cis[i + 3] << 16) |
2620 (cis[i + 2] << 8) |
2621 cis[i + 1]);
2622 else
2623 varbuf_append(&b, vstr_rdlsn,
2624 (cis[i + 2] << 8) |
2625 cis[i + 1]);
2626 break;
2627
2628 case HNBU_PMUREGS: {
2629 uint8 offset = 1, mode_addr, mode, addr;
2630 const char *fmt;
2631
2632 do {
2633 mode_addr = cis[i+offset];
2634
2635 mode = (mode_addr & PMUREGS_MODE_MASK)
2636 >> PMUREGS_MODE_SHIFT;
2637 addr = mode_addr & PMUREGS_ADDR_MASK;
2638
2639 switch (mode) {
2640 case PMU_PLLREG_MODE:
2641 fmt = vstr_pllreg;
2642 break;
2643 case PMU_CCREG_MODE:
2644 fmt = vstr_ccreg;
2645 break;
2646 case PMU_VOLTREG_MODE:
2647 fmt = vstr_regctrl;
2648 break;
2649 case PMU_RES_TIME_MODE:
2650 fmt = vstr_time;
2651 break;
2652 case PMU_RESDEPEND_MODE:
2653 fmt = vstr_depreg;
2654 break;
2655 default:
2656 fmt = NULL;
2657 break;
2658 }
2659
2660 if (fmt != NULL) {
2661 varbuf_append(&b, fmt, addr,
2662 (cis[i + offset + 4] << 24) |
2663 (cis[i + offset + 3] << 16) |
2664 (cis[i + offset + 2] << 8) |
2665 cis[i + offset + 1]);
2666 }
2667
2668 offset += PMUREGS_TPL_SIZE;
2669 } while (offset < tlen);
2670 break;
2671 }
2672
2673 case HNBU_USBREGS: {
2674 uint8 offset = 1, usb_reg;
2675 const char *fmt;
2676
2677 do {
2678 usb_reg = cis[i+offset];
2679
2680 switch (usb_reg) {
2681 case USB_DEV_CTRL_REG:
2682 fmt = vstr_usbdevctrl;
2683 break;
2684 case HSIC_PHY_CTRL1_REG:
2685 fmt = vstr_hsicphyctrl1;
2686 break;
2687 case HSIC_PHY_CTRL2_REG:
2688 fmt = vstr_hsicphyctrl2;
2689 break;
2690 default:
2691 fmt = NULL;
2692 break;
2693 }
2694
2695 if (fmt != NULL) {
2696 varbuf_append(&b, fmt,
2697 (cis[i + offset + 4] << 24) |
2698 (cis[i + offset + 3] << 16) |
2699 (cis[i + offset + 2] << 8) |
2700 cis[i + offset + 1]);
2701 }
2702
2703 offset += USBREGS_TPL_SIZE;
2704 } while (offset < tlen);
2705 break;
2706 }
2707
2708 case HNBU_USBRDY:
2709 /* The first byte of this tuple indicate if the host
2710 * needs to be informed about the readiness of
2711 * the HSIC/USB for enumeration on which GPIO should
2712 * the device assert this event.
2713 */
2714 varbuf_append(&b, vstr_usbrdy, cis[i + 1]);
2715
2716 /* The following fields in this OTP are optional.
2717 * The remaining bytes will indicate the delay required
2718 * before and/or after the ch_init(). The delay is defined
2719 * using 16-bits of this the MSB(bit15 of 15:0) will be
2720 * used indicate if the parameter is for Pre or Post delay.
2721 */
2722 for (j = 2; j < USBRDY_MAXOTP_SIZE && j < tlen;
2723 j += 2) {
2724 uint16 usb_delay;
2725
2726 usb_delay = cis[i + j] | (cis[i + j + 1] << 8);
2727
2728 /* The bit-15 of the delay field will indicate the
2729 * type of delay (pre or post).
2730 */
2731 if (usb_delay & USBRDY_DLY_TYPE) {
2732 varbuf_append(&b, vstr_usbpostdly,
2733 (usb_delay & USBRDY_DLY_MASK));
2734 } else {
2735 varbuf_append(&b, vstr_usbpredly,
2736 (usb_delay & USBRDY_DLY_MASK));
2737 }
2738 }
2739 break;
2740
2741 case HNBU_BLDR_TIMEOUT:
2742 /* The Delay after USBConnect for timeout till dongle
2743 * receives get_descriptor request.
2744 */
2745 varbuf_append(&b, vstr_bldr_reset_timeout,
2746 (cis[i + 1] | (cis[i + 2] << 8)));
2747 break;
2748
2749 case HNBU_MUXENAB:
2750 varbuf_append(&b, vstr_muxenab, cis[i + 1]);
2751 break;
2752 case HNBU_PUBKEY: {
2753 /* The public key is in binary format in OTP,
2754 * convert to string format before appending
2755 * buffer string.
2756 * public key(12 bytes) + crc (1byte) = 129
2757 */
2758 unsigned char a[300];
2759 int k;
2760
2761 for (k = 1, j = 0; k < 129; k++)
2762 j += snprintf((char *)(a + j),
2763 sizeof(a) - j,
2764 "%02x", cis[i + k]);
2765
2766 a[256] = 0;
2767
2768 varbuf_append(&b, vstr_pubkey, a);
2769 break;
2770 }
2771 #else
2772 case HNBU_AA:
2773 varbuf_append(&b, vstr_aa2g, cis[i + 1]);
2774 if (tlen >= 3)
2775 varbuf_append(&b, vstr_aa5g, cis[i + 2]);
2776 break;
2777
2778 case HNBU_AG:
2779 varbuf_append(&b, vstr_ag, 0, cis[i + 1]);
2780 if (tlen >= 3)
2781 varbuf_append(&b, vstr_ag, 1, cis[i + 2]);
2782 if (tlen >= 4)
2783 varbuf_append(&b, vstr_ag, 2, cis[i + 3]);
2784 if (tlen >= 5)
2785 varbuf_append(&b, vstr_ag, 3, cis[i + 4]);
2786 ag_init = TRUE;
2787 break;
2788
2789 case HNBU_ANT5G:
2790 varbuf_append(&b, vstr_aa5g, cis[i + 1]);
2791 varbuf_append(&b, vstr_ag, 1, cis[i + 2]);
2792 break;
2793
2794 case HNBU_CC:
2795 ASSERT(sromrev == 1);
2796 varbuf_append(&b, vstr_cc, cis[i + 1]);
2797 break;
2798
2799 case HNBU_PAPARMS: {
2800 uint8 pa0_lo_offset = 0;
2801 switch (tlen) {
2802 case 2:
2803 ASSERT(sromrev == 1);
2804 varbuf_append(&b, vstr_pa0maxpwr, cis[i + 1]);
2805 break;
2806 /* case 16:
2807 ASSERT(sromrev >= 11);
2808 for (j = 0; j < 3; j++) {
2809 varbuf_append(&b, vstr_pa0b_lo[j],
2810 (cis[i + (j * 2) + 11] << 8) +
2811 cis[i + (j * 2) + 10]);
2812 }
2813 FALLTHROUGH
2814 */
2815 case 10:
2816 case 16:
2817 ASSERT(sromrev >= 2);
2818 varbuf_append(&b, vstr_opo, cis[i + 9]);
2819 if (tlen >= 13 && pa0_lo_offset == 0)
2820 pa0_lo_offset = 9;
2821 /* FALLTHROUGH */
2822 case 9:
2823 case 15:
2824 varbuf_append(&b, vstr_pa0maxpwr, cis[i + 8]);
2825 if (tlen >= 13 && pa0_lo_offset == 0)
2826 pa0_lo_offset = 8;
2827 /* FALLTHROUGH */
2828 BCMDONGLECASE(8)
2829 BCMDONGLECASE(14)
2830 varbuf_append(&b, vstr_pa0itssit, cis[i + 7]);
2831 varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 7]);
2832 if (tlen >= 13 && pa0_lo_offset == 0)
2833 pa0_lo_offset = 7;
2834 /* FALLTHROUGH */
2835 BCMDONGLECASE(7)
2836 BCMDONGLECASE(13)
2837 for (j = 0; j < 3; j++) {
2838 varbuf_append(&b, vstr_pa0b[j],
2839 (cis[i + (j * 2) + 2] << 8) +
2840 cis[i + (j * 2) + 1]);
2841 }
2842 if (tlen >= 13 && pa0_lo_offset == 0)
2843 pa0_lo_offset = 6;
2844
2845 if (tlen >= 13 && pa0_lo_offset != 0) {
2846 for (j = 0; j < 3; j++) {
2847 varbuf_append(&b, vstr_pa0b_lo[j],
2848 (cis[pa0_lo_offset+i+(j*2)+2]<<8)+
2849 cis[pa0_lo_offset+i+(j*2)+1]);
2850 }
2851 }
2852 break;
2853 default:
2854 ASSERT((tlen == 2) || (tlen == 9) || (tlen == 10) ||
2855 (tlen == 15) || (tlen == 16));
2856 break;
2857 }
2858 break;
2859 }
2860 case HNBU_PAPARMS5G:
2861 ASSERT((sromrev == 2) || (sromrev == 3));
2862 switch (tlen) {
2863 case 23:
2864 varbuf_append(&b, vstr_pa1himaxpwr, cis[i + 22]);
2865 varbuf_append(&b, vstr_pa1lomaxpwr, cis[i + 21]);
2866 varbuf_append(&b, vstr_pa1maxpwr, cis[i + 20]);
2867 /* FALLTHROUGH */
2868 case 20:
2869 varbuf_append(&b, vstr_pa1itssit, cis[i + 19]);
2870 /* FALLTHROUGH */
2871 case 19:
2872 for (j = 0; j < 3; j++) {
2873 varbuf_append(&b, vstr_pa1b[j],
2874 (cis[i + (j * 2) + 2] << 8) +
2875 cis[i + (j * 2) + 1]);
2876 }
2877 for (j = 3; j < 6; j++) {
2878 varbuf_append(&b, vstr_pa1lob[j - 3],
2879 (cis[i + (j * 2) + 2] << 8) +
2880 cis[i + (j * 2) + 1]);
2881 }
2882 for (j = 6; j < 9; j++) {
2883 varbuf_append(&b, vstr_pa1hib[j - 6],
2884 (cis[i + (j * 2) + 2] << 8) +
2885 cis[i + (j * 2) + 1]);
2886 }
2887 break;
2888 default:
2889 ASSERT((tlen == 19) ||
2890 (tlen == 20) || (tlen == 23));
2891 break;
2892 }
2893 break;
2894
2895 case HNBU_OEM:
2896 ASSERT(sromrev == 1);
2897 varbuf_append(&b, vstr_oem,
2898 cis[i + 1], cis[i + 2],
2899 cis[i + 3], cis[i + 4],
2900 cis[i + 5], cis[i + 6],
2901 cis[i + 7], cis[i + 8]);
2902 break;
2903
2904 case HNBU_CCODE:
2905 ASSERT(sromrev > 1);
2906 if ((cis[i + 1] == 0) || (cis[i + 2] == 0))
2907 varbuf_append(&b, vstr_noccode);
2908 else
2909 varbuf_append(&b, vstr_ccode,
2910 cis[i + 1], cis[i + 2]);
2911 varbuf_append(&b, vstr_cctl, cis[i + 3]);
2912 break;
2913
2914 case HNBU_CCKPO:
2915 ASSERT(sromrev > 2);
2916 varbuf_append(&b, vstr_cckpo,
2917 (cis[i + 2] << 8) | cis[i + 1]);
2918 break;
2919
2920 case HNBU_OFDMPO:
2921 ASSERT(sromrev > 2);
2922 varbuf_append(&b, vstr_ofdmpo,
2923 (cis[i + 4] << 24) |
2924 (cis[i + 3] << 16) |
2925 (cis[i + 2] << 8) |
2926 cis[i + 1]);
2927 break;
2928
2929 case HNBU_WPS:
2930 varbuf_append(&b, vstr_wpsgpio, cis[i + 1]);
2931 if (tlen >= 3)
2932 varbuf_append(&b, vstr_wpsled, cis[i + 2]);
2933 break;
2934
2935 case HNBU_RSSISMBXA2G:
2936 ASSERT(sromrev == 3);
2937 varbuf_append(&b, vstr_rssismf2g, cis[i + 1] & 0xf);
2938 varbuf_append(&b, vstr_rssismc2g, (cis[i + 1] >> 4) & 0xf);
2939 varbuf_append(&b, vstr_rssisav2g, cis[i + 2] & 0x7);
2940 varbuf_append(&b, vstr_bxa2g, (cis[i + 2] >> 3) & 0x3);
2941 break;
2942
2943 case HNBU_RSSISMBXA5G:
2944 ASSERT(sromrev == 3);
2945 varbuf_append(&b, vstr_rssismf5g, cis[i + 1] & 0xf);
2946 varbuf_append(&b, vstr_rssismc5g, (cis[i + 1] >> 4) & 0xf);
2947 varbuf_append(&b, vstr_rssisav5g, cis[i + 2] & 0x7);
2948 varbuf_append(&b, vstr_bxa5g, (cis[i + 2] >> 3) & 0x3);
2949 break;
2950
2951 case HNBU_TRI2G:
2952 ASSERT(sromrev == 3);
2953 varbuf_append(&b, vstr_tri2g, cis[i + 1]);
2954 break;
2955
2956 case HNBU_TRI5G:
2957 ASSERT(sromrev == 3);
2958 varbuf_append(&b, vstr_tri5gl, cis[i + 1]);
2959 varbuf_append(&b, vstr_tri5g, cis[i + 2]);
2960 varbuf_append(&b, vstr_tri5gh, cis[i + 3]);
2961 break;
2962
2963 case HNBU_RXPO2G:
2964 ASSERT(sromrev == 3);
2965 varbuf_append(&b, vstr_rxpo2g, cis[i + 1]);
2966 break;
2967
2968 case HNBU_RXPO5G:
2969 ASSERT(sromrev == 3);
2970 varbuf_append(&b, vstr_rxpo5g, cis[i + 1]);
2971 break;
2972
2973 case HNBU_MACADDR:
2974 if (!(ETHER_ISNULLADDR(&cis[i+1])) &&
2975 !(ETHER_ISMULTI(&cis[i+1]))) {
2976 bcm_ether_ntoa((struct ether_addr *)&cis[i + 1],
2977 eabuf);
2978
2979 /* set boardnum if HNBU_BOARDNUM not seen yet */
2980 if (boardnum == -1)
2981 boardnum = (cis[i + 5] << 8) + cis[i + 6];
2982 }
2983 break;
2984
2985 case HNBU_CHAINSWITCH:
2986 varbuf_append(&b, vstr_txchain, cis[i + 1]);
2987 varbuf_append(&b, vstr_rxchain, cis[i + 2]);
2988 varbuf_append(&b, vstr_antswitch,
2989 (cis[i + 4] << 8) + cis[i + 3]);
2990 break;
2991
2992 case HNBU_ELNA2G:
2993 varbuf_append(&b, vstr_elna2g, cis[i + 1]);
2994 break;
2995
2996 case HNBU_ELNA5G:
2997 varbuf_append(&b, vstr_elna5g, cis[i + 1]);
2998 break;
2999
3000 case HNBU_REGREV:
3001 varbuf_append(&b, vstr_regrev,
3002 srom_data2value(&cis[i + 1], tlen - 1));
3003 break;
3004
3005 case HNBU_FEM: {
3006 uint16 fem = (cis[i + 2] << 8) + cis[i + 1];
3007 varbuf_append(&b, vstr_antswctl2g, (fem &
3008 SROM8_FEM_ANTSWLUT_MASK) >>
3009 SROM8_FEM_ANTSWLUT_SHIFT);
3010 varbuf_append(&b, vstr_triso2g, (fem &
3011 SROM8_FEM_TR_ISO_MASK) >>
3012 SROM8_FEM_TR_ISO_SHIFT);
3013 varbuf_append(&b, vstr_pdetrange2g, (fem &
3014 SROM8_FEM_PDET_RANGE_MASK) >>
3015 SROM8_FEM_PDET_RANGE_SHIFT);
3016 varbuf_append(&b, vstr_extpagain2g, (fem &
3017 SROM8_FEM_EXTPA_GAIN_MASK) >>
3018 SROM8_FEM_EXTPA_GAIN_SHIFT);
3019 varbuf_append(&b, vstr_tssipos2g, (fem &
3020 SROM8_FEM_TSSIPOS_MASK) >>
3021 SROM8_FEM_TSSIPOS_SHIFT);
3022 if (tlen < 5) break;
3023
3024 fem = (cis[i + 4] << 8) + cis[i + 3];
3025 varbuf_append(&b, vstr_antswctl5g, (fem &
3026 SROM8_FEM_ANTSWLUT_MASK) >>
3027 SROM8_FEM_ANTSWLUT_SHIFT);
3028 varbuf_append(&b, vstr_triso5g, (fem &
3029 SROM8_FEM_TR_ISO_MASK) >>
3030 SROM8_FEM_TR_ISO_SHIFT);
3031 varbuf_append(&b, vstr_pdetrange5g, (fem &
3032 SROM8_FEM_PDET_RANGE_MASK) >>
3033 SROM8_FEM_PDET_RANGE_SHIFT);
3034 varbuf_append(&b, vstr_extpagain5g, (fem &
3035 SROM8_FEM_EXTPA_GAIN_MASK) >>
3036 SROM8_FEM_EXTPA_GAIN_SHIFT);
3037 varbuf_append(&b, vstr_tssipos5g, (fem &
3038 SROM8_FEM_TSSIPOS_MASK) >>
3039 SROM8_FEM_TSSIPOS_SHIFT);
3040 break;
3041 }
3042
3043 case HNBU_PAPARMS_C0:
3044 varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 1]);
3045 varbuf_append(&b, vstr_itt2ga0, cis[i + 2]);
3046 varbuf_append(&b, vstr_pa, 2, 0, 0,
3047 (cis[i + 4] << 8) + cis[i + 3]);
3048 varbuf_append(&b, vstr_pa, 2, 1, 0,
3049 (cis[i + 6] << 8) + cis[i + 5]);
3050 varbuf_append(&b, vstr_pa, 2, 2, 0,
3051 (cis[i + 8] << 8) + cis[i + 7]);
3052 if (tlen < 31) break;
3053
3054 varbuf_append(&b, vstr_maxp5ga0, cis[i + 9]);
3055 varbuf_append(&b, vstr_itt5ga0, cis[i + 10]);
3056 varbuf_append(&b, vstr_maxp5gha0, cis[i + 11]);
3057 varbuf_append(&b, vstr_maxp5gla0, cis[i + 12]);
3058 varbuf_append(&b, vstr_pa, 5, 0, 0,
3059 (cis[i + 14] << 8) + cis[i + 13]);
3060 varbuf_append(&b, vstr_pa, 5, 1, 0,
3061 (cis[i + 16] << 8) + cis[i + 15]);
3062 varbuf_append(&b, vstr_pa, 5, 2, 0,
3063 (cis[i + 18] << 8) + cis[i + 17]);
3064 varbuf_append(&b, vstr_pahl, 5, 'l', 0, 0,
3065 (cis[i + 20] << 8) + cis[i + 19]);
3066 varbuf_append(&b, vstr_pahl, 5, 'l', 1, 0,
3067 (cis[i + 22] << 8) + cis[i + 21]);
3068 varbuf_append(&b, vstr_pahl, 5, 'l', 2, 0,
3069 (cis[i + 24] << 8) + cis[i + 23]);
3070 varbuf_append(&b, vstr_pahl, 5, 'h', 0, 0,
3071 (cis[i + 26] << 8) + cis[i + 25]);
3072 varbuf_append(&b, vstr_pahl, 5, 'h', 1, 0,
3073 (cis[i + 28] << 8) + cis[i + 27]);
3074 varbuf_append(&b, vstr_pahl, 5, 'h', 2, 0,
3075 (cis[i + 30] << 8) + cis[i + 29]);
3076 break;
3077
3078 case HNBU_PAPARMS_C1:
3079 varbuf_append(&b, vstr_maxp2ga, 1, cis[i + 1]);
3080 varbuf_append(&b, vstr_itt2ga1, cis[i + 2]);
3081 varbuf_append(&b, vstr_pa, 2, 0, 1,
3082 (cis[i + 4] << 8) + cis[i + 3]);
3083 varbuf_append(&b, vstr_pa, 2, 1, 1,
3084 (cis[i + 6] << 8) + cis[i + 5]);
3085 varbuf_append(&b, vstr_pa, 2, 2, 1,
3086 (cis[i + 8] << 8) + cis[i + 7]);
3087 if (tlen < 31) break;
3088
3089 varbuf_append(&b, vstr_maxp5ga1, cis[i + 9]);
3090 varbuf_append(&b, vstr_itt5ga1, cis[i + 10]);
3091 varbuf_append(&b, vstr_maxp5gha1, cis[i + 11]);
3092 varbuf_append(&b, vstr_maxp5gla1, cis[i + 12]);
3093 varbuf_append(&b, vstr_pa, 5, 0, 1,
3094 (cis[i + 14] << 8) + cis[i + 13]);
3095 varbuf_append(&b, vstr_pa, 5, 1, 1,
3096 (cis[i + 16] << 8) + cis[i + 15]);
3097 varbuf_append(&b, vstr_pa, 5, 2, 1,
3098 (cis[i + 18] << 8) + cis[i + 17]);
3099 varbuf_append(&b, vstr_pahl, 5, 'l', 0, 1,
3100 (cis[i + 20] << 8) + cis[i + 19]);
3101 varbuf_append(&b, vstr_pahl, 5, 'l', 1, 1,
3102 (cis[i + 22] << 8) + cis[i + 21]);
3103 varbuf_append(&b, vstr_pahl, 5, 'l', 2, 1,
3104 (cis[i + 24] << 8) + cis[i + 23]);
3105 varbuf_append(&b, vstr_pahl, 5, 'h', 0, 1,
3106 (cis[i + 26] << 8) + cis[i + 25]);
3107 varbuf_append(&b, vstr_pahl, 5, 'h', 1, 1,
3108 (cis[i + 28] << 8) + cis[i + 27]);
3109 varbuf_append(&b, vstr_pahl, 5, 'h', 2, 1,
3110 (cis[i + 30] << 8) + cis[i + 29]);
3111 break;
3112
3113 case HNBU_PO_CCKOFDM:
3114 varbuf_append(&b, vstr_cck2gpo,
3115 (cis[i + 2] << 8) + cis[i + 1]);
3116 varbuf_append(&b, vstr_ofdm2gpo,
3117 (cis[i + 6] << 24) + (cis[i + 5] << 16) +
3118 (cis[i + 4] << 8) + cis[i + 3]);
3119 if (tlen < 19) break;
3120
3121 varbuf_append(&b, vstr_ofdm5gpo,
3122 (cis[i + 10] << 24) + (cis[i + 9] << 16) +
3123 (cis[i + 8] << 8) + cis[i + 7]);
3124 varbuf_append(&b, vstr_ofdm5glpo,
3125 (cis[i + 14] << 24) + (cis[i + 13] << 16) +
3126 (cis[i + 12] << 8) + cis[i + 11]);
3127 varbuf_append(&b, vstr_ofdm5ghpo,
3128 (cis[i + 18] << 24) + (cis[i + 17] << 16) +
3129 (cis[i + 16] << 8) + cis[i + 15]);
3130 break;
3131
3132 case HNBU_PO_MCS2G:
3133 for (j = 0; j <= (tlen/2); j++) {
3134 varbuf_append(&b, vstr_mcspo, 2, j,
3135 (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
3136 }
3137 break;
3138
3139 case HNBU_PO_MCS5GM:
3140 for (j = 0; j <= (tlen/2); j++) {
3141 varbuf_append(&b, vstr_mcspo, 5, j,
3142 (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
3143 }
3144 break;
3145
3146 case HNBU_PO_MCS5GLH:
3147 for (j = 0; j <= (tlen/4); j++) {
3148 varbuf_append(&b, vstr_mcspohl, 5, 'l', j,
3149 (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
3150 }
3151
3152 for (j = 0; j <= (tlen/4); j++) {
3153 varbuf_append(&b, vstr_mcspohl, 5, 'h', j,
3154 (cis[i + ((tlen/2)+2) + 2*j] << 8) +
3155 cis[i + ((tlen/2)+1) + 2*j]);
3156 }
3157
3158 break;
3159
3160 case HNBU_PO_CDD:
3161 varbuf_append(&b, vstr_cddpo,
3162 (cis[i + 2] << 8) + cis[i + 1]);
3163 break;
3164
3165 case HNBU_PO_STBC:
3166 varbuf_append(&b, vstr_stbcpo,
3167 (cis[i + 2] << 8) + cis[i + 1]);
3168 break;
3169
3170 case HNBU_PO_40M:
3171 varbuf_append(&b, vstr_bw40po,
3172 (cis[i + 2] << 8) + cis[i + 1]);
3173 break;
3174
3175 case HNBU_PO_40MDUP:
3176 varbuf_append(&b, vstr_bwduppo,
3177 (cis[i + 2] << 8) + cis[i + 1]);
3178 break;
3179
3180 case HNBU_OFDMPO5G:
3181 varbuf_append(&b, vstr_ofdm5gpo,
3182 (cis[i + 4] << 24) + (cis[i + 3] << 16) +
3183 (cis[i + 2] << 8) + cis[i + 1]);
3184 varbuf_append(&b, vstr_ofdm5glpo,
3185 (cis[i + 8] << 24) + (cis[i + 7] << 16) +
3186 (cis[i + 6] << 8) + cis[i + 5]);
3187 varbuf_append(&b, vstr_ofdm5ghpo,
3188 (cis[i + 12] << 24) + (cis[i + 11] << 16) +
3189 (cis[i + 10] << 8) + cis[i + 9]);
3190 break;
3191 /* Power per rate for SROM V9 */
3192 case HNBU_CCKBW202GPO:
3193 varbuf_append(&b, vstr_cckbw202gpo[0],
3194 ((cis[i + 2] << 8) + cis[i + 1]));
3195 if (tlen > 4)
3196 varbuf_append(&b, vstr_cckbw202gpo[1],
3197 ((cis[i + 4] << 8) + cis[i + 3]));
3198 if (tlen > 6)
3199 varbuf_append(&b, vstr_cckbw202gpo[2],
3200 ((cis[i + 6] << 8) + cis[i + 5]));
3201 break;
3202
3203 case HNBU_LEGOFDMBW202GPO:
3204 varbuf_append(&b, vstr_legofdmbw202gpo[0],
3205 ((cis[i + 4] << 24) + (cis[i + 3] << 16) +
3206 (cis[i + 2] << 8) + cis[i + 1]));
3207 if (tlen > 6) {
3208 varbuf_append(&b, vstr_legofdmbw202gpo[1],
3209 ((cis[i + 8] << 24) + (cis[i + 7] << 16) +
3210 (cis[i + 6] << 8) + cis[i + 5]));
3211 }
3212 break;
3213
3214 case HNBU_LEGOFDMBW205GPO:
3215 for (j = 0; j < 6; j++) {
3216 if (tlen < (2 + 4 * j))
3217 break;
3218 varbuf_append(&b, vstr_legofdmbw205gpo[j],
3219 ((cis[4 * j + i + 4] << 24)
3220 + (cis[4 * j + i + 3] << 16)
3221 + (cis[4 * j + i + 2] << 8)
3222 + cis[4 * j + i + 1]));
3223 }
3224 break;
3225
3226 case HNBU_MCS2GPO:
3227 for (j = 0; j < 4; j++) {
3228 if (tlen < (2 + 4 * j))
3229 break;
3230 varbuf_append(&b, vstr_mcs2gpo[j],
3231 ((cis[4 * j + i + 4] << 24)
3232 + (cis[4 * j + i + 3] << 16)
3233 + (cis[4 * j + i + 2] << 8)
3234 + cis[4 * j + i + 1]));
3235 }
3236 break;
3237
3238 case HNBU_MCS5GLPO:
3239 for (j = 0; j < 3; j++) {
3240 if (tlen < (2 + 4 * j))
3241 break;
3242 varbuf_append(&b, vstr_mcs5glpo[j],
3243 ((cis[4 * j + i + 4] << 24)
3244 + (cis[4 * j + i + 3] << 16)
3245 + (cis[4 * j + i + 2] << 8)
3246 + cis[4 * j + i + 1]));
3247 }
3248 break;
3249
3250 case HNBU_MCS5GMPO:
3251 for (j = 0; j < 3; j++) {
3252 if (tlen < (2 + 4 * j))
3253 break;
3254 varbuf_append(&b, vstr_mcs5gmpo[j],
3255 ((cis[4 * j + i + 4] << 24)
3256 + (cis[4 * j + i + 3] << 16)
3257 + (cis[4 * j + i + 2] << 8)
3258 + cis[4 * j + i + 1]));
3259 }
3260 break;
3261
3262 case HNBU_MCS5GHPO:
3263 for (j = 0; j < 3; j++) {
3264 if (tlen < (2 + 4 * j))
3265 break;
3266 varbuf_append(&b, vstr_mcs5ghpo[j],
3267 ((cis[4 * j + i + 4] << 24)
3268 + (cis[4 * j + i + 3] << 16)
3269 + (cis[4 * j + i + 2] << 8)
3270 + cis[4 * j + i + 1]));
3271 }
3272 break;
3273
3274 case HNBU_MCS32PO:
3275 varbuf_append(&b, vstr_mcs32po,
3276 (cis[i + 2] << 8) + cis[i + 1]);
3277 break;
3278
3279 case HNBU_LEG40DUPPO:
3280 varbuf_append(&b, vstr_legofdm40duppo,
3281 (cis[i + 2] << 8) + cis[i + 1]);
3282 break;
3283
3284 case HNBU_CUSTOM1:
3285 varbuf_append(&b, vstr_custom, 1, ((cis[i + 4] << 24) +
3286 (cis[i + 3] << 16) + (cis[i + 2] << 8) +
3287 cis[i + 1]));
3288 break;
3289
3290 #if defined(BCMSDIO) || defined(BCMCCISSR3)
3291 case HNBU_SROM3SWRGN:
3292 if (tlen >= 73) {
3293 uint16 srom[35];
3294 uint8 srev = cis[i + 1 + 70];
3295 ASSERT(srev == 3);
3296 /* make tuple value 16-bit aligned and parse it */
3297 bcopy(&cis[i + 1], srom, sizeof(srom));
3298 _initvars_srom_pci(srev, srom, SROM3_SWRGN_OFF, &b);
3299 /* 2.4G antenna gain is included in SROM */
3300 ag_init = TRUE;
3301 /* Ethernet MAC address is included in SROM */
3302 eabuf[0] = 0;
3303 /* why boardnum is not -1? */
3304 boardnum = -1;
3305 }
3306 /* create extra variables */
3307 if (tlen >= 75)
3308 varbuf_append(&b, vstr_vendid,
3309 (cis[i + 1 + 73] << 8) +
3310 cis[i + 1 + 72]);
3311 if (tlen >= 77)
3312 varbuf_append(&b, vstr_devid,
3313 (cis[i + 1 + 75] << 8) +
3314 cis[i + 1 + 74]);
3315 if (tlen >= 79)
3316 varbuf_append(&b, vstr_xtalfreq,
3317 (cis[i + 1 + 77] << 8) +
3318 cis[i + 1 + 76]);
3319 break;
3320 #endif /* BCMSDIO || BCMCCISSR3 */
3321
3322 case HNBU_CCKFILTTYPE:
3323 varbuf_append(&b, vstr_cckdigfilttype,
3324 (cis[i + 1]));
3325 break;
3326
3327 case HNBU_TEMPTHRESH:
3328 varbuf_append(&b, vstr_tempthresh,
3329 (cis[i + 1]));
3330 /* period in msb nibble */
3331 varbuf_append(&b, vstr_temps_period,
3332 (cis[i + 2] & SROM11_TEMPS_PERIOD_MASK) >>
3333 SROM11_TEMPS_PERIOD_SHIFT);
3334 /* hysterisis in lsb nibble */
3335 varbuf_append(&b, vstr_temps_hysteresis,
3336 (cis[i + 2] & SROM11_TEMPS_HYSTERESIS_MASK) >>
3337 SROM11_TEMPS_HYSTERESIS_SHIFT);
3338 if (tlen >= 4) {
3339 varbuf_append(&b, vstr_tempoffset,
3340 (cis[i + 3]));
3341 varbuf_append(&b, vstr_tempsense_slope,
3342 (cis[i + 4]));
3343 varbuf_append(&b, vstr_temp_corrx,
3344 (cis[i + 5] & SROM11_TEMPCORRX_MASK) >>
3345 SROM11_TEMPCORRX_SHIFT);
3346 varbuf_append(&b, vstr_tempsense_option,
3347 (cis[i + 5] & SROM11_TEMPSENSE_OPTION_MASK) >>
3348 SROM11_TEMPSENSE_OPTION_SHIFT);
3349 varbuf_append(&b, vstr_phycal_tempdelta,
3350 (cis[i + 6]));
3351 }
3352 break;
3353
3354 case HNBU_FEM_CFG: {
3355 /* fem_cfg1 */
3356 uint16 fem_cfg = (cis[i + 2] << 8) + cis[i + 1];
3357 varbuf_append(&b, vstr_femctrl,
3358 (fem_cfg & SROM11_FEMCTRL_MASK) >>
3359 SROM11_FEMCTRL_SHIFT);
3360 varbuf_append(&b, vstr_papdcap, 2,
3361 (fem_cfg & SROM11_PAPDCAP_MASK) >>
3362 SROM11_PAPDCAP_SHIFT);
3363 varbuf_append(&b, vstr_tworangetssi, 2,
3364 (fem_cfg & SROM11_TWORANGETSSI_MASK) >>
3365 SROM11_TWORANGETSSI_SHIFT);
3366 varbuf_append(&b, vstr_pdgaing, 2,
3367 (fem_cfg & SROM11_PDGAIN_MASK) >>
3368 SROM11_PDGAIN_SHIFT);
3369 varbuf_append(&b, vstr_epagaing, 2,
3370 (fem_cfg & SROM11_EPAGAIN_MASK) >>
3371 SROM11_EPAGAIN_SHIFT);
3372 varbuf_append(&b, vstr_tssiposslopeg, 2,
3373 (fem_cfg & SROM11_TSSIPOSSLOPE_MASK) >>
3374 SROM11_TSSIPOSSLOPE_SHIFT);
3375 /* fem_cfg2 */
3376 fem_cfg = (cis[i + 4] << 8) + cis[i + 3];
3377 varbuf_append(&b, vstr_gainctrlsph,
3378 (fem_cfg & SROM11_GAINCTRLSPH_MASK) >>
3379 SROM11_GAINCTRLSPH_SHIFT);
3380 varbuf_append(&b, vstr_papdcap, 5,
3381 (fem_cfg & SROM11_PAPDCAP_MASK) >>
3382 SROM11_PAPDCAP_SHIFT);
3383 varbuf_append(&b, vstr_tworangetssi, 5,
3384 (fem_cfg & SROM11_TWORANGETSSI_MASK) >>
3385 SROM11_TWORANGETSSI_SHIFT);
3386 varbuf_append(&b, vstr_pdgaing, 5,
3387 (fem_cfg & SROM11_PDGAIN_MASK) >>
3388 SROM11_PDGAIN_SHIFT);
3389 varbuf_append(&b, vstr_epagaing, 5,
3390 (fem_cfg & SROM11_EPAGAIN_MASK) >>
3391 SROM11_EPAGAIN_SHIFT);
3392 varbuf_append(&b, vstr_tssiposslopeg, 5,
3393 (fem_cfg & SROM11_TSSIPOSSLOPE_MASK) >>
3394 SROM11_TSSIPOSSLOPE_SHIFT);
3395 break;
3396 }
3397
3398 case HNBU_ACPA_C0: {
3399 const int a = 0;
3400
3401 #ifndef OTP_SKIP_MAXP_PAPARAMS
3402 varbuf_append(&b, vstr_subband5gver,
3403 (cis[i + 2] << 8) + cis[i + 1]);
3404 /* maxp2g */
3405 /* Decoupling this touple to program from NVRAM */
3406 varbuf_append(&b, vstr_maxp2ga, a,
3407 (cis[i + 4] << 8) + cis[i + 3]);
3408 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3409 /* pa2g */
3410 varbuf_append(&b, vstr_pa2ga, a,
3411 (cis[i + 6] << 8) + cis[i + 5],
3412 (cis[i + 8] << 8) + cis[i + 7],
3413 (cis[i + 10] << 8) + cis[i + 9]);
3414 #ifndef OTP_SKIP_MAXP_PAPARAMS
3415 /* maxp5g */
3416 varbuf_append(&b, vstr_maxp5ga, a,
3417 cis[i + 11],
3418 cis[i + 12],
3419 cis[i + 13],
3420 cis[i + 14]);
3421 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3422 /* pa5g */
3423 varbuf_append(&b, vstr_pa5ga, a,
3424 (cis[i + 16] << 8) + cis[i + 15],
3425 (cis[i + 18] << 8) + cis[i + 17],
3426 (cis[i + 20] << 8) + cis[i + 19],
3427 (cis[i + 22] << 8) + cis[i + 21],
3428 (cis[i + 24] << 8) + cis[i + 23],
3429 (cis[i + 26] << 8) + cis[i + 25],
3430 (cis[i + 28] << 8) + cis[i + 27],
3431 (cis[i + 30] << 8) + cis[i + 29],
3432 (cis[i + 32] << 8) + cis[i + 31],
3433 (cis[i + 34] << 8) + cis[i + 33],
3434 (cis[i + 36] << 8) + cis[i + 35],
3435 (cis[i + 38] << 8) + cis[i + 37]);
3436 break;
3437 }
3438
3439 case HNBU_ACPA_C1: {
3440 const int a = 1;
3441
3442 #ifndef OTP_SKIP_MAXP_PAPARAMS
3443 /* maxp2g */
3444 /* Decoupling this touple to program from NVRAM */
3445 varbuf_append(&b, vstr_maxp2ga, a,
3446 (cis[i + 2] << 8) + cis[i + 1]);
3447 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3448 /* pa2g */
3449 varbuf_append(&b, vstr_pa2ga, a,
3450 (cis[i + 4] << 8) + cis[i + 3],
3451 (cis[i + 6] << 8) + cis[i + 5],
3452 (cis[i + 8] << 8) + cis[i + 7]);
3453 #ifndef OTP_SKIP_MAXP_PAPARAMS
3454 /* maxp5g */
3455 varbuf_append(&b, vstr_maxp5ga, a,
3456 cis[i + 9],
3457 cis[i + 10],
3458 cis[i + 11],
3459 cis[i + 12]);
3460 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3461 /* pa5g */
3462 varbuf_append(&b, vstr_pa5ga, a,
3463 (cis[i + 14] << 8) + cis[i + 13],
3464 (cis[i + 16] << 8) + cis[i + 15],
3465 (cis[i + 18] << 8) + cis[i + 17],
3466 (cis[i + 20] << 8) + cis[i + 19],
3467 (cis[i + 22] << 8) + cis[i + 21],
3468 (cis[i + 24] << 8) + cis[i + 23],
3469 (cis[i + 26] << 8) + cis[i + 25],
3470 (cis[i + 28] << 8) + cis[i + 27],
3471 (cis[i + 30] << 8) + cis[i + 29],
3472 (cis[i + 32] << 8) + cis[i + 31],
3473 (cis[i + 34] << 8) + cis[i + 33],
3474 (cis[i + 36] << 8) + cis[i + 35]);
3475 break;
3476 }
3477
3478 case HNBU_ACPA_C2: {
3479 const int a = 2;
3480
3481 #ifndef OTP_SKIP_MAXP_PAPARAMS
3482 /* maxp2g */
3483 /* Decoupling this touple to program from NVRAM */
3484 varbuf_append(&b, vstr_maxp2ga, a,
3485 (cis[i + 2] << 8) + cis[i + 1]);
3486 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3487 /* pa2g */
3488 varbuf_append(&b, vstr_pa2ga, a,
3489 (cis[i + 4] << 8) + cis[i + 3],
3490 (cis[i + 6] << 8) + cis[i + 5],
3491 (cis[i + 8] << 8) + cis[i + 7]);
3492 #ifndef OTP_SKIP_MAXP_PAPARAMS
3493 /* maxp5g */
3494 varbuf_append(&b, vstr_maxp5ga, a,
3495 cis[i + 9],
3496 cis[i + 10],
3497 cis[i + 11],
3498 cis[i + 12]);
3499 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3500 /* pa5g */
3501 varbuf_append(&b, vstr_pa5ga, a,
3502 (cis[i + 14] << 8) + cis[i + 13],
3503 (cis[i + 16] << 8) + cis[i + 15],
3504 (cis[i + 18] << 8) + cis[i + 17],
3505 (cis[i + 20] << 8) + cis[i + 19],
3506 (cis[i + 22] << 8) + cis[i + 21],
3507 (cis[i + 24] << 8) + cis[i + 23],
3508 (cis[i + 26] << 8) + cis[i + 25],
3509 (cis[i + 28] << 8) + cis[i + 27],
3510 (cis[i + 30] << 8) + cis[i + 29],
3511 (cis[i + 32] << 8) + cis[i + 31],
3512 (cis[i + 34] << 8) + cis[i + 33],
3513 (cis[i + 36] << 8) + cis[i + 35]);
3514 break;
3515 }
3516
3517 case HNBU_MEAS_PWR:
3518 varbuf_append(&b, vstr_measpower, cis[i + 1]);
3519 varbuf_append(&b, vstr_measpowerX, 1, (cis[i + 2]));
3520 varbuf_append(&b, vstr_measpowerX, 2, (cis[i + 3]));
3521 varbuf_append(&b, vstr_rawtempsense,
3522 ((cis[i + 5] & 0x1) << 8) + cis[i + 4]);
3523 break;
3524
3525 case HNBU_PDOFF:
3526 varbuf_append(&b, vstr_pdoffsetma, 40, 0,
3527 (cis[i + 2] << 8) + cis[i + 1]);
3528 varbuf_append(&b, vstr_pdoffsetma, 40, 1,
3529 (cis[i + 4] << 8) + cis[i + 3]);
3530 varbuf_append(&b, vstr_pdoffsetma, 40, 2,
3531 (cis[i + 6] << 8) + cis[i + 5]);
3532 varbuf_append(&b, vstr_pdoffsetma, 80, 0,
3533 (cis[i + 8] << 8) + cis[i + 7]);
3534 varbuf_append(&b, vstr_pdoffsetma, 80, 1,
3535 (cis[i + 10] << 8) + cis[i + 9]);
3536 varbuf_append(&b, vstr_pdoffsetma, 80, 2,
3537 (cis[i + 12] << 8) + cis[i + 11]);
3538 break;
3539
3540 case HNBU_ACPPR_2GPO:
3541 varbuf_append(&b, vstr_dot11agofdmhrbw202gpo,
3542 (cis[i + 2] << 8) + cis[i + 1]);
3543 varbuf_append(&b, vstr_ofdmlrbw202gpo,
3544 (cis[i + 4] << 8) + cis[i + 3]);
3545
3546 if (tlen < 13) break;
3547 varbuf_append(&b, vstr_sb20in40dot11agofdm2gpo,
3548 (cis[i + 6] << 8) + cis[i + 5]);
3549 varbuf_append(&b, vstr_sb20in80dot11agofdm2gpo,
3550 (cis[i + 8] << 8) + cis[i + 7]);
3551 varbuf_append(&b, vstr_sb20in40ofdmlrbw202gpo,
3552 (cis[i + 10] << 8) + cis[i + 9]);
3553 varbuf_append(&b, vstr_sb20in80ofdmlrbw202gpo,
3554 (cis[i + 12] << 8) + cis[i + 11]);
3555 break;
3556
3557 case HNBU_ACPPR_5GPO:
3558 varbuf_append(&b, vstr_mcsbw805gpo, 'l',
3559 (cis[i + 4] << 24) + (cis[i + 3] << 16) +
3560 (cis[i + 2] << 8) + cis[i + 1]);
3561 varbuf_append(&b, vstr_mcsbw1605gpo, 'l',
3562 (cis[i + 8] << 24) + (cis[i + 7] << 16) +
3563 (cis[i + 6] << 8) + cis[i + 5]);
3564 varbuf_append(&b, vstr_mcsbw805gpo, 'm',
3565 (cis[i + 12] << 24) + (cis[i + 11] << 16) +
3566 (cis[i + 10] << 8) + cis[i + 9]);
3567 varbuf_append(&b, vstr_mcsbw1605gpo, 'm',
3568 (cis[i + 16] << 24) + (cis[i + 15] << 16) +
3569 (cis[i + 14] << 8) + cis[i + 13]);
3570 varbuf_append(&b, vstr_mcsbw805gpo, 'h',
3571 (cis[i + 20] << 24) + (cis[i + 19] << 16) +
3572 (cis[i + 18] << 8) + cis[i + 17]);
3573 varbuf_append(&b, vstr_mcsbw1605gpo, 'h',
3574 (cis[i + 24] << 24) + (cis[i + 23] << 16) +
3575 (cis[i + 22] << 8) + cis[i + 21]);
3576 varbuf_append(&b, vstr_mcslr5gpo, 'l',
3577 (cis[i + 26] << 8) + cis[i + 25]);
3578 varbuf_append(&b, vstr_mcslr5gpo, 'm',
3579 (cis[i + 28] << 8) + cis[i + 27]);
3580 varbuf_append(&b, vstr_mcslr5gpo, 'h',
3581 (cis[i + 30] << 8) + cis[i + 29]);
3582
3583 if (tlen < 51) break;
3584 varbuf_append(&b, vstr_mcsbw80p805gpo, 'l',
3585 (cis[i + 34] << 24) + (cis[i + 33] << 16) +
3586 (cis[i + 32] << 8) + cis[i + 31]);
3587 varbuf_append(&b, vstr_mcsbw80p805gpo, 'm',
3588 (cis[i + 38] << 24) + (cis[i + 37] << 16) +
3589 (cis[i + 36] << 8) + cis[i + 35]);
3590 varbuf_append(&b, vstr_mcsbw80p805gpo, 'h',
3591 (cis[i + 42] << 24) + (cis[i + 41] << 16) +
3592 (cis[i + 40] << 8) + cis[i + 39]);
3593 varbuf_append(&b, vstr_mcsbw80p805g1po, 'x',
3594 (cis[i + 46] << 24) + (cis[i + 45] << 16) +
3595 (cis[i + 44] << 8) + cis[i + 43]);
3596 varbuf_append(&b, vstr_mcslr5g1po, 'x',
3597 (cis[i + 48] << 8) + cis[i + 47]);
3598 varbuf_append(&b, vstr_mcslr5g80p80po,
3599 (cis[i + 50] << 8) + cis[i + 49]);
3600 varbuf_append(&b, vstr_mcsbw805g1po, 'x',
3601 (cis[i + 54] << 24) + (cis[i + 53] << 16) +
3602 (cis[i + 52] << 8) + cis[i + 51]);
3603 varbuf_append(&b, vstr_mcsbw1605g1po, 'x',
3604 (cis[i + 58] << 24) + (cis[i + 57] << 16) +
3605 (cis[i + 56] << 8) + cis[i + 55]);
3606
3607 break;
3608
3609 case HNBU_MCS5Gx1PO:
3610 varbuf_append(&b, vstr_mcsbw205g1po, 'x',
3611 (cis[i + 4] << 24) + (cis[i + 3] << 16) +
3612 (cis[i + 2] << 8) + cis[i + 1]);
3613 varbuf_append(&b, vstr_mcsbw405g1po, 'x',
3614 (cis[i + 8] << 24) + (cis[i + 7] << 16) +
3615 (cis[i + 6] << 8) + cis[i + 5]);
3616 break;
3617
3618 case HNBU_ACPPR_SBPO:
3619 varbuf_append(&b, vstr_sb20in40rpo, 'h',
3620 (cis[i + 2] << 8) + cis[i + 1]);
3621 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'l',
3622 (cis[i + 4] << 8) + cis[i + 3]);
3623 varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'l',
3624 (cis[i + 6] << 8) + cis[i + 5]);
3625 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'm',
3626 (cis[i + 8] << 8) + cis[i + 7]);
3627 varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'm',
3628 (cis[i + 10] << 8) + cis[i + 9]);
3629 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'h',
3630 (cis[i + 12] << 8) + cis[i + 11]);
3631 varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'h',
3632 (cis[i + 14] << 8) + cis[i + 13]);
3633 varbuf_append(&b, vstr_sb20in40rpo, 'l',
3634 (cis[i + 16] << 8) + cis[i + 15]);
3635 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'l',
3636 (cis[i + 18] << 8) + cis[i + 17]);
3637 varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'l',
3638 (cis[i + 20] << 8) + cis[i + 19]);
3639 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'm',
3640 (cis[i + 22] << 8) + cis[i + 21]);
3641 varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'm',
3642 (cis[i + 24] << 8) + cis[i + 23]);
3643 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'h',
3644 (cis[i + 26] << 8) + cis[i + 25]);
3645 varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'h',
3646 (cis[i + 28] << 8) + cis[i + 27]);
3647 varbuf_append(&b, vstr_dot11agduprpo, 'h',
3648 (cis[i + 32] << 24) + (cis[i + 31] << 16) +
3649 (cis[i + 30] << 8) + cis[i + 29]);
3650 varbuf_append(&b, vstr_dot11agduprpo, 'l',
3651 (cis[i + 36] << 24) + (cis[i + 35] << 16) +
3652 (cis[i + 34] << 8) + cis[i + 33]);
3653
3654 if (tlen < 49) break;
3655 varbuf_append(&b, vstr_sb20in40and80rpo, 'h',
3656 (cis[i + 38] << 8) + cis[i + 37]);
3657 varbuf_append(&b, vstr_sb20in40and80rpo, 'l',
3658 (cis[i + 40] << 8) + cis[i + 39]);
3659 varbuf_append(&b, vstr_sb20in80and160r5g1po, 'h', 'x',
3660 (cis[i + 42] << 8) + cis[i + 41]);
3661 varbuf_append(&b, vstr_sb20in80and160r5g1po, 'l', 'x',
3662 (cis[i + 44] << 8) + cis[i + 43]);
3663 varbuf_append(&b, vstr_sb40and80r5g1po, 'h', 'x',
3664 (cis[i + 46] << 8) + cis[i + 45]);
3665 varbuf_append(&b, vstr_sb40and80r5g1po, 'l', 'x',
3666 (cis[i + 48] << 8) + cis[i + 47]);
3667 break;
3668
3669 case HNBU_ACPPR_SB8080_PO:
3670 varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'h', 'l',
3671 (cis[i + 2] << 8) + cis[i + 1]);
3672 varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'l', 'l',
3673 (cis[i + 4] << 8) + cis[i + 3]);
3674 varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'h', 'm',
3675 (cis[i + 6] << 8) + cis[i + 5]);
3676 varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'l', 'm',
3677 (cis[i + 8] << 8) + cis[i + 7]);
3678 varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'h', 'h',
3679 (cis[i + 10] << 8) + cis[i + 9]);
3680 varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'l', 'h',
3681 (cis[i + 12] << 8) + cis[i + 11]);
3682 varbuf_append(&b, vstr_sb2040and80in80p80r5g1po, 'h', 'x',
3683 (cis[i + 14] << 8) + cis[i + 13]);
3684 varbuf_append(&b, vstr_sb2040and80in80p80r5g1po, 'l', 'x',
3685 (cis[i + 16] << 8) + cis[i + 15]);
3686 varbuf_append(&b, vstr_sb20in80p80r5gpo, 'h',
3687 (cis[i + 18] << 8) + cis[i + 17]);
3688 varbuf_append(&b, vstr_sb20in80p80r5gpo, 'l',
3689 (cis[i + 20] << 8) + cis[i + 19]);
3690 varbuf_append(&b, vstr_dot11agduppo,
3691 (cis[i + 22] << 8) + cis[i + 21]);
3692 break;
3693
3694 case HNBU_NOISELVL:
3695 /* noiselvl2g */
3696 varbuf_append(&b, vstr_noiselvl2ga, 0,
3697 (cis[i + 1] & 0x1f));
3698 varbuf_append(&b, vstr_noiselvl2ga, 1,
3699 (cis[i + 2] & 0x1f));
3700 varbuf_append(&b, vstr_noiselvl2ga, 2,
3701 (cis[i + 3] & 0x1f));
3702 /* noiselvl5g */
3703 varbuf_append(&b, vstr_noiselvl5ga, 0,
3704 (cis[i + 4] & 0x1f),
3705 (cis[i + 5] & 0x1f),
3706 (cis[i + 6] & 0x1f),
3707 (cis[i + 7] & 0x1f));
3708 varbuf_append(&b, vstr_noiselvl5ga, 1,
3709 (cis[i + 8] & 0x1f),
3710 (cis[i + 9] & 0x1f),
3711 (cis[i + 10] & 0x1f),
3712 (cis[i + 11] & 0x1f));
3713 varbuf_append(&b, vstr_noiselvl5ga, 2,
3714 (cis[i + 12] & 0x1f),
3715 (cis[i + 13] & 0x1f),
3716 (cis[i + 14] & 0x1f),
3717 (cis[i + 15] & 0x1f));
3718 break;
3719
3720 case HNBU_RXGAIN_ERR:
3721 varbuf_append(&b, vstr_rxgainerr2ga, 0,
3722 (cis[i + 1] & 0x3f));
3723 varbuf_append(&b, vstr_rxgainerr2ga, 1,
3724 (cis[i + 2] & 0x1f));
3725 varbuf_append(&b, vstr_rxgainerr2ga, 2,
3726 (cis[i + 3] & 0x1f));
3727 varbuf_append(&b, vstr_rxgainerr5ga, 0,
3728 (cis[i + 4] & 0x3f),
3729 (cis[i + 5] & 0x3f),
3730 (cis[i + 6] & 0x3f),
3731 (cis[i + 7] & 0x3f));
3732 varbuf_append(&b, vstr_rxgainerr5ga, 1,
3733 (cis[i + 8] & 0x1f),
3734 (cis[i + 9] & 0x1f),
3735 (cis[i + 10] & 0x1f),
3736 (cis[i + 11] & 0x1f));
3737 varbuf_append(&b, vstr_rxgainerr5ga, 2,
3738 (cis[i + 12] & 0x1f),
3739 (cis[i + 13] & 0x1f),
3740 (cis[i + 14] & 0x1f),
3741 (cis[i + 15] & 0x1f));
3742 break;
3743
3744 case HNBU_AGBGA:
3745 varbuf_append(&b, vstr_agbg, 0, cis[i + 1]);
3746 varbuf_append(&b, vstr_agbg, 1, cis[i + 2]);
3747 varbuf_append(&b, vstr_agbg, 2, cis[i + 3]);
3748 varbuf_append(&b, vstr_aga, 0, cis[i + 4]);
3749 varbuf_append(&b, vstr_aga, 1, cis[i + 5]);
3750 varbuf_append(&b, vstr_aga, 2, cis[i + 6]);
3751 break;
3752
3753 case HNBU_ACRXGAINS_C0: {
3754 int a = 0;
3755
3756 /* rxgains */
3757 uint16 rxgains = (cis[i + 2] << 8) + cis[i + 1];
3758 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a,
3759 (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3760 SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3761 varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a,
3762 (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3763 SROM11_RXGAINS5GTRISOA_SHIFT);
3764 varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a,
3765 (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3766 SROM11_RXGAINS5GELNAGAINA_SHIFT);
3767 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a,
3768 (rxgains & SROM11_RXGAINS2GTRELNABYPA_MASK) >>
3769 SROM11_RXGAINS2GTRELNABYPA_SHIFT);
3770 varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a,
3771 (rxgains & SROM11_RXGAINS2GTRISOA_MASK) >>
3772 SROM11_RXGAINS2GTRISOA_SHIFT);
3773 varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a,
3774 (rxgains & SROM11_RXGAINS2GELNAGAINA_MASK) >>
3775 SROM11_RXGAINS2GELNAGAINA_SHIFT);
3776 /* rxgains1 */
3777 rxgains = (cis[i + 4] << 8) + cis[i + 3];
3778 varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'h', a,
3779 (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3780 SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3781 varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'h', a,
3782 (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3783 SROM11_RXGAINS5GTRISOA_SHIFT);
3784 varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'h', a,
3785 (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3786 SROM11_RXGAINS5GELNAGAINA_SHIFT);
3787 varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'm', a,
3788 (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3789 SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3790 varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'm', a,
3791 (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3792 SROM11_RXGAINS5GTRISOA_SHIFT);
3793 varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'm', a,
3794 (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3795 SROM11_RXGAINS5GELNAGAINA_SHIFT);
3796 break;
3797 }
3798
3799 case HNBU_ACRXGAINS_C1: {
3800 int a = 1;
3801
3802 /* rxgains */
3803 uint16 rxgains = (cis[i + 2] << 8) + cis[i + 1];
3804 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a,
3805 (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3806 SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3807 varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a,
3808 (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3809 SROM11_RXGAINS5GTRISOA_SHIFT);
3810 varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a,
3811 (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3812 SROM11_RXGAINS5GELNAGAINA_SHIFT);
3813 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a,
3814 (rxgains & SROM11_RXGAINS2GTRELNABYPA_MASK) >>
3815 SROM11_RXGAINS2GTRELNABYPA_SHIFT);
3816 varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a,
3817 (rxgains & SROM11_RXGAINS2GTRISOA_MASK) >>
3818 SROM11_RXGAINS2GTRISOA_SHIFT);
3819 varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a,
3820 (rxgains & SROM11_RXGAINS2GELNAGAINA_MASK) >>
3821 SROM11_RXGAINS2GELNAGAINA_SHIFT);
3822 /* rxgains1 */
3823 rxgains = (cis[i + 4] << 8) + cis[i + 3];
3824 varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'h', a,
3825 (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3826 SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3827 varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'h', a,
3828 (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3829 SROM11_RXGAINS5GTRISOA_SHIFT);
3830 varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'h', a,
3831 (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3832 SROM11_RXGAINS5GELNAGAINA_SHIFT);
3833 varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'm', a,
3834 (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3835 SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3836 varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'm', a,
3837 (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3838 SROM11_RXGAINS5GTRISOA_SHIFT);
3839 varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'm', a,
3840 (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3841 SROM11_RXGAINS5GELNAGAINA_SHIFT);
3842 break;
3843 }
3844
3845 case HNBU_ACRXGAINS_C2: {
3846 int a = 2;
3847
3848 /* rxgains */
3849 uint16 rxgains = (cis[i + 2] << 8) + cis[i + 1];
3850 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a,
3851 (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3852 SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3853 varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a,
3854 (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3855 SROM11_RXGAINS5GTRISOA_SHIFT);
3856 varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a,
3857 (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3858 SROM11_RXGAINS5GELNAGAINA_SHIFT);
3859 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a,
3860 (rxgains & SROM11_RXGAINS2GTRELNABYPA_MASK) >>
3861 SROM11_RXGAINS2GTRELNABYPA_SHIFT);
3862 varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a,
3863 (rxgains & SROM11_RXGAINS2GTRISOA_MASK) >>
3864 SROM11_RXGAINS2GTRISOA_SHIFT);
3865 varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a,
3866 (rxgains & SROM11_RXGAINS2GELNAGAINA_MASK) >>
3867 SROM11_RXGAINS2GELNAGAINA_SHIFT);
3868 /* rxgains1 */
3869 rxgains = (cis[i + 4] << 8) + cis[i + 3];
3870 varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'h', a,
3871 (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3872 SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3873 varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'h', a,
3874 (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3875 SROM11_RXGAINS5GTRISOA_SHIFT);
3876 varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'h', a,
3877 (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3878 SROM11_RXGAINS5GELNAGAINA_SHIFT);
3879 varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'm', a,
3880 (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3881 SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3882 varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'm', a,
3883 (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3884 SROM11_RXGAINS5GTRISOA_SHIFT);
3885 varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'm', a,
3886 (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3887 SROM11_RXGAINS5GELNAGAINA_SHIFT);
3888 break;
3889 }
3890
3891 case HNBU_TXDUTY: {
3892 varbuf_append(&b, vstr_txduty_ofdm, 40,
3893 (cis[i + 2] << 8) + cis[i + 1]);
3894 varbuf_append(&b, vstr_txduty_thresh, 40,
3895 (cis[i + 4] << 8) + cis[i + 3]);
3896 varbuf_append(&b, vstr_txduty_ofdm, 80,
3897 (cis[i + 6] << 8) + cis[i + 5]);
3898 varbuf_append(&b, vstr_txduty_thresh, 80,
3899 (cis[i + 8] << 8) + cis[i + 7]);
3900 break;
3901 }
3902
3903 case HNBU_UUID: {
3904 /* uuid format 12345678-1234-5678-1234-567812345678 */
3905
3906 char uuidstr[37]; /* 32 ids, 4 '-', 1 Null */
3907
3908 snprintf(uuidstr, sizeof(uuidstr),
3909 rstr_uuidstr,
3910 cis[i + 1], cis[i + 2], cis[i + 3], cis[i + 4],
3911 cis[i + 5], cis[i + 6], cis[i + 7], cis[i + 8],
3912 cis[i + 9], cis[i + 10], cis[i + 11], cis[i + 12],
3913 cis[i + 13], cis[i + 14], cis[i + 15], cis[i + 16]);
3914
3915 varbuf_append(&b, vstr_uuid, uuidstr);
3916 break;
3917 }
3918
3919 case HNBU_WOWLGPIO:
3920 varbuf_append(&b, vstr_wowlgpio, ((cis[i + 1]) & 0x7F));
3921 varbuf_append(&b, vstr_wowlgpiopol,
3922 (((cis[i + 1]) >> 7) & 0x1));
3923 break;
3924
3925 #endif /* !BCM_BOOTLOADER */
3926 #ifdef BCMUSBDEV_COMPOSITE
3927 case HNBU_USBDESC_COMPOSITE:
3928 varbuf_append(&b, vstr_usbdesc_composite,
3929 (cis[i + 2] << 8) | cis[i + 1]);
3930 break;
3931 #endif /* BCMUSBDEV_COMPOSITE */
3932 case HNBU_USBUTMI_CTL:
3933 varbuf_append(&b, vstr_usbutmi_ctl,
3934 (cis[i + 2] << 8) | cis[i + 1]);
3935 break;
3936
3937 case HNBU_USBSSPHY_UTMI_CTL0:
3938 varbuf_append(&b, vstr_usbssphy_utmi_ctl0,
3939 (cis[i + 4] << 24) | (cis[i + 3] << 16) |
3940 (cis[i + 2] << 8) | cis[i + 1]);
3941 break;
3942
3943 case HNBU_USBSSPHY_UTMI_CTL1:
3944 varbuf_append(&b, vstr_usbssphy_utmi_ctl1,
3945 (cis[i + 4] << 24) | (cis[i + 3] << 16) |
3946 (cis[i + 2] << 8) | cis[i + 1]);
3947 break;
3948
3949 case HNBU_USBSSPHY_UTMI_CTL2:
3950 varbuf_append(&b, vstr_usbssphy_utmi_ctl2,
3951 (cis[i + 4] << 24) | (cis[i + 3] << 16) |
3952 (cis[i + 2] << 8) | cis[i + 1]);
3953 break;
3954
3955 case HNBU_USBSSPHY_SLEEP0:
3956 varbuf_append(&b, vstr_usbssphy_sleep0,
3957 (cis[i + 2] << 8) | cis[i + 1]);
3958 break;
3959
3960 case HNBU_USBSSPHY_SLEEP1:
3961 varbuf_append(&b, vstr_usbssphy_sleep1,
3962 (cis[i + 2] << 8) | cis[i + 1]);
3963 break;
3964
3965 case HNBU_USBSSPHY_SLEEP2:
3966 varbuf_append(&b, vstr_usbssphy_sleep2,
3967 (cis[i + 2] << 8) | cis[i + 1]);
3968 break;
3969
3970 case HNBU_USBSSPHY_SLEEP3:
3971 varbuf_append(&b, vstr_usbssphy_sleep3,
3972 (cis[i + 2] << 8) | cis[i + 1]);
3973 break;
3974 case HNBU_USBSSPHY_MDIO: {
3975 uint8 setnum;
3976 uint16 k;
3977
3978 setnum = (cis[i + 1])/4;
3979 if (setnum == 0)
3980 break;
3981 for (j = 0; j < setnum; j++) {
3982 k = j*12;
3983 varbuf_append(&b, vstr_usbssphy_mdio, j,
3984 (cis[i+4+k]<<16) | (cis[i+3+k]<<8) | cis[i+2+k],
3985 (cis[i+7+k]<<16) | (cis[i+6+k]<<8) | cis[i+5+k],
3986 (cis[i+10+k]<<16) | (cis[i+9+k]<<8) | cis[i+8+k],
3987 (cis[i+13+k]<<16) | (cis[i+12+k]<<8) | cis[i+11+k]);
3988 }
3989 break;
3990 }
3991 case HNBU_USB30PHY_NOSS:
3992 varbuf_append(&b, vstr_usb30phy_noss, cis[i + 1]);
3993 break;
3994 case HNBU_USB30PHY_U1U2:
3995 varbuf_append(&b, vstr_usb30phy_u1u2, cis[i + 1]);
3996 break;
3997 case HNBU_USB30PHY_REGS:
3998 varbuf_append(&b, vstr_usb30phy_regs, 0,
3999 cis[i+4]|cis[i+3]|cis[i+2]|cis[i+1],
4000 cis[i+8]|cis[i+7]|cis[i+6]|cis[i+5],
4001 cis[i+12]|cis[i+11]|cis[i+10]|cis[i+9],
4002 cis[i+16]|cis[i+15]|cis[i+14]|cis[i+13]);
4003 varbuf_append(&b, vstr_usb30phy_regs, 1,
4004 cis[i+20]|cis[i+19]|cis[i+18]|cis[i+17],
4005 cis[i+24]|cis[i+23]|cis[i+22]|cis[i+21],
4006 cis[i+28]|cis[i+27]|cis[i+26]|cis[i+25],
4007 cis[i+32]|cis[i+31]|cis[i+30]|cis[i+29]);
4008
4009 break;
4010
4011 case HNBU_PDOFF_2G: {
4012 uint16 pdoff_2g = (cis[i + 2] << 8) + cis[i + 1];
4013 varbuf_append(&b, vstr_pdoffset2gma, 40, 0,
4014 (pdoff_2g & SROM11_PDOFF_2G_40M_A0_MASK) >>
4015 SROM11_PDOFF_2G_40M_A0_SHIFT);
4016 varbuf_append(&b, vstr_pdoffset2gma, 40, 1,
4017 (pdoff_2g & SROM11_PDOFF_2G_40M_A1_MASK) >>
4018 SROM11_PDOFF_2G_40M_A1_SHIFT);
4019 varbuf_append(&b, vstr_pdoffset2gma, 40, 2,
4020 (pdoff_2g & SROM11_PDOFF_2G_40M_A2_MASK) >>
4021 SROM11_PDOFF_2G_40M_A2_SHIFT);
4022 varbuf_append(&b, vstr_pdoffset2gmvalid, 40,
4023 (pdoff_2g & SROM11_PDOFF_2G_40M_VALID_MASK) >>
4024 SROM11_PDOFF_2G_40M_VALID_SHIFT);
4025 break;
4026 }
4027
4028 case HNBU_ACPA_CCK_C0:
4029 varbuf_append(&b, vstr_pa2gccka, 0,
4030 (cis[i + 2] << 8) + cis[i + 1],
4031 (cis[i + 4] << 8) + cis[i + 3],
4032 (cis[i + 6] << 8) + cis[i + 5]);
4033 break;
4034
4035 case HNBU_ACPA_CCK_C1:
4036 varbuf_append(&b, vstr_pa2gccka, 1,
4037 (cis[i + 2] << 8) + cis[i + 1],
4038 (cis[i + 4] << 8) + cis[i + 3],
4039 (cis[i + 6] << 8) + cis[i + 5]);
4040 break;
4041
4042 case HNBU_ACPA_40:
4043 varbuf_append(&b, vstr_pa5gbw40a, 0,
4044 (cis[i + 2] << 8) + cis[i + 1],
4045 (cis[i + 4] << 8) + cis[i + 3],
4046 (cis[i + 6] << 8) + cis[i + 5],
4047 (cis[i + 8] << 8) + cis[i + 7],
4048 (cis[i + 10] << 8) + cis[i + 9],
4049 (cis[i + 12] << 8) + cis[i + 11],
4050 (cis[i + 14] << 8) + cis[i + 13],
4051 (cis[i + 16] << 8) + cis[i + 15],
4052 (cis[i + 18] << 8) + cis[i + 17],
4053 (cis[i + 20] << 8) + cis[i + 19],
4054 (cis[i + 22] << 8) + cis[i + 21],
4055 (cis[i + 24] << 8) + cis[i + 23]);
4056 break;
4057
4058 case HNBU_ACPA_80:
4059 varbuf_append(&b, vstr_pa5gbw80a, 0,
4060 (cis[i + 2] << 8) + cis[i + 1],
4061 (cis[i + 4] << 8) + cis[i + 3],
4062 (cis[i + 6] << 8) + cis[i + 5],
4063 (cis[i + 8] << 8) + cis[i + 7],
4064 (cis[i + 10] << 8) + cis[i + 9],
4065 (cis[i + 12] << 8) + cis[i + 11],
4066 (cis[i + 14] << 8) + cis[i + 13],
4067 (cis[i + 16] << 8) + cis[i + 15],
4068 (cis[i + 18] << 8) + cis[i + 17],
4069 (cis[i + 20] << 8) + cis[i + 19],
4070 (cis[i + 22] << 8) + cis[i + 21],
4071 (cis[i + 24] << 8) + cis[i + 23]);
4072 break;
4073
4074 case HNBU_ACPA_4080:
4075 varbuf_append(&b, vstr_pa5gbw4080a, 0,
4076 (cis[i + 2] << 8) + cis[i + 1],
4077 (cis[i + 4] << 8) + cis[i + 3],
4078 (cis[i + 6] << 8) + cis[i + 5],
4079 (cis[i + 8] << 8) + cis[i + 7],
4080 (cis[i + 10] << 8) + cis[i + 9],
4081 (cis[i + 12] << 8) + cis[i + 11],
4082 (cis[i + 14] << 8) + cis[i + 13],
4083 (cis[i + 16] << 8) + cis[i + 15],
4084 (cis[i + 18] << 8) + cis[i + 17],
4085 (cis[i + 20] << 8) + cis[i + 19],
4086 (cis[i + 22] << 8) + cis[i + 21],
4087 (cis[i + 24] << 8) + cis[i + 23]);
4088 varbuf_append(&b, vstr_pa5gbw4080a, 1,
4089 (cis[i + 26] << 8) + cis[i + 25],
4090 (cis[i + 28] << 8) + cis[i + 27],
4091 (cis[i + 30] << 8) + cis[i + 29],
4092 (cis[i + 32] << 8) + cis[i + 31],
4093 (cis[i + 34] << 8) + cis[i + 33],
4094 (cis[i + 36] << 8) + cis[i + 35],
4095 (cis[i + 38] << 8) + cis[i + 37],
4096 (cis[i + 40] << 8) + cis[i + 39],
4097 (cis[i + 42] << 8) + cis[i + 41],
4098 (cis[i + 44] << 8) + cis[i + 43],
4099 (cis[i + 46] << 8) + cis[i + 45],
4100 (cis[i + 48] << 8) + cis[i + 47]);
4101 break;
4102
4103 case HNBU_ACPA_4X4C0:
4104 case HNBU_ACPA_4X4C1:
4105 case HNBU_ACPA_4X4C2:
4106 case HNBU_ACPA_4X4C3: {
4107 int core_num = 0;
4108 uint8 tuple = cis[i];
4109
4110 if (tuple == HNBU_ACPA_4X4C1) {
4111 core_num = 1;
4112 } else if (tuple == HNBU_ACPA_4X4C2) {
4113 core_num = 2;
4114 } else if (tuple == HNBU_ACPA_4X4C3) {
4115 core_num = 3;
4116 }
4117
4118 varbuf_append(&b, vstr_maxp2ga, core_num, cis[i + 1]);
4119 /* pa2g */
4120 varbuf_append(&b, vstr_sr13pa2ga, core_num,
4121 (cis[i + 3] << 8) + cis[i + 2],
4122 (cis[i + 5] << 8) + cis[i + 4],
4123 (cis[i + 7] << 8) + cis[i + 6],
4124 (cis[i + 9] << 8) + cis[i + 8]);
4125 /* pa2g40 */
4126 varbuf_append(&b, vstr_pa2g40a, core_num,
4127 (cis[i + 11] << 8) + cis[i + 10],
4128 (cis[i + 13] << 8) + cis[i + 12],
4129 (cis[i + 15] << 8) + cis[i + 14],
4130 (cis[i + 17] << 8) + cis[i + 16]);
4131 for (j = 0; j < 5; j++) {
4132 varbuf_append(&b, vstr_maxp5gba, j, core_num,
4133 cis[i + j + 18]);
4134 }
4135 break;
4136 }
4137
4138 case HNBU_ACPA_BW20_4X4C0:
4139 case HNBU_ACPA_BW40_4X4C0:
4140 case HNBU_ACPA_BW80_4X4C0:
4141 case HNBU_ACPA_BW20_4X4C1:
4142 case HNBU_ACPA_BW40_4X4C1:
4143 case HNBU_ACPA_BW80_4X4C1:
4144 case HNBU_ACPA_BW20_4X4C2:
4145 case HNBU_ACPA_BW40_4X4C2:
4146 case HNBU_ACPA_BW80_4X4C2:
4147 case HNBU_ACPA_BW20_4X4C3:
4148 case HNBU_ACPA_BW40_4X4C3:
4149 case HNBU_ACPA_BW80_4X4C3: {
4150 int k = 0;
4151 char pabuf[140]; /* max: 20 '0x????'s + 19 ','s + 1 Null */
4152 int core_num = 0, buflen = 0;
4153 uint8 tuple = cis[i];
4154
4155 if (tuple == HNBU_ACPA_BW20_4X4C1 ||
4156 tuple == HNBU_ACPA_BW40_4X4C1 ||
4157 tuple == HNBU_ACPA_BW80_4X4C1) {
4158 core_num = 1;
4159 } else if (tuple == HNBU_ACPA_BW20_4X4C2 ||
4160 tuple == HNBU_ACPA_BW40_4X4C2 ||
4161 tuple == HNBU_ACPA_BW80_4X4C2) {
4162 core_num = 2;
4163 } else if (tuple == HNBU_ACPA_BW20_4X4C3 ||
4164 tuple == HNBU_ACPA_BW40_4X4C3 ||
4165 tuple == HNBU_ACPA_BW80_4X4C3) {
4166 core_num = 3;
4167 }
4168
4169 buflen = sizeof(pabuf);
4170 for (j = 0; j < 20; j++) { /* cis[i+1] - cis[i+40] */
4171 k += snprintf(pabuf+k, buflen-k, rstr_hex,
4172 ((cis[i + (2*j) + 2] << 8) +
4173 cis[i + (2*j) + 1]));
4174 if (j < 19) {
4175 k += snprintf(pabuf+k, buflen-k,
4176 ",");
4177 }
4178 }
4179
4180 if (tuple == HNBU_ACPA_BW20_4X4C0 ||
4181 tuple == HNBU_ACPA_BW20_4X4C1 ||
4182 tuple == HNBU_ACPA_BW20_4X4C2 ||
4183 tuple == HNBU_ACPA_BW20_4X4C3) {
4184 varbuf_append(&b, vstr_sr13pa5ga, core_num, pabuf);
4185 } else {
4186 int bw = 40;
4187
4188 if (tuple == HNBU_ACPA_BW80_4X4C0 ||
4189 tuple == HNBU_ACPA_BW80_4X4C1 ||
4190 tuple == HNBU_ACPA_BW80_4X4C2 ||
4191 tuple == HNBU_ACPA_BW80_4X4C3) {
4192 bw = 80;
4193 }
4194 varbuf_append(&b, vstr_sr13pa5gbwa, bw,
4195 core_num, pabuf);
4196 }
4197 break;
4198 }
4199
4200 case HNBU_RSSI_DELTA_2G_B0:
4201 case HNBU_RSSI_DELTA_2G_B1:
4202 case HNBU_RSSI_DELTA_2G_B2:
4203 case HNBU_RSSI_DELTA_2G_B3:
4204 case HNBU_RSSI_DELTA_2G_B4: {
4205 uint8 tuple = cis[i];
4206 uint8 grp;
4207 if (tuple == HNBU_RSSI_DELTA_2G_B0) {
4208 grp = 0;
4209 } else if (tuple == HNBU_RSSI_DELTA_2G_B1) {
4210 grp = 1;
4211 } else if (tuple == HNBU_RSSI_DELTA_2G_B2) {
4212 grp = 2;
4213 } else if (tuple == HNBU_RSSI_DELTA_2G_B3) {
4214 grp = 3;
4215 } else {
4216 grp = 4;
4217 }
4218 /* 2G Band Gourp = grp */
4219 varbuf_append(&b, vstr_rssidelta2g, grp,
4220 cis[i + 1], cis[i + 2],
4221 cis[i + 3], cis[i + 4],
4222 cis[i + 5], cis[i + 6],
4223 cis[i + 7], cis[i + 8],
4224 cis[i + 9], cis[i + 10],
4225 cis[i + 11], cis[i + 12],
4226 cis[i + 13], cis[i + 14],
4227 cis[i + 15], cis[i + 16]);
4228 break;
4229 }
4230
4231 case HNBU_RSSI_CAL_FREQ_GRP_2G:
4232 /* 2G Band Gourp Defintion */
4233 varbuf_append(&b, vstr_rssicalfrqg,
4234 cis[i + 1], cis[i + 2],
4235 cis[i + 3], cis[i + 4],
4236 cis[i + 5], cis[i + 6],
4237 cis[i + 7]);
4238 break;
4239
4240 case HNBU_RSSI_DELTA_5GL:
4241 case HNBU_RSSI_DELTA_5GML:
4242 case HNBU_RSSI_DELTA_5GMU:
4243 case HNBU_RSSI_DELTA_5GH: {
4244 uint8 tuple = cis[i];
4245 char *band[] = {"l", "ml", "mu", "h"};
4246 char *pband;
4247 if (tuple == HNBU_RSSI_DELTA_5GL) {
4248 pband = band[0];
4249 } else if (tuple == HNBU_RSSI_DELTA_5GML) {
4250 pband = band[1];
4251 } else if (tuple == HNBU_RSSI_DELTA_5GMU) {
4252 pband = band[2];
4253 } else {
4254 pband = band[3];
4255 }
4256 /* 5G Band = band */
4257 varbuf_append(&b, vstr_rssidelta5g, pband,
4258 cis[i + 1], cis[i + 2],
4259 cis[i + 3], cis[i + 4],
4260 cis[i + 5], cis[i + 6],
4261 cis[i + 7], cis[i + 8],
4262 cis[i + 9], cis[i + 10],
4263 cis[i + 11], cis[i + 12],
4264 cis[i + 13], cis[i + 14],
4265 cis[i + 15], cis[i + 16],
4266 cis[i + 17], cis[i + 17],
4267 cis[i + 19], cis[i + 20],
4268 cis[i + 21], cis[i + 22],
4269 cis[i + 9], cis[i + 24]);
4270 break;
4271 }
4272
4273 case HNBU_ACPA_6G_C0: {
4274 const int a = 0;
4275 #ifndef OTP_SKIP_MAXP_PAPARAMS
4276 varbuf_append(&b, vstr_subband6gver,
4277 (cis[i + 2] << 8) + cis[i + 1]);
4278 /* maxp5g */
4279 varbuf_append(&b, vstr_maxp6ga, a,
4280 cis[i + 3],
4281 cis[i + 4],
4282 cis[i + 5],
4283 cis[i + 6],
4284 cis[i + 7],
4285 cis[i + 8]);
4286 #endif /* OTP_SKIP_MAXP_PAPARAMS */
4287 /* pa5g */
4288 varbuf_append(&b, vstr_pa6ga, a,
4289 (cis[i + 10] << 8) + cis[i + 9],
4290 (cis[i + 12] << 8) + cis[i + 11],
4291 (cis[i + 14] << 8) + cis[i + 13],
4292 (cis[i + 16] << 8) + cis[i + 15],
4293 (cis[i + 18] << 8) + cis[i + 17],
4294 (cis[i + 20] << 8) + cis[i + 19],
4295 (cis[i + 22] << 8) + cis[i + 21],
4296 (cis[i + 24] << 8) + cis[i + 23],
4297 (cis[i + 26] << 8) + cis[i + 25],
4298 (cis[i + 28] << 8) + cis[i + 27],
4299 (cis[i + 30] << 8) + cis[i + 29],
4300 (cis[i + 32] << 8) + cis[i + 31],
4301 (cis[i + 34] << 8) + cis[i + 33],
4302 (cis[i + 36] << 8) + cis[i + 35],
4303 (cis[i + 38] << 8) + cis[i + 37],
4304 (cis[i + 40] << 8) + cis[i + 39],
4305 (cis[i + 42] << 8) + cis[i + 41],
4306 (cis[i + 44] << 8) + cis[i + 43]);
4307 break;
4308 }
4309
4310 case HNBU_ACPA_6G_C1: {
4311 const int a = 1;
4312 #ifndef OTP_SKIP_MAXP_PAPARAMS
4313 /* maxp6g */
4314 varbuf_append(&b, vstr_maxp6ga, a,
4315 cis[i + 1],
4316 cis[i + 2],
4317 cis[i + 3],
4318 cis[i + 4],
4319 cis[i + 5],
4320 cis[i + 6]);
4321 #endif /* OTP_SKIP_MAXP_PAPARAMS */
4322 /* pa6g */
4323 varbuf_append(&b, vstr_pa6ga, a,
4324 (cis[i + 8] << 8) + cis[i + 7],
4325 (cis[i + 10] << 8) + cis[i + 9],
4326 (cis[i + 12] << 8) + cis[i + 11],
4327 (cis[i + 14] << 8) + cis[i + 13],
4328 (cis[i + 16] << 8) + cis[i + 15],
4329 (cis[i + 18] << 8) + cis[i + 17],
4330 (cis[i + 20] << 8) + cis[i + 19],
4331 (cis[i + 22] << 8) + cis[i + 21],
4332 (cis[i + 24] << 8) + cis[i + 23],
4333 (cis[i + 26] << 8) + cis[i + 25],
4334 (cis[i + 28] << 8) + cis[i + 27],
4335 (cis[i + 30] << 8) + cis[i + 29],
4336 (cis[i + 32] << 8) + cis[i + 31],
4337 (cis[i + 34] << 8) + cis[i + 33],
4338 (cis[i + 36] << 8) + cis[i + 35],
4339 (cis[i + 38] << 8) + cis[i + 37],
4340 (cis[i + 40] << 8) + cis[i + 39],
4341 (cis[i + 42] << 8) + cis[i + 41]);
4342 break;
4343 }
4344
4345 case HNBU_ACPA_6G_C2: {
4346 const int a = 2;
4347 #ifndef OTP_SKIP_MAXP_PAPARAMS
4348 /* maxp6g */
4349 varbuf_append(&b, vstr_maxp6ga, a,
4350 cis[i + 1],
4351 cis[i + 2],
4352 cis[i + 3],
4353 cis[i + 4],
4354 cis[i + 5],
4355 cis[i + 6]);
4356 #endif /* OTP_SKIP_MAXP_PAPARAMS */
4357 /* pa6g */
4358 varbuf_append(&b, vstr_pa6ga, a,
4359 (cis[i + 8] << 8) + cis[i + 7],
4360 (cis[i + 10] << 8) + cis[i + 9],
4361 (cis[i + 12] << 8) + cis[i + 11],
4362 (cis[i + 14] << 8) + cis[i + 13],
4363 (cis[i + 16] << 8) + cis[i + 15],
4364 (cis[i + 18] << 8) + cis[i + 17],
4365 (cis[i + 20] << 8) + cis[i + 19],
4366 (cis[i + 22] << 8) + cis[i + 21],
4367 (cis[i + 24] << 8) + cis[i + 23],
4368 (cis[i + 26] << 8) + cis[i + 25],
4369 (cis[i + 28] << 8) + cis[i + 27],
4370 (cis[i + 30] << 8) + cis[i + 29],
4371 (cis[i + 32] << 8) + cis[i + 31],
4372 (cis[i + 34] << 8) + cis[i + 33],
4373 (cis[i + 36] << 8) + cis[i + 35],
4374 (cis[i + 38] << 8) + cis[i + 37],
4375 (cis[i + 40] << 8) + cis[i + 39],
4376 (cis[i + 42] << 8) + cis[i + 41]);
4377 break;
4378 }
4379
4380 case HNBU_SUBBAND5GVER:
4381 varbuf_append(&b, vstr_subband5gver,
4382 (cis[i + 2] << 8) + cis[i + 1]);
4383 break;
4384
4385 case HNBU_PAPARAMBWVER:
4386 varbuf_append(&b, vstr_paparambwver, cis[i + 1]);
4387 break;
4388
4389 case HNBU_TXBFRPCALS:
4390 /* note: all 5 rpcal parameters are expected to be */
4391 /* inside one tuple record, i.e written with one */
4392 /* wl wrvar cmd as follows: */
4393 /* wl wrvar rpcal2g=0x1211 ... rpcal5gb3=0x0 */
4394 if (tlen != 11 ) { /* sanity check */
4395 BS_ERROR(("srom_parsecis:incorrect length:%d for"
4396 " HNBU_TXBFRPCALS tuple\n",
4397 tlen));
4398 break;
4399 }
4400
4401 varbuf_append(&b, vstr_paparamrpcalvars[0],
4402 (cis[i + 1] + (cis[i + 2] << 8)));
4403 varbuf_append(&b, vstr_paparamrpcalvars[1],
4404 (cis[i + 3] + (cis[i + 4] << 8)));
4405 varbuf_append(&b, vstr_paparamrpcalvars[2],
4406 (cis[i + 5] + (cis[i + 6] << 8)));
4407 varbuf_append(&b, vstr_paparamrpcalvars[3],
4408 (cis[i + 7] + (cis[i + 8] << 8)));
4409 varbuf_append(&b, vstr_paparamrpcalvars[4],
4410 (cis[i + 9] + (cis[i + 10] << 8)));
4411 break;
4412
4413 case HNBU_GPIO_PULL_DOWN:
4414 varbuf_append(&b, vstr_gpdn,
4415 (cis[i + 4] << 24) |
4416 (cis[i + 3] << 16) |
4417 (cis[i + 2] << 8) |
4418 cis[i + 1]);
4419 break;
4420
4421 case HNBU_MACADDR2:
4422 if (!(ETHER_ISNULLADDR(&cis[i+1])) &&
4423 !(ETHER_ISMULTI(&cis[i+1]))) {
4424 bcm_ether_ntoa((struct ether_addr *)&cis[i + 1],
4425 eabuf2);
4426 }
4427 break;
4428 } /* CISTPL_BRCM_HNBU */
4429 break;
4430 } /* switch (tup) */
4431
4432 i += tlen;
4433 } while (tup != CISTPL_END);
4434 }
4435
4436 if (boardnum != -1) {
4437 varbuf_append(&b, vstr_boardnum, boardnum);
4438 }
4439
4440 if (eabuf[0]) {
4441 varbuf_append(&b, vstr_macaddr, eabuf);
4442 }
4443
4444 if (eabuf2[0]) {
4445 varbuf_append(&b, vstr_macaddr2, eabuf2);
4446 }
4447
4448 #ifndef BCM_BOOTLOADER
4449 /* if there is no antenna gain field, set default */
4450 sromrev = (sromrev == 1u) ? (uint8)getintvar(NULL, rstr_sromrev) : sromrev;
4451 if (sromrev <= 10u && getvar(NULL, rstr_ag0) == NULL && ag_init == FALSE) {
4452 varbuf_append(&b, vstr_ag, 0, 0xff);
4453 }
4454 #endif
4455
4456 /* final nullbyte terminator */
4457 ASSERT(b.size >= 1u);
4458 *b.buf++ = '\0';
4459
4460 ASSERT((uint)(b.buf - base) <= var_cis_size);
4461
4462 /* initvars_table() MALLOCs, copies and assigns the MALLOCed buffer to '*vars' */
4463 err = initvars_table(osh, base /* start */, b.buf /* end */, vars, count);
4464
4465 MFREE(osh, base, var_cis_size);
4466 return err;
4467 }
4468 #endif /* !defined(BCMDONGLEHOST) */
4469
4470 /**
4471 * In chips with chipcommon rev 32 and later, the srom is in chipcommon,
4472 * not in the bus cores.
4473 */
4474 static uint16
4475 srom_cc_cmd(si_t *sih, osl_t *osh, volatile void *ccregs, uint32 cmd, uint wordoff, uint16 data)
4476 {
4477 chipcregs_t *cc = ccregs;
4478 uint wait_cnt = 1000;
4479 uint32 byteoff = 0, sprom_size = 0;
4480
4481 BCM_REFERENCE(sih);
4482 byteoff = wordoff * 2;
4483
4484 sprom_size = R_REG(osh, &cc->sromcontrol);
4485 sprom_size = (sprom_size & SROM_SIZE_MASK) >> SROM_SIZE_SHFT_MASK;
4486 if (sprom_size == SROM_SIZE_2K)
4487 sprom_size = 2048;
4488 else if (sprom_size == SROM_SIZE_512)
4489 sprom_size = 512;
4490 else if (sprom_size == SROM_SIZE_128)
4491 sprom_size = 128;
4492 if (byteoff >= sprom_size)
4493 return 0xffff;
4494
4495 if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
4496 if (sih->ccrev >= 59)
4497 W_REG(osh, &cc->chipcontrol, (byteoff & SROM16K_BANK_SEL_MASK) >>
4498 SROM16K_BANK_SHFT_MASK);
4499 W_REG(osh, &cc->sromaddress, (byteoff & SROM16K_ADDR_SEL_MASK));
4500 if (cmd == SRC_OP_WRITE)
4501 W_REG(osh, &cc->sromdata, data);
4502 }
4503
4504 W_REG(osh, &cc->sromcontrol, SRC_START | cmd);
4505
4506 while (wait_cnt--) {
4507 if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0)
4508 break;
4509 }
4510
4511 if (!wait_cnt) {
4512 BS_ERROR(("srom_cc_cmd: Command 0x%x timed out\n", cmd));
4513 return 0xffff;
4514 }
4515 if (cmd == SRC_OP_READ)
4516 return (uint16)R_REG(osh, &cc->sromdata);
4517 else
4518 return 0xffff;
4519 }
4520
4521 #define CC_SROM_SHADOW_WSIZE 512 /* 0x800 - 0xC00 */
4522
4523 /**
4524 * Read in and validate sprom.
4525 * Return 0 on success, nonzero on error.
4526 * Returns success on an SPROM containing only ones, unclear if this is intended.
4527 */
4528 static int
4529 sprom_read_pci(osl_t *osh, si_t *sih, volatile uint16 *sprom, uint wordoff,
4530 uint16 *buf, uint nwords, bool check_crc)
4531 {
4532 int err = 0;
4533 uint i;
4534 volatile void *ccregs = NULL;
4535 chipcregs_t *cc = NULL;
4536 uint32 ccval = 0, sprom_size = 0;
4537 uint32 sprom_num_words;
4538
4539 if (BCM43602_CHIP(sih->chip) ||
4540 (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
4541 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
4542 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
4543 /* save current control setting */
4544 ccval = si_chipcontrl_read(sih);
4545 }
4546
4547 if (BCM43602_CHIP(sih->chip) ||
4548 (((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
4549 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
4550 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
4551 (CHIPREV(sih->chiprev) <= 2))) {
4552 si_chipcontrl_srom4360(sih, TRUE);
4553 }
4554
4555 if (FALSE) {
4556 si_srom_clk_set(sih); /* corrects srom clock frequency */
4557 }
4558
4559 ccregs = ((volatile uint8 *)sprom - CC_SROM_OTP);
4560 cc = ccregs;
4561 sprom_size = R_REG(osh, &cc->sromcontrol);
4562 sprom_size = (sprom_size & SROM_SIZE_MASK) >> SROM_SIZE_SHFT_MASK;
4563 if (sprom_size == SROM_SIZE_2K)
4564 sprom_size = 2048;
4565 else if (sprom_size == SROM_SIZE_512)
4566 sprom_size = 512;
4567 else if (sprom_size == SROM_SIZE_128)
4568 sprom_size = 128;
4569 sprom_num_words = sprom_size/2;
4570
4571 /* read the sprom */
4572 for (i = 0; i < nwords; i++) {
4573 if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
4574 /* use indirect since direct is too slow on QT */
4575 if ((sih->cccaps & CC_CAP_SROM) == 0) {
4576 err = 1;
4577 goto error;
4578 }
4579
4580 /* hack to get ccregs */
4581 ccregs = (volatile void *)((volatile uint8 *)sprom - CC_SROM_OTP);
4582 buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0);
4583
4584 } else {
4585 /* Because of the slow emulation we need to read twice in QT */
4586 if (ISSIM_ENAB(sih)) {
4587 buf[i] = R_REG(osh, &sprom[wordoff + i]);
4588 }
4589
4590 if ((wordoff + i) >= sprom_num_words) {
4591 buf[i] = 0xffff;
4592 } else if ((wordoff + i) >= CC_SROM_SHADOW_WSIZE) {
4593 /* Srom shadow region in chipcommon is only 512 words
4594 * use indirect access for Srom beyond 512 words
4595 */
4596 buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0);
4597 } else {
4598 buf[i] = R_REG(osh, &sprom[wordoff + i]);
4599 }
4600 }
4601 if (i == SROM13_SIGN) {
4602 if ((buf[SROM13_SIGN] != SROM13_SIGNATURE) && (nwords == SROM13_WORDS)) {
4603 err = 1;
4604 goto error;
4605 }
4606 }
4607 }
4608
4609 /* bypass crc checking for simulation to allow srom hack */
4610 if (ISSIM_ENAB(sih)) {
4611 goto error;
4612 }
4613
4614 if (check_crc) {
4615
4616 if (buf[0] == 0xffff) {
4617 /* The hardware thinks that an srom that starts with 0xffff
4618 * is blank, regardless of the rest of the content, so declare
4619 * it bad.
4620 */
4621 BS_ERROR(("sprom_read_pci: buf[0] = 0x%x, returning bad-crc\n", buf[0]));
4622 err = 1;
4623 goto error;
4624 }
4625
4626 /* fixup the endianness so crc8 will pass */
4627 htol16_buf(buf, nwords * 2);
4628 if (hndcrc8((uint8 *)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
4629 /* DBG only pci always read srom4 first, then srom8/9 */
4630 /* BS_ERROR(("sprom_read_pci: bad crc\n")); */
4631 err = 1;
4632 }
4633 /* now correct the endianness of the byte array */
4634 ltoh16_buf(buf, nwords * 2);
4635 }
4636
4637 error:
4638 if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
4639 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
4640 (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
4641 BCM43602_CHIP(sih->chip)) {
4642 /* Restore config after reading SROM */
4643 si_chipcontrl_restore(sih, ccval);
4644 }
4645
4646 return err;
4647 }
4648
4649 #if !defined(BCMDONGLEHOST)
4650 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
4651 static int
4652 BCMSROMATTACHFN(otp_read_pci)(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz)
4653 {
4654 uint8 *otp;
4655 uint sz = OTP_SZ_MAX/2; /* size in words */
4656 int err = 0;
4657
4658 if (bufsz > OTP_SZ_MAX) {
4659 return BCME_ERROR;
4660 }
4661
4662 /* freed in same function */
4663 if ((otp = MALLOC_NOPERSIST(osh, OTP_SZ_MAX)) == NULL) {
4664 return BCME_ERROR;
4665 }
4666
4667 bzero(otp, OTP_SZ_MAX);
4668
4669 err = otp_read_region(sih, OTP_HW_RGN, (uint16 *)otp, &sz);
4670
4671 if (err) {
4672 MFREE(osh, otp, OTP_SZ_MAX);
4673 return err;
4674 }
4675
4676 bcopy(otp, buf, bufsz);
4677
4678 /* Check CRC */
4679 if (((uint16 *)otp)[0] == 0xffff) {
4680 /* The hardware thinks that an srom that starts with 0xffff
4681 * is blank, regardless of the rest of the content, so declare
4682 * it bad.
4683 */
4684 BS_ERROR(("otp_read_pci: otp[0] = 0x%x, returning bad-crc\n",
4685 ((uint16 *)otp)[0]));
4686 MFREE(osh, otp, OTP_SZ_MAX);
4687 return 1;
4688 }
4689
4690 /* fixup the endianness so crc8 will pass */
4691 htol16_buf(otp, OTP_SZ_MAX);
4692 if (hndcrc8(otp, SROM4_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE &&
4693 hndcrc8(otp, SROM10_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE &&
4694 hndcrc8(otp, SROM11_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE &&
4695 hndcrc8(otp, SROM12_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE &&
4696 hndcrc8(otp, SROM13_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
4697 BS_ERROR(("otp_read_pci: bad crc\n"));
4698 err = 1;
4699 }
4700
4701 MFREE(osh, otp, OTP_SZ_MAX);
4702
4703 return err;
4704 }
4705 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
4706 #endif /* !defined(BCMDONGLEHOST) */
4707
4708 int
4709 srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write)
4710 {
4711 #if defined(WLTEST) || defined(BCMDBG)
4712 int err = 0, crc = 0;
4713 #if !defined(BCMDONGLEHOST)
4714 uint8 *buf8;
4715
4716 /* Check nbytes is not odd or too big */
4717 if ((nbytes & 1) || (nbytes > SROM_MAX))
4718 return 1;
4719
4720 /* block invalid buffer size */
4721 if (nbytes < SROM4_WORDS * 2)
4722 return BCME_BUFTOOSHORT;
4723 else if (nbytes > SROM13_WORDS * 2)
4724 return BCME_BUFTOOLONG;
4725
4726 /* Verify signatures */
4727 if (!((buf16[SROM4_SIGN] == SROM4_SIGNATURE) ||
4728 (buf16[SROM8_SIGN] == SROM4_SIGNATURE) ||
4729 (buf16[SROM10_SIGN] == SROM4_SIGNATURE) ||
4730 (buf16[SROM11_SIGN] == SROM11_SIGNATURE)||
4731 (buf16[SROM12_SIGN] == SROM12_SIGNATURE)||
4732 (buf16[SROM13_SIGN] == SROM13_SIGNATURE))) {
4733 BS_ERROR(("srom_otp_write_region_crc: wrong signature SROM4_SIGN %x SROM8_SIGN %x"
4734 " SROM10_SIGN %x\n",
4735 buf16[SROM4_SIGN], buf16[SROM8_SIGN], buf16[SROM10_SIGN]));
4736 return BCME_ERROR;
4737 }
4738
4739 /* Check CRC */
4740 if (buf16[0] == 0xffff) {
4741 /* The hardware thinks that an srom that starts with 0xffff
4742 * is blank, regardless of the rest of the content, so declare
4743 * it bad.
4744 */
4745 BS_ERROR(("srom_otp_write_region_crc: invalid buf16[0] = 0x%x\n", buf16[0]));
4746 goto out;
4747 }
4748
4749 buf8 = (uint8*)buf16;
4750 /* fixup the endianness and then calculate crc */
4751 htol16_buf(buf8, nbytes);
4752 crc = ~hndcrc8(buf8, nbytes - 1, CRC8_INIT_VALUE);
4753 /* now correct the endianness of the byte array */
4754 ltoh16_buf(buf8, nbytes);
4755
4756 if (nbytes == SROM11_WORDS * 2)
4757 buf16[SROM11_CRCREV] = (crc << 8) | (buf16[SROM11_CRCREV] & 0xff);
4758 else if (nbytes == SROM12_WORDS * 2)
4759 buf16[SROM12_CRCREV] = (crc << 8) | (buf16[SROM12_CRCREV] & 0xff);
4760 else if (nbytes == SROM13_WORDS * 2)
4761 buf16[SROM13_CRCREV] = (crc << 8) | (buf16[SROM13_CRCREV] & 0xff);
4762 else if (nbytes == SROM10_WORDS * 2)
4763 buf16[SROM10_CRCREV] = (crc << 8) | (buf16[SROM10_CRCREV] & 0xff);
4764 else
4765 buf16[SROM4_CRCREV] = (crc << 8) | (buf16[SROM4_CRCREV] & 0xff);
4766
4767 #ifdef BCMNVRAMW
4768 /* Write the CRC back */
4769 if (write)
4770 err = otp_write_region(sih, OTP_HW_RGN, buf16, nbytes/2, 0);
4771 #endif /* BCMNVRAMW */
4772
4773 out:
4774 #endif /* !defined(BCMDONGLEHOST) */
4775 return write ? err : crc;
4776 #else
4777 BCM_REFERENCE(sih);
4778 BCM_REFERENCE(nbytes);
4779 BCM_REFERENCE(buf16);
4780 BCM_REFERENCE(write);
4781 return 0;
4782 #endif /* WLTEST || BCMDBG */
4783
4784 }
4785
4786 #if !defined(BCMDONGLEHOST)
4787 int
4788 BCMATTACHFN(dbushost_initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len)
4789 {
4790 return initvars_flash(sih, osh, base, len);
4791 }
4792
4793 /**
4794 * Find variables with <devpath> from flash. 'base' points to the beginning
4795 * of the table upon enter and to the end of the table upon exit when success.
4796 * Return 0 on success, nonzero on error.
4797 */
4798 static int
4799 BCMATTACHFN(initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len)
4800 {
4801 char *vp = *base;
4802 char *flash;
4803 int err;
4804 char *s;
4805 uint l, dl, copy_len;
4806 char devpath[SI_DEVPATH_BUFSZ], devpath_pcie[SI_DEVPATH_BUFSZ];
4807 char coded_name[SI_DEVPATH_BUFSZ] = {0};
4808 int path_len, coded_len, devid_len, pcie_path_len;
4809
4810 /* allocate memory and read in flash */
4811 /* freed in same function */
4812 if (!(flash = MALLOC_NOPERSIST(osh, MAX_NVRAM_SPACE)))
4813 return BCME_NOMEM;
4814 if ((err = nvram_getall(flash, MAX_NVRAM_SPACE)))
4815 goto exit;
4816
4817 /* create legacy devpath prefix */
4818 si_devpath(sih, devpath, sizeof(devpath));
4819 path_len = strlen(devpath);
4820
4821 if (BUSTYPE(sih->bustype) == PCI_BUS) {
4822 si_devpath_pcie(sih, devpath_pcie, sizeof(devpath_pcie));
4823 pcie_path_len = strlen(devpath_pcie);
4824 } else
4825 pcie_path_len = 0;
4826
4827 /* create coded devpath prefix */
4828 si_coded_devpathvar(sih, coded_name, sizeof(coded_name), "devid");
4829
4830 /* coded_name now is 'xx:devid, eat ending 'devid' */
4831 /* to be 'xx:' */
4832 devid_len = strlen("devid");
4833 coded_len = strlen(coded_name);
4834 if (coded_len > devid_len) {
4835 coded_name[coded_len - devid_len] = '\0';
4836 coded_len -= devid_len;
4837 }
4838 else
4839 coded_len = 0;
4840
4841 /* grab vars with the <devpath> prefix or <coded_name> previx in name */
4842 for (s = flash; s && *s; s += l + 1) {
4843 l = strlen(s);
4844
4845 /* skip non-matching variable */
4846 if (strncmp(s, devpath, path_len) == 0)
4847 dl = path_len;
4848 else if (pcie_path_len && strncmp(s, devpath_pcie, pcie_path_len) == 0)
4849 dl = pcie_path_len;
4850 else if (coded_len && strncmp(s, coded_name, coded_len) == 0)
4851 dl = coded_len;
4852 else
4853 continue;
4854
4855 /* is there enough room to copy? */
4856 copy_len = l - dl + 1;
4857 if (len < copy_len) {
4858 err = BCME_BUFTOOSHORT;
4859 goto exit;
4860 }
4861
4862 /* no prefix, just the name=value */
4863 strlcpy(vp, &s[dl], copy_len);
4864 vp += copy_len;
4865 len -= copy_len;
4866 }
4867
4868 /* add null string as terminator */
4869 if (len < 1) {
4870 err = BCME_BUFTOOSHORT;
4871 goto exit;
4872 }
4873 *vp++ = '\0';
4874
4875 *base = vp;
4876
4877 exit:
4878 MFREE(osh, flash, MAX_NVRAM_SPACE);
4879 return err;
4880 }
4881 #endif /* !defined(BCMDONGLEHOST) */
4882
4883 #if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) && \
4884 !defined(BCMPCIEDEV_ENABLED)
4885 #if !defined(BCMDONGLEHOST)
4886 /**
4887 * Initialize nonvolatile variable table from flash.
4888 * Return 0 on success, nonzero on error.
4889 */
4890 /* no needs to load the nvram variables from the flash for dongles.
4891 * These variables are mainly for supporting SROM-less devices although
4892 * we can use the same machenism to support configuration of multiple
4893 * cores of the same type.
4894 */
4895 static int
4896 BCMATTACHFN(initvars_flash_si)(si_t *sih, char **vars, uint *count)
4897 {
4898 osl_t *osh = si_osh(sih);
4899 char *vp, *base;
4900 int err;
4901
4902 ASSERT(vars != NULL);
4903 ASSERT(count != NULL);
4904
4905 /* freed in same function */
4906 base = vp = MALLOC_NOPERSIST(osh, MAXSZ_NVRAM_VARS);
4907 ASSERT(vp != NULL);
4908 if (!vp)
4909 return BCME_NOMEM;
4910
4911 if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)) == 0)
4912 err = initvars_table(osh, base, vp, vars, count);
4913
4914 MFREE(osh, base, MAXSZ_NVRAM_VARS);
4915
4916 return err;
4917 }
4918 #endif /* !defined(BCMDONGLEHOST) */
4919 #endif /* !BCMUSBDEV && !BCMSDIODEV */
4920
4921 #if !defined(BCMDONGLEHOST)
4922
4923 /** returns position of rightmost bit that was set in caller supplied mask */
4924 static uint
4925 mask_shift(uint16 mask)
4926 {
4927 uint i;
4928 for (i = 0; i < (sizeof(mask) << 3); i ++) {
4929 if (mask & (1 << i))
4930 return i;
4931 }
4932 ASSERT(mask);
4933 return 0;
4934 }
4935
4936 static uint
4937 mask_width(uint16 mask)
4938 {
4939 int i;
4940 for (i = (sizeof(mask) << 3) - 1; i >= 0; i --) {
4941 if (mask & (1 << i))
4942 return (uint)(i - mask_shift(mask) + 1);
4943 }
4944 ASSERT(mask);
4945 return 0;
4946 }
4947
4948 #ifdef BCMASSERT_SUPPORT
4949 static bool
4950 mask_valid(uint16 mask)
4951 {
4952 uint shift = mask_shift(mask);
4953 uint width = mask_width(mask);
4954 return mask == ((~0 << shift) & ~(~0 << (shift + width)));
4955 }
4956 #endif
4957 #ifdef NVSRCX
4958 void
4959 srom_set_sromvars(char *vars)
4960 {
4961 if (sromh)
4962 sromh->_srom_vars = vars;
4963 }
4964 char *
4965 srom_get_sromvars()
4966 {
4967 if (sromh)
4968 return sromh->_srom_vars;
4969 else
4970 return NULL;
4971 }
4972
4973 srom_info_t *
4974 srom_info_init(osl_t *osh)
4975 {
4976 sromh = (srom_info_t *) MALLOC_NOPERSIST(osh, sizeof(srom_info_t));
4977 if (!sromh)
4978 return NULL;
4979 sromh->_srom_vars = NULL;
4980 sromh->is_caldata_prsnt = FALSE;
4981 return sromh;
4982 }
4983 #endif /* NVSRCX */
4984 /**
4985 * Parses caller supplied SROM contents into name=value pairs. Global array pci_sromvars[] contains
4986 * the link between a word offset in SROM and the corresponding NVRAM variable name.'srom' points to
4987 * the SROM word array. 'off' specifies the offset of the first word 'srom' points to, which should
4988 * be either 0 or SROM3_SWRG_OFF (full SROM or software region).
4989 */
4990 static void
4991 BCMATTACHFN(_initvars_srom_pci)(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b)
4992 {
4993 uint16 w;
4994 uint32 val;
4995 const sromvar_t *srv;
4996 uint width;
4997 uint flags;
4998 uint32 sr = (1 << sromrev);
4999 bool in_array = FALSE;
5000 static char array_temp[256];
5001 uint array_curr = 0;
5002 const char* array_name = NULL;
5003
5004 varbuf_append(b, "sromrev=%d", sromrev);
5005 #if !defined(SROM15_MEMOPT) && !defined(SROM17_MEMOPT)
5006 if (sromrev == 15) {
5007 srv = pci_srom15vars;
5008 } else if (sromrev == 16) {
5009 srv = pci_srom16vars;
5010 } else if (sromrev == 17) {
5011 srv = pci_srom17vars;
5012 } else if (sromrev == 18) {
5013 srv = pci_srom18vars;
5014 } else {
5015 srv = pci_sromvars;
5016 }
5017 #else
5018 #if defined(SROM15_MEMOPT)
5019 srv = pci_srom15vars;
5020 #endif /* defined(SROM15_MEMOPT) */
5021 #if defined(SROM17_MEMOPT)
5022 srv = pci_srom17vars;
5023 #endif /* defined(SROM17_MEMOPT) */
5024 #endif /* !defined(SROM15_MEMOPT) && !defined(SROM17_MEMOPT) */
5025
5026 for (; srv->name != NULL; srv ++) {
5027 const char *name;
5028 static bool in_array2 = FALSE;
5029 static char array_temp2[256];
5030 static uint array_curr2 = 0;
5031 static const char* array_name2 = NULL;
5032
5033 if ((srv->revmask & sr) == 0)
5034 continue;
5035
5036 if (srv->off < off)
5037 continue;
5038
5039 flags = srv->flags;
5040 name = srv->name;
5041
5042 /* This entry is for mfgc only. Don't generate param for it, */
5043 if (flags & SRFL_NOVAR)
5044 continue;
5045
5046 if (flags & SRFL_ETHADDR) {
5047 char eabuf[ETHER_ADDR_STR_LEN];
5048 struct ether_addr ea;
5049
5050 ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff;
5051 ea.octet[1] = srom[srv->off - off] & 0xff;
5052 ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
5053 ea.octet[3] = srom[srv->off + 1 - off] & 0xff;
5054 ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
5055 ea.octet[5] = srom[srv->off + 2 - off] & 0xff;
5056 bcm_ether_ntoa(&ea, eabuf);
5057
5058 varbuf_append(b, "%s=%s", name, eabuf);
5059 } else {
5060 ASSERT(mask_valid(srv->mask));
5061 ASSERT(mask_width(srv->mask));
5062
5063 /* Start of an array */
5064 if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array2) {
5065 array_curr2 = 0;
5066 array_name2 = (const char*)srv->name;
5067 bzero((void*)array_temp2, sizeof(array_temp2));
5068 in_array2 = TRUE;
5069 }
5070
5071 w = srom[srv->off - off];
5072 val = (w & srv->mask) >> mask_shift(srv->mask);
5073 width = mask_width(srv->mask);
5074
5075 while (srv->flags & SRFL_MORE) {
5076 srv ++;
5077 ASSERT(srv->name != NULL);
5078
5079 if (srv->off == 0 || srv->off < off)
5080 continue;
5081
5082 ASSERT(mask_valid(srv->mask));
5083 ASSERT(mask_width(srv->mask));
5084
5085 w = srom[srv->off - off];
5086 val += ((w & srv->mask) >> mask_shift(srv->mask)) << width;
5087 width += mask_width(srv->mask);
5088 }
5089
5090 if ((flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1))
5091 continue;
5092
5093 /* Array support starts in sromrev 10. Skip arrays for sromrev <= 9 */
5094 if (sromrev <= 9 && srv->flags & SRFL_ARRAY) {
5095 while (srv->flags & SRFL_ARRAY)
5096 srv ++;
5097 srv ++;
5098 }
5099
5100 if (in_array2) {
5101 int ret;
5102
5103 if (flags & SRFL_PRHEX) {
5104 ret = snprintf(array_temp2 + array_curr2,
5105 sizeof(array_temp2) - array_curr2, "0x%x,", val);
5106 } else if ((flags & SRFL_PRSIGN) &&
5107 (val & (1 << (width - 1)))) {
5108 ret = snprintf(array_temp2 + array_curr2,
5109 sizeof(array_temp2) - array_curr2, "%d,",
5110 (int)(val | (~0 << width)));
5111 } else {
5112 ret = snprintf(array_temp2 + array_curr2,
5113 sizeof(array_temp2) - array_curr2, "%u,", val);
5114 }
5115
5116 if (ret > 0) {
5117 array_curr2 += ret;
5118 } else {
5119 BS_ERROR(("_initvars_srom_pci: array %s parsing error."
5120 " buffer too short.\n",
5121 array_name2));
5122 ASSERT(0);
5123
5124 /* buffer too small, skip this param */
5125 while (srv->flags & SRFL_ARRAY)
5126 srv ++;
5127 srv ++;
5128 in_array2 = FALSE;
5129 continue;
5130 }
5131
5132 if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */
5133 /* Remove the last ',' */
5134 array_temp2[array_curr2-1] = '\0';
5135 in_array2 = FALSE;
5136 varbuf_append(b, "%s=%s", array_name2, array_temp2);
5137 }
5138 } else if (flags & SRFL_CCODE) {
5139 if (val == 0)
5140 varbuf_append(b, "ccode=");
5141 else
5142 varbuf_append(b, "ccode=%c%c", (val >> 8), (val & 0xff));
5143 } else if (flags & SRFL_PRHEX) {
5144 varbuf_append(b, "%s=0x%x", name, val);
5145 } else if ((flags & SRFL_PRSIGN) && (val & (1 << (width - 1)))) {
5146 varbuf_append(b, "%s=%d", name, (int)(val | (~0 << width)));
5147 } else {
5148 varbuf_append(b, "%s=%u", name, val);
5149 }
5150 }
5151 }
5152
5153 if ((sromrev >= 4) && (sromrev != 16) && (sromrev != 18)) {
5154 /* Do per-path variables */
5155 uint p, pb, psz, path_num;
5156
5157 if ((sromrev == 17) || (sromrev == 15)) {
5158 pb = psz = 0;
5159 path_num = 0;
5160 if (sromh)
5161 sromh->is_caldata_prsnt = TRUE;
5162 } else if (sromrev >= 13) {
5163 pb = SROM13_PATH0;
5164 psz = SROM13_PATH1 - SROM13_PATH0;
5165 path_num = MAX_PATH_SROM_13;
5166 } else if (sromrev >= 12) {
5167 pb = SROM12_PATH0;
5168 psz = SROM12_PATH1 - SROM12_PATH0;
5169 path_num = MAX_PATH_SROM_12;
5170 } else if (sromrev >= 11) {
5171 pb = SROM11_PATH0;
5172 psz = SROM11_PATH1 - SROM11_PATH0;
5173 path_num = MAX_PATH_SROM_11;
5174 } else if (sromrev >= 8) {
5175 pb = SROM8_PATH0;
5176 psz = SROM8_PATH1 - SROM8_PATH0;
5177 path_num = MAX_PATH_SROM;
5178 } else {
5179 pb = SROM4_PATH0;
5180 psz = SROM4_PATH1 - SROM4_PATH0;
5181 path_num = MAX_PATH_SROM;
5182 }
5183
5184 for (p = 0; p < path_num; p++) {
5185 for (srv = perpath_pci_sromvars; srv->name != NULL; srv ++) {
5186
5187 if ((srv->revmask & sr) == 0)
5188 continue;
5189
5190 if (pb + srv->off < off)
5191 continue;
5192
5193 /* This entry is for mfgc only. Don't generate param for it, */
5194 if (srv->flags & SRFL_NOVAR)
5195 continue;
5196
5197 /* Start of an array */
5198 if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) {
5199 array_curr = 0;
5200 array_name = (const char*)srv->name;
5201 bzero((void*)array_temp, sizeof(array_temp));
5202 in_array = TRUE;
5203 }
5204
5205 w = srom[pb + srv->off - off];
5206
5207 ASSERT(mask_valid(srv->mask));
5208 val = (w & srv->mask) >> mask_shift(srv->mask);
5209 width = mask_width(srv->mask);
5210
5211 flags = srv->flags;
5212
5213 /* Cheating: no per-path var is more than 1 word */
5214
5215 if ((srv->flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1))
5216 continue;
5217
5218 if (in_array) {
5219 int ret;
5220
5221 if (flags & SRFL_PRHEX) {
5222 ret = snprintf(array_temp + array_curr,
5223 sizeof(array_temp) - array_curr, "0x%x,", val);
5224 } else if ((flags & SRFL_PRSIGN) &&
5225 (val & (1 << (width - 1)))) {
5226 ret = snprintf(array_temp + array_curr,
5227 sizeof(array_temp) - array_curr, "%d,",
5228 (int)(val | (~0 << width)));
5229 } else {
5230 ret = snprintf(array_temp + array_curr,
5231 sizeof(array_temp) - array_curr, "%u,", val);
5232 }
5233
5234 if (ret > 0) {
5235 array_curr += ret;
5236 } else {
5237 BS_ERROR(
5238 ("_initvars_srom_pci: array %s parsing error."
5239 " buffer too short.\n",
5240 array_name));
5241 ASSERT(0);
5242
5243 /* buffer too small, skip this param */
5244 while (srv->flags & SRFL_ARRAY)
5245 srv ++;
5246 srv ++;
5247 in_array = FALSE;
5248 continue;
5249 }
5250
5251 if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */
5252 /* Remove the last ',' */
5253 array_temp[array_curr-1] = '\0';
5254 in_array = FALSE;
5255 varbuf_append(b, "%s%d=%s",
5256 array_name, p, array_temp);
5257 }
5258 } else if (srv->flags & SRFL_PRHEX)
5259 varbuf_append(b, "%s%d=0x%x", srv->name, p, val);
5260 else
5261 varbuf_append(b, "%s%d=%d", srv->name, p, val);
5262 }
5263 if (sromrev >= 13 && (p == (MAX_PATH_SROM_13 - 2))) {
5264 psz = SROM13_PATH3 - SROM13_PATH2;
5265 }
5266 pb += psz;
5267 }
5268 } /* per path variables */
5269 } /* _initvars_srom_pci */
5270
5271 int
5272 BCMATTACHFN(get_srom_pci_caldata_size)(uint32 sromrev)
5273 {
5274 uint32 caldata_size;
5275
5276 switch (sromrev) {
5277 case 15:
5278 caldata_size = (SROM15_CALDATA_WORDS * 2);
5279 break;
5280 case 17:
5281 caldata_size = (SROM17_CALDATA_WORDS * 2);
5282 break;
5283 default:
5284 caldata_size = 0;
5285 break;
5286 }
5287 return caldata_size;
5288 }
5289
5290 uint32
5291 BCMATTACHFN(get_srom_size)(uint32 sromrev)
5292 {
5293 uint32 size;
5294
5295 switch (sromrev) {
5296 case 15:
5297 size = (SROM15_WORDS * 2);
5298 break;
5299 case 17:
5300 size = (SROM17_WORDS * 2);
5301 break;
5302 default:
5303 size = 0;
5304 break;
5305 }
5306 return size;
5307 }
5308 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5309
5310 int
5311 BCMATTACHFN(_initvars_srom_pci_caldata)(si_t *sih, uint16 *srom, uint32 sromrev)
5312 {
5313 int err = BCME_ERROR;
5314
5315 if (sromh && (!sromh->is_caldata_prsnt)) {
5316 return err;
5317 }
5318
5319 if (si_is_sprom_available(sih)) {
5320 uint32 caldata_size;
5321
5322 caldata_size = get_srom_pci_caldata_size(sromrev);
5323 memcpy(srom, caldata_array, caldata_size);
5324 err = BCME_OK;
5325 }
5326 return err;
5327 }
5328 #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */
5329 /**
5330 * Initialize nonvolatile variable table from sprom, or OTP when SPROM is not available, or
5331 * optionally a set of 'defaultsromvars' (compiled-in) variables when both OTP and SPROM bear no
5332 * contents.
5333 *
5334 * On success, a buffer containing var/val pairs is allocated and returned in params vars and count.
5335 *
5336 * Return 0 on success, nonzero on error.
5337 */
5338 static int
5339 BCMATTACHFN(initvars_srom_pci)(si_t *sih, volatile void *curmap, char **vars, uint *count)
5340 {
5341 uint16 *srom;
5342 volatile uint16 *sromwindow;
5343 uint8 sromrev = 0;
5344 uint32 sr;
5345 varbuf_t b;
5346 char *vp, *base = NULL;
5347 osl_t *osh = si_osh(sih);
5348 bool flash = FALSE;
5349 int err = 0;
5350 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5351 uint16 cal_wordoffset;
5352 #endif
5353
5354 /*
5355 * Apply CRC over SROM content regardless SROM is present or not, and use variable
5356 * <devpath>sromrev's existance in flash to decide if we should return an error when CRC
5357 * fails or read SROM variables from flash.
5358 */
5359
5360 /* freed in same function */
5361 srom = MALLOC_NOPERSIST(osh, SROM_MAX);
5362 ASSERT(srom != NULL);
5363 if (!srom)
5364 return -2;
5365
5366 sromwindow = (volatile uint16 *)srom_offset(sih, curmap);
5367 if (si_is_sprom_available(sih)) {
5368 err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM_SIGN_MINWORDS + 1, FALSE);
5369 if (err == 0) {
5370 if (srom[SROM18_SIGN] == SROM18_SIGNATURE) {
5371 err = sprom_read_pci(osh, sih, sromwindow,
5372 0, srom, SROM18_WORDS, TRUE);
5373 sromrev = srom[SROM18_CRCREV] & 0xff;
5374 } else if (srom[SROM17_SIGN] == SROM17_SIGNATURE) {
5375 err = sprom_read_pci(osh, sih, sromwindow,
5376 0, srom, SROM17_WORDS, TRUE);
5377 sromrev = srom[SROM17_CRCREV] & 0xff;
5378 } else if (srom[SROM16_SIGN] == SROM16_SIGNATURE) {
5379 err = sprom_read_pci(osh, sih, sromwindow,
5380 0, srom, SROM16_WORDS, TRUE);
5381 sromrev = srom[SROM16_CRCREV] & 0xff;
5382 } else if (srom[SROM15_SIGN] == SROM15_SIGNATURE) { /* srom 15 */
5383 err = sprom_read_pci(osh, sih, sromwindow,
5384 0, srom, SROM15_WORDS, TRUE);
5385 sromrev = srom[SROM15_CRCREV] & 0xff;
5386 } else if (srom[SROM11_SIGN] == SROM13_SIGNATURE) {
5387 err = sprom_read_pci(osh, sih, sromwindow,
5388 0, srom, SROM13_WORDS, TRUE);
5389 sromrev = srom[SROM13_CRCREV] & 0xff;
5390 } else if (srom[SROM11_SIGN] == SROM12_SIGNATURE) {
5391 err = sprom_read_pci(osh, sih, sromwindow,
5392 0, srom, SROM12_WORDS, TRUE);
5393 sromrev = srom[SROM12_CRCREV] & 0xff;
5394 } else if (srom[SROM11_SIGN] == SROM11_SIGNATURE) {
5395 err = sprom_read_pci(osh, sih, sromwindow,
5396 0, srom, SROM11_WORDS, TRUE);
5397 sromrev = srom[SROM11_CRCREV] & 0xff;
5398 } else if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || /* srom 4 */
5399 (srom[SROM8_SIGN] == SROM4_SIGNATURE)) { /* srom 8,9 */
5400 err = sprom_read_pci(osh, sih, sromwindow,
5401 0, srom, SROM4_WORDS, TRUE);
5402 sromrev = srom[SROM4_CRCREV] & 0xff;
5403 } else {
5404 err = sprom_read_pci(osh, sih, sromwindow, 0,
5405 srom, SROM_WORDS, TRUE);
5406 if (err == 0) {
5407 /* srom is good and is rev < 4 */
5408 /* top word of sprom contains version and crc8 */
5409 sromrev = srom[SROM_CRCREV] & 0xff;
5410 /* bcm4401 sroms misprogrammed */
5411 if (sromrev == 0x10)
5412 sromrev = 1;
5413 }
5414 }
5415 if (err)
5416 BS_ERROR(("srom read failed\n"));
5417 }
5418 else
5419 BS_ERROR(("srom read failed\n"));
5420 }
5421
5422 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
5423 /* Use OTP if SPROM not available */
5424 else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) {
5425 /* OTP only contain SROM rev8/rev9/rev10/Rev11 for now */
5426
5427 if (srom[SROM13_SIGN] == SROM13_SIGNATURE)
5428 sromrev = srom[SROM13_CRCREV] & 0xff;
5429 else if (srom[SROM12_SIGN] == SROM12_SIGNATURE)
5430 sromrev = srom[SROM12_CRCREV] & 0xff;
5431 else if (srom[SROM11_SIGN] == SROM11_SIGNATURE)
5432 sromrev = srom[SROM11_CRCREV] & 0xff;
5433 else if (srom[SROM10_SIGN] == SROM10_SIGNATURE)
5434 sromrev = srom[SROM10_CRCREV] & 0xff;
5435 else
5436 sromrev = srom[SROM4_CRCREV] & 0xff;
5437 }
5438 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
5439 else {
5440 err = 1;
5441 BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
5442 }
5443
5444 BS_ERROR(("srom rev:%d\n", sromrev));
5445
5446 /* We want internal/wltest driver to come up with default sromvars so we can
5447 * program a blank SPROM/OTP.
5448 */
5449 if (err || sromrev == 0) {
5450 char *value;
5451 #if defined(BCMHOSTVARS)
5452 uint32 val;
5453 #endif
5454
5455 if ((value = si_getdevpathvar(sih, "sromrev"))) {
5456 sromrev = (uint8)bcm_strtoul(value, NULL, 0);
5457 flash = TRUE;
5458 goto varscont;
5459 }
5460
5461 BS_ERROR(("initvars_srom_pci, SROM CRC Error\n"));
5462
5463 #if !defined(DONGLEBUILD) || defined(BCMPCIEDEV_SROM_FORMAT)
5464 /* NIC build or PCIe FD using SROM format shouldn't load driver
5465 * default when external nvram exists.
5466 */
5467 if ((value = getvar(NULL, "sromrev"))) {
5468 BS_ERROR(("initvars_srom_pci, Using external nvram\n"));
5469 err = 0;
5470 goto errout;
5471 }
5472 #endif /* !DONGLEBUILD || BCMPCIEDEV_SROM_FORMAT */
5473
5474 #if defined(BCMHOSTVARS)
5475 /*
5476 * CRC failed on srom, so if the device is using OTP
5477 * and if OTP is not programmed use the default variables.
5478 * for 4311 A1 there is no signature to indicate that OTP is
5479 * programmed, so can't really verify the OTP is unprogrammed
5480 * or a bad OTP.
5481 */
5482 val = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
5483 if ((si_is_sprom_available(sih) && srom[0] == 0xffff) ||
5484 #ifdef BCMQT
5485 (si_is_sprom_available(sih) && sromrev == 0) ||
5486 #endif
5487 (val & SPROM_OTPIN_USE)) {
5488 vp = base = mfgsromvars;
5489
5490 /* For windows internal/wltest driver, a .nvm file with default
5491 * nvram parameters is downloaded from the file system (in src/wl/sys:
5492 * wl_readconfigdata()).
5493 * Only when we cannot download default vars from the file system, use
5494 * defaultsromvars_wltest as default
5495 */
5496 if (defvarslen == 0) {
5497 BS_ERROR(("No nvm file, use generic default (for programming"
5498 " SPROM/OTP only)\n"));
5499
5500 if (BCM43602_CHIP(sih->chip)) {
5501 defvarslen = srom_vars_len(defaultsromvars_43602);
5502 bcopy(defaultsromvars_43602, vp, defvarslen);
5503 } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
5504 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
5505 defvarslen = srom_vars_len(defaultsromvars_4360);
5506 bcopy(defaultsromvars_4360, vp, defvarslen);
5507 } else if (BCM4378_CHIP(sih->chip)) {
5508 defvarslen = srom_vars_len(defaultsromvars_4378);
5509 bcopy(defaultsromvars_4378, vp, defvarslen);
5510 } else if (BCM4387_CHIP(sih->chip)) {
5511 defvarslen = srom_vars_len(defaultsromvars_4387);
5512 bcopy(defaultsromvars_4387, vp, defvarslen);
5513 } else {
5514 defvarslen = srom_vars_len(defaultsromvars_wltest);
5515 bcopy(defaultsromvars_wltest, vp, defvarslen);
5516 }
5517 } else {
5518 BS_ERROR(("Use nvm file as default\n"));
5519 }
5520
5521 vp += defvarslen;
5522 /* add final null terminator */
5523 *vp++ = '\0';
5524
5525 BS_ERROR(("Used %d bytes of defaultsromvars\n", defvarslen));
5526 goto varsdone;
5527
5528 } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
5529 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
5530 (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
5531 BCM43602_CHIP(sih->chip)) {
5532
5533 base = vp = mfgsromvars;
5534
5535 if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
5536 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
5537 (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
5538 BCM43602_CHIP(sih->chip))
5539 BS_ERROR(("4360 BOOT w/o SPROM or OTP\n"));
5540 else
5541 BS_ERROR(("BOOT w/o SPROM or OTP\n"));
5542
5543 if (defvarslen == 0) {
5544 if (BCM43602_CHIP(sih->chip)) {
5545 defvarslen = srom_vars_len(defaultsromvars_43602);
5546 bcopy(defaultsromvars_43602, vp, defvarslen);
5547 } else if ((sih->chip == BCM4360_CHIP_ID) ||
5548 (sih->chip == BCM4352_CHIP_ID)) {
5549 defvarslen = srom_vars_len(defaultsromvars_4360);
5550 bcopy(defaultsromvars_4360, vp, defvarslen);
5551 } else {
5552 defvarslen = srom_vars_len(defaultsromvars_4331);
5553 bcopy(defaultsromvars_4331, vp, defvarslen);
5554 }
5555 }
5556 vp += defvarslen;
5557 *vp++ = '\0';
5558 goto varsdone;
5559 } else
5560 #endif /* defined(BCMHOSTVARS) */
5561 {
5562 err = -1;
5563 goto errout;
5564 }
5565 }
5566 #if defined(BCM_ONE_NVRAM_SRC)
5567 /* Discard hostvars if SROM parsing is successful, so only one nvram source
5568 * will be used.
5569 * Routers use combined srom/host nvram so shouldn't define BCM_ONE_NVRAM_SRC.
5570 */
5571 else {
5572 nvram_exit((void *)sih); /* free up global vars */
5573 }
5574 #endif /* BCM_ONE_NVRAM_SRC */
5575
5576 varscont:
5577 /* Bitmask for the sromrev */
5578 sr = 1 << sromrev;
5579
5580 /* srom version check: Current valid versions are:
5581 * 1-5, 8-11, 12, 13, 15, 16, 17, 18 SROM_MAXREV
5582 * This is a bit mask of all valid SROM versions.
5583 */
5584 if ((sr & 0x7bf3e) == 0) {
5585 BS_ERROR(("Invalid SROM rev %d\n", sromrev));
5586 err = -2;
5587 goto errout;
5588 }
5589
5590 ASSERT(vars != NULL);
5591 ASSERT(count != NULL);
5592
5593 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5594 srom_sromrev = sromrev;
5595 #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */
5596
5597 /* freed in same function */
5598 base = vp = MALLOC_NOPERSIST(osh, MAXSZ_NVRAM_VARS);
5599 ASSERT(vp != NULL);
5600 if (!vp) {
5601 err = -2;
5602 goto errout;
5603 }
5604
5605 /* read variables from flash */
5606 if (flash) {
5607 if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)))
5608 goto errout;
5609 goto varsdone;
5610 }
5611
5612 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
5613
5614 /* parse SROM into name=value pairs. */
5615 _initvars_srom_pci(sromrev, srom, 0, &b);
5616
5617 /* final nullbyte terminator */
5618 ASSERT(b.size >= 1);
5619 vp = b.buf;
5620 *vp++ = '\0';
5621
5622 ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
5623
5624 varsdone:
5625 err = initvars_table(osh, base, vp, vars, count); /* allocates buffer in 'vars' */
5626
5627 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5628 if (sromrev == 18) {
5629 int caldata_wordoffset = srom[SROM18_CALDATA_OFFSET_LOC] / 2;
5630
5631 if ((caldata_wordoffset != 0) &&
5632 (caldata_wordoffset + SROM_CALDATA_WORDS < SROM18_WORDS)) {
5633 memcpy(caldata_array, srom + caldata_wordoffset, SROM18_CALDATA_WORDS * 2);
5634 is_caldata_prsnt = TRUE;
5635 }
5636 } else if (sromrev == 16) {
5637 int caldata_wordoffset = srom[SROM16_CALDATA_OFFSET_LOC] / 2;
5638
5639 if ((caldata_wordoffset != 0) &&
5640 (caldata_wordoffset + SROM_CALDATA_WORDS < SROM16_WORDS)) {
5641 memcpy(caldata_array, srom + caldata_wordoffset, SROM_CALDATA_WORDS * 2);
5642 is_caldata_prsnt = TRUE;
5643 }
5644 }
5645 #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */
5646
5647 #ifdef NVSRCX
5648 if (sromrev != 0)
5649 nvram_append((void *)sih, *vars, *count, VARBUF_PRIO_SROM);
5650 #endif
5651 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5652 if ((sromrev == 15) || (sromrev == 17)) {
5653 uint32 caldata_size = get_srom_pci_caldata_size(sromrev);
5654
5655 cal_wordoffset = getintvar(NULL, "caldata_offset")/2;
5656 memcpy(caldata_array, srom + cal_wordoffset, caldata_size);
5657 }
5658 #endif
5659 errout:
5660 #if defined(BCMHOSTVARS)
5661 if (base && (base != mfgsromvars))
5662 #else
5663 if (base)
5664 #endif /* defined(BCMHOSTVARS) */
5665 MFREE(osh, base, MAXSZ_NVRAM_VARS);
5666
5667 MFREE(osh, srom, SROM_MAX);
5668 return err;
5669 }
5670
5671 /**
5672 * initvars_cis_pci() parses OTP CIS. This is specifically for PCIe full dongle that has SROM
5673 * header plus CIS tuples programmed in OTP.
5674 * Return error if the content is not in CIS format or OTP is not present.
5675 */
5676 static int
5677 BCMATTACHFN(initvars_cis_pci)(si_t *sih, osl_t *osh, volatile void *curmap,
5678 char **vars, uint *count)
5679 {
5680 uint wsz = 0, sz = 0, base_len = 0;
5681 void *oh = NULL;
5682 int rc = BCME_OK;
5683 uint16 *cisbuf = NULL;
5684 uint8 *cis = NULL;
5685 #if defined (BCMHOSTVARS)
5686 char *vp = NULL;
5687 #endif /* BCMHOSTVARS */
5688 char *base = NULL;
5689 bool wasup;
5690 uint32 min_res_mask = 0;
5691 BCM_REFERENCE(curmap);
5692
5693 /* Bail out if we've dealt with OTP/SPROM before! */
5694 if (srvars_inited)
5695 goto exit;
5696
5697 /* Turn on OTP if it's not already on */
5698 if (!(wasup = si_is_otp_powered(sih)))
5699 si_otp_power(sih, TRUE, &min_res_mask);
5700
5701 if (si_cis_source(sih) != CIS_OTP)
5702 rc = BCME_NOTFOUND;
5703 else if ((oh = otp_init(sih)) == NULL)
5704 rc = BCME_ERROR;
5705 else if (!(((BUSCORETYPE(sih->buscoretype) == PCIE2_CORE_ID) || otp_newcis(oh)) &&
5706 (otp_status(oh) & OTPS_GUP_HW))) {
5707 /* OTP bit CIS format (507) not used by pcie core - only needed for sdio core */
5708 rc = BCME_NOTFOUND;
5709 } else if ((sz = otp_size(oh)) != 0) {
5710 if ((cisbuf = (uint16*)MALLOC_NOPERSIST(osh, sz))) {
5711 /* otp_size() returns bytes, not words. */
5712 wsz = sz >> 1;
5713 /* for 4389b0 (CCREV-70) sw region is before the hw region */
5714 if (CCREV(sih->ccrev) == 70) {
5715 rc = otp_read_region(sih, OTP_SW_RGN, cisbuf, &wsz);
5716 cis = (uint8*)cisbuf;
5717 } else {
5718 rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &wsz);
5719 /* Bypass the HW header and signature */
5720 cis = (uint8*)(cisbuf + (otp_pcie_hwhdr_sz(sih) / 2));
5721 }
5722 BS_ERROR(("initvars_cis_pci: Parsing CIS in OTP.\n"));
5723 } else
5724 rc = BCME_NOMEM;
5725 }
5726
5727 /* Restore original OTP state */
5728 if (!wasup)
5729 si_otp_power(sih, FALSE, &min_res_mask);
5730
5731 if (rc != BCME_OK) {
5732 BS_ERROR(("initvars_cis_pci: Not CIS format\n"));
5733 goto exit;
5734 }
5735
5736 #if defined (BCMHOSTVARS)
5737 if (defvarslen) {
5738 vp = mfgsromvars;
5739 vp += defvarslen;
5740
5741 /* allocates buffer in 'vars' */
5742 rc = initvars_table(osh, mfgsromvars, vp, &base, &base_len);
5743 if (rc)
5744 goto exit;
5745
5746 *vars = base;
5747 *count = base_len;
5748
5749 BS_ERROR(("initvars_cis_pci external nvram %d bytes\n", defvarslen));
5750 }
5751
5752 #endif /* BCMHOSTVARS */
5753
5754 /* Parse the CIS and allocate a(nother) buffer in 'vars' */
5755 rc = srom_parsecis(sih, osh, &cis, SROM_CIS_SINGLE, vars, count);
5756
5757 srvars_inited = TRUE;
5758 exit:
5759 /* Clean up */
5760 if (base)
5761 MFREE(osh, base, base_len);
5762 if (cisbuf)
5763 MFREE(osh, cisbuf, sz);
5764
5765 /* return OK so the driver will load & use defaults if bad srom/otp */
5766 return rc;
5767 }
5768 #endif /* !defined(BCMDONGLEHOST) */
5769
5770 #ifdef BCMSDIO
5771 #if !defined(BCMDONGLEHOST)
5772 /**
5773 * Read the SDIO cis and call parsecis to allocate and initialize the NVRAM vars buffer.
5774 * Return 0 on success, nonzero on error.
5775 */
5776 static int
5777 BCMATTACHFN(initvars_cis_sdio)(si_t *sih, osl_t *osh, char **vars, uint *count)
5778 {
5779 uint8 *cis[SBSDIO_NUM_FUNCTION + 1];
5780 uint fn, numfn;
5781 int rc = 0;
5782
5783 /* Using MALLOC here causes the Windows driver to crash Needs Investigating */
5784 #ifdef NDIS
5785 uint8 cisd[SBSDIO_NUM_FUNCTION + 1][SBSDIO_CIS_SIZE_LIMIT];
5786 #endif
5787
5788 numfn = bcmsdh_query_iofnum(NULL);
5789 ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
5790
5791 for (fn = 0; fn <= numfn; fn++) {
5792 #ifdef NDIS
5793 cis[fn] = (uint8*)cisd[fn];
5794 #else
5795 /* freed in same function */
5796 if ((cis[fn] = MALLOC_NOPERSIST(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) {
5797 rc = -1;
5798 break;
5799 }
5800 #endif /* NDIS */
5801
5802 bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT);
5803
5804 if (bcmsdh_cis_read(NULL, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT) != 0) {
5805 #ifdef NDIS
5806 /* nothing to do */
5807 #else
5808 MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
5809 #endif
5810 rc = -2;
5811 break;
5812 }
5813 }
5814
5815 if (!rc)
5816 rc = srom_parsecis(sih, osh, cis, fn, vars, count);
5817
5818 #ifdef NDIS
5819 /* nothing to do here */
5820 #else
5821 while (fn-- > 0)
5822 MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
5823 #endif
5824
5825 return (rc);
5826 }
5827 #endif /* !defined(BCMDONGLEHOST) */
5828
5829 /** set SDIO sprom command register */
5830 static int
5831 BCMATTACHFN(sprom_cmd_sdio)(osl_t *osh, uint8 cmd)
5832 {
5833 uint8 status = 0;
5834 uint wait_cnt = 1000;
5835
5836 /* write sprom command register */
5837 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, cmd, NULL);
5838
5839 /* wait status */
5840 while (wait_cnt--) {
5841 status = bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, NULL);
5842 if (status & SBSDIO_SPROM_DONE)
5843 return 0;
5844 }
5845
5846 return 1;
5847 }
5848
5849 /** read a word from the SDIO srom */
5850 static int
5851 sprom_read_sdio(osl_t *osh, uint16 addr, uint16 *data)
5852 {
5853 uint8 addr_l, addr_h, data_l, data_h;
5854
5855 addr_l = (uint8)((addr * 2) & 0xff);
5856 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
5857
5858 /* set address */
5859 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h, NULL);
5860 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l, NULL);
5861
5862 /* do read */
5863 if (sprom_cmd_sdio(osh, SBSDIO_SPROM_READ))
5864 return 1;
5865
5866 /* read data */
5867 data_h = bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, NULL);
5868 data_l = bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, NULL);
5869
5870 *data = (data_h << 8) | data_l;
5871 return 0;
5872 }
5873
5874 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
5875 /** write a word to the SDIO srom */
5876 static int
5877 sprom_write_sdio(osl_t *osh, uint16 addr, uint16 data)
5878 {
5879 uint8 addr_l, addr_h, data_l, data_h;
5880
5881 addr_l = (uint8)((addr * 2) & 0xff);
5882 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
5883 data_l = (uint8)(data & 0xff);
5884 data_h = (uint8)((data >> 8) & 0xff);
5885
5886 /* set address */
5887 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h, NULL);
5888 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l, NULL);
5889
5890 /* write data */
5891 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, data_h, NULL);
5892 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, data_l, NULL);
5893
5894 /* do write */
5895 return sprom_cmd_sdio(osh, SBSDIO_SPROM_WRITE);
5896 }
5897 #endif /* defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) */
5898 #endif /* BCMSDIO */
5899
5900 #if !defined(BCMDONGLEHOST)
5901 #ifdef BCMSPI
5902 /**
5903 * Read the SPI cis and call parsecis to allocate and initialize the NVRAM vars buffer.
5904 * Return 0 on success, nonzero on error.
5905 */
5906 static int
5907 BCMATTACHFN(initvars_cis_spi)(si_t *sih, osl_t *osh, char **vars, uint *count)
5908 {
5909 uint8 *cis;
5910 int rc;
5911
5912 /* Using MALLOC here causes the Windows driver to crash Needs Investigating */
5913 #ifdef NDIS
5914 uint8 cisd[SBSDIO_CIS_SIZE_LIMIT];
5915 cis = (uint8*)cisd;
5916 #else
5917 /* freed in same function */
5918 if ((cis = MALLOC_NOPERSIST(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) {
5919 return -1;
5920 }
5921 #endif /* NDIS */
5922
5923 bzero(cis, SBSDIO_CIS_SIZE_LIMIT);
5924
5925 if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, cis, SBSDIO_CIS_SIZE_LIMIT) != 0) {
5926 #ifdef NDIS
5927 /* nothing to do */
5928 #else
5929 MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
5930 #endif /* NDIS */
5931 return -2;
5932 }
5933
5934 rc = srom_parsecis(sih, osh, &cis, SDIO_FUNC_1, vars, count);
5935
5936 #ifdef NDIS
5937 /* nothing to do here */
5938 #else
5939 MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
5940 #endif
5941
5942 return (rc);
5943 }
5944 #endif /* BCMSPI */
5945 #endif /* !defined(BCMDONGLEHOST) */
5946
5947 /** Return sprom size in 16-bit words */
5948 uint
5949 srom_size(si_t *sih, osl_t *osh)
5950 {
5951 uint size = (SROM16_SIGN + 1) * 2; /* must big enough for SROM16 */
5952 return size;
5953 }
5954
5955 /**
5956 * initvars are different for BCMUSBDEV and BCMSDIODEV. This is OK when supporting both at
5957 * the same time, but only because all of the code is in attach functions and not in ROM.
5958 */
5959
5960 #if defined(BCMUSBDEV_ENABLED)
5961 #ifdef BCM_DONGLEVARS
5962 /*** reads a CIS structure (so not an SROM-MAP structure) from either OTP or SROM */
5963 static int
5964 BCMATTACHFN(initvars_srom_si_bl)(si_t *sih, osl_t *osh, volatile void *curmap,
5965 char **vars, uint *varsz)
5966 {
5967 int sel = 0; /* where to read srom/cis: 0 - none, 1 - otp, 2 - sprom */
5968 uint sz = 0; /* srom size in bytes */
5969 void *oh = NULL;
5970 int rc = BCME_OK;
5971 uint16 prio = VARBUF_PRIO_INVALID;
5972
5973 if ((oh = otp_init(sih)) != NULL && (otp_status(oh) & OTPS_GUP_SW)) {
5974 /* Access OTP if it is present, powered on, and programmed */
5975 sz = otp_size(oh);
5976 sel = 1;
5977 } else if ((sz = srom_size(sih, osh)) != 0) {
5978 /* Access the SPROM if it is present */
5979 sz <<= 1;
5980 sel = 2;
5981 }
5982
5983 /* Read CIS in OTP/SPROM */
5984 if (sel != 0) {
5985 uint16 *srom;
5986 uint8 *body = NULL;
5987 uint otpsz = sz;
5988
5989 ASSERT(sz);
5990
5991 /* Allocate memory */
5992 if ((srom = (uint16 *)MALLOC(osh, sz)) == NULL)
5993 return BCME_NOMEM;
5994
5995 /* Read CIS */
5996 switch (sel) {
5997 case 1:
5998 rc = otp_read_region(sih, OTP_SW_RGN, srom, &otpsz);
5999 sz = otpsz;
6000 body = (uint8 *)srom;
6001 prio = VARBUF_PRIO_OTP;
6002 break;
6003 case 2:
6004 rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, srom, TRUE);
6005 /* sprom has 8 byte h/w header */
6006 body = (uint8 *)srom + SBSDIO_SPROM_CIS_OFFSET;
6007 prio = VARBUF_PRIO_SROM;
6008 break;
6009 default:
6010 /* impossible to come here */
6011 ASSERT(0);
6012 break;
6013 }
6014
6015 /* Parse CIS */
6016 if (rc == BCME_OK) {
6017 /* each word is in host endian */
6018 htol16_buf((uint8 *)srom, sz);
6019 ASSERT(body);
6020 rc = srom_parsecis(sih, osh, &body, SROM_CIS_SINGLE, vars, varsz);
6021 }
6022
6023 MFREE(osh, srom, sz); /* Clean up */
6024
6025 /* Make SROM variables global */
6026 if (rc == BCME_OK) {
6027 nvram_append((void *)sih, *vars, *varsz, prio);
6028 DONGLE_STORE_VARS_OTP_PTR(*vars);
6029 }
6030 }
6031
6032 return BCME_OK;
6033 }
6034 #endif /* #ifdef BCM_DONGLEVARS */
6035
6036 /**
6037 * initvars_srom_si() is defined multiple times in this file. This is the 1st variant for chips with
6038 * an active USB interface. It is called only for bus types SI_BUS, and only for CIS
6039 * format in SPROM and/or OTP. Reads OTP or SPROM (bootloader only) and appends parsed contents to
6040 * caller supplied var/value pairs.
6041 */
6042 static int
6043 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6044 char **vars, uint *varsz)
6045 {
6046
6047 #if defined(BCM_DONGLEVARS)
6048 BCM_REFERENCE(osh);
6049 BCM_REFERENCE(sih);
6050 BCM_REFERENCE(curmap);
6051 #endif
6052
6053 /* Bail out if we've dealt with OTP/SPROM before! */
6054 if (srvars_inited)
6055 goto exit;
6056
6057 #ifdef BCM_DONGLEVARS /* this flag should be defined for usb bootloader, to read OTP or SROM */
6058 if (BCME_OK != initvars_srom_si_bl(sih, osh, curmap, vars, varsz)) /* CIS format only */
6059 return BCME_ERROR;
6060 #endif
6061
6062 /* update static local var to skip for next call */
6063 srvars_inited = TRUE;
6064
6065 exit:
6066 /* Tell the caller there is no individual SROM variables */
6067 *vars = NULL;
6068 *varsz = 0;
6069
6070 /* return OK so the driver will load & use defaults if bad srom/otp */
6071 return BCME_OK;
6072 }
6073
6074 #elif defined(BCMSDIODEV_ENABLED)
6075
6076 #ifdef BCM_DONGLEVARS
6077 static uint8 BCMATTACHDATA(defcis4369)[] = { 0x20, 0x4, 0xd0, 0x2, 0x64, 0x43, 0xff, 0xff };
6078 static uint8 BCMATTACHDATA(defcis43012)[] = { 0x20, 0x4, 0xd0, 0x2, 0x04, 0xA8, 0xff, 0xff };
6079 static uint8 BCMATTACHDATA(defcis43013)[] = { 0x20, 0x4, 0xd0, 0x2, 0x05, 0xA8, 0xff, 0xff };
6080 static uint8 BCMATTACHDATA(defcis43014)[] = { 0x20, 0x4, 0xd0, 0x2, 0x06, 0xA8, 0xff, 0xff };
6081 static uint8 BCMATTACHDATA(defcis4362)[] = { 0x20, 0x4, 0xd0, 0x2, 0x62, 0x43, 0xff, 0xff };
6082 static uint8 BCMATTACHDATA(defcis4378)[] = { 0x20, 0x4, 0xd0, 0x2, 0x78, 0x43, 0xff, 0xff };
6083 static uint8 BCMATTACHDATA(defcis4385)[] = { 0x20, 0x4, 0xd0, 0x2, 0x85, 0x43, 0xff, 0xff };
6084 static uint8 BCMATTACHDATA(defcis4387)[] = { 0x20, 0x4, 0xd0, 0x2, 0x78, 0x43, 0xff, 0xff };
6085 static uint8 BCMATTACHDATA(defcis4388)[] = { 0x20, 0x4, 0xd0, 0x2, 0x88, 0x43, 0xff, 0xff };
6086 static uint8 BCMATTACHDATA(defcis4389)[] = { 0x20, 0x4, 0xd0, 0x2, 0x89, 0x43, 0xff, 0xff };
6087 static uint8 BCMATTACHDATA(defcis4397)[] = { 0x20, 0x4, 0xd0, 0x2, 0x97, 0x43, 0xff, 0xff };
6088
6089 /**
6090 * initvars_srom_si() is defined multiple times in this file. This is the 2nd variant for chips with
6091 * an active SDIOd interface using DONGLEVARS
6092 */
6093 static int
6094 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6095 char **vars, uint *varsz)
6096 {
6097 int cis_src;
6098 uint msz = 0;
6099 uint sz = 0;
6100 void *oh = NULL;
6101 int rc = BCME_OK;
6102 bool new_cisformat = FALSE;
6103
6104 uint16 *cisbuf = NULL;
6105
6106 /* # sdiod fns + common + extra */
6107 uint8 *cis[SBSDIO_NUM_FUNCTION + 2] = { 0 };
6108
6109 uint ciss = 0;
6110 uint8 *defcis;
6111 uint hdrsz;
6112 uint16 prio = VARBUF_PRIO_INVALID;
6113
6114 #if defined(BCMSDIODEV_ENABLED) && defined(ATE_BUILD)
6115 if (si_chipcap_sdio_ate_only(sih)) {
6116 BS_ERROR(("ATE BUILD: skip cis based var init\n"));
6117 goto exit;
6118 }
6119 #endif /* BCMSDIODEV_ENABLED && ATE_BUILD */
6120
6121 /* Bail out if we've dealt with OTP/SPROM before! */
6122 if (srvars_inited)
6123 goto exit;
6124
6125 /* Initialize default and cis format count */
6126 switch (CHIPID(sih->chip)) {
6127 case BCM4369_CHIP_GRPID: ciss = 1; defcis = defcis4369; hdrsz = 4; break;
6128 case BCM4378_CHIP_GRPID: ciss = 1; defcis = defcis4378; hdrsz = 4; break;
6129 case BCM4385_CHIP_GRPID: ciss = 1; defcis = defcis4385; hdrsz = 4; break;
6130 case BCM4387_CHIP_GRPID: ciss = 1; defcis = defcis4387; hdrsz = 4; break;
6131 case BCM4388_CHIP_GRPID: ciss = 1; defcis = defcis4388; hdrsz = 4; break;
6132 case BCM4389_CHIP_GRPID: ciss = 1; defcis = defcis4389; hdrsz = 4; break;
6133 case BCM4397_CHIP_GRPID: ciss = 1; defcis = defcis4397; hdrsz = 4; break;
6134 case BCM43012_CHIP_ID: ciss = 1; defcis = defcis43012; hdrsz = 4; break;
6135 case BCM43013_CHIP_ID: ciss = 1; defcis = defcis43013; hdrsz = 4; break;
6136 case BCM43014_CHIP_ID: ciss = 1; defcis = defcis43014; hdrsz = 4; break;
6137 case BCM4362_CHIP_GRPID: ciss = 1; defcis = defcis4362; hdrsz = 4; break;
6138 default:
6139 BS_ERROR(("initvars_srom_si: Unknown chip 0x%04x\n", CHIPID(sih->chip)));
6140 return BCME_ERROR;
6141 }
6142 if (sih->ccrev >= 36) {
6143 uint32 otplayout;
6144 if (AOB_ENAB(sih)) {
6145 otplayout = si_corereg(sih, si_findcoreidx(sih, GCI_CORE_ID, 0),
6146 OFFSETOF(gciregs_t, otplayout), 0, 0);
6147 } else {
6148 otplayout = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otplayout),
6149 0, 0);
6150 }
6151 if (otplayout & OTP_CISFORMAT_NEW) {
6152 ciss = 1;
6153 hdrsz = 2;
6154 new_cisformat = TRUE;
6155 }
6156 else {
6157 ciss = 3;
6158 hdrsz = 12;
6159 }
6160 }
6161
6162 cis_src = si_cis_source(sih);
6163 switch (cis_src) {
6164 case CIS_SROM:
6165 sz = srom_size(sih, osh) << 1;
6166 prio = VARBUF_PRIO_SROM;
6167 break;
6168 case CIS_OTP:
6169 /* Note that for *this* type of OTP -- which otp_read_region()
6170 * can operate on -- otp_size() returns bytes, not words.
6171 */
6172 if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW))
6173 sz = otp_size(oh);
6174 prio = VARBUF_PRIO_OTP;
6175 break;
6176 }
6177
6178 if (sz != 0) {
6179 /* freed in same function */
6180 if ((cisbuf = (uint16*)MALLOC_NOPERSIST(osh, sz)) == NULL)
6181 return BCME_NOMEM;
6182 msz = sz;
6183
6184 switch (cis_src) {
6185 case CIS_SROM:
6186 rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, cisbuf, FALSE);
6187 break;
6188 case CIS_OTP:
6189 sz >>= 1;
6190 rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &sz);
6191 sz <<= 1;
6192 break;
6193 }
6194
6195 ASSERT(sz > hdrsz);
6196 if (rc == BCME_OK) {
6197 if ((cisbuf[0] == 0xffff) || (cisbuf[0] == 0)) {
6198 MFREE(osh, cisbuf, msz);
6199 } else if (new_cisformat) {
6200 cis[0] = (uint8*)(cisbuf + hdrsz);
6201 } else {
6202 cis[0] = (uint8*)cisbuf + hdrsz;
6203 cis[1] = (uint8*)cisbuf + hdrsz +
6204 (cisbuf[1] >> 8) + ((cisbuf[2] & 0x00ff) << 8) -
6205 SBSDIO_CIS_BASE_COMMON;
6206 cis[2] = (uint8*)cisbuf + hdrsz +
6207 cisbuf[3] - SBSDIO_CIS_BASE_COMMON;
6208 cis[3] = (uint8*)cisbuf + hdrsz +
6209 cisbuf[4] - SBSDIO_CIS_BASE_COMMON;
6210 ASSERT((cis[1] >= cis[0]) && (cis[1] < (uint8*)cisbuf + sz));
6211 ASSERT((cis[2] >= cis[0]) && (cis[2] < (uint8*)cisbuf + sz));
6212 ASSERT(((cis[3] >= cis[0]) && (cis[3] < (uint8*)cisbuf + sz)) ||
6213 (ciss <= 3));
6214 }
6215 }
6216 }
6217
6218 /* Use default if strapped to, or strapped source empty */
6219 if (cisbuf == NULL) {
6220 ciss = 1;
6221 cis[0] = defcis;
6222 }
6223
6224 /* Parse the CIS */
6225 if (rc == BCME_OK) {
6226 if ((rc = srom_parsecis(sih, osh, cis, ciss, vars, varsz)) == BCME_OK) {
6227 nvram_append((void *)sih, *vars, *varsz, prio);
6228 DONGLE_STORE_VARS_OTP_PTR(*vars);
6229 }
6230 }
6231
6232 /* Clean up */
6233 if (cisbuf != NULL)
6234 MFREE(osh, cisbuf, msz);
6235
6236 srvars_inited = TRUE;
6237 exit:
6238 /* Tell the caller there is no individual SROM variables */
6239 *vars = NULL;
6240 *varsz = 0;
6241
6242 /* return OK so the driver will load & use defaults if bad srom/otp */
6243 return BCME_OK;
6244 } /* initvars_srom_si */
6245 #else /* BCM_DONGLEVARS */
6246
6247 /**
6248 * initvars_srom_si() is defined multiple times in this file. This is the variant for chips with an
6249 * active SDIOd interface but without BCM_DONGLEVARS
6250 */
6251 static int
6252 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6253 char **vars, uint *varsz)
6254 {
6255 *vars = NULL;
6256 *varsz = 0;
6257 return BCME_OK;
6258 }
6259 #endif /* BCM_DONGLEVARS */
6260
6261 #elif defined(BCMPCIEDEV_ENABLED)
6262
6263 /**
6264 * initvars_srom_si() is defined multiple times in this file. This is the variant for chips with an
6265 * active PCIe interface *and* that use OTP for NVRAM storage.
6266 *
6267 * On success, a buffer containing var/val values has been allocated in parameter 'vars'.
6268 * put an ifdef where if the host wants the dongle wants to parse sprom or not
6269 */
6270 static int
6271 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6272 char **vars, uint *varsz)
6273 {
6274 #ifdef BCM_DONGLEVARS
6275 void *oh = NULL;
6276 uint8 *cis;
6277 uint sz = 0;
6278 int rc;
6279
6280 if (si_cis_source(sih) != CIS_OTP)
6281 return BCME_OK;
6282
6283 if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW))
6284 sz = otp_size(oh);
6285 if (sz == 0)
6286 return BCME_OK;
6287
6288 if ((cis = MALLOC(osh, sz)) == NULL)
6289 return BCME_NOMEM;
6290 sz >>= 1;
6291 rc = otp_read_region(sih, OTP_HW_RGN, (uint16 *)cis, &sz);
6292 sz <<= 1;
6293
6294 /* account for the Hardware header */
6295 if (sz == 128)
6296 return BCME_OK;
6297
6298 cis += 128;
6299
6300 /* need to find a better way to identify sprom format content and ignore parse */
6301 if (*(uint16 *)cis == SROM11_SIGNATURE) {
6302 return BCME_OK;
6303 }
6304
6305 if ((rc = srom_parsecis(sih, osh, &cis, SROM_CIS_SINGLE, vars, varsz)) == BCME_OK)
6306 nvram_append((void *)sih, *vars, *varsz, VARBUF_PRIO_OTP);
6307
6308 return rc;
6309 #else /* BCM_DONGLEVARS */
6310 *vars = NULL;
6311 *varsz = 0;
6312 return BCME_OK;
6313 #endif /* BCM_DONGLEVARS */
6314 }
6315 #else /* !BCMUSBDEV && !BCMSDIODEV && !BCMPCIEDEV */
6316
6317 #ifndef BCMDONGLEHOST
6318
6319 /**
6320 * initvars_srom_si() is defined multiple times in this file. This is the variant for:
6321 * !BCMDONGLEHOST && !BCMUSBDEV && !BCMSDIODEV && !BCMPCIEDEV
6322 * So this function is defined for PCI (not PCIe) builds that are also non DHD builds.
6323 * On success, a buffer containing var/val values has been allocated in parameter 'vars'.
6324 */
6325 static int
6326 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6327 char **vars, uint *varsz)
6328 {
6329 /* Search flash nvram section for srom variables */
6330 BCM_REFERENCE(osh);
6331 BCM_REFERENCE(curmap);
6332 return initvars_flash_si(sih, vars, varsz);
6333 } /* initvars_srom_si */
6334 #endif /* !BCMDONGLEHOST */
6335 #endif /* !BCMUSBDEV && !BCMSDIODEV && !BCMPCIEDEV */
6336
6337 void
6338 BCMATTACHFN(srom_var_deinit)(si_t *sih)
6339 {
6340 BCM_REFERENCE(sih);
6341
6342 srvars_inited = FALSE;
6343 }
6344
6345 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
6346 bool
6347 BCMATTACHFN(srom_caldata_prsnt)(si_t *sih)
6348 {
6349 return is_caldata_prsnt;
6350 }
6351
6352 int
6353 BCMATTACHFN(srom_get_caldata)(si_t *sih, uint16 *srom)
6354 {
6355 if (!is_caldata_prsnt) {
6356 return BCME_ERROR;
6357 }
6358 if (srom_sromrev == 18) {
6359 memcpy(srom, caldata_array, SROM18_CALDATA_WORDS * 2);
6360 } else {
6361 memcpy(srom, caldata_array, SROM_CALDATA_WORDS * 2);
6362 }
6363 return BCME_OK;
6364 }
6365 #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */