diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/b43/phy_lp.c | 507 |
1 files changed, 460 insertions, 47 deletions
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 296e209a8c10..cfb8337d3859 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -605,6 +605,8 @@ static void lpphy_radio_init(struct b43_wldev *dev) | |||
605 | } | 605 | } |
606 | } | 606 | } |
607 | 607 | ||
608 | struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; }; | ||
609 | |||
608 | static void lpphy_set_rc_cap(struct b43_wldev *dev) | 610 | static void lpphy_set_rc_cap(struct b43_wldev *dev) |
609 | { | 611 | { |
610 | u8 rc_cap = dev->phy.lp->rc_cap; | 612 | u8 rc_cap = dev->phy.lp->rc_cap; |
@@ -614,79 +616,326 @@ static void lpphy_set_rc_cap(struct b43_wldev *dev) | |||
614 | b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80); | 616 | b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80); |
615 | } | 617 | } |
616 | 618 | ||
617 | static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) | 619 | static u8 lpphy_get_bb_mult(struct b43_wldev *dev) |
618 | { | 620 | { |
619 | //TODO and SPEC FIXME | 621 | return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8; |
620 | } | 622 | } |
621 | 623 | ||
622 | static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev) | 624 | static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult) |
623 | { | 625 | { |
624 | struct ssb_bus *bus = dev->dev->bus; | 626 | b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8); |
625 | u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; | 627 | } |
626 | u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF; | ||
627 | int i; | ||
628 | 628 | ||
629 | b43_radio_write(dev, B2063_RX_BB_SP8, 0x0); | 629 | static void lpphy_disable_crs(struct b43_wldev *dev) |
630 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | 630 | { |
631 | b43_radio_mask(dev, B2063_PLL_SP1, 0xF7); | 631 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80); |
632 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); | 632 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1); |
633 | b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15); | 633 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); |
634 | b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70); | 634 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB); |
635 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52); | 635 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4); |
636 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); | 636 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7); |
637 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D); | 637 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8); |
638 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10); | ||
639 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); | ||
640 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF); | ||
641 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20); | ||
642 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF); | ||
643 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); | ||
644 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7); | ||
645 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38); | ||
646 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F); | ||
647 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100); | ||
648 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF); | ||
649 | b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0); | ||
650 | b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1); | ||
651 | b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20); | ||
652 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF); | ||
653 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF); | ||
654 | b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0); | ||
655 | b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF); | ||
656 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF); | ||
657 | } | ||
638 | 658 | ||
639 | for (i = 0; i < 10000; i++) { | 659 | static void lpphy_restore_crs(struct b43_wldev *dev) |
640 | if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) | 660 | { |
641 | break; | 661 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
642 | msleep(1); | 662 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60); |
663 | else | ||
664 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x20); | ||
665 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80); | ||
666 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00); | ||
667 | } | ||
668 | |||
669 | struct lpphy_tx_gains { u16 gm, pga, pad, dac; }; | ||
670 | |||
671 | static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev) | ||
672 | { | ||
673 | struct lpphy_tx_gains gains; | ||
674 | u16 tmp; | ||
675 | |||
676 | gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7; | ||
677 | if (dev->phy.rev < 2) { | ||
678 | tmp = b43_phy_read(dev, | ||
679 | B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF; | ||
680 | gains.gm = tmp & 0x0007; | ||
681 | gains.pga = (tmp & 0x0078) >> 3; | ||
682 | gains.pad = (tmp & 0x780) >> 7; | ||
683 | } else { | ||
684 | tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL); | ||
685 | gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF; | ||
686 | gains.gm = tmp & 0xFF; | ||
687 | gains.pga = (tmp >> 8) & 0xFF; | ||
643 | } | 688 | } |
644 | 689 | ||
645 | if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) | 690 | return gains; |
646 | b43_radio_write(dev, B2063_RX_BB_SP8, tmp); | 691 | } |
647 | 692 | ||
648 | tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF; | 693 | static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac) |
694 | { | ||
695 | u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F; | ||
696 | ctl |= dac << 7; | ||
697 | b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl); | ||
698 | } | ||
649 | 699 | ||
650 | b43_radio_write(dev, B2063_TX_BB_SP3, 0x0); | 700 | static void lpphy_set_tx_gains(struct b43_wldev *dev, |
651 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | 701 | struct lpphy_tx_gains gains) |
652 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); | 702 | { |
653 | b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55); | 703 | u16 rf_gain, pa_gain; |
654 | b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76); | ||
655 | 704 | ||
656 | if (crystal_freq == 24000000) { | 705 | if (dev->phy.rev < 2) { |
657 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC); | 706 | rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm; |
658 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0); | 707 | b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, |
708 | 0xF800, rf_gain); | ||
659 | } else { | 709 | } else { |
660 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13); | 710 | pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00; |
661 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); | 711 | b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, |
712 | (gains.pga << 8) | gains.gm); | ||
713 | b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, | ||
714 | 0x8000, gains.pad | pa_gain); | ||
715 | b43_phy_write(dev, B43_PHY_OFDM(0xFC), | ||
716 | (gains.pga << 8) | gains.gm); | ||
717 | b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), | ||
718 | 0x8000, gains.pad | pa_gain); | ||
662 | } | 719 | } |
720 | lpphy_set_dac_gain(dev, gains.dac); | ||
721 | if (dev->phy.rev < 2) { | ||
722 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8); | ||
723 | } else { | ||
724 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7); | ||
725 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14); | ||
726 | } | ||
727 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 4); | ||
728 | } | ||
663 | 729 | ||
664 | b43_radio_write(dev, B2063_PA_SP7, 0x7D); | 730 | static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain) |
731 | { | ||
732 | u16 trsw = gain & 0x1; | ||
733 | u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2); | ||
734 | u16 ext_lna = (gain & 2) >> 1; | ||
735 | |||
736 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw); | ||
737 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
738 | 0xFBFF, ext_lna << 10); | ||
739 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
740 | 0xF7FF, ext_lna << 11); | ||
741 | b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna); | ||
742 | } | ||
665 | 743 | ||
666 | for (i = 0; i < 10000; i++) { | 744 | static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain) |
667 | if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) | 745 | { |
746 | u16 low_gain = gain & 0xFFFF; | ||
747 | u16 high_gain = (gain >> 16) & 0xF; | ||
748 | u16 ext_lna = (gain >> 21) & 0x1; | ||
749 | u16 trsw = ~(gain >> 20) & 0x1; | ||
750 | u16 tmp; | ||
751 | |||
752 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw); | ||
753 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
754 | 0xFDFF, ext_lna << 9); | ||
755 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
756 | 0xFBFF, ext_lna << 10); | ||
757 | b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain); | ||
758 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain); | ||
759 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
760 | tmp = (gain >> 2) & 0x3; | ||
761 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
762 | 0xE7FF, tmp<<11); | ||
763 | b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3); | ||
764 | } | ||
765 | } | ||
766 | |||
767 | static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) | ||
768 | { | ||
769 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE); | ||
770 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF); | ||
771 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF); | ||
772 | if (dev->phy.rev >= 2) { | ||
773 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF); | ||
774 | if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ) | ||
775 | return; | ||
776 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF); | ||
777 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFF7); | ||
778 | } else { | ||
779 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); | ||
780 | } | ||
781 | } | ||
782 | |||
783 | static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) | ||
784 | { | ||
785 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1); | ||
786 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); | ||
787 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); | ||
788 | if (dev->phy.rev >= 2) { | ||
789 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100); | ||
790 | if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ) | ||
791 | return; | ||
792 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400); | ||
793 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x8); | ||
794 | } else { | ||
795 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200); | ||
796 | } | ||
797 | } | ||
798 | |||
799 | static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain) | ||
800 | { | ||
801 | if (dev->phy.rev < 2) | ||
802 | lpphy_rev0_1_set_rx_gain(dev, gain); | ||
803 | else | ||
804 | lpphy_rev2plus_set_rx_gain(dev, gain); | ||
805 | lpphy_enable_rx_gain_override(dev); | ||
806 | } | ||
807 | |||
808 | static void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx) | ||
809 | { | ||
810 | u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx)); | ||
811 | lpphy_set_rx_gain(dev, gain); | ||
812 | } | ||
813 | |||
814 | static void lpphy_stop_ddfs(struct b43_wldev *dev) | ||
815 | { | ||
816 | b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD); | ||
817 | b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF); | ||
818 | } | ||
819 | |||
820 | static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on, | ||
821 | int incr1, int incr2, int scale_idx) | ||
822 | { | ||
823 | lpphy_stop_ddfs(dev); | ||
824 | b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80); | ||
825 | b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF); | ||
826 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1); | ||
827 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 8); | ||
828 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3); | ||
829 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4); | ||
830 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5); | ||
831 | b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB); | ||
832 | b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2); | ||
833 | b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x20); | ||
834 | } | ||
835 | |||
836 | static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time, | ||
837 | struct lpphy_iq_est *iq_est) | ||
838 | { | ||
839 | int i; | ||
840 | |||
841 | b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7); | ||
842 | b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples); | ||
843 | b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time); | ||
844 | b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF); | ||
845 | b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFDFF); | ||
846 | |||
847 | for (i = 0; i < 500; i++) { | ||
848 | if (!(b43_phy_read(dev, | ||
849 | B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) | ||
668 | break; | 850 | break; |
669 | msleep(1); | 851 | msleep(1); |
670 | } | 852 | } |
671 | 853 | ||
672 | if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) | 854 | if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) { |
673 | b43_radio_write(dev, B2063_TX_BB_SP3, tmp); | 855 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8); |
856 | return false; | ||
857 | } | ||
674 | 858 | ||
675 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | 859 | iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR); |
860 | iq_est->iq_prod <<= 16; | ||
861 | iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR); | ||
862 | |||
863 | iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR); | ||
864 | iq_est->i_pwr <<= 16; | ||
865 | iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR); | ||
866 | |||
867 | iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR); | ||
868 | iq_est->q_pwr <<= 16; | ||
869 | iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR); | ||
870 | |||
871 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8); | ||
872 | return true; | ||
676 | } | 873 | } |
677 | 874 | ||
678 | static void lpphy_calibrate_rc(struct b43_wldev *dev) | 875 | static int lpphy_loopback(struct b43_wldev *dev) |
679 | { | 876 | { |
680 | struct b43_phy_lp *lpphy = dev->phy.lp; | 877 | struct lpphy_iq_est iq_est; |
878 | int i, index = -1; | ||
879 | u32 tmp; | ||
880 | |||
881 | memset(&iq_est, 0, sizeof(iq_est)); | ||
882 | |||
883 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3); | ||
884 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); | ||
885 | b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE); | ||
886 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800); | ||
887 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800); | ||
888 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8); | ||
889 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8); | ||
890 | b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80); | ||
891 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80); | ||
892 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80); | ||
893 | for (i = 0; i < 32; i++) { | ||
894 | lpphy_set_rx_gain_by_index(dev, i); | ||
895 | lpphy_run_ddfs(dev, 1, 1, 5, 5, 0); | ||
896 | if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est))) | ||
897 | continue; | ||
898 | tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000; | ||
899 | if ((tmp > 4000) && (tmp < 10000)) { | ||
900 | index = i; | ||
901 | break; | ||
902 | } | ||
903 | } | ||
904 | lpphy_stop_ddfs(dev); | ||
905 | return index; | ||
906 | } | ||
681 | 907 | ||
682 | if (dev->phy.rev >= 2) { | 908 | static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) |
683 | lpphy_rev2plus_rc_calib(dev); | 909 | { |
684 | } else if (!lpphy->rc_cap) { | 910 | u32 quotient, remainder, rbit, roundup, tmp; |
685 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 911 | |
686 | lpphy_rev0_1_rc_calib(dev); | 912 | if (divisor == 0) { |
913 | quotient = 0; | ||
914 | remainder = 0; | ||
687 | } else { | 915 | } else { |
688 | lpphy_set_rc_cap(dev); | 916 | quotient = dividend / divisor; |
917 | remainder = dividend % divisor; | ||
689 | } | 918 | } |
919 | |||
920 | rbit = divisor & 0x1; | ||
921 | roundup = (divisor >> 1) + rbit; | ||
922 | precision--; | ||
923 | |||
924 | while (precision != 0xFF) { | ||
925 | tmp = remainder - roundup; | ||
926 | quotient <<= 1; | ||
927 | remainder <<= 1; | ||
928 | if (remainder >= roundup) { | ||
929 | remainder = (tmp << 1) + rbit; | ||
930 | quotient--; | ||
931 | } | ||
932 | precision--; | ||
933 | } | ||
934 | |||
935 | if (remainder >= roundup) | ||
936 | quotient++; | ||
937 | |||
938 | return quotient; | ||
690 | } | 939 | } |
691 | 940 | ||
692 | /* Read the TX power control mode from hardware. */ | 941 | /* Read the TX power control mode from hardware. */ |
@@ -773,6 +1022,170 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev, | |||
773 | lpphy_write_tx_pctl_mode_to_hardware(dev); | 1022 | lpphy_write_tx_pctl_mode_to_hardware(dev); |
774 | } | 1023 | } |
775 | 1024 | ||
1025 | static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) | ||
1026 | { | ||
1027 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
1028 | struct lpphy_iq_est iq_est; | ||
1029 | struct lpphy_tx_gains tx_gains; | ||
1030 | static const u32 ideal_pwr_table[22] = { | ||
1031 | 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64, | ||
1032 | 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35, | ||
1033 | 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088, | ||
1034 | 0x0004c, 0x0002c, 0x0001a, 0xc0006, | ||
1035 | }; | ||
1036 | bool old_txg_ovr; | ||
1037 | u8 old_bbmult; | ||
1038 | u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval, | ||
1039 | old_rf2_ovr, old_rf2_ovrval, old_phy_ctl, old_txpctl; | ||
1040 | u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0; | ||
1041 | int loopback, i, j, inner_sum; | ||
1042 | |||
1043 | memset(&iq_est, 0, sizeof(iq_est)); | ||
1044 | |||
1045 | b43_switch_channel(dev, 7); | ||
1046 | old_txg_ovr = (b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) >> 6) & 1; | ||
1047 | old_bbmult = lpphy_get_bb_mult(dev); | ||
1048 | if (old_txg_ovr) | ||
1049 | tx_gains = lpphy_get_tx_gains(dev); | ||
1050 | old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0); | ||
1051 | old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0); | ||
1052 | old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR); | ||
1053 | old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL); | ||
1054 | old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2); | ||
1055 | old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL); | ||
1056 | old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL); | ||
1057 | old_txpctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD) & | ||
1058 | B43_LPPHY_TX_PWR_CTL_CMD_MODE; | ||
1059 | |||
1060 | lpphy_set_tx_power_control(dev, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF); | ||
1061 | lpphy_disable_crs(dev); | ||
1062 | loopback = lpphy_loopback(dev); | ||
1063 | if (loopback == -1) | ||
1064 | goto finish; | ||
1065 | lpphy_set_rx_gain_by_index(dev, loopback); | ||
1066 | b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40); | ||
1067 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1); | ||
1068 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8); | ||
1069 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0); | ||
1070 | for (i = 128; i <= 159; i++) { | ||
1071 | b43_radio_write(dev, B2062_N_RXBB_CALIB2, i); | ||
1072 | inner_sum = 0; | ||
1073 | for (j = 5; j <= 25; j++) { | ||
1074 | lpphy_run_ddfs(dev, 1, 1, j, j, 0); | ||
1075 | if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est))) | ||
1076 | goto finish; | ||
1077 | mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr; | ||
1078 | if (j == 5) | ||
1079 | tmp = mean_sq_pwr; | ||
1080 | ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1; | ||
1081 | normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12); | ||
1082 | mean_sq_pwr = ideal_pwr - normal_pwr; | ||
1083 | mean_sq_pwr *= mean_sq_pwr; | ||
1084 | inner_sum += mean_sq_pwr; | ||
1085 | if ((i = 128) || (inner_sum < mean_sq_pwr_min)) { | ||
1086 | lpphy->rc_cap = i; | ||
1087 | mean_sq_pwr_min = inner_sum; | ||
1088 | } | ||
1089 | } | ||
1090 | } | ||
1091 | lpphy_stop_ddfs(dev); | ||
1092 | |||
1093 | finish: | ||
1094 | lpphy_restore_crs(dev); | ||
1095 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval); | ||
1096 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr); | ||
1097 | b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval); | ||
1098 | b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr); | ||
1099 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval); | ||
1100 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr); | ||
1101 | b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl); | ||
1102 | |||
1103 | lpphy_set_bb_mult(dev, old_bbmult); | ||
1104 | if (old_txg_ovr) { | ||
1105 | /* | ||
1106 | * SPEC FIXME: The specs say "get_tx_gains" here, which is | ||
1107 | * illogical. According to lwfinger, vendor driver v4.150.10.5 | ||
1108 | * has a Set here, while v4.174.64.19 has a Get - regression in | ||
1109 | * the vendor driver? This should be tested this once the code | ||
1110 | * is testable. | ||
1111 | */ | ||
1112 | lpphy_set_tx_gains(dev, tx_gains); | ||
1113 | } | ||
1114 | lpphy_set_tx_power_control(dev, old_txpctl); | ||
1115 | if (lpphy->rc_cap) | ||
1116 | lpphy_set_rc_cap(dev); | ||
1117 | } | ||
1118 | |||
1119 | static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev) | ||
1120 | { | ||
1121 | struct ssb_bus *bus = dev->dev->bus; | ||
1122 | u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; | ||
1123 | u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF; | ||
1124 | int i; | ||
1125 | |||
1126 | b43_radio_write(dev, B2063_RX_BB_SP8, 0x0); | ||
1127 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | ||
1128 | b43_radio_mask(dev, B2063_PLL_SP1, 0xF7); | ||
1129 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); | ||
1130 | b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15); | ||
1131 | b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70); | ||
1132 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52); | ||
1133 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); | ||
1134 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D); | ||
1135 | |||
1136 | for (i = 0; i < 10000; i++) { | ||
1137 | if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) | ||
1138 | break; | ||
1139 | msleep(1); | ||
1140 | } | ||
1141 | |||
1142 | if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) | ||
1143 | b43_radio_write(dev, B2063_RX_BB_SP8, tmp); | ||
1144 | |||
1145 | tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF; | ||
1146 | |||
1147 | b43_radio_write(dev, B2063_TX_BB_SP3, 0x0); | ||
1148 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | ||
1149 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); | ||
1150 | b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55); | ||
1151 | b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76); | ||
1152 | |||
1153 | if (crystal_freq == 24000000) { | ||
1154 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC); | ||
1155 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0); | ||
1156 | } else { | ||
1157 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13); | ||
1158 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); | ||
1159 | } | ||
1160 | |||
1161 | b43_radio_write(dev, B2063_PA_SP7, 0x7D); | ||
1162 | |||
1163 | for (i = 0; i < 10000; i++) { | ||
1164 | if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) | ||
1165 | break; | ||
1166 | msleep(1); | ||
1167 | } | ||
1168 | |||
1169 | if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) | ||
1170 | b43_radio_write(dev, B2063_TX_BB_SP3, tmp); | ||
1171 | |||
1172 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | ||
1173 | } | ||
1174 | |||
1175 | static void lpphy_calibrate_rc(struct b43_wldev *dev) | ||
1176 | { | ||
1177 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
1178 | |||
1179 | if (dev->phy.rev >= 2) { | ||
1180 | lpphy_rev2plus_rc_calib(dev); | ||
1181 | } else if (!lpphy->rc_cap) { | ||
1182 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
1183 | lpphy_rev0_1_rc_calib(dev); | ||
1184 | } else { | ||
1185 | lpphy_set_rc_cap(dev); | ||
1186 | } | ||
1187 | } | ||
1188 | |||
776 | static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index) | 1189 | static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index) |
777 | { | 1190 | { |
778 | struct b43_phy_lp *lpphy = dev->phy.lp; | 1191 | struct b43_phy_lp *lpphy = dev->phy.lp; |