2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #include "ah_internal.h"
26 #include "ah_eeprom_v14.h"
27 #include "ah_eeprom_9287.h"
29 #include "ar5416/ar5416.h"
30 #include "ar5416/ar5416reg.h"
31 #include "ar5416/ar5416phy.h"
33 #include "ar9002/ar9287phy.h"
34 #include "ar9002/ar9287an.h"
36 #include "ar9002/ar9287_olc.h"
37 #include "ar9002/ar9287_reset.h"
40 * Set the TX power calibration table per-chain.
42 * This only supports open-loop TX power control for the AR9287.
45 ar9287SetPowerCalTable(struct ath_hal
*ah
,
46 const struct ieee80211_channel
*chan
, int16_t *pTxPowerIndexOffset
)
48 struct cal_data_op_loop_ar9287
*pRawDatasetOpenLoop
;
49 uint8_t *pCalBChans
= NULL
;
50 uint16_t pdGainOverlap_t2
;
51 uint16_t numPiers
= 0, i
;
52 uint16_t numXpdGain
, xpdMask
;
53 uint16_t xpdGainValues
[AR5416_NUM_PD_GAINS
] = {0, 0, 0, 0};
54 uint32_t regChainOffset
;
55 HAL_EEPROM_9287
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
56 struct ar9287_eeprom
*pEepData
= &ee
->ee_base
;
58 xpdMask
= pEepData
->modalHeader
.xpdGain
;
60 if ((pEepData
->baseEepHeader
.version
& AR9287_EEP_VER_MINOR_MASK
) >=
61 AR9287_EEP_MINOR_VER_2
)
62 pdGainOverlap_t2
= pEepData
->modalHeader
.pdGainOverlap
;
64 pdGainOverlap_t2
= (uint16_t)(MS(OS_REG_READ(ah
, AR_PHY_TPCRG5
),
65 AR_PHY_TPCRG5_PD_GAIN_OVERLAP
));
67 /* Note: Kiwi should only be 2ghz.. */
68 if (IEEE80211_IS_CHAN_2GHZ(chan
)) {
69 pCalBChans
= pEepData
->calFreqPier2G
;
70 numPiers
= AR9287_NUM_2G_CAL_PIERS
;
71 pRawDatasetOpenLoop
= (struct cal_data_op_loop_ar9287
*)pEepData
->calPierData2G
[0];
72 AH5416(ah
)->initPDADC
= pRawDatasetOpenLoop
->vpdPdg
[0][0];
76 /* Calculate the value of xpdgains from the xpdGain Mask */
77 for (i
= 1; i
<= AR5416_PD_GAINS_IN_MASK
; i
++) {
78 if ((xpdMask
>> (AR5416_PD_GAINS_IN_MASK
- i
)) & 1) {
79 if (numXpdGain
>= AR5416_NUM_PD_GAINS
)
81 xpdGainValues
[numXpdGain
] =
82 (uint16_t)(AR5416_PD_GAINS_IN_MASK
-i
);
87 OS_REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_NUM_PD_GAIN
,
88 (numXpdGain
- 1) & 0x3);
89 OS_REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_1
,
91 OS_REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_2
,
93 OS_REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_3
,
96 for (i
= 0; i
< AR9287_MAX_CHAINS
; i
++) {
97 regChainOffset
= i
* 0x1000;
99 if (pEepData
->baseEepHeader
.txMask
& (1 << i
)) {
101 pRawDatasetOpenLoop
=
102 (struct cal_data_op_loop_ar9287
*)pEepData
->calPierData2G
[i
];
103 ar9287olcGetTxGainIndex(ah
, chan
,
105 pCalBChans
, numPiers
,
107 ar9287olcSetPDADCs(ah
, txPower
, i
);
111 *pTxPowerIndexOffset
= 0;
115 /* XXX hard-coded values? */
116 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
119 * ar9287SetPowerPerRateTable
121 * Sets the transmit power in the baseband for the given
122 * operating channel and mode.
124 * This is like the v14 EEPROM table except the 5GHz code.
127 ar9287SetPowerPerRateTable(struct ath_hal
*ah
,
128 struct ar9287_eeprom
*pEepData
,
129 const struct ieee80211_channel
*chan
,
130 int16_t *ratesArray
, uint16_t cfgCtl
,
131 uint16_t AntennaReduction
,
132 uint16_t twiceMaxRegulatoryPower
,
135 #define N(a) (sizeof(a)/sizeof(a[0]))
136 /* Local defines to distinguish between extension and control CTL's */
137 #define EXT_ADDITIVE (0x8000)
138 #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
139 #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
140 #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
142 uint16_t twiceMaxEdgePower
= AR5416_MAX_RATE_POWER
;
144 int16_t twiceLargestAntenna
;
145 struct cal_ctl_data_ar9287
*rep
;
146 CAL_TARGET_POWER_LEG targetPowerOfdm
;
147 CAL_TARGET_POWER_LEG targetPowerCck
= {0, {0, 0, 0, 0}};
148 CAL_TARGET_POWER_LEG targetPowerOfdmExt
= {0, {0, 0, 0, 0}};
149 CAL_TARGET_POWER_LEG targetPowerCckExt
= {0, {0, 0, 0, 0}};
150 CAL_TARGET_POWER_HT targetPowerHt20
;
151 CAL_TARGET_POWER_HT targetPowerHt40
= {0, {0, 0, 0, 0}};
152 int16_t scaledPower
, minCtlPower
;
154 #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */
155 static const uint16_t ctlModesFor11g
[] = {
156 CTL_11B
, CTL_11G
, CTL_2GHT20
, CTL_11B_EXT
, CTL_11G_EXT
, CTL_2GHT40
158 const uint16_t *pCtlMode
;
159 uint16_t numCtlModes
, ctlMode
, freq
;
160 CHAN_CENTERS centers
;
162 ar5416GetChannelCenters(ah
, chan
, ¢ers
);
164 /* Compute TxPower reduction due to Antenna Gain */
166 twiceLargestAntenna
= AH_MAX(
167 pEepData
->modalHeader
.antennaGainCh
[0],
168 pEepData
->modalHeader
.antennaGainCh
[1]);
170 twiceLargestAntenna
= (int16_t)AH_MIN((AntennaReduction
) - twiceLargestAntenna
, 0);
172 /* XXX setup for 5212 use (really used?) */
173 ath_hal_eepromSet(ah
, AR_EEP_ANTGAINMAX_2
, twiceLargestAntenna
);
176 * scaledPower is the minimum of the user input power level and
177 * the regulatory allowed power level
179 scaledPower
= AH_MIN(powerLimit
, twiceMaxRegulatoryPower
+ twiceLargestAntenna
);
181 /* Reduce scaled Power by number of chains active to get to per chain tx power level */
182 /* TODO: better value than these? */
183 switch (owl_get_ntxchains(AH5416(ah
)->ah_tx_chainmask
)) {
187 scaledPower
-= REDUCE_SCALED_POWER_BY_TWO_CHAIN
;
190 return AH_FALSE
; /* Unsupported number of chains */
193 scaledPower
= AH_MAX(0, scaledPower
);
195 /* Get target powers from EEPROM - our baseline for TX Power */
196 /* XXX assume channel is 2ghz */
198 /* Setup for CTL modes */
199 numCtlModes
= N(ctlModesFor11g
) - SUB_NUM_CTL_MODES_AT_2G_40
; /* CTL_11B, CTL_11G, CTL_2GHT20 */
200 pCtlMode
= ctlModesFor11g
;
202 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPowerCck
,
203 AR9287_NUM_2G_CCK_TARGET_POWERS
, &targetPowerCck
, 4, AH_FALSE
);
204 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPower2G
,
205 AR9287_NUM_2G_20_TARGET_POWERS
, &targetPowerOfdm
, 4, AH_FALSE
);
206 ar5416GetTargetPowers(ah
, chan
, pEepData
->calTargetPower2GHT20
,
207 AR9287_NUM_2G_20_TARGET_POWERS
, &targetPowerHt20
, 8, AH_FALSE
);
209 if (IEEE80211_IS_CHAN_HT40(chan
)) {
210 numCtlModes
= N(ctlModesFor11g
); /* All 2G CTL's */
212 ar5416GetTargetPowers(ah
, chan
, pEepData
->calTargetPower2GHT40
,
213 AR9287_NUM_2G_40_TARGET_POWERS
, &targetPowerHt40
, 8, AH_TRUE
);
214 /* Get target powers for extension channels */
215 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPowerCck
,
216 AR9287_NUM_2G_CCK_TARGET_POWERS
, &targetPowerCckExt
, 4, AH_TRUE
);
217 ar5416GetTargetPowersLeg(ah
, chan
, pEepData
->calTargetPower2G
,
218 AR9287_NUM_2G_20_TARGET_POWERS
, &targetPowerOfdmExt
, 4, AH_TRUE
);
223 * For MIMO, need to apply regulatory caps individually across dynamically
224 * running modes: CCK, OFDM, HT20, HT40
226 * The outer loop walks through each possible applicable runtime mode.
227 * The inner loop walks through each ctlIndex entry in EEPROM.
228 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
231 for (ctlMode
= 0; ctlMode
< numCtlModes
; ctlMode
++) {
232 HAL_BOOL isHt40CtlMode
= (pCtlMode
[ctlMode
] == CTL_5GHT40
) ||
233 (pCtlMode
[ctlMode
] == CTL_2GHT40
);
235 freq
= centers
.ctl_center
;
236 } else if (pCtlMode
[ctlMode
] & EXT_ADDITIVE
) {
237 freq
= centers
.ext_center
;
239 freq
= centers
.ctl_center
;
242 /* walk through each CTL index stored in EEPROM */
243 for (i
= 0; (i
< AR9287_NUM_CTLS
) && pEepData
->ctlIndex
[i
]; i
++) {
244 uint16_t twiceMinEdgePower
;
246 /* compare test group from regulatory channel list with test mode from pCtlMode list */
247 if ((((cfgCtl
& ~CTL_MODE_M
) | (pCtlMode
[ctlMode
] & CTL_MODE_M
)) == pEepData
->ctlIndex
[i
]) ||
248 (((cfgCtl
& ~CTL_MODE_M
) | (pCtlMode
[ctlMode
] & CTL_MODE_M
)) ==
249 ((pEepData
->ctlIndex
[i
] & CTL_MODE_M
) | SD_NO_CTL
))) {
250 rep
= &(pEepData
->ctlData
[i
]);
251 twiceMinEdgePower
= ar5416GetMaxEdgePower(freq
,
252 rep
->ctlEdges
[owl_get_ntxchains(AH5416(ah
)->ah_tx_chainmask
) - 1],
253 IEEE80211_IS_CHAN_2GHZ(chan
));
254 if ((cfgCtl
& ~CTL_MODE_M
) == SD_NO_CTL
) {
255 /* Find the minimum of all CTL edge powers that apply to this channel */
256 twiceMaxEdgePower
= AH_MIN(twiceMaxEdgePower
, twiceMinEdgePower
);
259 twiceMaxEdgePower
= twiceMinEdgePower
;
264 minCtlPower
= (uint8_t)AH_MIN(twiceMaxEdgePower
, scaledPower
);
265 /* Apply ctl mode to correct target power set */
266 switch(pCtlMode
[ctlMode
]) {
268 for (i
= 0; i
< N(targetPowerCck
.tPow2x
); i
++) {
269 targetPowerCck
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerCck
.tPow2x
[i
], minCtlPower
);
274 for (i
= 0; i
< N(targetPowerOfdm
.tPow2x
); i
++) {
275 targetPowerOfdm
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerOfdm
.tPow2x
[i
], minCtlPower
);
280 for (i
= 0; i
< N(targetPowerHt20
.tPow2x
); i
++) {
281 targetPowerHt20
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerHt20
.tPow2x
[i
], minCtlPower
);
285 targetPowerCckExt
.tPow2x
[0] = (uint8_t)AH_MIN(targetPowerCckExt
.tPow2x
[0], minCtlPower
);
289 targetPowerOfdmExt
.tPow2x
[0] = (uint8_t)AH_MIN(targetPowerOfdmExt
.tPow2x
[0], minCtlPower
);
293 for (i
= 0; i
< N(targetPowerHt40
.tPow2x
); i
++) {
294 targetPowerHt40
.tPow2x
[i
] = (uint8_t)AH_MIN(targetPowerHt40
.tPow2x
[i
], minCtlPower
);
301 } /* end ctl mode checking */
303 /* Set rates Array from collected data */
304 ar5416SetRatesArrayFromTargetPower(ah
, chan
, ratesArray
,
316 #undef SUB_NUM_CTL_MODES_AT_5G_40
317 #undef SUB_NUM_CTL_MODES_AT_2G_40
321 #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN
324 * This is based off of the AR5416/AR9285 code and likely could
325 * be unified in the future.
328 ar9287SetTransmitPower(struct ath_hal
*ah
,
329 const struct ieee80211_channel
*chan
, uint16_t *rfXpdGain
)
331 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
332 #define N(a) (sizeof (a) / sizeof (a[0]))
334 const struct modal_eep_ar9287_header
*pModal
;
335 struct ath_hal_5212
*ahp
= AH5212(ah
);
336 int16_t txPowerIndexOffset
= 0;
341 uint16_t twiceAntennaReduction
;
342 uint16_t twiceMaxRegulatoryPower
;
344 HAL_EEPROM_9287
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
345 struct ar9287_eeprom
*pEepData
= &ee
->ee_base
;
347 AH5416(ah
)->ah_ht40PowerIncForPdadc
= 2;
349 /* Setup info for the actual eeprom */
350 OS_MEMZERO(AH5416(ah
)->ah_ratesArray
,
351 sizeof(AH5416(ah
)->ah_ratesArray
));
352 cfgCtl
= ath_hal_getctl(ah
, chan
);
353 powerLimit
= chan
->ic_maxregpower
* 2;
354 twiceAntennaReduction
= chan
->ic_maxantgain
;
355 twiceMaxRegulatoryPower
= AH_MIN(MAX_RATE_POWER
,
356 AH_PRIVATE(ah
)->ah_powerLimit
);
357 pModal
= &pEepData
->modalHeader
;
358 HALDEBUG(ah
, HAL_DEBUG_RESET
, "%s Channel=%u CfgCtl=%u\n",
359 __func__
,chan
->ic_freq
, cfgCtl
);
361 /* XXX Assume Minor is v2 or later */
362 AH5416(ah
)->ah_ht40PowerIncForPdadc
= pModal
->ht40PowerIncForPdadc
;
364 /* Fetch per-rate power table for the given channel */
365 if (! ar9287SetPowerPerRateTable(ah
, pEepData
, chan
,
366 &AH5416(ah
)->ah_ratesArray
[0],
368 twiceAntennaReduction
,
369 twiceMaxRegulatoryPower
, powerLimit
)) {
370 HALDEBUG(ah
, HAL_DEBUG_ANY
,
371 "%s: unable to set tx power per rate table\n", __func__
);
375 /* Set TX power control calibration curves for each TX chain */
376 ar9287SetPowerCalTable(ah
, chan
, &txPowerIndexOffset
);
378 /* Calculate maximum power level */
379 maxPower
= AH_MAX(AH5416(ah
)->ah_ratesArray
[rate6mb
],
380 AH5416(ah
)->ah_ratesArray
[rateHt20_0
]);
381 maxPower
= AH_MAX(maxPower
,
382 AH5416(ah
)->ah_ratesArray
[rate1l
]);
384 if (IEEE80211_IS_CHAN_HT40(chan
))
385 maxPower
= AH_MAX(maxPower
,
386 AH5416(ah
)->ah_ratesArray
[rateHt40_0
]);
388 ahp
->ah_tx6PowerInHalfDbm
= maxPower
;
389 AH_PRIVATE(ah
)->ah_maxPowerLevel
= maxPower
;
390 ahp
->ah_txPowerIndexOffset
= txPowerIndexOffset
;
393 * txPowerIndexOffset is set by the SetPowerTable() call -
394 * adjust the rate table (0 offset if rates EEPROM not loaded)
396 /* XXX what about the pwrTableOffset? */
397 for (i
= 0; i
< N(AH5416(ah
)->ah_ratesArray
); i
++) {
398 AH5416(ah
)->ah_ratesArray
[i
] =
399 (int16_t)(txPowerIndexOffset
+
400 AH5416(ah
)->ah_ratesArray
[i
]);
401 /* -5 dBm offset for Merlin and later; this includes Kiwi */
402 AH5416(ah
)->ah_ratesArray
[i
] -= AR5416_PWR_TABLE_OFFSET_DB
* 2;
403 if (AH5416(ah
)->ah_ratesArray
[i
] > AR5416_MAX_RATE_POWER
)
404 AH5416(ah
)->ah_ratesArray
[i
] = AR5416_MAX_RATE_POWER
;
405 if (AH5416(ah
)->ah_ratesArray
[i
] < 0)
406 AH5416(ah
)->ah_ratesArray
[i
] = 0;
409 #ifdef AH_EEPROM_DUMP
410 ar5416PrintPowerPerRate(ah
, AH5416(ah
)->ah_ratesArray
);
414 * Adjust the HT40 power to meet the correct target TX power
415 * for 40MHz mode, based on TX power curves that are established
418 * XXX handle overflow/too high power level?
420 if (IEEE80211_IS_CHAN_HT40(chan
)) {
421 AH5416(ah
)->ah_ratesArray
[rateHt40_0
] +=
422 AH5416(ah
)->ah_ht40PowerIncForPdadc
;
423 AH5416(ah
)->ah_ratesArray
[rateHt40_1
] +=
424 AH5416(ah
)->ah_ht40PowerIncForPdadc
;
425 AH5416(ah
)->ah_ratesArray
[rateHt40_2
] +=
426 AH5416(ah
)->ah_ht40PowerIncForPdadc
;
427 AH5416(ah
)->ah_ratesArray
[rateHt40_3
] +=
428 AH5416(ah
)->ah_ht40PowerIncForPdadc
;
429 AH5416(ah
)->ah_ratesArray
[rateHt40_4
] +=
430 AH5416(ah
)->ah_ht40PowerIncForPdadc
;
431 AH5416(ah
)->ah_ratesArray
[rateHt40_5
] +=
432 AH5416(ah
)->ah_ht40PowerIncForPdadc
;
433 AH5416(ah
)->ah_ratesArray
[rateHt40_6
] +=
434 AH5416(ah
)->ah_ht40PowerIncForPdadc
;
435 AH5416(ah
)->ah_ratesArray
[rateHt40_7
] +=
436 AH5416(ah
)->ah_ht40PowerIncForPdadc
;
439 /* Write the TX power rate registers */
440 ar5416WriteTxPowerRateRegisters(ah
, chan
, AH5416(ah
)->ah_ratesArray
);
448 * Read EEPROM header info and program the device for correct operation
449 * given the channel value.
452 ar9287SetBoardValues(struct ath_hal
*ah
, const struct ieee80211_channel
*chan
)
454 const HAL_EEPROM_9287
*ee
= AH_PRIVATE(ah
)->ah_eeprom
;
455 const struct ar9287_eeprom
*eep
= &ee
->ee_base
;
456 const struct modal_eep_ar9287_header
*pModal
= &eep
->modalHeader
;
457 uint16_t antWrites
[AR9287_ANT_16S
];
458 uint32_t regChainOffset
, regval
;
459 uint8_t txRxAttenLocal
;
460 int i
, j
, offset_num
;
462 pModal
= &eep
->modalHeader
;
464 antWrites
[0] = (uint16_t)((pModal
->antCtrlCommon
>> 28) & 0xF);
465 antWrites
[1] = (uint16_t)((pModal
->antCtrlCommon
>> 24) & 0xF);
466 antWrites
[2] = (uint16_t)((pModal
->antCtrlCommon
>> 20) & 0xF);
467 antWrites
[3] = (uint16_t)((pModal
->antCtrlCommon
>> 16) & 0xF);
468 antWrites
[4] = (uint16_t)((pModal
->antCtrlCommon
>> 12) & 0xF);
469 antWrites
[5] = (uint16_t)((pModal
->antCtrlCommon
>> 8) & 0xF);
470 antWrites
[6] = (uint16_t)((pModal
->antCtrlCommon
>> 4) & 0xF);
471 antWrites
[7] = (uint16_t)(pModal
->antCtrlCommon
& 0xF);
475 for (i
= 0, j
= offset_num
; i
< AR9287_MAX_CHAINS
; i
++) {
476 antWrites
[j
++] = (uint16_t)((pModal
->antCtrlChain
[i
] >> 28) & 0xf);
477 antWrites
[j
++] = (uint16_t)((pModal
->antCtrlChain
[i
] >> 10) & 0x3);
478 antWrites
[j
++] = (uint16_t)((pModal
->antCtrlChain
[i
] >> 8) & 0x3);
480 antWrites
[j
++] = (uint16_t)((pModal
->antCtrlChain
[i
] >> 6) & 0x3);
481 antWrites
[j
++] = (uint16_t)((pModal
->antCtrlChain
[i
] >> 4) & 0x3);
482 antWrites
[j
++] = (uint16_t)((pModal
->antCtrlChain
[i
] >> 2) & 0x3);
483 antWrites
[j
++] = (uint16_t)(pModal
->antCtrlChain
[i
] & 0x3);
486 OS_REG_WRITE(ah
, AR_PHY_SWITCH_COM
, pModal
->antCtrlCommon
);
488 for (i
= 0; i
< AR9287_MAX_CHAINS
; i
++) {
489 regChainOffset
= i
* 0x1000;
491 OS_REG_WRITE(ah
, AR_PHY_SWITCH_CHAIN_0
+ regChainOffset
,
492 pModal
->antCtrlChain
[i
]);
494 OS_REG_WRITE(ah
, AR_PHY_TIMING_CTRL4_CHAIN(0) + regChainOffset
,
495 (OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4_CHAIN(0)
497 & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
|
498 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
)) |
499 SM(pModal
->iqCalICh
[i
],
500 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
) |
501 SM(pModal
->iqCalQCh
[i
],
502 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
));
504 txRxAttenLocal
= pModal
->txRxAttenCh
[i
];
506 OS_REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ regChainOffset
,
507 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN
,
508 pModal
->bswMargin
[i
]);
509 OS_REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ regChainOffset
,
510 AR_PHY_GAIN_2GHZ_XATTEN1_DB
,
511 pModal
->bswAtten
[i
]);
512 OS_REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
+ regChainOffset
,
513 AR9280_PHY_RXGAIN_TXRX_ATTEN
,
515 OS_REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
+ regChainOffset
,
516 AR9280_PHY_RXGAIN_TXRX_MARGIN
,
517 pModal
->rxTxMarginCh
[i
]);
520 if (IEEE80211_IS_CHAN_HT40(chan
))
521 OS_REG_RMW_FIELD(ah
, AR_PHY_SETTLING
,
522 AR_PHY_SETTLING_SWITCH
, pModal
->swSettleHt40
);
524 OS_REG_RMW_FIELD(ah
, AR_PHY_SETTLING
,
525 AR_PHY_SETTLING_SWITCH
, pModal
->switchSettling
);
527 OS_REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
,
528 AR_PHY_DESIRED_SZ_ADC
, pModal
->adcDesiredSize
);
530 OS_REG_WRITE(ah
, AR_PHY_RF_CTL4
,
531 SM(pModal
->txEndToXpaOff
, AR_PHY_RF_CTL4_TX_END_XPAA_OFF
)
532 | SM(pModal
->txEndToXpaOff
, AR_PHY_RF_CTL4_TX_END_XPAB_OFF
)
533 | SM(pModal
->txFrameToXpaOn
, AR_PHY_RF_CTL4_FRAME_XPAA_ON
)
534 | SM(pModal
->txFrameToXpaOn
, AR_PHY_RF_CTL4_FRAME_XPAB_ON
));
536 OS_REG_RMW_FIELD(ah
, AR_PHY_RF_CTL3
,
537 AR_PHY_TX_END_TO_A2_RX_ON
, pModal
->txEndToRxOn
);
539 OS_REG_RMW_FIELD(ah
, AR_PHY_CCA
,
540 AR9280_PHY_CCA_THRESH62
, pModal
->thresh62
);
541 OS_REG_RMW_FIELD(ah
, AR_PHY_EXT_CCA0
,
542 AR_PHY_EXT_CCA0_THRESH62
, pModal
->thresh62
);
544 regval
= OS_REG_READ(ah
, AR9287_AN_RF2G3_CH0
);
545 regval
&= ~(AR9287_AN_RF2G3_DB1
|
546 AR9287_AN_RF2G3_DB2
|
547 AR9287_AN_RF2G3_OB_CCK
|
548 AR9287_AN_RF2G3_OB_PSK
|
549 AR9287_AN_RF2G3_OB_QAM
|
550 AR9287_AN_RF2G3_OB_PAL_OFF
);
551 regval
|= (SM(pModal
->db1
, AR9287_AN_RF2G3_DB1
) |
552 SM(pModal
->db2
, AR9287_AN_RF2G3_DB2
) |
553 SM(pModal
->ob_cck
, AR9287_AN_RF2G3_OB_CCK
) |
554 SM(pModal
->ob_psk
, AR9287_AN_RF2G3_OB_PSK
) |
555 SM(pModal
->ob_qam
, AR9287_AN_RF2G3_OB_QAM
) |
556 SM(pModal
->ob_pal_off
, AR9287_AN_RF2G3_OB_PAL_OFF
));
558 /* Analog write - requires a 100usec delay */
559 OS_A_REG_WRITE(ah
, AR9287_AN_RF2G3_CH0
, regval
);
561 regval
= OS_REG_READ(ah
, AR9287_AN_RF2G3_CH1
);
562 regval
&= ~(AR9287_AN_RF2G3_DB1
|
563 AR9287_AN_RF2G3_DB2
|
564 AR9287_AN_RF2G3_OB_CCK
|
565 AR9287_AN_RF2G3_OB_PSK
|
566 AR9287_AN_RF2G3_OB_QAM
|
567 AR9287_AN_RF2G3_OB_PAL_OFF
);
568 regval
|= (SM(pModal
->db1
, AR9287_AN_RF2G3_DB1
) |
569 SM(pModal
->db2
, AR9287_AN_RF2G3_DB2
) |
570 SM(pModal
->ob_cck
, AR9287_AN_RF2G3_OB_CCK
) |
571 SM(pModal
->ob_psk
, AR9287_AN_RF2G3_OB_PSK
) |
572 SM(pModal
->ob_qam
, AR9287_AN_RF2G3_OB_QAM
) |
573 SM(pModal
->ob_pal_off
, AR9287_AN_RF2G3_OB_PAL_OFF
));
575 OS_A_REG_WRITE(ah
, AR9287_AN_RF2G3_CH1
, regval
);
577 OS_REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
,
578 AR_PHY_TX_FRAME_TO_DATA_START
, pModal
->txFrameToDataStart
);
579 OS_REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
,
580 AR_PHY_TX_FRAME_TO_PA_ON
, pModal
->txFrameToPaOn
);
582 OS_A_REG_RMW_FIELD(ah
, AR9287_AN_TOP2
,
583 AR9287_AN_TOP2_XPABIAS_LVL
, pModal
->xpaBiasLvl
);