2 * Copyright (c) 2008 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.
22 static void ath9k_hw_analog_shift_rmw(struct ath_hal
*ah
,
28 regVal
= REG_READ(ah
, reg
) & ~mask
;
29 regVal
|= (val
<< shift
) & mask
;
31 REG_WRITE(ah
, reg
, regVal
);
33 if (ah
->ah_config
.analog_shiftreg
)
39 static inline u16
ath9k_hw_fbin2freq(u8 fbin
, bool is2GHz
)
42 if (fbin
== AR5416_BCHAN_UNUSED
)
45 return (u16
) ((is2GHz
) ? (2300 + fbin
) : (4800 + 5 * fbin
));
48 static inline int16_t ath9k_hw_interpolate(u16 target
,
49 u16 srcLeft
, u16 srcRight
,
55 if (srcRight
== srcLeft
) {
58 rv
= (int16_t) (((target
- srcLeft
) * targetRight
+
59 (srcRight
- target
) * targetLeft
) /
60 (srcRight
- srcLeft
));
65 static inline bool ath9k_hw_get_lower_upper_index(u8 target
, u8
*pList
,
66 u16 listSize
, u16
*indexL
,
71 if (target
<= pList
[0]) {
72 *indexL
= *indexR
= 0;
75 if (target
>= pList
[listSize
- 1]) {
76 *indexL
= *indexR
= (u16
) (listSize
- 1);
80 for (i
= 0; i
< listSize
- 1; i
++) {
81 if (pList
[i
] == target
) {
82 *indexL
= *indexR
= i
;
85 if (target
< pList
[i
+ 1]) {
87 *indexR
= (u16
) (i
+ 1);
94 static bool ath9k_hw_eeprom_read(struct ath_hal
*ah
, u32 off
, u16
*data
)
96 (void)REG_READ(ah
, AR5416_EEPROM_OFFSET
+ (off
<< AR5416_EEPROM_S
));
98 if (!ath9k_hw_wait(ah
,
99 AR_EEPROM_STATUS_DATA
,
100 AR_EEPROM_STATUS_DATA_BUSY
|
101 AR_EEPROM_STATUS_DATA_PROT_ACCESS
, 0)) {
105 *data
= MS(REG_READ(ah
, AR_EEPROM_STATUS_DATA
),
106 AR_EEPROM_STATUS_DATA_VAL
);
111 static int ath9k_hw_flash_map(struct ath_hal
*ah
)
113 struct ath_hal_5416
*ahp
= AH5416(ah
);
115 ahp
->ah_cal_mem
= ioremap(AR5416_EEPROM_START_ADDR
, AR5416_EEPROM_MAX
);
117 if (!ahp
->ah_cal_mem
) {
118 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
119 "%s: cannot remap eeprom region \n", __func__
);
126 static bool ath9k_hw_flash_read(struct ath_hal
*ah
, u32 off
, u16
*data
)
128 struct ath_hal_5416
*ahp
= AH5416(ah
);
130 *data
= ioread16(ahp
->ah_cal_mem
+ off
);
135 static inline bool ath9k_hw_nvram_read(struct ath_hal
*ah
, u32 off
, u16
*data
)
137 if (ath9k_hw_use_flash(ah
))
138 return ath9k_hw_flash_read(ah
, off
, data
);
140 return ath9k_hw_eeprom_read(ah
, off
, data
);
143 static bool ath9k_hw_fill_eeprom(struct ath_hal
*ah
)
145 struct ath_hal_5416
*ahp
= AH5416(ah
);
146 struct ar5416_eeprom
*eep
= &ahp
->ah_eeprom
;
148 int addr
, ar5416_eep_start_loc
= 0;
150 if (!ath9k_hw_use_flash(ah
)) {
151 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
152 "%s: Reading from EEPROM, not flash\n", __func__
);
153 ar5416_eep_start_loc
= 256;
156 if (AR_SREV_9100(ah
))
157 ar5416_eep_start_loc
= 256;
159 eep_data
= (u16
*)eep
;
161 for (addr
= 0; addr
< sizeof(struct ar5416_eeprom
) / sizeof(u16
); addr
++) {
162 if (!ath9k_hw_nvram_read(ah
, addr
+ ar5416_eep_start_loc
,
164 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
165 "%s: Unable to read eeprom region \n",
174 static int ath9k_hw_check_eeprom(struct ath_hal
*ah
)
176 struct ath_hal_5416
*ahp
= AH5416(ah
);
177 struct ar5416_eeprom
*eep
=
178 (struct ar5416_eeprom
*) &ahp
->ah_eeprom
;
179 u16
*eepdata
, temp
, magic
, magic2
;
181 bool need_swap
= false;
184 if (!ath9k_hw_use_flash(ah
)) {
185 if (!ath9k_hw_nvram_read(ah
, AR5416_EEPROM_MAGIC_OFFSET
,
187 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
188 "%s: Reading Magic # failed\n", __func__
);
192 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
, "%s: Read Magic = 0x%04X\n",
195 if (magic
!= AR5416_EEPROM_MAGIC
) {
196 magic2
= swab16(magic
);
198 if (magic2
== AR5416_EEPROM_MAGIC
) {
199 size
= sizeof(struct ar5416_eeprom
);
201 eepdata
= (u16
*) (&ahp
->ah_eeprom
);
203 for (addr
= 0; addr
< size
/ sizeof(u16
); addr
++) {
204 temp
= swab16(*eepdata
);
208 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
209 "0x%04X ", *eepdata
);
211 if (((addr
+ 1) % 6) == 0)
213 ATH_DBG_EEPROM
, "\n");
216 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
217 "Invalid EEPROM Magic. "
218 "endianness mismatch.\n");
224 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
, "need_swap = %s.\n",
225 need_swap
? "True" : "False");
228 el
= swab16(ahp
->ah_eeprom
.baseEepHeader
.length
);
230 el
= ahp
->ah_eeprom
.baseEepHeader
.length
;
232 if (el
> sizeof(struct ar5416_eeprom
))
233 el
= sizeof(struct ar5416_eeprom
) / sizeof(u16
);
235 el
= el
/ sizeof(u16
);
237 eepdata
= (u16
*)(&ahp
->ah_eeprom
);
239 for (i
= 0; i
< el
; i
++)
246 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
247 "EEPROM Endianness is not native.. Changing \n");
249 word
= swab16(eep
->baseEepHeader
.length
);
250 eep
->baseEepHeader
.length
= word
;
252 word
= swab16(eep
->baseEepHeader
.checksum
);
253 eep
->baseEepHeader
.checksum
= word
;
255 word
= swab16(eep
->baseEepHeader
.version
);
256 eep
->baseEepHeader
.version
= word
;
258 word
= swab16(eep
->baseEepHeader
.regDmn
[0]);
259 eep
->baseEepHeader
.regDmn
[0] = word
;
261 word
= swab16(eep
->baseEepHeader
.regDmn
[1]);
262 eep
->baseEepHeader
.regDmn
[1] = word
;
264 word
= swab16(eep
->baseEepHeader
.rfSilent
);
265 eep
->baseEepHeader
.rfSilent
= word
;
267 word
= swab16(eep
->baseEepHeader
.blueToothOptions
);
268 eep
->baseEepHeader
.blueToothOptions
= word
;
270 word
= swab16(eep
->baseEepHeader
.deviceCap
);
271 eep
->baseEepHeader
.deviceCap
= word
;
273 for (j
= 0; j
< ARRAY_SIZE(eep
->modalHeader
); j
++) {
274 struct modal_eep_header
*pModal
=
275 &eep
->modalHeader
[j
];
276 integer
= swab32(pModal
->antCtrlCommon
);
277 pModal
->antCtrlCommon
= integer
;
279 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
280 integer
= swab32(pModal
->antCtrlChain
[i
]);
281 pModal
->antCtrlChain
[i
] = integer
;
284 for (i
= 0; i
< AR5416_EEPROM_MODAL_SPURS
; i
++) {
285 word
= swab16(pModal
->spurChans
[i
].spurChan
);
286 pModal
->spurChans
[i
].spurChan
= word
;
291 if (sum
!= 0xffff || ar5416_get_eep_ver(ahp
) != AR5416_EEP_VER
||
292 ar5416_get_eep_rev(ahp
) < AR5416_EEP_NO_BACK_VER
) {
293 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
294 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
295 sum
, ar5416_get_eep_ver(ahp
));
302 static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin
, u8 pwrMax
, u8
*pPwrList
,
303 u8
*pVpdList
, u16 numIntercepts
,
308 u16 idxL
= 0, idxR
= 0;
310 for (i
= 0; i
<= (pwrMax
- pwrMin
) / 2; i
++) {
311 ath9k_hw_get_lower_upper_index(currPwr
, pPwrList
,
312 numIntercepts
, &(idxL
),
316 if (idxL
== numIntercepts
- 1)
317 idxL
= (u16
) (numIntercepts
- 2);
318 if (pPwrList
[idxL
] == pPwrList
[idxR
])
321 k
= (u16
)(((currPwr
- pPwrList
[idxL
]) * pVpdList
[idxR
] +
322 (pPwrList
[idxR
] - currPwr
) * pVpdList
[idxL
]) /
323 (pPwrList
[idxR
] - pPwrList
[idxL
]));
324 pRetVpdList
[i
] = (u8
) k
;
331 static void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal
*ah
,
332 struct ath9k_channel
*chan
,
333 struct cal_data_per_freq
*pRawDataSet
,
334 u8
*bChans
, u16 availPiers
,
335 u16 tPdGainOverlap
, int16_t *pMinCalPower
,
336 u16
*pPdGainBoundaries
, u8
*pPDADCValues
,
341 u16 idxL
= 0, idxR
= 0, numPiers
;
342 static u8 vpdTableL
[AR5416_NUM_PD_GAINS
]
343 [AR5416_MAX_PWR_RANGE_IN_HALF_DB
];
344 static u8 vpdTableR
[AR5416_NUM_PD_GAINS
]
345 [AR5416_MAX_PWR_RANGE_IN_HALF_DB
];
346 static u8 vpdTableI
[AR5416_NUM_PD_GAINS
]
347 [AR5416_MAX_PWR_RANGE_IN_HALF_DB
];
349 u8
*pVpdL
, *pVpdR
, *pPwrL
, *pPwrR
;
350 u8 minPwrT4
[AR5416_NUM_PD_GAINS
];
351 u8 maxPwrT4
[AR5416_NUM_PD_GAINS
];
354 u16 sizeCurrVpdTable
, maxIndex
, tgtIndex
;
356 int16_t minDelta
= 0;
357 struct chan_centers centers
;
359 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
361 for (numPiers
= 0; numPiers
< availPiers
; numPiers
++) {
362 if (bChans
[numPiers
] == AR5416_BCHAN_UNUSED
)
366 match
= ath9k_hw_get_lower_upper_index((u8
)FREQ2FBIN(centers
.synth_center
,
368 bChans
, numPiers
, &idxL
, &idxR
);
371 for (i
= 0; i
< numXpdGains
; i
++) {
372 minPwrT4
[i
] = pRawDataSet
[idxL
].pwrPdg
[i
][0];
373 maxPwrT4
[i
] = pRawDataSet
[idxL
].pwrPdg
[i
][4];
374 ath9k_hw_fill_vpd_table(minPwrT4
[i
], maxPwrT4
[i
],
375 pRawDataSet
[idxL
].pwrPdg
[i
],
376 pRawDataSet
[idxL
].vpdPdg
[i
],
377 AR5416_PD_GAIN_ICEPTS
,
381 for (i
= 0; i
< numXpdGains
; i
++) {
382 pVpdL
= pRawDataSet
[idxL
].vpdPdg
[i
];
383 pPwrL
= pRawDataSet
[idxL
].pwrPdg
[i
];
384 pVpdR
= pRawDataSet
[idxR
].vpdPdg
[i
];
385 pPwrR
= pRawDataSet
[idxR
].pwrPdg
[i
];
387 minPwrT4
[i
] = max(pPwrL
[0], pPwrR
[0]);
390 min(pPwrL
[AR5416_PD_GAIN_ICEPTS
- 1],
391 pPwrR
[AR5416_PD_GAIN_ICEPTS
- 1]);
394 ath9k_hw_fill_vpd_table(minPwrT4
[i
], maxPwrT4
[i
],
396 AR5416_PD_GAIN_ICEPTS
,
398 ath9k_hw_fill_vpd_table(minPwrT4
[i
], maxPwrT4
[i
],
400 AR5416_PD_GAIN_ICEPTS
,
403 for (j
= 0; j
<= (maxPwrT4
[i
] - minPwrT4
[i
]) / 2; j
++) {
405 (u8
)(ath9k_hw_interpolate((u16
)
410 bChans
[idxL
], bChans
[idxR
],
411 vpdTableL
[i
][j
], vpdTableR
[i
][j
]));
416 *pMinCalPower
= (int16_t)(minPwrT4
[0] / 2);
420 for (i
= 0; i
< numXpdGains
; i
++) {
421 if (i
== (numXpdGains
- 1))
422 pPdGainBoundaries
[i
] =
423 (u16
)(maxPwrT4
[i
] / 2);
425 pPdGainBoundaries
[i
] =
426 (u16
)((maxPwrT4
[i
] + minPwrT4
[i
+ 1]) / 4);
428 pPdGainBoundaries
[i
] =
429 min((u16
)AR5416_MAX_RATE_POWER
, pPdGainBoundaries
[i
]);
431 if ((i
== 0) && !AR_SREV_5416_V20_OR_LATER(ah
)) {
432 minDelta
= pPdGainBoundaries
[0] - 23;
433 pPdGainBoundaries
[0] = 23;
439 if (AR_SREV_9280_10_OR_LATER(ah
))
440 ss
= (int16_t)(0 - (minPwrT4
[i
] / 2));
444 ss
= (int16_t)((pPdGainBoundaries
[i
- 1] -
446 tPdGainOverlap
+ 1 + minDelta
);
448 vpdStep
= (int16_t)(vpdTableI
[i
][1] - vpdTableI
[i
][0]);
449 vpdStep
= (int16_t)((vpdStep
< 1) ? 1 : vpdStep
);
451 while ((ss
< 0) && (k
< (AR5416_NUM_PDADC_VALUES
- 1))) {
452 tmpVal
= (int16_t)(vpdTableI
[i
][0] + ss
* vpdStep
);
453 pPDADCValues
[k
++] = (u8
)((tmpVal
< 0) ? 0 : tmpVal
);
457 sizeCurrVpdTable
= (u8
) ((maxPwrT4
[i
] - minPwrT4
[i
]) / 2 + 1);
458 tgtIndex
= (u8
)(pPdGainBoundaries
[i
] + tPdGainOverlap
-
460 maxIndex
= (tgtIndex
< sizeCurrVpdTable
) ?
461 tgtIndex
: sizeCurrVpdTable
;
463 while ((ss
< maxIndex
) && (k
< (AR5416_NUM_PDADC_VALUES
- 1))) {
464 pPDADCValues
[k
++] = vpdTableI
[i
][ss
++];
467 vpdStep
= (int16_t)(vpdTableI
[i
][sizeCurrVpdTable
- 1] -
468 vpdTableI
[i
][sizeCurrVpdTable
- 2]);
469 vpdStep
= (int16_t)((vpdStep
< 1) ? 1 : vpdStep
);
471 if (tgtIndex
> maxIndex
) {
472 while ((ss
<= tgtIndex
) &&
473 (k
< (AR5416_NUM_PDADC_VALUES
- 1))) {
474 tmpVal
= (int16_t)((vpdTableI
[i
][sizeCurrVpdTable
- 1] +
475 (ss
- maxIndex
+ 1) * vpdStep
));
476 pPDADCValues
[k
++] = (u8
)((tmpVal
> 255) ?
483 while (i
< AR5416_PD_GAINS_IN_MASK
) {
484 pPdGainBoundaries
[i
] = pPdGainBoundaries
[i
- 1];
488 while (k
< AR5416_NUM_PDADC_VALUES
) {
489 pPDADCValues
[k
] = pPDADCValues
[k
- 1];
496 static void ath9k_hw_get_legacy_target_powers(struct ath_hal
*ah
,
497 struct ath9k_channel
*chan
,
498 struct cal_target_power_leg
*powInfo
,
500 struct cal_target_power_leg
*pNewPower
,
501 u16 numRates
, bool isExtTarget
)
503 struct chan_centers centers
;
506 int matchIndex
= -1, lowIndex
= -1;
509 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
510 freq
= (isExtTarget
) ? centers
.ext_center
: centers
.ctl_center
;
512 if (freq
<= ath9k_hw_fbin2freq(powInfo
[0].bChannel
,
513 IS_CHAN_2GHZ(chan
))) {
516 for (i
= 0; (i
< numChannels
) &&
517 (powInfo
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
518 if (freq
== ath9k_hw_fbin2freq(powInfo
[i
].bChannel
,
519 IS_CHAN_2GHZ(chan
))) {
522 } else if ((freq
< ath9k_hw_fbin2freq(powInfo
[i
].bChannel
,
523 IS_CHAN_2GHZ(chan
))) &&
524 (freq
> ath9k_hw_fbin2freq(powInfo
[i
- 1].bChannel
,
525 IS_CHAN_2GHZ(chan
)))) {
530 if ((matchIndex
== -1) && (lowIndex
== -1))
534 if (matchIndex
!= -1) {
535 *pNewPower
= powInfo
[matchIndex
];
537 clo
= ath9k_hw_fbin2freq(powInfo
[lowIndex
].bChannel
,
539 chi
= ath9k_hw_fbin2freq(powInfo
[lowIndex
+ 1].bChannel
,
542 for (i
= 0; i
< numRates
; i
++) {
543 pNewPower
->tPow2x
[i
] =
544 (u8
)ath9k_hw_interpolate(freq
, clo
, chi
,
545 powInfo
[lowIndex
].tPow2x
[i
],
546 powInfo
[lowIndex
+ 1].tPow2x
[i
]);
551 static void ath9k_hw_get_target_powers(struct ath_hal
*ah
,
552 struct ath9k_channel
*chan
,
553 struct cal_target_power_ht
*powInfo
,
555 struct cal_target_power_ht
*pNewPower
,
556 u16 numRates
, bool isHt40Target
)
558 struct chan_centers centers
;
561 int matchIndex
= -1, lowIndex
= -1;
564 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
565 freq
= isHt40Target
? centers
.synth_center
: centers
.ctl_center
;
567 if (freq
<= ath9k_hw_fbin2freq(powInfo
[0].bChannel
, IS_CHAN_2GHZ(chan
))) {
570 for (i
= 0; (i
< numChannels
) &&
571 (powInfo
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
572 if (freq
== ath9k_hw_fbin2freq(powInfo
[i
].bChannel
,
573 IS_CHAN_2GHZ(chan
))) {
577 if ((freq
< ath9k_hw_fbin2freq(powInfo
[i
].bChannel
,
578 IS_CHAN_2GHZ(chan
))) &&
579 (freq
> ath9k_hw_fbin2freq(powInfo
[i
- 1].bChannel
,
580 IS_CHAN_2GHZ(chan
)))) {
585 if ((matchIndex
== -1) && (lowIndex
== -1))
589 if (matchIndex
!= -1) {
590 *pNewPower
= powInfo
[matchIndex
];
592 clo
= ath9k_hw_fbin2freq(powInfo
[lowIndex
].bChannel
,
594 chi
= ath9k_hw_fbin2freq(powInfo
[lowIndex
+ 1].bChannel
,
597 for (i
= 0; i
< numRates
; i
++) {
598 pNewPower
->tPow2x
[i
] = (u8
)ath9k_hw_interpolate(freq
,
600 powInfo
[lowIndex
].tPow2x
[i
],
601 powInfo
[lowIndex
+ 1].tPow2x
[i
]);
606 static u16
ath9k_hw_get_max_edge_power(u16 freq
,
607 struct cal_ctl_edges
*pRdEdgesPower
,
610 u16 twiceMaxEdgePower
= AR5416_MAX_RATE_POWER
;
613 for (i
= 0; (i
< AR5416_NUM_BAND_EDGES
) &&
614 (pRdEdgesPower
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
615 if (freq
== ath9k_hw_fbin2freq(pRdEdgesPower
[i
].bChannel
, is2GHz
)) {
616 twiceMaxEdgePower
= pRdEdgesPower
[i
].tPower
;
618 } else if ((i
> 0) &&
619 (freq
< ath9k_hw_fbin2freq(pRdEdgesPower
[i
].bChannel
,
621 if (ath9k_hw_fbin2freq(pRdEdgesPower
[i
- 1].bChannel
,
623 pRdEdgesPower
[i
- 1].flag
) {
625 pRdEdgesPower
[i
- 1].tPower
;
631 return twiceMaxEdgePower
;
634 int ath9k_hw_set_txpower(struct ath_hal
*ah
,
635 struct ath9k_channel
*chan
,
637 u8 twiceAntennaReduction
,
638 u8 twiceMaxRegulatoryPower
,
641 struct ath_hal_5416
*ahp
= AH5416(ah
);
642 struct ar5416_eeprom
*pEepData
= &ahp
->ah_eeprom
;
643 struct modal_eep_header
*pModal
=
644 &(pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)]);
645 int16_t ratesArray
[Ar5416RateSize
];
646 int16_t txPowerIndexOffset
= 0;
647 u8 ht40PowerIncForPdadc
= 2;
650 memset(ratesArray
, 0, sizeof(ratesArray
));
652 if ((pEepData
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
653 AR5416_EEP_MINOR_VER_2
) {
654 ht40PowerIncForPdadc
= pModal
->ht40PowerIncForPdadc
;
657 if (!ath9k_hw_set_power_per_rate_table(ah
, chan
,
658 &ratesArray
[0], cfgCtl
,
659 twiceAntennaReduction
,
660 twiceMaxRegulatoryPower
,
662 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
663 "ath9k_hw_set_txpower: unable to set "
664 "tx power per rate table\n");
668 if (!ath9k_hw_set_power_cal_table(ah
, chan
, &txPowerIndexOffset
)) {
669 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
,
670 "ath9k_hw_set_txpower: unable to set power table\n");
674 for (i
= 0; i
< ARRAY_SIZE(ratesArray
); i
++) {
675 ratesArray
[i
] = (int16_t)(txPowerIndexOffset
+ ratesArray
[i
]);
676 if (ratesArray
[i
] > AR5416_MAX_RATE_POWER
)
677 ratesArray
[i
] = AR5416_MAX_RATE_POWER
;
680 if (AR_SREV_9280_10_OR_LATER(ah
)) {
681 for (i
= 0; i
< Ar5416RateSize
; i
++)
682 ratesArray
[i
] -= AR5416_PWR_TABLE_OFFSET
* 2;
685 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE1
,
686 ATH9K_POW_SM(ratesArray
[rate18mb
], 24)
687 | ATH9K_POW_SM(ratesArray
[rate12mb
], 16)
688 | ATH9K_POW_SM(ratesArray
[rate9mb
], 8)
689 | ATH9K_POW_SM(ratesArray
[rate6mb
], 0));
690 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE2
,
691 ATH9K_POW_SM(ratesArray
[rate54mb
], 24)
692 | ATH9K_POW_SM(ratesArray
[rate48mb
], 16)
693 | ATH9K_POW_SM(ratesArray
[rate36mb
], 8)
694 | ATH9K_POW_SM(ratesArray
[rate24mb
], 0));
696 if (IS_CHAN_2GHZ(chan
)) {
697 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE3
,
698 ATH9K_POW_SM(ratesArray
[rate2s
], 24)
699 | ATH9K_POW_SM(ratesArray
[rate2l
], 16)
700 | ATH9K_POW_SM(ratesArray
[rateXr
], 8)
701 | ATH9K_POW_SM(ratesArray
[rate1l
], 0));
702 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE4
,
703 ATH9K_POW_SM(ratesArray
[rate11s
], 24)
704 | ATH9K_POW_SM(ratesArray
[rate11l
], 16)
705 | ATH9K_POW_SM(ratesArray
[rate5_5s
], 8)
706 | ATH9K_POW_SM(ratesArray
[rate5_5l
], 0));
709 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE5
,
710 ATH9K_POW_SM(ratesArray
[rateHt20_3
], 24)
711 | ATH9K_POW_SM(ratesArray
[rateHt20_2
], 16)
712 | ATH9K_POW_SM(ratesArray
[rateHt20_1
], 8)
713 | ATH9K_POW_SM(ratesArray
[rateHt20_0
], 0));
714 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE6
,
715 ATH9K_POW_SM(ratesArray
[rateHt20_7
], 24)
716 | ATH9K_POW_SM(ratesArray
[rateHt20_6
], 16)
717 | ATH9K_POW_SM(ratesArray
[rateHt20_5
], 8)
718 | ATH9K_POW_SM(ratesArray
[rateHt20_4
], 0));
720 if (IS_CHAN_HT40(chan
)) {
721 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE7
,
722 ATH9K_POW_SM(ratesArray
[rateHt40_3
] +
723 ht40PowerIncForPdadc
, 24)
724 | ATH9K_POW_SM(ratesArray
[rateHt40_2
] +
725 ht40PowerIncForPdadc
, 16)
726 | ATH9K_POW_SM(ratesArray
[rateHt40_1
] +
727 ht40PowerIncForPdadc
, 8)
728 | ATH9K_POW_SM(ratesArray
[rateHt40_0
] +
729 ht40PowerIncForPdadc
, 0));
730 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE8
,
731 ATH9K_POW_SM(ratesArray
[rateHt40_7
] +
732 ht40PowerIncForPdadc
, 24)
733 | ATH9K_POW_SM(ratesArray
[rateHt40_6
] +
734 ht40PowerIncForPdadc
, 16)
735 | ATH9K_POW_SM(ratesArray
[rateHt40_5
] +
736 ht40PowerIncForPdadc
, 8)
737 | ATH9K_POW_SM(ratesArray
[rateHt40_4
] +
738 ht40PowerIncForPdadc
, 0));
740 REG_WRITE(ah
, AR_PHY_POWER_TX_RATE9
,
741 ATH9K_POW_SM(ratesArray
[rateExtOfdm
], 24)
742 | ATH9K_POW_SM(ratesArray
[rateExtCck
], 16)
743 | ATH9K_POW_SM(ratesArray
[rateDupOfdm
], 8)
744 | ATH9K_POW_SM(ratesArray
[rateDupCck
], 0));
747 REG_WRITE(ah
, AR_PHY_POWER_TX_SUB
,
748 ATH9K_POW_SM(pModal
->pwrDecreaseFor3Chain
, 6)
749 | ATH9K_POW_SM(pModal
->pwrDecreaseFor2Chain
, 0));
753 if (IS_CHAN_HT40(chan
))
755 else if (IS_CHAN_HT20(chan
))
758 if (AR_SREV_9280_10_OR_LATER(ah
))
759 ah
->ah_maxPowerLevel
=
760 ratesArray
[i
] + AR5416_PWR_TABLE_OFFSET
* 2;
762 ah
->ah_maxPowerLevel
= ratesArray
[i
];
767 void ath9k_hw_set_addac(struct ath_hal
*ah
, struct ath9k_channel
*chan
)
769 struct modal_eep_header
*pModal
;
770 struct ath_hal_5416
*ahp
= AH5416(ah
);
771 struct ar5416_eeprom
*eep
= &ahp
->ah_eeprom
;
774 if (ah
->ah_macVersion
!= AR_SREV_VERSION_9160
)
777 if (ar5416_get_eep_rev(ahp
) < AR5416_EEP_MINOR_VER_7
)
780 pModal
= &(eep
->modalHeader
[IS_CHAN_2GHZ(chan
)]);
782 if (pModal
->xpaBiasLvl
!= 0xff) {
783 biaslevel
= pModal
->xpaBiasLvl
;
785 u16 resetFreqBin
, freqBin
, freqCount
= 0;
786 struct chan_centers centers
;
788 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
790 resetFreqBin
= FREQ2FBIN(centers
.synth_center
, IS_CHAN_2GHZ(chan
));
791 freqBin
= pModal
->xpaBiasLvlFreq
[0] & 0xff;
792 biaslevel
= (u8
) (pModal
->xpaBiasLvlFreq
[0] >> 14);
796 while (freqCount
< 3) {
797 if (pModal
->xpaBiasLvlFreq
[freqCount
] == 0x0)
800 freqBin
= pModal
->xpaBiasLvlFreq
[freqCount
] & 0xff;
801 if (resetFreqBin
>= freqBin
) {
802 biaslevel
= (u8
)(pModal
->xpaBiasLvlFreq
[freqCount
] >> 14);
810 if (IS_CHAN_2GHZ(chan
)) {
811 INI_RA(&ahp
->ah_iniAddac
, 7, 1) =
812 (INI_RA(&ahp
->ah_iniAddac
, 7, 1) & (~0x18)) | biaslevel
<< 3;
814 INI_RA(&ahp
->ah_iniAddac
, 6, 1) =
815 (INI_RA(&ahp
->ah_iniAddac
, 6, 1) & (~0xc0)) | biaslevel
<< 6;
819 bool ath9k_hw_set_power_per_rate_table(struct ath_hal
*ah
,
820 struct ath9k_channel
*chan
,
824 u8 twiceMaxRegulatoryPower
,
827 struct ath_hal_5416
*ahp
= AH5416(ah
);
828 struct ar5416_eeprom
*pEepData
= &ahp
->ah_eeprom
;
829 u8 twiceMaxEdgePower
= AR5416_MAX_RATE_POWER
;
830 static const u16 tpScaleReductionTable
[5] =
831 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER
};
834 int8_t twiceLargestAntenna
;
835 struct cal_ctl_data
*rep
;
836 struct cal_target_power_leg targetPowerOfdm
, targetPowerCck
= {
839 struct cal_target_power_leg targetPowerOfdmExt
= {
840 0, { 0, 0, 0, 0} }, targetPowerCckExt
= {
843 struct cal_target_power_ht targetPowerHt20
, targetPowerHt40
= {
846 u8 scaledPower
= 0, minCtlPower
, maxRegAllowedPower
;
847 u16 ctlModesFor11a
[] =
848 { CTL_11A
, CTL_5GHT20
, CTL_11A_EXT
, CTL_5GHT40
};
849 u16 ctlModesFor11g
[] =
850 { CTL_11B
, CTL_11G
, CTL_2GHT20
, CTL_11B_EXT
, CTL_11G_EXT
,
853 u16 numCtlModes
, *pCtlMode
, ctlMode
, freq
;
854 struct chan_centers centers
;
856 u8 twiceMinEdgePower
;
858 tx_chainmask
= ahp
->ah_txchainmask
;
860 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
862 twiceLargestAntenna
= max(
863 pEepData
->modalHeader
864 [IS_CHAN_2GHZ(chan
)].antennaGainCh
[0],
865 pEepData
->modalHeader
866 [IS_CHAN_2GHZ(chan
)].antennaGainCh
[1]);
868 twiceLargestAntenna
= max((u8
)twiceLargestAntenna
,
869 pEepData
->modalHeader
870 [IS_CHAN_2GHZ(chan
)].antennaGainCh
[2]);
872 twiceLargestAntenna
= (int8_t)min(AntennaReduction
- twiceLargestAntenna
, 0);
874 maxRegAllowedPower
= twiceMaxRegulatoryPower
+ twiceLargestAntenna
;
876 if (ah
->ah_tpScale
!= ATH9K_TP_SCALE_MAX
) {
877 maxRegAllowedPower
-=
878 (tpScaleReductionTable
[(ah
->ah_tpScale
)] * 2);
881 scaledPower
= min(powerLimit
, maxRegAllowedPower
);
883 switch (ar5416_get_ntxchains(tx_chainmask
)) {
888 pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].pwrDecreaseFor2Chain
;
892 pEepData
->modalHeader
[IS_CHAN_2GHZ(chan
)].pwrDecreaseFor3Chain
;
896 scaledPower
= max(0, (int32_t) scaledPower
);
898 if (IS_CHAN_2GHZ(chan
)) {
899 numCtlModes
= ARRAY_SIZE(ctlModesFor11g
) -
900 SUB_NUM_CTL_MODES_AT_2G_40
;
901 pCtlMode
= ctlModesFor11g
;
903 ath9k_hw_get_legacy_target_powers(ah
, chan
,
904 pEepData
->calTargetPowerCck
,
905 AR5416_NUM_2G_CCK_TARGET_POWERS
,
906 &targetPowerCck
, 4, false);
907 ath9k_hw_get_legacy_target_powers(ah
, chan
,
908 pEepData
->calTargetPower2G
,
909 AR5416_NUM_2G_20_TARGET_POWERS
,
910 &targetPowerOfdm
, 4, false);
911 ath9k_hw_get_target_powers(ah
, chan
,
912 pEepData
->calTargetPower2GHT20
,
913 AR5416_NUM_2G_20_TARGET_POWERS
,
914 &targetPowerHt20
, 8, false);
916 if (IS_CHAN_HT40(chan
)) {
917 numCtlModes
= ARRAY_SIZE(ctlModesFor11g
);
918 ath9k_hw_get_target_powers(ah
, chan
,
919 pEepData
->calTargetPower2GHT40
,
920 AR5416_NUM_2G_40_TARGET_POWERS
,
921 &targetPowerHt40
, 8, true);
922 ath9k_hw_get_legacy_target_powers(ah
, chan
,
923 pEepData
->calTargetPowerCck
,
924 AR5416_NUM_2G_CCK_TARGET_POWERS
,
925 &targetPowerCckExt
, 4, true);
926 ath9k_hw_get_legacy_target_powers(ah
, chan
,
927 pEepData
->calTargetPower2G
,
928 AR5416_NUM_2G_20_TARGET_POWERS
,
929 &targetPowerOfdmExt
, 4, true);
932 numCtlModes
= ARRAY_SIZE(ctlModesFor11a
) -
933 SUB_NUM_CTL_MODES_AT_5G_40
;
934 pCtlMode
= ctlModesFor11a
;
936 ath9k_hw_get_legacy_target_powers(ah
, chan
,
937 pEepData
->calTargetPower5G
,
938 AR5416_NUM_5G_20_TARGET_POWERS
,
939 &targetPowerOfdm
, 4, false);
940 ath9k_hw_get_target_powers(ah
, chan
,
941 pEepData
->calTargetPower5GHT20
,
942 AR5416_NUM_5G_20_TARGET_POWERS
,
943 &targetPowerHt20
, 8, false);
945 if (IS_CHAN_HT40(chan
)) {
946 numCtlModes
= ARRAY_SIZE(ctlModesFor11a
);
947 ath9k_hw_get_target_powers(ah
, chan
,
948 pEepData
->calTargetPower5GHT40
,
949 AR5416_NUM_5G_40_TARGET_POWERS
,
950 &targetPowerHt40
, 8, true);
951 ath9k_hw_get_legacy_target_powers(ah
, chan
,
952 pEepData
->calTargetPower5G
,
953 AR5416_NUM_5G_20_TARGET_POWERS
,
954 &targetPowerOfdmExt
, 4, true);
958 for (ctlMode
= 0; ctlMode
< numCtlModes
; ctlMode
++) {
959 bool isHt40CtlMode
= (pCtlMode
[ctlMode
] == CTL_5GHT40
) ||
960 (pCtlMode
[ctlMode
] == CTL_2GHT40
);
962 freq
= centers
.synth_center
;
963 else if (pCtlMode
[ctlMode
] & EXT_ADDITIVE
)
964 freq
= centers
.ext_center
;
966 freq
= centers
.ctl_center
;
968 if (ar5416_get_eep_ver(ahp
) == 14 && ar5416_get_eep_rev(ahp
) <= 2)
969 twiceMaxEdgePower
= AR5416_MAX_RATE_POWER
;
971 DPRINTF(ah
->ah_sc
, ATH_DBG_POWER_MGMT
,
972 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
974 ctlMode
, numCtlModes
, isHt40CtlMode
,
975 (pCtlMode
[ctlMode
] & EXT_ADDITIVE
));
977 for (i
= 0; (i
< AR5416_NUM_CTLS
) && pEepData
->ctlIndex
[i
]; i
++) {
978 DPRINTF(ah
->ah_sc
, ATH_DBG_POWER_MGMT
,
979 " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
980 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
982 i
, cfgCtl
, pCtlMode
[ctlMode
],
983 pEepData
->ctlIndex
[i
], chan
->channel
);
985 if ((((cfgCtl
& ~CTL_MODE_M
) |
986 (pCtlMode
[ctlMode
] & CTL_MODE_M
)) ==
987 pEepData
->ctlIndex
[i
]) ||
988 (((cfgCtl
& ~CTL_MODE_M
) |
989 (pCtlMode
[ctlMode
] & CTL_MODE_M
)) ==
990 ((pEepData
->ctlIndex
[i
] & CTL_MODE_M
) | SD_NO_CTL
))) {
991 rep
= &(pEepData
->ctlData
[i
]);
993 twiceMinEdgePower
= ath9k_hw_get_max_edge_power(freq
,
994 rep
->ctlEdges
[ar5416_get_ntxchains(tx_chainmask
) - 1],
997 DPRINTF(ah
->ah_sc
, ATH_DBG_POWER_MGMT
,
998 " MATCH-EE_IDX %d: ch %d is2 %d "
999 "2xMinEdge %d chainmask %d chains %d\n",
1000 i
, freq
, IS_CHAN_2GHZ(chan
),
1001 twiceMinEdgePower
, tx_chainmask
,
1002 ar5416_get_ntxchains
1004 if ((cfgCtl
& ~CTL_MODE_M
) == SD_NO_CTL
) {
1005 twiceMaxEdgePower
= min(twiceMaxEdgePower
,
1008 twiceMaxEdgePower
= twiceMinEdgePower
;
1014 minCtlPower
= min(twiceMaxEdgePower
, scaledPower
);
1016 DPRINTF(ah
->ah_sc
, ATH_DBG_POWER_MGMT
,
1017 " SEL-Min ctlMode %d pCtlMode %d "
1018 "2xMaxEdge %d sP %d minCtlPwr %d\n",
1019 ctlMode
, pCtlMode
[ctlMode
], twiceMaxEdgePower
,
1020 scaledPower
, minCtlPower
);
1022 switch (pCtlMode
[ctlMode
]) {
1024 for (i
= 0; i
< ARRAY_SIZE(targetPowerCck
.tPow2x
); i
++) {
1025 targetPowerCck
.tPow2x
[i
] =
1026 min(targetPowerCck
.tPow2x
[i
],
1032 for (i
= 0; i
< ARRAY_SIZE(targetPowerOfdm
.tPow2x
); i
++) {
1033 targetPowerOfdm
.tPow2x
[i
] =
1034 min(targetPowerOfdm
.tPow2x
[i
],
1040 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt20
.tPow2x
); i
++) {
1041 targetPowerHt20
.tPow2x
[i
] =
1042 min(targetPowerHt20
.tPow2x
[i
],
1047 targetPowerCckExt
.tPow2x
[0] =
1048 min(targetPowerCckExt
.tPow2x
[0], minCtlPower
);
1052 targetPowerOfdmExt
.tPow2x
[0] =
1053 min(targetPowerOfdmExt
.tPow2x
[0], minCtlPower
);
1057 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt40
.tPow2x
); i
++) {
1058 targetPowerHt40
.tPow2x
[i
] =
1059 min(targetPowerHt40
.tPow2x
[i
],
1068 ratesArray
[rate6mb
] = ratesArray
[rate9mb
] = ratesArray
[rate12mb
] =
1069 ratesArray
[rate18mb
] = ratesArray
[rate24mb
] =
1070 targetPowerOfdm
.tPow2x
[0];
1071 ratesArray
[rate36mb
] = targetPowerOfdm
.tPow2x
[1];
1072 ratesArray
[rate48mb
] = targetPowerOfdm
.tPow2x
[2];
1073 ratesArray
[rate54mb
] = targetPowerOfdm
.tPow2x
[3];
1074 ratesArray
[rateXr
] = targetPowerOfdm
.tPow2x
[0];
1076 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt20
.tPow2x
); i
++)
1077 ratesArray
[rateHt20_0
+ i
] = targetPowerHt20
.tPow2x
[i
];
1079 if (IS_CHAN_2GHZ(chan
)) {
1080 ratesArray
[rate1l
] = targetPowerCck
.tPow2x
[0];
1081 ratesArray
[rate2s
] = ratesArray
[rate2l
] =
1082 targetPowerCck
.tPow2x
[1];
1083 ratesArray
[rate5_5s
] = ratesArray
[rate5_5l
] =
1084 targetPowerCck
.tPow2x
[2];
1086 ratesArray
[rate11s
] = ratesArray
[rate11l
] =
1087 targetPowerCck
.tPow2x
[3];
1090 if (IS_CHAN_HT40(chan
)) {
1091 for (i
= 0; i
< ARRAY_SIZE(targetPowerHt40
.tPow2x
); i
++) {
1092 ratesArray
[rateHt40_0
+ i
] =
1093 targetPowerHt40
.tPow2x
[i
];
1095 ratesArray
[rateDupOfdm
] = targetPowerHt40
.tPow2x
[0];
1096 ratesArray
[rateDupCck
] = targetPowerHt40
.tPow2x
[0];
1097 ratesArray
[rateExtOfdm
] = targetPowerOfdmExt
.tPow2x
[0];
1098 if (IS_CHAN_2GHZ(chan
)) {
1099 ratesArray
[rateExtCck
] =
1100 targetPowerCckExt
.tPow2x
[0];
1106 bool ath9k_hw_set_power_cal_table(struct ath_hal
*ah
,
1107 struct ath9k_channel
*chan
,
1108 int16_t *pTxPowerIndexOffset
)
1110 struct ath_hal_5416
*ahp
= AH5416(ah
);
1111 struct ar5416_eeprom
*pEepData
= &ahp
->ah_eeprom
;
1112 struct cal_data_per_freq
*pRawDataset
;
1113 u8
*pCalBChans
= NULL
;
1114 u16 pdGainOverlap_t2
;
1115 static u8 pdadcValues
[AR5416_NUM_PDADC_VALUES
];
1116 u16 gainBoundaries
[AR5416_PD_GAINS_IN_MASK
];
1118 int16_t tMinCalPower
;
1119 u16 numXpdGain
, xpdMask
;
1120 u16 xpdGainValues
[AR5416_NUM_PD_GAINS
] = { 0, 0, 0, 0 };
1121 u32 reg32
, regOffset
, regChainOffset
;
1124 modalIdx
= IS_CHAN_2GHZ(chan
) ? 1 : 0;
1125 xpdMask
= pEepData
->modalHeader
[modalIdx
].xpdGain
;
1127 if ((pEepData
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
1128 AR5416_EEP_MINOR_VER_2
) {
1130 pEepData
->modalHeader
[modalIdx
].pdGainOverlap
;
1132 pdGainOverlap_t2
= (u16
)(MS(REG_READ(ah
, AR_PHY_TPCRG5
),
1133 AR_PHY_TPCRG5_PD_GAIN_OVERLAP
));
1136 if (IS_CHAN_2GHZ(chan
)) {
1137 pCalBChans
= pEepData
->calFreqPier2G
;
1138 numPiers
= AR5416_NUM_2G_CAL_PIERS
;
1140 pCalBChans
= pEepData
->calFreqPier5G
;
1141 numPiers
= AR5416_NUM_5G_CAL_PIERS
;
1146 for (i
= 1; i
<= AR5416_PD_GAINS_IN_MASK
; i
++) {
1147 if ((xpdMask
>> (AR5416_PD_GAINS_IN_MASK
- i
)) & 1) {
1148 if (numXpdGain
>= AR5416_NUM_PD_GAINS
)
1150 xpdGainValues
[numXpdGain
] =
1151 (u16
)(AR5416_PD_GAINS_IN_MASK
- i
);
1156 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_NUM_PD_GAIN
,
1157 (numXpdGain
- 1) & 0x3);
1158 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_1
,
1160 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_2
,
1162 REG_RMW_FIELD(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_GAIN_3
,
1165 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
1166 if (AR_SREV_5416_V20_OR_LATER(ah
) &&
1167 (ahp
->ah_rxchainmask
== 5 || ahp
->ah_txchainmask
== 5) &&
1169 regChainOffset
= (i
== 1) ? 0x2000 : 0x1000;
1171 regChainOffset
= i
* 0x1000;
1173 if (pEepData
->baseEepHeader
.txMask
& (1 << i
)) {
1174 if (IS_CHAN_2GHZ(chan
))
1175 pRawDataset
= pEepData
->calPierData2G
[i
];
1177 pRawDataset
= pEepData
->calPierData5G
[i
];
1179 ath9k_hw_get_gain_boundaries_pdadcs(ah
, chan
,
1180 pRawDataset
, pCalBChans
,
1181 numPiers
, pdGainOverlap_t2
,
1182 &tMinCalPower
, gainBoundaries
,
1183 pdadcValues
, numXpdGain
);
1185 if ((i
== 0) || AR_SREV_5416_V20_OR_LATER(ah
)) {
1187 AR_PHY_TPCRG5
+ regChainOffset
,
1188 SM(pdGainOverlap_t2
,
1189 AR_PHY_TPCRG5_PD_GAIN_OVERLAP
)
1190 | SM(gainBoundaries
[0],
1191 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1
)
1192 | SM(gainBoundaries
[1],
1193 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2
)
1194 | SM(gainBoundaries
[2],
1195 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3
)
1196 | SM(gainBoundaries
[3],
1197 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4
));
1200 regOffset
= AR_PHY_BASE
+ (672 << 2) + regChainOffset
;
1201 for (j
= 0; j
< 32; j
++) {
1202 reg32
= ((pdadcValues
[4 * j
+ 0] & 0xFF) << 0) |
1203 ((pdadcValues
[4 * j
+ 1] & 0xFF) << 8) |
1204 ((pdadcValues
[4 * j
+ 2] & 0xFF) << 16) |
1205 ((pdadcValues
[4 * j
+ 3] & 0xFF) << 24);
1206 REG_WRITE(ah
, regOffset
, reg32
);
1208 DPRINTF(ah
->ah_sc
, ATH_DBG_PHY_IO
,
1209 "PDADC (%d,%4x): %4.4x %8.8x\n",
1210 i
, regChainOffset
, regOffset
,
1212 DPRINTF(ah
->ah_sc
, ATH_DBG_PHY_IO
,
1213 "PDADC: Chain %d | PDADC %3d Value %3d | "
1214 "PDADC %3d Value %3d | PDADC %3d Value %3d | "
1215 "PDADC %3d Value %3d |\n",
1216 i
, 4 * j
, pdadcValues
[4 * j
],
1217 4 * j
+ 1, pdadcValues
[4 * j
+ 1],
1218 4 * j
+ 2, pdadcValues
[4 * j
+ 2],
1220 pdadcValues
[4 * j
+ 3]);
1227 *pTxPowerIndexOffset
= 0;
1232 /* XXX: Clean me up, make me more legible */
1233 bool ath9k_hw_eeprom_set_board_values(struct ath_hal
*ah
,
1234 struct ath9k_channel
*chan
)
1236 struct modal_eep_header
*pModal
;
1237 struct ath_hal_5416
*ahp
= AH5416(ah
);
1238 struct ar5416_eeprom
*eep
= &ahp
->ah_eeprom
;
1239 int i
, regChainOffset
;
1243 pModal
= &(eep
->modalHeader
[IS_CHAN_2GHZ(chan
)]);
1245 txRxAttenLocal
= IS_CHAN_2GHZ(chan
) ? 23 : 44;
1247 ath9k_hw_get_eeprom_antenna_cfg(ah
, chan
, 1, &ant_config
);
1248 REG_WRITE(ah
, AR_PHY_SWITCH_COM
, ant_config
);
1250 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
1251 if (AR_SREV_9280(ah
)) {
1256 if (AR_SREV_5416_V20_OR_LATER(ah
) &&
1257 (ahp
->ah_rxchainmask
== 5 || ahp
->ah_txchainmask
== 5)
1259 regChainOffset
= (i
== 1) ? 0x2000 : 0x1000;
1261 regChainOffset
= i
* 0x1000;
1263 REG_WRITE(ah
, AR_PHY_SWITCH_CHAIN_0
+ regChainOffset
,
1264 pModal
->antCtrlChain
[i
]);
1266 REG_WRITE(ah
, AR_PHY_TIMING_CTRL4(0) + regChainOffset
,
1268 AR_PHY_TIMING_CTRL4(0) +
1270 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
|
1271 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
)) |
1272 SM(pModal
->iqCalICh
[i
],
1273 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
) |
1274 SM(pModal
->iqCalQCh
[i
],
1275 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
));
1277 if ((i
== 0) || AR_SREV_5416_V20_OR_LATER(ah
)) {
1278 if ((eep
->baseEepHeader
.version
&
1279 AR5416_EEP_VER_MINOR_MASK
) >=
1280 AR5416_EEP_MINOR_VER_3
) {
1281 txRxAttenLocal
= pModal
->txRxAttenCh
[i
];
1282 if (AR_SREV_9280_10_OR_LATER(ah
)) {
1286 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN
,
1292 AR_PHY_GAIN_2GHZ_XATTEN1_DB
,
1298 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN
,
1304 AR_PHY_GAIN_2GHZ_XATTEN2_DB
,
1314 ~AR_PHY_GAIN_2GHZ_BSW_MARGIN
)
1317 AR_PHY_GAIN_2GHZ_BSW_MARGIN
));
1324 ~AR_PHY_GAIN_2GHZ_BSW_ATTEN
)
1325 | SM(pModal
->bswAtten
[i
],
1326 AR_PHY_GAIN_2GHZ_BSW_ATTEN
));
1329 if (AR_SREV_9280_10_OR_LATER(ah
)) {
1333 AR9280_PHY_RXGAIN_TXRX_ATTEN
,
1338 AR9280_PHY_RXGAIN_TXRX_MARGIN
,
1339 pModal
->rxTxMarginCh
[i
]);
1342 AR_PHY_RXGAIN
+ regChainOffset
,
1346 ~AR_PHY_RXGAIN_TXRX_ATTEN
) |
1348 AR_PHY_RXGAIN_TXRX_ATTEN
));
1355 ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN
) |
1356 SM(pModal
->rxTxMarginCh
[i
],
1357 AR_PHY_GAIN_2GHZ_RXTX_MARGIN
));
1362 if (AR_SREV_9280_10_OR_LATER(ah
)) {
1363 if (IS_CHAN_2GHZ(chan
)) {
1364 ath9k_hw_analog_shift_rmw(ah
, AR_AN_RF2G1_CH0
,
1366 AR_AN_RF2G1_CH0_OB_S
,
1368 ath9k_hw_analog_shift_rmw(ah
, AR_AN_RF2G1_CH0
,
1370 AR_AN_RF2G1_CH0_DB_S
,
1372 ath9k_hw_analog_shift_rmw(ah
, AR_AN_RF2G1_CH1
,
1374 AR_AN_RF2G1_CH1_OB_S
,
1376 ath9k_hw_analog_shift_rmw(ah
, AR_AN_RF2G1_CH1
,
1378 AR_AN_RF2G1_CH1_DB_S
,
1381 ath9k_hw_analog_shift_rmw(ah
, AR_AN_RF5G1_CH0
,
1382 AR_AN_RF5G1_CH0_OB5
,
1383 AR_AN_RF5G1_CH0_OB5_S
,
1385 ath9k_hw_analog_shift_rmw(ah
, AR_AN_RF5G1_CH0
,
1386 AR_AN_RF5G1_CH0_DB5
,
1387 AR_AN_RF5G1_CH0_DB5_S
,
1389 ath9k_hw_analog_shift_rmw(ah
, AR_AN_RF5G1_CH1
,
1390 AR_AN_RF5G1_CH1_OB5
,
1391 AR_AN_RF5G1_CH1_OB5_S
,
1393 ath9k_hw_analog_shift_rmw(ah
, AR_AN_RF5G1_CH1
,
1394 AR_AN_RF5G1_CH1_DB5
,
1395 AR_AN_RF5G1_CH1_DB5_S
,
1398 ath9k_hw_analog_shift_rmw(ah
, AR_AN_TOP2
,
1399 AR_AN_TOP2_XPABIAS_LVL
,
1400 AR_AN_TOP2_XPABIAS_LVL_S
,
1401 pModal
->xpaBiasLvl
);
1402 ath9k_hw_analog_shift_rmw(ah
, AR_AN_TOP2
,
1403 AR_AN_TOP2_LOCALBIAS
,
1404 AR_AN_TOP2_LOCALBIAS_S
,
1405 pModal
->local_bias
);
1406 DPRINTF(ah
->ah_sc
, ATH_DBG_EEPROM
, "ForceXPAon: %d\n",
1407 pModal
->force_xpaon
);
1408 REG_RMW_FIELD(ah
, AR_PHY_XPA_CFG
, AR_PHY_FORCE_XPA_CFG
,
1409 pModal
->force_xpaon
);
1412 REG_RMW_FIELD(ah
, AR_PHY_SETTLING
, AR_PHY_SETTLING_SWITCH
,
1413 pModal
->switchSettling
);
1414 REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
, AR_PHY_DESIRED_SZ_ADC
,
1415 pModal
->adcDesiredSize
);
1417 if (!AR_SREV_9280_10_OR_LATER(ah
))
1418 REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
,
1419 AR_PHY_DESIRED_SZ_PGA
,
1420 pModal
->pgaDesiredSize
);
1422 REG_WRITE(ah
, AR_PHY_RF_CTL4
,
1423 SM(pModal
->txEndToXpaOff
, AR_PHY_RF_CTL4_TX_END_XPAA_OFF
)
1424 | SM(pModal
->txEndToXpaOff
,
1425 AR_PHY_RF_CTL4_TX_END_XPAB_OFF
)
1426 | SM(pModal
->txFrameToXpaOn
,
1427 AR_PHY_RF_CTL4_FRAME_XPAA_ON
)
1428 | SM(pModal
->txFrameToXpaOn
,
1429 AR_PHY_RF_CTL4_FRAME_XPAB_ON
));
1431 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL3
, AR_PHY_TX_END_TO_A2_RX_ON
,
1432 pModal
->txEndToRxOn
);
1433 if (AR_SREV_9280_10_OR_LATER(ah
)) {
1434 REG_RMW_FIELD(ah
, AR_PHY_CCA
, AR9280_PHY_CCA_THRESH62
,
1436 REG_RMW_FIELD(ah
, AR_PHY_EXT_CCA0
,
1437 AR_PHY_EXT_CCA0_THRESH62
,
1440 REG_RMW_FIELD(ah
, AR_PHY_CCA
, AR_PHY_CCA_THRESH62
,
1442 REG_RMW_FIELD(ah
, AR_PHY_EXT_CCA
,
1443 AR_PHY_EXT_CCA_THRESH62
,
1447 if ((eep
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
1448 AR5416_EEP_MINOR_VER_2
) {
1449 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
,
1450 AR_PHY_TX_END_DATA_START
,
1451 pModal
->txFrameToDataStart
);
1452 REG_RMW_FIELD(ah
, AR_PHY_RF_CTL2
, AR_PHY_TX_END_PA_ON
,
1453 pModal
->txFrameToPaOn
);
1456 if ((eep
->baseEepHeader
.version
& AR5416_EEP_VER_MINOR_MASK
) >=
1457 AR5416_EEP_MINOR_VER_3
) {
1458 if (IS_CHAN_HT40(chan
))
1459 REG_RMW_FIELD(ah
, AR_PHY_SETTLING
,
1460 AR_PHY_SETTLING_SWITCH
,
1461 pModal
->swSettleHt40
);
1467 int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal
*ah
,
1468 struct ath9k_channel
*chan
,
1469 u8 index
, u16
*config
)
1471 struct ath_hal_5416
*ahp
= AH5416(ah
);
1472 struct ar5416_eeprom
*eep
= &ahp
->ah_eeprom
;
1473 struct modal_eep_header
*pModal
=
1474 &(eep
->modalHeader
[IS_CHAN_2GHZ(chan
)]);
1475 struct base_eep_header
*pBase
= &eep
->baseEepHeader
;
1479 *config
= pModal
->antCtrlCommon
& 0xFFFF;
1482 if (pBase
->version
>= 0x0E0D) {
1483 if (pModal
->useAnt1
) {
1485 ((pModal
->antCtrlCommon
& 0xFFFF0000) >> 16);
1497 u8
ath9k_hw_get_num_ant_config(struct ath_hal
*ah
,
1498 enum ieee80211_band freq_band
)
1500 struct ath_hal_5416
*ahp
= AH5416(ah
);
1501 struct ar5416_eeprom
*eep
= &ahp
->ah_eeprom
;
1502 struct modal_eep_header
*pModal
=
1503 &(eep
->modalHeader
[IEEE80211_BAND_5GHZ
== freq_band
]);
1504 struct base_eep_header
*pBase
= &eep
->baseEepHeader
;
1509 if (pBase
->version
>= 0x0E0D)
1510 if (pModal
->useAnt1
)
1511 num_ant_config
+= 1;
1513 return num_ant_config
;
1516 u16
ath9k_hw_eeprom_get_spur_chan(struct ath_hal
*ah
, u16 i
, bool is2GHz
)
1518 struct ath_hal_5416
*ahp
= AH5416(ah
);
1519 struct ar5416_eeprom
*eep
=
1520 (struct ar5416_eeprom
*) &ahp
->ah_eeprom
;
1521 u16 spur_val
= AR_NO_SPUR
;
1523 DPRINTF(ah
->ah_sc
, ATH_DBG_ANI
,
1524 "Getting spur idx %d is2Ghz. %d val %x\n",
1525 i
, is2GHz
, ah
->ah_config
.spurchans
[i
][is2GHz
]);
1527 switch (ah
->ah_config
.spurmode
) {
1530 case SPUR_ENABLE_IOCTL
:
1531 spur_val
= ah
->ah_config
.spurchans
[i
][is2GHz
];
1532 DPRINTF(ah
->ah_sc
, ATH_DBG_ANI
,
1533 "Getting spur val from new loc. %d\n", spur_val
);
1535 case SPUR_ENABLE_EEPROM
:
1536 spur_val
= eep
->modalHeader
[is2GHz
].spurChans
[i
].spurChan
;
1544 u32
ath9k_hw_get_eeprom(struct ath_hal
*ah
,
1545 enum eeprom_param param
)
1547 struct ath_hal_5416
*ahp
= AH5416(ah
);
1548 struct ar5416_eeprom
*eep
= &ahp
->ah_eeprom
;
1549 struct modal_eep_header
*pModal
= eep
->modalHeader
;
1550 struct base_eep_header
*pBase
= &eep
->baseEepHeader
;
1553 case EEP_NFTHRESH_5
:
1554 return -pModal
[0].noiseFloorThreshCh
[0];
1555 case EEP_NFTHRESH_2
:
1556 return -pModal
[1].noiseFloorThreshCh
[0];
1557 case AR_EEPROM_MAC(0):
1558 return pBase
->macAddr
[0] << 8 | pBase
->macAddr
[1];
1559 case AR_EEPROM_MAC(1):
1560 return pBase
->macAddr
[2] << 8 | pBase
->macAddr
[3];
1561 case AR_EEPROM_MAC(2):
1562 return pBase
->macAddr
[4] << 8 | pBase
->macAddr
[5];
1564 return pBase
->regDmn
[0];
1566 return pBase
->regDmn
[1];
1568 return pBase
->deviceCap
;
1570 return pBase
->opCapFlags
;
1572 return pBase
->rfSilent
;
1574 return pModal
[0].ob
;
1576 return pModal
[0].db
;
1578 return pModal
[1].ob
;
1580 return pModal
[1].db
;
1582 return pBase
->version
& AR5416_EEP_VER_MINOR_MASK
;
1584 return pBase
->txMask
;
1586 return pBase
->rxMask
;
1592 int ath9k_hw_eeprom_attach(struct ath_hal
*ah
)
1596 if (ath9k_hw_use_flash(ah
))
1597 ath9k_hw_flash_map(ah
);
1599 if (!ath9k_hw_fill_eeprom(ah
))
1602 status
= ath9k_hw_check_eeprom(ah
);