aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k
diff options
context:
space:
mode:
authorSenthil Balasubramanian <senthilkumar@atheros.com>2009-02-12 03:27:03 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-02-27 14:51:46 -0500
commit8bd1d07f9345750bd4d767e6c1600919672f98ba (patch)
tree42b201403637888b4c5cde5e1fd096c373d4ca05 /drivers/net/wireless/ath9k
parent81cb7623ad3b408f871fa36b774fc20d8dfccac0 (diff)
ath9k: Add open loop control support
This patch adds Open Loop Control support for Atheros chipsets that supports open loop power control. Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k')
-rw-r--r--drivers/net/wireless/ath9k/calib.c31
-rw-r--r--drivers/net/wireless/ath9k/eeprom.c210
-rw-r--r--drivers/net/wireless/ath9k/eeprom.h13
-rw-r--r--drivers/net/wireless/ath9k/hw.c26
-rw-r--r--drivers/net/wireless/ath9k/hw.h7
-rw-r--r--drivers/net/wireless/ath9k/phy.h25
-rw-r--r--drivers/net/wireless/ath9k/rc.c4
7 files changed, 277 insertions, 39 deletions
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c
index a7ce8c5d48f5..e5abe6564ca7 100644
--- a/drivers/net/wireless/ath9k/calib.c
+++ b/drivers/net/wireless/ath9k/calib.c
@@ -718,10 +718,39 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
718 return nf; 718 return nf;
719} 719}
720 720
721static void ath9k_olc_temp_compensation(struct ath_hw *ah)
722{
723 u32 rddata, i;
724 int delta, currPDADC, regval;
725
726 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
727
728 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
729
730 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
731 delta = (currPDADC - ah->initPDADC + 4) / 8;
732 else
733 delta = (currPDADC - ah->initPDADC + 5) / 10;
734
735 if (delta != ah->PDADCdelta) {
736 ah->PDADCdelta = delta;
737 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
738 regval = ah->originalGain[i] - delta;
739 if (regval < 0)
740 regval = 0;
741
742 REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4,
743 AR_PHY_TX_GAIN, regval);
744 }
745 }
746}
747
721bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, 748bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
722 u8 rxchainmask, bool longcal, 749 u8 rxchainmask, bool longcal,
723 bool *isCalDone) 750 bool *isCalDone)
724{ 751{
752#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
753 ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
725 struct hal_cal_list *currCal = ah->cal_list_curr; 754 struct hal_cal_list *currCal = ah->cal_list_curr;
726 755
727 *isCalDone = true; 756 *isCalDone = true;
@@ -742,6 +771,8 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
742 } 771 }
743 772
744 if (longcal) { 773 if (longcal) {
774 if (OLC_FOR_AR9280_20_LATER)
775 ath9k_olc_temp_compensation(ah);
745 ath9k_hw_getnf(ah, chan); 776 ath9k_hw_getnf(ah, chan);
746 ath9k_hw_loadnf(ah, ah->curchan); 777 ath9k_hw_loadnf(ah, ah->curchan);
747 ath9k_hw_start_nfcal(ah); 778 ath9k_hw_start_nfcal(ah);
diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c
index b6f9c31ddfcf..fff7a1b6fbf2 100644
--- a/drivers/net/wireless/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath9k/eeprom.c
@@ -179,6 +179,69 @@ static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
179 } 179 }
180} 180}
181 181
182static void ath9k_get_txgain_index(struct ath_hw *ah,
183 struct ath9k_channel *chan,
184 struct calDataPerFreqOpLoop *rawDatasetOpLoop,
185 u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)
186{
187 u8 pcdac, i = 0;
188 u16 idxL = 0, idxR = 0, numPiers;
189 bool match;
190 struct chan_centers centers;
191
192 ath9k_hw_get_channel_centers(ah, chan, &centers);
193
194 for (numPiers = 0; numPiers < availPiers; numPiers++)
195 if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
196 break;
197
198 match = ath9k_hw_get_lower_upper_index(
199 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
200 calChans, numPiers, &idxL, &idxR);
201 if (match) {
202 pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
203 *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
204 } else {
205 pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
206 *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
207 rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
208 }
209
210 while (pcdac > ah->originalGain[i] &&
211 i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
212 i++;
213
214 *pcdacIdx = i;
215 return;
216}
217
218static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
219 u32 initTxGain,
220 int txPower,
221 u8 *pPDADCValues)
222{
223 u32 i;
224 u32 offset;
225
226 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
227 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
228 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
229 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
230
231 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
232 AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
233
234 offset = txPower;
235 for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
236 if (i < offset)
237 pPDADCValues[i] = 0x0;
238 else
239 pPDADCValues[i] = 0xFF;
240}
241
242
243
244
182static void ath9k_hw_get_target_powers(struct ath_hw *ah, 245static void ath9k_hw_get_target_powers(struct ath_hw *ah,
183 struct ath9k_channel *chan, 246 struct ath9k_channel *chan,
184 struct cal_target_power_ht *powInfo, 247 struct cal_target_power_ht *powInfo,
@@ -1596,6 +1659,16 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
1596 return pBase->rxGainType; 1659 return pBase->rxGainType;
1597 case EEP_TXGAIN_TYPE: 1660 case EEP_TXGAIN_TYPE:
1598 return pBase->txGainType; 1661 return pBase->txGainType;
1662 case EEP_OL_PWRCTRL:
1663 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1664 return pBase->openLoopPwrCntl ? true : false;
1665 else
1666 return false;
1667 case EEP_RC_CHAIN_MASK:
1668 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1669 return pBase->rcChainMask;
1670 else
1671 return 0;
1599 case EEP_DAC_HPWR_5G: 1672 case EEP_DAC_HPWR_5G:
1600 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) 1673 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
1601 return pBase->dacHiPwrMode_5G; 1674 return pBase->dacHiPwrMode_5G;
@@ -1839,8 +1912,15 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah,
1839 pModal->swSettleHt40); 1912 pModal->swSettleHt40);
1840 } 1913 }
1841 1914
1915 if (AR_SREV_9280_20_OR_LATER(ah) &&
1916 AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1917 REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
1918 AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
1919 pModal->miscBits);
1920
1921
1842 if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { 1922 if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
1843 if (IS_CHAN_HT20(chan)) 1923 if (IS_CHAN_2GHZ(chan))
1844 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 1924 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
1845 eep->baseEepHeader.dacLpMode); 1925 eep->baseEepHeader.dacLpMode);
1846 else if (eep->baseEepHeader.dacHiPwrMode_5G) 1926 else if (eep->baseEepHeader.dacHiPwrMode_5G)
@@ -1851,6 +1931,10 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah,
1851 1931
1852 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, 1932 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
1853 pModal->miscBits >> 2); 1933 pModal->miscBits >> 2);
1934
1935 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
1936 AR_PHY_TX_DESIRED_SCALE_CCK,
1937 eep->baseEepHeader.desiredScaleCCK);
1854 } 1938 }
1855 1939
1856 return true; 1940 return true;
@@ -2080,6 +2164,12 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
2080 struct ath9k_channel *chan, 2164 struct ath9k_channel *chan,
2081 int16_t *pTxPowerIndexOffset) 2165 int16_t *pTxPowerIndexOffset)
2082{ 2166{
2167#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
2168 ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
2169#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
2170#define SM_PDGAIN_B(x, y) \
2171 SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
2172
2083 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; 2173 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2084 struct cal_data_per_freq *pRawDataset; 2174 struct cal_data_per_freq *pRawDataset;
2085 u8 *pCalBChans = NULL; 2175 u8 *pCalBChans = NULL;
@@ -2113,6 +2203,12 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
2113 numPiers = AR5416_NUM_5G_CAL_PIERS; 2203 numPiers = AR5416_NUM_5G_CAL_PIERS;
2114 } 2204 }
2115 2205
2206 if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
2207 pRawDataset = pEepData->calPierData2G[0];
2208 ah->initPDADC = ((struct calDataPerFreqOpLoop *)
2209 pRawDataset)->vpdPdg[0][0];
2210 }
2211
2116 numXpdGain = 0; 2212 numXpdGain = 0;
2117 2213
2118 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { 2214 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
@@ -2148,25 +2244,45 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
2148 else 2244 else
2149 pRawDataset = pEepData->calPierData5G[i]; 2245 pRawDataset = pEepData->calPierData5G[i];
2150 2246
2151 ath9k_hw_get_def_gain_boundaries_pdadcs(ah, chan, 2247
2152 pRawDataset, pCalBChans, 2248 if (OLC_FOR_AR9280_20_LATER) {
2153 numPiers, pdGainOverlap_t2, 2249 u8 pcdacIdx;
2154 &tMinCalPower, gainBoundaries, 2250 u8 txPower;
2155 pdadcValues, numXpdGain); 2251
2252 ath9k_get_txgain_index(ah, chan,
2253 (struct calDataPerFreqOpLoop *)pRawDataset,
2254 pCalBChans, numPiers, &txPower, &pcdacIdx);
2255 ath9k_olc_get_pdadcs(ah, pcdacIdx,
2256 txPower/2, pdadcValues);
2257 } else {
2258 ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
2259 chan, pRawDataset,
2260 pCalBChans, numPiers,
2261 pdGainOverlap_t2,
2262 &tMinCalPower,
2263 gainBoundaries,
2264 pdadcValues,
2265 numXpdGain);
2266 }
2156 2267
2157 if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { 2268 if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
2158 REG_WRITE(ah, 2269 if (OLC_FOR_AR9280_20_LATER) {
2159 AR_PHY_TPCRG5 + regChainOffset, 2270 REG_WRITE(ah,
2160 SM(pdGainOverlap_t2, 2271 AR_PHY_TPCRG5 + regChainOffset,
2161 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) 2272 SM(0x6,
2162 | SM(gainBoundaries[0], 2273 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
2163 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) 2274 SM_PD_GAIN(1) | SM_PD_GAIN(2) |
2164 | SM(gainBoundaries[1], 2275 SM_PD_GAIN(3) | SM_PD_GAIN(4));
2165 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) 2276 } else {
2166 | SM(gainBoundaries[2], 2277 REG_WRITE(ah,
2167 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) 2278 AR_PHY_TPCRG5 + regChainOffset,
2168 | SM(gainBoundaries[3], 2279 SM(pdGainOverlap_t2,
2169 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); 2280 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
2281 SM_PDGAIN_B(0, 1) |
2282 SM_PDGAIN_B(1, 2) |
2283 SM_PDGAIN_B(2, 3) |
2284 SM_PDGAIN_B(3, 4));
2285 }
2170 } 2286 }
2171 2287
2172 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; 2288 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
@@ -2200,6 +2316,8 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
2200 *pTxPowerIndexOffset = 0; 2316 *pTxPowerIndexOffset = 0;
2201 2317
2202 return true; 2318 return true;
2319#undef SM_PD_GAIN
2320#undef SM_PDGAIN_B
2203} 2321}
2204 2322
2205static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, 2323static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
@@ -2500,13 +2618,14 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
2500 u8 twiceMaxRegulatoryPower, 2618 u8 twiceMaxRegulatoryPower,
2501 u8 powerLimit) 2619 u8 powerLimit)
2502{ 2620{
2621#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
2503 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; 2622 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2504 struct modal_eep_header *pModal = 2623 struct modal_eep_header *pModal =
2505 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); 2624 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
2506 int16_t ratesArray[Ar5416RateSize]; 2625 int16_t ratesArray[Ar5416RateSize];
2507 int16_t txPowerIndexOffset = 0; 2626 int16_t txPowerIndexOffset = 0;
2508 u8 ht40PowerIncForPdadc = 2; 2627 u8 ht40PowerIncForPdadc = 2;
2509 int i; 2628 int i, cck_ofdm_delta = 0;
2510 2629
2511 memset(ratesArray, 0, sizeof(ratesArray)); 2630 memset(ratesArray, 0, sizeof(ratesArray));
2512 2631
@@ -2555,16 +2674,30 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
2555 | ATH9K_POW_SM(ratesArray[rate24mb], 0)); 2674 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
2556 2675
2557 if (IS_CHAN_2GHZ(chan)) { 2676 if (IS_CHAN_2GHZ(chan)) {
2558 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, 2677 if (OLC_FOR_AR9280_20_LATER) {
2559 ATH9K_POW_SM(ratesArray[rate2s], 24) 2678 cck_ofdm_delta = 2;
2560 | ATH9K_POW_SM(ratesArray[rate2l], 16) 2679 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2561 | ATH9K_POW_SM(ratesArray[rateXr], 8) 2680 ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
2562 | ATH9K_POW_SM(ratesArray[rate1l], 0)); 2681 | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
2563 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, 2682 | ATH9K_POW_SM(ratesArray[rateXr], 8)
2564 ATH9K_POW_SM(ratesArray[rate11s], 24) 2683 | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
2565 | ATH9K_POW_SM(ratesArray[rate11l], 16) 2684 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2566 | ATH9K_POW_SM(ratesArray[rate5_5s], 8) 2685 ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
2567 | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); 2686 | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
2687 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
2688 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
2689 } else {
2690 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2691 ATH9K_POW_SM(ratesArray[rate2s], 24)
2692 | ATH9K_POW_SM(ratesArray[rate2l], 16)
2693 | ATH9K_POW_SM(ratesArray[rateXr], 8)
2694 | ATH9K_POW_SM(ratesArray[rate1l], 0));
2695 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2696 ATH9K_POW_SM(ratesArray[rate11s], 24)
2697 | ATH9K_POW_SM(ratesArray[rate11l], 16)
2698 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
2699 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
2700 }
2568 } 2701 }
2569 2702
2570 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, 2703 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
@@ -2597,12 +2730,19 @@ static int ath9k_hw_def_set_txpower(struct ath_hw *ah,
2597 ht40PowerIncForPdadc, 8) 2730 ht40PowerIncForPdadc, 8)
2598 | ATH9K_POW_SM(ratesArray[rateHt40_4] + 2731 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
2599 ht40PowerIncForPdadc, 0)); 2732 ht40PowerIncForPdadc, 0));
2600 2733 if (OLC_FOR_AR9280_20_LATER) {
2601 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, 2734 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2602 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) 2735 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
2603 | ATH9K_POW_SM(ratesArray[rateExtCck], 16) 2736 | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
2604 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) 2737 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
2605 | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); 2738 | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
2739 } else {
2740 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2741 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
2742 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
2743 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
2744 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
2745 }
2606 } 2746 }
2607 2747
2608 REG_WRITE(ah, AR_PHY_POWER_TX_SUB, 2748 REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h
index 60cb23de97c6..2cfea5d56d10 100644
--- a/drivers/net/wireless/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath9k/eeprom.h
@@ -168,6 +168,8 @@
168#define AR5416_EEP4K_PD_GAIN_ICEPTS 5 168#define AR5416_EEP4K_PD_GAIN_ICEPTS 5
169#define AR5416_EEP4K_MAX_CHAINS 1 169#define AR5416_EEP4K_MAX_CHAINS 1
170 170
171#define AR9280_TX_GAIN_TABLE_SIZE 22
172
171enum eeprom_param { 173enum eeprom_param {
172 EEP_NFTHRESH_5, 174 EEP_NFTHRESH_5,
173 EEP_NFTHRESH_2, 175 EEP_NFTHRESH_2,
@@ -188,6 +190,8 @@ enum eeprom_param {
188 EEP_RX_MASK, 190 EEP_RX_MASK,
189 EEP_RXGAIN_TYPE, 191 EEP_RXGAIN_TYPE,
190 EEP_TXGAIN_TYPE, 192 EEP_TXGAIN_TYPE,
193 EEP_OL_PWRCTRL,
194 EEP_RC_CHAIN_MASK,
191 EEP_DAC_HPWR_5G, 195 EEP_DAC_HPWR_5G,
192 EEP_FRAC_N_5G 196 EEP_FRAC_N_5G
193}; 197};
@@ -229,7 +233,7 @@ struct base_eep_header {
229 u8 futureBase_1[2]; 233 u8 futureBase_1[2];
230 u8 rxGainType; 234 u8 rxGainType;
231 u8 dacHiPwrMode_5G; 235 u8 dacHiPwrMode_5G;
232 u8 futureBase_2; 236 u8 openLoopPwrCntl;
233 u8 dacLpMode; 237 u8 dacLpMode;
234 u8 txGainType; 238 u8 txGainType;
235 u8 rcChainMask; 239 u8 rcChainMask;
@@ -310,6 +314,13 @@ struct modal_eep_header {
310 struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; 314 struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
311} __packed; 315} __packed;
312 316
317struct calDataPerFreqOpLoop {
318 u8 pwrPdg[2][5];
319 u8 vpdPdg[2][5];
320 u8 pcdac[2][5];
321 u8 empty[2][5];
322} __packed;
323
313struct modal_eep_4k_header { 324struct modal_eep_4k_header {
314 u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; 325 u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
315 u32 antCtrlCommon; 326 u32 antCtrlCommon;
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
index 4af1aac16785..e33c53fb6b7e 100644
--- a/drivers/net/wireless/ath9k/hw.c
+++ b/drivers/net/wireless/ath9k/hw.c
@@ -1202,10 +1202,23 @@ static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
1202 return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value); 1202 return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
1203} 1203}
1204 1204
1205static void ath9k_olc_init(struct ath_hw *ah)
1206{
1207 u32 i;
1208
1209 for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
1210 ah->originalGain[i] =
1211 MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
1212 AR_PHY_TX_GAIN);
1213 ah->PDADCdelta = 0;
1214}
1215
1205static int ath9k_hw_process_ini(struct ath_hw *ah, 1216static int ath9k_hw_process_ini(struct ath_hw *ah,
1206 struct ath9k_channel *chan, 1217 struct ath9k_channel *chan,
1207 enum ath9k_ht_macmode macmode) 1218 enum ath9k_ht_macmode macmode)
1208{ 1219{
1220#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \
1221 ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
1209 int i, regWrites = 0; 1222 int i, regWrites = 0;
1210 struct ieee80211_channel *channel = chan->chan; 1223 struct ieee80211_channel *channel = chan->chan;
1211 u32 modesIndex, freqIndex; 1224 u32 modesIndex, freqIndex;
@@ -1308,6 +1321,9 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
1308 ath9k_hw_set_regs(ah, chan, macmode); 1321 ath9k_hw_set_regs(ah, chan, macmode);
1309 ath9k_hw_init_chain_masks(ah); 1322 ath9k_hw_init_chain_masks(ah);
1310 1323
1324 if (OLC_FOR_AR9280_20_LATER)
1325 ath9k_olc_init(ah);
1326
1311 status = ah->eep_ops->set_txpower(ah, chan, 1327 status = ah->eep_ops->set_txpower(ah, chan,
1312 ath9k_regd_get_ctl(ah, chan), 1328 ath9k_regd_get_ctl(ah, chan),
1313 channel->max_antenna_gain * 2, 1329 channel->max_antenna_gain * 2,
@@ -1515,6 +1531,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
1515 AR_RTC_FORCE_WAKE_ON_INT); 1531 AR_RTC_FORCE_WAKE_ON_INT);
1516 1532
1517 REG_WRITE(ah, AR_RTC_RESET, 0); 1533 REG_WRITE(ah, AR_RTC_RESET, 0);
1534 udelay(2);
1518 REG_WRITE(ah, AR_RTC_RESET, 1); 1535 REG_WRITE(ah, AR_RTC_RESET, 1);
1519 1536
1520 if (!ath9k_hw_wait(ah, 1537 if (!ath9k_hw_wait(ah,
@@ -1582,7 +1599,10 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan,
1582static bool ath9k_hw_chip_reset(struct ath_hw *ah, 1599static bool ath9k_hw_chip_reset(struct ath_hw *ah,
1583 struct ath9k_channel *chan) 1600 struct ath9k_channel *chan)
1584{ 1601{
1585 if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) 1602 if (OLC_FOR_AR9280_20_LATER) {
1603 if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
1604 return false;
1605 } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
1586 return false; 1606 return false;
1587 1607
1588 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) 1608 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
@@ -3404,6 +3424,10 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
3404 return 0; 3424 return 0;
3405 } 3425 }
3406 return false; 3426 return false;
3427 case ATH9K_CAP_DS:
3428 return (AR_SREV_9280_20_OR_LATER(ah) &&
3429 (ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1))
3430 ? false : true;
3407 default: 3431 default:
3408 return false; 3432 return false;
3409 } 3433 }
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h
index 587a78db748d..08469d9525bc 100644
--- a/drivers/net/wireless/ath9k/hw.h
+++ b/drivers/net/wireless/ath9k/hw.h
@@ -162,7 +162,8 @@ enum ath9k_capability_type {
162 ATH9K_CAP_WME_TKIPMIC, 162 ATH9K_CAP_WME_TKIPMIC,
163 ATH9K_CAP_RFSILENT, 163 ATH9K_CAP_RFSILENT,
164 ATH9K_CAP_ANT_CFG_2GHZ, 164 ATH9K_CAP_ANT_CFG_2GHZ,
165 ATH9K_CAP_ANT_CFG_5GHZ 165 ATH9K_CAP_ANT_CFG_5GHZ,
166 ATH9K_CAP_DS
166}; 167};
167 168
168struct ath9k_hw_capabilities { 169struct ath9k_hw_capabilities {
@@ -551,6 +552,10 @@ struct ath_hw {
551 u8 txchainmask; 552 u8 txchainmask;
552 u8 rxchainmask; 553 u8 rxchainmask;
553 554
555 u32 originalGain[22];
556 int initPDADC;
557 int PDADCdelta;
558
554 struct ar5416IniArray iniModes; 559 struct ar5416IniArray iniModes;
555 struct ar5416IniArray iniCommon; 560 struct ar5416IniArray iniCommon;
556 struct ar5416IniArray iniBank0; 561 struct ar5416IniArray iniBank0;
diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h
index 4758c37e4b88..3dbdd54be4e9 100644
--- a/drivers/net/wireless/ath9k/phy.h
+++ b/drivers/net/wireless/ath9k/phy.h
@@ -387,6 +387,8 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
387 387
388#define AR_PHY_CCK_TX_CTRL 0xA204 388#define AR_PHY_CCK_TX_CTRL 0xA204
389#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 389#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
390#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C
391#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
390 392
391#define AR_PHY_CCK_DETECT 0xA208 393#define AR_PHY_CCK_DETECT 0xA208
392#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F 394#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
@@ -444,6 +446,29 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
444#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 446#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
445#define AR_PHY_TPCRG1_PD_GAIN_3_S 20 447#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
446 448
449#define AR_PHY_TX_PWRCTRL4 0xa264
450#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
451#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0
452#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE
453#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
454
455#define AR_PHY_TX_PWRCTRL6_0 0xa270
456#define AR_PHY_TX_PWRCTRL6_1 0xb270
457#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000
458#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
459
460#define AR_PHY_TX_PWRCTRL7 0xa274
461#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
462#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
463
464#define AR_PHY_TX_PWRCTRL9 0xa27C
465#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
466#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
467
468#define AR_PHY_TX_GAIN_TBL1 0xa300
469#define AR_PHY_TX_GAIN 0x0007F000
470#define AR_PHY_TX_GAIN_S 12
471
447#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 472#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
448#define AR_PHY_MASK2_M_31_45 0xa3a4 473#define AR_PHY_MASK2_M_31_45 0xa3a4
449#define AR_PHY_MASK2_M_16_30 0xa3a8 474#define AR_PHY_MASK2_M_16_30 0xa3a8
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index a4e863191766..6b4731c24736 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -1392,6 +1392,7 @@ static void ath_rc_init(struct ath_softc *sc,
1392 struct ath_rateset *rateset = &ath_rc_priv->neg_rates; 1392 struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
1393 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; 1393 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
1394 u8 i, j, k, hi = 0, hthi = 0; 1394 u8 i, j, k, hi = 0, hthi = 0;
1395 struct ath_hw *ah = sc->sc_ah;
1395 1396
1396 /* FIXME: Adhoc */ 1397 /* FIXME: Adhoc */
1397 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || 1398 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
@@ -1412,7 +1413,8 @@ static void ath_rc_init(struct ath_softc *sc,
1412 1413
1413 if (sta->ht_cap.ht_supported) { 1414 if (sta->ht_cap.ht_supported) {
1414 ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG; 1415 ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG;
1415 if (sc->sc_ah->caps.tx_chainmask != 1) 1416 if (sc->sc_ah->caps.tx_chainmask != 1 &&
1417 ath9k_hw_getcapability(ah, ATH9K_CAP_DS, 0, NULL))
1416 ath_rc_priv->ht_cap |= WLAN_RC_DS_FLAG; 1418 ath_rc_priv->ht_cap |= WLAN_RC_DS_FLAG;
1417 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) 1419 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
1418 ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG; 1420 ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG;