]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/mips/bcm47xx/sprom.c
2 * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
3 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
4 * Copyright (C) 2006 Michael Buesch <m@bues.ch>
5 * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
6 * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <bcm47xx_nvram.h>
31 #include <linux/if_ether.h>
32 #include <linux/etherdevice.h>
34 static void create_key(const char *prefix
, const char *postfix
,
35 const char *name
, char *buf
, int len
)
37 if (prefix
&& postfix
)
38 snprintf(buf
, len
, "%s%s%s", prefix
, name
, postfix
);
40 snprintf(buf
, len
, "%s%s", prefix
, name
);
42 snprintf(buf
, len
, "%s%s", name
, postfix
);
44 snprintf(buf
, len
, "%s", name
);
47 static int get_nvram_var(const char *prefix
, const char *postfix
,
48 const char *name
, char *buf
, int len
, bool fallback
)
53 create_key(prefix
, postfix
, name
, key
, sizeof(key
));
55 err
= bcm47xx_nvram_getenv(key
, buf
, len
);
56 if (fallback
&& err
== -ENOENT
&& prefix
) {
57 create_key(NULL
, postfix
, name
, key
, sizeof(key
));
58 err
= bcm47xx_nvram_getenv(key
, buf
, len
);
63 #define NVRAM_READ_VAL(type) \
64 static void nvram_read_ ## type (const char *prefix, \
65 const char *postfix, const char *name, \
66 type *val, type allset, bool fallback) \
72 err = get_nvram_var(prefix, postfix, name, buf, sizeof(buf), \
76 err = kstrto ## type(strim(buf), 0, &var); \
78 pr_warn("can not parse nvram name %s%s%s with value %s got %i\n", \
79 prefix, name, postfix, buf, err); \
82 if (allset && var == allset) \
94 static void nvram_read_u32_2(const char *prefix
, const char *name
,
95 u16
*val_lo
, u16
*val_hi
, bool fallback
)
101 err
= get_nvram_var(prefix
, NULL
, name
, buf
, sizeof(buf
), fallback
);
104 err
= kstrtou32(strim(buf
), 0, &val
);
106 pr_warn("can not parse nvram name %s%s with value %s got %i\n",
107 prefix
, name
, buf
, err
);
110 *val_lo
= (val
& 0x0000FFFFU
);
111 *val_hi
= (val
& 0xFFFF0000U
) >> 16;
114 static void nvram_read_leddc(const char *prefix
, const char *name
,
115 u8
*leddc_on_time
, u8
*leddc_off_time
,
122 err
= get_nvram_var(prefix
, NULL
, name
, buf
, sizeof(buf
), fallback
);
125 err
= kstrtou32(strim(buf
), 0, &val
);
127 pr_warn("can not parse nvram name %s%s with value %s got %i\n",
128 prefix
, name
, buf
, err
);
132 if (val
== 0xffff || val
== 0xffffffff)
135 *leddc_on_time
= val
& 0xff;
136 *leddc_off_time
= (val
>> 16) & 0xff;
139 static void bcm47xx_nvram_parse_macaddr(char *buf
, u8 macaddr
[6])
141 if (strchr(buf
, ':'))
142 sscanf(buf
, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr
[0],
143 &macaddr
[1], &macaddr
[2], &macaddr
[3], &macaddr
[4],
145 else if (strchr(buf
, '-'))
146 sscanf(buf
, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr
[0],
147 &macaddr
[1], &macaddr
[2], &macaddr
[3], &macaddr
[4],
150 pr_warn("Can not parse mac address: %s\n", buf
);
153 static void nvram_read_macaddr(const char *prefix
, const char *name
,
154 u8 val
[6], bool fallback
)
159 err
= get_nvram_var(prefix
, NULL
, name
, buf
, sizeof(buf
), fallback
);
163 bcm47xx_nvram_parse_macaddr(buf
, val
);
166 static void nvram_read_alpha2(const char *prefix
, const char *name
,
167 char val
[2], bool fallback
)
172 err
= get_nvram_var(prefix
, NULL
, name
, buf
, sizeof(buf
), fallback
);
177 if (strlen(buf
) > 2) {
178 pr_warn("alpha2 is too long %s\n", buf
);
184 static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom
*sprom
,
185 const char *prefix
, bool fallback
)
187 nvram_read_u16(prefix
, NULL
, "devid", &sprom
->dev_id
, 0, fallback
);
188 nvram_read_u8(prefix
, NULL
, "ledbh0", &sprom
->gpio0
, 0xff, fallback
);
189 nvram_read_u8(prefix
, NULL
, "ledbh1", &sprom
->gpio1
, 0xff, fallback
);
190 nvram_read_u8(prefix
, NULL
, "ledbh2", &sprom
->gpio2
, 0xff, fallback
);
191 nvram_read_u8(prefix
, NULL
, "ledbh3", &sprom
->gpio3
, 0xff, fallback
);
192 nvram_read_u8(prefix
, NULL
, "aa2g", &sprom
->ant_available_bg
, 0,
194 nvram_read_u8(prefix
, NULL
, "aa5g", &sprom
->ant_available_a
, 0,
196 nvram_read_s8(prefix
, NULL
, "ag0", &sprom
->antenna_gain
.a0
, 0,
198 nvram_read_s8(prefix
, NULL
, "ag1", &sprom
->antenna_gain
.a1
, 0,
200 nvram_read_alpha2(prefix
, "ccode", sprom
->alpha2
, fallback
);
203 static void bcm47xx_fill_sprom_r12389(struct ssb_sprom
*sprom
,
204 const char *prefix
, bool fallback
)
206 nvram_read_u16(prefix
, NULL
, "pa0b0", &sprom
->pa0b0
, 0, fallback
);
207 nvram_read_u16(prefix
, NULL
, "pa0b1", &sprom
->pa0b1
, 0, fallback
);
208 nvram_read_u16(prefix
, NULL
, "pa0b2", &sprom
->pa0b2
, 0, fallback
);
209 nvram_read_u8(prefix
, NULL
, "pa0itssit", &sprom
->itssi_bg
, 0, fallback
);
210 nvram_read_u8(prefix
, NULL
, "pa0maxpwr", &sprom
->maxpwr_bg
, 0,
212 nvram_read_u16(prefix
, NULL
, "pa1b0", &sprom
->pa1b0
, 0, fallback
);
213 nvram_read_u16(prefix
, NULL
, "pa1b1", &sprom
->pa1b1
, 0, fallback
);
214 nvram_read_u16(prefix
, NULL
, "pa1b2", &sprom
->pa1b2
, 0, fallback
);
215 nvram_read_u8(prefix
, NULL
, "pa1itssit", &sprom
->itssi_a
, 0, fallback
);
216 nvram_read_u8(prefix
, NULL
, "pa1maxpwr", &sprom
->maxpwr_a
, 0, fallback
);
219 static void bcm47xx_fill_sprom_r1(struct ssb_sprom
*sprom
, const char *prefix
,
222 nvram_read_u16(prefix
, NULL
, "boardflags", &sprom
->boardflags_lo
, 0,
224 nvram_read_u8(prefix
, NULL
, "cc", &sprom
->country_code
, 0, fallback
);
227 static void bcm47xx_fill_sprom_r2389(struct ssb_sprom
*sprom
,
228 const char *prefix
, bool fallback
)
230 nvram_read_u8(prefix
, NULL
, "opo", &sprom
->opo
, 0, fallback
);
231 nvram_read_u16(prefix
, NULL
, "pa1lob0", &sprom
->pa1lob0
, 0, fallback
);
232 nvram_read_u16(prefix
, NULL
, "pa1lob1", &sprom
->pa1lob1
, 0, fallback
);
233 nvram_read_u16(prefix
, NULL
, "pa1lob2", &sprom
->pa1lob2
, 0, fallback
);
234 nvram_read_u16(prefix
, NULL
, "pa1hib0", &sprom
->pa1hib0
, 0, fallback
);
235 nvram_read_u16(prefix
, NULL
, "pa1hib1", &sprom
->pa1hib1
, 0, fallback
);
236 nvram_read_u16(prefix
, NULL
, "pa1hib2", &sprom
->pa1hib2
, 0, fallback
);
237 nvram_read_u8(prefix
, NULL
, "pa1lomaxpwr", &sprom
->maxpwr_al
, 0,
239 nvram_read_u8(prefix
, NULL
, "pa1himaxpwr", &sprom
->maxpwr_ah
, 0,
243 static void bcm47xx_fill_sprom_r389(struct ssb_sprom
*sprom
, const char *prefix
,
246 nvram_read_u8(prefix
, NULL
, "bxa2g", &sprom
->bxa2g
, 0, fallback
);
247 nvram_read_u8(prefix
, NULL
, "rssisav2g", &sprom
->rssisav2g
, 0,
249 nvram_read_u8(prefix
, NULL
, "rssismc2g", &sprom
->rssismc2g
, 0,
251 nvram_read_u8(prefix
, NULL
, "rssismf2g", &sprom
->rssismf2g
, 0,
253 nvram_read_u8(prefix
, NULL
, "bxa5g", &sprom
->bxa5g
, 0, fallback
);
254 nvram_read_u8(prefix
, NULL
, "rssisav5g", &sprom
->rssisav5g
, 0,
256 nvram_read_u8(prefix
, NULL
, "rssismc5g", &sprom
->rssismc5g
, 0,
258 nvram_read_u8(prefix
, NULL
, "rssismf5g", &sprom
->rssismf5g
, 0,
260 nvram_read_u8(prefix
, NULL
, "tri2g", &sprom
->tri2g
, 0, fallback
);
261 nvram_read_u8(prefix
, NULL
, "tri5g", &sprom
->tri5g
, 0, fallback
);
262 nvram_read_u8(prefix
, NULL
, "tri5gl", &sprom
->tri5gl
, 0, fallback
);
263 nvram_read_u8(prefix
, NULL
, "tri5gh", &sprom
->tri5gh
, 0, fallback
);
264 nvram_read_s8(prefix
, NULL
, "rxpo2g", &sprom
->rxpo2g
, 0, fallback
);
265 nvram_read_s8(prefix
, NULL
, "rxpo5g", &sprom
->rxpo5g
, 0, fallback
);
268 static void bcm47xx_fill_sprom_r3(struct ssb_sprom
*sprom
, const char *prefix
,
271 nvram_read_u8(prefix
, NULL
, "regrev", &sprom
->regrev
, 0, fallback
);
272 nvram_read_leddc(prefix
, "leddc", &sprom
->leddc_on_time
,
273 &sprom
->leddc_off_time
, fallback
);
276 static void bcm47xx_fill_sprom_r4589(struct ssb_sprom
*sprom
,
277 const char *prefix
, bool fallback
)
279 nvram_read_u8(prefix
, NULL
, "regrev", &sprom
->regrev
, 0, fallback
);
280 nvram_read_s8(prefix
, NULL
, "ag2", &sprom
->antenna_gain
.a2
, 0,
282 nvram_read_s8(prefix
, NULL
, "ag3", &sprom
->antenna_gain
.a3
, 0,
284 nvram_read_u8(prefix
, NULL
, "txchain", &sprom
->txchain
, 0xf, fallback
);
285 nvram_read_u8(prefix
, NULL
, "rxchain", &sprom
->rxchain
, 0xf, fallback
);
286 nvram_read_u8(prefix
, NULL
, "antswitch", &sprom
->antswitch
, 0xff,
288 nvram_read_leddc(prefix
, "leddc", &sprom
->leddc_on_time
,
289 &sprom
->leddc_off_time
, fallback
);
292 static void bcm47xx_fill_sprom_r458(struct ssb_sprom
*sprom
, const char *prefix
,
295 nvram_read_u16(prefix
, NULL
, "cck2gpo", &sprom
->cck2gpo
, 0, fallback
);
296 nvram_read_u32(prefix
, NULL
, "ofdm2gpo", &sprom
->ofdm2gpo
, 0, fallback
);
297 nvram_read_u32(prefix
, NULL
, "ofdm5gpo", &sprom
->ofdm5gpo
, 0, fallback
);
298 nvram_read_u32(prefix
, NULL
, "ofdm5glpo", &sprom
->ofdm5glpo
, 0,
300 nvram_read_u32(prefix
, NULL
, "ofdm5ghpo", &sprom
->ofdm5ghpo
, 0,
302 nvram_read_u16(prefix
, NULL
, "cddpo", &sprom
->cddpo
, 0, fallback
);
303 nvram_read_u16(prefix
, NULL
, "stbcpo", &sprom
->stbcpo
, 0, fallback
);
304 nvram_read_u16(prefix
, NULL
, "bw40po", &sprom
->bw40po
, 0, fallback
);
305 nvram_read_u16(prefix
, NULL
, "bwduppo", &sprom
->bwduppo
, 0, fallback
);
306 nvram_read_u16(prefix
, NULL
, "mcs2gpo0", &sprom
->mcs2gpo
[0], 0,
308 nvram_read_u16(prefix
, NULL
, "mcs2gpo1", &sprom
->mcs2gpo
[1], 0,
310 nvram_read_u16(prefix
, NULL
, "mcs2gpo2", &sprom
->mcs2gpo
[2], 0,
312 nvram_read_u16(prefix
, NULL
, "mcs2gpo3", &sprom
->mcs2gpo
[3], 0,
314 nvram_read_u16(prefix
, NULL
, "mcs2gpo4", &sprom
->mcs2gpo
[4], 0,
316 nvram_read_u16(prefix
, NULL
, "mcs2gpo5", &sprom
->mcs2gpo
[5], 0,
318 nvram_read_u16(prefix
, NULL
, "mcs2gpo6", &sprom
->mcs2gpo
[6], 0,
320 nvram_read_u16(prefix
, NULL
, "mcs2gpo7", &sprom
->mcs2gpo
[7], 0,
322 nvram_read_u16(prefix
, NULL
, "mcs5gpo0", &sprom
->mcs5gpo
[0], 0,
324 nvram_read_u16(prefix
, NULL
, "mcs5gpo1", &sprom
->mcs5gpo
[1], 0,
326 nvram_read_u16(prefix
, NULL
, "mcs5gpo2", &sprom
->mcs5gpo
[2], 0,
328 nvram_read_u16(prefix
, NULL
, "mcs5gpo3", &sprom
->mcs5gpo
[3], 0,
330 nvram_read_u16(prefix
, NULL
, "mcs5gpo4", &sprom
->mcs5gpo
[4], 0,
332 nvram_read_u16(prefix
, NULL
, "mcs5gpo5", &sprom
->mcs5gpo
[5], 0,
334 nvram_read_u16(prefix
, NULL
, "mcs5gpo6", &sprom
->mcs5gpo
[6], 0,
336 nvram_read_u16(prefix
, NULL
, "mcs5gpo7", &sprom
->mcs5gpo
[7], 0,
338 nvram_read_u16(prefix
, NULL
, "mcs5glpo0", &sprom
->mcs5glpo
[0], 0,
340 nvram_read_u16(prefix
, NULL
, "mcs5glpo1", &sprom
->mcs5glpo
[1], 0,
342 nvram_read_u16(prefix
, NULL
, "mcs5glpo2", &sprom
->mcs5glpo
[2], 0,
344 nvram_read_u16(prefix
, NULL
, "mcs5glpo3", &sprom
->mcs5glpo
[3], 0,
346 nvram_read_u16(prefix
, NULL
, "mcs5glpo4", &sprom
->mcs5glpo
[4], 0,
348 nvram_read_u16(prefix
, NULL
, "mcs5glpo5", &sprom
->mcs5glpo
[5], 0,
350 nvram_read_u16(prefix
, NULL
, "mcs5glpo6", &sprom
->mcs5glpo
[6], 0,
352 nvram_read_u16(prefix
, NULL
, "mcs5glpo7", &sprom
->mcs5glpo
[7], 0,
354 nvram_read_u16(prefix
, NULL
, "mcs5ghpo0", &sprom
->mcs5ghpo
[0], 0,
356 nvram_read_u16(prefix
, NULL
, "mcs5ghpo1", &sprom
->mcs5ghpo
[1], 0,
358 nvram_read_u16(prefix
, NULL
, "mcs5ghpo2", &sprom
->mcs5ghpo
[2], 0,
360 nvram_read_u16(prefix
, NULL
, "mcs5ghpo3", &sprom
->mcs5ghpo
[3], 0,
362 nvram_read_u16(prefix
, NULL
, "mcs5ghpo4", &sprom
->mcs5ghpo
[4], 0,
364 nvram_read_u16(prefix
, NULL
, "mcs5ghpo5", &sprom
->mcs5ghpo
[5], 0,
366 nvram_read_u16(prefix
, NULL
, "mcs5ghpo6", &sprom
->mcs5ghpo
[6], 0,
368 nvram_read_u16(prefix
, NULL
, "mcs5ghpo7", &sprom
->mcs5ghpo
[7], 0,
372 static void bcm47xx_fill_sprom_r45(struct ssb_sprom
*sprom
, const char *prefix
,
375 nvram_read_u8(prefix
, NULL
, "txpid2ga0", &sprom
->txpid2g
[0], 0,
377 nvram_read_u8(prefix
, NULL
, "txpid2ga1", &sprom
->txpid2g
[1], 0,
379 nvram_read_u8(prefix
, NULL
, "txpid2ga2", &sprom
->txpid2g
[2], 0,
381 nvram_read_u8(prefix
, NULL
, "txpid2ga3", &sprom
->txpid2g
[3], 0,
383 nvram_read_u8(prefix
, NULL
, "txpid5ga0", &sprom
->txpid5g
[0], 0,
385 nvram_read_u8(prefix
, NULL
, "txpid5ga1", &sprom
->txpid5g
[1], 0,
387 nvram_read_u8(prefix
, NULL
, "txpid5ga2", &sprom
->txpid5g
[2], 0,
389 nvram_read_u8(prefix
, NULL
, "txpid5ga3", &sprom
->txpid5g
[3], 0,
391 nvram_read_u8(prefix
, NULL
, "txpid5gla0", &sprom
->txpid5gl
[0], 0,
393 nvram_read_u8(prefix
, NULL
, "txpid5gla1", &sprom
->txpid5gl
[1], 0,
395 nvram_read_u8(prefix
, NULL
, "txpid5gla2", &sprom
->txpid5gl
[2], 0,
397 nvram_read_u8(prefix
, NULL
, "txpid5gla3", &sprom
->txpid5gl
[3], 0,
399 nvram_read_u8(prefix
, NULL
, "txpid5gha0", &sprom
->txpid5gh
[0], 0,
401 nvram_read_u8(prefix
, NULL
, "txpid5gha1", &sprom
->txpid5gh
[1], 0,
403 nvram_read_u8(prefix
, NULL
, "txpid5gha2", &sprom
->txpid5gh
[2], 0,
405 nvram_read_u8(prefix
, NULL
, "txpid5gha3", &sprom
->txpid5gh
[3], 0,
409 static void bcm47xx_fill_sprom_r89(struct ssb_sprom
*sprom
, const char *prefix
,
412 nvram_read_u8(prefix
, NULL
, "tssipos2g", &sprom
->fem
.ghz2
.tssipos
, 0,
414 nvram_read_u8(prefix
, NULL
, "extpagain2g",
415 &sprom
->fem
.ghz2
.extpa_gain
, 0, fallback
);
416 nvram_read_u8(prefix
, NULL
, "pdetrange2g",
417 &sprom
->fem
.ghz2
.pdet_range
, 0, fallback
);
418 nvram_read_u8(prefix
, NULL
, "triso2g", &sprom
->fem
.ghz2
.tr_iso
, 0,
420 nvram_read_u8(prefix
, NULL
, "antswctl2g", &sprom
->fem
.ghz2
.antswlut
, 0,
422 nvram_read_u8(prefix
, NULL
, "tssipos5g", &sprom
->fem
.ghz5
.tssipos
, 0,
424 nvram_read_u8(prefix
, NULL
, "extpagain5g",
425 &sprom
->fem
.ghz5
.extpa_gain
, 0, fallback
);
426 nvram_read_u8(prefix
, NULL
, "pdetrange5g",
427 &sprom
->fem
.ghz5
.pdet_range
, 0, fallback
);
428 nvram_read_u8(prefix
, NULL
, "triso5g", &sprom
->fem
.ghz5
.tr_iso
, 0,
430 nvram_read_u8(prefix
, NULL
, "antswctl5g", &sprom
->fem
.ghz5
.antswlut
, 0,
432 nvram_read_u8(prefix
, NULL
, "tempthresh", &sprom
->tempthresh
, 0,
434 nvram_read_u8(prefix
, NULL
, "tempoffset", &sprom
->tempoffset
, 0,
436 nvram_read_u16(prefix
, NULL
, "rawtempsense", &sprom
->rawtempsense
, 0,
438 nvram_read_u8(prefix
, NULL
, "measpower", &sprom
->measpower
, 0,
440 nvram_read_u8(prefix
, NULL
, "tempsense_slope",
441 &sprom
->tempsense_slope
, 0, fallback
);
442 nvram_read_u8(prefix
, NULL
, "tempcorrx", &sprom
->tempcorrx
, 0,
444 nvram_read_u8(prefix
, NULL
, "tempsense_option",
445 &sprom
->tempsense_option
, 0, fallback
);
446 nvram_read_u8(prefix
, NULL
, "freqoffset_corr",
447 &sprom
->freqoffset_corr
, 0, fallback
);
448 nvram_read_u8(prefix
, NULL
, "iqcal_swp_dis", &sprom
->iqcal_swp_dis
, 0,
450 nvram_read_u8(prefix
, NULL
, "hw_iqcal_en", &sprom
->hw_iqcal_en
, 0,
452 nvram_read_u8(prefix
, NULL
, "elna2g", &sprom
->elna2g
, 0, fallback
);
453 nvram_read_u8(prefix
, NULL
, "elna5g", &sprom
->elna5g
, 0, fallback
);
454 nvram_read_u8(prefix
, NULL
, "phycal_tempdelta",
455 &sprom
->phycal_tempdelta
, 0, fallback
);
456 nvram_read_u8(prefix
, NULL
, "temps_period", &sprom
->temps_period
, 0,
458 nvram_read_u8(prefix
, NULL
, "temps_hysteresis",
459 &sprom
->temps_hysteresis
, 0, fallback
);
460 nvram_read_u8(prefix
, NULL
, "measpower1", &sprom
->measpower1
, 0,
462 nvram_read_u8(prefix
, NULL
, "measpower2", &sprom
->measpower2
, 0,
464 nvram_read_u8(prefix
, NULL
, "rxgainerr2ga0",
465 &sprom
->rxgainerr2ga
[0], 0, fallback
);
466 nvram_read_u8(prefix
, NULL
, "rxgainerr2ga1",
467 &sprom
->rxgainerr2ga
[1], 0, fallback
);
468 nvram_read_u8(prefix
, NULL
, "rxgainerr2ga2",
469 &sprom
->rxgainerr2ga
[2], 0, fallback
);
470 nvram_read_u8(prefix
, NULL
, "rxgainerr5gla0",
471 &sprom
->rxgainerr5gla
[0], 0, fallback
);
472 nvram_read_u8(prefix
, NULL
, "rxgainerr5gla1",
473 &sprom
->rxgainerr5gla
[1], 0, fallback
);
474 nvram_read_u8(prefix
, NULL
, "rxgainerr5gla2",
475 &sprom
->rxgainerr5gla
[2], 0, fallback
);
476 nvram_read_u8(prefix
, NULL
, "rxgainerr5gma0",
477 &sprom
->rxgainerr5gma
[0], 0, fallback
);
478 nvram_read_u8(prefix
, NULL
, "rxgainerr5gma1",
479 &sprom
->rxgainerr5gma
[1], 0, fallback
);
480 nvram_read_u8(prefix
, NULL
, "rxgainerr5gma2",
481 &sprom
->rxgainerr5gma
[2], 0, fallback
);
482 nvram_read_u8(prefix
, NULL
, "rxgainerr5gha0",
483 &sprom
->rxgainerr5gha
[0], 0, fallback
);
484 nvram_read_u8(prefix
, NULL
, "rxgainerr5gha1",
485 &sprom
->rxgainerr5gha
[1], 0, fallback
);
486 nvram_read_u8(prefix
, NULL
, "rxgainerr5gha2",
487 &sprom
->rxgainerr5gha
[2], 0, fallback
);
488 nvram_read_u8(prefix
, NULL
, "rxgainerr5gua0",
489 &sprom
->rxgainerr5gua
[0], 0, fallback
);
490 nvram_read_u8(prefix
, NULL
, "rxgainerr5gua1",
491 &sprom
->rxgainerr5gua
[1], 0, fallback
);
492 nvram_read_u8(prefix
, NULL
, "rxgainerr5gua2",
493 &sprom
->rxgainerr5gua
[2], 0, fallback
);
494 nvram_read_u8(prefix
, NULL
, "noiselvl2ga0", &sprom
->noiselvl2ga
[0], 0,
496 nvram_read_u8(prefix
, NULL
, "noiselvl2ga1", &sprom
->noiselvl2ga
[1], 0,
498 nvram_read_u8(prefix
, NULL
, "noiselvl2ga2", &sprom
->noiselvl2ga
[2], 0,
500 nvram_read_u8(prefix
, NULL
, "noiselvl5gla0",
501 &sprom
->noiselvl5gla
[0], 0, fallback
);
502 nvram_read_u8(prefix
, NULL
, "noiselvl5gla1",
503 &sprom
->noiselvl5gla
[1], 0, fallback
);
504 nvram_read_u8(prefix
, NULL
, "noiselvl5gla2",
505 &sprom
->noiselvl5gla
[2], 0, fallback
);
506 nvram_read_u8(prefix
, NULL
, "noiselvl5gma0",
507 &sprom
->noiselvl5gma
[0], 0, fallback
);
508 nvram_read_u8(prefix
, NULL
, "noiselvl5gma1",
509 &sprom
->noiselvl5gma
[1], 0, fallback
);
510 nvram_read_u8(prefix
, NULL
, "noiselvl5gma2",
511 &sprom
->noiselvl5gma
[2], 0, fallback
);
512 nvram_read_u8(prefix
, NULL
, "noiselvl5gha0",
513 &sprom
->noiselvl5gha
[0], 0, fallback
);
514 nvram_read_u8(prefix
, NULL
, "noiselvl5gha1",
515 &sprom
->noiselvl5gha
[1], 0, fallback
);
516 nvram_read_u8(prefix
, NULL
, "noiselvl5gha2",
517 &sprom
->noiselvl5gha
[2], 0, fallback
);
518 nvram_read_u8(prefix
, NULL
, "noiselvl5gua0",
519 &sprom
->noiselvl5gua
[0], 0, fallback
);
520 nvram_read_u8(prefix
, NULL
, "noiselvl5gua1",
521 &sprom
->noiselvl5gua
[1], 0, fallback
);
522 nvram_read_u8(prefix
, NULL
, "noiselvl5gua2",
523 &sprom
->noiselvl5gua
[2], 0, fallback
);
524 nvram_read_u8(prefix
, NULL
, "pcieingress_war",
525 &sprom
->pcieingress_war
, 0, fallback
);
528 static void bcm47xx_fill_sprom_r9(struct ssb_sprom
*sprom
, const char *prefix
,
531 nvram_read_u16(prefix
, NULL
, "cckbw202gpo", &sprom
->cckbw202gpo
, 0,
533 nvram_read_u16(prefix
, NULL
, "cckbw20ul2gpo", &sprom
->cckbw20ul2gpo
, 0,
535 nvram_read_u32(prefix
, NULL
, "legofdmbw202gpo",
536 &sprom
->legofdmbw202gpo
, 0, fallback
);
537 nvram_read_u32(prefix
, NULL
, "legofdmbw20ul2gpo",
538 &sprom
->legofdmbw20ul2gpo
, 0, fallback
);
539 nvram_read_u32(prefix
, NULL
, "legofdmbw205glpo",
540 &sprom
->legofdmbw205glpo
, 0, fallback
);
541 nvram_read_u32(prefix
, NULL
, "legofdmbw20ul5glpo",
542 &sprom
->legofdmbw20ul5glpo
, 0, fallback
);
543 nvram_read_u32(prefix
, NULL
, "legofdmbw205gmpo",
544 &sprom
->legofdmbw205gmpo
, 0, fallback
);
545 nvram_read_u32(prefix
, NULL
, "legofdmbw20ul5gmpo",
546 &sprom
->legofdmbw20ul5gmpo
, 0, fallback
);
547 nvram_read_u32(prefix
, NULL
, "legofdmbw205ghpo",
548 &sprom
->legofdmbw205ghpo
, 0, fallback
);
549 nvram_read_u32(prefix
, NULL
, "legofdmbw20ul5ghpo",
550 &sprom
->legofdmbw20ul5ghpo
, 0, fallback
);
551 nvram_read_u32(prefix
, NULL
, "mcsbw202gpo", &sprom
->mcsbw202gpo
, 0,
553 nvram_read_u32(prefix
, NULL
, "mcsbw20ul2gpo", &sprom
->mcsbw20ul2gpo
, 0,
555 nvram_read_u32(prefix
, NULL
, "mcsbw402gpo", &sprom
->mcsbw402gpo
, 0,
557 nvram_read_u32(prefix
, NULL
, "mcsbw205glpo", &sprom
->mcsbw205glpo
, 0,
559 nvram_read_u32(prefix
, NULL
, "mcsbw20ul5glpo",
560 &sprom
->mcsbw20ul5glpo
, 0, fallback
);
561 nvram_read_u32(prefix
, NULL
, "mcsbw405glpo", &sprom
->mcsbw405glpo
, 0,
563 nvram_read_u32(prefix
, NULL
, "mcsbw205gmpo", &sprom
->mcsbw205gmpo
, 0,
565 nvram_read_u32(prefix
, NULL
, "mcsbw20ul5gmpo",
566 &sprom
->mcsbw20ul5gmpo
, 0, fallback
);
567 nvram_read_u32(prefix
, NULL
, "mcsbw405gmpo", &sprom
->mcsbw405gmpo
, 0,
569 nvram_read_u32(prefix
, NULL
, "mcsbw205ghpo", &sprom
->mcsbw205ghpo
, 0,
571 nvram_read_u32(prefix
, NULL
, "mcsbw20ul5ghpo",
572 &sprom
->mcsbw20ul5ghpo
, 0, fallback
);
573 nvram_read_u32(prefix
, NULL
, "mcsbw405ghpo", &sprom
->mcsbw405ghpo
, 0,
575 nvram_read_u16(prefix
, NULL
, "mcs32po", &sprom
->mcs32po
, 0, fallback
);
576 nvram_read_u16(prefix
, NULL
, "legofdm40duppo",
577 &sprom
->legofdm40duppo
, 0, fallback
);
578 nvram_read_u8(prefix
, NULL
, "sar2g", &sprom
->sar2g
, 0, fallback
);
579 nvram_read_u8(prefix
, NULL
, "sar5g", &sprom
->sar5g
, 0, fallback
);
582 static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom
*sprom
,
583 const char *prefix
, bool fallback
)
588 for (i
= 0; i
< ARRAY_SIZE(sprom
->core_pwr_info
); i
++) {
589 struct ssb_sprom_core_pwr_info
*pwr_info
= &sprom
->core_pwr_info
[i
];
590 snprintf(postfix
, sizeof(postfix
), "%i", i
);
591 nvram_read_u8(prefix
, postfix
, "maxp2ga",
592 &pwr_info
->maxpwr_2g
, 0, fallback
);
593 nvram_read_u8(prefix
, postfix
, "itt2ga",
594 &pwr_info
->itssi_2g
, 0, fallback
);
595 nvram_read_u8(prefix
, postfix
, "itt5ga",
596 &pwr_info
->itssi_5g
, 0, fallback
);
597 nvram_read_u16(prefix
, postfix
, "pa2gw0a",
598 &pwr_info
->pa_2g
[0], 0, fallback
);
599 nvram_read_u16(prefix
, postfix
, "pa2gw1a",
600 &pwr_info
->pa_2g
[1], 0, fallback
);
601 nvram_read_u16(prefix
, postfix
, "pa2gw2a",
602 &pwr_info
->pa_2g
[2], 0, fallback
);
603 nvram_read_u8(prefix
, postfix
, "maxp5ga",
604 &pwr_info
->maxpwr_5g
, 0, fallback
);
605 nvram_read_u8(prefix
, postfix
, "maxp5gha",
606 &pwr_info
->maxpwr_5gh
, 0, fallback
);
607 nvram_read_u8(prefix
, postfix
, "maxp5gla",
608 &pwr_info
->maxpwr_5gl
, 0, fallback
);
609 nvram_read_u16(prefix
, postfix
, "pa5gw0a",
610 &pwr_info
->pa_5g
[0], 0, fallback
);
611 nvram_read_u16(prefix
, postfix
, "pa5gw1a",
612 &pwr_info
->pa_5g
[1], 0, fallback
);
613 nvram_read_u16(prefix
, postfix
, "pa5gw2a",
614 &pwr_info
->pa_5g
[2], 0, fallback
);
615 nvram_read_u16(prefix
, postfix
, "pa5glw0a",
616 &pwr_info
->pa_5gl
[0], 0, fallback
);
617 nvram_read_u16(prefix
, postfix
, "pa5glw1a",
618 &pwr_info
->pa_5gl
[1], 0, fallback
);
619 nvram_read_u16(prefix
, postfix
, "pa5glw2a",
620 &pwr_info
->pa_5gl
[2], 0, fallback
);
621 nvram_read_u16(prefix
, postfix
, "pa5ghw0a",
622 &pwr_info
->pa_5gh
[0], 0, fallback
);
623 nvram_read_u16(prefix
, postfix
, "pa5ghw1a",
624 &pwr_info
->pa_5gh
[1], 0, fallback
);
625 nvram_read_u16(prefix
, postfix
, "pa5ghw2a",
626 &pwr_info
->pa_5gh
[2], 0, fallback
);
630 static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom
*sprom
,
631 const char *prefix
, bool fallback
)
636 for (i
= 0; i
< ARRAY_SIZE(sprom
->core_pwr_info
); i
++) {
637 struct ssb_sprom_core_pwr_info
*pwr_info
= &sprom
->core_pwr_info
[i
];
638 snprintf(postfix
, sizeof(postfix
), "%i", i
);
639 nvram_read_u16(prefix
, postfix
, "pa2gw3a",
640 &pwr_info
->pa_2g
[3], 0, fallback
);
641 nvram_read_u16(prefix
, postfix
, "pa5gw3a",
642 &pwr_info
->pa_5g
[3], 0, fallback
);
643 nvram_read_u16(prefix
, postfix
, "pa5glw3a",
644 &pwr_info
->pa_5gl
[3], 0, fallback
);
645 nvram_read_u16(prefix
, postfix
, "pa5ghw3a",
646 &pwr_info
->pa_5gh
[3], 0, fallback
);
650 static bool bcm47xx_is_valid_mac(u8
*mac
)
652 return mac
&& !(mac
[0] == 0x00 && mac
[1] == 0x90 && mac
[2] == 0x4c);
655 static int bcm47xx_increase_mac_addr(u8
*mac
, u8 num
)
657 u8
*oui
= mac
+ ETH_ALEN
/2 - 1;
658 u8
*p
= mac
+ ETH_ALEN
- 1;
669 pr_err("unable to fetch mac address\n");
675 static int mac_addr_used
= 2;
677 static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom
*sprom
,
678 const char *prefix
, bool fallback
)
680 nvram_read_macaddr(prefix
, "et0macaddr", sprom
->et0mac
, fallback
);
681 nvram_read_u8(prefix
, NULL
, "et0mdcport", &sprom
->et0mdcport
, 0,
683 nvram_read_u8(prefix
, NULL
, "et0phyaddr", &sprom
->et0phyaddr
, 0,
686 nvram_read_macaddr(prefix
, "et1macaddr", sprom
->et1mac
, fallback
);
687 nvram_read_u8(prefix
, NULL
, "et1mdcport", &sprom
->et1mdcport
, 0,
689 nvram_read_u8(prefix
, NULL
, "et1phyaddr", &sprom
->et1phyaddr
, 0,
692 nvram_read_macaddr(prefix
, "macaddr", sprom
->il0mac
, fallback
);
693 nvram_read_macaddr(prefix
, "il0macaddr", sprom
->il0mac
, fallback
);
695 /* The address prefix 00:90:4C is used by Broadcom in their initial
696 configuration. When a mac address with the prefix 00:90:4C is used
697 all devices from the same series are sharing the same mac address.
698 To prevent mac address collisions we replace them with a mac address
699 based on the base address. */
700 if (!bcm47xx_is_valid_mac(sprom
->il0mac
)) {
703 nvram_read_macaddr(NULL
, "et0macaddr", mac
, false);
704 if (bcm47xx_is_valid_mac(mac
)) {
705 int err
= bcm47xx_increase_mac_addr(mac
, mac_addr_used
);
708 ether_addr_copy(sprom
->il0mac
, mac
);
715 static void bcm47xx_fill_board_data(struct ssb_sprom
*sprom
, const char *prefix
,
718 nvram_read_u16(prefix
, NULL
, "boardrev", &sprom
->board_rev
, 0, true);
719 nvram_read_u16(prefix
, NULL
, "boardnum", &sprom
->board_num
, 0,
721 nvram_read_u16(prefix
, NULL
, "boardtype", &sprom
->board_type
, 0, true);
722 nvram_read_u32_2(prefix
, "boardflags", &sprom
->boardflags_lo
,
723 &sprom
->boardflags_hi
, fallback
);
724 nvram_read_u32_2(prefix
, "boardflags2", &sprom
->boardflags2_lo
,
725 &sprom
->boardflags2_hi
, fallback
);
728 void bcm47xx_fill_sprom(struct ssb_sprom
*sprom
, const char *prefix
,
731 bcm47xx_fill_sprom_ethernet(sprom
, prefix
, fallback
);
732 bcm47xx_fill_board_data(sprom
, prefix
, fallback
);
734 nvram_read_u8(prefix
, NULL
, "sromrev", &sprom
->revision
, 0, fallback
);
736 switch (sprom
->revision
) {
738 bcm47xx_fill_sprom_r1234589(sprom
, prefix
, fallback
);
739 bcm47xx_fill_sprom_r12389(sprom
, prefix
, fallback
);
740 bcm47xx_fill_sprom_r1(sprom
, prefix
, fallback
);
743 bcm47xx_fill_sprom_r1234589(sprom
, prefix
, fallback
);
744 bcm47xx_fill_sprom_r12389(sprom
, prefix
, fallback
);
745 bcm47xx_fill_sprom_r2389(sprom
, prefix
, fallback
);
748 bcm47xx_fill_sprom_r1234589(sprom
, prefix
, fallback
);
749 bcm47xx_fill_sprom_r12389(sprom
, prefix
, fallback
);
750 bcm47xx_fill_sprom_r2389(sprom
, prefix
, fallback
);
751 bcm47xx_fill_sprom_r389(sprom
, prefix
, fallback
);
752 bcm47xx_fill_sprom_r3(sprom
, prefix
, fallback
);
756 bcm47xx_fill_sprom_r1234589(sprom
, prefix
, fallback
);
757 bcm47xx_fill_sprom_r4589(sprom
, prefix
, fallback
);
758 bcm47xx_fill_sprom_r458(sprom
, prefix
, fallback
);
759 bcm47xx_fill_sprom_r45(sprom
, prefix
, fallback
);
760 bcm47xx_fill_sprom_path_r4589(sprom
, prefix
, fallback
);
761 bcm47xx_fill_sprom_path_r45(sprom
, prefix
, fallback
);
764 bcm47xx_fill_sprom_r1234589(sprom
, prefix
, fallback
);
765 bcm47xx_fill_sprom_r12389(sprom
, prefix
, fallback
);
766 bcm47xx_fill_sprom_r2389(sprom
, prefix
, fallback
);
767 bcm47xx_fill_sprom_r389(sprom
, prefix
, fallback
);
768 bcm47xx_fill_sprom_r4589(sprom
, prefix
, fallback
);
769 bcm47xx_fill_sprom_r458(sprom
, prefix
, fallback
);
770 bcm47xx_fill_sprom_r89(sprom
, prefix
, fallback
);
771 bcm47xx_fill_sprom_path_r4589(sprom
, prefix
, fallback
);
774 bcm47xx_fill_sprom_r1234589(sprom
, prefix
, fallback
);
775 bcm47xx_fill_sprom_r12389(sprom
, prefix
, fallback
);
776 bcm47xx_fill_sprom_r2389(sprom
, prefix
, fallback
);
777 bcm47xx_fill_sprom_r389(sprom
, prefix
, fallback
);
778 bcm47xx_fill_sprom_r4589(sprom
, prefix
, fallback
);
779 bcm47xx_fill_sprom_r89(sprom
, prefix
, fallback
);
780 bcm47xx_fill_sprom_r9(sprom
, prefix
, fallback
);
781 bcm47xx_fill_sprom_path_r4589(sprom
, prefix
, fallback
);
784 pr_warn("Unsupported SPROM revision %d detected. Will extract"
785 " v1\n", sprom
->revision
);
787 bcm47xx_fill_sprom_r1234589(sprom
, prefix
, fallback
);
788 bcm47xx_fill_sprom_r12389(sprom
, prefix
, fallback
);
789 bcm47xx_fill_sprom_r1(sprom
, prefix
, fallback
);
793 #ifdef CONFIG_BCM47XX_SSB
794 void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo
*boardinfo
,
797 nvram_read_u16(prefix
, NULL
, "boardvendor", &boardinfo
->vendor
, 0,
799 if (!boardinfo
->vendor
)
800 boardinfo
->vendor
= SSB_BOARDVENDOR_BCM
;
802 nvram_read_u16(prefix
, NULL
, "boardtype", &boardinfo
->type
, 0, true);
806 #ifdef CONFIG_BCM47XX_BCMA
807 void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo
*boardinfo
,
810 nvram_read_u16(prefix
, NULL
, "boardvendor", &boardinfo
->vendor
, 0,
812 if (!boardinfo
->vendor
)
813 boardinfo
->vendor
= SSB_BOARDVENDOR_BCM
;
815 nvram_read_u16(prefix
, NULL
, "boardtype", &boardinfo
->type
, 0, true);
819 #if defined(CONFIG_BCM47XX_SSB)
820 static int bcm47xx_get_sprom_ssb(struct ssb_bus
*bus
, struct ssb_sprom
*out
)
824 if (bus
->bustype
== SSB_BUSTYPE_PCI
) {
825 memset(out
, 0, sizeof(struct ssb_sprom
));
826 snprintf(prefix
, sizeof(prefix
), "pci/%u/%u/",
827 bus
->host_pci
->bus
->number
+ 1,
828 PCI_SLOT(bus
->host_pci
->devfn
));
829 bcm47xx_fill_sprom(out
, prefix
, false);
832 pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
838 #if defined(CONFIG_BCM47XX_BCMA)
839 static int bcm47xx_get_sprom_bcma(struct bcma_bus
*bus
, struct ssb_sprom
*out
)
842 struct bcma_device
*core
;
844 switch (bus
->hosttype
) {
845 case BCMA_HOSTTYPE_PCI
:
846 memset(out
, 0, sizeof(struct ssb_sprom
));
847 snprintf(prefix
, sizeof(prefix
), "pci/%u/%u/",
848 bus
->host_pci
->bus
->number
+ 1,
849 PCI_SLOT(bus
->host_pci
->devfn
));
850 bcm47xx_fill_sprom(out
, prefix
, false);
852 case BCMA_HOSTTYPE_SOC
:
853 memset(out
, 0, sizeof(struct ssb_sprom
));
854 core
= bcma_find_core(bus
, BCMA_CORE_80211
);
856 snprintf(prefix
, sizeof(prefix
), "sb/%u/",
858 bcm47xx_fill_sprom(out
, prefix
, true);
860 bcm47xx_fill_sprom(out
, NULL
, false);
864 pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
871 * On bcm47xx we need to register SPROM fallback handler very early, so we can't
872 * use anything like platform device / driver for this.
874 void bcm47xx_sprom_register_fallbacks(void)
876 #if defined(CONFIG_BCM47XX_SSB)
877 if (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb
))
878 pr_warn("Failed to registered ssb SPROM handler\n");
881 #if defined(CONFIG_BCM47XX_BCMA)
882 if (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma
))
883 pr_warn("Failed to registered bcma SPROM handler\n");