2 * BCM47xx/BCM53xx nvram variable access
4 * Copyright (C) 2005 Broadcom Corporation
5 * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
6 * Copyright (C) 2006 Michael Buesch <m@bues.ch>
7 * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
8 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
9 * Copyright (C) 2010-2014 Hauke Mehrtens <hauke@hauke-m.de>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
17 #include <linux/types.h>
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/string.h>
21 #include <linux/of_address.h>
22 #include <linux/device.h>
23 #include <linux/platform_device.h>
24 #include <linux/of_platform.h>
26 #include <linux/ssb/ssb.h>
27 #include <linux/bcma/bcma.h>
28 #include <linux/bcm47xx_nvram.h>
29 #include <linux/if_ether.h>
30 #include <linux/etherdevice.h>
32 struct bcm47xx_sprom_fill
{
35 int (*getenv
)(const struct bcm47xx_sprom_fill
*fill
, const char *name
,
36 char *val
, size_t val_len
);
40 static void create_key(const char *prefix
, const char *postfix
,
41 const char *name
, char *buf
, int len
)
43 if (prefix
&& postfix
)
44 snprintf(buf
, len
, "%s%s%s", prefix
, name
, postfix
);
46 snprintf(buf
, len
, "%s%s", prefix
, name
);
48 snprintf(buf
, len
, "%s%s", name
, postfix
);
50 snprintf(buf
, len
, "%s", name
);
53 static int get_nvram_var(const struct bcm47xx_sprom_fill
*fill
,
54 const char *postfix
, const char *name
, char *buf
,
60 create_key(fill
->prefix
, postfix
, name
, key
, sizeof(key
));
62 err
= fill
->getenv(fill
, key
, buf
, len
);
63 if (fill
->fallback
&& err
== -ENOENT
&& fill
->prefix
) {
64 create_key(NULL
, postfix
, name
, key
, sizeof(key
));
65 err
= fill
->getenv(fill
, key
, buf
, len
);
70 #define NVRAM_READ_VAL(type) \
71 static void nvram_read_ ## type (const struct bcm47xx_sprom_fill *fill, \
72 const char *postfix, const char *name, \
73 type *val, type allset) \
79 err = get_nvram_var(fill, postfix, name, buf, sizeof(buf)); \
82 err = kstrto ## type(strim(buf), 0, &var); \
84 pr_warn("can not parse nvram name %s%s%s with value %s got %i\n", \
85 fill->prefix, name, postfix, buf, err); \
88 if (allset && var == allset) \
100 static void nvram_read_u32_2(const struct bcm47xx_sprom_fill
*fill
,
101 const char *name
, u16
*val_lo
, u16
*val_hi
)
107 err
= get_nvram_var(fill
, NULL
, name
, buf
, sizeof(buf
));
110 err
= kstrtou32(strim(buf
), 0, &val
);
112 pr_warn("can not parse nvram name %s%s with value %s got %i\n",
113 fill
->prefix
, name
, buf
, err
);
116 *val_lo
= (val
& 0x0000FFFFU
);
117 *val_hi
= (val
& 0xFFFF0000U
) >> 16;
120 static void nvram_read_leddc(const struct bcm47xx_sprom_fill
*fill
,
121 const char *name
, u8
*leddc_on_time
,
128 err
= get_nvram_var(fill
, NULL
, name
, buf
, sizeof(buf
));
131 err
= kstrtou32(strim(buf
), 0, &val
);
133 pr_warn("can not parse nvram name %s%s with value %s got %i\n",
134 fill
->prefix
, name
, buf
, err
);
138 if (val
== 0xffff || val
== 0xffffffff)
141 *leddc_on_time
= val
& 0xff;
142 *leddc_off_time
= (val
>> 16) & 0xff;
145 static void bcm47xx_nvram_parse_macaddr(char *buf
, u8 macaddr
[6])
147 if (strchr(buf
, ':'))
148 sscanf(buf
, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr
[0],
149 &macaddr
[1], &macaddr
[2], &macaddr
[3], &macaddr
[4],
151 else if (strchr(buf
, '-'))
152 sscanf(buf
, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr
[0],
153 &macaddr
[1], &macaddr
[2], &macaddr
[3], &macaddr
[4],
156 pr_warn("Can not parse mac address: %s\n", buf
);
159 static void nvram_read_macaddr(const struct bcm47xx_sprom_fill
*fill
,
160 const char *name
, u8 val
[6])
165 err
= get_nvram_var(fill
, NULL
, name
, buf
, sizeof(buf
));
169 bcm47xx_nvram_parse_macaddr(buf
, val
);
172 static void nvram_read_alpha2(const struct bcm47xx_sprom_fill
*fill
,
173 const char *name
, char val
[2])
178 err
= get_nvram_var(fill
, NULL
, name
, buf
, sizeof(buf
));
183 if (strlen(buf
) > 2) {
184 pr_warn("alpha2 is too long %s\n", buf
);
190 static void bcm47xx_sprom_fill_r1234589(struct ssb_sprom
*sprom
,
191 const struct bcm47xx_sprom_fill
*fill
)
193 nvram_read_u16(fill
, NULL
, "devid", &sprom
->dev_id
, 0);
194 nvram_read_u8(fill
, NULL
, "ledbh0", &sprom
->gpio0
, 0xff);
195 nvram_read_u8(fill
, NULL
, "ledbh1", &sprom
->gpio1
, 0xff);
196 nvram_read_u8(fill
, NULL
, "ledbh2", &sprom
->gpio2
, 0xff);
197 nvram_read_u8(fill
, NULL
, "ledbh3", &sprom
->gpio3
, 0xff);
198 nvram_read_u8(fill
, NULL
, "aa2g", &sprom
->ant_available_bg
, 0);
199 nvram_read_u8(fill
, NULL
, "aa5g", &sprom
->ant_available_a
, 0);
200 nvram_read_s8(fill
, NULL
, "ag0", &sprom
->antenna_gain
.a0
, 0);
201 nvram_read_s8(fill
, NULL
, "ag1", &sprom
->antenna_gain
.a1
, 0);
202 nvram_read_alpha2(fill
, "ccode", sprom
->alpha2
);
205 static void bcm47xx_sprom_fill_r12389(struct ssb_sprom
*sprom
,
206 const struct bcm47xx_sprom_fill
*fill
)
208 nvram_read_u16(fill
, NULL
, "pa0b0", &sprom
->pa0b0
, 0);
209 nvram_read_u16(fill
, NULL
, "pa0b1", &sprom
->pa0b1
, 0);
210 nvram_read_u16(fill
, NULL
, "pa0b2", &sprom
->pa0b2
, 0);
211 nvram_read_u8(fill
, NULL
, "pa0itssit", &sprom
->itssi_bg
, 0);
212 nvram_read_u8(fill
, NULL
, "pa0maxpwr", &sprom
->maxpwr_bg
, 0);
213 nvram_read_u16(fill
, NULL
, "pa1b0", &sprom
->pa1b0
, 0);
214 nvram_read_u16(fill
, NULL
, "pa1b1", &sprom
->pa1b1
, 0);
215 nvram_read_u16(fill
, NULL
, "pa1b2", &sprom
->pa1b2
, 0);
216 nvram_read_u8(fill
, NULL
, "pa1itssit", &sprom
->itssi_a
, 0);
217 nvram_read_u8(fill
, NULL
, "pa1maxpwr", &sprom
->maxpwr_a
, 0);
220 static void bcm47xx_sprom_fill_r1(struct ssb_sprom
*sprom
,
221 const struct bcm47xx_sprom_fill
*fill
)
223 nvram_read_u16(fill
, NULL
, "boardflags", &sprom
->boardflags_lo
, 0);
224 nvram_read_u8(fill
, NULL
, "cc", &sprom
->country_code
, 0);
227 static void bcm47xx_sprom_fill_r2389(struct ssb_sprom
*sprom
,
228 const struct bcm47xx_sprom_fill
*fill
)
230 nvram_read_u8(fill
, NULL
, "opo", &sprom
->opo
, 0);
231 nvram_read_u16(fill
, NULL
, "pa1lob0", &sprom
->pa1lob0
, 0);
232 nvram_read_u16(fill
, NULL
, "pa1lob1", &sprom
->pa1lob1
, 0);
233 nvram_read_u16(fill
, NULL
, "pa1lob2", &sprom
->pa1lob2
, 0);
234 nvram_read_u16(fill
, NULL
, "pa1hib0", &sprom
->pa1hib0
, 0);
235 nvram_read_u16(fill
, NULL
, "pa1hib1", &sprom
->pa1hib1
, 0);
236 nvram_read_u16(fill
, NULL
, "pa1hib2", &sprom
->pa1hib2
, 0);
237 nvram_read_u8(fill
, NULL
, "pa1lomaxpwr", &sprom
->maxpwr_al
, 0);
238 nvram_read_u8(fill
, NULL
, "pa1himaxpwr", &sprom
->maxpwr_ah
, 0);
241 static void bcm47xx_sprom_fill_r389(struct ssb_sprom
*sprom
,
242 const struct bcm47xx_sprom_fill
*fill
)
244 nvram_read_u8(fill
, NULL
, "bxa2g", &sprom
->bxa2g
, 0);
245 nvram_read_u8(fill
, NULL
, "rssisav2g", &sprom
->rssisav2g
, 0);
246 nvram_read_u8(fill
, NULL
, "rssismc2g", &sprom
->rssismc2g
, 0);
247 nvram_read_u8(fill
, NULL
, "rssismf2g", &sprom
->rssismf2g
, 0);
248 nvram_read_u8(fill
, NULL
, "bxa5g", &sprom
->bxa5g
, 0);
249 nvram_read_u8(fill
, NULL
, "rssisav5g", &sprom
->rssisav5g
, 0);
250 nvram_read_u8(fill
, NULL
, "rssismc5g", &sprom
->rssismc5g
, 0);
251 nvram_read_u8(fill
, NULL
, "rssismf5g", &sprom
->rssismf5g
, 0);
252 nvram_read_u8(fill
, NULL
, "tri2g", &sprom
->tri2g
, 0);
253 nvram_read_u8(fill
, NULL
, "tri5g", &sprom
->tri5g
, 0);
254 nvram_read_u8(fill
, NULL
, "tri5gl", &sprom
->tri5gl
, 0);
255 nvram_read_u8(fill
, NULL
, "tri5gh", &sprom
->tri5gh
, 0);
256 nvram_read_s8(fill
, NULL
, "rxpo2g", &sprom
->rxpo2g
, 0);
257 nvram_read_s8(fill
, NULL
, "rxpo5g", &sprom
->rxpo5g
, 0);
260 static void bcm47xx_sprom_fill_r3(struct ssb_sprom
*sprom
,
261 const struct bcm47xx_sprom_fill
*fill
)
263 nvram_read_u8(fill
, NULL
, "regrev", &sprom
->regrev
, 0);
264 nvram_read_leddc(fill
, "leddc", &sprom
->leddc_on_time
,
265 &sprom
->leddc_off_time
);
268 static void bcm47xx_sprom_fill_r4589(struct ssb_sprom
*sprom
,
269 const struct bcm47xx_sprom_fill
*fill
)
271 nvram_read_u8(fill
, NULL
, "regrev", &sprom
->regrev
, 0);
272 nvram_read_s8(fill
, NULL
, "ag2", &sprom
->antenna_gain
.a2
, 0);
273 nvram_read_s8(fill
, NULL
, "ag3", &sprom
->antenna_gain
.a3
, 0);
274 nvram_read_u8(fill
, NULL
, "txchain", &sprom
->txchain
, 0xf);
275 nvram_read_u8(fill
, NULL
, "rxchain", &sprom
->rxchain
, 0xf);
276 nvram_read_u8(fill
, NULL
, "antswitch", &sprom
->antswitch
, 0xff);
277 nvram_read_leddc(fill
, "leddc", &sprom
->leddc_on_time
,
278 &sprom
->leddc_off_time
);
281 static void bcm47xx_sprom_fill_r458(struct ssb_sprom
*sprom
,
282 const struct bcm47xx_sprom_fill
*fill
)
284 nvram_read_u16(fill
, NULL
, "cck2gpo", &sprom
->cck2gpo
, 0);
285 nvram_read_u32(fill
, NULL
, "ofdm2gpo", &sprom
->ofdm2gpo
, 0);
286 nvram_read_u32(fill
, NULL
, "ofdm5gpo", &sprom
->ofdm5gpo
, 0);
287 nvram_read_u32(fill
, NULL
, "ofdm5glpo", &sprom
->ofdm5glpo
, 0);
288 nvram_read_u32(fill
, NULL
, "ofdm5ghpo", &sprom
->ofdm5ghpo
, 0);
289 nvram_read_u16(fill
, NULL
, "cddpo", &sprom
->cddpo
, 0);
290 nvram_read_u16(fill
, NULL
, "stbcpo", &sprom
->stbcpo
, 0);
291 nvram_read_u16(fill
, NULL
, "bw40po", &sprom
->bw40po
, 0);
292 nvram_read_u16(fill
, NULL
, "bwduppo", &sprom
->bwduppo
, 0);
293 nvram_read_u16(fill
, NULL
, "mcs2gpo0", &sprom
->mcs2gpo
[0], 0);
294 nvram_read_u16(fill
, NULL
, "mcs2gpo1", &sprom
->mcs2gpo
[1], 0);
295 nvram_read_u16(fill
, NULL
, "mcs2gpo2", &sprom
->mcs2gpo
[2], 0);
296 nvram_read_u16(fill
, NULL
, "mcs2gpo3", &sprom
->mcs2gpo
[3], 0);
297 nvram_read_u16(fill
, NULL
, "mcs2gpo4", &sprom
->mcs2gpo
[4], 0);
298 nvram_read_u16(fill
, NULL
, "mcs2gpo5", &sprom
->mcs2gpo
[5], 0);
299 nvram_read_u16(fill
, NULL
, "mcs2gpo6", &sprom
->mcs2gpo
[6], 0);
300 nvram_read_u16(fill
, NULL
, "mcs2gpo7", &sprom
->mcs2gpo
[7], 0);
301 nvram_read_u16(fill
, NULL
, "mcs5gpo0", &sprom
->mcs5gpo
[0], 0);
302 nvram_read_u16(fill
, NULL
, "mcs5gpo1", &sprom
->mcs5gpo
[1], 0);
303 nvram_read_u16(fill
, NULL
, "mcs5gpo2", &sprom
->mcs5gpo
[2], 0);
304 nvram_read_u16(fill
, NULL
, "mcs5gpo3", &sprom
->mcs5gpo
[3], 0);
305 nvram_read_u16(fill
, NULL
, "mcs5gpo4", &sprom
->mcs5gpo
[4], 0);
306 nvram_read_u16(fill
, NULL
, "mcs5gpo5", &sprom
->mcs5gpo
[5], 0);
307 nvram_read_u16(fill
, NULL
, "mcs5gpo6", &sprom
->mcs5gpo
[6], 0);
308 nvram_read_u16(fill
, NULL
, "mcs5gpo7", &sprom
->mcs5gpo
[7], 0);
309 nvram_read_u16(fill
, NULL
, "mcs5glpo0", &sprom
->mcs5glpo
[0], 0);
310 nvram_read_u16(fill
, NULL
, "mcs5glpo1", &sprom
->mcs5glpo
[1], 0);
311 nvram_read_u16(fill
, NULL
, "mcs5glpo2", &sprom
->mcs5glpo
[2], 0);
312 nvram_read_u16(fill
, NULL
, "mcs5glpo3", &sprom
->mcs5glpo
[3], 0);
313 nvram_read_u16(fill
, NULL
, "mcs5glpo4", &sprom
->mcs5glpo
[4], 0);
314 nvram_read_u16(fill
, NULL
, "mcs5glpo5", &sprom
->mcs5glpo
[5], 0);
315 nvram_read_u16(fill
, NULL
, "mcs5glpo6", &sprom
->mcs5glpo
[6], 0);
316 nvram_read_u16(fill
, NULL
, "mcs5glpo7", &sprom
->mcs5glpo
[7], 0);
317 nvram_read_u16(fill
, NULL
, "mcs5ghpo0", &sprom
->mcs5ghpo
[0], 0);
318 nvram_read_u16(fill
, NULL
, "mcs5ghpo1", &sprom
->mcs5ghpo
[1], 0);
319 nvram_read_u16(fill
, NULL
, "mcs5ghpo2", &sprom
->mcs5ghpo
[2], 0);
320 nvram_read_u16(fill
, NULL
, "mcs5ghpo3", &sprom
->mcs5ghpo
[3], 0);
321 nvram_read_u16(fill
, NULL
, "mcs5ghpo4", &sprom
->mcs5ghpo
[4], 0);
322 nvram_read_u16(fill
, NULL
, "mcs5ghpo5", &sprom
->mcs5ghpo
[5], 0);
323 nvram_read_u16(fill
, NULL
, "mcs5ghpo6", &sprom
->mcs5ghpo
[6], 0);
324 nvram_read_u16(fill
, NULL
, "mcs5ghpo7", &sprom
->mcs5ghpo
[7], 0);
327 static void bcm47xx_sprom_fill_r45(struct ssb_sprom
*sprom
,
328 const struct bcm47xx_sprom_fill
*fill
)
330 nvram_read_u8(fill
, NULL
, "txpid2ga0", &sprom
->txpid2g
[0], 0);
331 nvram_read_u8(fill
, NULL
, "txpid2ga1", &sprom
->txpid2g
[1], 0);
332 nvram_read_u8(fill
, NULL
, "txpid2ga2", &sprom
->txpid2g
[2], 0);
333 nvram_read_u8(fill
, NULL
, "txpid2ga3", &sprom
->txpid2g
[3], 0);
334 nvram_read_u8(fill
, NULL
, "txpid5ga0", &sprom
->txpid5g
[0], 0);
335 nvram_read_u8(fill
, NULL
, "txpid5ga1", &sprom
->txpid5g
[1], 0);
336 nvram_read_u8(fill
, NULL
, "txpid5ga2", &sprom
->txpid5g
[2], 0);
337 nvram_read_u8(fill
, NULL
, "txpid5ga3", &sprom
->txpid5g
[3], 0);
338 nvram_read_u8(fill
, NULL
, "txpid5gla0", &sprom
->txpid5gl
[0], 0);
339 nvram_read_u8(fill
, NULL
, "txpid5gla1", &sprom
->txpid5gl
[1], 0);
340 nvram_read_u8(fill
, NULL
, "txpid5gla2", &sprom
->txpid5gl
[2], 0);
341 nvram_read_u8(fill
, NULL
, "txpid5gla3", &sprom
->txpid5gl
[3], 0);
342 nvram_read_u8(fill
, NULL
, "txpid5gha0", &sprom
->txpid5gh
[0], 0);
343 nvram_read_u8(fill
, NULL
, "txpid5gha1", &sprom
->txpid5gh
[1], 0);
344 nvram_read_u8(fill
, NULL
, "txpid5gha2", &sprom
->txpid5gh
[2], 0);
345 nvram_read_u8(fill
, NULL
, "txpid5gha3", &sprom
->txpid5gh
[3], 0);
348 static void bcm47xx_sprom_fill_r89(struct ssb_sprom
*sprom
,
349 const struct bcm47xx_sprom_fill
*fill
)
351 nvram_read_u8(fill
, NULL
, "tssipos2g", &sprom
->fem
.ghz2
.tssipos
, 0);
352 nvram_read_u8(fill
, NULL
, "extpagain2g", &sprom
->fem
.ghz2
.extpa_gain
, 0);
353 nvram_read_u8(fill
, NULL
, "pdetrange2g", &sprom
->fem
.ghz2
.pdet_range
, 0);
354 nvram_read_u8(fill
, NULL
, "triso2g", &sprom
->fem
.ghz2
.tr_iso
, 0);
355 nvram_read_u8(fill
, NULL
, "antswctl2g", &sprom
->fem
.ghz2
.antswlut
, 0);
356 nvram_read_u8(fill
, NULL
, "tssipos5g", &sprom
->fem
.ghz5
.tssipos
, 0);
357 nvram_read_u8(fill
, NULL
, "extpagain5g", &sprom
->fem
.ghz5
.extpa_gain
, 0);
358 nvram_read_u8(fill
, NULL
, "pdetrange5g", &sprom
->fem
.ghz5
.pdet_range
, 0);
359 nvram_read_u8(fill
, NULL
, "triso5g", &sprom
->fem
.ghz5
.tr_iso
, 0);
360 nvram_read_u8(fill
, NULL
, "antswctl5g", &sprom
->fem
.ghz5
.antswlut
, 0);
361 nvram_read_u8(fill
, NULL
, "tempthresh", &sprom
->tempthresh
, 0);
362 nvram_read_u8(fill
, NULL
, "tempoffset", &sprom
->tempoffset
, 0);
363 nvram_read_u16(fill
, NULL
, "rawtempsense", &sprom
->rawtempsense
, 0);
364 nvram_read_u8(fill
, NULL
, "measpower", &sprom
->measpower
, 0);
365 nvram_read_u8(fill
, NULL
, "tempsense_slope", &sprom
->tempsense_slope
, 0);
366 nvram_read_u8(fill
, NULL
, "tempcorrx", &sprom
->tempcorrx
, 0);
367 nvram_read_u8(fill
, NULL
, "tempsense_option", &sprom
->tempsense_option
, 0);
368 nvram_read_u8(fill
, NULL
, "freqoffset_corr", &sprom
->freqoffset_corr
, 0);
369 nvram_read_u8(fill
, NULL
, "iqcal_swp_dis", &sprom
->iqcal_swp_dis
, 0);
370 nvram_read_u8(fill
, NULL
, "hw_iqcal_en", &sprom
->hw_iqcal_en
, 0);
371 nvram_read_u8(fill
, NULL
, "elna2g", &sprom
->elna2g
, 0);
372 nvram_read_u8(fill
, NULL
, "elna5g", &sprom
->elna5g
, 0);
373 nvram_read_u8(fill
, NULL
, "phycal_tempdelta", &sprom
->phycal_tempdelta
, 0);
374 nvram_read_u8(fill
, NULL
, "temps_period", &sprom
->temps_period
, 0);
375 nvram_read_u8(fill
, NULL
, "temps_hysteresis", &sprom
->temps_hysteresis
, 0);
376 nvram_read_u8(fill
, NULL
, "measpower1", &sprom
->measpower1
, 0);
377 nvram_read_u8(fill
, NULL
, "measpower2", &sprom
->measpower2
, 0);
378 nvram_read_u8(fill
, NULL
, "rxgainerr2ga0", &sprom
->rxgainerr2ga
[0], 0);
379 nvram_read_u8(fill
, NULL
, "rxgainerr2ga1", &sprom
->rxgainerr2ga
[1], 0);
380 nvram_read_u8(fill
, NULL
, "rxgainerr2ga2", &sprom
->rxgainerr2ga
[2], 0);
381 nvram_read_u8(fill
, NULL
, "rxgainerr5gla0", &sprom
->rxgainerr5gla
[0], 0);
382 nvram_read_u8(fill
, NULL
, "rxgainerr5gla1", &sprom
->rxgainerr5gla
[1], 0);
383 nvram_read_u8(fill
, NULL
, "rxgainerr5gla2", &sprom
->rxgainerr5gla
[2], 0);
384 nvram_read_u8(fill
, NULL
, "rxgainerr5gma0", &sprom
->rxgainerr5gma
[0], 0);
385 nvram_read_u8(fill
, NULL
, "rxgainerr5gma1", &sprom
->rxgainerr5gma
[1], 0);
386 nvram_read_u8(fill
, NULL
, "rxgainerr5gma2", &sprom
->rxgainerr5gma
[2], 0);
387 nvram_read_u8(fill
, NULL
, "rxgainerr5gha0", &sprom
->rxgainerr5gha
[0], 0);
388 nvram_read_u8(fill
, NULL
, "rxgainerr5gha1", &sprom
->rxgainerr5gha
[1], 0);
389 nvram_read_u8(fill
, NULL
, "rxgainerr5gha2", &sprom
->rxgainerr5gha
[2], 0);
390 nvram_read_u8(fill
, NULL
, "rxgainerr5gua0", &sprom
->rxgainerr5gua
[0], 0);
391 nvram_read_u8(fill
, NULL
, "rxgainerr5gua1", &sprom
->rxgainerr5gua
[1], 0);
392 nvram_read_u8(fill
, NULL
, "rxgainerr5gua2", &sprom
->rxgainerr5gua
[2], 0);
393 nvram_read_u8(fill
, NULL
, "noiselvl2ga0", &sprom
->noiselvl2ga
[0], 0);
394 nvram_read_u8(fill
, NULL
, "noiselvl2ga1", &sprom
->noiselvl2ga
[1], 0);
395 nvram_read_u8(fill
, NULL
, "noiselvl2ga2", &sprom
->noiselvl2ga
[2], 0);
396 nvram_read_u8(fill
, NULL
, "noiselvl5gla0", &sprom
->noiselvl5gla
[0], 0);
397 nvram_read_u8(fill
, NULL
, "noiselvl5gla1", &sprom
->noiselvl5gla
[1], 0);
398 nvram_read_u8(fill
, NULL
, "noiselvl5gla2", &sprom
->noiselvl5gla
[2], 0);
399 nvram_read_u8(fill
, NULL
, "noiselvl5gma0", &sprom
->noiselvl5gma
[0], 0);
400 nvram_read_u8(fill
, NULL
, "noiselvl5gma1", &sprom
->noiselvl5gma
[1], 0);
401 nvram_read_u8(fill
, NULL
, "noiselvl5gma2", &sprom
->noiselvl5gma
[2], 0);
402 nvram_read_u8(fill
, NULL
, "noiselvl5gha0", &sprom
->noiselvl5gha
[0], 0);
403 nvram_read_u8(fill
, NULL
, "noiselvl5gha1", &sprom
->noiselvl5gha
[1], 0);
404 nvram_read_u8(fill
, NULL
, "noiselvl5gha2", &sprom
->noiselvl5gha
[2], 0);
405 nvram_read_u8(fill
, NULL
, "noiselvl5gua0", &sprom
->noiselvl5gua
[0], 0);
406 nvram_read_u8(fill
, NULL
, "noiselvl5gua1", &sprom
->noiselvl5gua
[1], 0);
407 nvram_read_u8(fill
, NULL
, "noiselvl5gua2", &sprom
->noiselvl5gua
[2], 0);
408 nvram_read_u8(fill
, NULL
, "pcieingress_war", &sprom
->pcieingress_war
, 0);
411 static void bcm47xx_sprom_fill_r9(struct ssb_sprom
*sprom
,
412 const struct bcm47xx_sprom_fill
*fill
)
414 nvram_read_u16(fill
, NULL
, "cckbw202gpo", &sprom
->cckbw202gpo
, 0);
415 nvram_read_u16(fill
, NULL
, "cckbw20ul2gpo", &sprom
->cckbw20ul2gpo
, 0);
416 nvram_read_u32(fill
, NULL
, "legofdmbw202gpo", &sprom
->legofdmbw202gpo
, 0);
417 nvram_read_u32(fill
, NULL
, "legofdmbw20ul2gpo", &sprom
->legofdmbw20ul2gpo
, 0);
418 nvram_read_u32(fill
, NULL
, "legofdmbw205glpo", &sprom
->legofdmbw205glpo
, 0);
419 nvram_read_u32(fill
, NULL
, "legofdmbw20ul5glpo", &sprom
->legofdmbw20ul5glpo
, 0);
420 nvram_read_u32(fill
, NULL
, "legofdmbw205gmpo", &sprom
->legofdmbw205gmpo
, 0);
421 nvram_read_u32(fill
, NULL
, "legofdmbw20ul5gmpo", &sprom
->legofdmbw20ul5gmpo
, 0);
422 nvram_read_u32(fill
, NULL
, "legofdmbw205ghpo", &sprom
->legofdmbw205ghpo
, 0);
423 nvram_read_u32(fill
, NULL
, "legofdmbw20ul5ghpo", &sprom
->legofdmbw20ul5ghpo
, 0);
424 nvram_read_u32(fill
, NULL
, "mcsbw202gpo", &sprom
->mcsbw202gpo
, 0);
425 nvram_read_u32(fill
, NULL
, "mcsbw20ul2gpo", &sprom
->mcsbw20ul2gpo
, 0);
426 nvram_read_u32(fill
, NULL
, "mcsbw402gpo", &sprom
->mcsbw402gpo
, 0);
427 nvram_read_u32(fill
, NULL
, "mcsbw205glpo", &sprom
->mcsbw205glpo
, 0);
428 nvram_read_u32(fill
, NULL
, "mcsbw20ul5glpo", &sprom
->mcsbw20ul5glpo
, 0);
429 nvram_read_u32(fill
, NULL
, "mcsbw405glpo", &sprom
->mcsbw405glpo
, 0);
430 nvram_read_u32(fill
, NULL
, "mcsbw205gmpo", &sprom
->mcsbw205gmpo
, 0);
431 nvram_read_u32(fill
, NULL
, "mcsbw20ul5gmpo", &sprom
->mcsbw20ul5gmpo
, 0);
432 nvram_read_u32(fill
, NULL
, "mcsbw405gmpo", &sprom
->mcsbw405gmpo
, 0);
433 nvram_read_u32(fill
, NULL
, "mcsbw205ghpo", &sprom
->mcsbw205ghpo
, 0);
434 nvram_read_u32(fill
, NULL
, "mcsbw20ul5ghpo", &sprom
->mcsbw20ul5ghpo
, 0);
435 nvram_read_u32(fill
, NULL
, "mcsbw405ghpo", &sprom
->mcsbw405ghpo
, 0);
436 nvram_read_u16(fill
, NULL
, "mcs32po", &sprom
->mcs32po
, 0);
437 nvram_read_u16(fill
, NULL
, "legofdm40duppo", &sprom
->legofdm40duppo
, 0);
438 nvram_read_u8(fill
, NULL
, "sar2g", &sprom
->sar2g
, 0);
439 nvram_read_u8(fill
, NULL
, "sar5g", &sprom
->sar5g
, 0);
442 static void bcm47xx_sprom_fill_path_r4589(struct ssb_sprom
*sprom
,
443 const struct bcm47xx_sprom_fill
*fill
)
448 for (i
= 0; i
< ARRAY_SIZE(sprom
->core_pwr_info
); i
++) {
449 struct ssb_sprom_core_pwr_info
*pwr_info
= &sprom
->core_pwr_info
[i
];
451 snprintf(postfix
, sizeof(postfix
), "%i", i
);
452 nvram_read_u8(fill
, postfix
, "maxp2ga", &pwr_info
->maxpwr_2g
, 0);
453 nvram_read_u8(fill
, postfix
, "itt2ga", &pwr_info
->itssi_2g
, 0);
454 nvram_read_u8(fill
, postfix
, "itt5ga", &pwr_info
->itssi_5g
, 0);
455 nvram_read_u16(fill
, postfix
, "pa2gw0a", &pwr_info
->pa_2g
[0], 0);
456 nvram_read_u16(fill
, postfix
, "pa2gw1a", &pwr_info
->pa_2g
[1], 0);
457 nvram_read_u16(fill
, postfix
, "pa2gw2a", &pwr_info
->pa_2g
[2], 0);
458 nvram_read_u8(fill
, postfix
, "maxp5ga", &pwr_info
->maxpwr_5g
, 0);
459 nvram_read_u8(fill
, postfix
, "maxp5gha", &pwr_info
->maxpwr_5gh
, 0);
460 nvram_read_u8(fill
, postfix
, "maxp5gla", &pwr_info
->maxpwr_5gl
, 0);
461 nvram_read_u16(fill
, postfix
, "pa5gw0a", &pwr_info
->pa_5g
[0], 0);
462 nvram_read_u16(fill
, postfix
, "pa5gw1a", &pwr_info
->pa_5g
[1], 0);
463 nvram_read_u16(fill
, postfix
, "pa5gw2a", &pwr_info
->pa_5g
[2], 0);
464 nvram_read_u16(fill
, postfix
, "pa5glw0a", &pwr_info
->pa_5gl
[0], 0);
465 nvram_read_u16(fill
, postfix
, "pa5glw1a", &pwr_info
->pa_5gl
[1], 0);
466 nvram_read_u16(fill
, postfix
, "pa5glw2a", &pwr_info
->pa_5gl
[2], 0);
467 nvram_read_u16(fill
, postfix
, "pa5ghw0a", &pwr_info
->pa_5gh
[0], 0);
468 nvram_read_u16(fill
, postfix
, "pa5ghw1a", &pwr_info
->pa_5gh
[1], 0);
469 nvram_read_u16(fill
, postfix
, "pa5ghw2a", &pwr_info
->pa_5gh
[2], 0);
473 static void bcm47xx_sprom_fill_path_r45(struct ssb_sprom
*sprom
,
474 const struct bcm47xx_sprom_fill
*fill
)
479 for (i
= 0; i
< ARRAY_SIZE(sprom
->core_pwr_info
); i
++) {
480 struct ssb_sprom_core_pwr_info
*pwr_info
= &sprom
->core_pwr_info
[i
];
482 snprintf(postfix
, sizeof(postfix
), "%i", i
);
483 nvram_read_u16(fill
, postfix
, "pa2gw3a", &pwr_info
->pa_2g
[3], 0);
484 nvram_read_u16(fill
, postfix
, "pa5gw3a", &pwr_info
->pa_5g
[3], 0);
485 nvram_read_u16(fill
, postfix
, "pa5glw3a", &pwr_info
->pa_5gl
[3], 0);
486 nvram_read_u16(fill
, postfix
, "pa5ghw3a", &pwr_info
->pa_5gh
[3], 0);
490 static bool bcm47xx_is_valid_mac(u8
*mac
)
492 return mac
&& !(mac
[0] == 0x00 && mac
[1] == 0x90 && mac
[2] == 0x4c);
495 static int bcm47xx_increase_mac_addr(u8
*mac
, u8 num
)
497 u8
*oui
= mac
+ ETH_ALEN
/2 - 1;
498 u8
*p
= mac
+ ETH_ALEN
- 1;
509 pr_err("unable to fetch mac address\n");
516 * This is a global counter because different instances of sprom will
517 * access the same nvram.
519 static int mac_addr_used
= 2;
521 static void bcm47xx_sprom_fill_ethernet(struct ssb_sprom
*sprom
,
522 const struct bcm47xx_sprom_fill
*fill
)
524 nvram_read_macaddr(fill
, "et0macaddr", sprom
->et0mac
);
525 nvram_read_u8(fill
, NULL
, "et0mdcport", &sprom
->et0mdcport
, 0);
526 nvram_read_u8(fill
, NULL
, "et0phyaddr", &sprom
->et0phyaddr
, 0);
528 nvram_read_macaddr(fill
, "et1macaddr", sprom
->et1mac
);
529 nvram_read_u8(fill
, NULL
, "et1mdcport", &sprom
->et1mdcport
, 0);
530 nvram_read_u8(fill
, NULL
, "et1phyaddr", &sprom
->et1phyaddr
, 0);
532 nvram_read_macaddr(fill
, "macaddr", sprom
->il0mac
);
533 nvram_read_macaddr(fill
, "il0macaddr", sprom
->il0mac
);
536 * The address prefix 00:90:4C is used by Broadcom in their initial
537 * configuration. When a mac address with the prefix 00:90:4C is used
538 * all devices from the same series are sharing the same mac address.
539 * To prevent mac address collisions we replace them with a mac address
540 * based on the base address.
542 if (!bcm47xx_is_valid_mac(sprom
->il0mac
)) {
544 struct bcm47xx_sprom_fill fill_no_prefix
;
546 memcpy(&fill_no_prefix
, fill
, sizeof(fill_no_prefix
));
547 fill_no_prefix
.prefix
= NULL
;
549 nvram_read_macaddr(&fill_no_prefix
, "et0macaddr", mac
);
550 if (bcm47xx_is_valid_mac(mac
)) {
551 int err
= bcm47xx_increase_mac_addr(mac
, mac_addr_used
);
554 ether_addr_copy(sprom
->il0mac
, mac
);
561 static void bcm47xx_sprom_fill_board_data(struct ssb_sprom
*sprom
,
562 const struct bcm47xx_sprom_fill
*fill
)
564 nvram_read_u16(fill
, NULL
, "boardrev", &sprom
->board_rev
, 0);
565 nvram_read_u16(fill
, NULL
, "boardnum", &sprom
->board_num
, 0);
566 nvram_read_u16(fill
, NULL
, "boardtype", &sprom
->board_type
, 0);
567 nvram_read_u32_2(fill
, "boardflags", &sprom
->boardflags_lo
,
568 &sprom
->boardflags_hi
);
569 nvram_read_u32_2(fill
, "boardflags2", &sprom
->boardflags2_lo
,
570 &sprom
->boardflags2_hi
);
573 static void bcm47xx_sprom_fill(struct ssb_sprom
*sprom
,
574 const struct bcm47xx_sprom_fill
*fill
)
576 bcm47xx_sprom_fill_ethernet(sprom
, fill
);
577 bcm47xx_sprom_fill_board_data(sprom
, fill
);
579 nvram_read_u8(fill
, NULL
, "sromrev", &sprom
->revision
, 0);
581 switch (sprom
->revision
) {
583 bcm47xx_sprom_fill_r1234589(sprom
, fill
);
584 bcm47xx_sprom_fill_r12389(sprom
, fill
);
585 bcm47xx_sprom_fill_r1(sprom
, fill
);
588 bcm47xx_sprom_fill_r1234589(sprom
, fill
);
589 bcm47xx_sprom_fill_r12389(sprom
, fill
);
590 bcm47xx_sprom_fill_r2389(sprom
, fill
);
593 bcm47xx_sprom_fill_r1234589(sprom
, fill
);
594 bcm47xx_sprom_fill_r12389(sprom
, fill
);
595 bcm47xx_sprom_fill_r2389(sprom
, fill
);
596 bcm47xx_sprom_fill_r389(sprom
, fill
);
597 bcm47xx_sprom_fill_r3(sprom
, fill
);
601 bcm47xx_sprom_fill_r1234589(sprom
, fill
);
602 bcm47xx_sprom_fill_r4589(sprom
, fill
);
603 bcm47xx_sprom_fill_r458(sprom
, fill
);
604 bcm47xx_sprom_fill_r45(sprom
, fill
);
605 bcm47xx_sprom_fill_path_r4589(sprom
, fill
);
606 bcm47xx_sprom_fill_path_r45(sprom
, fill
);
609 bcm47xx_sprom_fill_r1234589(sprom
, fill
);
610 bcm47xx_sprom_fill_r12389(sprom
, fill
);
611 bcm47xx_sprom_fill_r2389(sprom
, fill
);
612 bcm47xx_sprom_fill_r389(sprom
, fill
);
613 bcm47xx_sprom_fill_r4589(sprom
, fill
);
614 bcm47xx_sprom_fill_r458(sprom
, fill
);
615 bcm47xx_sprom_fill_r89(sprom
, fill
);
616 bcm47xx_sprom_fill_path_r4589(sprom
, fill
);
619 bcm47xx_sprom_fill_r1234589(sprom
, fill
);
620 bcm47xx_sprom_fill_r12389(sprom
, fill
);
621 bcm47xx_sprom_fill_r2389(sprom
, fill
);
622 bcm47xx_sprom_fill_r389(sprom
, fill
);
623 bcm47xx_sprom_fill_r4589(sprom
, fill
);
624 bcm47xx_sprom_fill_r89(sprom
, fill
);
625 bcm47xx_sprom_fill_r9(sprom
, fill
);
626 bcm47xx_sprom_fill_path_r4589(sprom
, fill
);
629 pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
632 bcm47xx_sprom_fill_r1234589(sprom
, fill
);
633 bcm47xx_sprom_fill_r12389(sprom
, fill
);
634 bcm47xx_sprom_fill_r1(sprom
, fill
);
638 static int bcm47xx_sprom_getenv(const struct bcm47xx_sprom_fill
*fill
,
639 const char *name
, char *val
, size_t val_len
)
641 return bcm47xx_nvram_getenv(name
, val
, val_len
);
644 /* FIXME: This should not be static, but some callback argument */
645 static struct platform_device
*sprom_pdev
= NULL
;
648 * This function has to be called in a very precise moment. It has to be done:
649 * 1) After bcma registers flash cores, so we can read NVRAM.
650 * 2) Before any code needs SPROM content.
652 * This can be achieved only by using bcma callback.
654 static int bcm47xx_sprom_init(struct bcma_bus
*bus
, struct ssb_sprom
*out
)
656 struct platform_device
*pdev
= sprom_pdev
;
657 struct device
*dev
= &pdev
->dev
;
658 struct device_node
*np
= dev
->of_node
;
659 const __be32
*handle
;
660 struct device_node
*nvram_node
;
661 struct platform_device
*nvram_dev
;
662 struct bcm47xx_sprom_fill fill
;
664 handle
= of_get_property(np
, "nvram", NULL
);
668 nvram_node
= of_find_node_by_phandle(be32_to_cpup(handle
));
672 nvram_dev
= of_find_device_by_node(nvram_node
);
676 fill
.prefix
= of_get_property(np
, "prefix", NULL
);
678 fill
.fallback
= false;
679 fill
.getenv
= bcm47xx_sprom_getenv
;
680 fill
.priv
= nvram_dev
;
682 bcm47xx_sprom_fill(out
, &fill
);
687 static int bcm47xx_sprom_probe(struct platform_device
*pdev
)
689 /* This is the only way to make pdev accessible to the callback */
692 return bcma_arch_register_fallback_sprom(&bcm47xx_sprom_init
);
695 static const struct of_device_id bcm47xx_sprom_of_match_table
[] = {
696 { .compatible
= "brcm,bcm47xx-sprom", },
699 MODULE_DEVICE_TABLE(of
, mvebu_pcie_of_match_table
);
701 static struct platform_driver bcm47xx_sprom_driver
= {
703 .owner
= THIS_MODULE
,
704 .name
= "bcm47xx-sprom",
705 .of_match_table
= bcm47xx_sprom_of_match_table
,
706 /* driver unloading/unbinding currently not supported */
707 .suppress_bind_attrs
= true,
709 .probe
= bcm47xx_sprom_probe
,
711 module_platform_driver(bcm47xx_sprom_driver
);
713 MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
714 MODULE_LICENSE("GPL v2");