2 * Copyright (c) 2008-2011 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 <asm/unaligned.h>
19 #include "ar9002_phy.h"
21 static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw
*ah
)
23 return ((ah
->eeprom
.map4k
.baseEepHeader
.version
>> 12) & 0xF);
26 static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw
*ah
)
28 return ((ah
->eeprom
.map4k
.baseEepHeader
.version
) & 0xFFF);
31 #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
33 static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw
*ah
)
35 struct ath_common
*common
= ath9k_hw_common(ah
);
36 u16
*eep_data
= (u16
*)&ah
->eeprom
.map4k
;
37 int addr
, eep_start_loc
= 64;
39 for (addr
= 0; addr
< SIZE_EEPROM_4K
; addr
++) {
40 if (!ath9k_hw_nvram_read(common
, addr
+ eep_start_loc
, eep_data
)) {
41 ath_dbg(common
, ATH_DBG_EEPROM
,
42 "Unable to read eeprom region\n");
51 static bool __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw
*ah
)
53 u16
*eep_data
= (u16
*)&ah
->eeprom
.map4k
;
55 ath9k_hw_usb_gen_fill_eeprom(ah
, eep_data
, 64, SIZE_EEPROM_4K
);
60 static bool ath9k_hw_4k_fill_eeprom(struct ath_hw
*ah
)
62 struct ath_common
*common
= ath9k_hw_common(ah
);
64 if (!ath9k_hw_use_flash(ah
)) {
65 ath_dbg(common
, ATH_DBG_EEPROM
,
66 "Reading from EEPROM, not flash\n");
69 if (common
->bus_ops
->ath_bus_type
== ATH_USB
)
70 return __ath9k_hw_usb_4k_fill_eeprom(ah
);
72 return __ath9k_hw_4k_fill_eeprom(ah
);
77 static int ath9k_hw_4k_check_eeprom(struct ath_hw
*ah
)
79 #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
80 struct ath_common
*common
= ath9k_hw_common(ah
);
81 struct ar5416_eeprom_4k
*eep
=
82 (struct ar5416_eeprom_4k
*) &ah
->eeprom
.map4k
;
83 u16
*eepdata
, temp
, magic
, magic2
;
85 bool need_swap
= false;
89 if (!ath9k_hw_use_flash(ah
)) {
90 if (!ath9k_hw_nvram_read(common
, AR5416_EEPROM_MAGIC_OFFSET
,
92 ath_err(common
, "Reading Magic # failed\n");
96 ath_dbg(common
, ATH_DBG_EEPROM
,
97 "Read Magic = 0x%04X\n", magic
);
99 if (magic
!= AR5416_EEPROM_MAGIC
) {
100 magic2
= swab16(magic
);
102 if (magic2
== AR5416_EEPROM_MAGIC
) {
104 eepdata
= (u16
*) (&ah
->eeprom
);
106 for (addr
= 0; addr
< EEPROM_4K_SIZE
; addr
++) {
107 temp
= swab16(*eepdata
);
113 "Invalid EEPROM Magic. Endianness mismatch.\n");
119 ath_dbg(common
, ATH_DBG_EEPROM
, "need_swap = %s.\n",
120 need_swap
? "True" : "False");
123 el
= swab16(ah
->eeprom
.map4k
.baseEepHeader
.length
);
125 el
= ah
->eeprom
.map4k
.baseEepHeader
.length
;
127 if (el
> sizeof(struct ar5416_eeprom_4k
))
128 el
= sizeof(struct ar5416_eeprom_4k
) / sizeof(u16
);
130 el
= el
/ sizeof(u16
);
132 eepdata
= (u16
*)(&ah
->eeprom
);
134 for (i
= 0; i
< el
; i
++)
141 ath_dbg(common
, ATH_DBG_EEPROM
,
142 "EEPROM Endianness is not native.. Changing\n");
144 word
= swab16(eep
->baseEepHeader
.length
);
145 eep
->baseEepHeader
.length
= word
;
147 word
= swab16(eep
->baseEepHeader
.checksum
);
148 eep
->baseEepHeader
.checksum
= word
;
150 word
= swab16(eep
->baseEepHeader
.version
);
151 eep
->baseEepHeader
.version
= word
;
153 word
= swab16(eep
->baseEepHeader
.regDmn
[0]);
154 eep
->baseEepHeader
.regDmn
[0] = word
;
156 word
= swab16(eep
->baseEepHeader
.regDmn
[1]);
157 eep
->baseEepHeader
.regDmn
[1] = word
;
159 word
= swab16(eep
->baseEepHeader
.rfSilent
);
160 eep
->baseEepHeader
.rfSilent
= word
;
162 word
= swab16(eep
->baseEepHeader
.blueToothOptions
);
163 eep
->baseEepHeader
.blueToothOptions
= word
;
165 word
= swab16(eep
->baseEepHeader
.deviceCap
);
166 eep
->baseEepHeader
.deviceCap
= word
;
168 integer
= swab32(eep
->modalHeader
.antCtrlCommon
);
169 eep
->modalHeader
.antCtrlCommon
= integer
;
171 for (i
= 0; i
< AR5416_EEP4K_MAX_CHAINS
; i
++) {
172 integer
= swab32(eep
->modalHeader
.antCtrlChain
[i
]);
173 eep
->modalHeader
.antCtrlChain
[i
] = integer
;
176 for (i
= 0; i
< AR_EEPROM_MODAL_SPURS
; i
++) {
177 word
= swab16(eep
->modalHeader
.spurChans
[i
].spurChan
);
178 eep
->modalHeader
.spurChans
[i
].spurChan
= word
;
182 if (sum
!= 0xffff || ah
->eep_ops
->get_eeprom_ver(ah
) != AR5416_EEP_VER
||
183 ah
->eep_ops
->get_eeprom_rev(ah
) < AR5416_EEP_NO_BACK_VER
) {
184 ath_err(common
, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
185 sum
, ah
->eep_ops
->get_eeprom_ver(ah
));
190 #undef EEPROM_4K_SIZE
193 static u32
ath9k_hw_4k_get_eeprom(struct ath_hw
*ah
,
194 enum eeprom_param param
)
196 struct ar5416_eeprom_4k
*eep
= &ah
->eeprom
.map4k
;
197 struct modal_eep_4k_header
*pModal
= &eep
->modalHeader
;
198 struct base_eep_header_4k
*pBase
= &eep
->baseEepHeader
;
201 ver_minor
= pBase
->version
& AR5416_EEP_VER_MINOR_MASK
;
205 return pModal
->noiseFloorThreshCh
[0];
207 return get_unaligned_be16(pBase
->macAddr
);
209 return get_unaligned_be16(pBase
->macAddr
+ 2);
211 return get_unaligned_be16(pBase
->macAddr
+ 4);
213 return pBase
->regDmn
[0];
215 return pBase
->regDmn
[1];
217 return pBase
->deviceCap
;
219 return pBase
->opCapFlags
;
221 return pBase
->rfSilent
;
225 return pModal
->db1_1
;
229 return pBase
->txMask
;
231 return pBase
->rxMask
;
234 case EEP_PWR_TABLE_OFFSET
:
235 return AR5416_PWR_TABLE_OFFSET_DB
;
237 return pModal
->version
;
238 case EEP_ANT_DIV_CTL1
:
239 return pModal
->antdiv_ctl1
;
240 case EEP_TXGAIN_TYPE
:
241 if (ver_minor
>= AR5416_EEP_MINOR_VER_19
)
242 return pBase
->txGainType
;
244 return AR5416_EEP_TXGAIN_ORIGINAL
;
250 static void ath9k_hw_set_4k_power_cal_table(struct ath_hw
*ah
,
251 struct ath9k_channel
*chan
,
252 int16_t *pTxPowerIndexOffset
)
254 struct ath_common
*common
= ath9k_hw_common(ah
);
255 struct ar5416_eeprom_4k
*pEepData
= &ah
->eeprom
.map4k
;
256 struct cal_data_per_freq_4k
*pRawDataset
;
257 u8
*pCalBChans
= NULL
;
258 u16 pdGainOverlap_t2
;
259 static u8 pdadcValues
[AR5416_NUM_PDADC_VALUES
];
260 u16 gainBoundaries
[AR5416_PD_GAINS_IN_MASK
];
262 u16 numXpdGain
, xpdMask
;
263 u16 xpdGainValues
[AR5416_EEP4K_NUM_PD_GAINS
] = { 0, 0 };
264 u32 reg32
, regOffset
, regChainOffset
;
266 xpdMask
= pEepData
->modalHeader
.xpdGain
;
268 if ((pEepData
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
269 AR5416_EEP_MINOR_VER_2
) {
271 pEepData
->modalHeader
.pdGainOverlap
;
273 pdGainOverlap_t2
= (u16
)(MS(REG_READ(ah
, AR_PHY_TPCRG5
),
274 AR_PHY_TPCRG5_PD_GAIN_OVERLAP
));
277 pCalBChans
= pEepData
->calFreqPier2G
;
278 numPiers
= AR5416_EEP4K_NUM_2G_CAL_PIERS
;
282 for (i
= 1; i
<= AR5416_PD_GAINS_IN_MASK
; i
++) {
283 if ((xpdMask
>> (AR5416_PD_GAINS_IN_MASK
- i
)) & 1) {
284 if (numXpdGain
>= AR5416_EEP4K_NUM_PD_GAINS
)
286 xpdGainValues
[numXpdGain
] =
287 (u16
)(AR5416_PD_GAINS_IN_MASK
- i
);
292 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_NUM_PD_GAIN
,
293 (numXpdGain
- 1) & 0x3);
294 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_1
,
296 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_2
,
298 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_3
, 0);
300 for (i
= 0; i
< AR5416_EEP4K_MAX_CHAINS
; i
++) {
301 if (AR_SREV_5416_20_OR_LATER(ah
) &&
302 (ah
->rxchainmask
== 5 || ah
->txchainmask
== 5) &&
304 regChainOffset
= (i
== 1) ? 0x2000 : 0x1000;
306 regChainOffset
= i
* 0x1000;
308 if (pEepData
->baseEepHeader
.txMask
& (1 << i
)) {
309 pRawDataset
= pEepData
->calPierData2G
[i
];
311 ath9k_hw_get_gain_boundaries_pdadcs(ah
, chan
,
312 pRawDataset
, pCalBChans
,
313 numPiers
, pdGainOverlap_t2
,
315 pdadcValues
, numXpdGain
);
317 ENABLE_REGWRITE_BUFFER(ah
);
319 if ((i
== 0) || AR_SREV_5416_20_OR_LATER(ah
)) {
320 REG_WRITE(ah
, AR_PHY_TPCRG5
+ regChainOffset
,
322 AR_PHY_TPCRG5_PD_GAIN_OVERLAP
)
323 | SM(gainBoundaries
[0],
324 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1
)
325 | SM(gainBoundaries
[1],
326 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2
)
327 | SM(gainBoundaries
[2],
328 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3
)
329 | SM(gainBoundaries
[3],
330 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4
));
333 regOffset
= AR_PHY_BASE
+ (672 << 2) + regChainOffset
;
334 for (j
= 0; j
< 32; j
++) {
335 reg32
= get_unaligned_le32(&pdadcValues
[4 * j
]);
336 REG_WRITE(ah
, regOffset
, reg32
);
338 ath_dbg(common
, ATH_DBG_EEPROM
,
339 "PDADC (%d,%4x): %4.4x %8.8x\n",
340 i
, regChainOffset
, regOffset
,
342 ath_dbg(common
, ATH_DBG_EEPROM
,
344 "PDADC %3d Value %3d | "
345 "PDADC %3d Value %3d | "
346 "PDADC %3d Value %3d | "
347 "PDADC %3d Value %3d |\n",
348 i
, 4 * j
, pdadcValues
[4 * j
],
349 4 * j
+ 1, pdadcValues
[4 * j
+ 1],
350 4 * j
+ 2, pdadcValues
[4 * j
+ 2],
351 4 * j
+ 3, pdadcValues
[4 * j
+ 3]);
356 REGWRITE_BUFFER_FLUSH(ah
);
360 *pTxPowerIndexOffset
= 0;
363 static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw
*ah
,
364 struct ath9k_channel
*chan
,
367 u16 AntennaReduction
,
368 u16 twiceMaxRegulatoryPower
,
371 #define CMP_TEST_GRP \
372 (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) == \
373 pEepData->ctlIndex[i]) \
374 || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
375 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
377 struct ath_regulatory
*regulatory
= ath9k_hw_regulatory(ah
);
379 int16_t twiceLargestAntenna
;
380 u16 twiceMinEdgePower
;
381 u16 twiceMaxEdgePower
= MAX_RATE_POWER
;
382 u16 scaledPower
= 0, minCtlPower
, maxRegAllowedPower
;
386 struct chan_centers centers
;
387 struct cal_ctl_data_4k
*rep
;
388 struct ar5416_eeprom_4k
*pEepData
= &ah
->eeprom
.map4k
;
389 static const u16 tpScaleReductionTable
[5] =
390 { 0, 3, 6, 9, MAX_RATE_POWER
};
391 struct cal_target_power_leg targetPowerOfdm
, targetPowerCck
= {
394 struct cal_target_power_leg targetPowerOfdmExt
= {
395 0, { 0, 0, 0, 0} }, targetPowerCckExt
= {
398 struct cal_target_power_ht targetPowerHt20
, targetPowerHt40
= {
401 static const u16 ctlModesFor11g
[] = {
402 CTL_11B
, CTL_11G
, CTL_2GHT20
,
403 CTL_11B_EXT
, CTL_11G_EXT
, CTL_2GHT40
406 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
408 twiceLargestAntenna
= pEepData
->modalHeader
.antennaGainCh
[0];
409 twiceLargestAntenna
= (int16_t)min(AntennaReduction
-
410 twiceLargestAntenna
, 0);
412 maxRegAllowedPower
= twiceMaxRegulatoryPower
+ twiceLargestAntenna
;
413 if (regulatory
->tp_scale
!= ATH9K_TP_SCALE_MAX
) {
414 maxRegAllowedPower
-=
415 (tpScaleReductionTable
[(regulatory
->tp_scale
)] * 2);
418 scaledPower
= min(powerLimit
, maxRegAllowedPower
);
419 scaledPower
= max((u16
)0, scaledPower
);
421 numCtlModes
= ARRAY_SIZE(ctlModesFor11g
) - SUB_NUM_CTL_MODES_AT_2G_40
;
422 pCtlMode
= ctlModesFor11g
;
424 ath9k_hw_get_legacy_target_powers(ah
, chan
,
425 pEepData
->calTargetPowerCck
,
426 AR5416_NUM_2G_CCK_TARGET_POWERS
,
427 &targetPowerCck
, 4, false);
428 ath9k_hw_get_legacy_target_powers(ah
, chan
,
429 pEepData
->calTargetPower2G
,
430 AR5416_NUM_2G_20_TARGET_POWERS
,
431 &targetPowerOfdm
, 4, false);
432 ath9k_hw_get_target_powers(ah
, chan
,
433 pEepData
->calTargetPower2GHT20
,
434 AR5416_NUM_2G_20_TARGET_POWERS
,
435 &targetPowerHt20
, 8, false);
437 if (IS_CHAN_HT40(chan
)) {
438 numCtlModes
= ARRAY_SIZE(ctlModesFor11g
);
439 ath9k_hw_get_target_powers(ah
, chan
,
440 pEepData
->calTargetPower2GHT40
,
441 AR5416_NUM_2G_40_TARGET_POWERS
,
442 &targetPowerHt40
, 8, true);
443 ath9k_hw_get_legacy_target_powers(ah
, chan
,
444 pEepData
->calTargetPowerCck
,
445 AR5416_NUM_2G_CCK_TARGET_POWERS
,
446 &targetPowerCckExt
, 4, true);
447 ath9k_hw_get_legacy_target_powers(ah
, chan
,
448 pEepData
->calTargetPower2G
,
449 AR5416_NUM_2G_20_TARGET_POWERS
,
450 &targetPowerOfdmExt
, 4, true);
453 for (ctlMode
= 0; ctlMode
< numCtlModes
; ctlMode
++) {
454 bool isHt40CtlMode
= (pCtlMode
[ctlMode
] == CTL_5GHT40
) ||
455 (pCtlMode
[ctlMode
] == CTL_2GHT40
);
458 freq
= centers
.synth_center
;
459 else if (pCtlMode
[ctlMode
] & EXT_ADDITIVE
)
460 freq
= centers
.ext_center
;
462 freq
= centers
.ctl_center
;
464 if (ah
->eep_ops
->get_eeprom_ver(ah
) == 14 &&
465 ah
->eep_ops
->get_eeprom_rev(ah
) <= 2)
466 twiceMaxEdgePower
= MAX_RATE_POWER
;
468 for (i
= 0; (i
< AR5416_EEP4K_NUM_CTLS
) &&
469 pEepData
->ctlIndex
[i
]; i
++) {
472 rep
= &(pEepData
->ctlData
[i
]);
474 twiceMinEdgePower
= ath9k_hw_get_max_edge_power(
477 ar5416_get_ntxchains(ah
->txchainmask
) - 1],
479 AR5416_EEP4K_NUM_BAND_EDGES
);
481 if ((cfgCtl
& ~CTL_MODE_M
) == SD_NO_CTL
) {
483 min(twiceMaxEdgePower
,
486 twiceMaxEdgePower
= twiceMinEdgePower
;
492 minCtlPower
= (u8
)min(twiceMaxEdgePower
, scaledPower
);
494 switch (pCtlMode
[ctlMode
]) {
496 for (i
= 0; i
< ARRAY_SIZE(targetPowerCck
.tPow2x
); i
++) {
497 targetPowerCck
.tPow2x
[i
] =
498 min((u16
)targetPowerCck
.tPow2x
[i
],
503 for (i
= 0; i
< ARRAY_SIZE(targetPowerOfdm
.tPow2x
); i
++) {
504 targetPowerOfdm
.tPow2x
[i
] =
505 min((u16
)targetPowerOfdm
.tPow2x
[i
],
510 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt20
.tPow2x
); i
++) {
511 targetPowerHt20
.tPow2x
[i
] =
512 min((u16
)targetPowerHt20
.tPow2x
[i
],
517 targetPowerCckExt
.tPow2x
[0] =
518 min((u16
)targetPowerCckExt
.tPow2x
[0],
522 targetPowerOfdmExt
.tPow2x
[0] =
523 min((u16
)targetPowerOfdmExt
.tPow2x
[0],
527 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt40
.tPow2x
); i
++) {
528 targetPowerHt40
.tPow2x
[i
] =
529 min((u16
)targetPowerHt40
.tPow2x
[i
],
538 ratesArray
[rate6mb
] =
539 ratesArray
[rate9mb
] =
540 ratesArray
[rate12mb
] =
541 ratesArray
[rate18mb
] =
542 ratesArray
[rate24mb
] =
543 targetPowerOfdm
.tPow2x
[0];
545 ratesArray
[rate36mb
] = targetPowerOfdm
.tPow2x
[1];
546 ratesArray
[rate48mb
] = targetPowerOfdm
.tPow2x
[2];
547 ratesArray
[rate54mb
] = targetPowerOfdm
.tPow2x
[3];
548 ratesArray
[rateXr
] = targetPowerOfdm
.tPow2x
[0];
550 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt20
.tPow2x
); i
++)
551 ratesArray
[rateHt20_0
+ i
] = targetPowerHt20
.tPow2x
[i
];
553 ratesArray
[rate1l
] = targetPowerCck
.tPow2x
[0];
554 ratesArray
[rate2s
] = ratesArray
[rate2l
] = targetPowerCck
.tPow2x
[1];
555 ratesArray
[rate5_5s
] = ratesArray
[rate5_5l
] = targetPowerCck
.tPow2x
[2];
556 ratesArray
[rate11s
] = ratesArray
[rate11l
] = targetPowerCck
.tPow2x
[3];
558 if (IS_CHAN_HT40(chan
)) {
559 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt40
.tPow2x
); i
++) {
560 ratesArray
[rateHt40_0
+ i
] =
561 targetPowerHt40
.tPow2x
[i
];
563 ratesArray
[rateDupOfdm
] = targetPowerHt40
.tPow2x
[0];
564 ratesArray
[rateDupCck
] = targetPowerHt40
.tPow2x
[0];
565 ratesArray
[rateExtOfdm
] = targetPowerOfdmExt
.tPow2x
[0];
566 ratesArray
[rateExtCck
] = targetPowerCckExt
.tPow2x
[0];
572 static void ath9k_hw_4k_set_txpower(struct ath_hw
*ah
,
573 struct ath9k_channel
*chan
,
575 u8 twiceAntennaReduction
,
576 u8 twiceMaxRegulatoryPower
,
577 u8 powerLimit
, bool test
)
579 struct ath_regulatory
*regulatory
= ath9k_hw_regulatory(ah
);
580 struct ar5416_eeprom_4k
*pEepData
= &ah
->eeprom
.map4k
;
581 struct modal_eep_4k_header
*pModal
= &pEepData
->modalHeader
;
582 int16_t ratesArray
[Ar5416RateSize
];
583 int16_t txPowerIndexOffset
= 0;
584 u8 ht40PowerIncForPdadc
= 2;
587 memset(ratesArray
, 0, sizeof(ratesArray
));
589 if ((pEepData
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
590 AR5416_EEP_MINOR_VER_2
) {
591 ht40PowerIncForPdadc
= pModal
->ht40PowerIncForPdadc
;
594 ath9k_hw_set_4k_power_per_rate_table(ah
, chan
,
595 &ratesArray
[0], cfgCtl
,
596 twiceAntennaReduction
,
597 twiceMaxRegulatoryPower
,
600 ath9k_hw_set_4k_power_cal_table(ah
, chan
, &txPowerIndexOffset
);
602 regulatory
->max_power_level
= 0;
603 for (i
= 0; i
< ARRAY_SIZE(ratesArray
); i
++) {
604 ratesArray
[i
] = (int16_t)(txPowerIndexOffset
+ ratesArray
[i
]);
605 if (ratesArray
[i
] > MAX_RATE_POWER
)
606 ratesArray
[i
] = MAX_RATE_POWER
;
608 if (ratesArray
[i
] > regulatory
->max_power_level
)
609 regulatory
->max_power_level
= ratesArray
[i
];
615 /* Update regulatory */
617 if (IS_CHAN_HT40(chan
))
619 else if (IS_CHAN_HT20(chan
))
622 regulatory
->max_power_level
= ratesArray
[i
];
624 if (AR_SREV_9280_20_OR_LATER(ah
)) {
625 for (i
= 0; i
< Ar5416RateSize
; i
++)
626 ratesArray
[i
] -= AR5416_PWR_TABLE_OFFSET_DB
* 2;
629 ENABLE_REGWRITE_BUFFER(ah
);
631 /* OFDM power per rate */
632 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE1
,
633 ATH9K_POW_SM(ratesArray
[rate18mb
], 24)
634 | ATH9K_POW_SM(ratesArray
[rate12mb
], 16)
635 | ATH9K_POW_SM(ratesArray
[rate9mb
], 8)
636 | ATH9K_POW_SM(ratesArray
[rate6mb
], 0));
637 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE2
,
638 ATH9K_POW_SM(ratesArray
[rate54mb
], 24)
639 | ATH9K_POW_SM(ratesArray
[rate48mb
], 16)
640 | ATH9K_POW_SM(ratesArray
[rate36mb
], 8)
641 | ATH9K_POW_SM(ratesArray
[rate24mb
], 0));
643 /* CCK power per rate */
644 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE3
,
645 ATH9K_POW_SM(ratesArray
[rate2s
], 24)
646 | ATH9K_POW_SM(ratesArray
[rate2l
], 16)
647 | ATH9K_POW_SM(ratesArray
[rateXr
], 8)
648 | ATH9K_POW_SM(ratesArray
[rate1l
], 0));
649 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE4
,
650 ATH9K_POW_SM(ratesArray
[rate11s
], 24)
651 | ATH9K_POW_SM(ratesArray
[rate11l
], 16)
652 | ATH9K_POW_SM(ratesArray
[rate5_5s
], 8)
653 | ATH9K_POW_SM(ratesArray
[rate5_5l
], 0));
655 /* HT20 power per rate */
656 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE5
,
657 ATH9K_POW_SM(ratesArray
[rateHt20_3
], 24)
658 | ATH9K_POW_SM(ratesArray
[rateHt20_2
], 16)
659 | ATH9K_POW_SM(ratesArray
[rateHt20_1
], 8)
660 | ATH9K_POW_SM(ratesArray
[rateHt20_0
], 0));
661 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE6
,
662 ATH9K_POW_SM(ratesArray
[rateHt20_7
], 24)
663 | ATH9K_POW_SM(ratesArray
[rateHt20_6
], 16)
664 | ATH9K_POW_SM(ratesArray
[rateHt20_5
], 8)
665 | ATH9K_POW_SM(ratesArray
[rateHt20_4
], 0));
667 /* HT40 power per rate */
668 if (IS_CHAN_HT40(chan
)) {
669 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE7
,
670 ATH9K_POW_SM(ratesArray
[rateHt40_3
] +
671 ht40PowerIncForPdadc
, 24)
672 | ATH9K_POW_SM(ratesArray
[rateHt40_2
] +
673 ht40PowerIncForPdadc
, 16)
674 | ATH9K_POW_SM(ratesArray
[rateHt40_1
] +
675 ht40PowerIncForPdadc
, 8)
676 | ATH9K_POW_SM(ratesArray
[rateHt40_0
] +
677 ht40PowerIncForPdadc
, 0));
678 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE8
,
679 ATH9K_POW_SM(ratesArray
[rateHt40_7
] +
680 ht40PowerIncForPdadc
, 24)
681 | ATH9K_POW_SM(ratesArray
[rateHt40_6
] +
682 ht40PowerIncForPdadc
, 16)
683 | ATH9K_POW_SM(ratesArray
[rateHt40_5
] +
684 ht40PowerIncForPdadc
, 8)
685 | ATH9K_POW_SM(ratesArray
[rateHt40_4
] +
686 ht40PowerIncForPdadc
, 0));
687 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE9
,
688 ATH9K_POW_SM(ratesArray
[rateExtOfdm
], 24)
689 | ATH9K_POW_SM(ratesArray
[rateExtCck
], 16)
690 | ATH9K_POW_SM(ratesArray
[rateDupOfdm
], 8)
691 | ATH9K_POW_SM(ratesArray
[rateDupCck
], 0));
694 REGWRITE_BUFFER_FLUSH(ah
);
697 static void ath9k_hw_4k_set_addac(struct ath_hw
*ah
,
698 struct ath9k_channel
*chan
)
700 struct modal_eep_4k_header
*pModal
;
701 struct ar5416_eeprom_4k
*eep
= &ah
->eeprom
.map4k
;
704 if (ah
->hw_version
.macVersion
!= AR_SREV_VERSION_9160
)
707 if (ah
->eep_ops
->get_eeprom_rev(ah
) < AR5416_EEP_MINOR_VER_7
)
710 pModal
= &eep
->modalHeader
;
712 if (pModal
->xpaBiasLvl
!= 0xff) {
713 biaslevel
= pModal
->xpaBiasLvl
;
714 INI_RA(&ah
->iniAddac
, 7, 1) =
715 (INI_RA(&ah
->iniAddac
, 7, 1) & (~0x18)) | biaslevel
<< 3;
719 static void ath9k_hw_4k_set_gain(struct ath_hw
*ah
,
720 struct modal_eep_4k_header
*pModal
,
721 struct ar5416_eeprom_4k
*eep
,
724 REG_WRITE(ah
, AR_PHY_SWITCH_CHAIN_0
,
725 pModal
->antCtrlChain
[0]);
727 REG_WRITE(ah
, AR_PHY_TIMING_CTRL4(0),
728 (REG_READ(ah
, AR_PHY_TIMING_CTRL4(0)) &
729 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
|
730 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
)) |
731 SM(pModal
->iqCalICh
[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
) |
732 SM(pModal
->iqCalQCh
[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
));
734 if ((eep
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
735 AR5416_EEP_MINOR_VER_3
) {
736 txRxAttenLocal
= pModal
->txRxAttenCh
[0];
738 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
,
739 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN
, pModal
->bswMargin
[0]);
740 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
,
741 AR_PHY_GAIN_2GHZ_XATTEN1_DB
, pModal
->bswAtten
[0]);
742 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
,
743 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN
,
744 pModal
->xatten2Margin
[0]);
745 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
,
746 AR_PHY_GAIN_2GHZ_XATTEN2_DB
, pModal
->xatten2Db
[0]);
748 /* Set the block 1 value to block 0 value */
749 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000,
750 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN
,
751 pModal
->bswMargin
[0]);
752 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000,
753 AR_PHY_GAIN_2GHZ_XATTEN1_DB
, pModal
->bswAtten
[0]);
754 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000,
755 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN
,
756 pModal
->xatten2Margin
[0]);
757 REG_RMW_FIELD(ah
, AR_PHY_GAIN_2GHZ
+ 0x1000,
758 AR_PHY_GAIN_2GHZ_XATTEN2_DB
,
759 pModal
->xatten2Db
[0]);
762 REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
,
763 AR9280_PHY_RXGAIN_TXRX_ATTEN
, txRxAttenLocal
);
764 REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
,
765 AR9280_PHY_RXGAIN_TXRX_MARGIN
, pModal
->rxTxMarginCh
[0]);
767 REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
+ 0x1000,
768 AR9280_PHY_RXGAIN_TXRX_ATTEN
, txRxAttenLocal
);
769 REG_RMW_FIELD(ah
, AR_PHY_RXGAIN
+ 0x1000,
770 AR9280_PHY_RXGAIN_TXRX_MARGIN
, pModal
->rxTxMarginCh
[0]);
774 * Read EEPROM header info and program the device for correct operation
775 * given the channel value.
777 static void ath9k_hw_4k_set_board_values(struct ath_hw
*ah
,
778 struct ath9k_channel
*chan
)
780 struct modal_eep_4k_header
*pModal
;
781 struct ar5416_eeprom_4k
*eep
= &ah
->eeprom
.map4k
;
782 struct base_eep_header_4k
*pBase
= &eep
->baseEepHeader
;
784 u8 ob
[5], db1
[5], db2
[5];
785 u8 ant_div_control1
, ant_div_control2
;
788 pModal
= &eep
->modalHeader
;
791 REG_WRITE(ah
, AR_PHY_SWITCH_COM
, pModal
->antCtrlCommon
);
793 /* Single chain for 4K EEPROM*/
794 ath9k_hw_4k_set_gain(ah
, pModal
, eep
, txRxAttenLocal
);
796 /* Initialize Ant Diversity settings from EEPROM */
797 if (pModal
->version
>= 3) {
798 ant_div_control1
= pModal
->antdiv_ctl1
;
799 ant_div_control2
= pModal
->antdiv_ctl2
;
801 regVal
= REG_READ(ah
, AR_PHY_MULTICHAIN_GAIN_CTL
);
802 regVal
&= (~(AR_PHY_9285_ANT_DIV_CTL_ALL
));
804 regVal
|= SM(ant_div_control1
,
805 AR_PHY_9285_ANT_DIV_CTL
);
806 regVal
|= SM(ant_div_control2
,
807 AR_PHY_9285_ANT_DIV_ALT_LNACONF
);
808 regVal
|= SM((ant_div_control2
>> 2),
809 AR_PHY_9285_ANT_DIV_MAIN_LNACONF
);
810 regVal
|= SM((ant_div_control1
>> 1),
811 AR_PHY_9285_ANT_DIV_ALT_GAINTB
);
812 regVal
|= SM((ant_div_control1
>> 2),
813 AR_PHY_9285_ANT_DIV_MAIN_GAINTB
);
816 REG_WRITE(ah
, AR_PHY_MULTICHAIN_GAIN_CTL
, regVal
);
817 regVal
= REG_READ(ah
, AR_PHY_MULTICHAIN_GAIN_CTL
);
818 regVal
= REG_READ(ah
, AR_PHY_CCK_DETECT
);
819 regVal
&= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV
);
820 regVal
|= SM((ant_div_control1
>> 3),
821 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV
);
823 REG_WRITE(ah
, AR_PHY_CCK_DETECT
, regVal
);
824 regVal
= REG_READ(ah
, AR_PHY_CCK_DETECT
);
827 if (pModal
->version
>= 2) {
828 ob
[0] = pModal
->ob_0
;
829 ob
[1] = pModal
->ob_1
;
830 ob
[2] = pModal
->ob_2
;
831 ob
[3] = pModal
->ob_3
;
832 ob
[4] = pModal
->ob_4
;
834 db1
[0] = pModal
->db1_0
;
835 db1
[1] = pModal
->db1_1
;
836 db1
[2] = pModal
->db1_2
;
837 db1
[3] = pModal
->db1_3
;
838 db1
[4] = pModal
->db1_4
;
840 db2
[0] = pModal
->db2_0
;
841 db2
[1] = pModal
->db2_1
;
842 db2
[2] = pModal
->db2_2
;
843 db2
[3] = pModal
->db2_3
;
844 db2
[4] = pModal
->db2_4
;
845 } else if (pModal
->version
== 1) {
846 ob
[0] = pModal
->ob_0
;
847 ob
[1] = ob
[2] = ob
[3] = ob
[4] = pModal
->ob_1
;
848 db1
[0] = pModal
->db1_0
;
849 db1
[1] = db1
[2] = db1
[3] = db1
[4] = pModal
->db1_1
;
850 db2
[0] = pModal
->db2_0
;
851 db2
[1] = db2
[2] = db2
[3] = db2
[4] = pModal
->db2_1
;
855 for (i
= 0; i
< 5; i
++) {
856 ob
[i
] = pModal
->ob_0
;
857 db1
[i
] = pModal
->db1_0
;
858 db2
[i
] = pModal
->db1_0
;
862 if (AR_SREV_9271(ah
)) {
863 ath9k_hw_analog_shift_rmw(ah
,
865 AR9271_AN_RF2G3_OB_cck
,
866 AR9271_AN_RF2G3_OB_cck_S
,
868 ath9k_hw_analog_shift_rmw(ah
,
870 AR9271_AN_RF2G3_OB_psk
,
871 AR9271_AN_RF2G3_OB_psk_S
,
873 ath9k_hw_analog_shift_rmw(ah
,
875 AR9271_AN_RF2G3_OB_qam
,
876 AR9271_AN_RF2G3_OB_qam_S
,
878 ath9k_hw_analog_shift_rmw(ah
,
880 AR9271_AN_RF2G3_DB_1
,
881 AR9271_AN_RF2G3_DB_1_S
,
883 ath9k_hw_analog_shift_rmw(ah
,
885 AR9271_AN_RF2G4_DB_2
,
886 AR9271_AN_RF2G4_DB_2_S
,
889 ath9k_hw_analog_shift_rmw(ah
,
891 AR9285_AN_RF2G3_OB_0
,
892 AR9285_AN_RF2G3_OB_0_S
,
894 ath9k_hw_analog_shift_rmw(ah
,
896 AR9285_AN_RF2G3_OB_1
,
897 AR9285_AN_RF2G3_OB_1_S
,
899 ath9k_hw_analog_shift_rmw(ah
,
901 AR9285_AN_RF2G3_OB_2
,
902 AR9285_AN_RF2G3_OB_2_S
,
904 ath9k_hw_analog_shift_rmw(ah
,
906 AR9285_AN_RF2G3_OB_3
,
907 AR9285_AN_RF2G3_OB_3_S
,
909 ath9k_hw_analog_shift_rmw(ah
,
911 AR9285_AN_RF2G3_OB_4
,
912 AR9285_AN_RF2G3_OB_4_S
,
915 ath9k_hw_analog_shift_rmw(ah
,
917 AR9285_AN_RF2G3_DB1_0
,
918 AR9285_AN_RF2G3_DB1_0_S
,
920 ath9k_hw_analog_shift_rmw(ah
,
922 AR9285_AN_RF2G3_DB1_1
,
923 AR9285_AN_RF2G3_DB1_1_S
,
925 ath9k_hw_analog_shift_rmw(ah
,
927 AR9285_AN_RF2G3_DB1_2
,
928 AR9285_AN_RF2G3_DB1_2_S
,
930 ath9k_hw_analog_shift_rmw(ah
,
932 AR9285_AN_RF2G4_DB1_3
,
933 AR9285_AN_RF2G4_DB1_3_S
,
935 ath9k_hw_analog_shift_rmw(ah
,
937 AR9285_AN_RF2G4_DB1_4
,
938 AR9285_AN_RF2G4_DB1_4_S
, db1
[4]);
940 ath9k_hw_analog_shift_rmw(ah
,
942 AR9285_AN_RF2G4_DB2_0
,
943 AR9285_AN_RF2G4_DB2_0_S
,
945 ath9k_hw_analog_shift_rmw(ah
,
947 AR9285_AN_RF2G4_DB2_1
,
948 AR9285_AN_RF2G4_DB2_1_S
,
950 ath9k_hw_analog_shift_rmw(ah
,
952 AR9285_AN_RF2G4_DB2_2
,
953 AR9285_AN_RF2G4_DB2_2_S
,
955 ath9k_hw_analog_shift_rmw(ah
,
957 AR9285_AN_RF2G4_DB2_3
,
958 AR9285_AN_RF2G4_DB2_3_S
,
960 ath9k_hw_analog_shift_rmw(ah
,
962 AR9285_AN_RF2G4_DB2_4
,
963 AR9285_AN_RF2G4_DB2_4_S
,
968 REG_RMW_FIELD(ah
, AR_PHY_SETTLING
, AR_PHY_SETTLING_SWITCH
,
969 pModal
->switchSettling
);
970 REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
, AR_PHY_DESIRED_SZ_ADC
,
971 pModal
->adcDesiredSize
);
973 REG_WRITE(ah
, AR_PHY_RF_CTL4
,
974 SM(pModal
->txEndToXpaOff
, AR_PHY_RF_CTL4_TX_END_XPAA_OFF
) |
975 SM(pModal
->txEndToXpaOff
, AR_PHY_RF_CTL4_TX_END_XPAB_OFF
) |
976 SM(pModal
->txFrameToXpaOn
, AR_PHY_RF_CTL4_FRAME_XPAA_ON
) |
977 SM(pModal
->txFrameToXpaOn
, AR_PHY_RF_CTL4_FRAME_XPAB_ON
));
979 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL3
, AR_PHY_TX_END_TO_A2_RX_ON
,
980 pModal
->txEndToRxOn
);
982 if (AR_SREV_9271_10(ah
))
983 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL3
, AR_PHY_TX_END_TO_A2_RX_ON
,
984 pModal
->txEndToRxOn
);
985 REG_RMW_FIELD(ah
, AR_PHY_CCA
, AR9280_PHY_CCA_THRESH62
,
987 REG_RMW_FIELD(ah
, AR_PHY_EXT_CCA0
, AR_PHY_EXT_CCA0_THRESH62
,
990 if ((eep
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
991 AR5416_EEP_MINOR_VER_2
) {
992 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
, AR_PHY_TX_END_DATA_START
,
993 pModal
->txFrameToDataStart
);
994 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
, AR_PHY_TX_END_PA_ON
,
995 pModal
->txFrameToPaOn
);
998 if ((eep
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
999 AR5416_EEP_MINOR_VER_3
) {
1000 if (IS_CHAN_HT40(chan
))
1001 REG_RMW_FIELD(ah
, AR_PHY_SETTLING
,
1002 AR_PHY_SETTLING_SWITCH
,
1003 pModal
->swSettleHt40
);
1005 if (AR_SREV_9271(ah
) || AR_SREV_9285(ah
)) {
1006 u8 bb_desired_scale
= (pModal
->bb_scale_smrt_antenna
&
1007 EEP_4K_BB_DESIRED_SCALE_MASK
);
1008 if ((pBase
->txGainType
== 0) && (bb_desired_scale
!= 0)) {
1009 u32 pwrctrl
, mask
, clr
;
1011 mask
= BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
1012 pwrctrl
= mask
* bb_desired_scale
;
1014 REG_RMW(ah
, AR_PHY_TX_PWRCTRL8
, pwrctrl
, clr
);
1015 REG_RMW(ah
, AR_PHY_TX_PWRCTRL10
, pwrctrl
, clr
);
1016 REG_RMW(ah
, AR_PHY_CH0_TX_PWRCTRL12
, pwrctrl
, clr
);
1018 mask
= BIT(0)|BIT(5)|BIT(15);
1019 pwrctrl
= mask
* bb_desired_scale
;
1021 REG_RMW(ah
, AR_PHY_TX_PWRCTRL9
, pwrctrl
, clr
);
1023 mask
= BIT(0)|BIT(5);
1024 pwrctrl
= mask
* bb_desired_scale
;
1026 REG_RMW(ah
, AR_PHY_CH0_TX_PWRCTRL11
, pwrctrl
, clr
);
1027 REG_RMW(ah
, AR_PHY_CH0_TX_PWRCTRL13
, pwrctrl
, clr
);
1032 static u16
ath9k_hw_4k_get_spur_channel(struct ath_hw
*ah
, u16 i
, bool is2GHz
)
1034 #define EEP_MAP4K_SPURCHAN \
1035 (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
1036 struct ath_common
*common
= ath9k_hw_common(ah
);
1038 u16 spur_val
= AR_NO_SPUR
;
1040 ath_dbg(common
, ATH_DBG_ANI
,
1041 "Getting spur idx:%d is2Ghz:%d val:%x\n",
1042 i
, is2GHz
, ah
->config
.spurchans
[i
][is2GHz
]);
1044 switch (ah
->config
.spurmode
) {
1047 case SPUR_ENABLE_IOCTL
:
1048 spur_val
= ah
->config
.spurchans
[i
][is2GHz
];
1049 ath_dbg(common
, ATH_DBG_ANI
,
1050 "Getting spur val from new loc. %d\n", spur_val
);
1052 case SPUR_ENABLE_EEPROM
:
1053 spur_val
= EEP_MAP4K_SPURCHAN
;
1059 #undef EEP_MAP4K_SPURCHAN
1062 const struct eeprom_ops eep_4k_ops
= {
1063 .check_eeprom
= ath9k_hw_4k_check_eeprom
,
1064 .get_eeprom
= ath9k_hw_4k_get_eeprom
,
1065 .fill_eeprom
= ath9k_hw_4k_fill_eeprom
,
1066 .get_eeprom_ver
= ath9k_hw_4k_get_eeprom_ver
,
1067 .get_eeprom_rev
= ath9k_hw_4k_get_eeprom_rev
,
1068 .set_board_values
= ath9k_hw_4k_set_board_values
,
1069 .set_addac
= ath9k_hw_4k_set_addac
,
1070 .set_txpower
= ath9k_hw_4k_set_txpower
,
1071 .get_spur_channel
= ath9k_hw_4k_get_spur_channel