blob: 839eed89179d68eb212b973825a5878b52a055d0 [file] [log] [blame]
Sujithb5aec952009-08-07 09:45:15 +05301/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070017#include "hw.h"
Sujithb5aec952009-08-07 09:45:15 +053018
19static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah)
20{
21 return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF;
22}
23
24static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah)
25{
26 return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF;
27}
28
29static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah)
30{
31 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070032 struct ath_common *common = ath9k_hw_common(ah);
Sujithb5aec952009-08-07 09:45:15 +053033 u16 *eep_data;
34 int addr, eep_start_loc = AR9287_EEP_START_LOC;
35 eep_data = (u16 *)eep;
36
37 if (!ath9k_hw_use_flash(ah)) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070038 ath_print(common, ATH_DBG_EEPROM,
39 "Reading from EEPROM, not flash\n");
Sujithb5aec952009-08-07 09:45:15 +053040 }
41
42 for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
43 addr++) {
44 if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070045 ath_print(common, ATH_DBG_EEPROM,
46 "Unable to read eeprom region \n");
Sujithb5aec952009-08-07 09:45:15 +053047 return false;
48 }
49 eep_data++;
50 }
51 return true;
52}
53
54static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
55{
56 u32 sum = 0, el, integer;
57 u16 temp, word, magic, magic2, *eepdata;
58 int i, addr;
59 bool need_swap = false;
60 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070061 struct ath_common *common = ath9k_hw_common(ah);
Sujithb5aec952009-08-07 09:45:15 +053062
63 if (!ath9k_hw_use_flash(ah)) {
64 if (!ath9k_hw_nvram_read
65 (ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070066 ath_print(common, ATH_DBG_FATAL,
67 "Reading Magic # failed\n");
Sujithb5aec952009-08-07 09:45:15 +053068 return false;
69 }
70
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070071 ath_print(common, ATH_DBG_EEPROM,
72 "Read Magic = 0x%04X\n", magic);
Sujithb5aec952009-08-07 09:45:15 +053073 if (magic != AR5416_EEPROM_MAGIC) {
74 magic2 = swab16(magic);
75
76 if (magic2 == AR5416_EEPROM_MAGIC) {
77 need_swap = true;
78 eepdata = (u16 *)(&ah->eeprom);
79
80 for (addr = 0;
81 addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
82 addr++) {
83 temp = swab16(*eepdata);
84 *eepdata = temp;
85 eepdata++;
86 }
87 } else {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070088 ath_print(common, ATH_DBG_FATAL,
89 "Invalid EEPROM Magic. "
90 "endianness mismatch.\n");
Sujithb5aec952009-08-07 09:45:15 +053091 return -EINVAL;
92 }
93 }
94 }
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070095 ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ?
96 "True" : "False");
Sujithb5aec952009-08-07 09:45:15 +053097
98 if (need_swap)
99 el = swab16(ah->eeprom.map9287.baseEepHeader.length);
100 else
101 el = ah->eeprom.map9287.baseEepHeader.length;
102
103 if (el > sizeof(struct ar9287_eeprom))
104 el = sizeof(struct ar9287_eeprom) / sizeof(u16);
105 else
106 el = el / sizeof(u16);
107
108 eepdata = (u16 *)(&ah->eeprom);
109 for (i = 0; i < el; i++)
110 sum ^= *eepdata++;
111
112 if (need_swap) {
113 word = swab16(eep->baseEepHeader.length);
114 eep->baseEepHeader.length = word;
115
116 word = swab16(eep->baseEepHeader.checksum);
117 eep->baseEepHeader.checksum = word;
118
119 word = swab16(eep->baseEepHeader.version);
120 eep->baseEepHeader.version = word;
121
122 word = swab16(eep->baseEepHeader.regDmn[0]);
123 eep->baseEepHeader.regDmn[0] = word;
124
125 word = swab16(eep->baseEepHeader.regDmn[1]);
126 eep->baseEepHeader.regDmn[1] = word;
127
128 word = swab16(eep->baseEepHeader.rfSilent);
129 eep->baseEepHeader.rfSilent = word;
130
131 word = swab16(eep->baseEepHeader.blueToothOptions);
132 eep->baseEepHeader.blueToothOptions = word;
133
134 word = swab16(eep->baseEepHeader.deviceCap);
135 eep->baseEepHeader.deviceCap = word;
136
137 integer = swab32(eep->modalHeader.antCtrlCommon);
138 eep->modalHeader.antCtrlCommon = integer;
139
140 for (i = 0; i < AR9287_MAX_CHAINS; i++) {
141 integer = swab32(eep->modalHeader.antCtrlChain[i]);
142 eep->modalHeader.antCtrlChain[i] = integer;
143 }
144
145 for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) {
146 word = swab16(eep->modalHeader.spurChans[i].spurChan);
147 eep->modalHeader.spurChans[i].spurChan = word;
148 }
149 }
150
151 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
152 || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700153 ath_print(common, ATH_DBG_FATAL,
154 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
155 sum, ah->eep_ops->get_eeprom_ver(ah));
Sujithb5aec952009-08-07 09:45:15 +0530156 return -EINVAL;
157 }
158
159 return 0;
160}
161
162static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah,
163 enum eeprom_param param)
164{
165 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
166 struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
167 struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
168 u16 ver_minor;
169
170 ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK;
171 switch (param) {
172 case EEP_NFTHRESH_2:
173 return pModal->noiseFloorThreshCh[0];
174 case AR_EEPROM_MAC(0):
175 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
176 case AR_EEPROM_MAC(1):
177 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
178 case AR_EEPROM_MAC(2):
179 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
180 case EEP_REG_0:
181 return pBase->regDmn[0];
182 case EEP_REG_1:
183 return pBase->regDmn[1];
184 case EEP_OP_CAP:
185 return pBase->deviceCap;
186 case EEP_OP_MODE:
187 return pBase->opCapFlags;
188 case EEP_RF_SILENT:
189 return pBase->rfSilent;
190 case EEP_MINOR_REV:
191 return ver_minor;
192 case EEP_TX_MASK:
193 return pBase->txMask;
194 case EEP_RX_MASK:
195 return pBase->rxMask;
196 case EEP_DEV_TYPE:
197 return pBase->deviceType;
198 case EEP_OL_PWRCTRL:
199 return pBase->openLoopPwrCntl;
200 case EEP_TEMPSENSE_SLOPE:
201 if (ver_minor >= AR9287_EEP_MINOR_VER_2)
202 return pBase->tempSensSlope;
203 else
204 return 0;
205 case EEP_TEMPSENSE_SLOPE_PAL_ON:
206 if (ver_minor >= AR9287_EEP_MINOR_VER_3)
207 return pBase->tempSensSlopePalOn;
208 else
209 return 0;
210 default:
211 return 0;
212 }
213}
214
215
216static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah,
217 struct ath9k_channel *chan,
218 struct cal_data_per_freq_ar9287 *pRawDataSet,
219 u8 *bChans, u16 availPiers,
220 u16 tPdGainOverlap, int16_t *pMinCalPower,
221 u16 *pPdGainBoundaries, u8 *pPDADCValues,
222 u16 numXpdGains)
223{
224#define TMP_VAL_VPD_TABLE \
225 ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
226
227 int i, j, k;
228 int16_t ss;
229 u16 idxL = 0, idxR = 0, numPiers;
230 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
231 u8 minPwrT4[AR9287_NUM_PD_GAINS];
232 u8 maxPwrT4[AR9287_NUM_PD_GAINS];
233 int16_t vpdStep;
234 int16_t tmpVal;
235 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
236 bool match;
237 int16_t minDelta = 0;
238 struct chan_centers centers;
239 static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
240 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
241 static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
242 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
243 static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
244 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
245
246 ath9k_hw_get_channel_centers(ah, chan, &centers);
247
248 for (numPiers = 0; numPiers < availPiers; numPiers++) {
249 if (bChans[numPiers] == AR9287_BCHAN_UNUSED)
250 break;
251 }
252
253 match = ath9k_hw_get_lower_upper_index(
254 (u8)FREQ2FBIN(centers.synth_center,
255 IS_CHAN_2GHZ(chan)), bChans, numPiers,
256 &idxL, &idxR);
257
258 if (match) {
259 for (i = 0; i < numXpdGains; i++) {
260 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
261 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
262 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
263 pRawDataSet[idxL].pwrPdg[i],
264 pRawDataSet[idxL].vpdPdg[i],
265 AR9287_PD_GAIN_ICEPTS, vpdTableI[i]);
266 }
267 } else {
268 for (i = 0; i < numXpdGains; i++) {
269 pVpdL = pRawDataSet[idxL].vpdPdg[i];
270 pPwrL = pRawDataSet[idxL].pwrPdg[i];
271 pVpdR = pRawDataSet[idxR].vpdPdg[i];
272 pPwrR = pRawDataSet[idxR].pwrPdg[i];
273
274 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
275
276 maxPwrT4[i] =
277 min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1],
278 pPwrR[AR9287_PD_GAIN_ICEPTS - 1]);
279
280 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
281 pPwrL, pVpdL,
282 AR9287_PD_GAIN_ICEPTS,
283 vpdTableL[i]);
284 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
285 pPwrR, pVpdR,
286 AR9287_PD_GAIN_ICEPTS,
287 vpdTableR[i]);
288
289 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
290 vpdTableI[i][j] =
291 (u8)(ath9k_hw_interpolate((u16)
292 FREQ2FBIN(centers. synth_center,
293 IS_CHAN_2GHZ(chan)),
294 bChans[idxL], bChans[idxR],
295 vpdTableL[i][j], vpdTableR[i][j]));
296 }
297 }
298 }
299 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
300
301 k = 0;
302 for (i = 0; i < numXpdGains; i++) {
303 if (i == (numXpdGains - 1))
304 pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2);
305 else
306 pPdGainBoundaries[i] = (u16)((maxPwrT4[i] +
307 minPwrT4[i+1]) / 4);
308
309 pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER,
310 pPdGainBoundaries[i]);
311
312
313 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
314 minDelta = pPdGainBoundaries[0] - 23;
315 pPdGainBoundaries[0] = 23;
316 } else
317 minDelta = 0;
318
319 if (i == 0) {
320 if (AR_SREV_9280_10_OR_LATER(ah))
321 ss = (int16_t)(0 - (minPwrT4[i] / 2));
322 else
323 ss = 0;
324 } else
325 ss = (int16_t)((pPdGainBoundaries[i-1] -
326 (minPwrT4[i] / 2)) -
327 tPdGainOverlap + 1 + minDelta);
328
329 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
330 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
331 while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) {
332 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
333 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
334 ss++;
335 }
336
337 sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
338 tgtIndex = (u8)(pPdGainBoundaries[i] +
339 tPdGainOverlap - (minPwrT4[i] / 2));
340 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
341 tgtIndex : sizeCurrVpdTable;
342
343 while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1)))
344 pPDADCValues[k++] = vpdTableI[i][ss++];
345
346 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
347 vpdTableI[i][sizeCurrVpdTable - 2]);
348 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
349 if (tgtIndex > maxIndex) {
350 while ((ss <= tgtIndex) &&
351 (k < (AR9287_NUM_PDADC_VALUES - 1))) {
352 tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
353 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
354 255 : tmpVal);
355 ss++;
356 }
357 }
358 }
359
360 while (i < AR9287_PD_GAINS_IN_MASK) {
361 pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
362 i++;
363 }
364
365 while (k < AR9287_NUM_PDADC_VALUES) {
366 pPDADCValues[k] = pPDADCValues[k-1];
367 k++;
368 }
369
370#undef TMP_VAL_VPD_TABLE
371}
372
373static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
374 struct ath9k_channel *chan,
375 struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
376 u8 *pCalChans, u16 availPiers,
377 int8_t *pPwr)
378{
Sujithb5aec952009-08-07 09:45:15 +0530379 u16 idxL = 0, idxR = 0, numPiers;
380 bool match;
381 struct chan_centers centers;
382
383 ath9k_hw_get_channel_centers(ah, chan, &centers);
384
385 for (numPiers = 0; numPiers < availPiers; numPiers++) {
386 if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED)
387 break;
388 }
389
390 match = ath9k_hw_get_lower_upper_index(
391 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
392 pCalChans, numPiers,
393 &idxL, &idxR);
394
395 if (match) {
Vivek Natarajand4fe5af2009-08-14 11:32:04 +0530396 *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0];
Sujithb5aec952009-08-07 09:45:15 +0530397 } else {
Vivek Natarajand4fe5af2009-08-14 11:32:04 +0530398 *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
399 (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
Sujithb5aec952009-08-07 09:45:15 +0530400 }
401
Sujithb5aec952009-08-07 09:45:15 +0530402}
403
404static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
405 int32_t txPower, u16 chain)
406{
407 u32 tmpVal;
408 u32 a;
409
410 tmpVal = REG_READ(ah, 0xa270);
411 tmpVal = tmpVal & 0xFCFFFFFF;
412 tmpVal = tmpVal | (0x3 << 24);
413 REG_WRITE(ah, 0xa270, tmpVal);
414
415 tmpVal = REG_READ(ah, 0xb270);
416 tmpVal = tmpVal & 0xFCFFFFFF;
417 tmpVal = tmpVal | (0x3 << 24);
418 REG_WRITE(ah, 0xb270, tmpVal);
419
420 if (chain == 0) {
421 tmpVal = REG_READ(ah, 0xa398);
422 tmpVal = tmpVal & 0xff00ffff;
423 a = (txPower)&0xff;
424 tmpVal = tmpVal | (a << 16);
425 REG_WRITE(ah, 0xa398, tmpVal);
426 }
427
428 if (chain == 1) {
429 tmpVal = REG_READ(ah, 0xb398);
430 tmpVal = tmpVal & 0xff00ffff;
431 a = (txPower)&0xff;
432 tmpVal = tmpVal | (a << 16);
433 REG_WRITE(ah, 0xb398, tmpVal);
434 }
435}
436
437static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah,
438 struct ath9k_channel *chan,
439 int16_t *pTxPowerIndexOffset)
440{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700441 struct ath_common *common = ath9k_hw_common(ah);
Sujithb5aec952009-08-07 09:45:15 +0530442 struct cal_data_per_freq_ar9287 *pRawDataset;
443 struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
444 u8 *pCalBChans = NULL;
445 u16 pdGainOverlap_t2;
446 u8 pdadcValues[AR9287_NUM_PDADC_VALUES];
447 u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK];
448 u16 numPiers = 0, i, j;
449 int16_t tMinCalPower;
450 u16 numXpdGain, xpdMask;
451 u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0};
452 u32 reg32, regOffset, regChainOffset;
453 int16_t modalIdx, diff = 0;
454 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
455 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
456 xpdMask = pEepData->modalHeader.xpdGain;
457 if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
458 AR9287_EEP_MINOR_VER_2)
459 pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
460 else
461 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
462 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
463
464 if (IS_CHAN_2GHZ(chan)) {
465 pCalBChans = pEepData->calFreqPier2G;
466 numPiers = AR9287_NUM_2G_CAL_PIERS;
467 if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
468 pRawDatasetOpenLoop =
469 (struct cal_data_op_loop_ar9287 *)
470 pEepData->calPierData2G[0];
471 ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
472 }
473 }
474
475 numXpdGain = 0;
476 for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) {
477 if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) {
478 if (numXpdGain >= AR9287_NUM_PD_GAINS)
479 break;
480 xpdGainValues[numXpdGain] =
481 (u16)(AR9287_PD_GAINS_IN_MASK-i);
482 numXpdGain++;
483 }
484 }
485
486 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
487 (numXpdGain - 1) & 0x3);
488 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
489 xpdGainValues[0]);
490 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
491 xpdGainValues[1]);
492 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
493 xpdGainValues[2]);
494
495 for (i = 0; i < AR9287_MAX_CHAINS; i++) {
496 regChainOffset = i * 0x1000;
497 if (pEepData->baseEepHeader.txMask & (1 << i)) {
498 pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *)
499 pEepData->calPierData2G[i];
500 if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
501 int8_t txPower;
502 ar9287_eeprom_get_tx_gain_index(ah, chan,
503 pRawDatasetOpenLoop,
504 pCalBChans, numPiers,
505 &txPower);
506 ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i);
507 } else {
508 pRawDataset =
509 (struct cal_data_per_freq_ar9287 *)
510 pEepData->calPierData2G[i];
511 ath9k_hw_get_AR9287_gain_boundaries_pdadcs(
512 ah, chan, pRawDataset,
513 pCalBChans, numPiers,
514 pdGainOverlap_t2,
515 &tMinCalPower, gainBoundaries,
516 pdadcValues, numXpdGain);
517 }
518
519 if (i == 0) {
520 if (!ath9k_hw_AR9287_get_eeprom(
521 ah, EEP_OL_PWRCTRL)) {
522 REG_WRITE(ah, AR_PHY_TPCRG5 +
523 regChainOffset,
524 SM(pdGainOverlap_t2,
525 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
526 SM(gainBoundaries[0],
527 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
528 | SM(gainBoundaries[1],
529 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
530 | SM(gainBoundaries[2],
531 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
532 | SM(gainBoundaries[3],
533 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
534 }
535 }
536
537 if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB !=
538 pEepData->baseEepHeader.pwrTableOffset) {
539 diff = (u16)
540 (pEepData->baseEepHeader.pwrTableOffset
541 - (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
542 diff *= 2;
543
544 for (j = 0;
545 j < ((u16)AR9287_NUM_PDADC_VALUES-diff);
546 j++)
547 pdadcValues[j] = pdadcValues[j+diff];
548
549 for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff);
550 j < AR9287_NUM_PDADC_VALUES; j++)
551 pdadcValues[j] =
552 pdadcValues[
553 AR9287_NUM_PDADC_VALUES-diff];
554 }
555
556 if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
557 regOffset = AR_PHY_BASE + (672 << 2) +
558 regChainOffset;
559 for (j = 0; j < 32; j++) {
560 reg32 = ((pdadcValues[4*j + 0]
561 & 0xFF) << 0) |
562 ((pdadcValues[4*j + 1]
563 & 0xFF) << 8) |
564 ((pdadcValues[4*j + 2]
565 & 0xFF) << 16) |
566 ((pdadcValues[4*j + 3]
567 & 0xFF) << 24) ;
568 REG_WRITE(ah, regOffset, reg32);
569
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700570 ath_print(common, ATH_DBG_EEPROM,
571 "PDADC (%d,%4x): %4.4x "
572 "%8.8x\n",
573 i, regChainOffset, regOffset,
574 reg32);
Sujithb5aec952009-08-07 09:45:15 +0530575
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700576 ath_print(common, ATH_DBG_EEPROM,
577 "PDADC: Chain %d | "
578 "PDADC %3d Value %3d | "
579 "PDADC %3d Value %3d | "
580 "PDADC %3d Value %3d | "
581 "PDADC %3d Value %3d |\n",
582 i, 4 * j, pdadcValues[4 * j],
583 4 * j + 1,
584 pdadcValues[4 * j + 1],
585 4 * j + 2,
586 pdadcValues[4 * j + 2],
587 4 * j + 3,
588 pdadcValues[4 * j + 3]);
Sujithb5aec952009-08-07 09:45:15 +0530589
590 regOffset += 4;
591 }
592 }
593 }
594 }
595
596 *pTxPowerIndexOffset = 0;
597}
598
599static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah,
600 struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl,
601 u16 AntennaReduction, u16 twiceMaxRegulatoryPower,
602 u16 powerLimit)
603{
604#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
605#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -0700606 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
Sujithb5aec952009-08-07 09:45:15 +0530607 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
608 static const u16 tpScaleReductionTable[5] =
609 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
610 int i;
611 int16_t twiceLargestAntenna;
612 struct cal_ctl_data_ar9287 *rep;
613 struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
614 targetPowerCck = {0, {0, 0, 0, 0} };
615 struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
616 targetPowerCckExt = {0, {0, 0, 0, 0} };
617 struct cal_target_power_ht targetPowerHt20,
618 targetPowerHt40 = {0, {0, 0, 0, 0} };
619 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
620 u16 ctlModesFor11g[] =
621 {CTL_11B, CTL_11G, CTL_2GHT20,
622 CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40};
623 u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq;
624 struct chan_centers centers;
625 int tx_chainmask;
626 u16 twiceMinEdgePower;
627 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
628 tx_chainmask = ah->txchainmask;
629
630 ath9k_hw_get_channel_centers(ah, chan, &centers);
631
632 twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
633 pEepData->modalHeader.antennaGainCh[1]);
634
635 twiceLargestAntenna = (int16_t)min((AntennaReduction) -
636 twiceLargestAntenna, 0);
637
638 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -0700639 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
Sujithb5aec952009-08-07 09:45:15 +0530640 maxRegAllowedPower -=
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -0700641 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
Sujithb5aec952009-08-07 09:45:15 +0530642
643 scaledPower = min(powerLimit, maxRegAllowedPower);
644
645 switch (ar5416_get_ntxchains(tx_chainmask)) {
646 case 1:
647 break;
648 case 2:
649 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
650 break;
651 case 3:
652 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
653 break;
654 }
655 scaledPower = max((u16)0, scaledPower);
656
657 if (IS_CHAN_2GHZ(chan)) {
658 numCtlModes =
659 ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
660 pCtlMode = ctlModesFor11g;
661
662 ath9k_hw_get_legacy_target_powers(ah, chan,
663 pEepData->calTargetPowerCck,
664 AR9287_NUM_2G_CCK_TARGET_POWERS,
665 &targetPowerCck, 4, false);
666 ath9k_hw_get_legacy_target_powers(ah, chan,
667 pEepData->calTargetPower2G,
668 AR9287_NUM_2G_20_TARGET_POWERS,
669 &targetPowerOfdm, 4, false);
670 ath9k_hw_get_target_powers(ah, chan,
671 pEepData->calTargetPower2GHT20,
672 AR9287_NUM_2G_20_TARGET_POWERS,
673 &targetPowerHt20, 8, false);
674
675 if (IS_CHAN_HT40(chan)) {
676 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
677 ath9k_hw_get_target_powers(ah, chan,
678 pEepData->calTargetPower2GHT40,
679 AR9287_NUM_2G_40_TARGET_POWERS,
680 &targetPowerHt40, 8, true);
681 ath9k_hw_get_legacy_target_powers(ah, chan,
682 pEepData->calTargetPowerCck,
683 AR9287_NUM_2G_CCK_TARGET_POWERS,
684 &targetPowerCckExt, 4, true);
685 ath9k_hw_get_legacy_target_powers(ah, chan,
686 pEepData->calTargetPower2G,
687 AR9287_NUM_2G_20_TARGET_POWERS,
688 &targetPowerOfdmExt, 4, true);
689 }
690 }
691
692 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
693 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
694 (pCtlMode[ctlMode] == CTL_2GHT40);
695 if (isHt40CtlMode)
696 freq = centers.synth_center;
697 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
698 freq = centers.ext_center;
699 else
700 freq = centers.ctl_center;
701
702 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
703 ah->eep_ops->get_eeprom_rev(ah) <= 2)
704 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
705
706 for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
707 if ((((cfgCtl & ~CTL_MODE_M) |
708 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
709 pEepData->ctlIndex[i]) ||
710 (((cfgCtl & ~CTL_MODE_M) |
711 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
712 ((pEepData->ctlIndex[i] &
713 CTL_MODE_M) | SD_NO_CTL))) {
714
715 rep = &(pEepData->ctlData[i]);
716 twiceMinEdgePower = ath9k_hw_get_max_edge_power(
717 freq,
718 rep->ctlEdges[ar5416_get_ntxchains(
719 tx_chainmask) - 1],
720 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
721
722 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
723 twiceMaxEdgePower = min(
724 twiceMaxEdgePower,
725 twiceMinEdgePower);
726 else {
727 twiceMaxEdgePower = twiceMinEdgePower;
728 break;
729 }
730 }
731 }
732
733 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
734
735 switch (pCtlMode[ctlMode]) {
736 case CTL_11B:
737 for (i = 0;
738 i < ARRAY_SIZE(targetPowerCck.tPow2x);
739 i++) {
740 targetPowerCck.tPow2x[i] = (u8)min(
741 (u16)targetPowerCck.tPow2x[i],
742 minCtlPower);
743 }
744 break;
745 case CTL_11A:
746 case CTL_11G:
747 for (i = 0;
748 i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
749 i++) {
750 targetPowerOfdm.tPow2x[i] = (u8)min(
751 (u16)targetPowerOfdm.tPow2x[i],
752 minCtlPower);
753 }
754 break;
755 case CTL_5GHT20:
756 case CTL_2GHT20:
757 for (i = 0;
758 i < ARRAY_SIZE(targetPowerHt20.tPow2x);
759 i++) {
760 targetPowerHt20.tPow2x[i] = (u8)min(
761 (u16)targetPowerHt20.tPow2x[i],
762 minCtlPower);
763 }
764 break;
765 case CTL_11B_EXT:
766 targetPowerCckExt.tPow2x[0] = (u8)min(
767 (u16)targetPowerCckExt.tPow2x[0],
768 minCtlPower);
769 break;
770 case CTL_11A_EXT:
771 case CTL_11G_EXT:
772 targetPowerOfdmExt.tPow2x[0] = (u8)min(
773 (u16)targetPowerOfdmExt.tPow2x[0],
774 minCtlPower);
775 break;
776 case CTL_5GHT40:
777 case CTL_2GHT40:
778 for (i = 0;
779 i < ARRAY_SIZE(targetPowerHt40.tPow2x);
780 i++) {
781 targetPowerHt40.tPow2x[i] = (u8)min(
782 (u16)targetPowerHt40.tPow2x[i],
783 minCtlPower);
784 }
785 break;
786 default:
787 break;
788 }
789 }
790
791 ratesArray[rate6mb] =
792 ratesArray[rate9mb] =
793 ratesArray[rate12mb] =
794 ratesArray[rate18mb] =
795 ratesArray[rate24mb] =
796 targetPowerOfdm.tPow2x[0];
797
798 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
799 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
800 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
801 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
802
803 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
804 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
805
806 if (IS_CHAN_2GHZ(chan)) {
807 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
808 ratesArray[rate2s] = ratesArray[rate2l] =
809 targetPowerCck.tPow2x[1];
810 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
811 targetPowerCck.tPow2x[2];
812 ratesArray[rate11s] = ratesArray[rate11l] =
813 targetPowerCck.tPow2x[3];
814 }
815 if (IS_CHAN_HT40(chan)) {
816 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++)
817 ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
818
819 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
820 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
821 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
822 if (IS_CHAN_2GHZ(chan))
823 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
824 }
825
826#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN
827#undef REDUCE_SCALED_POWER_BY_THREE_CHAIN
828}
829
830static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
831 struct ath9k_channel *chan, u16 cfgCtl,
832 u8 twiceAntennaReduction,
833 u8 twiceMaxRegulatoryPower,
834 u8 powerLimit)
835{
836#define INCREASE_MAXPOW_BY_TWO_CHAIN 6
837#define INCREASE_MAXPOW_BY_THREE_CHAIN 10
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700838 struct ath_common *common = ath9k_hw_common(ah);
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -0700839 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
Sujithb5aec952009-08-07 09:45:15 +0530840 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
841 struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
842 int16_t ratesArray[Ar5416RateSize];
843 int16_t txPowerIndexOffset = 0;
844 u8 ht40PowerIncForPdadc = 2;
845 int i;
846
847 memset(ratesArray, 0, sizeof(ratesArray));
848
849 if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
850 AR9287_EEP_MINOR_VER_2)
851 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
852
853 ath9k_hw_set_AR9287_power_per_rate_table(ah, chan,
854 &ratesArray[0], cfgCtl,
855 twiceAntennaReduction,
856 twiceMaxRegulatoryPower,
857 powerLimit);
858
859 ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset);
860
861 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
862 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
863 if (ratesArray[i] > AR9287_MAX_RATE_POWER)
864 ratesArray[i] = AR9287_MAX_RATE_POWER;
865 }
866
867 if (AR_SREV_9280_10_OR_LATER(ah)) {
868 for (i = 0; i < Ar5416RateSize; i++)
869 ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
870 }
871
872 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
873 ATH9K_POW_SM(ratesArray[rate18mb], 24)
874 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
875 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
876 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
877
878 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
879 ATH9K_POW_SM(ratesArray[rate54mb], 24)
880 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
881 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
882 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
883
884 if (IS_CHAN_2GHZ(chan)) {
885 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
886 ATH9K_POW_SM(ratesArray[rate2s], 24)
887 | ATH9K_POW_SM(ratesArray[rate2l], 16)
888 | ATH9K_POW_SM(ratesArray[rateXr], 8)
889 | ATH9K_POW_SM(ratesArray[rate1l], 0));
890 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
891 ATH9K_POW_SM(ratesArray[rate11s], 24)
892 | ATH9K_POW_SM(ratesArray[rate11l], 16)
893 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
894 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
895 }
896
897 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
898 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
899 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
900 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
901 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
902
903 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
904 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
905 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
906 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
907 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
908
909 if (IS_CHAN_HT40(chan)) {
910 if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
911 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
912 ATH9K_POW_SM(ratesArray[rateHt40_3], 24)
913 | ATH9K_POW_SM(ratesArray[rateHt40_2], 16)
914 | ATH9K_POW_SM(ratesArray[rateHt40_1], 8)
915 | ATH9K_POW_SM(ratesArray[rateHt40_0], 0));
916
917 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
918 ATH9K_POW_SM(ratesArray[rateHt40_7], 24)
919 | ATH9K_POW_SM(ratesArray[rateHt40_6], 16)
920 | ATH9K_POW_SM(ratesArray[rateHt40_5], 8)
921 | ATH9K_POW_SM(ratesArray[rateHt40_4], 0));
922 } else {
923 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
924 ATH9K_POW_SM(ratesArray[rateHt40_3] +
925 ht40PowerIncForPdadc, 24)
926 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
927 ht40PowerIncForPdadc, 16)
928 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
929 ht40PowerIncForPdadc, 8)
930 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
931 ht40PowerIncForPdadc, 0));
932
933 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
934 ATH9K_POW_SM(ratesArray[rateHt40_7] +
935 ht40PowerIncForPdadc, 24)
936 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
937 ht40PowerIncForPdadc, 16)
938 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
939 ht40PowerIncForPdadc, 8)
940 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
941 ht40PowerIncForPdadc, 0));
942 }
943
944 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
945 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
946 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
947 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
948 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
949 }
950
951 if (IS_CHAN_2GHZ(chan))
952 i = rate1l;
953 else
954 i = rate6mb;
955
956 if (AR_SREV_9280_10_OR_LATER(ah))
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -0700957 regulatory->max_power_level =
Sujithb5aec952009-08-07 09:45:15 +0530958 ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
959 else
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -0700960 regulatory->max_power_level = ratesArray[i];
Sujithb5aec952009-08-07 09:45:15 +0530961
962 switch (ar5416_get_ntxchains(ah->txchainmask)) {
963 case 1:
964 break;
965 case 2:
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -0700966 regulatory->max_power_level +=
Sujithb5aec952009-08-07 09:45:15 +0530967 INCREASE_MAXPOW_BY_TWO_CHAIN;
968 break;
969 case 3:
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -0700970 regulatory->max_power_level +=
Sujithb5aec952009-08-07 09:45:15 +0530971 INCREASE_MAXPOW_BY_THREE_CHAIN;
972 break;
973 default:
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700974 ath_print(common, ATH_DBG_EEPROM,
975 "Invalid chainmask configuration\n");
Sujithb5aec952009-08-07 09:45:15 +0530976 break;
977 }
978}
979
980static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah,
981 struct ath9k_channel *chan)
982{
983}
984
985static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah,
986 struct ath9k_channel *chan)
987{
988 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
989 struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
990 u16 antWrites[AR9287_ANT_16S];
991 u32 regChainOffset;
992 u8 txRxAttenLocal;
993 int i, j, offset_num;
994
995 pModal = &eep->modalHeader;
996
997 antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF);
998 antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF);
999 antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF);
1000 antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF);
1001 antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF);
1002 antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF);
1003 antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF);
1004 antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF);
1005
1006 offset_num = 8;
1007
1008 for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) {
1009 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf);
1010 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3);
1011 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3);
1012 antWrites[j++] = 0;
1013 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3);
1014 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3);
1015 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3);
1016 antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3);
1017 }
1018
1019 REG_WRITE(ah, AR_PHY_SWITCH_COM,
1020 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
1021
1022 for (i = 0; i < AR9287_MAX_CHAINS; i++) {
1023 regChainOffset = i * 0x1000;
1024
1025 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
1026 pModal->antCtrlChain[i]);
1027
1028 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
1029 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset)
1030 & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
1031 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1032 SM(pModal->iqCalICh[i],
1033 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1034 SM(pModal->iqCalQCh[i],
1035 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
1036
1037 txRxAttenLocal = pModal->txRxAttenCh[i];
1038
1039 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1040 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
1041 pModal->bswMargin[i]);
1042 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1043 AR_PHY_GAIN_2GHZ_XATTEN1_DB,
1044 pModal->bswAtten[i]);
1045 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1046 AR9280_PHY_RXGAIN_TXRX_ATTEN,
1047 txRxAttenLocal);
1048 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1049 AR9280_PHY_RXGAIN_TXRX_MARGIN,
1050 pModal->rxTxMarginCh[i]);
1051 }
1052
1053
1054 if (IS_CHAN_HT40(chan))
1055 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1056 AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
1057 else
1058 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1059 AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
1060
1061 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
1062 AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
1063
1064 REG_WRITE(ah, AR_PHY_RF_CTL4,
1065 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
1066 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
1067 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
1068 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
1069
1070 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3,
1071 AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
1072
1073 REG_RMW_FIELD(ah, AR_PHY_CCA,
1074 AR9280_PHY_CCA_THRESH62, pModal->thresh62);
1075 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
1076 AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
1077
1078 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1,
1079 AR9287_AN_RF2G3_DB1_S, pModal->db1);
1080 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2,
1081 AR9287_AN_RF2G3_DB2_S, pModal->db2);
1082 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
1083 AR9287_AN_RF2G3_OB_CCK,
1084 AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
1085 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
1086 AR9287_AN_RF2G3_OB_PSK,
1087 AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
1088 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
1089 AR9287_AN_RF2G3_OB_QAM,
1090 AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
1091 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
1092 AR9287_AN_RF2G3_OB_PAL_OFF,
1093 AR9287_AN_RF2G3_OB_PAL_OFF_S,
1094 pModal->ob_pal_off);
1095
1096 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1097 AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S,
1098 pModal->db1);
1099 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2,
1100 AR9287_AN_RF2G3_DB2_S, pModal->db2);
1101 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1102 AR9287_AN_RF2G3_OB_CCK,
1103 AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
1104 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1105 AR9287_AN_RF2G3_OB_PSK,
1106 AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
1107 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1108 AR9287_AN_RF2G3_OB_QAM,
1109 AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
1110 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1111 AR9287_AN_RF2G3_OB_PAL_OFF,
1112 AR9287_AN_RF2G3_OB_PAL_OFF_S,
1113 pModal->ob_pal_off);
1114
1115 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
1116 AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
1117 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
1118 AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn);
1119
1120 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2,
1121 AR9287_AN_TOP2_XPABIAS_LVL,
1122 AR9287_AN_TOP2_XPABIAS_LVL_S,
1123 pModal->xpaBiasLvl);
1124}
1125
1126static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah,
1127 enum ieee80211_band freq_band)
1128{
1129 return 1;
1130}
1131
1132static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
1133 struct ath9k_channel *chan)
1134{
1135 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
1136 struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
1137
1138 return pModal->antCtrlCommon & 0xFFFF;
1139}
1140
1141static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah,
1142 u16 i, bool is2GHz)
1143{
1144#define EEP_MAP9287_SPURCHAN \
1145 (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001146 struct ath_common *common = ath9k_hw_common(ah);
Sujithb5aec952009-08-07 09:45:15 +05301147 u16 spur_val = AR_NO_SPUR;
1148
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001149 ath_print(common, ATH_DBG_ANI,
1150 "Getting spur idx %d is2Ghz. %d val %x\n",
1151 i, is2GHz, ah->config.spurchans[i][is2GHz]);
Sujithb5aec952009-08-07 09:45:15 +05301152
1153 switch (ah->config.spurmode) {
1154 case SPUR_DISABLE:
1155 break;
1156 case SPUR_ENABLE_IOCTL:
1157 spur_val = ah->config.spurchans[i][is2GHz];
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001158 ath_print(common, ATH_DBG_ANI,
1159 "Getting spur val from new loc. %d\n", spur_val);
Sujithb5aec952009-08-07 09:45:15 +05301160 break;
1161 case SPUR_ENABLE_EEPROM:
1162 spur_val = EEP_MAP9287_SPURCHAN;
1163 break;
1164 }
1165
1166 return spur_val;
1167
1168#undef EEP_MAP9287_SPURCHAN
1169}
1170
1171const struct eeprom_ops eep_AR9287_ops = {
1172 .check_eeprom = ath9k_hw_AR9287_check_eeprom,
1173 .get_eeprom = ath9k_hw_AR9287_get_eeprom,
1174 .fill_eeprom = ath9k_hw_AR9287_fill_eeprom,
1175 .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver,
1176 .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev,
1177 .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config,
1178 .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg,
1179 .set_board_values = ath9k_hw_AR9287_set_board_values,
1180 .set_addac = ath9k_hw_AR9287_set_addac,
1181 .set_txpower = ath9k_hw_AR9287_set_txpower,
1182 .get_spur_channel = ath9k_hw_AR9287_get_spur_channel
1183};