2 * Copyright (c) 2002-2008 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.
17 * $Id: ar5416_cal.c,v 1.1.1.1 2008/12/11 04:46:47 alc Exp $
22 #include "ah_internal.h"
25 #include "ah_eeprom_v14.h"
27 #include "ar5416/ar5416.h"
28 #include "ar5416/ar5416reg.h"
29 #include "ar5416/ar5416phy.h"
31 /* Owl specific stuff */
32 #define NUM_NOISEFLOOR_READINGS 6 /* 3 chains * (ctl + ext) */
34 static void ar5416StartNFCal(struct ath_hal
*ah
);
35 static void ar5416LoadNF(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*);
36 static int16_t ar5416GetNf(struct ath_hal
*, HAL_CHANNEL_INTERNAL
*);
39 * Determine if calibration is supported by device and channel flags
41 static OS_INLINE HAL_BOOL
42 ar5416IsCalSupp(struct ath_hal
*ah
, HAL_CHANNEL
*chan
, HAL_CAL_TYPE calType
)
44 struct ar5416PerCal
*cal
= &AH5416(ah
)->ah_cal
;
46 switch (calType
& cal
->suppCals
) {
48 /* Run IQ Mismatch for non-CCK only */
49 return !IS_CHAN_B(chan
);
52 /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
53 return !IS_CHAN_B(chan
) &&
54 !(IS_CHAN_2GHZ(chan
) && IS_CHAN_HT20(chan
));
60 * Setup HW to collect samples used for current cal
63 ar5416SetupMeasurement(struct ath_hal
*ah
, HAL_CAL_LIST
*currCal
)
65 /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
66 OS_REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4
,
67 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
,
68 currCal
->calData
->calCountMax
);
70 /* Select calibration to run */
71 switch (currCal
->calData
->calType
) {
73 OS_REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_IQ
);
74 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
75 "%s: start IQ Mismatch calibration\n", __func__
);
78 OS_REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_ADC_GAIN
);
79 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
80 "%s: start ADC Gain calibration\n", __func__
);
83 OS_REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_ADC_DC_PER
);
84 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
85 "%s: start ADC DC calibration\n", __func__
);
88 OS_REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_ADC_DC_INIT
);
89 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
90 "%s: start Init ADC DC calibration\n", __func__
);
94 OS_REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4
, AR_PHY_TIMING_CTRL4_DO_CAL
);
98 * Initialize shared data structures and prepare a cal to be run.
101 ar5416ResetMeasurement(struct ath_hal
*ah
, HAL_CAL_LIST
*currCal
)
103 struct ar5416PerCal
*cal
= &AH5416(ah
)->ah_cal
;
105 /* Reset data structures shared between different calibrations */
106 OS_MEMZERO(cal
->caldata
, sizeof(cal
->caldata
));
109 /* Setup HW for new calibration */
110 ar5416SetupMeasurement(ah
, currCal
);
112 /* Change SW state to RUNNING for this calibration */
113 currCal
->calState
= CAL_RUNNING
;
118 * Run non-periodic calibrations.
121 ar5416RunInitCals(struct ath_hal
*ah
, int init_cal_count
)
123 struct ath_hal_5416
*ahp
= AH5416(ah
);
124 struct ar5416PerCal
*cal
= &AH5416(ah
)->ah_cal
;
125 HAL_CHANNEL_INTERNAL ichan
; /* XXX bogus */
126 HAL_CAL_LIST
*curCal
= ahp
->ah_cal_curr
;
130 if (curCal
== AH_NULL
)
134 for (i
= 0; i
< init_cal_count
; i
++) {
136 ar5416ResetMeasurement(ah
, curCal
);
137 /* Poll for offset calibration complete */
138 if (!ath_hal_wait(ah
, AR_PHY_TIMING_CTRL4
, AR_PHY_TIMING_CTRL4_DO_CAL
, 0)) {
139 HALDEBUG(ah
, HAL_DEBUG_ANY
,
140 "%s: Cal %d failed to finish in 100ms.\n",
141 __func__
, curCal
->calData
->calType
);
142 /* Re-initialize list pointers for periodic cals */
143 cal
->cal_list
= cal
->cal_last
= cal
->cal_curr
= AH_NULL
;
147 ar5416DoCalibration(ah
, &ichan
, ahp
->ah_rxchainmask
,
150 HALDEBUG(ah
, HAL_DEBUG_ANY
,
151 "%s: init cal %d did not complete.\n",
152 __func__
, curCal
->calData
->calType
);
153 if (curCal
->calNext
!= AH_NULL
)
154 curCal
= curCal
->calNext
;
157 /* Re-initialize list pointers for periodic cals */
158 cal
->cal_list
= cal
->cal_last
= cal
->cal_curr
= AH_NULL
;
164 * Initialize Calibration infrastructure.
167 ar5416InitCal(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
169 struct ar5416PerCal
*cal
= &AH5416(ah
)->ah_cal
;
170 HAL_CHANNEL_INTERNAL
*ichan
;
172 ichan
= ath_hal_checkchannel(ah
, chan
);
173 HALASSERT(ichan
!= AH_NULL
);
175 if (AR_SREV_MERLIN_10_OR_LATER(ah
)) {
176 /* Enable Rx Filter Cal */
177 OS_REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
178 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
,
179 AR_PHY_AGC_CONTROL_FLTR_CAL
);
181 /* Clear the carrier leak cal bit */
182 OS_REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
184 /* kick off the cal */
185 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
);
187 /* Poll for offset calibration complete */
188 if (!ath_hal_wait(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
, 0)) {
189 HALDEBUG(ah
, HAL_DEBUG_ANY
,
190 "%s: offset calibration failed to complete in 1ms; "
191 "noisy environment?\n", __func__
);
195 /* Set the cl cal bit and rerun the cal a 2nd time */
196 /* Enable Rx Filter Cal */
197 OS_REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
198 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
,
199 AR_PHY_AGC_CONTROL_FLTR_CAL
);
201 OS_REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
204 /* Calibrate the AGC */
205 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
);
207 /* Poll for offset calibration complete */
208 if (!ath_hal_wait(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
, 0)) {
209 HALDEBUG(ah
, HAL_DEBUG_ANY
,
210 "%s: offset calibration did not complete in 1ms; "
211 "noisy environment?\n", __func__
);
216 * Do NF calibration after DC offset and other CALs.
217 * Per system engineers, noise floor value can sometimes be 20 dB
218 * higher than normal value if DC offset and noise floor cal are
219 * triggered at the same time.
221 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NF
);
223 /* Initialize list pointers */
224 cal
->cal_list
= cal
->cal_last
= cal
->cal_curr
= AH_NULL
;
227 * Enable IQ, ADC Gain, ADC DC Offset Cals
229 if (AR_SREV_SOWL_10_OR_LATER(ah
)) {
230 /* Setup all non-periodic, init time only calibrations */
231 /* XXX: Init DC Offset not working yet */
233 if (ar5416IsCalSupp(ah
, chan
, ADC_DC_INIT_CAL
)) {
234 INIT_CAL(&cal
->adcDcCalInitData
);
235 INSERT_CAL(cal
, &cal
->adcDcCalInitData
);
237 /* Initialize current pointer to first element in list */
238 cal
->cal_curr
= cal
->cal_list
;
240 if (cal
->ah_cal_curr
!= AH_NULL
&& !ar5416RunInitCals(ah
, 0))
245 /* If Cals are supported, add them to list via INIT/INSERT_CAL */
246 if (ar5416IsCalSupp(ah
, chan
, ADC_GAIN_CAL
)) {
247 INIT_CAL(&cal
->adcGainCalData
);
248 INSERT_CAL(cal
, &cal
->adcGainCalData
);
249 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
250 "%s: enable ADC Gain Calibration.\n", __func__
);
252 if (ar5416IsCalSupp(ah
, chan
, ADC_DC_CAL
)) {
253 INIT_CAL(&cal
->adcDcCalData
);
254 INSERT_CAL(cal
, &cal
->adcDcCalData
);
255 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
256 "%s: enable ADC DC Calibration.\n", __func__
);
258 if (ar5416IsCalSupp(ah
, chan
, IQ_MISMATCH_CAL
)) {
259 INIT_CAL(&cal
->iqCalData
);
260 INSERT_CAL(cal
, &cal
->iqCalData
);
261 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
262 "%s: enable IQ Calibration.\n", __func__
);
264 /* Initialize current pointer to first element in list */
265 cal
->cal_curr
= cal
->cal_list
;
267 /* Kick off measurements for the first cal */
268 if (cal
->cal_curr
!= AH_NULL
)
269 ar5416ResetMeasurement(ah
, cal
->cal_curr
);
271 /* Mark all calibrations on this channel as being invalid */
278 * Entry point for upper layers to restart current cal.
279 * Reset the calibration valid bit in channel.
282 ar5416ResetCalValid(struct ath_hal
*ah
, HAL_CHANNEL
*chan
)
284 struct ar5416PerCal
*cal
= &AH5416(ah
)->ah_cal
;
285 HAL_CHANNEL_INTERNAL
*ichan
= ath_hal_checkchannel(ah
, chan
);
286 HAL_CAL_LIST
*currCal
= cal
->cal_curr
;
288 if (!AR_SREV_SOWL_10_OR_LATER(ah
))
290 if (currCal
== AH_NULL
)
292 if (ichan
== AH_NULL
) {
293 HALDEBUG(ah
, HAL_DEBUG_ANY
,
294 "%s: invalid channel %u/0x%x; no mapping\n",
295 __func__
, chan
->channel
, chan
->channelFlags
);
299 * Expected that this calibration has run before, post-reset.
300 * Current state should be done
302 if (currCal
->calState
!= CAL_DONE
) {
303 HALDEBUG(ah
, HAL_DEBUG_ANY
,
304 "%s: Calibration state incorrect, %d\n",
305 __func__
, currCal
->calState
);
309 /* Verify Cal is supported on this channel */
310 if (!ar5416IsCalSupp(ah
, chan
, currCal
->calData
->calType
))
313 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
314 "%s: Resetting Cal %d state for channel %u/0x%x\n",
315 __func__
, currCal
->calData
->calType
, chan
->channel
,
318 /* Disable cal validity in channel */
319 ichan
->calValid
&= ~currCal
->calData
->calType
;
320 currCal
->calState
= CAL_WAITING
;
326 * Recalibrate the lower PHY chips to account for temperature/environment
330 ar5416DoCalibration(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*ichan
,
331 uint8_t rxchainmask
, HAL_CAL_LIST
*currCal
, HAL_BOOL
*isCalDone
)
333 struct ar5416PerCal
*cal
= &AH5416(ah
)->ah_cal
;
335 /* Cal is assumed not done until explicitly set below */
336 *isCalDone
= AH_FALSE
;
338 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
339 "%s: %s Calibration, state %d, calValid 0x%x\n",
340 __func__
, currCal
->calData
->calName
, currCal
->calState
,
343 /* Calibration in progress. */
344 if (currCal
->calState
== CAL_RUNNING
) {
345 /* Check to see if it has finished. */
346 if (!(OS_REG_READ(ah
, AR_PHY_TIMING_CTRL4
) & AR_PHY_TIMING_CTRL4_DO_CAL
)) {
347 HALDEBUG(ah
, HAL_DEBUG_PERCAL
,
348 "%s: sample %d of %d finished\n",
349 __func__
, cal
->calSamples
,
350 currCal
->calData
->calNumSamples
);
352 * Collect measurements for active chains.
354 currCal
->calData
->calCollect(ah
);
355 if (++cal
->calSamples
>= currCal
->calData
->calNumSamples
) {
356 int i
, numChains
= 0;
357 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
358 if (rxchainmask
& (1 << i
))
362 * Process accumulated data
364 currCal
->calData
->calPostProc(ah
, numChains
);
366 /* Calibration has finished. */
367 ichan
->calValid
|= currCal
->calData
->calType
;
368 currCal
->calState
= CAL_DONE
;
369 *isCalDone
= AH_TRUE
;
372 * Set-up to collect of another sub-sample.
374 ar5416SetupMeasurement(ah
, currCal
);
377 } else if (!(ichan
->calValid
& currCal
->calData
->calType
)) {
378 /* If current cal is marked invalid in channel, kick it off */
379 ar5416ResetMeasurement(ah
, currCal
);
384 * Internal interface to schedule periodic calibration work.
387 ar5416PerCalibrationN(struct ath_hal
*ah
, HAL_CHANNEL
*chan
,
388 u_int rxchainmask
, HAL_BOOL longcal
, HAL_BOOL
*isCalDone
)
390 struct ar5416PerCal
*cal
= &AH5416(ah
)->ah_cal
;
391 HAL_CAL_LIST
*currCal
= cal
->cal_curr
;
392 HAL_CHANNEL_INTERNAL
*ichan
;
394 OS_MARK(ah
, AH_MARK_PERCAL
, chan
->channel
);
396 *isCalDone
= AH_TRUE
;
398 /* Invalid channel check */
399 ichan
= ath_hal_checkchannel(ah
, chan
);
400 if (ichan
== AH_NULL
) {
401 HALDEBUG(ah
, HAL_DEBUG_ANY
,
402 "%s: invalid channel %u/0x%x; no mapping\n",
403 __func__
, chan
->channel
, chan
->channelFlags
);
408 * For given calibration:
409 * 1. Call generic cal routine
410 * 2. When this cal is done (isCalDone) if we have more cals waiting
411 * (eg after reset), mask this to upper layers by not propagating
412 * isCalDone if it is set to TRUE.
413 * Instead, change isCalDone to FALSE and setup the waiting cal(s)
416 if (currCal
!= AH_NULL
&&
417 (currCal
->calState
== CAL_RUNNING
||
418 currCal
->calState
== CAL_WAITING
)) {
419 ar5416DoCalibration(ah
, ichan
, rxchainmask
, currCal
, isCalDone
);
420 if (*isCalDone
== AH_TRUE
) {
421 cal
->cal_curr
= currCal
= currCal
->calNext
;
422 if (currCal
->calState
== CAL_WAITING
) {
423 *isCalDone
= AH_FALSE
;
424 ar5416ResetMeasurement(ah
, currCal
);
429 /* Do NF cal only at longer intervals */
432 * Get the value from the previous NF cal
433 * and update the history buffer.
435 ar5416GetNf(ah
, ichan
);
438 * Load the NF from history buffer of the current channel.
439 * NF is slow time-variant, so it is OK to use a
442 ar5416LoadNF(ah
, AH_PRIVATE(ah
)->ah_curchan
);
444 /* start NF calibration, without updating BB NF register*/
445 ar5416StartNFCal(ah
);
447 if ((ichan
->channelFlags
& CHANNEL_CW_INT
) != 0) {
448 /* report up and clear internal state */
449 chan
->channelFlags
|= CHANNEL_CW_INT
;
450 ichan
->channelFlags
&= ~CHANNEL_CW_INT
;
457 * Recalibrate the lower PHY chips to account for temperature/environment
461 ar5416PerCalibration(struct ath_hal
*ah
, HAL_CHANNEL
*chan
, HAL_BOOL
*isIQdone
)
463 struct ath_hal_5416
*ahp
= AH5416(ah
);
464 struct ar5416PerCal
*cal
= &AH5416(ah
)->ah_cal
;
465 HAL_CAL_LIST
*curCal
= cal
->cal_curr
;
467 if (curCal
!= AH_NULL
&& curCal
->calData
->calType
== IQ_MISMATCH_CAL
) {
468 return ar5416PerCalibrationN(ah
, chan
, ahp
->ah_rx_chainmask
,
473 *isIQdone
= AH_FALSE
;
474 return ar5416PerCalibrationN(ah
, chan
, ahp
->ah_rx_chainmask
,
475 AH_TRUE
, &isCalDone
);
480 ar5416GetEepromNoiseFloorThresh(struct ath_hal
*ah
,
481 const HAL_CHANNEL_INTERNAL
*chan
, int16_t *nft
)
483 switch (chan
->channelFlags
& CHANNEL_ALL_NOTURBO
) {
486 case CHANNEL_A_HT40PLUS
:
487 case CHANNEL_A_HT40MINUS
:
488 ath_hal_eepromGet(ah
, AR_EEP_NFTHRESH_5
, nft
);
493 case CHANNEL_G_HT40PLUS
:
494 case CHANNEL_G_HT40MINUS
:
495 ath_hal_eepromGet(ah
, AR_EEP_NFTHRESH_2
, nft
);
498 HALDEBUG(ah
, HAL_DEBUG_ANY
,
499 "%s: invalid channel flags 0x%x\n",
500 __func__
, chan
->channelFlags
);
507 ar5416StartNFCal(struct ath_hal
*ah
)
509 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_ENABLE_NF
);
510 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NO_UPDATE_NF
);
511 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NF
);
515 ar5416LoadNF(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
)
517 static const uint32_t ar5416_cca_regs
[] = {
525 struct ar5212NfCalHist
*h
;
531 * Force NF calibration for all chains.
533 if (AR_SREV_KITE(ah
)) {
534 /* Kite has only one chain */
536 } else if (AR_SREV_MERLIN(ah
)) {
537 /* Merlin has only two chains */
544 * Write filtered NF values into maxCCApwr register parameter
545 * so we can load below.
547 h
= AH5416(ah
)->ah_cal
.nfCalHist
;
548 for (i
= 0; i
< AR5416_NUM_NF_READINGS
; i
++)
549 if (chainmask
& (1 << i
)) {
550 val
= OS_REG_READ(ah
, ar5416_cca_regs
[i
]);
552 val
|= (((uint32_t)(h
[i
].privNF
) << 1) & 0x1ff);
553 OS_REG_WRITE(ah
, ar5416_cca_regs
[i
], val
);
556 /* Load software filtered NF value into baseband internal minCCApwr variable. */
557 OS_REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_ENABLE_NF
);
558 OS_REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NO_UPDATE_NF
);
559 OS_REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_NF
);
561 /* Wait for load to complete, should be fast, a few 10s of us. */
562 for (j
= 0; j
< 1000; j
++) {
563 if ((OS_REG_READ(ah
, AR_PHY_AGC_CONTROL
) & AR_PHY_AGC_CONTROL_NF
) == 0)
569 * Restore maxCCAPower register parameter again so that we're not capped
570 * by the median we just loaded. This will be initial (and max) value
571 * of next noise floor calibration the baseband does.
573 for (i
= 0; i
< AR5416_NUM_NF_READINGS
; i
++)
574 if (chainmask
& (1 << i
)) {
575 val
= OS_REG_READ(ah
, ar5416_cca_regs
[i
]);
577 val
|= (((uint32_t)(-50) << 1) & 0x1ff);
578 OS_REG_WRITE(ah
, ar5416_cca_regs
[i
], val
);
583 ar5416InitNfHistBuff(struct ar5212NfCalHist
*h
)
587 for (i
= 0; i
< AR5416_NUM_NF_READINGS
; i
++) {
589 h
[i
].privNF
= AR5416_CCA_MAX_GOOD_VALUE
;
590 h
[i
].invalidNFcount
= AR512_NF_CAL_HIST_MAX
;
591 for (j
= 0; j
< AR512_NF_CAL_HIST_MAX
; j
++)
592 h
[i
].nfCalBuffer
[j
] = AR5416_CCA_MAX_GOOD_VALUE
;
597 * Update the noise floor buffer as a ring buffer
600 ar5416UpdateNFHistBuff(struct ar5212NfCalHist
*h
, int16_t *nfarray
)
604 for (i
= 0; i
< AR5416_NUM_NF_READINGS
; i
++) {
605 h
[i
].nfCalBuffer
[h
[i
].currIndex
] = nfarray
[i
];
607 if (++h
[i
].currIndex
>= AR512_NF_CAL_HIST_MAX
)
609 if (h
[i
].invalidNFcount
> 0) {
610 if (nfarray
[i
] < AR5416_CCA_MIN_BAD_VALUE
||
611 nfarray
[i
] > AR5416_CCA_MAX_HIGH_VALUE
) {
612 h
[i
].invalidNFcount
= AR512_NF_CAL_HIST_MAX
;
614 h
[i
].invalidNFcount
--;
615 h
[i
].privNF
= nfarray
[i
];
618 h
[i
].privNF
= ar5212GetNfHistMid(h
[i
].nfCalBuffer
);
624 * Read the NF and check it against the noise floor threshhold
627 ar5416GetNf(struct ath_hal
*ah
, HAL_CHANNEL_INTERNAL
*chan
)
629 int16_t nf
, nfThresh
;
631 if (OS_REG_READ(ah
, AR_PHY_AGC_CONTROL
) & AR_PHY_AGC_CONTROL_NF
) {
632 HALDEBUG(ah
, HAL_DEBUG_ANY
,
633 "%s: NF didn't complete in calibration window\n", __func__
);
636 /* Finished NF cal, check against threshold */
637 int16_t nfarray
[NUM_NOISEFLOOR_READINGS
] = { 0 };
639 /* TODO - enhance for multiple chains and ext ch */
640 ath_hal_getNoiseFloor(ah
, nfarray
);
642 if (ar5416GetEepromNoiseFloorThresh(ah
, chan
, &nfThresh
)) {
644 HALDEBUG(ah
, HAL_DEBUG_ANY
,
645 "%s: noise floor failed detected; "
646 "detected %d, threshold %d\n", __func__
,
649 * NB: Don't discriminate 2.4 vs 5Ghz, if this
650 * happens it indicates a problem regardless
653 chan
->channelFlags
|= CHANNEL_CW_INT
;
659 ar5416UpdateNFHistBuff(AH5416(ah
)->ah_cal
.nfCalHist
, nfarray
);
660 chan
->rawNoiseFloor
= nf
;