aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVivek Natarajan <vnatarajan@atheros.com>2009-09-18 05:33:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:38 -0400
commit0b98eaaa02965fb06dee4ad8c605bb3c93df2c98 (patch)
tree564b56fb04c8e4a199f5bb0470570f870a5e9c74
parent181af387033e20065e94363d07ecbace7738278c (diff)
ath9k: Add Calibration checks
* Prevent divide-by-zero errors in IQ Calibration. * Do not run temperature compensation if initPDADC or currPDADC is zero. * Also, introduce a separate function for handling OLC for AR9287. Signed-off-by: Vivek Natarajan <vnatarajan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c78
1 files changed, 50 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 36c5f89e2fc7..9c46b54d2a98 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -403,7 +403,8 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
403 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; 403 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
404 qCoffDenom = powerMeasQ / 64; 404 qCoffDenom = powerMeasQ / 64;
405 405
406 if (powerMeasQ != 0) { 406 if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
407 (qCoffDenom != 0)) {
407 iCoff = iqCorrMeas / iCoffDenom; 408 iCoff = iqCorrMeas / iCoffDenom;
408 qCoff = powerMeasI / qCoffDenom - 64; 409 qCoff = powerMeasI / qCoffDenom - 64;
409 ath_print(common, ATH_DBG_CALIBRATE, 410 ath_print(common, ATH_DBG_CALIBRATE,
@@ -746,44 +747,65 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
746 return nf; 747 return nf;
747} 748}
748 749
749static void ath9k_olc_temp_compensation(struct ath_hw *ah) 750static void ath9k_olc_temp_compensation_9287(struct ath_hw *ah)
750{ 751{
751 u32 rddata, i; 752 u32 rddata;
752 int delta, currPDADC, regval, slope; 753 int32_t delta, currPDADC, slope;
753 754
754 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); 755 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
755 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); 756 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
756 757
758 if (ah->initPDADC == 0 || currPDADC == 0) {
759 /*
760 * Zero value indicates that no frames have been transmitted yet,
761 * can't do temperature compensation until frames are transmitted.
762 */
763 return;
764 } else {
765 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
766
767 if (slope == 0) { /* to avoid divide by zero case */
768 delta = 0;
769 } else {
770 delta = ((currPDADC - ah->initPDADC)*4) / slope;
771 }
772 REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
773 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
774 REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
775 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
776 }
777}
778
779static void ath9k_olc_temp_compensation(struct ath_hw *ah)
780{
781 u32 rddata, i;
782 int delta, currPDADC, regval;
757 783
758 if (OLC_FOR_AR9287_10_LATER) { 784 if (OLC_FOR_AR9287_10_LATER) {
785 ath9k_olc_temp_compensation_9287(ah);
786 } else {
787 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
788 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
789
759 if (ah->initPDADC == 0 || currPDADC == 0) { 790 if (ah->initPDADC == 0 || currPDADC == 0) {
760 return; 791 return;
761 } else { 792 } else {
762 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); 793 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
763 if (slope == 0) 794 delta = (currPDADC - ah->initPDADC + 4) / 8;
764 delta = 0;
765 else 795 else
766 delta = ((currPDADC - ah->initPDADC)*4) / slope; 796 delta = (currPDADC - ah->initPDADC + 5) / 10;
767 REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, 797
768 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); 798 if (delta != ah->PDADCdelta) {
769 REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, 799 ah->PDADCdelta = delta;
770 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); 800 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
771 } 801 regval = ah->originalGain[i] - delta;
772 } else { 802 if (regval < 0)
773 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) 803 regval = 0;
774 delta = (currPDADC - ah->initPDADC + 4) / 8; 804
775 else 805 REG_RMW_FIELD(ah,
776 delta = (currPDADC - ah->initPDADC + 5) / 10; 806 AR_PHY_TX_GAIN_TBL1 + i * 4,
777 807 AR_PHY_TX_GAIN, regval);
778 if (delta != ah->PDADCdelta) { 808 }
779 ah->PDADCdelta = delta;
780 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
781 regval = ah->originalGain[i] - delta;
782 if (regval < 0)
783 regval = 0;
784
785 REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
786 AR_PHY_TX_GAIN, regval);
787 } 809 }
788 } 810 }
789 } 811 }