~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/staging/brcm80211/util/bcmsrom.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

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