diff options
author | Gábor Stefanik <netrolller.3d@gmail.com> | 2009-08-11 15:53:06 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-14 09:14:03 -0400 |
commit | d4de9532fd0b50d486259ace17650a58bbb751c2 (patch) | |
tree | f2a10d510be7edaac7938237e40e3fe85740a422 /drivers | |
parent | 84ec167d327b42414285f22eb037a5bdee486ded (diff) |
b43: Implement RC calibration for rev.2+ LP PHYs
Signed-off-by: Gábor Stefanik <netrolller.3d@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/b43/phy_lp.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 2bec791041fe..296e209a8c10 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -605,6 +605,90 @@ static void lpphy_radio_init(struct b43_wldev *dev) | |||
605 | } | 605 | } |
606 | } | 606 | } |
607 | 607 | ||
608 | static void lpphy_set_rc_cap(struct b43_wldev *dev) | ||
609 | { | ||
610 | u8 rc_cap = dev->phy.lp->rc_cap; | ||
611 | |||
612 | b43_radio_write(dev, B2062_N_RXBB_CALIB2, max_t(u8, rc_cap-4, 0x80)); | ||
613 | b43_radio_write(dev, B2062_N_TX_CTL_A, ((rc_cap & 0x1F) >> 1) | 0x80); | ||
614 | b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80); | ||
615 | } | ||
616 | |||
617 | static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) | ||
618 | { | ||
619 | //TODO and SPEC FIXME | ||
620 | } | ||
621 | |||
622 | static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev) | ||
623 | { | ||
624 | struct ssb_bus *bus = dev->dev->bus; | ||
625 | u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; | ||
626 | u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF; | ||
627 | int i; | ||
628 | |||
629 | b43_radio_write(dev, B2063_RX_BB_SP8, 0x0); | ||
630 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | ||
631 | b43_radio_mask(dev, B2063_PLL_SP1, 0xF7); | ||
632 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); | ||
633 | b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15); | ||
634 | b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70); | ||
635 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52); | ||
636 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); | ||
637 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D); | ||
638 | |||
639 | for (i = 0; i < 10000; i++) { | ||
640 | if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) | ||
641 | break; | ||
642 | msleep(1); | ||
643 | } | ||
644 | |||
645 | if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) | ||
646 | b43_radio_write(dev, B2063_RX_BB_SP8, tmp); | ||
647 | |||
648 | tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF; | ||
649 | |||
650 | b43_radio_write(dev, B2063_TX_BB_SP3, 0x0); | ||
651 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | ||
652 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); | ||
653 | b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55); | ||
654 | b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76); | ||
655 | |||
656 | if (crystal_freq == 24000000) { | ||
657 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC); | ||
658 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0); | ||
659 | } else { | ||
660 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13); | ||
661 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); | ||
662 | } | ||
663 | |||
664 | b43_radio_write(dev, B2063_PA_SP7, 0x7D); | ||
665 | |||
666 | for (i = 0; i < 10000; i++) { | ||
667 | if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) | ||
668 | break; | ||
669 | msleep(1); | ||
670 | } | ||
671 | |||
672 | if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) | ||
673 | b43_radio_write(dev, B2063_TX_BB_SP3, tmp); | ||
674 | |||
675 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | ||
676 | } | ||
677 | |||
678 | static void lpphy_calibrate_rc(struct b43_wldev *dev) | ||
679 | { | ||
680 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
681 | |||
682 | if (dev->phy.rev >= 2) { | ||
683 | lpphy_rev2plus_rc_calib(dev); | ||
684 | } else if (!lpphy->rc_cap) { | ||
685 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
686 | lpphy_rev0_1_rc_calib(dev); | ||
687 | } else { | ||
688 | lpphy_set_rc_cap(dev); | ||
689 | } | ||
690 | } | ||
691 | |||
608 | /* Read the TX power control mode from hardware. */ | 692 | /* Read the TX power control mode from hardware. */ |
609 | static void lpphy_read_tx_pctl_mode_from_hardware(struct b43_wldev *dev) | 693 | static void lpphy_read_tx_pctl_mode_from_hardware(struct b43_wldev *dev) |
610 | { | 694 | { |
@@ -780,7 +864,7 @@ static int b43_lpphy_op_init(struct b43_wldev *dev) | |||
780 | lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs? | 864 | lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs? |
781 | lpphy_baseband_init(dev); | 865 | lpphy_baseband_init(dev); |
782 | lpphy_radio_init(dev); | 866 | lpphy_radio_init(dev); |
783 | //TODO calibrate RC | 867 | lpphy_calibrate_rc(dev); |
784 | //TODO set channel | 868 | //TODO set channel |
785 | lpphy_tx_pctl_init(dev); | 869 | lpphy_tx_pctl_init(dev); |
786 | lpphy_calibration(dev); | 870 | lpphy_calibration(dev); |