staging: brcm80211: remove usage of pcicfg.h from brcmsmac driver
[linux-2.6-block.git] / drivers / staging / brcm80211 / brcmsmac / bcmsrom.c
CommitLineData
a9533e7e
HP
1/*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
48c51a8c 16#include <linux/kernel.h>
3327989a 17#include <linux/string.h>
3ca5ada5 18#include <linux/etherdevice.h>
a1c16ed2 19#include <bcmdefs.h>
c6ac24e9
BR
20#include <linux/module.h>
21#include <linux/pci.h>
a9533e7e 22#include <stdarg.h>
e40514c2 23#include "wlc_types.h"
a9533e7e 24#include <bcmutils.h>
189aed09 25#include <bcmsoc.h>
a9533e7e
HP
26#include <sbchipc.h>
27#include <bcmdevs.h>
4b168116 28#include <nicpci.h>
b21c892d 29#include <aiutils.h>
a9533e7e 30#include <bcmsrom.h>
a9533e7e
HP
31
32#include <bcmnvram.h>
33#include <bcmotp.h>
34
a9533e7e
HP
35#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
36 (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
36ef9a1e
GKH
37 ((u8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
38 ((u8 *)curmap + PCI_BAR0_SPROM_OFFSET))
a9533e7e
HP
39
40#if defined(BCMDBG)
41#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
42#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
43#endif
44
23d77de3
AS
45/* Maximum srom: 6 Kilobits == 768 bytes */
46#define SROM_MAX 768
47
48/* PCI fields */
49#define PCI_F0DEVID 48
50
51#define SROM_WORDS 64
52
53#define SROM_SSID 2
54
55#define SROM_WL1LHMAXP 29
56
57#define SROM_WL1LPAB0 30
58#define SROM_WL1LPAB1 31
59#define SROM_WL1LPAB2 32
60
61#define SROM_WL1HPAB0 33
62#define SROM_WL1HPAB1 34
63#define SROM_WL1HPAB2 35
64
65#define SROM_MACHI_IL0 36
66#define SROM_MACMID_IL0 37
67#define SROM_MACLO_IL0 38
68#define SROM_MACHI_ET1 42
69#define SROM_MACMID_ET1 43
70#define SROM_MACLO_ET1 44
71#define SROM3_MACHI 37
72#define SROM3_MACMID 38
73#define SROM3_MACLO 39
74
75#define SROM_BXARSSI2G 40
76#define SROM_BXARSSI5G 41
77
78#define SROM_TRI52G 42
79#define SROM_TRI5GHL 43
80
81#define SROM_RXPO52G 45
82
83#define SROM_AABREV 46
84/* Fields in AABREV */
85#define SROM_BR_MASK 0x00ff
86#define SROM_CC_MASK 0x0f00
87#define SROM_CC_SHIFT 8
88#define SROM_AA0_MASK 0x3000
89#define SROM_AA0_SHIFT 12
90#define SROM_AA1_MASK 0xc000
91#define SROM_AA1_SHIFT 14
92
93#define SROM_WL0PAB0 47
94#define SROM_WL0PAB1 48
95#define SROM_WL0PAB2 49
96
97#define SROM_LEDBH10 50
98#define SROM_LEDBH32 51
99
100#define SROM_WL10MAXP 52
101
102#define SROM_WL1PAB0 53
103#define SROM_WL1PAB1 54
104#define SROM_WL1PAB2 55
105
106#define SROM_ITT 56
107
108#define SROM_BFL 57
109#define SROM_BFL2 28
110#define SROM3_BFL2 61
111
112#define SROM_AG10 58
113
114#define SROM_CCODE 59
115
116#define SROM_OPO 60
117
118#define SROM3_LEDDC 62
119
120#define SROM_CRCREV 63
121
122/* SROM Rev 4: Reallocate the software part of the srom to accommodate
123 * MIMO features. It assumes up to two PCIE functions and 440 bytes
124 * of usable srom i.e. the usable storage in chips with OTP that
125 * implements hardware redundancy.
126 */
127
128#define SROM4_WORDS 220
129
130#define SROM4_SIGN 32
131#define SROM4_SIGNATURE 0x5372
132
133#define SROM4_BREV 33
134
135#define SROM4_BFL0 34
136#define SROM4_BFL1 35
137#define SROM4_BFL2 36
138#define SROM4_BFL3 37
139#define SROM5_BFL0 37
140#define SROM5_BFL1 38
141#define SROM5_BFL2 39
142#define SROM5_BFL3 40
143
144#define SROM4_MACHI 38
145#define SROM4_MACMID 39
146#define SROM4_MACLO 40
147#define SROM5_MACHI 41
148#define SROM5_MACMID 42
149#define SROM5_MACLO 43
150
151#define SROM4_CCODE 41
152#define SROM4_REGREV 42
153#define SROM5_CCODE 34
154#define SROM5_REGREV 35
155
156#define SROM4_LEDBH10 43
157#define SROM4_LEDBH32 44
158#define SROM5_LEDBH10 59
159#define SROM5_LEDBH32 60
160
161#define SROM4_LEDDC 45
162#define SROM5_LEDDC 45
163
164#define SROM4_AA 46
165
166#define SROM4_AG10 47
167#define SROM4_AG32 48
168
169#define SROM4_TXPID2G 49
170#define SROM4_TXPID5G 51
171#define SROM4_TXPID5GL 53
172#define SROM4_TXPID5GH 55
173
174#define SROM4_TXRXC 61
175#define SROM4_TXCHAIN_MASK 0x000f
176#define SROM4_TXCHAIN_SHIFT 0
177#define SROM4_RXCHAIN_MASK 0x00f0
178#define SROM4_RXCHAIN_SHIFT 4
179#define SROM4_SWITCH_MASK 0xff00
180#define SROM4_SWITCH_SHIFT 8
181
182/* Per-path fields */
183#define MAX_PATH_SROM 4
184#define SROM4_PATH0 64
185#define SROM4_PATH1 87
186#define SROM4_PATH2 110
187#define SROM4_PATH3 133
188
189#define SROM4_2G_ITT_MAXP 0
190#define SROM4_2G_PA 1
191#define SROM4_5G_ITT_MAXP 5
192#define SROM4_5GLH_MAXP 6
193#define SROM4_5G_PA 7
194#define SROM4_5GL_PA 11
195#define SROM4_5GH_PA 15
196
197/* All the miriad power offsets */
198#define SROM4_2G_CCKPO 156
199#define SROM4_2G_OFDMPO 157
200#define SROM4_5G_OFDMPO 159
201#define SROM4_5GL_OFDMPO 161
202#define SROM4_5GH_OFDMPO 163
203#define SROM4_2G_MCSPO 165
204#define SROM4_5G_MCSPO 173
205#define SROM4_5GL_MCSPO 181
206#define SROM4_5GH_MCSPO 189
207#define SROM4_CDDPO 197
208#define SROM4_STBCPO 198
209#define SROM4_BW40PO 199
210#define SROM4_BWDUPPO 200
211
212#define SROM4_CRCREV 219
213
214/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
215 * This is acombined srom for both MIMO and SISO boards, usable in
216 * the .130 4Kilobit OTP with hardware redundancy.
217 */
218#define SROM8_BREV 65
219
220#define SROM8_BFL0 66
221#define SROM8_BFL1 67
222#define SROM8_BFL2 68
223#define SROM8_BFL3 69
224
225#define SROM8_MACHI 70
226#define SROM8_MACMID 71
227#define SROM8_MACLO 72
228
229#define SROM8_CCODE 73
230#define SROM8_REGREV 74
231
232#define SROM8_LEDBH10 75
233#define SROM8_LEDBH32 76
234
235#define SROM8_LEDDC 77
236
237#define SROM8_AA 78
238
239#define SROM8_AG10 79
240#define SROM8_AG32 80
241
242#define SROM8_TXRXC 81
243
244#define SROM8_BXARSSI2G 82
245#define SROM8_BXARSSI5G 83
246#define SROM8_TRI52G 84
247#define SROM8_TRI5GHL 85
248#define SROM8_RXPO52G 86
249
250#define SROM8_FEM2G 87
251#define SROM8_FEM5G 88
252#define SROM8_FEM_ANTSWLUT_MASK 0xf800
253#define SROM8_FEM_ANTSWLUT_SHIFT 11
254#define SROM8_FEM_TR_ISO_MASK 0x0700
255#define SROM8_FEM_TR_ISO_SHIFT 8
256#define SROM8_FEM_PDET_RANGE_MASK 0x00f8
257#define SROM8_FEM_PDET_RANGE_SHIFT 3
258#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006
259#define SROM8_FEM_EXTPA_GAIN_SHIFT 1
260#define SROM8_FEM_TSSIPOS_MASK 0x0001
261#define SROM8_FEM_TSSIPOS_SHIFT 0
262
263#define SROM8_THERMAL 89
264
265/* Temp sense related entries */
266#define SROM8_MPWR_RAWTS 90
267#define SROM8_TS_SLP_OPT_CORRX 91
268/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
269#define SROM8_FOC_HWIQ_IQSWP 92
270
271/* Temperature delta for PHY calibration */
272#define SROM8_PHYCAL_TEMPDELTA 93
273
274/* Per-path offsets & fields */
275#define SROM8_PATH0 96
276#define SROM8_PATH1 112
277#define SROM8_PATH2 128
278#define SROM8_PATH3 144
279
280#define SROM8_2G_ITT_MAXP 0
281#define SROM8_2G_PA 1
282#define SROM8_5G_ITT_MAXP 4
283#define SROM8_5GLH_MAXP 5
284#define SROM8_5G_PA 6
285#define SROM8_5GL_PA 9
286#define SROM8_5GH_PA 12
287
288/* All the miriad power offsets */
289#define SROM8_2G_CCKPO 160
290
291#define SROM8_2G_OFDMPO 161
292#define SROM8_5G_OFDMPO 163
293#define SROM8_5GL_OFDMPO 165
294#define SROM8_5GH_OFDMPO 167
295
296#define SROM8_2G_MCSPO 169
297#define SROM8_5G_MCSPO 177
298#define SROM8_5GL_MCSPO 185
299#define SROM8_5GH_MCSPO 193
300
301#define SROM8_CDDPO 201
302#define SROM8_STBCPO 202
303#define SROM8_BW40PO 203
304#define SROM8_BWDUPPO 204
305
306/* SISO PA parameters are in the path0 spaces */
307#define SROM8_SISO 96
308
309/* Legacy names for SISO PA paramters */
310#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP)
311#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA)
312#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1)
313#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2)
314#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP)
315#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP)
316#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA)
317#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1)
318#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2)
319#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA)
320#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1)
321#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2)
322#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA)
323#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1)
324#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2)
325
326/* SROM REV 9 */
327#define SROM9_2GPO_CCKBW20 160
328#define SROM9_2GPO_CCKBW20UL 161
329#define SROM9_2GPO_LOFDMBW20 162
330#define SROM9_2GPO_LOFDMBW20UL 164
331
332#define SROM9_5GLPO_LOFDMBW20 166
333#define SROM9_5GLPO_LOFDMBW20UL 168
334#define SROM9_5GMPO_LOFDMBW20 170
335#define SROM9_5GMPO_LOFDMBW20UL 172
336#define SROM9_5GHPO_LOFDMBW20 174
337#define SROM9_5GHPO_LOFDMBW20UL 176
338
339#define SROM9_2GPO_MCSBW20 178
340#define SROM9_2GPO_MCSBW20UL 180
341#define SROM9_2GPO_MCSBW40 182
342
343#define SROM9_5GLPO_MCSBW20 184
344#define SROM9_5GLPO_MCSBW20UL 186
345#define SROM9_5GLPO_MCSBW40 188
346#define SROM9_5GMPO_MCSBW20 190
347#define SROM9_5GMPO_MCSBW20UL 192
348#define SROM9_5GMPO_MCSBW40 194
349#define SROM9_5GHPO_MCSBW20 196
350#define SROM9_5GHPO_MCSBW20UL 198
351#define SROM9_5GHPO_MCSBW40 200
352
353#define SROM9_PO_MCS32 202
354#define SROM9_PO_LOFDM40DUP 203
355
a4f031d3
AS
356/* SROM flags (see sromvar_t) */
357#define SRFL_MORE 1 /* value continues as described by the next entry */
358#define SRFL_NOFFS 2 /* value bits can't be all one's */
359#define SRFL_PRHEX 4 /* value is in hexdecimal format */
360#define SRFL_PRSIGN 8 /* value is in signed decimal format */
361#define SRFL_CCODE 0x10 /* value is in country code format */
362#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */
363#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */
364#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */
365
31c9f6d9
RV
366/* Max. nvram variable table size */
367#define MAXSZ_NVRAM_VARS 4096
368
a4f031d3
AS
369typedef struct {
370 const char *name;
371 u32 revmask;
372 u32 flags;
373 u16 off;
374 u16 mask;
375} sromvar_t;
376
a9533e7e
HP
377typedef struct varbuf {
378 char *base; /* pointer to buffer base */
379 char *buf; /* pointer to current position */
380 unsigned int size; /* current (residual) size in bytes */
381} varbuf_t;
a9533e7e 382
a4f031d3
AS
383/* Assumptions:
384 * - Ethernet address spans across 3 consective words
385 *
386 * Table rules:
387 * - Add multiple entries next to each other if a value spans across multiple words
388 * (even multiple fields in the same word) with each entry except the last having
389 * it's SRFL_MORE bit set.
390 * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
391 * bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
392 * - The last entry's name field must be NULL to indicate the end of the table. Other
393 * entries must have non-NULL name.
394 */
395static const sromvar_t pci_sromvars[] = {
396 {"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff},
397 {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK},
398 {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
399 {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
400 {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
401 {"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
402 {"", 0, 0, SROM_BFL2, 0xffff},
403 {"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
404 {"", 0, 0, SROM3_BFL2, 0xffff},
405 {"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff},
406 {"", 0, 0, SROM4_BFL1, 0xffff},
407 {"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff},
408 {"", 0, 0, SROM5_BFL1, 0xffff},
409 {"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff},
410 {"", 0, 0, SROM8_BFL1, 0xffff},
411 {"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff},
412 {"", 0, 0, SROM4_BFL3, 0xffff},
413 {"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff},
414 {"", 0, 0, SROM5_BFL3, 0xffff},
415 {"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff},
416 {"", 0, 0, SROM8_BFL3, 0xffff},
417 {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
418 {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
419 {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff},
420 {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff},
421 {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff},
422 {"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff},
423 {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
424 {"regrev", 0x00000008, 0, SROM_OPO, 0xff00},
425 {"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff},
426 {"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff},
427 {"regrev", 0xffffff00, 0, SROM8_REGREV, 0x00ff},
428 {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
429 {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
430 {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
431 {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
432 {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
433 {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
434 {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
435 {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
436 {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
437 {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
438 {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
439 {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
440 {"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
441 {"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
442 {"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
443 {"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
444 {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
445 {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
446 {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
447 {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff},
448 {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
449 {"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
450 {"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
451 {"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
452 {"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
453 {"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
454 {"opo", 0x0000000c, 0, SROM_OPO, 0x00ff},
455 {"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
456 {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
457 {"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff},
458 {"aa2g", 0xffffff00, 0, SROM8_AA, 0x00ff},
459 {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
460 {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00},
461 {"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00},
462 {"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff},
463 {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00},
464 {"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff},
465 {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00},
466 {"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff},
467 {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00},
468 {"ag0", 0xffffff00, 0, SROM8_AG10, 0x00ff},
469 {"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00},
470 {"ag2", 0xffffff00, 0, SROM8_AG32, 0x00ff},
471 {"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00},
472 {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
473 {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
474 {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
475 {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
476 {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
477 {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
478 {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
479 {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
480 {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
481 {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00},
482 {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
483 {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
484 {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
485 {"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
486 {"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
487 {"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
488 {"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
489 {"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
490 {"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
491 {"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
492 {"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
493 {"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
494 {"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
495 {"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
496 {"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
497 {"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
498 {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
499 {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
500 {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
501 {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
502 {"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
503 {"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
504 {"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
505 {"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
506 {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
507 {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
508 {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
509 {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
510 {"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
511 {"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
512 {"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
513 {"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
514 {"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff},
515 {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00},
516 {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
517 {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00},
518 {"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
519 {"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00},
520 {"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
521 {"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
522 {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
523 {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
524 {"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
525 {"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
526 {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK},
527 {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK},
528 {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK},
529 {"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK},
530 {"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK},
531 {"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK},
532 {"tssipos2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK},
533 {"extpagain2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK},
534 {"pdetrange2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK},
535 {"triso2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
536 {"antswctl2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK},
537 {"tssipos5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK},
538 {"extpagain5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK},
539 {"pdetrange5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK},
540 {"triso5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
541 {"antswctl5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK},
542 {"tempthresh", 0xffffff00, 0, SROM8_THERMAL, 0xff00},
543 {"tempoffset", 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
544 {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
545 {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
546 {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
547 {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
548 {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
549 {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
550 {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
551 {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
552 {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
553 {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
554 {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
555 {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
556 {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
557 {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
558 {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
559 {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
560
561 {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
562 {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
563 {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
564 {"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
565 {"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
566 {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
567 {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
568 {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
569 {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff},
570 {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff},
571 {"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff},
572 {"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff},
573 {"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff},
574 {"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff},
575 {"rawtempsense", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff},
576 {"measpower", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00},
577 {"tempsense_slope", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
578 0x00ff},
579 {"tempcorrx", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00},
580 {"tempsense_option", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
581 0x0300},
582 {"freqoffset_corr", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
583 0x000f},
584 {"iqcal_swp_dis", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010},
585 {"hw_iqcal_en", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020},
586 {"phycal_tempdelta", 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff},
587
588 {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
589 {"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
590 {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
591 {"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
592 {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
593 {"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
594 {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
595 {"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
596 {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
597 {"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
598 {"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
599 {"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
600 {"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
601 {"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
602 {"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
603 {"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
604 {"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
605 {"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
606 {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
607 {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
608 {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
609 {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
610 {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
611 {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
612 {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
613 {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
614 {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
615 {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
616 {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
617 {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
618 {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
619 {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
620 {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
621 {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
622 {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
623 {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
624 {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
625 {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
626 {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
627 {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
628 {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
629 {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
630 {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
631 {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
632 {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
633 {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
634 {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
635 {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
636 {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
637 {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
638 {"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
639 {"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
640 {"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
641 {"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
642 {"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
643 {"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
644 {"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
645 {"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
646 {"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
647 {"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
648 {"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
649 {"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
650 {"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
651 {"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
652 {"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
653 {"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
654 {"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
655 {"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
656 {"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
657 {"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
658 {"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
659 {"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
660 {"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
661 {"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
662 {"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
663 {"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
664 {"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
665 {"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
666 {"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
667 {"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
668 {"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
669 {"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
670 {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff},
671 {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff},
672 {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff},
673 {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
674 {"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff},
675 {"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff},
676 {"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff},
677 {"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
678
679 /* power per rate from sromrev 9 */
680 {"cckbw202gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
681 {"cckbw20ul2gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
682 {"legofdmbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20,
683 0xffff},
684 {"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
685 {"legofdmbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL,
686 0xffff},
687 {"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
688 {"legofdmbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20,
689 0xffff},
690 {"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
691 {"legofdmbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,
692 0xffff},
693 {"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
694 {"legofdmbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20,
695 0xffff},
696 {"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
697 {"legofdmbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,
698 0xffff},
699 {"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
700 {"legofdmbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20,
701 0xffff},
702 {"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
703 {"legofdmbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,
704 0xffff},
705 {"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
706 {"mcsbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff},
707 {"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
708 {"mcsbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff},
709 {"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
710 {"mcsbw402gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff},
711 {"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
712 {"mcsbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff},
713 {"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
714 {"mcsbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20UL,
715 0xffff},
716 {"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
717 {"mcsbw405glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff},
718 {"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
719 {"mcsbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff},
720 {"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
721 {"mcsbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20UL,
722 0xffff},
723 {"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
724 {"mcsbw405gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff},
725 {"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
726 {"mcsbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff},
727 {"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
728 {"mcsbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20UL,
729 0xffff},
730 {"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
731 {"mcsbw405ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff},
732 {"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
733 {"mcs32po", 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
734 {"legofdm40duppo", 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
735
736 {NULL, 0, 0, 0, 0}
737};
738
739static const sromvar_t perpath_pci_sromvars[] = {
740 {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
741 {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
742 {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
743 {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
744 {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
745 {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
746 {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
747 {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
748 {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
749 {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
750 {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
751 {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
752 {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
753 {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
754 {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
755 {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff},
756 {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff},
757 {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff},
758 {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
759 {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff},
760 {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff},
761 {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff},
762 {"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
763 {"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
764 {"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
765 {"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
766 {"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
767 {"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
768 {"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
769 {"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
770 {"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
771 {"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
772 {"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
773 {"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
774 {"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
775 {"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff},
776 {"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff},
777 {"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
778 {"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff},
779 {"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff},
780 {NULL, 0, 0, 0, 0}
781};
782
26bcc181
AS
783static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *count);
784static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b);
785static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count);
7cc4a4c0 786static int initvars_flash_si(si_t *sih, char **vars, uint *count);
26bcc181 787static int sprom_read_pci(si_t *sih, u16 *sprom,
e69284f2 788 uint wordoff, u16 *buf, uint nwords, bool check_crc);
a9533e7e 789#if defined(BCMNVRAMR)
26bcc181 790static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz);
a9533e7e 791#endif
26bcc181 792static u16 srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
7d4df48e 793 uint wordoff, u16 data);
a9533e7e 794
26bcc181 795static int initvars_table(char *start, char *end,
e69284f2 796 char **vars, uint *count);
26bcc181 797static int initvars_flash(si_t *sih, char **vp,
e69284f2 798 uint len);
a9533e7e
HP
799
800/* Initialization of varbuf structure */
0d2f0724 801static void varbuf_init(varbuf_t *b, char *buf, uint size)
a2627bc0 802{
a9533e7e
HP
803 b->size = size;
804 b->base = b->buf = buf;
805}
806
807/* append a null terminated var=value string */
0d2f0724 808static int varbuf_append(varbuf_t *b, const char *fmt, ...)
a2627bc0 809{
a9533e7e
HP
810 va_list ap;
811 int r;
812 size_t len;
813 char *s;
814
815 if (b->size < 2)
816 return 0;
817
818 va_start(ap, fmt);
819 r = vsnprintf(b->buf, b->size, fmt, ap);
820 va_end(ap);
821
822 /* C99 snprintf behavior returns r >= size on overflow,
823 * others return -1 on overflow.
824 * All return -1 on format error.
825 * We need to leave room for 2 null terminations, one for the current var
826 * string, and one for final null of the var table. So check that the
827 * strlen written, r, leaves room for 2 chars.
828 */
829 if ((r == -1) || (r > (int)(b->size - 2))) {
830 b->size = 0;
831 return 0;
832 }
833
834 /* Remove any earlier occurrence of the same variable */
ca8c1e59
JC
835 s = strchr(b->buf, '=');
836 if (s != NULL) {
a9533e7e
HP
837 len = (size_t) (s - b->buf);
838 for (s = b->base; s < b->buf;) {
a043b266 839 if ((memcmp(s, b->buf, len) == 0) && s[len] == '=') {
a9533e7e
HP
840 len = strlen(s) + 1;
841 memmove(s, (s + len),
842 ((b->buf + r + 1) - (s + len)));
843 b->buf -= len;
844 b->size += (unsigned int)len;
845 break;
846 }
847
62145822
JC
848 while (*s++)
849 ;
a9533e7e
HP
850 }
851 }
852
853 /* skip over this string's null termination */
854 r++;
855 b->size -= r;
856 b->buf += r;
857
858 return r;
859}
860
861/*
862 * Initialize local vars from the right source for this platform.
863 * Return 0 on success, nonzero on error.
864 */
26bcc181 865int srom_var_init(si_t *sih, uint bustype, void *curmap,
0d2f0724
GKH
866 char **vars, uint *count)
867{
a9533e7e
HP
868 uint len;
869
870 len = 0;
871
a9533e7e 872 if (vars == NULL || count == NULL)
90ea2296 873 return 0;
a9533e7e
HP
874
875 *vars = NULL;
876 *count = 0;
877
fa7a1db2 878 switch (bustype) {
a9533e7e
HP
879 case SI_BUS:
880 case JTAG_BUS:
26bcc181 881 return initvars_srom_si(sih, curmap, vars, count);
a9533e7e
HP
882
883 case PCI_BUS:
a9533e7e 884 if (curmap == NULL)
90ea2296 885 return -1;
a9533e7e
HP
886
887 return initvars_srom_pci(sih, curmap, vars, count);
888
a9533e7e 889 default:
909f43a0 890 break;
a9533e7e 891 }
90ea2296 892 return -1;
a9533e7e
HP
893}
894
a9533e7e
HP
895/* In chips with chipcommon rev 32 and later, the srom is in chipcommon,
896 * not in the bus cores.
897 */
7d4df48e 898static u16
26bcc181 899srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
e69284f2 900 uint wordoff, u16 data)
a9533e7e
HP
901{
902 chipcregs_t *cc = (chipcregs_t *) ccregs;
903 uint wait_cnt = 1000;
904
905 if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
ff31c54c 906 W_REG(&cc->sromaddress, wordoff * 2);
a9533e7e 907 if (cmd == SRC_OP_WRITE)
ff31c54c 908 W_REG(&cc->sromdata, data);
a9533e7e
HP
909 }
910
ff31c54c 911 W_REG(&cc->sromcontrol, SRC_START | cmd);
a9533e7e
HP
912
913 while (wait_cnt--) {
ff31c54c 914 if ((R_REG(&cc->sromcontrol) & SRC_BUSY) == 0)
a9533e7e
HP
915 break;
916 }
917
918 if (!wait_cnt) {
a9533e7e
HP
919 return 0xffff;
920 }
921 if (cmd == SRC_OP_READ)
ff31c54c 922 return (u16) R_REG(&cc->sromdata);
a9533e7e
HP
923 else
924 return 0xffff;
925}
926
f3171549
SF
927static inline void ltoh16_buf(u16 *buf, unsigned int size)
928{
929 for (size /= 2; size; size--)
930 *(buf + size) = le16_to_cpu(*(buf + size));
931}
932
933static inline void htol16_buf(u16 *buf, unsigned int size)
934{
935 for (size /= 2; size; size--)
936 *(buf + size) = cpu_to_le16(*(buf + size));
937}
938
a9533e7e
HP
939/*
940 * Read in and validate sprom.
941 * Return 0 on success, nonzero on error.
942 */
943static int
26bcc181 944sprom_read_pci(si_t *sih, u16 *sprom, uint wordoff,
7d4df48e 945 u16 *buf, uint nwords, bool check_crc)
a9533e7e
HP
946{
947 int err = 0;
948 uint i;
949 void *ccregs = NULL;
950
951 /* read the sprom */
952 for (i = 0; i < nwords; i++) {
953
954 if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
955 /* use indirect since direct is too slow on QT */
956 if ((sih->cccaps & CC_CAP_SROM) == 0)
957 return 1;
958
36ef9a1e 959 ccregs = (void *)((u8 *) sprom - CC_SROM_OTP);
a9533e7e 960 buf[i] =
26bcc181 961 srom_cc_cmd(sih, ccregs, SRC_OP_READ,
a9533e7e
HP
962 wordoff + i, 0);
963
964 } else {
965 if (ISSIM_ENAB(sih))
ff31c54c 966 buf[i] = R_REG(&sprom[wordoff + i]);
a9533e7e 967
ff31c54c 968 buf[i] = R_REG(&sprom[wordoff + i]);
a9533e7e
HP
969 }
970
971 }
972
973 /* bypass crc checking for simulation to allow srom hack */
974 if (ISSIM_ENAB(sih))
975 return err;
976
977 if (check_crc) {
978
979 if (buf[0] == 0xffff) {
980 /* The hardware thinks that an srom that starts with 0xffff
981 * is blank, regardless of the rest of the content, so declare
982 * it bad.
983 */
a9533e7e
HP
984 return 1;
985 }
986
987 /* fixup the endianness so crc8 will pass */
988 htol16_buf(buf, nwords * 2);
b33f0e28 989 if (bcm_crc8((u8 *) buf, nwords * 2, CRC8_INIT_VALUE) !=
a9533e7e
HP
990 CRC8_GOOD_VALUE) {
991 /* DBG only pci always read srom4 first, then srom8/9 */
a9533e7e
HP
992 err = 1;
993 }
994 /* now correct the endianness of the byte array */
995 ltoh16_buf(buf, nwords * 2);
996 }
997 return err;
998}
999
1000#if defined(BCMNVRAMR)
26bcc181 1001static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz)
a9533e7e 1002{
36ef9a1e 1003 u8 *otp;
a9533e7e
HP
1004 uint sz = OTP_SZ_MAX / 2; /* size in words */
1005 int err = 0;
1006
5fcc1fcb 1007 otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
ca8c1e59 1008 if (otp == NULL) {
b74ac12e 1009 return -EBADE;
a9533e7e
HP
1010 }
1011
7d4df48e 1012 err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
a9533e7e 1013
02160695 1014 memcpy(buf, otp, bufsz);
a9533e7e 1015
46d994b1 1016 kfree(otp);
a9533e7e
HP
1017
1018 /* Check CRC */
1019 if (buf[0] == 0xffff) {
1020 /* The hardware thinks that an srom that starts with 0xffff
1021 * is blank, regardless of the rest of the content, so declare
1022 * it bad.
1023 */
a9533e7e
HP
1024 return 1;
1025 }
1026
1027 /* fixup the endianness so crc8 will pass */
1028 htol16_buf(buf, bufsz);
b33f0e28 1029 if (bcm_crc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
a9533e7e 1030 CRC8_GOOD_VALUE) {
a9533e7e
HP
1031 err = 1;
1032 }
1033 /* now correct the endianness of the byte array */
1034 ltoh16_buf(buf, bufsz);
1035
1036 return err;
1037}
1038#endif /* defined(BCMNVRAMR) */
1039/*
1040* Create variable table from memory.
1041* Return 0 on success, nonzero on error.
1042*/
26bcc181 1043static int initvars_table(char *start, char *end,
e69284f2 1044 char **vars, uint *count)
0d2f0724 1045{
a9533e7e
HP
1046 int c = (int)(end - start);
1047
1048 /* do it only when there is more than just the null string */
1049 if (c > 1) {
5fcc1fcb 1050 char *vp = kmalloc(c, GFP_ATOMIC);
a9533e7e 1051 if (!vp)
e10d82d4 1052 return -ENOMEM;
02160695 1053 memcpy(vp, start, c);
a9533e7e
HP
1054 *vars = vp;
1055 *count = c;
1056 } else {
1057 *vars = NULL;
1058 *count = 0;
1059 }
1060
1061 return 0;
1062}
1063
1064/*
1065 * Find variables with <devpath> from flash. 'base' points to the beginning
1066 * of the table upon enter and to the end of the table upon exit when success.
1067 * Return 0 on success, nonzero on error.
1068 */
26bcc181 1069static int initvars_flash(si_t *sih, char **base, uint len)
a2627bc0 1070{
a9533e7e
HP
1071 char *vp = *base;
1072 char *flash;
1073 int err;
1074 char *s;
1075 uint l, dl, copy_len;
1076 char devpath[SI_DEVPATH_BUFSZ];
1077
1078 /* allocate memory and read in flash */
5fcc1fcb 1079 flash = kmalloc(NVRAM_SPACE, GFP_ATOMIC);
ca8c1e59 1080 if (!flash)
e10d82d4 1081 return -ENOMEM;
ca8c1e59
JC
1082 err = nvram_getall(flash, NVRAM_SPACE);
1083 if (err)
a9533e7e
HP
1084 goto exit;
1085
b21c892d 1086 ai_devpath(sih, devpath, sizeof(devpath));
a9533e7e
HP
1087
1088 /* grab vars with the <devpath> prefix in name */
1089 dl = strlen(devpath);
1090 for (s = flash; s && *s; s += l + 1) {
1091 l = strlen(s);
1092
1093 /* skip non-matching variable */
1094 if (strncmp(s, devpath, dl))
1095 continue;
1096
1097 /* is there enough room to copy? */
1098 copy_len = l - dl + 1;
1099 if (len < copy_len) {
e10d82d4 1100 err = -EOVERFLOW;
a9533e7e
HP
1101 goto exit;
1102 }
1103
1104 /* no prefix, just the name=value */
1105 strncpy(vp, &s[dl], copy_len);
1106 vp += copy_len;
1107 len -= copy_len;
1108 }
1109
1110 /* add null string as terminator */
1111 if (len < 1) {
e10d82d4 1112 err = -EOVERFLOW;
a9533e7e
HP
1113 goto exit;
1114 }
1115 *vp++ = '\0';
1116
1117 *base = vp;
1118
182acb3c 1119 exit: kfree(flash);
a9533e7e
HP
1120 return err;
1121}
1122
1123/*
1124 * Initialize nonvolatile variable table from flash.
1125 * Return 0 on success, nonzero on error.
1126 */
0d2f0724 1127static int initvars_flash_si(si_t *sih, char **vars, uint *count)
a2627bc0 1128{
a9533e7e
HP
1129 char *vp, *base;
1130 int err;
1131
5fcc1fcb 1132 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
a9533e7e 1133 if (!vp)
e10d82d4 1134 return -ENOMEM;
a9533e7e 1135
26bcc181 1136 err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
ca8c1e59 1137 if (err == 0)
26bcc181 1138 err = initvars_table(base, vp, vars, count);
a9533e7e 1139
182acb3c 1140 kfree(base);
a9533e7e
HP
1141
1142 return err;
1143}
1144
1145/* Parse SROM and create name=value pairs. 'srom' points to
1146 * the SROM word array. 'off' specifies the offset of the
1147 * first word 'srom' points to, which should be either 0 or
1148 * SROM3_SWRG_OFF (full SROM or software region).
1149 */
1150
7d4df48e 1151static uint mask_shift(u16 mask)
a9533e7e
HP
1152{
1153 uint i;
1154 for (i = 0; i < (sizeof(mask) << 3); i++) {
1155 if (mask & (1 << i))
1156 return i;
1157 }
a9533e7e
HP
1158 return 0;
1159}
1160
7d4df48e 1161static uint mask_width(u16 mask)
a9533e7e
HP
1162{
1163 int i;
1164 for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
1165 if (mask & (1 << i))
1166 return (uint) (i - mask_shift(mask) + 1);
1167 }
a9533e7e
HP
1168 return 0;
1169}
1170
0d2f0724
GKH
1171static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b)
1172{
7d4df48e 1173 u16 w;
66cbd3ab 1174 u32 val;
a9533e7e
HP
1175 const sromvar_t *srv;
1176 uint width;
1177 uint flags;
66cbd3ab 1178 u32 sr = (1 << sromrev);
a9533e7e
HP
1179
1180 varbuf_append(b, "sromrev=%d", sromrev);
1181
1182 for (srv = pci_sromvars; srv->name != NULL; srv++) {
1183 const char *name;
1184
1185 if ((srv->revmask & sr) == 0)
1186 continue;
1187
1188 if (srv->off < off)
1189 continue;
1190
1191 flags = srv->flags;
1192 name = srv->name;
1193
1194 /* This entry is for mfgc only. Don't generate param for it, */
1195 if (flags & SRFL_NOVAR)
1196 continue;
1197
1198 if (flags & SRFL_ETHADDR) {
a44d4236 1199 u8 ea[ETH_ALEN];
a9533e7e 1200
a44d4236
AS
1201 ea[0] = (srom[srv->off - off] >> 8) & 0xff;
1202 ea[1] = srom[srv->off - off] & 0xff;
1203 ea[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
1204 ea[3] = srom[srv->off + 1 - off] & 0xff;
1205 ea[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
1206 ea[5] = srom[srv->off + 2 - off] & 0xff;
a9533e7e 1207
a44d4236 1208 varbuf_append(b, "%s=%pM", name, ea);
a9533e7e 1209 } else {
a9533e7e
HP
1210 w = srom[srv->off - off];
1211 val = (w & srv->mask) >> mask_shift(srv->mask);
1212 width = mask_width(srv->mask);
1213
1214 while (srv->flags & SRFL_MORE) {
1215 srv++;
a9533e7e
HP
1216 if (srv->off == 0 || srv->off < off)
1217 continue;
1218
a9533e7e
HP
1219 w = srom[srv->off - off];
1220 val +=
1221 ((w & srv->mask) >> mask_shift(srv->
1222 mask)) <<
1223 width;
1224 width += mask_width(srv->mask);
1225 }
1226
1227 if ((flags & SRFL_NOFFS)
1228 && ((int)val == (1 << width) - 1))
1229 continue;
1230
1231 if (flags & SRFL_CCODE) {
1232 if (val == 0)
1233 varbuf_append(b, "ccode=");
1234 else
1235 varbuf_append(b, "ccode=%c%c",
1236 (val >> 8), (val & 0xff));
1237 }
1238 /* LED Powersave duty cycle has to be scaled:
1239 *(oncount >> 24) (offcount >> 8)
1240 */
1241 else if (flags & SRFL_LEDDC) {
66cbd3ab 1242 u32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
a9533e7e
HP
1243 (((val & 0xff)) << 8); /* offcount */
1244 varbuf_append(b, "leddc=%d", w32);
1245 } else if (flags & SRFL_PRHEX)
1246 varbuf_append(b, "%s=0x%x", name, val);
1247 else if ((flags & SRFL_PRSIGN)
1248 && (val & (1 << (width - 1))))
1249 varbuf_append(b, "%s=%d", name,
1250 (int)(val | (~0 << width)));
1251 else
1252 varbuf_append(b, "%s=%u", name, val);
1253 }
1254 }
1255
1256 if (sromrev >= 4) {
1257 /* Do per-path variables */
1258 uint p, pb, psz;
1259
1260 if (sromrev >= 8) {
1261 pb = SROM8_PATH0;
1262 psz = SROM8_PATH1 - SROM8_PATH0;
1263 } else {
1264 pb = SROM4_PATH0;
1265 psz = SROM4_PATH1 - SROM4_PATH0;
1266 }
1267
1268 for (p = 0; p < MAX_PATH_SROM; p++) {
1269 for (srv = perpath_pci_sromvars; srv->name != NULL;
1270 srv++) {
1271 if ((srv->revmask & sr) == 0)
1272 continue;
1273
1274 if (pb + srv->off < off)
1275 continue;
1276
1277 /* This entry is for mfgc only. Don't generate param for it, */
1278 if (srv->flags & SRFL_NOVAR)
1279 continue;
1280
1281 w = srom[pb + srv->off - off];
a9533e7e
HP
1282 val = (w & srv->mask) >> mask_shift(srv->mask);
1283 width = mask_width(srv->mask);
1284
1285 /* Cheating: no per-path var is more than 1 word */
1286
1287 if ((srv->flags & SRFL_NOFFS)
1288 && ((int)val == (1 << width) - 1))
1289 continue;
1290
1291 if (srv->flags & SRFL_PRHEX)
1292 varbuf_append(b, "%s%d=0x%x", srv->name,
1293 p, val);
1294 else
1295 varbuf_append(b, "%s%d=%d", srv->name,
1296 p, val);
1297 }
1298 pb += psz;
1299 }
1300 }
1301}
1302
1303/*
1304 * Initialize nonvolatile variable table from sprom.
1305 * Return 0 on success, nonzero on error.
1306 */
0d2f0724
GKH
1307static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
1308{
7d4df48e 1309 u16 *srom, *sromwindow;
36ef9a1e 1310 u8 sromrev = 0;
66cbd3ab 1311 u32 sr;
a9533e7e
HP
1312 varbuf_t b;
1313 char *vp, *base = NULL;
0965ae88 1314 bool flash = false;
a9533e7e
HP
1315 int err = 0;
1316
1317 /*
1318 * Apply CRC over SROM content regardless SROM is present or not,
25985edc 1319 * and use variable <devpath>sromrev's existence in flash to decide
a9533e7e
HP
1320 * if we should return an error when CRC fails or read SROM variables
1321 * from flash.
1322 */
5fcc1fcb 1323 srom = kmalloc(SROM_MAX, GFP_ATOMIC);
a9533e7e
HP
1324 if (!srom)
1325 return -2;
1326
7d4df48e 1327 sromwindow = (u16 *) SROM_OFFSET(sih);
b21c892d 1328 if (ai_is_sprom_available(sih)) {
a9533e7e 1329 err =
26bcc181 1330 sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
0f0881b0 1331 true);
a9533e7e
HP
1332
1333 if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
1334 (((sih->buscoretype == PCIE_CORE_ID)
1335 && (sih->buscorerev >= 6))
1336 || ((sih->buscoretype == PCI_CORE_ID)
1337 && (sih->buscorerev >= 0xe)))) {
1338 /* sromrev >= 4, read more */
1339 err =
26bcc181 1340 sprom_read_pci(sih, sromwindow, 0, srom,
0f0881b0 1341 SROM4_WORDS, true);
a9533e7e 1342 sromrev = srom[SROM4_CRCREV] & 0xff;
a9533e7e
HP
1343 } else if (err == 0) {
1344 /* srom is good and is rev < 4 */
1345 /* top word of sprom contains version and crc8 */
1346 sromrev = srom[SROM_CRCREV] & 0xff;
1347 /* bcm4401 sroms misprogrammed */
1348 if (sromrev == 0x10)
1349 sromrev = 1;
1350 }
1351 }
1352#if defined(BCMNVRAMR)
1353 /* Use OTP if SPROM not available */
a9533e7e 1354 else {
26bcc181
AS
1355 err = otp_read_pci(sih, srom, SROM_MAX);
1356 if (err == 0)
1357 /* OTP only contain SROM rev8/rev9 for now */
1358 sromrev = srom[SROM4_CRCREV] & 0xff;
1359 else
1360 err = 1;
a9533e7e 1361 }
26bcc181
AS
1362#else
1363 else
1364 err = 1;
1365#endif
a9533e7e 1366
26bcc181
AS
1367 /*
1368 * We want internal/wltest driver to come up with default
1369 * sromvars so we can program a blank SPROM/OTP.
a9533e7e
HP
1370 */
1371 if (err) {
1372 char *value;
66cbd3ab 1373 u32 val;
a9533e7e
HP
1374 val = 0;
1375
b21c892d 1376 value = ai_getdevpathvar(sih, "sromrev");
ca8c1e59 1377 if (value) {
36ef9a1e 1378 sromrev = (u8) simple_strtoul(value, NULL, 0);
0f0881b0 1379 flash = true;
a9533e7e
HP
1380 goto varscont;
1381 }
1382
b21c892d 1383 value = ai_getnvramflvar(sih, "sromrev");
ca8c1e59 1384 if (value) {
a9533e7e
HP
1385 err = 0;
1386 goto errout;
1387 }
1388
1389 {
1390 err = -1;
1391 goto errout;
1392 }
1393 }
1394
1395 varscont:
1396 /* Bitmask for the sromrev */
1397 sr = 1 << sromrev;
1398
1399 /* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */
1400 if ((sr & 0x33e) == 0) {
1401 err = -2;
1402 goto errout;
1403 }
1404
5fcc1fcb 1405 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
a9533e7e
HP
1406 if (!vp) {
1407 err = -2;
1408 goto errout;
1409 }
1410
1411 /* read variables from flash */
1412 if (flash) {
26bcc181 1413 err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
ca8c1e59 1414 if (err)
a9533e7e
HP
1415 goto errout;
1416 goto varsdone;
1417 }
1418
1419 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
1420
1421 /* parse SROM into name=value pairs. */
1422 _initvars_srom_pci(sromrev, srom, 0, &b);
1423
1424 /* final nullbyte terminator */
a9533e7e
HP
1425 vp = b.buf;
1426 *vp++ = '\0';
1427
a9533e7e 1428 varsdone:
26bcc181 1429 err = initvars_table(base, vp, vars, count);
a9533e7e
HP
1430
1431 errout:
1432 if (base)
182acb3c 1433 kfree(base);
a9533e7e 1434
182acb3c 1435 kfree(srom);
a9533e7e
HP
1436 return err;
1437}
1438
a9533e7e 1439
26bcc181 1440static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *varsz)
0d2f0724 1441{
a9533e7e
HP
1442 /* Search flash nvram section for srom variables */
1443 return initvars_flash_si(sih, vars, varsz);
1444}