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.
18 #include "ar9002_phy.h"
20 static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw
*ah
)
22 return ((ah
->eeprom
.map4k
.baseEepHeader
.version
>> 12) & 0xF);
25 static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw
*ah
)
27 return ((ah
->eeprom
.map4k
.baseEepHeader
.version
) & 0xFFF);
30 static bool ath9k_hw_4k_fill_eeprom(struct ath_hw
*ah
)
32 #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
33 struct ath_common
*common
= ath9k_hw_common(ah
);
34 u16
*eep_data
= (u16
*)&ah
->eeprom
.map4k
;
35 int addr
, eep_start_loc
= 0;
39 if (!ath9k_hw_use_flash(ah
)) {
40 ath_dbg(common
, ATH_DBG_EEPROM
,
41 "Reading from EEPROM, not flash\n");
44 for (addr
= 0; addr
< SIZE_EEPROM_4K
; addr
++) {
45 if (!ath9k_hw_nvram_read(common
, addr
+ eep_start_loc
, eep_data
)) {
46 ath_dbg(common
, ATH_DBG_EEPROM
,
47 "Unable to read eeprom region\n");
57 static int ath9k_hw_4k_check_eeprom(struct ath_hw
*ah
)
59 #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
60 struct ath_common
*common
= ath9k_hw_common(ah
);
61 struct ar5416_eeprom_4k
*eep
=
62 (struct ar5416_eeprom_4k
*) &ah
->eeprom
.map4k
;
63 u16
*eepdata
, temp
, magic
, magic2
;
65 bool need_swap
= false;
69 if (!ath9k_hw_use_flash(ah
)) {
70 if (!ath9k_hw_nvram_read(common
, AR5416_EEPROM_MAGIC_OFFSET
,
72 ath_err(common
, "Reading Magic # failed\n");
76 ath_dbg(common
, ATH_DBG_EEPROM
,
77 "Read Magic = 0x%04X\n", magic
);
79 if (magic
!= AR5416_EEPROM_MAGIC
) {
80 magic2
= swab16(magic
);
82 if (magic2
== AR5416_EEPROM_MAGIC
) {
84 eepdata
= (u16
*) (&ah
->eeprom
);
86 for (addr
= 0; addr
< EEPROM_4K_SIZE
; addr
++) {
87 temp
= swab16(*eepdata
);
93 "Invalid EEPROM Magic. Endianness mismatch.\n");
99 ath_dbg(common
, ATH_DBG_EEPROM
, "need_swap = %s.\n",
100 need_swap
? "True" : "False");
103 el
= swab16(ah
->eeprom
.map4k
.baseEepHeader
.length
);
105 el
= ah
->eeprom
.map4k
.baseEepHeader
.length
;
107 if (el
> sizeof(struct ar5416_eeprom_4k
))
108 el
= sizeof(struct ar5416_eeprom_4k
) / sizeof(u16
);
110 el
= el
/ sizeof(u16
);
112 eepdata
= (u16
*)(&ah
->eeprom
);
114 for (i
= 0; i
< el
; i
++)
121 ath_dbg(common
, ATH_DBG_EEPROM
,
122 "EEPROM Endianness is not native.. Changing\n");
124 word
= swab16(eep
->baseEepHeader
.length
);
125 eep
->baseEepHeader
.length
= word
;
127 word
= swab16(eep
->baseEepHeader
.checksum
);
128 eep
->baseEepHeader
.checksum
= word
;
130 word
= swab16(eep
->baseEepHeader
.version
);
131 eep
->baseEepHeader
.version
= word
;
133 word
= swab16(eep
->baseEepHeader
.regDmn
[0]);
134 eep
->baseEepHeader
.regDmn
[0] = word
;
136 word
= swab16(eep
->baseEepHeader
.regDmn
[1]);
137 eep
->baseEepHeader
.regDmn
[1] = word
;
139 word
= swab16(eep
->baseEepHeader
.rfSilent
);
140 eep
->baseEepHeader
.rfSilent
= word
;
142 word
= swab16(eep
->baseEepHeader
.blueToothOptions
);
143 eep
->baseEepHeader
.blueToothOptions
= word
;
145 word
= swab16(eep
->baseEepHeader
.deviceCap
);
146 eep
->baseEepHeader
.deviceCap
= word
;
148 integer
= swab32(eep
->modalHeader
.antCtrlCommon
);
149 eep
->modalHeader
.antCtrlCommon
= integer
;
151 for (i
= 0; i
< AR5416_EEP4K_MAX_CHAINS
; i
++) {
152 integer
= swab32(eep
->modalHeader
.antCtrlChain
[i
]);
153 eep
->modalHeader
.antCtrlChain
[i
] = integer
;
156 for (i
= 0; i
< AR_EEPROM_MODAL_SPURS
; i
++) {
157 word
= swab16(eep
->modalHeader
.spurChans
[i
].spurChan
);
158 eep
->modalHeader
.spurChans
[i
].spurChan
= word
;
162 if (sum
!= 0xffff || ah
->eep_ops
->get_eeprom_ver(ah
) != AR5416_EEP_VER
||
163 ah
->eep_ops
->get_eeprom_rev(ah
) < AR5416_EEP_NO_BACK_VER
) {
164 ath_err(common
, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
165 sum
, ah
->eep_ops
->get_eeprom_ver(ah
));
170 #undef EEPROM_4K_SIZE
173 static u32
ath9k_hw_4k_get_eeprom(struct ath_hw
*ah
,
174 enum eeprom_param param
)
176 struct ar5416_eeprom_4k
*eep
= &ah
->eeprom
.map4k
;
177 struct modal_eep_4k_header
*pModal
= &eep
->modalHeader
;
178 struct base_eep_header_4k
*pBase
= &eep
->baseEepHeader
;
181 ver_minor
= pBase
->version
& AR5416_EEP_VER_MINOR_MASK
;
185 return pModal
->noiseFloorThreshCh
[0];
187 return pBase
->macAddr
[0] << 8 | pBase
->macAddr
[1];
189 return pBase
->macAddr
[2] << 8 | pBase
->macAddr
[3];
191 return pBase
->macAddr
[4] << 8 | pBase
->macAddr
[5];
193 return pBase
->regDmn
[0];
195 return pBase
->regDmn
[1];
197 return pBase
->deviceCap
;
199 return pBase
->opCapFlags
;
201 return pBase
->rfSilent
;
205 return pModal
->db1_1
;
209 return pBase
->txMask
;
211 return pBase
->rxMask
;
214 case EEP_PWR_TABLE_OFFSET
:
215 return AR5416_PWR_TABLE_OFFSET_DB
;
217 return pModal
->version
;
218 case EEP_ANT_DIV_CTL1
:
219 return pModal
->antdiv_ctl1
;
220 case EEP_TXGAIN_TYPE
:
221 if (ver_minor
>= AR5416_EEP_MINOR_VER_19
)
222 return pBase
->txGainType
;
224 return AR5416_EEP_TXGAIN_ORIGINAL
;
230 static void ath9k_hw_set_4k_power_cal_table(struct ath_hw
*ah
,
231 struct ath9k_channel
*chan
,
232 int16_t *pTxPowerIndexOffset
)
234 struct ath_common
*common
= ath9k_hw_common(ah
);
235 struct ar5416_eeprom_4k
*pEepData
= &ah
->eeprom
.map4k
;
236 struct cal_data_per_freq_4k
*pRawDataset
;
237 u8
*pCalBChans
= NULL
;
238 u16 pdGainOverlap_t2
;
239 static u8 pdadcValues
[AR5416_NUM_PDADC_VALUES
];
240 u16 gainBoundaries
[AR5416_PD_GAINS_IN_MASK
];
242 u16 numXpdGain
, xpdMask
;
243 u16 xpdGainValues
[AR5416_EEP4K_NUM_PD_GAINS
] = { 0, 0 };
244 u32 reg32
, regOffset
, regChainOffset
;
246 xpdMask
= pEepData
->modalHeader
.xpdGain
;
248 if ((pEepData
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
249 AR5416_EEP_MINOR_VER_2
) {
251 pEepData
->modalHeader
.pdGainOverlap
;
253 pdGainOverlap_t2
= (u16
)(MS(REG_READ(ah
, AR_PHY_TPCRG5
),
254 AR_PHY_TPCRG5_PD_GAIN_OVERLAP
));
257 pCalBChans
= pEepData
->calFreqPier2G
;
258 numPiers
= AR5416_EEP4K_NUM_2G_CAL_PIERS
;
262 for (i
= 1; i
<= AR5416_PD_GAINS_IN_MASK
; i
++) {
263 if ((xpdMask
>> (AR5416_PD_GAINS_IN_MASK
- i
)) & 1) {
264 if (numXpdGain
>= AR5416_EEP4K_NUM_PD_GAINS
)
266 xpdGainValues
[numXpdGain
] =
267 (u16
)(AR5416_PD_GAINS_IN_MASK
- i
);
272 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_NUM_PD_GAIN
,
273 (numXpdGain
- 1) & 0x3);
274 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_1
,
276 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_2
,
278 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_3
, 0);
280 for (i
= 0; i
< AR5416_EEP4K_MAX_CHAINS
; i
++) {
281 if (AR_SREV_5416_20_OR_LATER(ah
) &&
282 (ah
->rxchainmask
== 5 || ah
->txchainmask
== 5) &&
284 regChainOffset
= (i
== 1) ? 0x2000 : 0x1000;
286 regChainOffset
= i
* 0x1000;
288 if (pEepData
->baseEepHeader
.txMask
& (1 << i
)) {
289 pRawDataset
= pEepData
->calPierData2G
[i
];
291 ath9k_hw_get_gain_boundaries_pdadcs(ah
, chan
,
292 pRawDataset
, pCalBChans
,
293 numPiers
, pdGainOverlap_t2
,
295 pdadcValues
, numXpdGain
);
297 ENABLE_REGWRITE_BUFFER(ah
);
299 if ((i
== 0) || AR_SREV_5416_20_OR_LATER(ah
)) {
300 REG_WRITE(ah
, AR_PHY_TPCRG5
+ regChainOffset
,
302 AR_PHY_TPCRG5_PD_GAIN_OVERLAP
)
303 | SM(gainBoundaries
[0],
304 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1
)
305 | SM(gainBoundaries
[1],
306 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2
)
307 | SM(gainBoundaries
[2],
308 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3
)
309 | SM(gainBoundaries
[3],
310 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4
));
313 regOffset
= AR_PHY_BASE
+ (672 << 2) + regChainOffset
;
314 for (j
= 0; j
< 32; j
++) {
315 reg32
= ((pdadcValues
[4 * j
+ 0] & 0xFF) << 0) |
316 ((pdadcValues
[4 * j
+ 1] & 0xFF) << 8) |
317 ((pdadcValues
[4 * j
+ 2] & 0xFF) << 16)|
318 ((pdadcValues
[4 * j
+ 3] & 0xFF) << 24);
319 REG_WRITE(ah
, regOffset
, reg32
);
321 ath_dbg(common
, ATH_DBG_EEPROM
,
322 "PDADC (%d,%4x): %4.4x %8.8x\n",
323 i
, regChainOffset
, regOffset
,
325 ath_dbg(common
, ATH_DBG_EEPROM
,
327 "PDADC %3d Value %3d | "
328 "PDADC %3d Value %3d | "
329 "PDADC %3d Value %3d | "
330 "PDADC %3d Value %3d |\n",
331 i
, 4 * j
, pdadcValues
[4 * j
],
332 4 * j
+ 1, pdadcValues
[4 * j
+ 1],
333 4 * j
+ 2, pdadcValues
[4 * j
+ 2],
334 4 * j
+ 3, pdadcValues
[4 * j
+ 3]);
339 REGWRITE_BUFFER_FLUSH(ah
);
343 *pTxPowerIndexOffset
= 0;
346 static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw
*ah
,
347 struct ath9k_channel
*chan
,
350 u16 AntennaReduction
,
351 u16 twiceMaxRegulatoryPower
,
354 #define CMP_TEST_GRP \
355 (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) == \
356 pEepData->ctlIndex[i]) \
357 || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
358 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
360 struct ath_regulatory
*regulatory
= ath9k_hw_regulatory(ah
);
362 int16_t twiceLargestAntenna
;
363 u16 twiceMinEdgePower
;
364 u16 twiceMaxEdgePower
= MAX_RATE_POWER
;
365 u16 scaledPower
= 0, minCtlPower
, maxRegAllowedPower
;
369 struct chan_centers centers
;
370 struct cal_ctl_data_4k
*rep
;
371 struct ar5416_eeprom_4k
*pEepData
= &ah
->eeprom
.map4k
;
372 static const u16 tpScaleReductionTable
[5] =
373 { 0, 3, 6, 9, MAX_RATE_POWER
};
374 struct cal_target_power_leg targetPowerOfdm
, targetPowerCck
= {
377 struct cal_target_power_leg targetPowerOfdmExt
= {
378 0, { 0, 0, 0, 0} }, targetPowerCckExt
= {
381 struct cal_target_power_ht targetPowerHt20
, targetPowerHt40
= {
384 static const u16 ctlModesFor11g
[] = {
385 CTL_11B
, CTL_11G
, CTL_2GHT20
,
386 CTL_11B_EXT
, CTL_11G_EXT
, CTL_2GHT40
389 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
391 twiceLargestAntenna
= pEepData
->modalHeader
.antennaGainCh
[0];
392 twiceLargestAntenna
= (int16_t)min(AntennaReduction
-
393 twiceLargestAntenna
, 0);
395 maxRegAllowedPower
= twiceMaxRegulatoryPower
+ twiceLargestAntenna
;
396 if (regulatory
->tp_scale
!= ATH9K_TP_SCALE_MAX
) {
397 maxRegAllowedPower
-=
398 (tpScaleReductionTable
[(regulatory
->tp_scale
)] * 2);
401 scaledPower
= min(powerLimit
, maxRegAllowedPower
);
402 scaledPower
= max((u16
)0, scaledPower
);
404 numCtlModes
= ARRAY_SIZE(ctlModesFor11g
) - SUB_NUM_CTL_MODES_AT_2G_40
;
405 pCtlMode
= ctlModesFor11g
;
407 ath9k_hw_get_legacy_target_powers(ah
, chan
,
408 pEepData
->calTargetPowerCck
,
409 AR5416_NUM_2G_CCK_TARGET_POWERS
,
410 &targetPowerCck
, 4, false);
411 ath9k_hw_get_legacy_target_powers(ah
, chan
,
412 pEepData
->calTargetPower2G
,
413 AR5416_NUM_2G_20_TARGET_POWERS
,
414 &targetPowerOfdm
, 4, false);
415 ath9k_hw_get_target_powers(ah
, chan
,
416 pEepData
->calTargetPower2GHT20
,
417 AR5416_NUM_2G_20_TARGET_POWERS
,
418 &targetPowerHt20
, 8, false);
420 if (IS_CHAN_HT40(chan
)) {
421 numCtlModes
= ARRAY_SIZE(ctlModesFor11g
);
422 ath9k_hw_get_target_powers(ah
, chan
,
423 pEepData
->calTargetPower2GHT40
,
424 AR5416_NUM_2G_40_TARGET_POWERS
,
425 &targetPowerHt40
, 8, true);
426 ath9k_hw_get_legacy_target_powers(ah
, chan
,
427 pEepData
->calTargetPowerCck
,
428 AR5416_NUM_2G_CCK_TARGET_POWERS
,
429 &targetPowerCckExt
, 4, true);
430 ath9k_hw_get_legacy_target_powers(ah
, chan
,
431 pEepData
->calTargetPower2G
,
432 AR5416_NUM_2G_20_TARGET_POWERS
,
433 &targetPowerOfdmExt
, 4, true);
436 for (ctlMode
= 0; ctlMode
< numCtlModes
; ctlMode
++) {
437 bool isHt40CtlMode
= (pCtlMode
[ctlMode
] == CTL_5GHT40
) ||
438 (pCtlMode
[ctlMode
] == CTL_2GHT40
);
441 freq
= centers
.synth_center
;
442 else if (pCtlMode
[ctlMode
] & EXT_ADDITIVE
)
443 freq
= centers
.ext_center
;
445 freq
= centers
.ctl_center
;
447 if (ah
->eep_ops
->get_eeprom_ver(ah
) == 14 &&
448 ah
->eep_ops
->get_eeprom_rev(ah
) <= 2)
449 twiceMaxEdgePower
= MAX_RATE_POWER
;
451 for (i
= 0; (i
< AR5416_EEP4K_NUM_CTLS
) &&
452 pEepData
->ctlIndex
[i
]; i
++) {
455 rep
= &(pEepData
->ctlData
[i
]);
457 twiceMinEdgePower
= ath9k_hw_get_max_edge_power(
460 ar5416_get_ntxchains(ah
->txchainmask
) - 1],
462 AR5416_EEP4K_NUM_BAND_EDGES
);
464 if ((cfgCtl
& ~CTL_MODE_M
) == SD_NO_CTL
) {
466 min(twiceMaxEdgePower
,
469 twiceMaxEdgePower
= twiceMinEdgePower
;
475 minCtlPower
= (u8
)min(twiceMaxEdgePower
, scaledPower
);
477 switch (pCtlMode
[ctlMode
]) {
479 for (i
= 0; i
< ARRAY_SIZE(targetPowerCck
.tPow2x
); i
++) {
480 targetPowerCck
.tPow2x
[i
] =
481 min((u16
)targetPowerCck
.tPow2x
[i
],
486 for (i
= 0; i
< ARRAY_SIZE(targetPowerOfdm
.tPow2x
); i
++) {
487 targetPowerOfdm
.tPow2x
[i
] =
488 min((u16
)targetPowerOfdm
.tPow2x
[i
],
493 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt20
.tPow2x
); i
++) {
494 targetPowerHt20
.tPow2x
[i
] =
495 min((u16
)targetPowerHt20
.tPow2x
[i
],
500 targetPowerCckExt
.tPow2x
[0] =
501 min((u16
)targetPowerCckExt
.tPow2x
[0],
505 targetPowerOfdmExt
.tPow2x
[0] =
506 min((u16
)targetPowerOfdmExt
.tPow2x
[0],
510 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt40
.tPow2x
); i
++) {
511 targetPowerHt40
.tPow2x
[i
] =
512 min((u16
)targetPowerHt40
.tPow2x
[i
],
521 ratesArray
[rate6mb
] =
522 ratesArray
[rate9mb
] =
523 ratesArray
[rate12mb
] =
524 ratesArray
[rate18mb
] =
525 ratesArray
[rate24mb
] =
526 targetPowerOfdm
.tPow2x
[0];
528 ratesArray
[rate36mb
] = targetPowerOfdm
.tPow2x
[1];
529 ratesArray
[rate48mb
] = targetPowerOfdm
.tPow2x
[2];
530 ratesArray
[rate54mb
] = targetPowerOfdm
.tPow2x
[3];
531 ratesArray
[rateXr
] = targetPowerOfdm
.tPow2x
[0];
533 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt20
.tPow2x
); i
++)
534 ratesArray
[rateHt20_0
+ i
] = targetPowerHt20
.tPow2x
[i
];
536 ratesArray
[rate1l
] = targetPowerCck
.tPow2x
[0];
537 ratesArray
[rate2s
] = ratesArray
[rate2l
] = targetPowerCck
.tPow2x
[1];
538 ratesArray
[rate5_5s
] = ratesArray
[rate5_5l
] = targetPowerCck
.tPow2x
[2];
539 ratesArray
[rate11s
] = ratesArray
[rate11l
] = targetPowerCck
.tPow2x
[3];
541 if (IS_CHAN_HT40(chan
)) {
542 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt40
.tPow2x
); i
++) {
543 ratesArray
[rateHt40_0
+ i
] =
544 targetPowerHt40
.tPow2x
[i
];
546 ratesArray
[rateDupOfdm
] = targetPowerHt40
.tPow2x
[0];
547 ratesArray
[rateDupCck
] = targetPowerHt40
.tPow2x
[0];
548 ratesArray
[rateExtOfdm
] = targetPowerOfdmExt
.tPow2x
[0];
549 ratesArray
[rateExtCck
] = targetPowerCckExt
.tPow2x
[0];
555 static void ath9k_hw_4k_set_txpower(struct ath_hw
*ah
,
556 struct ath9k_channel
*chan
,
558 u8 twiceAntennaReduction
,
559 u8 twiceMaxRegulatoryPower
,
560 u8 powerLimit
, bool test
)
562 struct ath_regulatory
*regulatory
= ath9k_hw_regulatory(ah
);
563 struct ar5416_eeprom_4k
*pEepData
= &ah
->eeprom
.map4k
;
564 struct modal_eep_4k_header
*pModal
= &pEepData
->modalHeader
;
565 int16_t ratesArray
[Ar5416RateSize
];
566 int16_t txPowerIndexOffset
= 0;
567 u8 ht40PowerIncForPdadc
= 2;
570 memset(ratesArray
, 0, sizeof(ratesArray
));
572 if ((pEepData
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
573 AR5416_EEP_MINOR_VER_2
) {
574 ht40PowerIncForPdadc
= pModal
->ht40PowerIncForPdadc
;
577 ath9k_hw_set_4k_power_per_rate_table(ah
, chan
,
578 &ratesArray
[0], cfgCtl
,
579 twiceAntennaReduction
,
580 twiceMaxRegulatoryPower
,
583 ath9k_hw_set_4k_power_cal_table(ah
, chan
, &txPowerIndexOffset
);
585 regulatory
->max_power_level
= 0;
586 for (i
= 0; i
< ARRAY_SIZE(ratesArray
); i
++) {
587 ratesArray
[i
] = (int16_t)(txPowerIndexOffset
+ ratesArray
[i
]);
588 if (ratesArray
[i
] > MAX_RATE_POWER
)
589 ratesArray
[i
] = MAX_RATE_POWER
;
591 if (ratesArray
[i
] > regulatory
->max_power_level
)
592 regulatory
->max_power_level
= ratesArray
[i
];
598 /* Update regulatory */
600 if (IS_CHAN_HT40(chan
))
602 else if (IS_CHAN_HT20(chan
))
605 regulatory
->max_power_level
= ratesArray
[i
];
607 if (AR_SREV_9280_20_OR_LATER(ah
)) {
608 for (i
= 0; i
< Ar5416RateSize
; i
++)
609 ratesArray
[i
] -= AR5416_PWR_TABLE_OFFSET_DB
* 2;
612 ENABLE_REGWRITE_BUFFER(ah
);
614 /* OFDM power per rate */
615 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE1
,
616 ATH9K_POW_SM(ratesArray
[rate18mb
], 24)
617 | ATH9K_POW_SM(ratesArray
[rate12mb
], 16)
618 | ATH9K_POW_SM(ratesArray
[rate9mb
], 8)
619 | ATH9K_POW_SM(ratesArray
[rate6mb
], 0));
620 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE2
,
621 ATH9K_POW_SM(ratesArray
[rate54mb
], 24)
622 | ATH9K_POW_SM(ratesArray
[rate48mb
], 16)
623 | ATH9K_POW_SM(ratesArray
[rate36mb
], 8)
624 | ATH9K_POW_SM(ratesArray
[rate24mb
], 0));
626 /* CCK power per rate */
627 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE3
,
628 ATH9K_POW_SM(ratesArray
[rate2s
], 24)
629 | ATH9K_POW_SM(ratesArray
[rate2l
], 16)
630 | ATH9K_POW_SM(ratesArray
[rateXr
], 8)
631 | ATH9K_POW_SM(ratesArray
[rate1l
], 0));
632 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE4
,
633 ATH9K_POW_SM(ratesArray
[rate11s
], 24)
634 | ATH9K_POW_SM(ratesArray
[rate11l
], 16)
635 | ATH9K_POW_SM(ratesArray
[rate5_5s
], 8)
636 | ATH9K_POW_SM(ratesArray
[rate5_5l
], 0));
638 /* HT20 power per rate */
639 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE5
,
640 ATH9K_POW_SM(ratesArray
[rateHt20_3
], 24)
641 | ATH9K_POW_SM(ratesArray
[rateHt20_2
], 16)
642 | ATH9K_POW_SM(ratesArray
[rateHt20_1
], 8)
643 | ATH9K_POW_SM(ratesArray
[rateHt20_0
], 0));
644 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE6
,
645 ATH9K_POW_SM(ratesArray
[rateHt20_7
], 24)
646 | ATH9K_POW_SM(ratesArray
[rateHt20_6
], 16)
647 | ATH9K_POW_SM(ratesArray
[rateHt20_5
], 8)
648 | ATH9K_POW_SM(ratesArray
[rateHt20_4
], 0));
650 /* HT40 power per rate */
651 if (IS_CHAN_HT40(chan
)) {
652 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE7
,
653 ATH9K_POW_SM(ratesArray
[rateHt40_3
] +
654 ht40PowerIncForPdadc
, 24)
655 | ATH9K_POW_SM(ratesArray
[rateHt40_2
] +
656 ht40PowerIncForPdadc
, 16)
657 | ATH9K_POW_SM(ratesArray
[rateHt40_1
] +
658 ht40PowerIncForPdadc
, 8)
659 | ATH9K_POW_SM(ratesArray
[rateHt40_0
] +
660 ht40PowerIncForPdadc
, 0));
661 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE8
,
662 ATH9K_POW_SM(ratesArray
[rateHt40_7
] +
663 ht40PowerIncForPdadc
, 24)
664 | ATH9K_POW_SM(ratesArray
[rateHt40_6
] +
665 ht40PowerIncForPdadc
, 16)
666 | ATH9K_POW_SM(ratesArray
[rateHt40_5
] +
667 ht40PowerIncForPdadc
, 8)
668 | ATH9K_POW_SM(ratesArray
[rateHt40_4
] +
669 ht40PowerIncForPdadc
, 0));
670 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE9
,
671 ATH9K_POW_SM(ratesArray
[rateExtOfdm
], 24)
672 | ATH9K_POW_SM(ratesArray
[rateExtCck
], 16)
673 | ATH9K_POW_SM(ratesArray
[rateDupOfdm
], 8)
674 | ATH9K_POW_SM(ratesArray
[rateDupCck
], 0));
677 REGWRITE_BUFFER_FLUSH(ah
);
680 static void ath9k_hw_4k_set_addac(struct ath_hw
*ah
,
681 struct ath9k_channel
*chan
)
683 struct modal_eep_4k_header
*pModal
;
684 struct ar5416_eeprom_4k
*eep
= &ah
->eeprom
.map4k
;
687 if (ah
->hw_version
.macVersion
!= AR_SREV_VERSION_9160
)
690 if (ah
->eep_ops
->get_eeprom_rev(ah
) < AR5416_EEP_MINOR_VER_7
)
693 pModal
= &eep
->modalHeader
;
695 if (pModal
->xpaBiasLvl
!= 0xff) {
696 biaslevel
= pModal
->xpaBiasLvl
;
697 INI_RA(&ah
->iniAddac
, 7, 1) =
698 (INI_RA(&ah
->iniAddac
, 7, 1) & (~0x18)) | biaslevel
<< 3;
702 static void ath9k_hw_4k_set_gain(struct ath_hw
*ah
,
703 struct modal_eep_4k_header
*pModal
,
704 struct ar5416_eeprom_4k
*eep
,
707 REG_WRITE(ah
, AR_PHY_SWITCH_CHAIN_0
,
708 pModal
->antCtrlChain
[0]);
710 REG_WRITE(ah
, AR_PHY_TIMING_CTRL4(0),
711 (REG_READ(ah
, AR_PHY_TIMING_CTRL4(0)) &
712 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
|
713 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
)) |
714 SM(pModal
->iqCalICh
[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
) |
715 SM(pModal
->iqCalQCh
[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
));
717 if ((eep
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
718 AR5416_EEP_MINOR_VER_3
) {
719 txRxAttenLocal
= pModal
->txRxAttenCh
[0];
721 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
,
722 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN
, pModal
->bswMargin
[0]);
723 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
,
724 AR_PHY_GAIN_2GHZ_XATTEN1_DB
, pModal
->bswAtten
[0]);
725 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
,
726 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN
,
727 pModal
->xatten2Margin
[0]);
728 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
,
729 AR_PHY_GAIN_2GHZ_XATTEN2_DB
, pModal
->xatten2Db
[0]);
731 /* Set the block 1 value to block 0 value */
732 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000,
733 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN
,
734 pModal
->bswMargin
[0]);
735 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000,
736 AR_PHY_GAIN_2GHZ_XATTEN1_DB
, pModal
->bswAtten
[0]);
737 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000,
738 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN
,
739 pModal
->xatten2Margin
[0]);
740 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000,
741 AR_PHY_GAIN_2GHZ_XATTEN2_DB
,
742 pModal
->xatten2Db
[0]);
745 REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
,
746 AR9280_PHY_RXGAIN_TXRX_ATTEN
, txRxAttenLocal
);
747 REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
,
748 AR9280_PHY_RXGAIN_TXRX_MARGIN
, pModal
->rxTxMarginCh
[0]);
750 REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
+ 0x1000,
751 AR9280_PHY_RXGAIN_TXRX_ATTEN
, txRxAttenLocal
);
752 REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
+ 0x1000,
753 AR9280_PHY_RXGAIN_TXRX_MARGIN
, pModal
->rxTxMarginCh
[0]);
757 * Read EEPROM header info and program the device for correct operation
758 * given the channel value.
760 static void ath9k_hw_4k_set_board_values(struct ath_hw
*ah
,
761 struct ath9k_channel
*chan
)
763 struct modal_eep_4k_header
*pModal
;
764 struct ar5416_eeprom_4k
*eep
= &ah
->eeprom
.map4k
;
766 u8 ob
[5], db1
[5], db2
[5];
767 u8 ant_div_control1
, ant_div_control2
;
770 pModal
= &eep
->modalHeader
;
773 REG_WRITE(ah
, AR_PHY_SWITCH_COM
, pModal
->antCtrlCommon
);
775 /* Single chain for 4K EEPROM*/
776 ath9k_hw_4k_set_gain(ah
, pModal
, eep
, txRxAttenLocal
);
778 /* Initialize Ant Diversity settings from EEPROM */
779 if (pModal
->version
>= 3) {
780 ant_div_control1
= pModal
->antdiv_ctl1
;
781 ant_div_control2
= pModal
->antdiv_ctl2
;
783 regVal
= REG_READ(ah
, AR_PHY_MULTICHAIN_GAIN_CTL
);
784 regVal
&= (~(AR_PHY_9285_ANT_DIV_CTL_ALL
));
786 regVal
|= SM(ant_div_control1
,
787 AR_PHY_9285_ANT_DIV_CTL
);
788 regVal
|= SM(ant_div_control2
,
789 AR_PHY_9285_ANT_DIV_ALT_LNACONF
);
790 regVal
|= SM((ant_div_control2
>> 2),
791 AR_PHY_9285_ANT_DIV_MAIN_LNACONF
);
792 regVal
|= SM((ant_div_control1
>> 1),
793 AR_PHY_9285_ANT_DIV_ALT_GAINTB
);
794 regVal
|= SM((ant_div_control1
>> 2),
795 AR_PHY_9285_ANT_DIV_MAIN_GAINTB
);
798 REG_WRITE(ah
, AR_PHY_MULTICHAIN_GAIN_CTL
, regVal
);
799 regVal
= REG_READ(ah
, AR_PHY_MULTICHAIN_GAIN_CTL
);
800 regVal
= REG_READ(ah
, AR_PHY_CCK_DETECT
);
801 regVal
&= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV
);
802 regVal
|= SM((ant_div_control1
>> 3),
803 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV
);
805 REG_WRITE(ah
, AR_PHY_CCK_DETECT
, regVal
);
806 regVal
= REG_READ(ah
, AR_PHY_CCK_DETECT
);
809 if (pModal
->version
>= 2) {
810 ob
[0] = pModal
->ob_0
;
811 ob
[1] = pModal
->ob_1
;
812 ob
[2] = pModal
->ob_2
;
813 ob
[3] = pModal
->ob_3
;
814 ob
[4] = pModal
->ob_4
;
816 db1
[0] = pModal
->db1_0
;
817 db1
[1] = pModal
->db1_1
;
818 db1
[2] = pModal
->db1_2
;
819 db1
[3] = pModal
->db1_3
;
820 db1
[4] = pModal
->db1_4
;
822 db2
[0] = pModal
->db2_0
;
823 db2
[1] = pModal
->db2_1
;
824 db2
[2] = pModal
->db2_2
;
825 db2
[3] = pModal
->db2_3
;
826 db2
[4] = pModal
->db2_4
;
827 } else if (pModal
->version
== 1) {
828 ob
[0] = pModal
->ob_0
;
829 ob
[1] = ob
[2] = ob
[3] = ob
[4] = pModal
->ob_1
;
830 db1
[0] = pModal
->db1_0
;
831 db1
[1] = db1
[2] = db1
[3] = db1
[4] = pModal
->db1_1
;
832 db2
[0] = pModal
->db2_0
;
833 db2
[1] = db2
[2] = db2
[3] = db2
[4] = pModal
->db2_1
;
837 for (i
= 0; i
< 5; i
++) {
838 ob
[i
] = pModal
->ob_0
;
839 db1
[i
] = pModal
->db1_0
;
840 db2
[i
] = pModal
->db1_0
;
844 if (AR_SREV_9271(ah
)) {
845 ath9k_hw_analog_shift_rmw(ah
,
847 AR9271_AN_RF2G3_OB_cck
,
848 AR9271_AN_RF2G3_OB_cck_S
,
850 ath9k_hw_analog_shift_rmw(ah
,
852 AR9271_AN_RF2G3_OB_psk
,
853 AR9271_AN_RF2G3_OB_psk_S
,
855 ath9k_hw_analog_shift_rmw(ah
,
857 AR9271_AN_RF2G3_OB_qam
,
858 AR9271_AN_RF2G3_OB_qam_S
,
860 ath9k_hw_analog_shift_rmw(ah
,
862 AR9271_AN_RF2G3_DB_1
,
863 AR9271_AN_RF2G3_DB_1_S
,
865 ath9k_hw_analog_shift_rmw(ah
,
867 AR9271_AN_RF2G4_DB_2
,
868 AR9271_AN_RF2G4_DB_2_S
,
871 ath9k_hw_analog_shift_rmw(ah
,
873 AR9285_AN_RF2G3_OB_0
,
874 AR9285_AN_RF2G3_OB_0_S
,
876 ath9k_hw_analog_shift_rmw(ah
,
878 AR9285_AN_RF2G3_OB_1
,
879 AR9285_AN_RF2G3_OB_1_S
,
881 ath9k_hw_analog_shift_rmw(ah
,
883 AR9285_AN_RF2G3_OB_2
,
884 AR9285_AN_RF2G3_OB_2_S
,
886 ath9k_hw_analog_shift_rmw(ah
,
888 AR9285_AN_RF2G3_OB_3
,
889 AR9285_AN_RF2G3_OB_3_S
,
891 ath9k_hw_analog_shift_rmw(ah
,
893 AR9285_AN_RF2G3_OB_4
,
894 AR9285_AN_RF2G3_OB_4_S
,
897 ath9k_hw_analog_shift_rmw(ah
,
899 AR9285_AN_RF2G3_DB1_0
,
900 AR9285_AN_RF2G3_DB1_0_S
,
902 ath9k_hw_analog_shift_rmw(ah
,
904 AR9285_AN_RF2G3_DB1_1
,
905 AR9285_AN_RF2G3_DB1_1_S
,
907 ath9k_hw_analog_shift_rmw(ah
,
909 AR9285_AN_RF2G3_DB1_2
,
910 AR9285_AN_RF2G3_DB1_2_S
,
912 ath9k_hw_analog_shift_rmw(ah
,
914 AR9285_AN_RF2G4_DB1_3
,
915 AR9285_AN_RF2G4_DB1_3_S
,
917 ath9k_hw_analog_shift_rmw(ah
,
919 AR9285_AN_RF2G4_DB1_4
,
920 AR9285_AN_RF2G4_DB1_4_S
, db1
[4]);
922 ath9k_hw_analog_shift_rmw(ah
,
924 AR9285_AN_RF2G4_DB2_0
,
925 AR9285_AN_RF2G4_DB2_0_S
,
927 ath9k_hw_analog_shift_rmw(ah
,
929 AR9285_AN_RF2G4_DB2_1
,
930 AR9285_AN_RF2G4_DB2_1_S
,
932 ath9k_hw_analog_shift_rmw(ah
,
934 AR9285_AN_RF2G4_DB2_2
,
935 AR9285_AN_RF2G4_DB2_2_S
,
937 ath9k_hw_analog_shift_rmw(ah
,
939 AR9285_AN_RF2G4_DB2_3
,
940 AR9285_AN_RF2G4_DB2_3_S
,
942 ath9k_hw_analog_shift_rmw(ah
,
944 AR9285_AN_RF2G4_DB2_4
,
945 AR9285_AN_RF2G4_DB2_4_S
,
950 REG_RMW_FIELD(ah
, AR_PHY_SETTLING
, AR_PHY_SETTLING_SWITCH
,
951 pModal
->switchSettling
);
952 REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
, AR_PHY_DESIRED_SZ_ADC
,
953 pModal
->adcDesiredSize
);
955 REG_WRITE(ah
, AR_PHY_RF_CTL4
,
956 SM(pModal
->txEndToXpaOff
, AR_PHY_RF_CTL4_TX_END_XPAA_OFF
) |
957 SM(pModal
->txEndToXpaOff
, AR_PHY_RF_CTL4_TX_END_XPAB_OFF
) |
958 SM(pModal
->txFrameToXpaOn
, AR_PHY_RF_CTL4_FRAME_XPAA_ON
) |
959 SM(pModal
->txFrameToXpaOn
, AR_PHY_RF_CTL4_FRAME_XPAB_ON
));
961 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL3
, AR_PHY_TX_END_TO_A2_RX_ON
,
962 pModal
->txEndToRxOn
);
964 if (AR_SREV_9271_10(ah
))
965 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL3
, AR_PHY_TX_END_TO_A2_RX_ON
,
966 pModal
->txEndToRxOn
);
967 REG_RMW_FIELD(ah
, AR_PHY_CCA
, AR9280_PHY_CCA_THRESH62
,
969 REG_RMW_FIELD(ah
, AR_PHY_EXT_CCA0
, AR_PHY_EXT_CCA0_THRESH62
,
972 if ((eep
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
973 AR5416_EEP_MINOR_VER_2
) {
974 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
, AR_PHY_TX_END_DATA_START
,
975 pModal
->txFrameToDataStart
);
976 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
, AR_PHY_TX_END_PA_ON
,
977 pModal
->txFrameToPaOn
);
980 if ((eep
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
981 AR5416_EEP_MINOR_VER_3
) {
982 if (IS_CHAN_HT40(chan
))
983 REG_RMW_FIELD(ah
, AR_PHY_SETTLING
,
984 AR_PHY_SETTLING_SWITCH
,
985 pModal
->swSettleHt40
);
989 static u16
ath9k_hw_4k_get_spur_channel(struct ath_hw
*ah
, u16 i
, bool is2GHz
)
991 #define EEP_MAP4K_SPURCHAN \
992 (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
993 struct ath_common
*common
= ath9k_hw_common(ah
);
995 u16 spur_val
= AR_NO_SPUR
;
997 ath_dbg(common
, ATH_DBG_ANI
,
998 "Getting spur idx:%d is2Ghz:%d val:%x\n",
999 i
, is2GHz
, ah
->config
.spurchans
[i
][is2GHz
]);
1001 switch (ah
->config
.spurmode
) {
1004 case SPUR_ENABLE_IOCTL
:
1005 spur_val
= ah
->config
.spurchans
[i
][is2GHz
];
1006 ath_dbg(common
, ATH_DBG_ANI
,
1007 "Getting spur val from new loc. %d\n", spur_val
);
1009 case SPUR_ENABLE_EEPROM
:
1010 spur_val
= EEP_MAP4K_SPURCHAN
;
1016 #undef EEP_MAP4K_SPURCHAN
1019 const struct eeprom_ops eep_4k_ops
= {
1020 .check_eeprom
= ath9k_hw_4k_check_eeprom
,
1021 .get_eeprom
= ath9k_hw_4k_get_eeprom
,
1022 .fill_eeprom
= ath9k_hw_4k_fill_eeprom
,
1023 .get_eeprom_ver
= ath9k_hw_4k_get_eeprom_ver
,
1024 .get_eeprom_rev
= ath9k_hw_4k_get_eeprom_rev
,
1025 .set_board_values
= ath9k_hw_4k_set_board_values
,
1026 .set_addac
= ath9k_hw_4k_set_addac
,
1027 .set_txpower
= ath9k_hw_4k_set_txpower
,
1028 .get_spur_channel
= ath9k_hw_4k_get_spur_channel