aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb/pci.c
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2007-12-22 15:51:30 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:09:14 -0500
commite861b98d5e1be769ca6483b6df97149b956ea834 (patch)
tree88754e03eddc9a7b1441421125a776c5cbd597d1 /drivers/ssb/pci.c
parent66c6b139f77e8568f03611422967bfaa4c4a3bbd (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/pci.c')
-rw-r--r--drivers/ssb/pci.c76
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
253static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) 253static 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
300static 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
300static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) 321static 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
356static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) 398static 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);