Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6.git] / drivers / net / wireless / ath / ath9k / eeprom.c
blob93e8ce0598a4f498956bdc90b0d4fcda3fa02df3
1 /*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
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.
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.
17 #include "ath9k.h"
19 static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah,
20 u32 reg, u32 mask,
21 u32 shift, u32 val)
23 u32 regVal;
25 regVal = REG_READ(ah, reg) & ~mask;
26 regVal |= (val << shift) & mask;
28 REG_WRITE(ah, reg, regVal);
30 if (ah->config.analog_shiftreg)
31 udelay(100);
33 return;
36 static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
39 if (fbin == AR5416_BCHAN_UNUSED)
40 return fbin;
42 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
45 static inline int16_t ath9k_hw_interpolate(u16 target,
46 u16 srcLeft, u16 srcRight,
47 int16_t targetLeft,
48 int16_t targetRight)
50 int16_t rv;
52 if (srcRight == srcLeft) {
53 rv = targetLeft;
54 } else {
55 rv = (int16_t) (((target - srcLeft) * targetRight +
56 (srcRight - target) * targetLeft) /
57 (srcRight - srcLeft));
59 return rv;
62 static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
63 u16 listSize, u16 *indexL,
64 u16 *indexR)
66 u16 i;
68 if (target <= pList[0]) {
69 *indexL = *indexR = 0;
70 return true;
72 if (target >= pList[listSize - 1]) {
73 *indexL = *indexR = (u16) (listSize - 1);
74 return true;
77 for (i = 0; i < listSize - 1; i++) {
78 if (pList[i] == target) {
79 *indexL = *indexR = i;
80 return true;
82 if (target < pList[i + 1]) {
83 *indexL = i;
84 *indexR = (u16) (i + 1);
85 return false;
88 return false;
91 static inline bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
93 struct ath_softc *sc = ah->ah_sc;
95 return sc->bus_ops->eeprom_read(ah, off, data);
98 static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
99 u8 *pVpdList, u16 numIntercepts,
100 u8 *pRetVpdList)
102 u16 i, k;
103 u8 currPwr = pwrMin;
104 u16 idxL = 0, idxR = 0;
106 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
107 ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
108 numIntercepts, &(idxL),
109 &(idxR));
110 if (idxR < 1)
111 idxR = 1;
112 if (idxL == numIntercepts - 1)
113 idxL = (u16) (numIntercepts - 2);
114 if (pPwrList[idxL] == pPwrList[idxR])
115 k = pVpdList[idxL];
116 else
117 k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
118 (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
119 (pPwrList[idxR] - pPwrList[idxL]));
120 pRetVpdList[i] = (u8) k;
121 currPwr += 2;
124 return true;
127 static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
128 struct ath9k_channel *chan,
129 struct cal_target_power_leg *powInfo,
130 u16 numChannels,
131 struct cal_target_power_leg *pNewPower,
132 u16 numRates, bool isExtTarget)
134 struct chan_centers centers;
135 u16 clo, chi;
136 int i;
137 int matchIndex = -1, lowIndex = -1;
138 u16 freq;
140 ath9k_hw_get_channel_centers(ah, chan, &centers);
141 freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
143 if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
144 IS_CHAN_2GHZ(chan))) {
145 matchIndex = 0;
146 } else {
147 for (i = 0; (i < numChannels) &&
148 (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
149 if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
150 IS_CHAN_2GHZ(chan))) {
151 matchIndex = i;
152 break;
153 } else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
154 IS_CHAN_2GHZ(chan))) &&
155 (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
156 IS_CHAN_2GHZ(chan)))) {
157 lowIndex = i - 1;
158 break;
161 if ((matchIndex == -1) && (lowIndex == -1))
162 matchIndex = i - 1;
165 if (matchIndex != -1) {
166 *pNewPower = powInfo[matchIndex];
167 } else {
168 clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
169 IS_CHAN_2GHZ(chan));
170 chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
171 IS_CHAN_2GHZ(chan));
173 for (i = 0; i < numRates; i++) {
174 pNewPower->tPow2x[i] =
175 (u8)ath9k_hw_interpolate(freq, clo, chi,
176 powInfo[lowIndex].tPow2x[i],
177 powInfo[lowIndex + 1].tPow2x[i]);
182 static 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)
187 u8 pcdac, i = 0;
188 u16 idxL = 0, idxR = 0, numPiers;
189 bool match;
190 struct chan_centers centers;
192 ath9k_hw_get_channel_centers(ah, chan, &centers);
194 for (numPiers = 0; numPiers < availPiers; numPiers++)
195 if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
196 break;
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;
210 while (pcdac > ah->originalGain[i] &&
211 i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
212 i++;
214 *pcdacIdx = i;
215 return;
218 static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
219 u32 initTxGain,
220 int txPower,
221 u8 *pPDADCValues)
223 u32 i;
224 u32 offset;
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);
231 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
232 AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
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;
245 static void ath9k_hw_get_target_powers(struct ath_hw *ah,
246 struct ath9k_channel *chan,
247 struct cal_target_power_ht *powInfo,
248 u16 numChannels,
249 struct cal_target_power_ht *pNewPower,
250 u16 numRates, bool isHt40Target)
252 struct chan_centers centers;
253 u16 clo, chi;
254 int i;
255 int matchIndex = -1, lowIndex = -1;
256 u16 freq;
258 ath9k_hw_get_channel_centers(ah, chan, &centers);
259 freq = isHt40Target ? centers.synth_center : centers.ctl_center;
261 if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
262 matchIndex = 0;
263 } else {
264 for (i = 0; (i < numChannels) &&
265 (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
266 if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
267 IS_CHAN_2GHZ(chan))) {
268 matchIndex = i;
269 break;
270 } else
271 if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
272 IS_CHAN_2GHZ(chan))) &&
273 (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
274 IS_CHAN_2GHZ(chan)))) {
275 lowIndex = i - 1;
276 break;
279 if ((matchIndex == -1) && (lowIndex == -1))
280 matchIndex = i - 1;
283 if (matchIndex != -1) {
284 *pNewPower = powInfo[matchIndex];
285 } else {
286 clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
287 IS_CHAN_2GHZ(chan));
288 chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
289 IS_CHAN_2GHZ(chan));
291 for (i = 0; i < numRates; i++) {
292 pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
293 clo, chi,
294 powInfo[lowIndex].tPow2x[i],
295 powInfo[lowIndex + 1].tPow2x[i]);
300 static u16 ath9k_hw_get_max_edge_power(u16 freq,
301 struct cal_ctl_edges *pRdEdgesPower,
302 bool is2GHz, int num_band_edges)
304 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
305 int i;
307 for (i = 0; (i < num_band_edges) &&
308 (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
309 if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
310 twiceMaxEdgePower = pRdEdgesPower[i].tPower;
311 break;
312 } else if ((i > 0) &&
313 (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
314 is2GHz))) {
315 if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
316 is2GHz) < freq &&
317 pRdEdgesPower[i - 1].flag) {
318 twiceMaxEdgePower =
319 pRdEdgesPower[i - 1].tPower;
321 break;
325 return twiceMaxEdgePower;
328 /****************************************/
329 /* EEPROM Operations for 4K sized cards */
330 /****************************************/
332 static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
334 return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
337 static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
339 return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
342 static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
344 #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
345 u16 *eep_data = (u16 *)&ah->eeprom.map4k;
346 int addr, eep_start_loc = 0;
348 eep_start_loc = 64;
350 if (!ath9k_hw_use_flash(ah)) {
351 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
352 "Reading from EEPROM, not flash\n");
355 for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
356 if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
357 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
358 "Unable to read eeprom region \n");
359 return false;
361 eep_data++;
364 return true;
365 #undef SIZE_EEPROM_4K
368 static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
370 #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
371 struct ar5416_eeprom_4k *eep =
372 (struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
373 u16 *eepdata, temp, magic, magic2;
374 u32 sum = 0, el;
375 bool need_swap = false;
376 int i, addr;
379 if (!ath9k_hw_use_flash(ah)) {
380 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
381 &magic)) {
382 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
383 "Reading Magic # failed\n");
384 return false;
387 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
388 "Read Magic = 0x%04X\n", magic);
390 if (magic != AR5416_EEPROM_MAGIC) {
391 magic2 = swab16(magic);
393 if (magic2 == AR5416_EEPROM_MAGIC) {
394 need_swap = true;
395 eepdata = (u16 *) (&ah->eeprom);
397 for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
398 temp = swab16(*eepdata);
399 *eepdata = temp;
400 eepdata++;
402 } else {
403 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
404 "Invalid EEPROM Magic. "
405 "endianness mismatch.\n");
406 return -EINVAL;
411 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
412 need_swap ? "True" : "False");
414 if (need_swap)
415 el = swab16(ah->eeprom.map4k.baseEepHeader.length);
416 else
417 el = ah->eeprom.map4k.baseEepHeader.length;
419 if (el > sizeof(struct ar5416_eeprom_4k))
420 el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
421 else
422 el = el / sizeof(u16);
424 eepdata = (u16 *)(&ah->eeprom);
426 for (i = 0; i < el; i++)
427 sum ^= *eepdata++;
429 if (need_swap) {
430 u32 integer;
431 u16 word;
433 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
434 "EEPROM Endianness is not native.. Changing\n");
436 word = swab16(eep->baseEepHeader.length);
437 eep->baseEepHeader.length = word;
439 word = swab16(eep->baseEepHeader.checksum);
440 eep->baseEepHeader.checksum = word;
442 word = swab16(eep->baseEepHeader.version);
443 eep->baseEepHeader.version = word;
445 word = swab16(eep->baseEepHeader.regDmn[0]);
446 eep->baseEepHeader.regDmn[0] = word;
448 word = swab16(eep->baseEepHeader.regDmn[1]);
449 eep->baseEepHeader.regDmn[1] = word;
451 word = swab16(eep->baseEepHeader.rfSilent);
452 eep->baseEepHeader.rfSilent = word;
454 word = swab16(eep->baseEepHeader.blueToothOptions);
455 eep->baseEepHeader.blueToothOptions = word;
457 word = swab16(eep->baseEepHeader.deviceCap);
458 eep->baseEepHeader.deviceCap = word;
460 integer = swab32(eep->modalHeader.antCtrlCommon);
461 eep->modalHeader.antCtrlCommon = integer;
463 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
464 integer = swab32(eep->modalHeader.antCtrlChain[i]);
465 eep->modalHeader.antCtrlChain[i] = integer;
468 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
469 word = swab16(eep->modalHeader.spurChans[i].spurChan);
470 eep->modalHeader.spurChans[i].spurChan = word;
474 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
475 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
476 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
477 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
478 sum, ah->eep_ops->get_eeprom_ver(ah));
479 return -EINVAL;
482 return 0;
483 #undef EEPROM_4K_SIZE
486 static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
487 enum eeprom_param param)
489 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
490 struct modal_eep_4k_header *pModal = &eep->modalHeader;
491 struct base_eep_header_4k *pBase = &eep->baseEepHeader;
493 switch (param) {
494 case EEP_NFTHRESH_2:
495 return pModal->noiseFloorThreshCh[0];
496 case AR_EEPROM_MAC(0):
497 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
498 case AR_EEPROM_MAC(1):
499 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
500 case AR_EEPROM_MAC(2):
501 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
502 case EEP_REG_0:
503 return pBase->regDmn[0];
504 case EEP_REG_1:
505 return pBase->regDmn[1];
506 case EEP_OP_CAP:
507 return pBase->deviceCap;
508 case EEP_OP_MODE:
509 return pBase->opCapFlags;
510 case EEP_RF_SILENT:
511 return pBase->rfSilent;
512 case EEP_OB_2:
513 return pModal->ob_01;
514 case EEP_DB_2:
515 return pModal->db1_01;
516 case EEP_MINOR_REV:
517 return pBase->version & AR5416_EEP_VER_MINOR_MASK;
518 case EEP_TX_MASK:
519 return pBase->txMask;
520 case EEP_RX_MASK:
521 return pBase->rxMask;
522 case EEP_FRAC_N_5G:
523 return 0;
524 default:
525 return 0;
529 static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
530 struct ath9k_channel *chan,
531 struct cal_data_per_freq_4k *pRawDataSet,
532 u8 *bChans, u16 availPiers,
533 u16 tPdGainOverlap, int16_t *pMinCalPower,
534 u16 *pPdGainBoundaries, u8 *pPDADCValues,
535 u16 numXpdGains)
537 #define TMP_VAL_VPD_TABLE \
538 ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
539 int i, j, k;
540 int16_t ss;
541 u16 idxL = 0, idxR = 0, numPiers;
542 static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
543 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
544 static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
545 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
546 static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
547 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
549 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
550 u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
551 u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
552 int16_t vpdStep;
553 int16_t tmpVal;
554 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
555 bool match;
556 int16_t minDelta = 0;
557 struct chan_centers centers;
558 #define PD_GAIN_BOUNDARY_DEFAULT 58;
560 ath9k_hw_get_channel_centers(ah, chan, &centers);
562 for (numPiers = 0; numPiers < availPiers; numPiers++) {
563 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
564 break;
567 match = ath9k_hw_get_lower_upper_index(
568 (u8)FREQ2FBIN(centers.synth_center,
569 IS_CHAN_2GHZ(chan)), bChans, numPiers,
570 &idxL, &idxR);
572 if (match) {
573 for (i = 0; i < numXpdGains; i++) {
574 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
575 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
576 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
577 pRawDataSet[idxL].pwrPdg[i],
578 pRawDataSet[idxL].vpdPdg[i],
579 AR5416_EEP4K_PD_GAIN_ICEPTS,
580 vpdTableI[i]);
582 } else {
583 for (i = 0; i < numXpdGains; i++) {
584 pVpdL = pRawDataSet[idxL].vpdPdg[i];
585 pPwrL = pRawDataSet[idxL].pwrPdg[i];
586 pVpdR = pRawDataSet[idxR].vpdPdg[i];
587 pPwrR = pRawDataSet[idxR].pwrPdg[i];
589 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
591 maxPwrT4[i] =
592 min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
593 pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
596 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
597 pPwrL, pVpdL,
598 AR5416_EEP4K_PD_GAIN_ICEPTS,
599 vpdTableL[i]);
600 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
601 pPwrR, pVpdR,
602 AR5416_EEP4K_PD_GAIN_ICEPTS,
603 vpdTableR[i]);
605 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
606 vpdTableI[i][j] =
607 (u8)(ath9k_hw_interpolate((u16)
608 FREQ2FBIN(centers.
609 synth_center,
610 IS_CHAN_2GHZ
611 (chan)),
612 bChans[idxL], bChans[idxR],
613 vpdTableL[i][j], vpdTableR[i][j]));
618 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
620 k = 0;
622 for (i = 0; i < numXpdGains; i++) {
623 if (i == (numXpdGains - 1))
624 pPdGainBoundaries[i] =
625 (u16)(maxPwrT4[i] / 2);
626 else
627 pPdGainBoundaries[i] =
628 (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
630 pPdGainBoundaries[i] =
631 min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
633 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
634 minDelta = pPdGainBoundaries[0] - 23;
635 pPdGainBoundaries[0] = 23;
636 } else {
637 minDelta = 0;
640 if (i == 0) {
641 if (AR_SREV_9280_10_OR_LATER(ah))
642 ss = (int16_t)(0 - (minPwrT4[i] / 2));
643 else
644 ss = 0;
645 } else {
646 ss = (int16_t)((pPdGainBoundaries[i - 1] -
647 (minPwrT4[i] / 2)) -
648 tPdGainOverlap + 1 + minDelta);
650 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
651 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
653 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
654 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
655 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
656 ss++;
659 sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
660 tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
661 (minPwrT4[i] / 2));
662 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
663 tgtIndex : sizeCurrVpdTable;
665 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
666 pPDADCValues[k++] = vpdTableI[i][ss++];
668 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
669 vpdTableI[i][sizeCurrVpdTable - 2]);
670 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
672 if (tgtIndex >= maxIndex) {
673 while ((ss <= tgtIndex) &&
674 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
675 tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
676 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
677 255 : tmpVal);
678 ss++;
683 while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
684 pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
685 i++;
688 while (k < AR5416_NUM_PDADC_VALUES) {
689 pPDADCValues[k] = pPDADCValues[k - 1];
690 k++;
693 return;
694 #undef TMP_VAL_VPD_TABLE
697 static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
698 struct ath9k_channel *chan,
699 int16_t *pTxPowerIndexOffset)
701 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
702 struct cal_data_per_freq_4k *pRawDataset;
703 u8 *pCalBChans = NULL;
704 u16 pdGainOverlap_t2;
705 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
706 u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
707 u16 numPiers, i, j;
708 int16_t tMinCalPower;
709 u16 numXpdGain, xpdMask;
710 u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
711 u32 reg32, regOffset, regChainOffset;
713 xpdMask = pEepData->modalHeader.xpdGain;
715 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
716 AR5416_EEP_MINOR_VER_2) {
717 pdGainOverlap_t2 =
718 pEepData->modalHeader.pdGainOverlap;
719 } else {
720 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
721 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
724 pCalBChans = pEepData->calFreqPier2G;
725 numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
727 numXpdGain = 0;
729 for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
730 if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
731 if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
732 break;
733 xpdGainValues[numXpdGain] =
734 (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
735 numXpdGain++;
739 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
740 (numXpdGain - 1) & 0x3);
741 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
742 xpdGainValues[0]);
743 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
744 xpdGainValues[1]);
745 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
747 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
748 if (AR_SREV_5416_20_OR_LATER(ah) &&
749 (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
750 (i != 0)) {
751 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
752 } else
753 regChainOffset = i * 0x1000;
755 if (pEepData->baseEepHeader.txMask & (1 << i)) {
756 pRawDataset = pEepData->calPierData2G[i];
758 ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
759 pRawDataset, pCalBChans,
760 numPiers, pdGainOverlap_t2,
761 &tMinCalPower, gainBoundaries,
762 pdadcValues, numXpdGain);
764 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
765 REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
766 SM(pdGainOverlap_t2,
767 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
768 | SM(gainBoundaries[0],
769 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
770 | SM(gainBoundaries[1],
771 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
772 | SM(gainBoundaries[2],
773 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
774 | SM(gainBoundaries[3],
775 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
778 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
779 for (j = 0; j < 32; j++) {
780 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
781 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
782 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
783 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
784 REG_WRITE(ah, regOffset, reg32);
786 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
787 "PDADC (%d,%4x): %4.4x %8.8x\n",
788 i, regChainOffset, regOffset,
789 reg32);
790 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
791 "PDADC: Chain %d | "
792 "PDADC %3d Value %3d | "
793 "PDADC %3d Value %3d | "
794 "PDADC %3d Value %3d | "
795 "PDADC %3d Value %3d |\n",
796 i, 4 * j, pdadcValues[4 * j],
797 4 * j + 1, pdadcValues[4 * j + 1],
798 4 * j + 2, pdadcValues[4 * j + 2],
799 4 * j + 3,
800 pdadcValues[4 * j + 3]);
802 regOffset += 4;
807 *pTxPowerIndexOffset = 0;
810 static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
811 struct ath9k_channel *chan,
812 int16_t *ratesArray,
813 u16 cfgCtl,
814 u16 AntennaReduction,
815 u16 twiceMaxRegulatoryPower,
816 u16 powerLimit)
818 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
819 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
820 static const u16 tpScaleReductionTable[5] =
821 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
823 int i;
824 int16_t twiceLargestAntenna;
825 struct cal_ctl_data_4k *rep;
826 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
827 0, { 0, 0, 0, 0}
829 struct cal_target_power_leg targetPowerOfdmExt = {
830 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
831 0, { 0, 0, 0, 0 }
833 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
834 0, {0, 0, 0, 0}
836 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
837 u16 ctlModesFor11g[] =
838 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
839 CTL_2GHT40
841 u16 numCtlModes, *pCtlMode, ctlMode, freq;
842 struct chan_centers centers;
843 int tx_chainmask;
844 u16 twiceMinEdgePower;
846 tx_chainmask = ah->txchainmask;
848 ath9k_hw_get_channel_centers(ah, chan, &centers);
850 twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
852 twiceLargestAntenna = (int16_t)min(AntennaReduction -
853 twiceLargestAntenna, 0);
855 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
857 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
858 maxRegAllowedPower -=
859 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
862 scaledPower = min(powerLimit, maxRegAllowedPower);
863 scaledPower = max((u16)0, scaledPower);
865 numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
866 pCtlMode = ctlModesFor11g;
868 ath9k_hw_get_legacy_target_powers(ah, chan,
869 pEepData->calTargetPowerCck,
870 AR5416_NUM_2G_CCK_TARGET_POWERS,
871 &targetPowerCck, 4, false);
872 ath9k_hw_get_legacy_target_powers(ah, chan,
873 pEepData->calTargetPower2G,
874 AR5416_NUM_2G_20_TARGET_POWERS,
875 &targetPowerOfdm, 4, false);
876 ath9k_hw_get_target_powers(ah, chan,
877 pEepData->calTargetPower2GHT20,
878 AR5416_NUM_2G_20_TARGET_POWERS,
879 &targetPowerHt20, 8, false);
881 if (IS_CHAN_HT40(chan)) {
882 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
883 ath9k_hw_get_target_powers(ah, chan,
884 pEepData->calTargetPower2GHT40,
885 AR5416_NUM_2G_40_TARGET_POWERS,
886 &targetPowerHt40, 8, true);
887 ath9k_hw_get_legacy_target_powers(ah, chan,
888 pEepData->calTargetPowerCck,
889 AR5416_NUM_2G_CCK_TARGET_POWERS,
890 &targetPowerCckExt, 4, true);
891 ath9k_hw_get_legacy_target_powers(ah, chan,
892 pEepData->calTargetPower2G,
893 AR5416_NUM_2G_20_TARGET_POWERS,
894 &targetPowerOfdmExt, 4, true);
897 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
898 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
899 (pCtlMode[ctlMode] == CTL_2GHT40);
900 if (isHt40CtlMode)
901 freq = centers.synth_center;
902 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
903 freq = centers.ext_center;
904 else
905 freq = centers.ctl_center;
907 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
908 ah->eep_ops->get_eeprom_rev(ah) <= 2)
909 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
911 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
912 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
913 "EXT_ADDITIVE %d\n",
914 ctlMode, numCtlModes, isHt40CtlMode,
915 (pCtlMode[ctlMode] & EXT_ADDITIVE));
917 for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
918 pEepData->ctlIndex[i]; i++) {
919 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
920 " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
921 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
922 "chan %d\n",
923 i, cfgCtl, pCtlMode[ctlMode],
924 pEepData->ctlIndex[i], chan->channel);
926 if ((((cfgCtl & ~CTL_MODE_M) |
927 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
928 pEepData->ctlIndex[i]) ||
929 (((cfgCtl & ~CTL_MODE_M) |
930 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
931 ((pEepData->ctlIndex[i] & CTL_MODE_M) |
932 SD_NO_CTL))) {
933 rep = &(pEepData->ctlData[i]);
935 twiceMinEdgePower =
936 ath9k_hw_get_max_edge_power(freq,
937 rep->ctlEdges[ar5416_get_ntxchains
938 (tx_chainmask) - 1],
939 IS_CHAN_2GHZ(chan),
940 AR5416_EEP4K_NUM_BAND_EDGES);
942 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
943 " MATCH-EE_IDX %d: ch %d is2 %d "
944 "2xMinEdge %d chainmask %d chains %d\n",
945 i, freq, IS_CHAN_2GHZ(chan),
946 twiceMinEdgePower, tx_chainmask,
947 ar5416_get_ntxchains
948 (tx_chainmask));
949 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
950 twiceMaxEdgePower =
951 min(twiceMaxEdgePower,
952 twiceMinEdgePower);
953 } else {
954 twiceMaxEdgePower = twiceMinEdgePower;
955 break;
960 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
962 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
963 " SEL-Min ctlMode %d pCtlMode %d "
964 "2xMaxEdge %d sP %d minCtlPwr %d\n",
965 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
966 scaledPower, minCtlPower);
968 switch (pCtlMode[ctlMode]) {
969 case CTL_11B:
970 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
971 i++) {
972 targetPowerCck.tPow2x[i] =
973 min((u16)targetPowerCck.tPow2x[i],
974 minCtlPower);
976 break;
977 case CTL_11G:
978 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
979 i++) {
980 targetPowerOfdm.tPow2x[i] =
981 min((u16)targetPowerOfdm.tPow2x[i],
982 minCtlPower);
984 break;
985 case CTL_2GHT20:
986 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
987 i++) {
988 targetPowerHt20.tPow2x[i] =
989 min((u16)targetPowerHt20.tPow2x[i],
990 minCtlPower);
992 break;
993 case CTL_11B_EXT:
994 targetPowerCckExt.tPow2x[0] = min((u16)
995 targetPowerCckExt.tPow2x[0],
996 minCtlPower);
997 break;
998 case CTL_11G_EXT:
999 targetPowerOfdmExt.tPow2x[0] = min((u16)
1000 targetPowerOfdmExt.tPow2x[0],
1001 minCtlPower);
1002 break;
1003 case CTL_2GHT40:
1004 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
1005 i++) {
1006 targetPowerHt40.tPow2x[i] =
1007 min((u16)targetPowerHt40.tPow2x[i],
1008 minCtlPower);
1010 break;
1011 default:
1012 break;
1016 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
1017 ratesArray[rate18mb] = ratesArray[rate24mb] =
1018 targetPowerOfdm.tPow2x[0];
1019 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
1020 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
1021 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
1022 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
1024 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
1025 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
1027 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
1028 ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
1029 ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
1030 ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
1032 if (IS_CHAN_HT40(chan)) {
1033 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
1034 ratesArray[rateHt40_0 + i] =
1035 targetPowerHt40.tPow2x[i];
1037 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
1038 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
1039 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
1040 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
1044 static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
1045 struct ath9k_channel *chan,
1046 u16 cfgCtl,
1047 u8 twiceAntennaReduction,
1048 u8 twiceMaxRegulatoryPower,
1049 u8 powerLimit)
1051 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
1052 struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
1053 int16_t ratesArray[Ar5416RateSize];
1054 int16_t txPowerIndexOffset = 0;
1055 u8 ht40PowerIncForPdadc = 2;
1056 int i;
1058 memset(ratesArray, 0, sizeof(ratesArray));
1060 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1061 AR5416_EEP_MINOR_VER_2) {
1062 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
1065 ath9k_hw_set_4k_power_per_rate_table(ah, chan,
1066 &ratesArray[0], cfgCtl,
1067 twiceAntennaReduction,
1068 twiceMaxRegulatoryPower,
1069 powerLimit);
1071 ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
1073 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
1074 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
1075 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
1076 ratesArray[i] = AR5416_MAX_RATE_POWER;
1079 if (AR_SREV_9280_10_OR_LATER(ah)) {
1080 for (i = 0; i < Ar5416RateSize; i++)
1081 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
1084 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
1085 ATH9K_POW_SM(ratesArray[rate18mb], 24)
1086 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
1087 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
1088 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
1089 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
1090 ATH9K_POW_SM(ratesArray[rate54mb], 24)
1091 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
1092 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
1093 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
1095 if (IS_CHAN_2GHZ(chan)) {
1096 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
1097 ATH9K_POW_SM(ratesArray[rate2s], 24)
1098 | ATH9K_POW_SM(ratesArray[rate2l], 16)
1099 | ATH9K_POW_SM(ratesArray[rateXr], 8)
1100 | ATH9K_POW_SM(ratesArray[rate1l], 0));
1101 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
1102 ATH9K_POW_SM(ratesArray[rate11s], 24)
1103 | ATH9K_POW_SM(ratesArray[rate11l], 16)
1104 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
1105 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
1108 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
1109 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
1110 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
1111 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
1112 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
1113 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
1114 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
1115 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
1116 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
1117 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
1119 if (IS_CHAN_HT40(chan)) {
1120 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
1121 ATH9K_POW_SM(ratesArray[rateHt40_3] +
1122 ht40PowerIncForPdadc, 24)
1123 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
1124 ht40PowerIncForPdadc, 16)
1125 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
1126 ht40PowerIncForPdadc, 8)
1127 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
1128 ht40PowerIncForPdadc, 0));
1129 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
1130 ATH9K_POW_SM(ratesArray[rateHt40_7] +
1131 ht40PowerIncForPdadc, 24)
1132 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
1133 ht40PowerIncForPdadc, 16)
1134 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
1135 ht40PowerIncForPdadc, 8)
1136 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
1137 ht40PowerIncForPdadc, 0));
1139 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
1140 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
1141 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
1142 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
1143 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
1146 i = rate6mb;
1148 if (IS_CHAN_HT40(chan))
1149 i = rateHt40_0;
1150 else if (IS_CHAN_HT20(chan))
1151 i = rateHt20_0;
1153 if (AR_SREV_9280_10_OR_LATER(ah))
1154 ah->regulatory.max_power_level =
1155 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
1156 else
1157 ah->regulatory.max_power_level = ratesArray[i];
1161 static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
1162 struct ath9k_channel *chan)
1164 struct modal_eep_4k_header *pModal;
1165 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1166 u8 biaslevel;
1168 if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
1169 return;
1171 if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
1172 return;
1174 pModal = &eep->modalHeader;
1176 if (pModal->xpaBiasLvl != 0xff) {
1177 biaslevel = pModal->xpaBiasLvl;
1178 INI_RA(&ah->iniAddac, 7, 1) =
1179 (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
1183 static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
1184 struct modal_eep_4k_header *pModal,
1185 struct ar5416_eeprom_4k *eep,
1186 u8 txRxAttenLocal, int regChainOffset)
1188 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
1189 pModal->antCtrlChain[0]);
1191 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
1192 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
1193 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
1194 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1195 SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1196 SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
1198 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1199 AR5416_EEP_MINOR_VER_3) {
1200 txRxAttenLocal = pModal->txRxAttenCh[0];
1202 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1203 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
1204 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1205 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
1206 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1207 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
1208 pModal->xatten2Margin[0]);
1209 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1210 AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
1212 /* Set the block 1 value to block 0 value */
1213 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
1214 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
1215 pModal->bswMargin[0]);
1216 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
1217 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
1218 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
1219 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
1220 pModal->xatten2Margin[0]);
1221 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
1222 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
1223 pModal->xatten2Db[0]);
1226 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1227 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
1228 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1229 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
1231 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
1232 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
1233 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
1234 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
1236 if (AR_SREV_9285_11(ah))
1237 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
1240 static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
1241 struct ath9k_channel *chan)
1243 struct modal_eep_4k_header *pModal;
1244 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1245 u8 txRxAttenLocal;
1246 u8 ob[5], db1[5], db2[5];
1247 u8 ant_div_control1, ant_div_control2;
1248 u32 regVal;
1250 pModal = &eep->modalHeader;
1251 txRxAttenLocal = 23;
1253 REG_WRITE(ah, AR_PHY_SWITCH_COM,
1254 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
1256 /* Single chain for 4K EEPROM*/
1257 ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0);
1259 /* Initialize Ant Diversity settings from EEPROM */
1260 if (pModal->version >= 3) {
1261 ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
1262 ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
1263 regVal = REG_READ(ah, 0x99ac);
1264 regVal &= (~(0x7f000000));
1265 regVal |= ((ant_div_control1 & 0x1) << 24);
1266 regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
1267 regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
1268 regVal |= ((ant_div_control2 & 0x3) << 25);
1269 regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
1270 REG_WRITE(ah, 0x99ac, regVal);
1271 regVal = REG_READ(ah, 0x99ac);
1272 regVal = REG_READ(ah, 0xa208);
1273 regVal &= (~(0x1 << 13));
1274 regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
1275 REG_WRITE(ah, 0xa208, regVal);
1276 regVal = REG_READ(ah, 0xa208);
1279 if (pModal->version >= 2) {
1280 ob[0] = (pModal->ob_01 & 0xf);
1281 ob[1] = (pModal->ob_01 >> 4) & 0xf;
1282 ob[2] = (pModal->ob_234 & 0xf);
1283 ob[3] = ((pModal->ob_234 >> 4) & 0xf);
1284 ob[4] = ((pModal->ob_234 >> 8) & 0xf);
1286 db1[0] = (pModal->db1_01 & 0xf);
1287 db1[1] = ((pModal->db1_01 >> 4) & 0xf);
1288 db1[2] = (pModal->db1_234 & 0xf);
1289 db1[3] = ((pModal->db1_234 >> 4) & 0xf);
1290 db1[4] = ((pModal->db1_234 >> 8) & 0xf);
1292 db2[0] = (pModal->db2_01 & 0xf);
1293 db2[1] = ((pModal->db2_01 >> 4) & 0xf);
1294 db2[2] = (pModal->db2_234 & 0xf);
1295 db2[3] = ((pModal->db2_234 >> 4) & 0xf);
1296 db2[4] = ((pModal->db2_234 >> 8) & 0xf);
1298 } else if (pModal->version == 1) {
1299 ob[0] = (pModal->ob_01 & 0xf);
1300 ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
1301 db1[0] = (pModal->db1_01 & 0xf);
1302 db1[1] = db1[2] = db1[3] =
1303 db1[4] = ((pModal->db1_01 >> 4) & 0xf);
1304 db2[0] = (pModal->db2_01 & 0xf);
1305 db2[1] = db2[2] = db2[3] =
1306 db2[4] = ((pModal->db2_01 >> 4) & 0xf);
1307 } else {
1308 int i;
1309 for (i = 0; i < 5; i++) {
1310 ob[i] = pModal->ob_01;
1311 db1[i] = pModal->db1_01;
1312 db2[i] = pModal->db1_01;
1316 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1317 AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
1318 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1319 AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
1320 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1321 AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
1322 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1323 AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
1324 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1325 AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
1327 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1328 AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
1329 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1330 AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
1331 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
1332 AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
1333 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1334 AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
1335 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1336 AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
1338 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1339 AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
1340 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1341 AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
1342 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1343 AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
1344 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1345 AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
1346 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
1347 AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
1350 if (AR_SREV_9285_11(ah))
1351 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
1353 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
1354 pModal->switchSettling);
1355 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
1356 pModal->adcDesiredSize);
1358 REG_WRITE(ah, AR_PHY_RF_CTL4,
1359 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
1360 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
1361 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
1362 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
1364 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
1365 pModal->txEndToRxOn);
1366 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
1367 pModal->thresh62);
1368 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
1369 pModal->thresh62);
1371 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1372 AR5416_EEP_MINOR_VER_2) {
1373 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
1374 pModal->txFrameToDataStart);
1375 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
1376 pModal->txFrameToPaOn);
1379 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1380 AR5416_EEP_MINOR_VER_3) {
1381 if (IS_CHAN_HT40(chan))
1382 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1383 AR_PHY_SETTLING_SWITCH,
1384 pModal->swSettleHt40);
1388 static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
1389 struct ath9k_channel *chan)
1391 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1392 struct modal_eep_4k_header *pModal = &eep->modalHeader;
1394 return pModal->antCtrlCommon & 0xFFFF;
1397 static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
1398 enum ieee80211_band freq_band)
1400 return 1;
1403 static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
1405 #define EEP_MAP4K_SPURCHAN \
1406 (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
1408 u16 spur_val = AR_NO_SPUR;
1410 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1411 "Getting spur idx %d is2Ghz. %d val %x\n",
1412 i, is2GHz, ah->config.spurchans[i][is2GHz]);
1414 switch (ah->config.spurmode) {
1415 case SPUR_DISABLE:
1416 break;
1417 case SPUR_ENABLE_IOCTL:
1418 spur_val = ah->config.spurchans[i][is2GHz];
1419 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1420 "Getting spur val from new loc. %d\n", spur_val);
1421 break;
1422 case SPUR_ENABLE_EEPROM:
1423 spur_val = EEP_MAP4K_SPURCHAN;
1424 break;
1427 return spur_val;
1429 #undef EEP_MAP4K_SPURCHAN
1432 static struct eeprom_ops eep_4k_ops = {
1433 .check_eeprom = ath9k_hw_4k_check_eeprom,
1434 .get_eeprom = ath9k_hw_4k_get_eeprom,
1435 .fill_eeprom = ath9k_hw_4k_fill_eeprom,
1436 .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
1437 .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
1438 .get_num_ant_config = ath9k_hw_4k_get_num_ant_config,
1439 .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg,
1440 .set_board_values = ath9k_hw_4k_set_board_values,
1441 .set_addac = ath9k_hw_4k_set_addac,
1442 .set_txpower = ath9k_hw_4k_set_txpower,
1443 .get_spur_channel = ath9k_hw_4k_get_spur_channel
1446 /************************************************/
1447 /* EEPROM Operations for non-4K (Default) cards */
1448 /************************************************/
1450 static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
1452 return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
1455 static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
1457 return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
1460 static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
1462 #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
1463 u16 *eep_data = (u16 *)&ah->eeprom.def;
1464 int addr, ar5416_eep_start_loc = 0x100;
1466 for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
1467 if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
1468 eep_data)) {
1469 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1470 "Unable to read eeprom region\n");
1471 return false;
1473 eep_data++;
1475 return true;
1476 #undef SIZE_EEPROM_DEF
1479 static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
1481 struct ar5416_eeprom_def *eep =
1482 (struct ar5416_eeprom_def *) &ah->eeprom.def;
1483 u16 *eepdata, temp, magic, magic2;
1484 u32 sum = 0, el;
1485 bool need_swap = false;
1486 int i, addr, size;
1488 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
1489 DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n");
1490 return false;
1493 if (!ath9k_hw_use_flash(ah)) {
1494 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1495 "Read Magic = 0x%04X\n", magic);
1497 if (magic != AR5416_EEPROM_MAGIC) {
1498 magic2 = swab16(magic);
1500 if (magic2 == AR5416_EEPROM_MAGIC) {
1501 size = sizeof(struct ar5416_eeprom_def);
1502 need_swap = true;
1503 eepdata = (u16 *) (&ah->eeprom);
1505 for (addr = 0; addr < size / sizeof(u16); addr++) {
1506 temp = swab16(*eepdata);
1507 *eepdata = temp;
1508 eepdata++;
1510 } else {
1511 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1512 "Invalid EEPROM Magic. "
1513 "Endianness mismatch.\n");
1514 return -EINVAL;
1519 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
1520 need_swap ? "True" : "False");
1522 if (need_swap)
1523 el = swab16(ah->eeprom.def.baseEepHeader.length);
1524 else
1525 el = ah->eeprom.def.baseEepHeader.length;
1527 if (el > sizeof(struct ar5416_eeprom_def))
1528 el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
1529 else
1530 el = el / sizeof(u16);
1532 eepdata = (u16 *)(&ah->eeprom);
1534 for (i = 0; i < el; i++)
1535 sum ^= *eepdata++;
1537 if (need_swap) {
1538 u32 integer, j;
1539 u16 word;
1541 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1542 "EEPROM Endianness is not native.. Changing.\n");
1544 word = swab16(eep->baseEepHeader.length);
1545 eep->baseEepHeader.length = word;
1547 word = swab16(eep->baseEepHeader.checksum);
1548 eep->baseEepHeader.checksum = word;
1550 word = swab16(eep->baseEepHeader.version);
1551 eep->baseEepHeader.version = word;
1553 word = swab16(eep->baseEepHeader.regDmn[0]);
1554 eep->baseEepHeader.regDmn[0] = word;
1556 word = swab16(eep->baseEepHeader.regDmn[1]);
1557 eep->baseEepHeader.regDmn[1] = word;
1559 word = swab16(eep->baseEepHeader.rfSilent);
1560 eep->baseEepHeader.rfSilent = word;
1562 word = swab16(eep->baseEepHeader.blueToothOptions);
1563 eep->baseEepHeader.blueToothOptions = word;
1565 word = swab16(eep->baseEepHeader.deviceCap);
1566 eep->baseEepHeader.deviceCap = word;
1568 for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
1569 struct modal_eep_header *pModal =
1570 &eep->modalHeader[j];
1571 integer = swab32(pModal->antCtrlCommon);
1572 pModal->antCtrlCommon = integer;
1574 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1575 integer = swab32(pModal->antCtrlChain[i]);
1576 pModal->antCtrlChain[i] = integer;
1579 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
1580 word = swab16(pModal->spurChans[i].spurChan);
1581 pModal->spurChans[i].spurChan = word;
1586 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
1587 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
1588 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1589 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
1590 sum, ah->eep_ops->get_eeprom_ver(ah));
1591 return -EINVAL;
1594 return 0;
1597 static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
1598 enum eeprom_param param)
1600 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1601 struct modal_eep_header *pModal = eep->modalHeader;
1602 struct base_eep_header *pBase = &eep->baseEepHeader;
1604 switch (param) {
1605 case EEP_NFTHRESH_5:
1606 return pModal[0].noiseFloorThreshCh[0];
1607 case EEP_NFTHRESH_2:
1608 return pModal[1].noiseFloorThreshCh[0];
1609 case AR_EEPROM_MAC(0):
1610 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
1611 case AR_EEPROM_MAC(1):
1612 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
1613 case AR_EEPROM_MAC(2):
1614 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
1615 case EEP_REG_0:
1616 return pBase->regDmn[0];
1617 case EEP_REG_1:
1618 return pBase->regDmn[1];
1619 case EEP_OP_CAP:
1620 return pBase->deviceCap;
1621 case EEP_OP_MODE:
1622 return pBase->opCapFlags;
1623 case EEP_RF_SILENT:
1624 return pBase->rfSilent;
1625 case EEP_OB_5:
1626 return pModal[0].ob;
1627 case EEP_DB_5:
1628 return pModal[0].db;
1629 case EEP_OB_2:
1630 return pModal[1].ob;
1631 case EEP_DB_2:
1632 return pModal[1].db;
1633 case EEP_MINOR_REV:
1634 return AR5416_VER_MASK;
1635 case EEP_TX_MASK:
1636 return pBase->txMask;
1637 case EEP_RX_MASK:
1638 return pBase->rxMask;
1639 case EEP_RXGAIN_TYPE:
1640 return pBase->rxGainType;
1641 case EEP_TXGAIN_TYPE:
1642 return pBase->txGainType;
1643 case EEP_OL_PWRCTRL:
1644 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1645 return pBase->openLoopPwrCntl ? true : false;
1646 else
1647 return false;
1648 case EEP_RC_CHAIN_MASK:
1649 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1650 return pBase->rcChainMask;
1651 else
1652 return 0;
1653 case EEP_DAC_HPWR_5G:
1654 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
1655 return pBase->dacHiPwrMode_5G;
1656 else
1657 return 0;
1658 case EEP_FRAC_N_5G:
1659 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
1660 return pBase->frac_n_5g;
1661 else
1662 return 0;
1663 default:
1664 return 0;
1668 static void ath9k_hw_def_set_gain(struct ath_hw *ah,
1669 struct modal_eep_header *pModal,
1670 struct ar5416_eeprom_def *eep,
1671 u8 txRxAttenLocal, int regChainOffset, int i)
1673 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
1674 txRxAttenLocal = pModal->txRxAttenCh[i];
1676 if (AR_SREV_9280_10_OR_LATER(ah)) {
1677 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1678 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
1679 pModal->bswMargin[i]);
1680 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1681 AR_PHY_GAIN_2GHZ_XATTEN1_DB,
1682 pModal->bswAtten[i]);
1683 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1684 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
1685 pModal->xatten2Margin[i]);
1686 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1687 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
1688 pModal->xatten2Db[i]);
1689 } else {
1690 REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1691 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1692 ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
1693 | SM(pModal-> bswMargin[i],
1694 AR_PHY_GAIN_2GHZ_BSW_MARGIN));
1695 REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1696 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1697 ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
1698 | SM(pModal->bswAtten[i],
1699 AR_PHY_GAIN_2GHZ_BSW_ATTEN));
1703 if (AR_SREV_9280_10_OR_LATER(ah)) {
1704 REG_RMW_FIELD(ah,
1705 AR_PHY_RXGAIN + regChainOffset,
1706 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
1707 REG_RMW_FIELD(ah,
1708 AR_PHY_RXGAIN + regChainOffset,
1709 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
1710 } else {
1711 REG_WRITE(ah,
1712 AR_PHY_RXGAIN + regChainOffset,
1713 (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
1714 ~AR_PHY_RXGAIN_TXRX_ATTEN)
1715 | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
1716 REG_WRITE(ah,
1717 AR_PHY_GAIN_2GHZ + regChainOffset,
1718 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1719 ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
1720 SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
1724 static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
1725 struct ath9k_channel *chan)
1727 struct modal_eep_header *pModal;
1728 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1729 int i, regChainOffset;
1730 u8 txRxAttenLocal;
1732 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
1733 txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
1735 REG_WRITE(ah, AR_PHY_SWITCH_COM,
1736 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
1738 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1739 if (AR_SREV_9280(ah)) {
1740 if (i >= 2)
1741 break;
1744 if (AR_SREV_5416_20_OR_LATER(ah) &&
1745 (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
1746 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
1747 else
1748 regChainOffset = i * 0x1000;
1750 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
1751 pModal->antCtrlChain[i]);
1753 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
1754 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
1755 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
1756 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1757 SM(pModal->iqCalICh[i],
1758 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1759 SM(pModal->iqCalQCh[i],
1760 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
1762 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
1763 ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
1764 regChainOffset, i);
1767 if (AR_SREV_9280_10_OR_LATER(ah)) {
1768 if (IS_CHAN_2GHZ(chan)) {
1769 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
1770 AR_AN_RF2G1_CH0_OB,
1771 AR_AN_RF2G1_CH0_OB_S,
1772 pModal->ob);
1773 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
1774 AR_AN_RF2G1_CH0_DB,
1775 AR_AN_RF2G1_CH0_DB_S,
1776 pModal->db);
1777 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
1778 AR_AN_RF2G1_CH1_OB,
1779 AR_AN_RF2G1_CH1_OB_S,
1780 pModal->ob_ch1);
1781 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
1782 AR_AN_RF2G1_CH1_DB,
1783 AR_AN_RF2G1_CH1_DB_S,
1784 pModal->db_ch1);
1785 } else {
1786 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
1787 AR_AN_RF5G1_CH0_OB5,
1788 AR_AN_RF5G1_CH0_OB5_S,
1789 pModal->ob);
1790 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
1791 AR_AN_RF5G1_CH0_DB5,
1792 AR_AN_RF5G1_CH0_DB5_S,
1793 pModal->db);
1794 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
1795 AR_AN_RF5G1_CH1_OB5,
1796 AR_AN_RF5G1_CH1_OB5_S,
1797 pModal->ob_ch1);
1798 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
1799 AR_AN_RF5G1_CH1_DB5,
1800 AR_AN_RF5G1_CH1_DB5_S,
1801 pModal->db_ch1);
1803 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
1804 AR_AN_TOP2_XPABIAS_LVL,
1805 AR_AN_TOP2_XPABIAS_LVL_S,
1806 pModal->xpaBiasLvl);
1807 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
1808 AR_AN_TOP2_LOCALBIAS,
1809 AR_AN_TOP2_LOCALBIAS_S,
1810 pModal->local_bias);
1811 REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
1812 pModal->force_xpaon);
1815 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
1816 pModal->switchSettling);
1817 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
1818 pModal->adcDesiredSize);
1820 if (!AR_SREV_9280_10_OR_LATER(ah))
1821 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
1822 AR_PHY_DESIRED_SZ_PGA,
1823 pModal->pgaDesiredSize);
1825 REG_WRITE(ah, AR_PHY_RF_CTL4,
1826 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
1827 | SM(pModal->txEndToXpaOff,
1828 AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
1829 | SM(pModal->txFrameToXpaOn,
1830 AR_PHY_RF_CTL4_FRAME_XPAA_ON)
1831 | SM(pModal->txFrameToXpaOn,
1832 AR_PHY_RF_CTL4_FRAME_XPAB_ON));
1834 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
1835 pModal->txEndToRxOn);
1837 if (AR_SREV_9280_10_OR_LATER(ah)) {
1838 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
1839 pModal->thresh62);
1840 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
1841 AR_PHY_EXT_CCA0_THRESH62,
1842 pModal->thresh62);
1843 } else {
1844 REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
1845 pModal->thresh62);
1846 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
1847 AR_PHY_EXT_CCA_THRESH62,
1848 pModal->thresh62);
1851 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
1852 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
1853 AR_PHY_TX_END_DATA_START,
1854 pModal->txFrameToDataStart);
1855 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
1856 pModal->txFrameToPaOn);
1859 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
1860 if (IS_CHAN_HT40(chan))
1861 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1862 AR_PHY_SETTLING_SWITCH,
1863 pModal->swSettleHt40);
1866 if (AR_SREV_9280_20_OR_LATER(ah) &&
1867 AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1868 REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
1869 AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
1870 pModal->miscBits);
1873 if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
1874 if (IS_CHAN_2GHZ(chan))
1875 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
1876 eep->baseEepHeader.dacLpMode);
1877 else if (eep->baseEepHeader.dacHiPwrMode_5G)
1878 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
1879 else
1880 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
1881 eep->baseEepHeader.dacLpMode);
1883 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
1884 pModal->miscBits >> 2);
1886 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
1887 AR_PHY_TX_DESIRED_SCALE_CCK,
1888 eep->baseEepHeader.desiredScaleCCK);
1892 static void ath9k_hw_def_set_addac(struct ath_hw *ah,
1893 struct ath9k_channel *chan)
1895 #define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
1896 struct modal_eep_header *pModal;
1897 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1898 u8 biaslevel;
1900 if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
1901 return;
1903 if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
1904 return;
1906 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
1908 if (pModal->xpaBiasLvl != 0xff) {
1909 biaslevel = pModal->xpaBiasLvl;
1910 } else {
1911 u16 resetFreqBin, freqBin, freqCount = 0;
1912 struct chan_centers centers;
1914 ath9k_hw_get_channel_centers(ah, chan, &centers);
1916 resetFreqBin = FREQ2FBIN(centers.synth_center,
1917 IS_CHAN_2GHZ(chan));
1918 freqBin = XPA_LVL_FREQ(0) & 0xff;
1919 biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
1921 freqCount++;
1923 while (freqCount < 3) {
1924 if (XPA_LVL_FREQ(freqCount) == 0x0)
1925 break;
1927 freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
1928 if (resetFreqBin >= freqBin)
1929 biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
1930 else
1931 break;
1932 freqCount++;
1936 if (IS_CHAN_2GHZ(chan)) {
1937 INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
1938 7, 1) & (~0x18)) | biaslevel << 3;
1939 } else {
1940 INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
1941 6, 1) & (~0xc0)) | biaslevel << 6;
1943 #undef XPA_LVL_FREQ
1946 static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
1947 struct ath9k_channel *chan,
1948 struct cal_data_per_freq *pRawDataSet,
1949 u8 *bChans, u16 availPiers,
1950 u16 tPdGainOverlap, int16_t *pMinCalPower,
1951 u16 *pPdGainBoundaries, u8 *pPDADCValues,
1952 u16 numXpdGains)
1954 int i, j, k;
1955 int16_t ss;
1956 u16 idxL = 0, idxR = 0, numPiers;
1957 static u8 vpdTableL[AR5416_NUM_PD_GAINS]
1958 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
1959 static u8 vpdTableR[AR5416_NUM_PD_GAINS]
1960 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
1961 static u8 vpdTableI[AR5416_NUM_PD_GAINS]
1962 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
1964 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
1965 u8 minPwrT4[AR5416_NUM_PD_GAINS];
1966 u8 maxPwrT4[AR5416_NUM_PD_GAINS];
1967 int16_t vpdStep;
1968 int16_t tmpVal;
1969 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
1970 bool match;
1971 int16_t minDelta = 0;
1972 struct chan_centers centers;
1974 ath9k_hw_get_channel_centers(ah, chan, &centers);
1976 for (numPiers = 0; numPiers < availPiers; numPiers++) {
1977 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
1978 break;
1981 match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
1982 IS_CHAN_2GHZ(chan)),
1983 bChans, numPiers, &idxL, &idxR);
1985 if (match) {
1986 for (i = 0; i < numXpdGains; i++) {
1987 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
1988 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
1989 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
1990 pRawDataSet[idxL].pwrPdg[i],
1991 pRawDataSet[idxL].vpdPdg[i],
1992 AR5416_PD_GAIN_ICEPTS,
1993 vpdTableI[i]);
1995 } else {
1996 for (i = 0; i < numXpdGains; i++) {
1997 pVpdL = pRawDataSet[idxL].vpdPdg[i];
1998 pPwrL = pRawDataSet[idxL].pwrPdg[i];
1999 pVpdR = pRawDataSet[idxR].vpdPdg[i];
2000 pPwrR = pRawDataSet[idxR].pwrPdg[i];
2002 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
2004 maxPwrT4[i] =
2005 min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
2006 pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
2009 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
2010 pPwrL, pVpdL,
2011 AR5416_PD_GAIN_ICEPTS,
2012 vpdTableL[i]);
2013 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
2014 pPwrR, pVpdR,
2015 AR5416_PD_GAIN_ICEPTS,
2016 vpdTableR[i]);
2018 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
2019 vpdTableI[i][j] =
2020 (u8)(ath9k_hw_interpolate((u16)
2021 FREQ2FBIN(centers.
2022 synth_center,
2023 IS_CHAN_2GHZ
2024 (chan)),
2025 bChans[idxL], bChans[idxR],
2026 vpdTableL[i][j], vpdTableR[i][j]));
2031 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
2033 k = 0;
2035 for (i = 0; i < numXpdGains; i++) {
2036 if (i == (numXpdGains - 1))
2037 pPdGainBoundaries[i] =
2038 (u16)(maxPwrT4[i] / 2);
2039 else
2040 pPdGainBoundaries[i] =
2041 (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
2043 pPdGainBoundaries[i] =
2044 min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
2046 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
2047 minDelta = pPdGainBoundaries[0] - 23;
2048 pPdGainBoundaries[0] = 23;
2049 } else {
2050 minDelta = 0;
2053 if (i == 0) {
2054 if (AR_SREV_9280_10_OR_LATER(ah))
2055 ss = (int16_t)(0 - (minPwrT4[i] / 2));
2056 else
2057 ss = 0;
2058 } else {
2059 ss = (int16_t)((pPdGainBoundaries[i - 1] -
2060 (minPwrT4[i] / 2)) -
2061 tPdGainOverlap + 1 + minDelta);
2063 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
2064 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
2066 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
2067 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
2068 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
2069 ss++;
2072 sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
2073 tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
2074 (minPwrT4[i] / 2));
2075 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
2076 tgtIndex : sizeCurrVpdTable;
2078 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
2079 pPDADCValues[k++] = vpdTableI[i][ss++];
2082 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
2083 vpdTableI[i][sizeCurrVpdTable - 2]);
2084 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
2086 if (tgtIndex > maxIndex) {
2087 while ((ss <= tgtIndex) &&
2088 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
2089 tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
2090 (ss - maxIndex + 1) * vpdStep));
2091 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
2092 255 : tmpVal);
2093 ss++;
2098 while (i < AR5416_PD_GAINS_IN_MASK) {
2099 pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
2100 i++;
2103 while (k < AR5416_NUM_PDADC_VALUES) {
2104 pPDADCValues[k] = pPDADCValues[k - 1];
2105 k++;
2108 return;
2111 static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
2112 struct ath9k_channel *chan,
2113 int16_t *pTxPowerIndexOffset)
2115 #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
2116 #define SM_PDGAIN_B(x, y) \
2117 SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
2119 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2120 struct cal_data_per_freq *pRawDataset;
2121 u8 *pCalBChans = NULL;
2122 u16 pdGainOverlap_t2;
2123 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
2124 u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
2125 u16 numPiers, i, j;
2126 int16_t tMinCalPower;
2127 u16 numXpdGain, xpdMask;
2128 u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
2129 u32 reg32, regOffset, regChainOffset;
2130 int16_t modalIdx;
2132 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
2133 xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
2135 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2136 AR5416_EEP_MINOR_VER_2) {
2137 pdGainOverlap_t2 =
2138 pEepData->modalHeader[modalIdx].pdGainOverlap;
2139 } else {
2140 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
2141 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
2144 if (IS_CHAN_2GHZ(chan)) {
2145 pCalBChans = pEepData->calFreqPier2G;
2146 numPiers = AR5416_NUM_2G_CAL_PIERS;
2147 } else {
2148 pCalBChans = pEepData->calFreqPier5G;
2149 numPiers = AR5416_NUM_5G_CAL_PIERS;
2152 if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
2153 pRawDataset = pEepData->calPierData2G[0];
2154 ah->initPDADC = ((struct calDataPerFreqOpLoop *)
2155 pRawDataset)->vpdPdg[0][0];
2158 numXpdGain = 0;
2160 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
2161 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
2162 if (numXpdGain >= AR5416_NUM_PD_GAINS)
2163 break;
2164 xpdGainValues[numXpdGain] =
2165 (u16)(AR5416_PD_GAINS_IN_MASK - i);
2166 numXpdGain++;
2170 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
2171 (numXpdGain - 1) & 0x3);
2172 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
2173 xpdGainValues[0]);
2174 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
2175 xpdGainValues[1]);
2176 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
2177 xpdGainValues[2]);
2179 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
2180 if (AR_SREV_5416_20_OR_LATER(ah) &&
2181 (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
2182 (i != 0)) {
2183 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
2184 } else
2185 regChainOffset = i * 0x1000;
2187 if (pEepData->baseEepHeader.txMask & (1 << i)) {
2188 if (IS_CHAN_2GHZ(chan))
2189 pRawDataset = pEepData->calPierData2G[i];
2190 else
2191 pRawDataset = pEepData->calPierData5G[i];
2194 if (OLC_FOR_AR9280_20_LATER) {
2195 u8 pcdacIdx;
2196 u8 txPower;
2198 ath9k_get_txgain_index(ah, chan,
2199 (struct calDataPerFreqOpLoop *)pRawDataset,
2200 pCalBChans, numPiers, &txPower, &pcdacIdx);
2201 ath9k_olc_get_pdadcs(ah, pcdacIdx,
2202 txPower/2, pdadcValues);
2203 } else {
2204 ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
2205 chan, pRawDataset,
2206 pCalBChans, numPiers,
2207 pdGainOverlap_t2,
2208 &tMinCalPower,
2209 gainBoundaries,
2210 pdadcValues,
2211 numXpdGain);
2214 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
2215 if (OLC_FOR_AR9280_20_LATER) {
2216 REG_WRITE(ah,
2217 AR_PHY_TPCRG5 + regChainOffset,
2218 SM(0x6,
2219 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
2220 SM_PD_GAIN(1) | SM_PD_GAIN(2) |
2221 SM_PD_GAIN(3) | SM_PD_GAIN(4));
2222 } else {
2223 REG_WRITE(ah,
2224 AR_PHY_TPCRG5 + regChainOffset,
2225 SM(pdGainOverlap_t2,
2226 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
2227 SM_PDGAIN_B(0, 1) |
2228 SM_PDGAIN_B(1, 2) |
2229 SM_PDGAIN_B(2, 3) |
2230 SM_PDGAIN_B(3, 4));
2234 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
2235 for (j = 0; j < 32; j++) {
2236 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
2237 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
2238 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
2239 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
2240 REG_WRITE(ah, regOffset, reg32);
2242 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2243 "PDADC (%d,%4x): %4.4x %8.8x\n",
2244 i, regChainOffset, regOffset,
2245 reg32);
2246 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2247 "PDADC: Chain %d | PDADC %3d "
2248 "Value %3d | PDADC %3d Value %3d | "
2249 "PDADC %3d Value %3d | PDADC %3d "
2250 "Value %3d |\n",
2251 i, 4 * j, pdadcValues[4 * j],
2252 4 * j + 1, pdadcValues[4 * j + 1],
2253 4 * j + 2, pdadcValues[4 * j + 2],
2254 4 * j + 3,
2255 pdadcValues[4 * j + 3]);
2257 regOffset += 4;
2262 *pTxPowerIndexOffset = 0;
2263 #undef SM_PD_GAIN
2264 #undef SM_PDGAIN_B
2267 static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
2268 struct ath9k_channel *chan,
2269 int16_t *ratesArray,
2270 u16 cfgCtl,
2271 u16 AntennaReduction,
2272 u16 twiceMaxRegulatoryPower,
2273 u16 powerLimit)
2275 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
2276 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
2278 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2279 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
2280 static const u16 tpScaleReductionTable[5] =
2281 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
2283 int i;
2284 int16_t twiceLargestAntenna;
2285 struct cal_ctl_data *rep;
2286 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
2287 0, { 0, 0, 0, 0}
2289 struct cal_target_power_leg targetPowerOfdmExt = {
2290 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
2291 0, { 0, 0, 0, 0 }
2293 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
2294 0, {0, 0, 0, 0}
2296 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
2297 u16 ctlModesFor11a[] =
2298 { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
2299 u16 ctlModesFor11g[] =
2300 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
2301 CTL_2GHT40
2303 u16 numCtlModes, *pCtlMode, ctlMode, freq;
2304 struct chan_centers centers;
2305 int tx_chainmask;
2306 u16 twiceMinEdgePower;
2308 tx_chainmask = ah->txchainmask;
2310 ath9k_hw_get_channel_centers(ah, chan, &centers);
2312 twiceLargestAntenna = max(
2313 pEepData->modalHeader
2314 [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
2315 pEepData->modalHeader
2316 [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
2318 twiceLargestAntenna = max((u8)twiceLargestAntenna,
2319 pEepData->modalHeader
2320 [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
2322 twiceLargestAntenna = (int16_t)min(AntennaReduction -
2323 twiceLargestAntenna, 0);
2325 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
2327 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
2328 maxRegAllowedPower -=
2329 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
2332 scaledPower = min(powerLimit, maxRegAllowedPower);
2334 switch (ar5416_get_ntxchains(tx_chainmask)) {
2335 case 1:
2336 break;
2337 case 2:
2338 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
2339 break;
2340 case 3:
2341 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
2342 break;
2345 scaledPower = max((u16)0, scaledPower);
2347 if (IS_CHAN_2GHZ(chan)) {
2348 numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
2349 SUB_NUM_CTL_MODES_AT_2G_40;
2350 pCtlMode = ctlModesFor11g;
2352 ath9k_hw_get_legacy_target_powers(ah, chan,
2353 pEepData->calTargetPowerCck,
2354 AR5416_NUM_2G_CCK_TARGET_POWERS,
2355 &targetPowerCck, 4, false);
2356 ath9k_hw_get_legacy_target_powers(ah, chan,
2357 pEepData->calTargetPower2G,
2358 AR5416_NUM_2G_20_TARGET_POWERS,
2359 &targetPowerOfdm, 4, false);
2360 ath9k_hw_get_target_powers(ah, chan,
2361 pEepData->calTargetPower2GHT20,
2362 AR5416_NUM_2G_20_TARGET_POWERS,
2363 &targetPowerHt20, 8, false);
2365 if (IS_CHAN_HT40(chan)) {
2366 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
2367 ath9k_hw_get_target_powers(ah, chan,
2368 pEepData->calTargetPower2GHT40,
2369 AR5416_NUM_2G_40_TARGET_POWERS,
2370 &targetPowerHt40, 8, true);
2371 ath9k_hw_get_legacy_target_powers(ah, chan,
2372 pEepData->calTargetPowerCck,
2373 AR5416_NUM_2G_CCK_TARGET_POWERS,
2374 &targetPowerCckExt, 4, true);
2375 ath9k_hw_get_legacy_target_powers(ah, chan,
2376 pEepData->calTargetPower2G,
2377 AR5416_NUM_2G_20_TARGET_POWERS,
2378 &targetPowerOfdmExt, 4, true);
2380 } else {
2381 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
2382 SUB_NUM_CTL_MODES_AT_5G_40;
2383 pCtlMode = ctlModesFor11a;
2385 ath9k_hw_get_legacy_target_powers(ah, chan,
2386 pEepData->calTargetPower5G,
2387 AR5416_NUM_5G_20_TARGET_POWERS,
2388 &targetPowerOfdm, 4, false);
2389 ath9k_hw_get_target_powers(ah, chan,
2390 pEepData->calTargetPower5GHT20,
2391 AR5416_NUM_5G_20_TARGET_POWERS,
2392 &targetPowerHt20, 8, false);
2394 if (IS_CHAN_HT40(chan)) {
2395 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
2396 ath9k_hw_get_target_powers(ah, chan,
2397 pEepData->calTargetPower5GHT40,
2398 AR5416_NUM_5G_40_TARGET_POWERS,
2399 &targetPowerHt40, 8, true);
2400 ath9k_hw_get_legacy_target_powers(ah, chan,
2401 pEepData->calTargetPower5G,
2402 AR5416_NUM_5G_20_TARGET_POWERS,
2403 &targetPowerOfdmExt, 4, true);
2407 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
2408 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
2409 (pCtlMode[ctlMode] == CTL_2GHT40);
2410 if (isHt40CtlMode)
2411 freq = centers.synth_center;
2412 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2413 freq = centers.ext_center;
2414 else
2415 freq = centers.ctl_center;
2417 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
2418 ah->eep_ops->get_eeprom_rev(ah) <= 2)
2419 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
2421 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2422 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2423 "EXT_ADDITIVE %d\n",
2424 ctlMode, numCtlModes, isHt40CtlMode,
2425 (pCtlMode[ctlMode] & EXT_ADDITIVE));
2427 for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
2428 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2429 " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2430 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2431 "chan %d\n",
2432 i, cfgCtl, pCtlMode[ctlMode],
2433 pEepData->ctlIndex[i], chan->channel);
2435 if ((((cfgCtl & ~CTL_MODE_M) |
2436 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2437 pEepData->ctlIndex[i]) ||
2438 (((cfgCtl & ~CTL_MODE_M) |
2439 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2440 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
2441 rep = &(pEepData->ctlData[i]);
2443 twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
2444 rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
2445 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
2447 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2448 " MATCH-EE_IDX %d: ch %d is2 %d "
2449 "2xMinEdge %d chainmask %d chains %d\n",
2450 i, freq, IS_CHAN_2GHZ(chan),
2451 twiceMinEdgePower, tx_chainmask,
2452 ar5416_get_ntxchains
2453 (tx_chainmask));
2454 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
2455 twiceMaxEdgePower = min(twiceMaxEdgePower,
2456 twiceMinEdgePower);
2457 } else {
2458 twiceMaxEdgePower = twiceMinEdgePower;
2459 break;
2464 minCtlPower = min(twiceMaxEdgePower, scaledPower);
2466 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2467 " SEL-Min ctlMode %d pCtlMode %d "
2468 "2xMaxEdge %d sP %d minCtlPwr %d\n",
2469 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
2470 scaledPower, minCtlPower);
2472 switch (pCtlMode[ctlMode]) {
2473 case CTL_11B:
2474 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
2475 targetPowerCck.tPow2x[i] =
2476 min((u16)targetPowerCck.tPow2x[i],
2477 minCtlPower);
2479 break;
2480 case CTL_11A:
2481 case CTL_11G:
2482 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
2483 targetPowerOfdm.tPow2x[i] =
2484 min((u16)targetPowerOfdm.tPow2x[i],
2485 minCtlPower);
2487 break;
2488 case CTL_5GHT20:
2489 case CTL_2GHT20:
2490 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
2491 targetPowerHt20.tPow2x[i] =
2492 min((u16)targetPowerHt20.tPow2x[i],
2493 minCtlPower);
2495 break;
2496 case CTL_11B_EXT:
2497 targetPowerCckExt.tPow2x[0] = min((u16)
2498 targetPowerCckExt.tPow2x[0],
2499 minCtlPower);
2500 break;
2501 case CTL_11A_EXT:
2502 case CTL_11G_EXT:
2503 targetPowerOfdmExt.tPow2x[0] = min((u16)
2504 targetPowerOfdmExt.tPow2x[0],
2505 minCtlPower);
2506 break;
2507 case CTL_5GHT40:
2508 case CTL_2GHT40:
2509 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
2510 targetPowerHt40.tPow2x[i] =
2511 min((u16)targetPowerHt40.tPow2x[i],
2512 minCtlPower);
2514 break;
2515 default:
2516 break;
2520 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
2521 ratesArray[rate18mb] = ratesArray[rate24mb] =
2522 targetPowerOfdm.tPow2x[0];
2523 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
2524 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
2525 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
2526 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
2528 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
2529 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
2531 if (IS_CHAN_2GHZ(chan)) {
2532 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
2533 ratesArray[rate2s] = ratesArray[rate2l] =
2534 targetPowerCck.tPow2x[1];
2535 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
2536 targetPowerCck.tPow2x[2];
2537 ratesArray[rate11s] = ratesArray[rate11l] =
2538 targetPowerCck.tPow2x[3];
2540 if (IS_CHAN_HT40(chan)) {
2541 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
2542 ratesArray[rateHt40_0 + i] =
2543 targetPowerHt40.tPow2x[i];
2545 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
2546 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
2547 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
2548 if (IS_CHAN_2GHZ(chan)) {
2549 ratesArray[rateExtCck] =
2550 targetPowerCckExt.tPow2x[0];
2555 static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
2556 struct ath9k_channel *chan,
2557 u16 cfgCtl,
2558 u8 twiceAntennaReduction,
2559 u8 twiceMaxRegulatoryPower,
2560 u8 powerLimit)
2562 #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
2563 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2564 struct modal_eep_header *pModal =
2565 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
2566 int16_t ratesArray[Ar5416RateSize];
2567 int16_t txPowerIndexOffset = 0;
2568 u8 ht40PowerIncForPdadc = 2;
2569 int i, cck_ofdm_delta = 0;
2571 memset(ratesArray, 0, sizeof(ratesArray));
2573 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2574 AR5416_EEP_MINOR_VER_2) {
2575 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
2578 ath9k_hw_set_def_power_per_rate_table(ah, chan,
2579 &ratesArray[0], cfgCtl,
2580 twiceAntennaReduction,
2581 twiceMaxRegulatoryPower,
2582 powerLimit);
2584 ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
2586 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
2587 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
2588 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
2589 ratesArray[i] = AR5416_MAX_RATE_POWER;
2592 if (AR_SREV_9280_10_OR_LATER(ah)) {
2593 for (i = 0; i < Ar5416RateSize; i++)
2594 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
2597 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
2598 ATH9K_POW_SM(ratesArray[rate18mb], 24)
2599 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
2600 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
2601 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
2602 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
2603 ATH9K_POW_SM(ratesArray[rate54mb], 24)
2604 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
2605 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
2606 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
2608 if (IS_CHAN_2GHZ(chan)) {
2609 if (OLC_FOR_AR9280_20_LATER) {
2610 cck_ofdm_delta = 2;
2611 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2612 ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
2613 | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
2614 | ATH9K_POW_SM(ratesArray[rateXr], 8)
2615 | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
2616 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2617 ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
2618 | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
2619 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
2620 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
2621 } else {
2622 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2623 ATH9K_POW_SM(ratesArray[rate2s], 24)
2624 | ATH9K_POW_SM(ratesArray[rate2l], 16)
2625 | ATH9K_POW_SM(ratesArray[rateXr], 8)
2626 | ATH9K_POW_SM(ratesArray[rate1l], 0));
2627 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2628 ATH9K_POW_SM(ratesArray[rate11s], 24)
2629 | ATH9K_POW_SM(ratesArray[rate11l], 16)
2630 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
2631 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
2635 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
2636 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
2637 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
2638 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
2639 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
2640 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
2641 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
2642 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
2643 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
2644 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
2646 if (IS_CHAN_HT40(chan)) {
2647 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
2648 ATH9K_POW_SM(ratesArray[rateHt40_3] +
2649 ht40PowerIncForPdadc, 24)
2650 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
2651 ht40PowerIncForPdadc, 16)
2652 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
2653 ht40PowerIncForPdadc, 8)
2654 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
2655 ht40PowerIncForPdadc, 0));
2656 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
2657 ATH9K_POW_SM(ratesArray[rateHt40_7] +
2658 ht40PowerIncForPdadc, 24)
2659 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
2660 ht40PowerIncForPdadc, 16)
2661 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
2662 ht40PowerIncForPdadc, 8)
2663 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
2664 ht40PowerIncForPdadc, 0));
2665 if (OLC_FOR_AR9280_20_LATER) {
2666 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2667 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
2668 | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
2669 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
2670 | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
2671 } else {
2672 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2673 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
2674 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
2675 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
2676 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
2680 REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
2681 ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
2682 | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
2684 i = rate6mb;
2686 if (IS_CHAN_HT40(chan))
2687 i = rateHt40_0;
2688 else if (IS_CHAN_HT20(chan))
2689 i = rateHt20_0;
2691 if (AR_SREV_9280_10_OR_LATER(ah))
2692 ah->regulatory.max_power_level =
2693 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
2694 else
2695 ah->regulatory.max_power_level = ratesArray[i];
2697 switch(ar5416_get_ntxchains(ah->txchainmask)) {
2698 case 1:
2699 break;
2700 case 2:
2701 ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
2702 break;
2703 case 3:
2704 ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
2705 break;
2706 default:
2707 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2708 "Invalid chainmask configuration\n");
2709 break;
2713 static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
2714 enum ieee80211_band freq_band)
2716 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
2717 struct modal_eep_header *pModal =
2718 &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
2719 struct base_eep_header *pBase = &eep->baseEepHeader;
2720 u8 num_ant_config;
2722 num_ant_config = 1;
2724 if (pBase->version >= 0x0E0D)
2725 if (pModal->useAnt1)
2726 num_ant_config += 1;
2728 return num_ant_config;
2731 static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
2732 struct ath9k_channel *chan)
2734 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
2735 struct modal_eep_header *pModal =
2736 &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
2738 return pModal->antCtrlCommon & 0xFFFF;
2741 static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
2743 #define EEP_DEF_SPURCHAN \
2744 (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
2746 u16 spur_val = AR_NO_SPUR;
2748 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2749 "Getting spur idx %d is2Ghz. %d val %x\n",
2750 i, is2GHz, ah->config.spurchans[i][is2GHz]);
2752 switch (ah->config.spurmode) {
2753 case SPUR_DISABLE:
2754 break;
2755 case SPUR_ENABLE_IOCTL:
2756 spur_val = ah->config.spurchans[i][is2GHz];
2757 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2758 "Getting spur val from new loc. %d\n", spur_val);
2759 break;
2760 case SPUR_ENABLE_EEPROM:
2761 spur_val = EEP_DEF_SPURCHAN;
2762 break;
2765 return spur_val;
2767 #undef EEP_DEF_SPURCHAN
2770 static struct eeprom_ops eep_def_ops = {
2771 .check_eeprom = ath9k_hw_def_check_eeprom,
2772 .get_eeprom = ath9k_hw_def_get_eeprom,
2773 .fill_eeprom = ath9k_hw_def_fill_eeprom,
2774 .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
2775 .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
2776 .get_num_ant_config = ath9k_hw_def_get_num_ant_config,
2777 .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg,
2778 .set_board_values = ath9k_hw_def_set_board_values,
2779 .set_addac = ath9k_hw_def_set_addac,
2780 .set_txpower = ath9k_hw_def_set_txpower,
2781 .get_spur_channel = ath9k_hw_def_get_spur_channel
2784 int ath9k_hw_eeprom_attach(struct ath_hw *ah)
2786 int status;
2788 if (AR_SREV_9285(ah)) {
2789 ah->eep_map = EEP_MAP_4KBITS;
2790 ah->eep_ops = &eep_4k_ops;
2791 } else {
2792 ah->eep_map = EEP_MAP_DEFAULT;
2793 ah->eep_ops = &eep_def_ops;
2796 if (!ah->eep_ops->fill_eeprom(ah))
2797 return -EIO;
2799 status = ah->eep_ops->check_eeprom(ah);
2801 return status;