diff options
author | Michael Buesch <mb@bu3sch.de> | 2007-12-22 15:51:30 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:09:14 -0500 |
commit | e861b98d5e1be769ca6483b6df97149b956ea834 (patch) | |
tree | 88754e03eddc9a7b1441421125a776c5cbd597d1 /drivers/ssb | |
parent | 66c6b139f77e8568f03611422967bfaa4c4a3bbd (diff) |
ssb: Fix extraction of values from SPROM
This fixes extraction of some values from the SPROM.
It mainly fixes extraction of antenna related values, which
is needed for another b43 fix sent later.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/ssb')
-rw-r--r-- | drivers/ssb/pci.c | 76 |
1 files changed, 65 insertions, 11 deletions
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 9777dcb5bfe5..ed2a38752274 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -247,7 +247,7 @@ static void sprom_do_read(struct ssb_bus *bus, u16 *sprom) | |||
247 | int i; | 247 | int i; |
248 | 248 | ||
249 | for (i = 0; i < bus->sprom_size; i++) | 249 | for (i = 0; i < bus->sprom_size; i++) |
250 | sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2)); | 250 | sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2)); |
251 | } | 251 | } |
252 | 252 | ||
253 | static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) | 253 | static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) |
@@ -297,10 +297,32 @@ err_ctlreg: | |||
297 | return err; | 297 | return err; |
298 | } | 298 | } |
299 | 299 | ||
300 | static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, | ||
301 | u16 mask, u16 shift) | ||
302 | { | ||
303 | u16 v; | ||
304 | u8 gain; | ||
305 | |||
306 | v = in[SPOFF(SSB_SPROM1_AGAIN)]; | ||
307 | gain = (v & mask) >> shift; | ||
308 | if (gain == 0xFF) | ||
309 | gain = 2; /* If unset use 2dBm */ | ||
310 | if (sprom_revision == 1) { | ||
311 | /* Convert to Q5.2 */ | ||
312 | gain <<= 2; | ||
313 | } else { | ||
314 | /* Q5.2 Fractional part is stored in 0xC0 */ | ||
315 | gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); | ||
316 | } | ||
317 | |||
318 | return (s8)gain; | ||
319 | } | ||
320 | |||
300 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | 321 | static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) |
301 | { | 322 | { |
302 | int i; | 323 | int i; |
303 | u16 v; | 324 | u16 v; |
325 | s8 gain; | ||
304 | u16 loc[3]; | 326 | u16 loc[3]; |
305 | 327 | ||
306 | if (out->revision == 3) { /* rev 3 moved MAC */ | 328 | if (out->revision == 3) { /* rev 3 moved MAC */ |
@@ -327,8 +349,15 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
327 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); | 349 | SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); |
328 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, | 350 | SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, |
329 | SSB_SPROM1_ETHPHY_ET1A_SHIFT); | 351 | SSB_SPROM1_ETHPHY_ET1A_SHIFT); |
352 | SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); | ||
353 | SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); | ||
354 | SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); | ||
330 | SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, | 355 | SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, |
331 | SSB_SPROM1_BINF_CCODE_SHIFT); | 356 | SSB_SPROM1_BINF_CCODE_SHIFT); |
357 | SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, | ||
358 | SSB_SPROM1_BINF_ANTA_SHIFT); | ||
359 | SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, | ||
360 | SSB_SPROM1_BINF_ANTBG_SHIFT); | ||
332 | SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); | 361 | SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); |
333 | SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); | 362 | SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); |
334 | SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); | 363 | SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); |
@@ -348,9 +377,22 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
348 | SSB_SPROM1_ITSSI_A_SHIFT); | 377 | SSB_SPROM1_ITSSI_A_SHIFT); |
349 | SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); | 378 | SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); |
350 | SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); | 379 | SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); |
351 | SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0); | 380 | |
352 | SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG, | 381 | /* Extract the antenna gain values. */ |
353 | SSB_SPROM1_AGAIN_BG_SHIFT); | 382 | gain = r123_extract_antgain(out->revision, in, |
383 | SSB_SPROM1_AGAIN_BG, | ||
384 | SSB_SPROM1_AGAIN_BG_SHIFT); | ||
385 | out->antenna_gain.ghz24.a0 = gain; | ||
386 | out->antenna_gain.ghz24.a1 = gain; | ||
387 | out->antenna_gain.ghz24.a2 = gain; | ||
388 | out->antenna_gain.ghz24.a3 = gain; | ||
389 | gain = r123_extract_antgain(out->revision, in, | ||
390 | SSB_SPROM1_AGAIN_A, | ||
391 | SSB_SPROM1_AGAIN_A_SHIFT); | ||
392 | out->antenna_gain.ghz5.a0 = gain; | ||
393 | out->antenna_gain.ghz5.a1 = gain; | ||
394 | out->antenna_gain.ghz5.a2 = gain; | ||
395 | out->antenna_gain.ghz5.a3 = gain; | ||
354 | } | 396 | } |
355 | 397 | ||
356 | static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) | 398 | static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) |
@@ -376,9 +418,10 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) | |||
376 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); | 418 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); |
377 | SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); | 419 | SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); |
378 | SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); | 420 | SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); |
379 | SPEX(antenna_gain_a, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_0, 0); | 421 | SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, |
380 | SPEX(antenna_gain_bg, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_1, | 422 | SSB_SPROM4_ANTAVAIL_A_SHIFT); |
381 | SSB_SPROM4_AGAIN_1_SHIFT); | 423 | SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG, |
424 | SSB_SPROM4_ANTAVAIL_BG_SHIFT); | ||
382 | SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0); | 425 | SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0); |
383 | SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG, | 426 | SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG, |
384 | SSB_SPROM4_ITSSI_BG_SHIFT); | 427 | SSB_SPROM4_ITSSI_BG_SHIFT); |
@@ -391,6 +434,19 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) | |||
391 | SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); | 434 | SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); |
392 | SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, | 435 | SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, |
393 | SSB_SPROM4_GPIOB_P3_SHIFT); | 436 | SSB_SPROM4_GPIOB_P3_SHIFT); |
437 | |||
438 | /* Extract the antenna gain values. */ | ||
439 | SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01, | ||
440 | SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT); | ||
441 | SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01, | ||
442 | SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT); | ||
443 | SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23, | ||
444 | SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT); | ||
445 | SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23, | ||
446 | SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT); | ||
447 | memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, | ||
448 | sizeof(out->antenna_gain.ghz5)); | ||
449 | |||
394 | /* TODO - get remaining rev 4 stuff needed */ | 450 | /* TODO - get remaining rev 4 stuff needed */ |
395 | } | 451 | } |
396 | 452 | ||
@@ -400,7 +456,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, | |||
400 | memset(out, 0, sizeof(*out)); | 456 | memset(out, 0, sizeof(*out)); |
401 | 457 | ||
402 | out->revision = in[size - 1] & 0x00FF; | 458 | out->revision = in[size - 1] & 0x00FF; |
403 | ssb_printk(KERN_INFO PFX "SPROM revision %d detected.\n", out->revision); | 459 | ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); |
404 | if ((bus->chip_id & 0xFF00) == 0x4400) { | 460 | if ((bus->chip_id & 0xFF00) == 0x4400) { |
405 | /* Workaround: The BCM44XX chip has a stupid revision | 461 | /* Workaround: The BCM44XX chip has a stupid revision |
406 | * number stored in the SPROM. | 462 | * number stored in the SPROM. |
@@ -445,9 +501,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, | |||
445 | err = sprom_check_crc(buf, bus->sprom_size); | 501 | err = sprom_check_crc(buf, bus->sprom_size); |
446 | if (err) { | 502 | if (err) { |
447 | /* check for rev 4 sprom - has special signature */ | 503 | /* check for rev 4 sprom - has special signature */ |
448 | if (buf [32] == 0x5372) { | 504 | if (buf[32] == 0x5372) { |
449 | ssb_printk(KERN_WARNING PFX "Extracting a rev 4" | ||
450 | " SPROM\n"); | ||
451 | kfree(buf); | 505 | kfree(buf); |
452 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), | 506 | buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), |
453 | GFP_KERNEL); | 507 | GFP_KERNEL); |