aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ssb/pci.c')
-rw-r--r--drivers/ssb/pci.c118
1 files changed, 84 insertions, 34 deletions
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 6e88d2b603b4..7ad48585c5e6 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -406,6 +406,46 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
406 out->antenna_gain.ghz5.a3 = gain; 406 out->antenna_gain.ghz5.a3 = gain;
407} 407}
408 408
409/* Revs 4 5 and 8 have partially shared layout */
410static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
411{
412 SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
413 SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
414 SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
415 SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
416 SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
417 SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
418 SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
419 SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
420
421 SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
422 SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
423 SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
424 SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
425 SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
426 SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
427 SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
428 SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
429
430 SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
431 SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
432 SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
433 SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
434 SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
435 SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
436 SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
437 SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
438
439 SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
440 SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
441 SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
442 SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
443 SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
444 SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
445 SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
446 SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
447}
448
409static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) 449static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
410{ 450{
411 int i; 451 int i;
@@ -428,10 +468,14 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
428 SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); 468 SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
429 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); 469 SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
430 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); 470 SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
471 SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
472 SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
431 } else { 473 } else {
432 SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0); 474 SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
433 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); 475 SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
434 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); 476 SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
477 SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
478 SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
435 } 479 }
436 SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, 480 SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
437 SSB_SPROM4_ANTAVAIL_A_SHIFT); 481 SSB_SPROM4_ANTAVAIL_A_SHIFT);
@@ -471,6 +515,8 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
471 memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, 515 memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
472 sizeof(out->antenna_gain.ghz5)); 516 sizeof(out->antenna_gain.ghz5));
473 517
518 sprom_extract_r458(out, in);
519
474 /* TODO - get remaining rev 4 stuff needed */ 520 /* TODO - get remaining rev 4 stuff needed */
475} 521}
476 522
@@ -561,6 +607,8 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
561 memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, 607 memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
562 sizeof(out->antenna_gain.ghz5)); 608 sizeof(out->antenna_gain.ghz5));
563 609
610 sprom_extract_r458(out, in);
611
564 /* TODO - get remaining rev 8 stuff needed */ 612 /* TODO - get remaining rev 8 stuff needed */
565} 613}
566 614
@@ -573,37 +621,34 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
573 ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); 621 ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
574 memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */ 622 memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
575 memset(out->et1mac, 0xFF, 6); 623 memset(out->et1mac, 0xFF, 6);
624
576 if ((bus->chip_id & 0xFF00) == 0x4400) { 625 if ((bus->chip_id & 0xFF00) == 0x4400) {
577 /* Workaround: The BCM44XX chip has a stupid revision 626 /* Workaround: The BCM44XX chip has a stupid revision
578 * number stored in the SPROM. 627 * number stored in the SPROM.
579 * Always extract r1. */ 628 * Always extract r1. */
580 out->revision = 1; 629 out->revision = 1;
630 ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
631 }
632
633 switch (out->revision) {
634 case 1:
635 case 2:
636 case 3:
581 sprom_extract_r123(out, in); 637 sprom_extract_r123(out, in);
582 } else if (bus->chip_id == 0x4321) { 638 break;
583 /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */ 639 case 4:
584 out->revision = 4; 640 case 5:
585 sprom_extract_r45(out, in); 641 sprom_extract_r45(out, in);
586 } else { 642 break;
587 switch (out->revision) { 643 case 8:
588 case 1: 644 sprom_extract_r8(out, in);
589 case 2: 645 break;
590 case 3: 646 default:
591 sprom_extract_r123(out, in); 647 ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
592 break; 648 " revision %d detected. Will extract"
593 case 4: 649 " v1\n", out->revision);
594 case 5: 650 out->revision = 1;
595 sprom_extract_r45(out, in); 651 sprom_extract_r123(out, in);
596 break;
597 case 8:
598 sprom_extract_r8(out, in);
599 break;
600 default:
601 ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
602 " revision %d detected. Will extract"
603 " v1\n", out->revision);
604 out->revision = 1;
605 sprom_extract_r123(out, in);
606 }
607 } 652 }
608 653
609 if (out->boardflags_lo == 0xFFFF) 654 if (out->boardflags_lo == 0xFFFF)
@@ -617,15 +662,14 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
617static int ssb_pci_sprom_get(struct ssb_bus *bus, 662static int ssb_pci_sprom_get(struct ssb_bus *bus,
618 struct ssb_sprom *sprom) 663 struct ssb_sprom *sprom)
619{ 664{
620 const struct ssb_sprom *fallback; 665 int err;
621 int err = -ENOMEM;
622 u16 *buf; 666 u16 *buf;
623 667
624 if (!ssb_is_sprom_available(bus)) { 668 if (!ssb_is_sprom_available(bus)) {
625 ssb_printk(KERN_ERR PFX "No SPROM available!\n"); 669 ssb_printk(KERN_ERR PFX "No SPROM available!\n");
626 return -ENODEV; 670 return -ENODEV;
627 } 671 }
628 if (bus->chipco.dev) { /* can be unavailible! */ 672 if (bus->chipco.dev) { /* can be unavailable! */
629 /* 673 /*
630 * get SPROM offset: SSB_SPROM_BASE1 except for 674 * get SPROM offset: SSB_SPROM_BASE1 except for
631 * chipcommon rev >= 31 or chip ID is 0x4312 and 675 * chipcommon rev >= 31 or chip ID is 0x4312 and
@@ -645,7 +689,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
645 689
646 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); 690 buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
647 if (!buf) 691 if (!buf)
648 goto out; 692 return -ENOMEM;
649 bus->sprom_size = SSB_SPROMSIZE_WORDS_R123; 693 bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
650 sprom_do_read(bus, buf); 694 sprom_do_read(bus, buf);
651 err = sprom_check_crc(buf, bus->sprom_size); 695 err = sprom_check_crc(buf, bus->sprom_size);
@@ -655,17 +699,24 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
655 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), 699 buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
656 GFP_KERNEL); 700 GFP_KERNEL);
657 if (!buf) 701 if (!buf)
658 goto out; 702 return -ENOMEM;
659 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4; 703 bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
660 sprom_do_read(bus, buf); 704 sprom_do_read(bus, buf);
661 err = sprom_check_crc(buf, bus->sprom_size); 705 err = sprom_check_crc(buf, bus->sprom_size);
662 if (err) { 706 if (err) {
663 /* All CRC attempts failed. 707 /* All CRC attempts failed.
664 * Maybe there is no SPROM on the device? 708 * Maybe there is no SPROM on the device?
665 * If we have a fallback, use that. */ 709 * Now we ask the arch code if there is some sprom
666 fallback = ssb_get_fallback_sprom(); 710 * available for this device in some other storage */
667 if (fallback) { 711 err = ssb_fill_sprom_with_fallback(bus, sprom);
668 memcpy(sprom, fallback, sizeof(*sprom)); 712 if (err) {
713 ssb_printk(KERN_WARNING PFX "WARNING: Using"
714 " fallback SPROM failed (err %d)\n",
715 err);
716 } else {
717 ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
718 " revision %d provided by"
719 " platform.\n", sprom->revision);
669 err = 0; 720 err = 0;
670 goto out_free; 721 goto out_free;
671 } 722 }
@@ -677,7 +728,6 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
677 728
678out_free: 729out_free:
679 kfree(buf); 730 kfree(buf);
680out:
681 return err; 731 return err;
682} 732}
683 733