1/*
2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
3 *
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.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17
18
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24#include "ah_desc.h"
25
26#include "ar9300.h"
27#include "ar9300reg.h"
28#include "ar9300phy.h"
29#include "ar9300desc.h"
30
31#define FIX_NOISE_FLOOR     1
32
33
34/* Additional Time delay to wait after activiting the Base band */
35#define BASE_ACTIVATE_DELAY         100     /* usec */
36#define RTC_PLL_SETTLE_DELAY        100     /* usec */
37#define COEF_SCALE_S                24
38#define HT40_CHANNEL_CENTER_SHIFT   10      /* MHz      */
39
40#define DELPT 32
41
42/* XXX Duplicates! (in ar9300desc.h) */
43#if 0
44extern  HAL_BOOL ar9300_reset_tx_queue(struct ath_hal *ah, u_int q);
45extern  u_int32_t ar9300_num_tx_pending(struct ath_hal *ah, u_int q);
46#endif
47
48
49#define MAX_MEASUREMENT 8
50#define MAXIQCAL 3
51struct coeff_t {
52    int32_t mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
53    int32_t phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
54    int32_t iqc_coeff[2];
55    int last_nmeasurement;
56    HAL_BOOL last_cal;
57};
58
59static HAL_BOOL ar9300_tx_iq_cal_hw_run(struct ath_hal *ah);
60static void ar9300_tx_iq_cal_post_proc(struct ath_hal *ah,HAL_CHANNEL_INTERNAL *ichan,
61       int iqcal_idx, int max_iqcal, HAL_BOOL is_cal_reusable, HAL_BOOL apply_last_corr);
62static void ar9300_tx_iq_cal_outlier_detection(struct ath_hal *ah,HAL_CHANNEL_INTERNAL *ichan,
63       u_int32_t num_chains, struct coeff_t *coeff, HAL_BOOL is_cal_reusable);
64#if ATH_SUPPORT_CAL_REUSE
65static void ar9300_tx_iq_cal_apply(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan);
66#endif
67
68
69static inline void ar9300_prog_ini(struct ath_hal *ah, struct ar9300_ini_array *ini_arr, int column);
70static inline void ar9300_set_rf_mode(struct ath_hal *ah, struct ieee80211_channel *chan);
71static inline HAL_BOOL ar9300_init_cal(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_BOOL skip_if_none, HAL_BOOL apply_last_corr);
72static inline void ar9300_init_user_settings(struct ath_hal *ah);
73
74#ifdef HOST_OFFLOAD
75/*
76 * For usb offload solution, some USB registers must be tuned
77 * to gain better stability/performance but these registers
78 * might be changed while doing wlan reset so do this here
79 */
80#define WAR_USB_DISABLE_PLL_LOCK_DETECT(__ah) \
81do { \
82    if (AR_SREV_HORNET(__ah) || AR_SREV_WASP(__ah)) { \
83        volatile u_int32_t *usb_ctrl_r1 = (u_int32_t *) 0xb8116c84; \
84        volatile u_int32_t *usb_ctrl_r2 = (u_int32_t *) 0xb8116c88; \
85        *usb_ctrl_r1 = (*usb_ctrl_r1 & 0xffefffff); \
86        *usb_ctrl_r2 = (*usb_ctrl_r2 & 0xfc1fffff) | (1 << 21) | (3 << 22); \
87    } \
88} while (0)
89#else
90#define WAR_USB_DISABLE_PLL_LOCK_DETECT(__ah)
91#endif
92
93static inline void
94ar9300_attach_hw_platform(struct ath_hal *ah)
95{
96    struct ath_hal_9300 *ahp = AH9300(ah);
97
98    ahp->ah_hwp = HAL_TRUE_CHIP;
99    return;
100}
101
102/* Adjust various register settings based on half/quarter rate clock setting.
103 * This includes: +USEC, TX/RX latency,
104 *                + IFS params: slot, eifs, misc etc.
105 * SIFS stays the same.
106 */
107static void
108ar9300_set_ifs_timing(struct ath_hal *ah, struct ieee80211_channel *chan)
109{
110    u_int32_t tx_lat, rx_lat, usec, slot, regval, eifs;
111
112    regval = OS_REG_READ(ah, AR_USEC);
113    regval &= ~(AR_USEC_RX_LATENCY | AR_USEC_TX_LATENCY | AR_USEC_USEC);
114    if (IEEE80211_IS_CHAN_HALF(chan)) { /* half rates */
115        slot = ar9300_mac_to_clks(ah, AR_SLOT_HALF);
116        eifs = ar9300_mac_to_clks(ah, AR_EIFS_HALF);
117        if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { /* fast clock */
118            rx_lat = SM(AR_RX_LATENCY_HALF_FAST_CLOCK, AR_USEC_RX_LATENCY);
119            tx_lat = SM(AR_TX_LATENCY_HALF_FAST_CLOCK, AR_USEC_TX_LATENCY);
120            usec = SM(AR_USEC_HALF_FAST_CLOCK, AR_USEC_USEC);
121        } else {
122            rx_lat = SM(AR_RX_LATENCY_HALF, AR_USEC_RX_LATENCY);
123            tx_lat = SM(AR_TX_LATENCY_HALF, AR_USEC_TX_LATENCY);
124            usec = SM(AR_USEC_HALF, AR_USEC_USEC);
125        }
126    } else { /* quarter rate */
127        slot = ar9300_mac_to_clks(ah, AR_SLOT_QUARTER);
128        eifs = ar9300_mac_to_clks(ah, AR_EIFS_QUARTER);
129        if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { /* fast clock */
130            rx_lat = SM(AR_RX_LATENCY_QUARTER_FAST_CLOCK, AR_USEC_RX_LATENCY);
131            tx_lat = SM(AR_TX_LATENCY_QUARTER_FAST_CLOCK, AR_USEC_TX_LATENCY);
132            usec = SM(AR_USEC_QUARTER_FAST_CLOCK, AR_USEC_USEC);
133        } else {
134            rx_lat = SM(AR_RX_LATENCY_QUARTER, AR_USEC_RX_LATENCY);
135            tx_lat = SM(AR_TX_LATENCY_QUARTER, AR_USEC_TX_LATENCY);
136            usec = SM(AR_USEC_QUARTER, AR_USEC_USEC);
137        }
138    }
139
140    OS_REG_WRITE(ah, AR_USEC, (usec | regval | tx_lat | rx_lat));
141    OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot);
142    OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs);
143}
144
145
146/*
147 * This inline function configures the chip either
148 * to encrypt/decrypt management frames or pass thru
149 */
150static inline void
151ar9300_init_mfp(struct ath_hal * ah)
152{
153    u_int32_t   mfpcap, mfp_qos;
154
155    ath_hal_getcapability(ah, HAL_CAP_MFP, 0, &mfpcap);
156
157    if (mfpcap == HAL_MFP_QOSDATA) {
158        /* Treat like legacy hardware. Do not touch the MFP registers. */
159        HALDEBUG(ah, HAL_DEBUG_RESET, "%s forced to use QOSDATA\n", __func__);
160        return;
161    }
162
163    /* MFP support (Sowl 1.0 or greater) */
164    if (mfpcap == HAL_MFP_HW_CRYPTO) {
165        /* configure hardware MFP support */
166        HALDEBUG(ah, HAL_DEBUG_RESET, "%s using HW crypto\n", __func__);
167        OS_REG_RMW_FIELD(ah,
168            AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, AR_AES_MUTE_MASK1_FC_MGMT_MFP);
169        OS_REG_RMW(ah,
170            AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE,
171            AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
172        /*
173        * Mask used to construct AAD for CCMP-AES
174        * Cisco spec defined bits 0-3 as mask
175        * IEEE802.11w defined as bit 4.
176        */
177        if (ath_hal_get_mfp_qos(ah)) {
178            mfp_qos = AR_MFP_QOS_MASK_IEEE;
179        } else {
180            mfp_qos = AR_MFP_QOS_MASK_CISCO;
181        }
182        OS_REG_RMW_FIELD(ah,
183            AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_MGMT_QOS, mfp_qos);
184    } else if (mfpcap == HAL_MFP_PASSTHRU) {
185        /* Disable en/decrypt by hardware */
186        HALDEBUG(ah, HAL_DEBUG_RESET, "%s using passthru\n", __func__);
187        OS_REG_RMW(ah,
188            AR_PCU_MISC_MODE2,
189            AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT,
190            AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
191    }
192}
193
194void
195ar9300_get_channel_centers(struct ath_hal *ah, const struct ieee80211_channel *chan,
196    CHAN_CENTERS *centers)
197{
198    int8_t      extoff;
199    struct ath_hal_9300 *ahp = AH9300(ah);
200    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
201
202    if (!IEEE80211_IS_CHAN_HT40(chan)) {
203        centers->ctl_center = centers->ext_center =
204        centers->synth_center = ichan->channel;
205        return;
206    }
207
208    HALASSERT(IEEE80211_IS_CHAN_HT40(chan));
209
210    /*
211     * In 20/40 phy mode, the center frequency is
212     * "between" the primary and extension channels.
213     */
214    if (IEEE80211_IS_CHAN_HT40U(chan)) {
215        centers->synth_center = ichan->channel + HT40_CHANNEL_CENTER_SHIFT;
216        extoff = 1;
217    } else {
218        centers->synth_center = ichan->channel - HT40_CHANNEL_CENTER_SHIFT;
219        extoff = -1;
220    }
221
222    centers->ctl_center =
223        centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
224    centers->ext_center =
225        centers->synth_center +
226        (extoff * ((ahp->ah_ext_prot_spacing == HAL_HT_EXTPROTSPACING_20) ?
227            HT40_CHANNEL_CENTER_SHIFT : 15));
228}
229
230/*
231 * Read the noise-floor values from the HW.
232 * Specifically, read the minimum clear-channel assessment value for
233 * each chain, for both the control and extension channels.
234 * (The received power level during clear-channel periods is the
235 * noise floor.)
236 * These noise floor values computed by the HW will be stored in the
237 * NF history buffer.
238 * The HW sometimes produces bogus NF values.  To avoid using these
239 * bogus values, the NF data is (a) range-limited, and (b) filtered.
240 * However, this data-processing is done when reading the NF values
241 * out of the history buffer.  The history buffer stores the raw values.
242 * This allows the NF history buffer to be used to check for interference.
243 * A single high NF reading might be a bogus HW value, but if the NF
244 * readings are consistently high, it must be due to interference.
245 * This is the purpose of storing raw NF values in the history buffer,
246 * rather than processed values.  By looking at a history of NF values
247 * that have not been range-limited, we can check if they are consistently
248 * high (due to interference).
249 */
250#define AH_NF_SIGN_EXTEND(nf)      \
251    ((nf) & 0x100) ?               \
252        0 - (((nf) ^ 0x1ff) + 1) : \
253        (nf)
254void
255ar9300_upload_noise_floor(struct ath_hal *ah, int is_2g,
256    int16_t nfarray[HAL_NUM_NF_READINGS])
257{
258    int16_t nf;
259    int chan, chain;
260    u_int32_t regs[HAL_NUM_NF_READINGS] = {
261        /* control channel */
262        AR_PHY_CCA_0,     /* chain 0 */
263        AR_PHY_CCA_1,     /* chain 1 */
264        AR_PHY_CCA_2,     /* chain 2 */
265        /* extension channel */
266        AR_PHY_EXT_CCA,   /* chain 0 */
267        AR_PHY_EXT_CCA_1, /* chain 1 */
268        AR_PHY_EXT_CCA_2, /* chain 2 */
269    };
270    u_int8_t chainmask;
271
272    /*
273     * Within a given channel (ctl vs. ext), the CH0, CH1, and CH2
274     * masks and shifts are the same, though they differ for the
275     * control vs. extension channels.
276     */
277    u_int32_t masks[2] = {
278        AR_PHY_MINCCA_PWR,     /* control channel */
279        AR_PHY_EXT_MINCCA_PWR, /* extention channel */
280    };
281    u_int8_t shifts[2] = {
282        AR_PHY_MINCCA_PWR_S,     /* control channel */
283        AR_PHY_EXT_MINCCA_PWR_S, /* extention channel */
284    };
285
286    /*
287     * Force NF calibration for all chains.
288     */
289    if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
290        chainmask = 0x01;
291    } else if (AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah) || AR_SREV_HONEYBEE(ah)) {
292        chainmask = 0x03;
293    } else {
294        chainmask = 0x07;
295    }
296
297    for (chan = 0; chan < 2 /*ctl,ext*/; chan++) {
298        for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
299            int i;
300
301            if (!((chainmask >> chain) & 0x1)) {
302                continue;
303            }
304            i = chan * AR9300_MAX_CHAINS + chain;
305            nf = (OS_REG_READ(ah, regs[i]) & masks[chan]) >> shifts[chan];
306            nfarray[i] = AH_NF_SIGN_EXTEND(nf);
307        }
308    }
309}
310
311/* ar9300_get_min_cca_pwr -
312 * Used by the scan function for a quick read of the noise floor.
313 * This is used to detect presence of CW interference such as video bridge.
314 * The noise floor is assumed to have been already started during reset
315 * called during channel change. The function checks if the noise floor
316 * reading is done. In case it has been done, it reads the noise floor value.
317 * If the noise floor calibration has not been finished, it assumes this is
318 * due to presence of CW interference an returns a high value for noise floor,
319 * derived from the CW interference threshold + margin fudge factor.
320 */
321#define BAD_SCAN_NF_MARGIN (30)
322int16_t ar9300_get_min_cca_pwr(struct ath_hal *ah)
323{
324    int16_t nf;
325//    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
326
327
328    if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) {
329        nf = MS(OS_REG_READ(ah, AR_PHY_CCA_0), AR9280_PHY_MINCCA_PWR);
330        if (nf & 0x100) {
331            nf = 0 - ((nf ^ 0x1ff) + 1);
332        }
333    } else {
334        /* NF calibration is not done, assume CW interference */
335        nf = AH9300(ah)->nfp->nominal + AH9300(ah)->nf_cw_int_delta +
336            BAD_SCAN_NF_MARGIN;
337    }
338    return nf;
339}
340
341
342/*
343 * Noise Floor values for all chains.
344 * Most recently updated values from the NF history buffer are used.
345 */
346void ar9300_chain_noise_floor(struct ath_hal *ah, int16_t *nf_buf,
347    struct ieee80211_channel *chan, int is_scan)
348{
349    struct ath_hal_9300 *ahp = AH9300(ah);
350    int i, nf_hist_len, recent_nf_index = 0;
351    HAL_NFCAL_HIST_FULL *h;
352    u_int8_t rx_chainmask = ahp->ah_rx_chainmask | (ahp->ah_rx_chainmask << 3);
353    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
354    HALASSERT(ichan);
355
356#ifdef ATH_NF_PER_CHAN
357    /* Fill 0 if valid internal channel is not found */
358    if (ichan == AH_NULL) {
359        OS_MEMZERO(nf_buf, sizeof(nf_buf[0])*HAL_NUM_NF_READINGS);
360        return;
361    }
362    h = &ichan->nf_cal_hist;
363    nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL;
364#else
365    /*
366     * If a scan is not in progress, then the most recent value goes
367     * into ahpriv->nf_cal_hist.  If a scan is in progress, then
368     * the most recent value goes into ichan->nf_cal_hist.
369     * Thus, return the value from ahpriv->nf_cal_hist if there's
370     * no scan, and if the specified channel is the current channel.
371     * Otherwise, return the noise floor from ichan->nf_cal_hist.
372     */
373    if ((!is_scan) && chan == AH_PRIVATE(ah)->ah_curchan) {
374        h = &AH_PRIVATE(ah)->nf_cal_hist;
375        nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL;
376    } else {
377        /* Fill 0 if valid internal channel is not found */
378        if (ichan == AH_NULL) {
379            OS_MEMZERO(nf_buf, sizeof(nf_buf[0])*HAL_NUM_NF_READINGS);
380            return;
381        }
382       /*
383        * It is okay to treat a HAL_NFCAL_HIST_SMALL struct as if it were a
384        * HAL_NFCAL_HIST_FULL struct, as long as only the index 0 of the
385        * nf_cal_buffer is used (nf_cal_buffer[0][0:HAL_NUM_NF_READINGS-1])
386        */
387        h = (HAL_NFCAL_HIST_FULL *) &ichan->nf_cal_hist;
388        nf_hist_len = HAL_NF_CAL_HIST_LEN_SMALL;
389    }
390#endif
391    /* Get most recently updated values from nf cal history buffer */
392    recent_nf_index =
393        (h->base.curr_index) ? h->base.curr_index - 1 : nf_hist_len - 1;
394
395    for (i = 0; i < HAL_NUM_NF_READINGS; i++) {
396        /* Fill 0 for unsupported chains */
397        if (!(rx_chainmask & (1 << i))) {
398            nf_buf[i] = 0;
399            continue;
400        }
401        nf_buf[i] = h->nf_cal_buffer[recent_nf_index][i];
402    }
403}
404
405/*
406 * Return the current NF value in register.
407 * If the current NF cal is not completed, return 0.
408 */
409int16_t ar9300_get_nf_from_reg(struct ath_hal *ah, struct ieee80211_channel *chan, int wait_time)
410{
411    int16_t nfarray[HAL_NUM_NF_READINGS] = {0};
412    int is_2g = 0;
413    HAL_CHANNEL_INTERNAL *ichan = NULL;
414
415    ichan = ath_hal_checkchannel(ah, chan);
416    if (ichan == NULL)
417        return (0);
418
419    if (wait_time <= 0) {
420        return 0;
421    }
422
423    if (!ath_hal_waitfor(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF, 0, wait_time)) {
424        ath_hal_printf(ah, "%s: NF cal is not complete in %dus", __func__, wait_time);
425        return 0;
426    }
427    is_2g = !! (IS_CHAN_2GHZ(ichan));
428    ar9300_upload_noise_floor(ah, is_2g, nfarray);
429
430    return nfarray[0];
431}
432
433/*
434 * Pick up the medium one in the noise floor buffer and update the
435 * corresponding range for valid noise floor values
436 */
437static int16_t
438ar9300_get_nf_hist_mid(struct ath_hal *ah, HAL_NFCAL_HIST_FULL *h, int reading,
439    int hist_len)
440{
441    int16_t nfval;
442    int16_t sort[HAL_NF_CAL_HIST_LEN_FULL]; /* upper bound for hist_len */
443    int i, j;
444
445
446    for (i = 0; i < hist_len; i++) {
447        sort[i] = h->nf_cal_buffer[i][reading];
448        HALDEBUG(ah, HAL_DEBUG_NFCAL,
449            "nf_cal_buffer[%d][%d] = %d\n", i, reading, (int)sort[i]);
450    }
451    for (i = 0; i < hist_len - 1; i++) {
452        for (j = 1; j < hist_len - i; j++) {
453            if (sort[j] > sort[j - 1]) {
454                nfval = sort[j];
455                sort[j] = sort[j - 1];
456                sort[j - 1] = nfval;
457            }
458        }
459    }
460    nfval = sort[(hist_len - 1) >> 1];
461
462    return nfval;
463}
464
465static int16_t ar9300_limit_nf_range(struct ath_hal *ah, int16_t nf)
466{
467    if (nf < AH9300(ah)->nfp->min) {
468        return AH9300(ah)->nfp->nominal;
469    } else if (nf > AH9300(ah)->nfp->max) {
470        return AH9300(ah)->nfp->max;
471    }
472    return nf;
473}
474
475#ifndef ATH_NF_PER_CHAN
476inline static void
477ar9300_reset_nf_hist_buff(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
478{
479    HAL_CHAN_NFCAL_HIST *h = &ichan->nf_cal_hist;
480    HAL_NFCAL_HIST_FULL *home = &AH_PRIVATE(ah)->nf_cal_hist;
481    int i;
482
483    /*
484     * Copy the value for the channel in question into the home-channel
485     * NF history buffer.  The channel NF is probably a value filled in by
486     * a prior background channel scan, but if no scan has been done then
487     * it is the nominal noise floor filled in by ath_hal_init_NF_buffer
488     * for this chip and the channel's band.
489     * Replicate this channel NF into all entries of the home-channel NF
490     * history buffer.
491     * If the channel NF was filled in by a channel scan, it has not had
492     * bounds limits applied to it yet - do so now.  It is important to
493     * apply bounds limits to the priv_nf value that gets loaded into the
494     * WLAN chip's min_cca_pwr register field.  It is also necessary to
495     * apply bounds limits to the nf_cal_buffer[] elements.  Since we are
496     * replicating a single NF reading into all nf_cal_buffer elements,
497     * if the single reading were above the CW_INT threshold, the CW_INT
498     * check in ar9300_get_nf would immediately conclude that CW interference
499     * is present, even though we're not supposed to set CW_INT unless
500     * NF values are _consistently_ above the CW_INT threshold.
501     * Applying the bounds limits to the nf_cal_buffer contents fixes this
502     * problem.
503     */
504    for (i = 0; i < HAL_NUM_NF_READINGS; i ++) {
505        int j;
506        int16_t nf;
507        /*
508         * No need to set curr_index, since it already has a value in
509         * the range [0..HAL_NF_CAL_HIST_LEN_FULL), and all nf_cal_buffer
510         * values will be the same.
511         */
512        nf = ar9300_limit_nf_range(ah, h->nf_cal_buffer[0][i]);
513        for (j = 0; j < HAL_NF_CAL_HIST_LEN_FULL; j++) {
514            home->nf_cal_buffer[j][i] = nf;
515        }
516        AH_PRIVATE(ah)->nf_cal_hist.base.priv_nf[i] = nf;
517    }
518}
519#endif
520
521/*
522 *  Update the noise floor buffer as a ring buffer
523 */
524static int16_t
525ar9300_update_nf_hist_buff(struct ath_hal *ah, HAL_NFCAL_HIST_FULL *h,
526   int16_t *nfarray, int hist_len)
527{
528    int i, nr;
529    int16_t nf_no_lim_chain0;
530
531    nf_no_lim_chain0 = ar9300_get_nf_hist_mid(ah, h, 0, hist_len);
532
533    HALDEBUG(ah, HAL_DEBUG_NFCAL, "%s[%d] BEFORE\n", __func__, __LINE__);
534    for (nr = 0; nr < HAL_NF_CAL_HIST_LEN_FULL; nr++) {
535        for (i = 0; i < HAL_NUM_NF_READINGS; i++) {
536            HALDEBUG(ah, HAL_DEBUG_NFCAL,
537                "nf_cal_buffer[%d][%d] = %d\n",
538                nr, i, (int)h->nf_cal_buffer[nr][i]);
539        }
540    }
541    for (i = 0; i < HAL_NUM_NF_READINGS; i++) {
542        h->nf_cal_buffer[h->base.curr_index][i] = nfarray[i];
543        h->base.priv_nf[i] = ar9300_limit_nf_range(
544            ah, ar9300_get_nf_hist_mid(ah, h, i, hist_len));
545    }
546    HALDEBUG(ah, HAL_DEBUG_NFCAL, "%s[%d] AFTER\n", __func__, __LINE__);
547    for (nr = 0; nr < HAL_NF_CAL_HIST_LEN_FULL; nr++) {
548        for (i = 0; i < HAL_NUM_NF_READINGS; i++) {
549            HALDEBUG(ah, HAL_DEBUG_NFCAL,
550                "nf_cal_buffer[%d][%d] = %d\n",
551                nr, i, (int)h->nf_cal_buffer[nr][i]);
552        }
553    }
554
555    if (++h->base.curr_index >= hist_len) {
556        h->base.curr_index = 0;
557    }
558
559    return nf_no_lim_chain0;
560}
561
562#ifdef UNUSED
563static HAL_BOOL
564get_noise_floor_thresh(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *chan,
565    int16_t *nft)
566{
567    struct ath_hal_9300 *ahp = AH9300(ah);
568
569
570    switch (chan->channel_flags & CHANNEL_ALL_NOTURBO) {
571    case CHANNEL_A:
572    case CHANNEL_A_HT20:
573    case CHANNEL_A_HT40PLUS:
574    case CHANNEL_A_HT40MINUS:
575        *nft = (int8_t)ar9300_eeprom_get(ahp, EEP_NFTHRESH_5);
576        break;
577    case CHANNEL_B:
578    case CHANNEL_G:
579    case CHANNEL_G_HT20:
580    case CHANNEL_G_HT40PLUS:
581    case CHANNEL_G_HT40MINUS:
582        *nft = (int8_t)ar9300_eeprom_get(ahp, EEP_NFTHRESH_2);
583        break;
584    default:
585        HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: invalid channel flags 0x%x\n",
586                __func__, chan->channel_flags);
587        return AH_FALSE;
588    }
589    return AH_TRUE;
590}
591#endif
592
593/*
594 * Read the NF and check it against the noise floor threshhold
595 */
596#define IS(_c, _f)       (((_c)->channel_flags & _f) || 0)
597static int
598ar9300_store_new_nf(struct ath_hal *ah, struct ieee80211_channel *chan,
599  int is_scan)
600{
601//    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
602    int nf_hist_len;
603    int16_t nf_no_lim;
604    int16_t nfarray[HAL_NUM_NF_READINGS] = {0};
605    HAL_NFCAL_HIST_FULL *h;
606    int is_2g = 0;
607    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
608    struct ath_hal_9300 *ahp = AH9300(ah);
609
610    if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
611        u_int32_t tsf32, nf_cal_dur_tsf;
612        /*
613         * The reason the NF calibration did not complete may just be that
614         * not enough time has passed since the NF calibration was started,
615         * because under certain conditions (when first moving to a new
616         * channel) the NF calibration may be checked very repeatedly.
617         * Or, there may be CW interference keeping the NF calibration
618         * from completing.  Check the delta time between when the NF
619         * calibration was started and now to see whether the NF calibration
620         * should have already completed (but hasn't, probably due to CW
621         * interference), or hasn't had enough time to finish yet.
622         */
623        /*
624         * AH_NF_CAL_DUR_MAX_TSF - A conservative maximum time that the
625         *     HW should need to finish a NF calibration.  If the HW
626         *     does not complete a NF calibration within this time period,
627         *     there must be a problem - probably CW interference.
628         * AH_NF_CAL_PERIOD_MAX_TSF - A conservative maximum time between
629         *     check of the HW's NF calibration being finished.
630         *     If the difference between the current TSF and the TSF
631         *     recorded when the NF calibration started is larger than this
632         *     value, the TSF must have been reset.
633         *     In general, we expect the TSF to only be reset during
634         *     regular operation for STAs, not for APs.  However, an
635         *     AP's TSF could be reset when joining an IBSS.
636         *     There's an outside chance that this could result in the
637         *     CW_INT flag being erroneously set, if the TSF adjustment
638         *     is smaller than AH_NF_CAL_PERIOD_MAX_TSF but larger than
639         *     AH_NF_CAL_DUR_TSF.  However, even if this does happen,
640         *     it shouldn't matter, as the IBSS case shouldn't be
641         *     concerned about CW_INT.
642         */
643        /* AH_NF_CAL_DUR_TSF - 90 sec in usec units */
644        #define AH_NF_CAL_DUR_TSF (90 * 1000 * 1000)
645        /* AH_NF_CAL_PERIOD_MAX_TSF - 180 sec in usec units */
646        #define AH_NF_CAL_PERIOD_MAX_TSF (180 * 1000 * 1000)
647        /* wraparound handled by using unsigned values */
648        tsf32 = ar9300_get_tsf32(ah);
649        nf_cal_dur_tsf = tsf32 - AH9300(ah)->nf_tsf32;
650        if (nf_cal_dur_tsf > AH_NF_CAL_PERIOD_MAX_TSF) {
651            /*
652             * The TSF must have gotten reset during the NF cal -
653             * just reset the NF TSF timestamp, so the next time
654             * this function is called, the timestamp comparison
655             * will be valid.
656             */
657            AH9300(ah)->nf_tsf32 = tsf32;
658        } else if (nf_cal_dur_tsf > AH_NF_CAL_DUR_TSF) {
659            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
660                "%s: NF did not complete in calibration window\n", __func__);
661            /* the NF incompletion is probably due to CW interference */
662            chan->ic_state |= IEEE80211_CHANSTATE_CWINT;
663        }
664        return 0; /* HW's NF measurement not finished */
665    }
666    HALDEBUG(ah, HAL_DEBUG_NFCAL,
667        "%s[%d] chan %d\n", __func__, __LINE__, ichan->channel);
668    is_2g = !! IS_CHAN_2GHZ(ichan);
669    ar9300_upload_noise_floor(ah, is_2g, nfarray);
670
671    /* Update the NF buffer for each chain masked by chainmask */
672#ifdef ATH_NF_PER_CHAN
673    h = &ichan->nf_cal_hist;
674    nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL;
675#else
676    if (is_scan) {
677        /*
678         * This channel's NF cal info is just a HAL_NFCAL_HIST_SMALL struct
679         * rather than a HAL_NFCAL_HIST_FULL struct.
680         * As long as we only use the first history element of nf_cal_buffer
681         * (nf_cal_buffer[0][0:HAL_NUM_NF_READINGS-1]), we can use
682         * HAL_NFCAL_HIST_SMALL and HAL_NFCAL_HIST_FULL interchangeably.
683         */
684        h = (HAL_NFCAL_HIST_FULL *) &ichan->nf_cal_hist;
685        nf_hist_len = HAL_NF_CAL_HIST_LEN_SMALL;
686    } else {
687        h = &AH_PRIVATE(ah)->nf_cal_hist;
688        nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL;
689    }
690#endif
691
692    /*
693     * nf_no_lim = median value from NF history buffer without bounds limits,
694     * priv_nf = median value from NF history buffer with bounds limits.
695     */
696    nf_no_lim = ar9300_update_nf_hist_buff(ah, h, nfarray, nf_hist_len);
697    ichan->rawNoiseFloor = h->base.priv_nf[0];
698
699    /* check if there is interference */
700//    ichan->channel_flags &= (~CHANNEL_CW_INT);
701    /*
702     * Use AR9300_EMULATION to check for emulation purpose as PCIE Device ID
703     * 0xABCD is recognized as valid Osprey as WAR in some EVs.
704     */
705    if (nf_no_lim > ahp->nfp->nominal + ahp->nf_cw_int_delta) {
706        /*
707         * Since this CW interference check is being applied to the
708         * median element of the NF history buffer, this indicates that
709         * the CW interference is persistent.  A single high NF reading
710         * will not show up in the median, and thus will not cause the
711         * CW_INT flag to be set.
712         */
713        HALDEBUG(ah, HAL_DEBUG_NFCAL,
714            "%s: NF Cal: CW interferer detected through NF: %d\n",
715            __func__, nf_no_lim);
716        chan->ic_state |= IEEE80211_CHANSTATE_CWINT;
717    }
718    return 1; /* HW's NF measurement finished */
719}
720#undef IS
721
722static inline void
723ar9300_get_delta_slope_values(struct ath_hal *ah, u_int32_t coef_scaled,
724    u_int32_t *coef_mantissa, u_int32_t *coef_exponent)
725{
726    u_int32_t coef_exp, coef_man;
727
728    /*
729     * ALGO -> coef_exp = 14-floor(log2(coef));
730     * floor(log2(x)) is the highest set bit position
731     */
732    for (coef_exp = 31; coef_exp > 0; coef_exp--) {
733        if ((coef_scaled >> coef_exp) & 0x1) {
734            break;
735        }
736    }
737    /* A coef_exp of 0 is a legal bit position but an unexpected coef_exp */
738    HALASSERT(coef_exp);
739    coef_exp = 14 - (coef_exp - COEF_SCALE_S);
740
741
742    /*
743     * ALGO -> coef_man = floor(coef* 2^coef_exp+0.5);
744     * The coefficient is already shifted up for scaling
745     */
746    coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
747
748    *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
749    *coef_exponent = coef_exp - 16;
750}
751
752#define MAX_ANALOG_START        319             /* XXX */
753
754/*
755 * Delta slope coefficient computation.
756 * Required for OFDM operation.
757 */
758static void
759ar9300_set_delta_slope(struct ath_hal *ah, struct ieee80211_channel *chan)
760{
761    u_int32_t coef_scaled, ds_coef_exp, ds_coef_man;
762    u_int32_t fclk = COEFF; /* clock * 2.5 */
763
764    u_int32_t clock_mhz_scaled = 0x1000000 * fclk;
765    CHAN_CENTERS centers;
766
767    /*
768     * half and quarter rate can divide the scaled clock by 2 or 4
769     * scale for selected channel bandwidth
770     */
771    if (IEEE80211_IS_CHAN_HALF(chan)) {
772        clock_mhz_scaled = clock_mhz_scaled >> 1;
773    } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
774        clock_mhz_scaled = clock_mhz_scaled >> 2;
775    }
776
777    /*
778     * ALGO -> coef = 1e8/fcarrier*fclock/40;
779     * scaled coef to provide precision for this floating calculation
780     */
781    ar9300_get_channel_centers(ah, chan, &centers);
782    coef_scaled = clock_mhz_scaled / centers.synth_center;
783
784    ar9300_get_delta_slope_values(ah, coef_scaled, &ds_coef_man, &ds_coef_exp);
785
786    OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
787    OS_REG_RMW_FIELD(ah, AR_PHY_TIMING3, AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
788
789    /*
790     * For Short GI,
791     * scaled coeff is 9/10 that of normal coeff
792     */
793    coef_scaled = (9 * coef_scaled) / 10;
794
795    ar9300_get_delta_slope_values(ah, coef_scaled, &ds_coef_man, &ds_coef_exp);
796
797    /* for short gi */
798    OS_REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, AR_PHY_SGI_DSC_MAN, ds_coef_man);
799    OS_REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, AR_PHY_SGI_DSC_EXP, ds_coef_exp);
800}
801
802#define IS(_c, _f)       (IEEE80211_IS_ ## _f(_c))
803
804/*
805 * XXX FreeBSD: This should be turned into something generic in ath_hal!
806 */
807HAL_CHANNEL_INTERNAL *
808ar9300_check_chan(struct ath_hal *ah, const struct ieee80211_channel *chan)
809{
810
811    if (chan == NULL) {
812        return AH_NULL;
813    }
814
815    if ((IS(chan, CHAN_2GHZ) ^ IS(chan, CHAN_5GHZ)) == 0) {
816        HALDEBUG(ah, HAL_DEBUG_CHANNEL,
817            "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n",
818            __func__, chan->ic_freq , chan->ic_flags);
819        return AH_NULL;
820    }
821
822    /*
823     * FreeBSD sets multiple flags, so this will fail.
824     */
825#if 0
826    if ((IS(chan, CHAN_OFDM) ^ IS(chan, CHAN_CCK) ^ IS(chan, CHAN_DYN) ^
827         IS(chan, CHAN_HT20) ^ IS(chan, CHAN_HT40U) ^
828         IS(chan, CHAN_HT40D)) == 0)
829    {
830        HALDEBUG(ah, HAL_DEBUG_CHANNEL,
831            "%s: invalid channel %u/0x%x; not marked as "
832            "OFDM or CCK or DYN or HT20 or HT40PLUS or HT40MINUS\n",
833            __func__, chan->ic_freq , chan->ic_flags);
834        return AH_NULL;
835    }
836#endif
837
838    return (ath_hal_checkchannel(ah, chan));
839}
840#undef IS
841
842static void
843ar9300_set_11n_regs(struct ath_hal *ah, struct ieee80211_channel *chan,
844    HAL_HT_MACMODE macmode)
845{
846    u_int32_t phymode;
847//    struct ath_hal_9300 *ahp = AH9300(ah);
848    u_int32_t enable_dac_fifo;
849
850    /* XXX */
851    enable_dac_fifo =
852        OS_REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO;
853
854    /* Enable 11n HT, 20 MHz */
855    phymode =
856        AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_SHORT_GI_40
857        | enable_dac_fifo;
858    /* Configure baseband for dynamic 20/40 operation */
859    if (IEEE80211_IS_CHAN_HT40(chan)) {
860        phymode |= AR_PHY_GC_DYN2040_EN;
861        /* Configure control (primary) channel at +-10MHz */
862        if (IEEE80211_IS_CHAN_HT40U(chan)) {
863            phymode |= AR_PHY_GC_DYN2040_PRI_CH;
864        }
865
866#if 0
867        /* Configure 20/25 spacing */
868        if (ahp->ah_ext_prot_spacing == HAL_HT_EXTPROTSPACING_25) {
869            phymode |= AR_PHY_GC_DYN2040_EXT_CH;
870        }
871#endif
872    }
873
874    /* make sure we preserve INI settings */
875    phymode |= OS_REG_READ(ah, AR_PHY_GEN_CTRL);
876
877    /* EV 62881/64991 - turn off Green Field detection for Maverick STA beta */
878    phymode &= ~AR_PHY_GC_GF_DETECT_EN;
879
880    OS_REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode);
881
882    /* Set IFS timing for half/quarter rates */
883    if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan)) {
884        u_int32_t modeselect = OS_REG_READ(ah, AR_PHY_MODE);
885
886        if (IEEE80211_IS_CHAN_HALF(chan)) {
887            modeselect |= AR_PHY_MS_HALF_RATE;
888        } else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
889            modeselect |= AR_PHY_MS_QUARTER_RATE;
890        }
891        OS_REG_WRITE(ah, AR_PHY_MODE, modeselect);
892
893        ar9300_set_ifs_timing(ah, chan);
894        OS_REG_RMW_FIELD(
895            ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_CF_OVERLAP_WINDOW, 0x3);
896    }
897
898    /* Configure MAC for 20/40 operation */
899    ar9300_set_11n_mac2040(ah, macmode);
900
901    /* global transmit timeout (25 TUs default)*/
902    /* XXX - put this elsewhere??? */
903    OS_REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
904
905    /* carrier sense timeout */
906    OS_REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
907}
908
909/*
910 * Spur mitigation for MRC CCK
911 */
912static void
913ar9300_spur_mitigate_mrc_cck(struct ath_hal *ah, struct ieee80211_channel *chan)
914{
915    int i;
916    /* spur_freq_for_osprey - hardcoded by Systems team for now. */
917    u_int32_t spur_freq_for_osprey[4] = { 2420, 2440, 2464, 2480 };
918    u_int32_t spur_freq_for_jupiter[2] = { 2440, 2464};
919    int cur_bb_spur, negative = 0, cck_spur_freq;
920    u_int8_t* spur_fbin_ptr = NULL;
921    int synth_freq;
922    int range = 10;
923    int max_spurcounts = OSPREY_EEPROM_MODAL_SPURS;
924    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
925
926    /*
927     * Need to verify range +/- 10 MHz in control channel, otherwise spur
928     * is out-of-band and can be ignored.
929     */
930    if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) ||
931        AR_SREV_WASP(ah)  || AR_SREV_SCORPION(ah)) {
932        spur_fbin_ptr = ar9300_eeprom_get_spur_chans_ptr(ah, 1);
933        if (spur_fbin_ptr[0] == 0) {
934            return;      /* No spur in the mode */
935        }
936        if (IEEE80211_IS_CHAN_HT40(chan)) {
937            range = 19;
938            if (OS_REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH)
939                == 0x0)
940            {
941                synth_freq = ichan->channel + 10;
942            } else {
943                synth_freq = ichan->channel - 10;
944            }
945        } else {
946            range = 10;
947            synth_freq = ichan->channel;
948        }
949    } else if(AR_SREV_JUPITER(ah)) {
950        range = 5;
951        max_spurcounts = 2; /* Hardcoded by Jupiter Systems team for now. */
952        synth_freq = ichan->channel;
953    } else {
954        range = 10;
955        max_spurcounts = 4; /* Hardcoded by Osprey Systems team for now. */
956        synth_freq = ichan->channel;
957    }
958
959    for (i = 0; i < max_spurcounts; i++) {
960        negative = 0;
961
962        if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) ||
963            AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
964            cur_bb_spur =
965                FBIN2FREQ(spur_fbin_ptr[i], HAL_FREQ_BAND_2GHZ) - synth_freq;
966        } else if(AR_SREV_JUPITER(ah)) {
967            cur_bb_spur = spur_freq_for_jupiter[i] - synth_freq;
968        } else {
969            cur_bb_spur = spur_freq_for_osprey[i] - synth_freq;
970        }
971
972        if (cur_bb_spur < 0) {
973            negative = 1;
974            cur_bb_spur = -cur_bb_spur;
975        }
976        if (cur_bb_spur < range) {
977            cck_spur_freq = (int)((cur_bb_spur << 19) / 11);
978            if (negative == 1) {
979                cck_spur_freq = -cck_spur_freq;
980            }
981            cck_spur_freq = cck_spur_freq & 0xfffff;
982            /*OS_REG_WRITE_field(ah, BB_agc_control.ycok_max, 0x7);*/
983            OS_REG_RMW_FIELD(ah,
984                AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_YCOK_MAX, 0x7);
985            /*OS_REG_WRITE_field(ah, BB_cck_spur_mit.spur_rssi_thr, 0x7f);*/
986            OS_REG_RMW_FIELD(ah,
987                AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR, 0x7f);
988            /*OS_REG_WRITE(ah, BB_cck_spur_mit.spur_filter_type, 0x2);*/
989            OS_REG_RMW_FIELD(ah,
990                AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE, 0x2);
991            /*OS_REG_WRITE(ah, BB_cck_spur_mit.use_cck_spur_mit, 0x1);*/
992            OS_REG_RMW_FIELD(ah,
993                AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, 0x1);
994            /*OS_REG_WRITE(ah, BB_cck_spur_mit.cck_spur_freq, cck_spur_freq);*/
995            OS_REG_RMW_FIELD(ah,
996                AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ,
997                cck_spur_freq);
998            return;
999        }
1000    }
1001
1002    /*OS_REG_WRITE(ah, BB_agc_control.ycok_max, 0x5);*/
1003    OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_YCOK_MAX, 0x5);
1004    /*OS_REG_WRITE(ah, BB_cck_spur_mit.use_cck_spur_mit, 0x0);*/
1005    OS_REG_RMW_FIELD(ah,
1006        AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, 0x0);
1007    /*OS_REG_WRITE(ah, BB_cck_spur_mit.cck_spur_freq, 0x0);*/
1008    OS_REG_RMW_FIELD(ah,
1009        AR_PHY_CCK_SPUR_MIT, AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0x0);
1010}
1011
1012/* Spur mitigation for OFDM */
1013static void
1014ar9300_spur_mitigate_ofdm(struct ath_hal *ah, struct ieee80211_channel *chan)
1015{
1016    int synth_freq;
1017    int range = 10;
1018    int freq_offset = 0;
1019    int spur_freq_sd = 0;
1020    int spur_subchannel_sd = 0;
1021    int spur_delta_phase = 0;
1022    int mask_index = 0;
1023    int i;
1024    int mode;
1025    u_int8_t* spur_chans_ptr;
1026    struct ath_hal_9300 *ahp;
1027    ahp = AH9300(ah);
1028    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
1029
1030    if (IS_CHAN_5GHZ(ichan)) {
1031        spur_chans_ptr = ar9300_eeprom_get_spur_chans_ptr(ah, 0);
1032        mode = 0;
1033    } else {
1034        spur_chans_ptr = ar9300_eeprom_get_spur_chans_ptr(ah, 1);
1035        mode = 1;
1036    }
1037
1038    if (IEEE80211_IS_CHAN_HT40(chan)) {
1039        range = 19;
1040        if (OS_REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH)
1041            == 0x0)
1042        {
1043            synth_freq = ichan->channel - 10;
1044        } else {
1045            synth_freq = ichan->channel + 10;
1046        }
1047    } else {
1048        range = 10;
1049        synth_freq = ichan->channel;
1050    }
1051
1052    /* Clean all spur register fields */
1053    OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0);
1054    OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_FREQ_SD, 0);
1055    OS_REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_DELTA_PHASE, 0);
1056    OS_REG_RMW_FIELD(ah,
1057        AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, 0);
1058    OS_REG_RMW_FIELD(ah,
1059        AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0);
1060    OS_REG_RMW_FIELD(ah,
1061        AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0);
1062    OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0);
1063    OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 0);
1064    OS_REG_RMW_FIELD(ah,
1065        AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 0);
1066    OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0);
1067    OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0);
1068    OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0);
1069    OS_REG_RMW_FIELD(ah,
1070        AR_PHY_PILOT_SPUR_MASK, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, 0);
1071    OS_REG_RMW_FIELD(ah,
1072        AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, 0);
1073    OS_REG_RMW_FIELD(ah,
1074        AR_PHY_CHAN_SPUR_MASK, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, 0);
1075    OS_REG_RMW_FIELD(ah,
1076        AR_PHY_PILOT_SPUR_MASK, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0);
1077    OS_REG_RMW_FIELD(ah,
1078        AR_PHY_CHAN_SPUR_MASK, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0);
1079    OS_REG_RMW_FIELD(ah,
1080        AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0);
1081    OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0);
1082
1083    i = 0;
1084    while (spur_chans_ptr[i] && i < 5) {
1085        freq_offset = FBIN2FREQ(spur_chans_ptr[i], mode) - synth_freq;
1086        if (abs(freq_offset) < range) {
1087            /*
1088            printf(
1089                "Spur Mitigation for OFDM: Synth Frequency = %d, "
1090                "Spur Frequency = %d\n",
1091                synth_freq, FBIN2FREQ(spur_chans_ptr[i], mode));
1092             */
1093            if (IEEE80211_IS_CHAN_HT40(chan)) {
1094                if (freq_offset < 0) {
1095                    if (OS_REG_READ_FIELD(
1096                        ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
1097                    {
1098                        spur_subchannel_sd = 1;
1099                    } else {
1100                        spur_subchannel_sd = 0;
1101                    }
1102                    spur_freq_sd = ((freq_offset + 10) << 9) / 11;
1103                } else {
1104                    if (OS_REG_READ_FIELD(ah,
1105                        AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
1106                    {
1107                        spur_subchannel_sd = 0;
1108                    } else {
1109                        spur_subchannel_sd = 1;
1110                    }
1111                    spur_freq_sd = ((freq_offset - 10) << 9) / 11;
1112                }
1113                spur_delta_phase = (freq_offset << 17) / 5;
1114            } else {
1115                spur_subchannel_sd = 0;
1116                spur_freq_sd = (freq_offset << 9) / 11;
1117                spur_delta_phase = (freq_offset << 18) / 5;
1118            }
1119            spur_freq_sd = spur_freq_sd & 0x3ff;
1120            spur_delta_phase = spur_delta_phase & 0xfffff;
1121            /*
1122            printf(
1123                "spur_subchannel_sd = %d, spur_freq_sd = 0x%x, "
1124                "spur_delta_phase = 0x%x\n", spur_subchannel_sd,
1125                spur_freq_sd, spur_delta_phase);
1126             */
1127
1128            /* OFDM Spur mitigation */
1129            OS_REG_RMW_FIELD(ah,
1130                AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0x1);
1131            OS_REG_RMW_FIELD(ah,
1132                AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd);
1133            OS_REG_RMW_FIELD(ah,
1134                AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_DELTA_PHASE,
1135                spur_delta_phase);
1136            OS_REG_RMW_FIELD(ah,
1137                AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD,
1138                spur_subchannel_sd);
1139            OS_REG_RMW_FIELD(ah,
1140                AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1);
1141            OS_REG_RMW_FIELD(ah,
1142                AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR,
1143                0x1);
1144            OS_REG_RMW_FIELD(ah,
1145                AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1);
1146            OS_REG_RMW_FIELD(ah,
1147                AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34);
1148            OS_REG_RMW_FIELD(ah,
1149                AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1);
1150
1151            /*
1152             * Do not subtract spur power from noise floor for wasp.
1153             * This causes the maximum client test (on Veriwave) to fail
1154             * when run on spur channel (2464 MHz).
1155             * Refer to ev#82746 and ev#82744.
1156             */
1157            if (!AR_SREV_WASP(ah) && (OS_REG_READ_FIELD(ah, AR_PHY_MODE,
1158                                           AR_PHY_MODE_DYNAMIC) == 0x1)) {
1159                OS_REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
1160                    AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1);
1161            }
1162
1163            mask_index = (freq_offset << 4) / 5;
1164            if (mask_index < 0) {
1165                mask_index = mask_index - 1;
1166            }
1167            mask_index = mask_index & 0x7f;
1168            /*printf("Bin 0x%x\n", mask_index);*/
1169
1170            OS_REG_RMW_FIELD(ah,
1171                AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0x1);
1172            OS_REG_RMW_FIELD(ah,
1173                AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0x1);
1174            OS_REG_RMW_FIELD(ah,
1175                AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0x1);
1176            OS_REG_RMW_FIELD(ah,
1177                AR_PHY_PILOT_SPUR_MASK,
1178                AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, mask_index);
1179            OS_REG_RMW_FIELD(ah,
1180                AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A,
1181                mask_index);
1182            OS_REG_RMW_FIELD(ah,
1183                AR_PHY_CHAN_SPUR_MASK,
1184                AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, mask_index);
1185            OS_REG_RMW_FIELD(ah,
1186                AR_PHY_PILOT_SPUR_MASK, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A,
1187                0xc);
1188            OS_REG_RMW_FIELD(ah,
1189                AR_PHY_CHAN_SPUR_MASK, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A,
1190                0xc);
1191            OS_REG_RMW_FIELD(ah,
1192                AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0);
1193            OS_REG_RMW_FIELD(ah,
1194                AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff);
1195            /*
1196            printf("BB_timing_control_4 = 0x%x\n",
1197                OS_REG_READ(ah, AR_PHY_TIMING4));
1198            printf("BB_timing_control_11 = 0x%x\n",
1199                OS_REG_READ(ah, AR_PHY_TIMING11));
1200            printf("BB_ext_chan_scorr_thr = 0x%x\n",
1201                OS_REG_READ(ah, AR_PHY_SFCORR_EXT));
1202            printf("BB_spur_mask_controls = 0x%x\n",
1203                OS_REG_READ(ah, AR_PHY_SPUR_REG));
1204            printf("BB_pilot_spur_mask = 0x%x\n",
1205                OS_REG_READ(ah, AR_PHY_PILOT_SPUR_MASK));
1206            printf("BB_chan_spur_mask = 0x%x\n",
1207                OS_REG_READ(ah, AR_PHY_CHAN_SPUR_MASK));
1208            printf("BB_vit_spur_mask_A = 0x%x\n",
1209                OS_REG_READ(ah, AR_PHY_SPUR_MASK_A));
1210             */
1211            break;
1212        }
1213        i++;
1214    }
1215}
1216
1217
1218/*
1219 * Convert to baseband spur frequency given input channel frequency
1220 * and compute register settings below.
1221 */
1222static void
1223ar9300_spur_mitigate(struct ath_hal *ah, struct ieee80211_channel *chan)
1224{
1225    ar9300_spur_mitigate_ofdm(ah, chan);
1226    ar9300_spur_mitigate_mrc_cck(ah, chan);
1227}
1228
1229/**************************************************************
1230 * ar9300_channel_change
1231 * Assumes caller wants to change channel, and not reset.
1232 */
1233static inline HAL_BOOL
1234ar9300_channel_change(struct ath_hal *ah, struct ieee80211_channel *chan,
1235    HAL_CHANNEL_INTERNAL *ichan, HAL_HT_MACMODE macmode)
1236{
1237
1238    u_int32_t synth_delay, qnum;
1239    struct ath_hal_9300 *ahp = AH9300(ah);
1240
1241    /* TX must be stopped by now */
1242    for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
1243        if (ar9300_num_tx_pending(ah, qnum)) {
1244            HALDEBUG(ah, HAL_DEBUG_QUEUE,
1245                "%s: Transmit frames pending on queue %d\n", __func__, qnum);
1246            HALASSERT(0);
1247            return AH_FALSE;
1248        }
1249    }
1250
1251
1252    /*
1253     * Kill last Baseband Rx Frame - Request analog bus grant
1254     */
1255    OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
1256    if (!ath_hal_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
1257            AR_PHY_RFBUS_GRANT_EN))
1258    {
1259        HALDEBUG(ah, HAL_DEBUG_PHYIO,
1260            "%s: Could not kill baseband RX\n", __func__);
1261        return AH_FALSE;
1262    }
1263
1264
1265    /* Setup 11n MAC/Phy mode registers */
1266    ar9300_set_11n_regs(ah, chan, macmode);
1267
1268    /*
1269     * Change the synth
1270     */
1271    if (!ahp->ah_rf_hal.set_channel(ah, chan)) {
1272        HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: failed to set channel\n", __func__);
1273        return AH_FALSE;
1274    }
1275
1276    /*
1277     * Some registers get reinitialized during ATH_INI_POST INI programming.
1278     */
1279    ar9300_init_user_settings(ah);
1280
1281    /*
1282     * Setup the transmit power values.
1283     *
1284     * After the public to private hal channel mapping, ichan contains the
1285     * valid regulatory power value.
1286     * ath_hal_getctl and ath_hal_getantennaallowed look up ichan from chan.
1287     */
1288    if (ar9300_eeprom_set_transmit_power(
1289         ah, &ahp->ah_eeprom, chan, ath_hal_getctl(ah, chan),
1290         ath_hal_getantennaallowed(ah, chan),
1291         ath_hal_get_twice_max_regpower(AH_PRIVATE(ah), ichan, chan),
1292         AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit)) != HAL_OK)
1293    {
1294        HALDEBUG(ah, HAL_DEBUG_EEPROM,
1295            "%s: error init'ing transmit power\n", __func__);
1296        return AH_FALSE;
1297    }
1298
1299    /*
1300     * Release the RFBus Grant.
1301     */
1302    OS_REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
1303
1304    /*
1305     * Write spur immunity and delta slope for OFDM enabled modes (A, G, Turbo)
1306     */
1307    if (IEEE80211_IS_CHAN_OFDM(chan) || IEEE80211_IS_CHAN_HT(chan)) {
1308        ar9300_set_delta_slope(ah, chan);
1309    } else {
1310        /* Set to Ini default */
1311        OS_REG_WRITE(ah, AR_PHY_TIMING3, 0x9c0a9f6b);
1312        OS_REG_WRITE(ah, AR_PHY_SGI_DELTA, 0x00046384);
1313    }
1314
1315    ar9300_spur_mitigate(ah, chan);
1316
1317
1318    /*
1319     * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN).
1320     * Read the phy active delay register. Value is in 100ns increments.
1321     */
1322    synth_delay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
1323    if (IEEE80211_IS_CHAN_CCK(chan)) {
1324        synth_delay = (4 * synth_delay) / 22;
1325    } else {
1326        synth_delay /= 10;
1327    }
1328
1329    OS_DELAY(synth_delay + BASE_ACTIVATE_DELAY);
1330
1331    /*
1332     * Do calibration.
1333     */
1334
1335    return AH_TRUE;
1336}
1337
1338void
1339ar9300_set_operating_mode(struct ath_hal *ah, int opmode)
1340{
1341    u_int32_t val;
1342
1343    val = OS_REG_READ(ah, AR_STA_ID1);
1344    val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
1345    switch (opmode) {
1346    case HAL_M_HOSTAP:
1347        OS_REG_WRITE(ah, AR_STA_ID1,
1348            val | AR_STA_ID1_STA_AP | AR_STA_ID1_KSRCH_MODE);
1349        OS_REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
1350        break;
1351    case HAL_M_IBSS:
1352        OS_REG_WRITE(ah, AR_STA_ID1,
1353            val | AR_STA_ID1_ADHOC | AR_STA_ID1_KSRCH_MODE);
1354        OS_REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
1355        break;
1356    case HAL_M_STA:
1357    case HAL_M_MONITOR:
1358        OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
1359        break;
1360    }
1361}
1362
1363/* XXX need the logic for Osprey */
1364void
1365ar9300_init_pll(struct ath_hal *ah, struct ieee80211_channel *chan)
1366{
1367    u_int32_t pll;
1368    u_int8_t clk_25mhz = AH9300(ah)->clk_25mhz;
1369    HAL_CHANNEL_INTERNAL *ichan = NULL;
1370
1371    if (chan)
1372        ichan = ath_hal_checkchannel(ah, chan);
1373
1374    if (AR_SREV_HORNET(ah)) {
1375        if (clk_25mhz) {
1376            /* Hornet uses PLL_CONTROL_2. Xtal is 25MHz for Hornet.
1377             * REFDIV set to 0x1.
1378             * $xtal_freq = 25;
1379             * $PLL2_div = (704/$xtal_freq); # 176 * 4 = 704.
1380             * MAC and BB run at 176 MHz.
1381             * $PLL2_divint = int($PLL2_div);
1382             * $PLL2_divfrac = $PLL2_div - $PLL2_divint;
1383             * $PLL2_divfrac = int($PLL2_divfrac * 0x4000); # 2^14
1384             * $PLL2_Val = ($PLL2_divint & 0x3f) << 19 | (0x1) << 14 |
1385             *     $PLL2_divfrac & 0x3fff;
1386             * Therefore, $PLL2_Val = 0xe04a3d
1387             */
1388#define DPLL2_KD_VAL            0x1D
1389#define DPLL2_KI_VAL            0x06
1390#define DPLL3_PHASE_SHIFT_VAL   0x1
1391
1392            /* Rewrite DDR PLL2 and PLL3 */
1393            /* program DDR PLL ki and kd value, ki=0x6, kd=0x1d */
1394            OS_REG_WRITE(ah, AR_HORNET_CH0_DDR_DPLL2, 0x18e82f01);
1395
1396            /* program DDR PLL phase_shift to 0x1 */
1397            OS_REG_RMW_FIELD(ah, AR_HORNET_CH0_DDR_DPLL3,
1398                AR_PHY_BB_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
1399
1400            OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
1401            OS_DELAY(1000);
1402
1403            /* program refdiv, nint, frac to RTC register */
1404            OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0xe04a3d);
1405
1406            /* program BB PLL ki and kd value, ki=0x6, kd=0x1d */
1407            OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1408                AR_PHY_BB_DPLL2_KD, DPLL2_KD_VAL);
1409            OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1410                AR_PHY_BB_DPLL2_KI, DPLL2_KI_VAL);
1411
1412            /* program BB PLL phase_shift to 0x1 */
1413            OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL3,
1414                AR_PHY_BB_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
1415        } else { /* 40MHz */
1416#undef  DPLL2_KD_VAL
1417#undef  DPLL2_KI_VAL
1418#define DPLL2_KD_VAL            0x3D
1419#define DPLL2_KI_VAL            0x06
1420            /* Rewrite DDR PLL2 and PLL3 */
1421            /* program DDR PLL ki and kd value, ki=0x6, kd=0x3d */
1422            OS_REG_WRITE(ah, AR_HORNET_CH0_DDR_DPLL2, 0x19e82f01);
1423
1424            /* program DDR PLL phase_shift to 0x1 */
1425            OS_REG_RMW_FIELD(ah, AR_HORNET_CH0_DDR_DPLL3,
1426                AR_PHY_BB_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
1427
1428            OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
1429            OS_DELAY(1000);
1430
1431            /* program refdiv, nint, frac to RTC register */
1432            OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
1433
1434            /* program BB PLL ki and kd value, ki=0x6, kd=0x3d */
1435            OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1436                AR_PHY_BB_DPLL2_KD, DPLL2_KD_VAL);
1437            OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1438                AR_PHY_BB_DPLL2_KI, DPLL2_KI_VAL);
1439
1440            /* program BB PLL phase_shift to 0x1 */
1441            OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL3,
1442                AR_PHY_BB_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
1443        }
1444        OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c);
1445        OS_DELAY(1000);
1446    } else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
1447        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2, AR_PHY_BB_DPLL2_PLL_PWD, 0x1);
1448
1449        /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */
1450        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1451            AR_PHY_BB_DPLL2_KD, 0x40);
1452        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1453            AR_PHY_BB_DPLL2_KI, 0x4);
1454
1455        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL1,
1456            AR_PHY_BB_DPLL1_REFDIV, 0x5);
1457        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL1,
1458            AR_PHY_BB_DPLL1_NINI, 0x58);
1459        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL1,
1460            AR_PHY_BB_DPLL1_NFRAC, 0x0);
1461
1462        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1463            AR_PHY_BB_DPLL2_OUTDIV, 0x1);
1464        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1465            AR_PHY_BB_DPLL2_LOCAL_PLL, 0x1);
1466        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1467            AR_PHY_BB_DPLL2_EN_NEGTRIG, 0x1);
1468
1469        /* program BB PLL phase_shift to 0x6 */
1470        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL3,
1471            AR_PHY_BB_DPLL3_PHASE_SHIFT, 0x6);
1472
1473        OS_REG_RMW_FIELD(ah, AR_PHY_BB_DPLL2,
1474            AR_PHY_BB_DPLL2_PLL_PWD, 0x0);
1475        OS_DELAY(1000);
1476
1477        OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c);
1478        OS_DELAY(1000);
1479    } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {
1480#define SRIF_PLL 1
1481        u_int32_t regdata, pll2_divint, pll2_divfrac;
1482
1483#ifndef SRIF_PLL
1484	u_int32_t pll2_clkmode;
1485#endif
1486
1487#ifdef SRIF_PLL
1488        u_int32_t refdiv;
1489#endif
1490        if (clk_25mhz) {
1491#ifndef SRIF_PLL
1492            pll2_divint = 0x1c;
1493            pll2_divfrac = 0xa3d7;
1494#else
1495            if (AR_SREV_HONEYBEE(ah)) {
1496                pll2_divint = 0x1c;
1497                pll2_divfrac = 0xa3d2;
1498                refdiv = 1;
1499            } else {
1500                pll2_divint = 0x54;
1501                pll2_divfrac = 0x1eb85;
1502                refdiv = 3;
1503            }
1504#endif
1505        } else {
1506#ifndef SRIF_PLL
1507            pll2_divint = 0x11;
1508            pll2_divfrac = 0x26666;
1509#else
1510            if (AR_SREV_WASP(ah)) {
1511                pll2_divint = 88;
1512                pll2_divfrac = 0;
1513                refdiv = 5;
1514            } else {
1515                pll2_divint = 0x11;
1516                pll2_divfrac = 0x26666;
1517                refdiv = 1;
1518            }
1519#endif
1520        }
1521#ifndef SRIF_PLL
1522        pll2_clkmode = 0x3d;
1523#endif
1524        /* PLL programming through SRIF Local Mode */
1525        OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); /* Bypass mode */
1526        OS_DELAY(1000);
1527        do {
1528            regdata = OS_REG_READ(ah, AR_PHY_PLL_MODE);
1529            if (AR_SREV_HONEYBEE(ah)) {
1530                regdata = regdata | (0x1 << 22);
1531            } else {
1532                regdata = regdata | (0x1 << 16);
1533            }
1534            OS_REG_WRITE(ah, AR_PHY_PLL_MODE, regdata); /* PWD_PLL set to 1 */
1535            OS_DELAY(100);
1536            /* override int, frac, refdiv */
1537#ifndef SRIF_PLL
1538            OS_REG_WRITE(ah, AR_PHY_PLL_CONTROL,
1539                ((1 << 27) | (pll2_divint << 18) | pll2_divfrac));
1540#else
1541            OS_REG_WRITE(ah, AR_PHY_PLL_CONTROL,
1542                ((refdiv << 27) | (pll2_divint << 18) | pll2_divfrac));
1543#endif
1544            OS_DELAY(100);
1545            regdata = OS_REG_READ(ah, AR_PHY_PLL_MODE);
1546#ifndef SRIF_PLL
1547            regdata = (regdata & 0x80071fff) |
1548                (0x1 << 30) | (0x1 << 13) | (0x6 << 26) | (pll2_clkmode << 19);
1549#else
1550            if (AR_SREV_WASP(ah)) {
1551                regdata = (regdata & 0x80071fff) |
1552                    (0x1 << 30) | (0x1 << 13) | (0x4 << 26) | (0x18 << 19);
1553            } else if (AR_SREV_HONEYBEE(ah)) {
1554                /*
1555                 * Kd=10, Ki=2, Outdiv=1, Local PLL=0, Phase Shift=4
1556                 */
1557                regdata = (regdata & 0x01c00fff) |
1558                    (0x1 << 31) | (0x2 << 29) | (0xa << 25) | (0x1 << 19) | (0x6 << 12);
1559            } else {
1560                regdata = (regdata & 0x80071fff) |
1561                    (0x3 << 30) | (0x1 << 13) | (0x4 << 26) | (0x60 << 19);
1562            }
1563#endif
1564            /* Ki, Kd, Local PLL, Outdiv */
1565            OS_REG_WRITE(ah, AR_PHY_PLL_MODE, regdata);
1566            regdata = OS_REG_READ(ah, AR_PHY_PLL_MODE);
1567            if (AR_SREV_HONEYBEE(ah)) {
1568                regdata = (regdata & 0xffbfffff);
1569            } else {
1570                regdata = (regdata & 0xfffeffff);
1571            }
1572            OS_REG_WRITE(ah, AR_PHY_PLL_MODE, regdata); /* PWD_PLL set to 0 */
1573            OS_DELAY(1000);
1574            if (AR_SREV_WASP(ah)) {
1575                /* clear do measure */
1576                regdata = OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL3);
1577                regdata &= ~(1 << 30);
1578                OS_REG_WRITE(ah, AR_PHY_PLL_BB_DPLL3, regdata);
1579                OS_DELAY(100);
1580
1581                /* set do measure */
1582                regdata = OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL3);
1583                regdata |= (1 << 30);
1584                OS_REG_WRITE(ah, AR_PHY_PLL_BB_DPLL3, regdata);
1585
1586                /* wait for measure done */
1587                do {
1588                    regdata = OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL4);
1589                } while ((regdata & (1 << 3)) == 0);
1590
1591                /* clear do measure */
1592                regdata = OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL3);
1593                regdata &= ~(1 << 30);
1594                OS_REG_WRITE(ah, AR_PHY_PLL_BB_DPLL3, regdata);
1595
1596                /* get measure sqsum dvc */
1597                regdata = (OS_REG_READ(ah, AR_PHY_PLL_BB_DPLL3) & 0x007FFFF8) >> 3;
1598            } else {
1599                break;
1600            }
1601        } while (regdata >= 0x40000);
1602
1603        /* Remove from Bypass mode */
1604        OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c);
1605        OS_DELAY(1000);
1606    } else {
1607        pll = SM(0x5, AR_RTC_PLL_REFDIV);
1608
1609        /* Supposedly not needed on Osprey */
1610#if 0
1611        if (chan && IS_CHAN_HALF_RATE(chan)) {
1612            pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
1613        } else if (chan && IS_CHAN_QUARTER_RATE(chan)) {
1614            pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
1615        }
1616#endif
1617        if (ichan && IS_CHAN_5GHZ(ichan)) {
1618            pll |= SM(0x28, AR_RTC_PLL_DIV);
1619            /*
1620             * When doing fast clock, set PLL to 0x142c
1621             */
1622            if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
1623                pll = 0x142c;
1624            }
1625        } else {
1626            pll |= SM(0x2c, AR_RTC_PLL_DIV);
1627        }
1628
1629        OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
1630    }
1631
1632    /* TODO:
1633     * For multi-band owl, switch between bands by reiniting the PLL.
1634     */
1635    OS_DELAY(RTC_PLL_SETTLE_DELAY);
1636
1637    OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1638        AR_RTC_FORCE_DERIVED_CLK | AR_RTC_PCIE_RST_PWDN_EN);
1639
1640    /* XXX TODO: honeybee? */
1641    if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
1642        if (clk_25mhz) {
1643            OS_REG_WRITE(ah,
1644                AR_RTC_DERIVED_RTC_CLK, (0x17c << 1)); /* 32KHz sleep clk */
1645            OS_REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
1646            OS_REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae);
1647        } else {
1648            OS_REG_WRITE(ah,
1649                AR_RTC_DERIVED_RTC_CLK, (0x261 << 1)); /* 32KHz sleep clk */
1650            OS_REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
1651            OS_REG_WRITE(ah, AR_SLP32_INC, 0x0001e800);
1652        }
1653        OS_DELAY(100);
1654    }
1655}
1656
1657static inline HAL_BOOL
1658ar9300_set_reset(struct ath_hal *ah, int type)
1659{
1660    u_int32_t rst_flags;
1661    u_int32_t tmp_reg;
1662    struct ath_hal_9300 *ahp = AH9300(ah);
1663
1664    HALASSERT(type == HAL_RESET_WARM || type == HAL_RESET_COLD);
1665
1666    /*
1667     * RTC Force wake should be done before resetting the MAC.
1668     * MDK/ART does it that way.
1669     */
1670    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), AH9300(ah)->ah_wa_reg_val);
1671    OS_DELAY(10); /* delay to allow AR_WA reg write to kick in */
1672    OS_REG_WRITE(ah,
1673        AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
1674
1675    /* Reset AHB */
1676    /* Bug26871 */
1677    tmp_reg = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));
1678    if (AR_SREV_WASP(ah)) {
1679        if (tmp_reg & (AR9340_INTR_SYNC_LOCAL_TIMEOUT)) {
1680            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), 0);
1681            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_HOSTIF);
1682        }
1683    } else {
1684        if (tmp_reg & (AR9300_INTR_SYNC_LOCAL_TIMEOUT | AR9300_INTR_SYNC_RADM_CPL_TIMEOUT)) {
1685            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), 0);
1686            OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_HOSTIF);
1687        }
1688        else {
1689            /* NO AR_RC_AHB in Osprey */
1690            /*OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_AHB);*/
1691        }
1692    }
1693
1694    rst_flags = AR_RTC_RC_MAC_WARM;
1695    if (type == HAL_RESET_COLD) {
1696        rst_flags |= AR_RTC_RC_MAC_COLD;
1697    }
1698
1699#ifdef AH_SUPPORT_HORNET
1700    /* Hornet WAR: trigger SoC to reset WMAC if ...
1701     * (1) doing cold reset. Ref: EV 69254
1702     * (2) beacon pending. Ref: EV 70983
1703     */
1704    if (AR_SREV_HORNET(ah) &&
1705        (ar9300_num_tx_pending(
1706            ah, AH_PRIVATE(ah)->ah_caps.halTotalQueues - 1) != 0 ||
1707         type == HAL_RESET_COLD))
1708    {
1709        u_int32_t time_out;
1710#define AR_SOC_RST_RESET         0xB806001C
1711#define AR_SOC_BOOT_STRAP        0xB80600AC
1712#define AR_SOC_WLAN_RST          0x00000800 /* WLAN reset */
1713#define REG_WRITE(_reg, _val)    *((volatile u_int32_t *)(_reg)) = (_val);
1714#define REG_READ(_reg)           *((volatile u_int32_t *)(_reg))
1715        HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Hornet SoC reset WMAC.\n", __func__);
1716
1717        REG_WRITE(AR_SOC_RST_RESET,
1718            REG_READ(AR_SOC_RST_RESET) | AR_SOC_WLAN_RST);
1719        REG_WRITE(AR_SOC_RST_RESET,
1720            REG_READ(AR_SOC_RST_RESET) & (~AR_SOC_WLAN_RST));
1721
1722        time_out = 0;
1723
1724        while (1) {
1725            tmp_reg = REG_READ(AR_SOC_BOOT_STRAP);
1726            if ((tmp_reg & 0x10) == 0) {
1727                break;
1728            }
1729            if (time_out > 20) {
1730                break;
1731            }
1732            OS_DELAY(10000);
1733            time_out++;
1734        }
1735
1736        OS_REG_WRITE(ah, AR_RTC_RESET, 1);
1737#undef REG_READ
1738#undef REG_WRITE
1739#undef AR_SOC_WLAN_RST
1740#undef AR_SOC_RST_RESET
1741#undef AR_SOC_BOOT_STRAP
1742    }
1743#endif /* AH_SUPPORT_HORNET */
1744
1745#ifdef AH_SUPPORT_SCORPION
1746    if (AR_SREV_SCORPION(ah)) {
1747#define DDR_CTL_CONFIG_ADDRESS                                       0xb8000000
1748#define DDR_CTL_CONFIG_OFFSET                                        0x0108
1749#define DDR_CTL_CONFIG_CLIENT_ACTIVITY_MSB                           29
1750#define DDR_CTL_CONFIG_CLIENT_ACTIVITY_LSB                           21
1751#define DDR_CTL_CONFIG_CLIENT_ACTIVITY_MASK                          0x3fe00000
1752#define DDR_CTL_CONFIG_CLIENT_ACTIVITY_GET(x)                        (((x) & DDR_CTL_CONFIG_CLIENT_ACTIVITY_MASK) >> DDR_CTL_CONFIG_CLIENT_ACTIVITY_LSB)
1753#define DDR_CTL_CONFIG_CLIENT_ACTIVITY_SET(x)                        (((x) << DDR_CTL_CONFIG_CLIENT_ACTIVITY_LSB) & DDR_CTL_CONFIG_CLIENT_ACTIVITY_MASK)
1754#define MAC_DMA_CFG_ADDRESS                                          0xb8100000
1755#define MAC_DMA_CFG_OFFSET                                           0x0014
1756
1757#define MAC_DMA_CFG_HALT_REQ_MSB                                     11
1758#define MAC_DMA_CFG_HALT_REQ_LSB                                     11
1759#define MAC_DMA_CFG_HALT_REQ_MASK                                    0x00000800
1760#define MAC_DMA_CFG_HALT_REQ_GET(x)                                  (((x) & MAC_DMA_CFG_HALT_REQ_MASK) >> MAC_DMA_CFG_HALT_REQ_LSB)
1761#define MAC_DMA_CFG_HALT_REQ_SET(x)                                  (((x) << MAC_DMA_CFG_HALT_REQ_LSB) & MAC_DMA_CFG_HALT_REQ_MASK)
1762#define MAC_DMA_CFG_HALT_ACK_MSB                                     12
1763#define MAC_DMA_CFG_HALT_ACK_LSB                                     12
1764#define MAC_DMA_CFG_HALT_ACK_MASK                                    0x00001000
1765#define MAC_DMA_CFG_HALT_ACK_GET(x)                                  (((x) & MAC_DMA_CFG_HALT_ACK_MASK) >> MAC_DMA_CFG_HALT_ACK_LSB)
1766#define MAC_DMA_CFG_HALT_ACK_SET(x)                                  (((x) << MAC_DMA_CFG_HALT_ACK_LSB) & MAC_DMA_CFG_HALT_ACK_MASK)
1767
1768#define RST_RESET                                                    0xB806001c
1769#define RTC_RESET                                                    (1<<27)
1770
1771#define REG_READ(_reg)          *((volatile u_int32_t *)(_reg))
1772#define REG_WRITE(_reg, _val)   *((volatile u_int32_t *)(_reg)) = (_val);
1773
1774#define DDR_REG_READ(_ah, _reg) \
1775	    *((volatile u_int32_t *)( DDR_CTL_CONFIG_ADDRESS + (_reg)))
1776#define DDR_REG_WRITE(_ah, _reg, _val) \
1777	    *((volatile u_int32_t *)(DDR_CTL_CONFIG_ADDRESS + (_reg))) = (_val)
1778
1779	    OS_REG_WRITE(ah,MAC_DMA_CFG_OFFSET, (OS_REG_READ(ah,MAC_DMA_CFG_OFFSET) & ~MAC_DMA_CFG_HALT_REQ_MASK) |
1780			    MAC_DMA_CFG_HALT_REQ_SET(1));
1781
1782	    {
1783		    int count;
1784            u_int32_t data;
1785
1786		    count = 0;
1787		    while (!MAC_DMA_CFG_HALT_ACK_GET(OS_REG_READ(ah, MAC_DMA_CFG_OFFSET) ))
1788		    {
1789			    count++;
1790			    if (count > 10) {
1791				    ath_hal_printf(ah, "Halt ACK timeout\n");
1792				    break;
1793			    }
1794			    OS_DELAY(10);
1795		    }
1796
1797		    data = DDR_REG_READ(ah,DDR_CTL_CONFIG_OFFSET);
1798		    HALDEBUG(ah, HAL_DEBUG_RESET, "check DDR Activity - HIGH\n");
1799
1800		    count = 0;
1801		    while (DDR_CTL_CONFIG_CLIENT_ACTIVITY_GET(data)) {
1802			    //      AVE_DEBUG(0,"DDR Activity - HIGH\n");
1803			    HALDEBUG(ah, HAL_DEBUG_RESET, "DDR Activity - HIGH\n");
1804			    count++;
1805			    OS_DELAY(10);
1806			    data = DDR_REG_READ(ah,DDR_CTL_CONFIG_OFFSET);
1807			    if (count > 10) {
1808				    ath_hal_printf(ah, "DDR Activity timeout\n");
1809				    break;
1810			    }
1811		    }
1812	    }
1813
1814
1815	    {
1816		    //Force RTC reset
1817		    REG_WRITE(RST_RESET, (REG_READ(RST_RESET) | RTC_RESET));
1818		    OS_DELAY(10);
1819		    REG_WRITE(RST_RESET, (REG_READ(RST_RESET) & ~RTC_RESET));
1820		    OS_DELAY(10);
1821		    OS_REG_WRITE(ah, AR_RTC_RESET, 0);
1822		    OS_DELAY(10);
1823		    OS_REG_WRITE(ah, AR_RTC_RESET, 1);
1824		    OS_DELAY(10);
1825		    HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Scorpion SoC RTC reset done.\n", __func__);
1826	    }
1827#undef REG_READ
1828#undef REG_WRITE
1829    }
1830#endif  /* AH_SUPPORT_SCORPION */
1831
1832    /*
1833     * Set Mac(BB,Phy) Warm Reset
1834     */
1835    OS_REG_WRITE(ah, AR_RTC_RC, rst_flags);
1836
1837    OS_DELAY(50); /* XXX 50 usec */
1838
1839    /*
1840     * Clear resets and force wakeup
1841     */
1842    OS_REG_WRITE(ah, AR_RTC_RC, 0);
1843    if (!ath_hal_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0)) {
1844        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
1845            "%s: RTC stuck in MAC reset\n", __FUNCTION__);
1846        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
1847            "%s: AR_RTC_RC = 0x%x\n", __func__, OS_REG_READ(ah, AR_RTC_RC));
1848        return AH_FALSE;
1849    }
1850
1851    /* Clear AHB reset */
1852    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), 0);
1853
1854    ar9300_attach_hw_platform(ah);
1855
1856    ahp->ah_chip_reset_done = 1;
1857    return AH_TRUE;
1858}
1859
1860static inline HAL_BOOL
1861ar9300_set_reset_power_on(struct ath_hal *ah)
1862{
1863    /* Force wake */
1864    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), AH9300(ah)->ah_wa_reg_val);
1865    OS_DELAY(10); /* delay to allow AR_WA reg write to kick in */
1866    OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
1867        AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
1868    /*
1869     * RTC reset and clear. Some delay in between is needed
1870     * to give the chip time to settle.
1871     */
1872    OS_REG_WRITE(ah, AR_RTC_RESET, 0);
1873    OS_DELAY(2);
1874    OS_REG_WRITE(ah, AR_RTC_RESET, 1);
1875
1876    /*
1877     * Poll till RTC is ON
1878     */
1879    if (!ath_hal_wait(ah,
1880             AR_RTC_STATUS, AR_RTC_STATUS_M,
1881             AR_RTC_STATUS_ON))
1882    {
1883        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
1884            "%s: RTC not waking up for %d\n", __FUNCTION__, 1000);
1885        return AH_FALSE;
1886    }
1887
1888    /*
1889     * Read Revisions from Chip right after RTC is on for the first time.
1890     * This helps us detect the chip type early and initialize it accordingly.
1891     */
1892    ar9300_read_revisions(ah);
1893
1894    /*
1895     * Warm reset if we aren't really powering on,
1896     * just restarting the driver.
1897     */
1898    return ar9300_set_reset(ah, HAL_RESET_WARM);
1899}
1900
1901/*
1902 * Write the given reset bit mask into the reset register
1903 */
1904HAL_BOOL
1905ar9300_set_reset_reg(struct ath_hal *ah, u_int32_t type)
1906{
1907    HAL_BOOL ret = AH_FALSE;
1908
1909    /*
1910     * Set force wake
1911     */
1912    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_WA), AH9300(ah)->ah_wa_reg_val);
1913    OS_DELAY(10); /* delay to allow AR_WA reg write to kick in */
1914    OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
1915        AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
1916
1917    switch (type) {
1918    case HAL_RESET_POWER_ON:
1919        ret = ar9300_set_reset_power_on(ah);
1920        break;
1921    case HAL_RESET_WARM:
1922    case HAL_RESET_COLD:
1923        ret = ar9300_set_reset(ah, type);
1924        break;
1925    default:
1926        break;
1927    }
1928
1929#if ATH_SUPPORT_MCI
1930    if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
1931        OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
1932    }
1933#endif
1934
1935    return ret;
1936}
1937
1938/*
1939 * Places the PHY and Radio chips into reset.  A full reset
1940 * must be called to leave this state.  The PCI/MAC/PCU are
1941 * not placed into reset as we must receive interrupt to
1942 * re-enable the hardware.
1943 */
1944HAL_BOOL
1945ar9300_phy_disable(struct ath_hal *ah)
1946{
1947    if (!ar9300_set_reset_reg(ah, HAL_RESET_WARM)) {
1948        return AH_FALSE;
1949    }
1950
1951#ifdef ATH_SUPPORT_LED
1952#define REG_READ(_reg)          *((volatile u_int32_t *)(_reg))
1953#define REG_WRITE(_reg, _val)   *((volatile u_int32_t *)(_reg)) = (_val);
1954#define ATH_GPIO_OE             0xB8040000
1955#define ATH_GPIO_OUT            0xB8040008 /* GPIO Ouput Value reg.*/
1956    if (AR_SREV_WASP(ah)) {
1957        if (IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan))) {
1958            REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 13)));
1959        }
1960        else {
1961            REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 12)));
1962        }
1963    }
1964    else if (AR_SREV_SCORPION(ah)) {
1965        if (IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan))) {
1966            REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 13)));
1967        }
1968        else {
1969            REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 12)));
1970        }
1971        /* Turn off JMPST led */
1972        REG_WRITE(ATH_GPIO_OUT, (REG_READ(ATH_GPIO_OUT) | (0x1 << 15)));
1973    }
1974    else if (AR_SREV_HONEYBEE(ah)) {
1975        REG_WRITE(ATH_GPIO_OE, (REG_READ(ATH_GPIO_OE) | (0x1 << 12)));
1976    }
1977#undef REG_READ
1978#undef REG_WRITE
1979#endif
1980
1981    if ( AR_SREV_OSPREY(ah) ) {
1982        OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1), 0x0, 0x1f);
1983    }
1984
1985
1986    ar9300_init_pll(ah, AH_NULL);
1987
1988    return AH_TRUE;
1989}
1990
1991/*
1992 * Places all of hardware into reset
1993 */
1994HAL_BOOL
1995ar9300_disable(struct ath_hal *ah)
1996{
1997    if (!ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE)) {
1998        return AH_FALSE;
1999    }
2000    if (!ar9300_set_reset_reg(ah, HAL_RESET_COLD)) {
2001        return AH_FALSE;
2002    }
2003
2004    ar9300_init_pll(ah, AH_NULL);
2005
2006    return AH_TRUE;
2007}
2008
2009/*
2010 * TODO: Only write the PLL if we're changing to or from CCK mode
2011 *
2012 * WARNING: The order of the PLL and mode registers must be correct.
2013 */
2014static inline void
2015ar9300_set_rf_mode(struct ath_hal *ah, struct ieee80211_channel *chan)
2016{
2017    u_int32_t rf_mode = 0;
2018
2019    if (chan == AH_NULL) {
2020        return;
2021    }
2022    switch (AH9300(ah)->ah_hwp) {
2023    case HAL_TRUE_CHIP:
2024        rf_mode |= (IEEE80211_IS_CHAN_B(chan) || IEEE80211_IS_CHAN_G(chan)) ?
2025            AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
2026        break;
2027    default:
2028        HALASSERT(0);
2029        break;
2030    }
2031    /*  Phy mode bits for 5GHz channels requiring Fast Clock */
2032    if ( IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
2033        rf_mode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
2034    }
2035    OS_REG_WRITE(ah, AR_PHY_MODE, rf_mode);
2036}
2037
2038/*
2039 * Places the hardware into reset and then pulls it out of reset
2040 */
2041HAL_BOOL
2042ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan)
2043{
2044    struct ath_hal_9300     *ahp = AH9300(ah);
2045    int type = HAL_RESET_WARM;
2046
2047    OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0);
2048
2049    /*
2050     * Warm reset is optimistic.
2051     *
2052     * If the TX/RX DMA engines aren't shut down (eg, they're
2053     * wedged) then we're better off doing a full cold reset
2054     * to try and shake that condition.
2055     */
2056    if (ahp->ah_chip_full_sleep ||
2057        (ah->ah_config.ah_force_full_reset == 1) ||
2058        OS_REG_READ(ah, AR_Q_TXE) ||
2059        (OS_REG_READ(ah, AR_CR) & AR_CR_RXE)) {
2060            type = HAL_RESET_COLD;
2061    }
2062
2063    if (!ar9300_set_reset_reg(ah, type)) {
2064        return AH_FALSE;
2065    }
2066
2067    /* Bring out of sleep mode (AGAIN) */
2068    if (!ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE)) {
2069        return AH_FALSE;
2070    }
2071
2072    ahp->ah_chip_full_sleep = AH_FALSE;
2073
2074    if (AR_SREV_HORNET(ah)) {
2075        ar9300_internal_regulator_apply(ah);
2076    }
2077
2078    ar9300_init_pll(ah, chan);
2079
2080    /*
2081     * Perform warm reset before the mode/PLL/turbo registers
2082     * are changed in order to deactivate the radio.  Mode changes
2083     * with an active radio can result in corrupted shifts to the
2084     * radio device.
2085     */
2086    ar9300_set_rf_mode(ah, chan);
2087
2088    return AH_TRUE;
2089}
2090
2091/* ar9300_setup_calibration
2092 * Setup HW to collect samples used for current cal
2093 */
2094inline static void
2095ar9300_setup_calibration(struct ath_hal *ah, HAL_CAL_LIST *curr_cal)
2096{
2097    /* Select calibration to run */
2098    switch (curr_cal->cal_data->cal_type) {
2099    case IQ_MISMATCH_CAL:
2100        /* Start calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
2101        OS_REG_RMW_FIELD(ah, AR_PHY_TIMING4,
2102            AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
2103            curr_cal->cal_data->cal_count_max);
2104        OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
2105
2106        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2107            "%s: starting IQ Mismatch Calibration\n", __func__);
2108
2109        /* Kick-off cal */
2110        OS_REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
2111
2112        break;
2113    case TEMP_COMP_CAL:
2114        if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) ||
2115            AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
2116            OS_REG_RMW_FIELD(ah,
2117                AR_HORNET_CH0_THERM, AR_PHY_65NM_CH0_THERM_LOCAL, 1);
2118            OS_REG_RMW_FIELD(ah,
2119                AR_HORNET_CH0_THERM, AR_PHY_65NM_CH0_THERM_START, 1);
2120        } else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
2121            OS_REG_RMW_FIELD(ah,
2122                AR_PHY_65NM_CH0_THERM_JUPITER, AR_PHY_65NM_CH0_THERM_LOCAL, 1);
2123            OS_REG_RMW_FIELD(ah,
2124                AR_PHY_65NM_CH0_THERM_JUPITER, AR_PHY_65NM_CH0_THERM_START, 1);
2125        } else {
2126            OS_REG_RMW_FIELD(ah,
2127                AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_LOCAL, 1);
2128            OS_REG_RMW_FIELD(ah,
2129                AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_START, 1);
2130        }
2131
2132        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2133            "%s: starting Temperature Compensation Calibration\n", __func__);
2134        break;
2135    default:
2136        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
2137            "%s called with incorrect calibration type.\n", __func__);
2138    }
2139}
2140
2141/* ar9300_reset_calibration
2142 * Initialize shared data structures and prepare a cal to be run.
2143 */
2144inline static void
2145ar9300_reset_calibration(struct ath_hal *ah, HAL_CAL_LIST *curr_cal)
2146{
2147    struct ath_hal_9300 *ahp = AH9300(ah);
2148    int i;
2149
2150    /* Setup HW for new calibration */
2151    ar9300_setup_calibration(ah, curr_cal);
2152
2153    /* Change SW state to RUNNING for this calibration */
2154    curr_cal->cal_state = CAL_RUNNING;
2155
2156    /* Reset data structures shared between different calibrations */
2157    for (i = 0; i < AR9300_MAX_CHAINS; i++) {
2158        ahp->ah_meas0.sign[i] = 0;
2159        ahp->ah_meas1.sign[i] = 0;
2160        ahp->ah_meas2.sign[i] = 0;
2161        ahp->ah_meas3.sign[i] = 0;
2162    }
2163
2164    ahp->ah_cal_samples = 0;
2165}
2166
2167#ifdef XXX_UNUSED_FUNCTION
2168/*
2169 * Find out which of the RX chains are enabled
2170 */
2171static u_int32_t
2172ar9300_get_rx_chain_mask(struct ath_hal *ah)
2173{
2174    u_int32_t ret_val = OS_REG_READ(ah, AR_PHY_RX_CHAINMASK);
2175    /* The bits [2:0] indicate the rx chain mask and are to be
2176     * interpreted as follows:
2177     * 00x => Only chain 0 is enabled
2178     * 01x => Chain 1 and 0 enabled
2179     * 1xx => Chain 2,1 and 0 enabled
2180     */
2181    return (ret_val & 0x7);
2182}
2183#endif
2184
2185static void
2186ar9300_get_nf_hist_base(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
2187    int is_scan, int16_t nf[])
2188{
2189    HAL_NFCAL_BASE *h_base;
2190
2191#ifdef ATH_NF_PER_CHAN
2192    h_base = &chan->nf_cal_hist.base;
2193#else
2194    if (is_scan) {
2195        /*
2196         * The channel we are currently on is not the home channel,
2197         * so we shouldn't use the home channel NF buffer's values on
2198         * this channel.  Instead, use the NF single value already
2199         * read for this channel.  (Or, if we haven't read the NF for
2200         * this channel yet, the SW default for this chip/band will
2201         * be used.)
2202         */
2203        h_base = &chan->nf_cal_hist.base;
2204    } else {
2205        /* use the home channel NF info */
2206        h_base = &AH_PRIVATE(ah)->nf_cal_hist.base;
2207    }
2208#endif
2209    OS_MEMCPY(nf, h_base->priv_nf, sizeof(h_base->priv_nf));
2210}
2211
2212HAL_BOOL
2213ar9300_load_nf(struct ath_hal *ah, int16_t nf[])
2214{
2215    int i, j;
2216    int32_t val;
2217    /* XXX where are EXT regs defined */
2218    const u_int32_t ar9300_cca_regs[] = {
2219        AR_PHY_CCA_0,
2220        AR_PHY_CCA_1,
2221        AR_PHY_CCA_2,
2222        AR_PHY_EXT_CCA,
2223        AR_PHY_EXT_CCA_1,
2224        AR_PHY_EXT_CCA_2,
2225    };
2226    u_int8_t chainmask;
2227
2228    /*
2229     * Force NF calibration for all chains, otherwise Vista station
2230     * would conduct a bad performance
2231     */
2232    if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
2233        chainmask = 0x9;
2234    } else if (AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah) || AR_SREV_HONEYBEE(ah)) {
2235        chainmask = 0x1b;
2236    } else {
2237        chainmask = 0x3F;
2238    }
2239
2240    /*
2241     * Write filtered NF values into max_cca_pwr register parameter
2242     * so we can load below.
2243     */
2244    for (i = 0; i < HAL_NUM_NF_READINGS; i++) {
2245        if (chainmask & (1 << i)) {
2246            val = OS_REG_READ(ah, ar9300_cca_regs[i]);
2247            val &= 0xFFFFFE00;
2248            val |= (((u_int32_t)(nf[i]) << 1) & 0x1ff);
2249            OS_REG_WRITE(ah, ar9300_cca_regs[i], val);
2250        }
2251    }
2252
2253    HALDEBUG(ah, HAL_DEBUG_NFCAL, "%s: load %d %d %d %d %d %d\n",
2254      __func__,
2255      nf[0], nf[1], nf[2],
2256      nf[3], nf[4], nf[5]);
2257
2258    /*
2259     * Load software filtered NF value into baseband internal min_cca_pwr
2260     * variable.
2261     */
2262    OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
2263    OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
2264    OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
2265
2266    /* Wait for load to complete, should be fast, a few 10s of us. */
2267    /* Changed the max delay 250us back to 10000us, since 250us often
2268     * results in NF load timeout and causes deaf condition
2269     * during stress testing 12/12/2009
2270     */
2271    for (j = 0; j < 10000; j++) {
2272        if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0){
2273            break;
2274        }
2275        OS_DELAY(10);
2276    }
2277    if (j == 10000) {
2278        /*
2279         * We timed out waiting for the noisefloor to load, probably
2280         * due to an in-progress rx.  Simply return here and allow
2281         * the load plenty of time to complete before the next
2282         * calibration interval.  We need to avoid trying to load -50
2283         * (which happens below) while the previous load is still in
2284         * progress as this can cause rx deafness (see EV 66368,62830).
2285         * Instead by returning here, the baseband nf cal will
2286         * just be capped by our present noisefloor until the next
2287         * calibration timer.
2288         */
2289        HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
2290            "%s: *** TIMEOUT while waiting for nf to load: "
2291            "AR_PHY_AGC_CONTROL=0x%x ***\n",
2292            __func__, OS_REG_READ(ah, AR_PHY_AGC_CONTROL));
2293        return AH_FALSE;
2294    }
2295
2296    /*
2297     * Restore max_cca_power register parameter again so that we're not capped
2298     * by the median we just loaded.  This will be initial (and max) value
2299     * of next noise floor calibration the baseband does.
2300     */
2301    for (i = 0; i < HAL_NUM_NF_READINGS; i++) {
2302        if (chainmask & (1 << i)) {
2303            val = OS_REG_READ(ah, ar9300_cca_regs[i]);
2304            val &= 0xFFFFFE00;
2305            val |= (((u_int32_t)(-50) << 1) & 0x1ff);
2306            OS_REG_WRITE(ah, ar9300_cca_regs[i], val);
2307        }
2308    }
2309    return AH_TRUE;
2310}
2311
2312/* ar9300_per_calibration
2313 * Generic calibration routine.
2314 * Recalibrate the lower PHY chips to account for temperature/environment
2315 * changes.
2316 */
2317inline static void
2318ar9300_per_calibration(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *ichan,
2319    u_int8_t rxchainmask, HAL_CAL_LIST *curr_cal, HAL_BOOL *is_cal_done)
2320{
2321    struct ath_hal_9300 *ahp = AH9300(ah);
2322
2323    /* Cal is assumed not done until explicitly set below */
2324    *is_cal_done = AH_FALSE;
2325
2326    /* Calibration in progress. */
2327    if (curr_cal->cal_state == CAL_RUNNING) {
2328        /* Check to see if it has finished. */
2329        if (!(OS_REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
2330            int i, num_chains = 0;
2331            for (i = 0; i < AR9300_MAX_CHAINS; i++) {
2332                if (rxchainmask & (1 << i)) {
2333                    num_chains++;
2334                }
2335            }
2336
2337            /*
2338             * Accumulate cal measures for active chains
2339             */
2340            curr_cal->cal_data->cal_collect(ah, num_chains);
2341
2342            ahp->ah_cal_samples++;
2343
2344            if (ahp->ah_cal_samples >= curr_cal->cal_data->cal_num_samples) {
2345                /*
2346                 * Process accumulated data
2347                 */
2348                curr_cal->cal_data->cal_post_proc(ah, num_chains);
2349
2350                /* Calibration has finished. */
2351                ichan->calValid |= curr_cal->cal_data->cal_type;
2352                curr_cal->cal_state = CAL_DONE;
2353                *is_cal_done = AH_TRUE;
2354            } else {
2355                /* Set-up collection of another sub-sample until we
2356                 * get desired number
2357                 */
2358                ar9300_setup_calibration(ah, curr_cal);
2359            }
2360        }
2361    } else if (!(ichan->calValid & curr_cal->cal_data->cal_type)) {
2362        /* If current cal is marked invalid in channel, kick it off */
2363        ar9300_reset_calibration(ah, curr_cal);
2364    }
2365}
2366
2367static void
2368ar9300_start_nf_cal(struct ath_hal *ah)
2369{
2370    struct ath_hal_9300 *ahp = AH9300(ah);
2371    OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
2372    OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
2373    OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
2374    AH9300(ah)->nf_tsf32 = ar9300_get_tsf32(ah);
2375
2376/*
2377 *  We are reading the NF values before we start the NF operation, because
2378 *  of that we are getting very high values like -45.
2379 *  This triggers the CW_INT detected and EACS module triggers the channel change
2380 *  chip_reset_done value is used to fix this issue.
2381 *  chip_reset_flag is set during the RTC reset.
2382 *  chip_reset_flag is cleared during the starting NF operation.
2383 *  if flag is set we will clear the flag and will not read the NF values.
2384 */
2385    ahp->ah_chip_reset_done = 0;
2386}
2387
2388/* ar9300_calibration
2389 * Wrapper for a more generic Calibration routine. Primarily to abstract to
2390 * upper layers whether there is 1 or more calibrations to be run.
2391 */
2392HAL_BOOL
2393ar9300_calibration(struct ath_hal *ah, struct ieee80211_channel *chan, u_int8_t rxchainmask,
2394    HAL_BOOL do_nf_cal, HAL_BOOL *is_cal_done, int is_scan,
2395    u_int32_t *sched_cals)
2396{
2397    struct ath_hal_9300 *ahp = AH9300(ah);
2398    HAL_CAL_LIST *curr_cal = ahp->ah_cal_list_curr;
2399    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
2400    int16_t nf_buf[HAL_NUM_NF_READINGS];
2401
2402    *is_cal_done = AH_TRUE;
2403
2404
2405    /* XXX: For initial wasp bringup - disable periodic calibration */
2406    /* Invalid channel check */
2407    if (ichan == AH_NULL) {
2408        HALDEBUG(ah, HAL_DEBUG_CHANNEL,
2409            "%s: invalid channel %u/0x%x; no mapping\n",
2410            __func__, chan->ic_freq, chan->ic_flags);
2411        return AH_FALSE;
2412    }
2413
2414    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2415        "%s: Entering, Doing NF Cal = %d\n", __func__, do_nf_cal);
2416    HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Chain 0 Rx IQ Cal Correction 0x%08x\n",
2417        __func__, OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
2418    if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah) && !AR_SREV_APHRODITE(ah)) {
2419        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2420            "%s: Chain 1 Rx IQ Cal Correction 0x%08x\n",
2421            __func__, OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B1));
2422        if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah)) {
2423            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2424                "%s: Chain 2 Rx IQ Cal Correction 0x%08x\n",
2425                __func__, OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B2));
2426        }
2427    }
2428
2429    OS_MARK(ah, AH_MARK_PERCAL, chan->ic_freq);
2430
2431    /* For given calibration:
2432     * 1. Call generic cal routine
2433     * 2. When this cal is done (is_cal_done) if we have more cals waiting
2434     *    (eg after reset), mask this to upper layers by not propagating
2435     *    is_cal_done if it is set to TRUE.
2436     *    Instead, change is_cal_done to FALSE and setup the waiting cal(s)
2437     *    to be run.
2438     */
2439    if (curr_cal && (curr_cal->cal_data->cal_type & *sched_cals) &&
2440        (curr_cal->cal_state == CAL_RUNNING ||
2441         curr_cal->cal_state == CAL_WAITING))
2442    {
2443        ar9300_per_calibration(ah, ichan, rxchainmask, curr_cal, is_cal_done);
2444
2445        if (*is_cal_done == AH_TRUE) {
2446            ahp->ah_cal_list_curr = curr_cal = curr_cal->cal_next;
2447
2448            if (curr_cal && curr_cal->cal_state == CAL_WAITING) {
2449                *is_cal_done = AH_FALSE;
2450                ar9300_reset_calibration(ah, curr_cal);
2451            } else {
2452                *sched_cals &= ~IQ_MISMATCH_CAL;
2453            }
2454        }
2455    }
2456
2457    /* Do NF cal only at longer intervals */
2458    if (do_nf_cal) {
2459        int nf_done;
2460
2461        /* Get the value from the previous NF cal and update history buffer */
2462        nf_done = ar9300_store_new_nf(ah, chan, is_scan);
2463#if 0
2464        if (ichan->channel_flags & CHANNEL_CW_INT) {
2465            chan->channel_flags |= CHANNEL_CW_INT;
2466        }
2467#endif
2468        chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;
2469
2470        if (nf_done) {
2471            /*
2472             * Load the NF from history buffer of the current channel.
2473             * NF is slow time-variant, so it is OK to use a historical value.
2474             */
2475            ar9300_get_nf_hist_base(ah, ichan, is_scan, nf_buf);
2476            ar9300_load_nf(ah, nf_buf);
2477
2478            /* start NF calibration, without updating BB NF register*/
2479            ar9300_start_nf_cal(ah);
2480        }
2481    }
2482    return AH_TRUE;
2483}
2484
2485/* ar9300_iq_cal_collect
2486 * Collect data from HW to later perform IQ Mismatch Calibration
2487 */
2488void
2489ar9300_iq_cal_collect(struct ath_hal *ah, u_int8_t num_chains)
2490{
2491    struct ath_hal_9300 *ahp = AH9300(ah);
2492    int i;
2493
2494    /*
2495     * Accumulate IQ cal measures for active chains
2496     */
2497    for (i = 0; i < num_chains; i++) {
2498        ahp->ah_total_power_meas_i[i] = OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
2499        ahp->ah_total_power_meas_q[i] = OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
2500        ahp->ah_total_iq_corr_meas[i] =
2501            (int32_t) OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
2502        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2503            "%d: Chn %d "
2504            "Reg Offset(0x%04x)pmi=0x%08x; "
2505            "Reg Offset(0x%04x)pmq=0x%08x; "
2506            "Reg Offset (0x%04x)iqcm=0x%08x;\n",
2507            ahp->ah_cal_samples,
2508            i,
2509            (unsigned) AR_PHY_CAL_MEAS_0(i),
2510            ahp->ah_total_power_meas_i[i],
2511            (unsigned) AR_PHY_CAL_MEAS_1(i),
2512            ahp->ah_total_power_meas_q[i],
2513            (unsigned) AR_PHY_CAL_MEAS_2(i),
2514            ahp->ah_total_iq_corr_meas[i]);
2515    }
2516}
2517
2518/* ar9300_iq_calibration
2519 * Use HW data to perform IQ Mismatch Calibration
2520 */
2521void
2522ar9300_iq_calibration(struct ath_hal *ah, u_int8_t num_chains)
2523{
2524    struct ath_hal_9300 *ahp = AH9300(ah);
2525    u_int32_t power_meas_q, power_meas_i, iq_corr_meas;
2526    u_int32_t q_coff_denom, i_coff_denom;
2527    int32_t q_coff, i_coff;
2528    int iq_corr_neg, i;
2529    HAL_CHANNEL_INTERNAL *ichan;
2530    static const u_int32_t offset_array[3] = {
2531        AR_PHY_RX_IQCAL_CORR_B0,
2532        AR_PHY_RX_IQCAL_CORR_B1,
2533        AR_PHY_RX_IQCAL_CORR_B2,
2534    };
2535
2536    ichan = ath_hal_checkchannel(ah, AH_PRIVATE(ah)->ah_curchan);
2537
2538    for (i = 0; i < num_chains; i++) {
2539        power_meas_i = ahp->ah_total_power_meas_i[i];
2540        power_meas_q = ahp->ah_total_power_meas_q[i];
2541        iq_corr_meas = ahp->ah_total_iq_corr_meas[i];
2542
2543        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2544            "Starting IQ Cal and Correction for Chain %d\n", i);
2545        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2546            "Orignal: Chn %diq_corr_meas = 0x%08x\n",
2547            i, ahp->ah_total_iq_corr_meas[i]);
2548
2549        iq_corr_neg = 0;
2550
2551        /* iq_corr_meas is always negative. */
2552        if (iq_corr_meas > 0x80000000)  {
2553            iq_corr_meas = (0xffffffff - iq_corr_meas) + 1;
2554            iq_corr_neg = 1;
2555        }
2556
2557        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2558            "Chn %d pwr_meas_i = 0x%08x\n", i, power_meas_i);
2559        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2560            "Chn %d pwr_meas_q = 0x%08x\n", i, power_meas_q);
2561        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2562            "iq_corr_neg is 0x%08x\n", iq_corr_neg);
2563
2564        i_coff_denom = (power_meas_i / 2 + power_meas_q / 2) / 256;
2565        q_coff_denom = power_meas_q / 64;
2566
2567        /* Protect against divide-by-0 */
2568        if ((i_coff_denom != 0) && (q_coff_denom != 0)) {
2569            /* IQ corr_meas is already negated if iqcorr_neg == 1 */
2570            i_coff = iq_corr_meas / i_coff_denom;
2571            q_coff = power_meas_i / q_coff_denom - 64;
2572            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2573                "Chn %d i_coff = 0x%08x\n", i, i_coff);
2574            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2575                "Chn %d q_coff = 0x%08x\n", i, q_coff);
2576
2577            /* Force bounds on i_coff */
2578            if (i_coff >= 63) {
2579                i_coff = 63;
2580            } else if (i_coff <= -63) {
2581                i_coff = -63;
2582            }
2583
2584            /* Negate i_coff if iq_corr_neg == 0 */
2585            if (iq_corr_neg == 0x0) {
2586                i_coff = -i_coff;
2587            }
2588
2589            /* Force bounds on q_coff */
2590            if (q_coff >= 63) {
2591                q_coff = 63;
2592            } else if (q_coff <= -63) {
2593                q_coff = -63;
2594            }
2595
2596            i_coff = i_coff & 0x7f;
2597            q_coff = q_coff & 0x7f;
2598
2599            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2600                "Chn %d : i_coff = 0x%x  q_coff = 0x%x\n", i, i_coff, q_coff);
2601            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2602                "Register offset (0x%04x) before update = 0x%x\n",
2603                offset_array[i], OS_REG_READ(ah, offset_array[i]));
2604
2605            OS_REG_RMW_FIELD(ah, offset_array[i],
2606                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, i_coff);
2607            OS_REG_RMW_FIELD(ah, offset_array[i],
2608                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, q_coff);
2609
2610            /* store the RX cal results */
2611	    if (ichan != NULL) {
2612            ahp->ah_rx_cal_corr[i] = OS_REG_READ(ah, offset_array[i]) & 0x7fff;
2613            ahp->ah_rx_cal_complete = AH_TRUE;
2614            ahp->ah_rx_cal_chan = ichan->channel;
2615//            ahp->ah_rx_cal_chan_flag = ichan->channel_flags &~ CHANNEL_PASSIVE;
2616            ahp->ah_rx_cal_chan_flag = 0; /* XXX */
2617	    } else {
2618	        /* XXX? Is this what I should do? */
2619            	ahp->ah_rx_cal_complete = AH_FALSE;
2620
2621	    }
2622
2623            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2624                "Register offset (0x%04x) QI COFF (bitfields 0x%08x) "
2625                "after update = 0x%x\n",
2626                offset_array[i], AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
2627                OS_REG_READ(ah, offset_array[i]));
2628            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2629                "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) "
2630                "after update = 0x%x\n",
2631                offset_array[i], AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
2632                OS_REG_READ(ah, offset_array[i]));
2633            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2634                "IQ Cal and Correction done for Chain %d\n", i);
2635        }
2636    }
2637
2638    OS_REG_SET_BIT(ah,
2639        AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
2640    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2641        "IQ Cal and Correction (offset 0x%04x) enabled "
2642        "(bit position 0x%08x). New Value 0x%08x\n",
2643        (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
2644        AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
2645        OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
2646}
2647
2648/*
2649 * When coming back from offchan, we do not perform RX IQ Cal.
2650 * But the chip reset will clear all previous results
2651 * We store the previous results and restore here.
2652 */
2653static void
2654ar9300_rx_iq_cal_restore(struct ath_hal *ah)
2655{
2656    struct ath_hal_9300 *ahp = AH9300(ah);
2657    u_int32_t   i_coff, q_coff;
2658    HAL_BOOL is_restore = AH_FALSE;
2659    int i;
2660    static const u_int32_t offset_array[3] = {
2661        AR_PHY_RX_IQCAL_CORR_B0,
2662        AR_PHY_RX_IQCAL_CORR_B1,
2663        AR_PHY_RX_IQCAL_CORR_B2,
2664    };
2665
2666    for (i=0; i<AR9300_MAX_CHAINS; i++) {
2667        if (ahp->ah_rx_cal_corr[i]) {
2668            i_coff = (ahp->ah_rx_cal_corr[i] &
2669                        AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF) >>
2670                        AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF_S;
2671            q_coff = (ahp->ah_rx_cal_corr[i] &
2672                        AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF) >>
2673                        AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF_S;
2674
2675            OS_REG_RMW_FIELD(ah, offset_array[i],
2676                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, i_coff);
2677            OS_REG_RMW_FIELD(ah, offset_array[i],
2678                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, q_coff);
2679
2680            is_restore = AH_TRUE;
2681        }
2682    }
2683
2684    if (is_restore)
2685        OS_REG_SET_BIT(ah,
2686            AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
2687
2688    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2689        "%s: IQ Cal and Correction (offset 0x%04x) enabled "
2690        "(bit position 0x%08x). New Value 0x%08x\n",
2691        __func__,
2692        (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
2693        AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
2694        OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
2695}
2696
2697/*
2698 * Set a limit on the overall output power.  Used for dynamic
2699 * transmit power control and the like.
2700 *
2701 * NB: limit is in units of 0.5 dbM.
2702 */
2703HAL_BOOL
2704ar9300_set_tx_power_limit(struct ath_hal *ah, u_int32_t limit,
2705    u_int16_t extra_txpow, u_int16_t tpc_in_db)
2706{
2707    struct ath_hal_9300 *ahp = AH9300(ah);
2708    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
2709    const struct ieee80211_channel *chan = ahpriv->ah_curchan;
2710    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
2711
2712    if (NULL == chan) {
2713        return AH_FALSE;
2714    }
2715
2716    ahpriv->ah_powerLimit = AH_MIN(limit, MAX_RATE_POWER);
2717    ahpriv->ah_extraTxPow = extra_txpow;
2718
2719    if(chan == NULL) {
2720        return AH_FALSE;
2721    }
2722    if (ar9300_eeprom_set_transmit_power(ah, &ahp->ah_eeprom, chan,
2723        ath_hal_getctl(ah, chan), ath_hal_getantennaallowed(ah, chan),
2724        ath_hal_get_twice_max_regpower(ahpriv, ichan, chan),
2725        AH_MIN(MAX_RATE_POWER, ahpriv->ah_powerLimit)) != HAL_OK)
2726    {
2727        return AH_FALSE;
2728    }
2729    return AH_TRUE;
2730}
2731
2732/*
2733 * Exported call to check for a recent gain reading and return
2734 * the current state of the thermal calibration gain engine.
2735 */
2736HAL_RFGAIN
2737ar9300_get_rfgain(struct ath_hal *ah)
2738{
2739    return HAL_RFGAIN_INACTIVE;
2740}
2741
2742#define HAL_GREEN_AP_RX_MASK 0x1
2743
2744static inline void
2745ar9300_init_chain_masks(struct ath_hal *ah, int rx_chainmask, int tx_chainmask)
2746{
2747    if (AH9300(ah)->green_ap_ps_on) {
2748        rx_chainmask = HAL_GREEN_AP_RX_MASK;
2749    }
2750    if (rx_chainmask == 0x5) {
2751        OS_REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN);
2752    }
2753    OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
2754    OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
2755
2756    /*
2757     * Adaptive Power Management:
2758     * Some 3 stream chips exceed the PCIe power requirements.
2759     * This workaround will reduce power consumption by using 2 tx chains
2760     * for 1 and 2 stream rates (5 GHz only).
2761     *
2762     * Set the self gen mask to 2 tx chains when APM is enabled.
2763     *
2764     */
2765    if (AH_PRIVATE(ah)->ah_caps.halApmEnable && (tx_chainmask == 0x7)) {
2766        OS_REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
2767    }
2768    else {
2769        OS_REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
2770    }
2771
2772    if (tx_chainmask == 0x5) {
2773        OS_REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN);
2774    }
2775}
2776
2777/*
2778 * Override INI values with chip specific configuration.
2779 */
2780static inline void
2781ar9300_override_ini(struct ath_hal *ah, struct ieee80211_channel *chan)
2782{
2783    u_int32_t val;
2784    HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
2785
2786    /*
2787     * Set the RX_ABORT and RX_DIS and clear it only after
2788     * RXE is set for MAC. This prevents frames with
2789     * corrupted descriptor status.
2790     */
2791    OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
2792    /*
2793     * For Merlin and above, there is a new feature that allows Multicast
2794     * search based on both MAC Address and Key ID.
2795     * By default, this feature is enabled.
2796     * But since the driver is not using this feature, we switch it off;
2797     * otherwise multicast search based on MAC addr only will fail.
2798     */
2799    val = OS_REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
2800    OS_REG_WRITE(ah, AR_PCU_MISC_MODE2,
2801        val | AR_BUG_58603_FIX_ENABLE | AR_AGG_WEP_ENABLE);
2802
2803
2804    /* Osprey revision specific configuration */
2805
2806    /* Osprey 2.0+ - if SW RAC support is disabled, must also disable
2807     * the Osprey 2.0 hardware RAC fix.
2808     */
2809    if (p_cap->halIsrRacSupport == AH_FALSE) {
2810        OS_REG_CLR_BIT(ah, AR_CFG, AR_CFG_MISSING_TX_INTR_FIX_ENABLE);
2811    }
2812
2813    /* try to enable old pal if it is needed for h/w green tx */
2814    ar9300_hwgreentx_set_pal_spare(ah, 1);
2815}
2816
2817static inline void
2818ar9300_prog_ini(struct ath_hal *ah, struct ar9300_ini_array *ini_arr,
2819    int column)
2820{
2821    int i, reg_writes = 0;
2822
2823    /* New INI format: Array may be undefined (pre, core, post arrays) */
2824    if (ini_arr->ia_array == NULL) {
2825        return;
2826    }
2827
2828    /*
2829     * New INI format: Pre, core, and post arrays for a given subsystem may be
2830     * modal (> 2 columns) or non-modal (2 columns).
2831     * Determine if the array is non-modal and force the column to 1.
2832     */
2833    if (column >= ini_arr->ia_columns) {
2834        column = 1;
2835    }
2836
2837    for (i = 0; i < ini_arr->ia_rows; i++) {
2838        u_int32_t reg = INI_RA(ini_arr, i, 0);
2839        u_int32_t val = INI_RA(ini_arr, i, column);
2840
2841        /*
2842        ** Determine if this is a shift register value
2843        ** (reg >= 0x16000 && reg < 0x17000 for Osprey) ,
2844        ** and insert the configured delay if so.
2845        ** -this delay is not required for Osprey (EV#71410)
2846        */
2847        OS_REG_WRITE(ah, reg, val);
2848        WAR_6773(reg_writes);
2849
2850    }
2851}
2852
2853static inline HAL_STATUS
2854ar9300_process_ini(struct ath_hal *ah, struct ieee80211_channel *chan,
2855    HAL_CHANNEL_INTERNAL *ichan, HAL_HT_MACMODE macmode)
2856{
2857    int reg_writes = 0;
2858    struct ath_hal_9300 *ahp = AH9300(ah);
2859    u_int modes_index, modes_txgaintable_index = 0;
2860    int i;
2861    HAL_STATUS status;
2862    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
2863    /* Setup the indices for the next set of register array writes */
2864    /* TODO:
2865     * If the channel marker is indicative of the current mode rather
2866     * than capability, we do not need to check the phy mode below.
2867     */
2868#if 0
2869    switch (chan->channel_flags & CHANNEL_ALL) {
2870    case CHANNEL_A:
2871    case CHANNEL_A_HT20:
2872        if (AR_SREV_SCORPION(ah)){
2873            if (chan->channel <= 5350){
2874                modes_txgaintable_index = 1;
2875            }else if ((chan->channel > 5350) && (chan->channel <= 5600)){
2876                modes_txgaintable_index = 3;
2877            }else if (chan->channel > 5600){
2878                modes_txgaintable_index = 5;
2879            }
2880        }
2881        modes_index = 1;
2882        freq_index  = 1;
2883        break;
2884
2885    case CHANNEL_A_HT40PLUS:
2886    case CHANNEL_A_HT40MINUS:
2887        if (AR_SREV_SCORPION(ah)){
2888            if (chan->channel <= 5350){
2889                modes_txgaintable_index = 2;
2890            }else if ((chan->channel > 5350) && (chan->channel <= 5600)){
2891                modes_txgaintable_index = 4;
2892            }else if (chan->channel > 5600){
2893                modes_txgaintable_index = 6;
2894            }
2895        }
2896        modes_index = 2;
2897        freq_index  = 1;
2898        break;
2899
2900    case CHANNEL_PUREG:
2901    case CHANNEL_G_HT20:
2902    case CHANNEL_B:
2903        if (AR_SREV_SCORPION(ah)){
2904            modes_txgaintable_index = 8;
2905        }else if (AR_SREV_HONEYBEE(ah)){
2906	    modes_txgaintable_index = 1;
2907	}
2908        modes_index = 4;
2909        freq_index  = 2;
2910        break;
2911
2912    case CHANNEL_G_HT40PLUS:
2913    case CHANNEL_G_HT40MINUS:
2914        if (AR_SREV_SCORPION(ah)){
2915            modes_txgaintable_index = 7;
2916        }else if (AR_SREV_HONEYBEE(ah)){
2917            modes_txgaintable_index = 1;
2918        }
2919        modes_index = 3;
2920        freq_index  = 2;
2921        break;
2922
2923    case CHANNEL_108G:
2924        modes_index = 5;
2925        freq_index  = 2;
2926        break;
2927
2928    default:
2929        HALASSERT(0);
2930        return HAL_EINVAL;
2931    }
2932#endif
2933
2934    /* FreeBSD */
2935    if (IS_CHAN_5GHZ(ichan)) {
2936        if (IEEE80211_IS_CHAN_HT40U(chan) || IEEE80211_IS_CHAN_HT40D(chan)) {
2937            if (AR_SREV_SCORPION(ah)){
2938                if (ichan->channel <= 5350){
2939                    modes_txgaintable_index = 2;
2940                }else if ((ichan->channel > 5350) && (ichan->channel <= 5600)){
2941                    modes_txgaintable_index = 4;
2942                }else if (ichan->channel > 5600){
2943                    modes_txgaintable_index = 6;
2944                }
2945            }
2946            modes_index = 2;
2947        } else if (IEEE80211_IS_CHAN_A(chan) || IEEE80211_IS_CHAN_HT20(chan)) {
2948            if (AR_SREV_SCORPION(ah)){
2949                if (ichan->channel <= 5350){
2950                    modes_txgaintable_index = 1;
2951                }else if ((ichan->channel > 5350) && (ichan->channel <= 5600)){
2952                    modes_txgaintable_index = 3;
2953                }else if (ichan->channel > 5600){
2954                    modes_txgaintable_index = 5;
2955                }
2956            }
2957            modes_index = 1;
2958        } else
2959            return HAL_EINVAL;
2960    } else if (IS_CHAN_2GHZ(ichan)) {
2961        if (IEEE80211_IS_CHAN_108G(chan)) {
2962            modes_index = 5;
2963        } else if (IEEE80211_IS_CHAN_HT40U(chan) || IEEE80211_IS_CHAN_HT40D(chan)) {
2964            if (AR_SREV_SCORPION(ah)){
2965                modes_txgaintable_index = 7;
2966            } else if (AR_SREV_HONEYBEE(ah)){
2967                modes_txgaintable_index = 1;
2968            }
2969            modes_index = 3;
2970        } else if (IEEE80211_IS_CHAN_HT20(chan) || IEEE80211_IS_CHAN_G(chan) || IEEE80211_IS_CHAN_B(chan) || IEEE80211_IS_CHAN_PUREG(chan)) {
2971            if (AR_SREV_SCORPION(ah)){
2972                modes_txgaintable_index = 8;
2973            } else if (AR_SREV_HONEYBEE(ah)){
2974                modes_txgaintable_index = 1;
2975            }
2976            modes_index = 4;
2977        } else
2978            return HAL_EINVAL;
2979    } else
2980            return HAL_EINVAL;
2981
2982#if 0
2983    /* Set correct Baseband to analog shift setting to access analog chips. */
2984    OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
2985#endif
2986
2987    HALDEBUG(ah, HAL_DEBUG_RESET,
2988        "ar9300_process_ini: "
2989        "Skipping OS-REG-WRITE(ah, AR-PHY(0), 0x00000007)\n");
2990    HALDEBUG(ah, HAL_DEBUG_RESET,
2991        "ar9300_process_ini: no ADDac programming\n");
2992
2993
2994    /*
2995     * Osprey 2.0+ - new INI format.
2996     * Each subsystem has a pre, core, and post array.
2997     */
2998    for (i = 0; i < ATH_INI_NUM_SPLIT; i++) {
2999        ar9300_prog_ini(ah, &ahp->ah_ini_soc[i], modes_index);
3000        ar9300_prog_ini(ah, &ahp->ah_ini_mac[i], modes_index);
3001        ar9300_prog_ini(ah, &ahp->ah_ini_bb[i], modes_index);
3002        ar9300_prog_ini(ah, &ahp->ah_ini_radio[i], modes_index);
3003        if ((i == ATH_INI_POST) && (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah))) {
3004            ar9300_prog_ini(ah, &ahp->ah_ini_radio_post_sys2ant, modes_index);
3005        }
3006
3007    }
3008
3009	if (!(AR_SREV_SOC(ah))) {
3010			/* Doubler issue : Some board doesn't work well with MCS15. Turn off doubler after freq locking is complete*/
3011			//ath_hal_printf(ah, "%s[%d] ==== before reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2));
3012			OS_REG_RMW(ah, AR_PHY_65NM_CH0_RXTX2, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
3013			               1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0); /*Set synthon, synthover */
3014			//ath_hal_printf(ah, "%s[%d] ==== after reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2));
3015
3016			OS_REG_RMW(ah, AR_PHY_65NM_CH1_RXTX2, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
3017			               1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0); /*Set synthon, synthover */
3018			OS_REG_RMW(ah, AR_PHY_65NM_CH2_RXTX2, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
3019			               1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0); /*Set synthon, synthover */
3020			OS_DELAY(200);
3021
3022			//ath_hal_printf(ah, "%s[%d] ==== before reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2));
3023			OS_REG_CLR_BIT(ah, AR_PHY_65NM_CH0_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK); /* clr synthon */
3024			OS_REG_CLR_BIT(ah, AR_PHY_65NM_CH1_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK); /* clr synthon */
3025			OS_REG_CLR_BIT(ah, AR_PHY_65NM_CH2_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK); /* clr synthon */
3026			//ath_hal_printf(ah, "%s[%d] ==== after reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2));
3027
3028			OS_DELAY(1);
3029
3030			//ath_hal_printf(ah, "%s[%d] ==== before reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2));
3031			OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1); /* set synthon */
3032			OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1); /* set synthon */
3033			OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX2, AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1); /* set synthon */
3034			//ath_hal_printf(ah, "%s[%d] ==== after reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2));
3035
3036			OS_DELAY(200);
3037
3038			//ath_hal_printf(ah, "%s[%d] ==== before reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_SYNTH12, OS_REG_READ(ah, AR_PHY_65NM_CH0_SYNTH12));
3039			OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH12, AR_PHY_65NM_CH0_SYNTH12_VREFMUL3, 0xf);
3040			//OS_REG_CLR_BIT(ah, AR_PHY_65NM_CH0_SYNTH12, 1<< 16); /* clr charge pump */
3041			//ath_hal_printf(ah, "%s[%d] ==== After  reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_SYNTH12, OS_REG_READ(ah, AR_PHY_65NM_CH0_SYNTH12));
3042
3043			OS_REG_RMW(ah, AR_PHY_65NM_CH0_RXTX2, 0, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
3044			               1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S); /*Clr synthon, synthover */
3045			OS_REG_RMW(ah, AR_PHY_65NM_CH1_RXTX2, 0, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
3046			               1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S); /*Clr synthon, synthover */
3047			OS_REG_RMW(ah, AR_PHY_65NM_CH2_RXTX2, 0, 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S |
3048			               1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S); /*Clr synthon, synthover */
3049			//ath_hal_printf(ah, "%s[%d] ==== after reg[0x%08x] = 0x%08x\n", __func__, __LINE__, AR_PHY_65NM_CH0_RXTX2, OS_REG_READ(ah, AR_PHY_65NM_CH0_RXTX2));
3050		}
3051
3052    /* Write rxgain Array Parameters */
3053    REG_WRITE_ARRAY(&ahp->ah_ini_modes_rxgain, 1, reg_writes);
3054    HALDEBUG(ah, HAL_DEBUG_RESET, "ar9300_process_ini: Rx Gain programming\n");
3055
3056    if (AR_SREV_JUPITER_20_OR_LATER(ah)) {
3057        /*
3058         * CUS217 mix LNA mode.
3059         */
3060        if (ar9300_rx_gain_index_get(ah) == 2) {
3061            REG_WRITE_ARRAY(&ahp->ah_ini_modes_rxgain_bb_core, 1, reg_writes);
3062            REG_WRITE_ARRAY(&ahp->ah_ini_modes_rxgain_bb_postamble,
3063                modes_index, reg_writes);
3064        }
3065
3066        /*
3067         * 5G-XLNA
3068         */
3069        if ((ar9300_rx_gain_index_get(ah) == 2) ||
3070            (ar9300_rx_gain_index_get(ah) == 3)) {
3071            REG_WRITE_ARRAY(&ahp->ah_ini_modes_rxgain_xlna, modes_index,
3072              reg_writes);
3073        }
3074    }
3075
3076    if (AR_SREV_SCORPION(ah)) {
3077        /* Write rxgain bounds Array */
3078        REG_WRITE_ARRAY(&ahp->ah_ini_modes_rxgain_bounds, modes_index, reg_writes);
3079        HALDEBUG(ah, HAL_DEBUG_RESET, "ar9300_process_ini: Rx Gain table bounds programming\n");
3080    }
3081    /* UB124 xLNA settings */
3082    if (AR_SREV_WASP(ah) && ar9300_rx_gain_index_get(ah) == 2) {
3083#define REG_WRITE(_reg,_val)    *((volatile u_int32_t *)(_reg)) = (_val);
3084#define REG_READ(_reg)          *((volatile u_int32_t *)(_reg))
3085        u_int32_t val;
3086        /* B8040000:  bit[0]=0, bit[3]=0; */
3087        val = REG_READ(0xB8040000);
3088        val &= 0xfffffff6;
3089        REG_WRITE(0xB8040000, val);
3090        /* B804002c:  bit[31:24]=0x2e; bit[7:0]=0x2f; */
3091        val = REG_READ(0xB804002c);
3092        val &= 0x00ffff00;
3093        val |= 0x2e00002f;
3094        REG_WRITE(0xB804002c, val);
3095        /* B804006c:  bit[1]=1; */
3096        val = REG_READ(0xB804006c);
3097        val |= 0x2;
3098        REG_WRITE(0xB804006c, val);
3099#undef REG_READ
3100#undef REG_WRITE
3101    }
3102
3103
3104    /* Write txgain Array Parameters */
3105    if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {
3106        REG_WRITE_ARRAY(&ahp->ah_ini_modes_txgain, modes_txgaintable_index,
3107            reg_writes);
3108    }else{
3109        REG_WRITE_ARRAY(&ahp->ah_ini_modes_txgain, modes_index, reg_writes);
3110    }
3111    HALDEBUG(ah, HAL_DEBUG_RESET, "ar9300_process_ini: Tx Gain programming\n");
3112
3113
3114    /* For 5GHz channels requiring Fast Clock, apply different modal values */
3115    if (IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
3116        HALDEBUG(ah, HAL_DEBUG_RESET,
3117            "%s: Fast clock enabled, use special ini values\n", __func__);
3118        REG_WRITE_ARRAY(&ahp->ah_ini_modes_additional, modes_index, reg_writes);
3119    }
3120
3121    if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) {
3122        HALDEBUG(ah, HAL_DEBUG_RESET,
3123            "%s: use xtal ini for AH9300(ah)->clk_25mhz: %d\n",
3124            __func__, AH9300(ah)->clk_25mhz);
3125        REG_WRITE_ARRAY(
3126            &ahp->ah_ini_modes_additional, 1/*modes_index*/, reg_writes);
3127    }
3128
3129    if (AR_SREV_WASP(ah) && (AH9300(ah)->clk_25mhz == 0)) {
3130        HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Apply 40MHz ini settings\n", __func__);
3131        REG_WRITE_ARRAY(
3132            &ahp->ah_ini_modes_additional_40mhz, 1/*modesIndex*/, reg_writes);
3133    }
3134
3135    /* Handle Japan Channel 14 channel spreading */
3136    if (2484 == ichan->channel) {
3137        ar9300_prog_ini(ah, &ahp->ah_ini_japan2484, 1);
3138    }
3139
3140#if 0
3141    /* XXX TODO! */
3142    if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
3143        ar9300_prog_ini(ah, &ahp->ah_ini_BTCOEX_MAX_TXPWR, 1);
3144    }
3145#endif
3146
3147    /* Override INI with chip specific configuration */
3148    ar9300_override_ini(ah, chan);
3149
3150    /* Setup 11n MAC/Phy mode registers */
3151    ar9300_set_11n_regs(ah, chan, macmode);
3152
3153    /*
3154     * Moved ar9300_init_chain_masks() here to ensure the swap bit is set before
3155     * the pdadc table is written.  Swap must occur before any radio dependent
3156     * replicated register access.  The pdadc curve addressing in particular
3157     * depends on the consistent setting of the swap bit.
3158     */
3159    ar9300_init_chain_masks(ah, ahp->ah_rx_chainmask, ahp->ah_tx_chainmask);
3160
3161    /*
3162     * Setup the transmit power values.
3163     *
3164     * After the public to private hal channel mapping, ichan contains the
3165     * valid regulatory power value.
3166     * ath_hal_getctl and ath_hal_getantennaallowed look up ichan from chan.
3167     */
3168    status = ar9300_eeprom_set_transmit_power(ah, &ahp->ah_eeprom, chan,
3169             ath_hal_getctl(ah, chan), ath_hal_getantennaallowed(ah, chan),
3170             ath_hal_get_twice_max_regpower(ahpriv, ichan, chan),
3171             AH_MIN(MAX_RATE_POWER, ahpriv->ah_powerLimit));
3172    if (status != HAL_OK) {
3173        HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
3174            "%s: error init'ing transmit power\n", __func__);
3175        return HAL_EIO;
3176    }
3177
3178
3179    return HAL_OK;
3180#undef N
3181}
3182
3183/* ar9300_is_cal_supp
3184 * Determine if calibration is supported by device and channel flags
3185 */
3186inline static HAL_BOOL
3187ar9300_is_cal_supp(struct ath_hal *ah, const struct ieee80211_channel *chan,
3188    HAL_CAL_TYPES cal_type)
3189{
3190    struct ath_hal_9300 *ahp = AH9300(ah);
3191    HAL_BOOL retval = AH_FALSE;
3192
3193    switch (cal_type & ahp->ah_supp_cals) {
3194    case IQ_MISMATCH_CAL:
3195        /* Run IQ Mismatch for non-CCK only */
3196        if (!IEEE80211_IS_CHAN_B(chan)) {
3197            retval = AH_TRUE;
3198        }
3199        break;
3200    case TEMP_COMP_CAL:
3201        retval = AH_TRUE;
3202        break;
3203    }
3204
3205    return retval;
3206}
3207
3208
3209#if 0
3210/* ar9285_pa_cal
3211 * PA Calibration for Kite 1.1 and later versions of Kite.
3212 * - from system's team.
3213 */
3214static inline void
3215ar9285_pa_cal(struct ath_hal *ah)
3216{
3217    u_int32_t reg_val;
3218    int i, lo_gn, offs_6_1, offs_0;
3219    u_int8_t reflo;
3220    u_int32_t phy_test2_reg_val, phy_adc_ctl_reg_val;
3221    u_int32_t an_top2_reg_val, phy_tst_dac_reg_val;
3222
3223
3224    /* Kite 1.1 WAR for Bug 35666
3225     * Increase the LDO value to 1.28V before accessing analog Reg */
3226    if (AR_SREV_KITE_11(ah)) {
3227        OS_REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14) );
3228    }
3229    an_top2_reg_val = OS_REG_READ(ah, AR9285_AN_TOP2);
3230
3231    /* set pdv2i pdrxtxbb */
3232    reg_val = OS_REG_READ(ah, AR9285_AN_RXTXBB1);
3233    reg_val |= ((0x1 << 5) | (0x1 << 7));
3234    OS_REG_WRITE(ah, AR9285_AN_RXTXBB1, reg_val);
3235
3236    /* clear pwddb */
3237    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G7);
3238    reg_val &= 0xfffffffd;
3239    OS_REG_WRITE(ah, AR9285_AN_RF2G7, reg_val);
3240
3241    /* clear enpacal */
3242    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G1);
3243    reg_val &= 0xfffff7ff;
3244    OS_REG_WRITE(ah, AR9285_AN_RF2G1, reg_val);
3245
3246    /* set offcal */
3247    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G2);
3248    reg_val |= (0x1 << 12);
3249    OS_REG_WRITE(ah, AR9285_AN_RF2G2, reg_val);
3250
3251    /* set pdpadrv1=pdpadrv2=pdpaout=1 */
3252    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G1);
3253    reg_val |= (0x7 << 23);
3254    OS_REG_WRITE(ah, AR9285_AN_RF2G1, reg_val);
3255
3256    /* Read back reflo, increase it by 1 and write it. */
3257    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3);
3258    reflo = ((reg_val >> 26) & 0x7);
3259
3260    if (reflo < 0x7) {
3261        reflo++;
3262    }
3263    reg_val = ((reg_val & 0xe3ffffff) | (reflo << 26));
3264    OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val);
3265
3266    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3);
3267    reflo = ((reg_val >> 26) & 0x7);
3268
3269    /* use TX single carrier to transmit
3270     * dac const
3271     * reg. 15
3272     */
3273    phy_tst_dac_reg_val = OS_REG_READ(ah, AR_PHY_TSTDAC_CONST);
3274    OS_REG_WRITE(ah, AR_PHY_TSTDAC_CONST, ((0x7ff << 11) | 0x7ff));
3275    reg_val = OS_REG_READ(ah, AR_PHY_TSTDAC_CONST);
3276
3277    /* source is dac const
3278     * reg. 2
3279     */
3280    phy_test2_reg_val = OS_REG_READ(ah, AR_PHY_TEST2);
3281    OS_REG_WRITE(ah, AR_PHY_TEST2, ((0x1 << 7) | (0x1 << 1)));
3282    reg_val = OS_REG_READ(ah, AR_PHY_TEST2);
3283
3284    /* set dac on
3285     * reg. 11
3286     */
3287    phy_adc_ctl_reg_val = OS_REG_READ(ah, AR_PHY_ADC_CTL);
3288    OS_REG_WRITE(ah, AR_PHY_ADC_CTL, 0x80008000);
3289    reg_val = OS_REG_READ(ah, AR_PHY_ADC_CTL);
3290
3291    OS_REG_WRITE(ah, AR9285_AN_TOP2, (0x1 << 27) | (0x1 << 17) | (0x1 << 16) |
3292              (0x1 << 14) | (0x1 << 12) | (0x1 << 11) |
3293              (0x1 << 7) | (0x1 << 5));
3294
3295    OS_DELAY(10); /* 10 usec */
3296
3297    /* clear off[6:0] */
3298    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G6);
3299    reg_val &= 0xfc0fffff;
3300    OS_REG_WRITE(ah, AR9285_AN_RF2G6, reg_val);
3301    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3);
3302    reg_val &= 0xfdffffff;
3303    OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val);
3304
3305    offs_6_1 = 0;
3306    for (i = 6; i > 0; i--) {
3307        /* sef off[$k]==1 */
3308        reg_val = OS_REG_READ(ah, AR9285_AN_RF2G6);
3309        reg_val &= 0xfc0fffff;
3310        reg_val = reg_val | (0x1 << (19 + i)) | ((offs_6_1) << 20);
3311        OS_REG_WRITE(ah, AR9285_AN_RF2G6, reg_val);
3312        lo_gn = (OS_REG_READ(ah, AR9285_AN_RF2G9)) & 0x1;
3313        offs_6_1 = offs_6_1 | (lo_gn << (i - 1));
3314    }
3315
3316    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G6);
3317    reg_val &= 0xfc0fffff;
3318    reg_val = reg_val | ((offs_6_1 - 1) << 20);
3319    OS_REG_WRITE(ah, AR9285_AN_RF2G6, reg_val);
3320
3321    /* set off_0=1; */
3322    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3);
3323    reg_val &= 0xfdffffff;
3324    reg_val = reg_val | (0x1 << 25);
3325    OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val);
3326
3327    lo_gn = OS_REG_READ(ah, AR9285_AN_RF2G9) & 0x1;
3328    offs_0 = lo_gn;
3329
3330    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3);
3331    reg_val &= 0xfdffffff;
3332    reg_val = reg_val | (offs_0 << 25);
3333    OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val);
3334
3335    /* clear pdv2i */
3336    reg_val = OS_REG_READ(ah, AR9285_AN_RXTXBB1);
3337    reg_val &= 0xffffff5f;
3338    OS_REG_WRITE(ah, AR9285_AN_RXTXBB1, reg_val);
3339
3340    /* set enpacal */
3341    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G1);
3342    reg_val |= (0x1 << 11);
3343    OS_REG_WRITE(ah, AR9285_AN_RF2G1, reg_val);
3344
3345    /* clear offcal */
3346    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G2);
3347    reg_val &= 0xffffefff;
3348    OS_REG_WRITE(ah, AR9285_AN_RF2G2, reg_val);
3349
3350    /* set pdpadrv1=pdpadrv2=pdpaout=0 */
3351    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G1);
3352    reg_val &= 0xfc7fffff;
3353    OS_REG_WRITE(ah, AR9285_AN_RF2G1, reg_val);
3354
3355    /* Read back reflo, decrease it by 1 and write it. */
3356    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3);
3357    reflo = (reg_val >> 26) & 0x7;
3358    if (reflo) {
3359        reflo--;
3360    }
3361    reg_val = ((reg_val & 0xe3ffffff) | (reflo << 26));
3362    OS_REG_WRITE(ah, AR9285_AN_RF2G3, reg_val);
3363    reg_val = OS_REG_READ(ah, AR9285_AN_RF2G3);
3364    reflo = (reg_val >> 26) & 0x7;
3365
3366    /* write back registers */
3367    OS_REG_WRITE(ah, AR_PHY_TSTDAC_CONST, phy_tst_dac_reg_val);
3368    OS_REG_WRITE(ah, AR_PHY_TEST2, phy_test2_reg_val);
3369    OS_REG_WRITE(ah, AR_PHY_ADC_CTL, phy_adc_ctl_reg_val);
3370    OS_REG_WRITE(ah, AR9285_AN_TOP2, an_top2_reg_val);
3371
3372    /* Kite 1.1 WAR for Bug 35666
3373     * Decrease the LDO value back to 1.20V */
3374    if (AR_SREV_KITE_11(ah)) {
3375        OS_REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
3376    }
3377}
3378#endif
3379
3380/* ar9300_run_init_cals
3381 * Runs non-periodic calibrations
3382 */
3383inline static HAL_BOOL
3384ar9300_run_init_cals(struct ath_hal *ah, int init_cal_count)
3385{
3386    struct ath_hal_9300 *ahp = AH9300(ah);
3387    HAL_CHANNEL_INTERNAL ichan; /* bogus */
3388    HAL_BOOL is_cal_done;
3389    HAL_CAL_LIST *curr_cal;
3390    const HAL_PERCAL_DATA *cal_data;
3391    int i;
3392
3393    curr_cal = ahp->ah_cal_list_curr;
3394    if (curr_cal == AH_NULL) {
3395        return AH_FALSE;
3396    }
3397    cal_data = curr_cal->cal_data;
3398    ichan.calValid = 0;
3399
3400    for (i = 0; i < init_cal_count; i++) {
3401        /* Reset this Cal */
3402        ar9300_reset_calibration(ah, curr_cal);
3403        /* Poll for offset calibration complete */
3404        if (!ath_hal_wait(
3405                ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL, 0))
3406        {
3407            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3408                "%s: Cal %d failed to complete in 100ms.\n",
3409                __func__, curr_cal->cal_data->cal_type);
3410            /* Re-initialize list pointers for periodic cals */
3411            ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr
3412                = AH_NULL;
3413            return AH_FALSE;
3414        }
3415        /* Run this cal */
3416        ar9300_per_calibration(
3417            ah, &ichan, ahp->ah_rx_chainmask, curr_cal, &is_cal_done);
3418        if (is_cal_done == AH_FALSE) {
3419            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3420                "%s: Not able to run Init Cal %d.\n", __func__,
3421                curr_cal->cal_data->cal_type);
3422        }
3423        if (curr_cal->cal_next) {
3424            curr_cal = curr_cal->cal_next;
3425        }
3426    }
3427
3428    /* Re-initialize list pointers for periodic cals */
3429    ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = AH_NULL;
3430    return AH_TRUE;
3431}
3432
3433#if 0
3434static void
3435ar9300_tx_carrier_leak_war(struct ath_hal *ah)
3436{
3437    unsigned long tx_gain_table_max;
3438    unsigned long reg_bb_cl_map_0_b0 = 0xffffffff;
3439    unsigned long reg_bb_cl_map_1_b0 = 0xffffffff;
3440    unsigned long reg_bb_cl_map_2_b0 = 0xffffffff;
3441    unsigned long reg_bb_cl_map_3_b0 = 0xffffffff;
3442    unsigned long tx_gain, cal_run = 0;
3443    unsigned long cal_gain[AR_PHY_TPC_7_TX_GAIN_TABLE_MAX + 1];
3444    unsigned long cal_gain_index[AR_PHY_TPC_7_TX_GAIN_TABLE_MAX + 1];
3445    unsigned long new_gain[AR_PHY_TPC_7_TX_GAIN_TABLE_MAX + 1];
3446    int i, j;
3447
3448    OS_MEMSET(new_gain, 0, sizeof(new_gain));
3449    /*printf("     Running TxCarrierLeakWAR\n");*/
3450
3451    /* process tx gain table, we use cl_map_hw_gen=0. */
3452    OS_REG_RMW_FIELD(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_MAP_HW_GEN, 0);
3453
3454	//the table we used is txbb_gc[2:0], 1dB[2:1].
3455    tx_gain_table_max = OS_REG_READ_FIELD(ah,
3456        AR_PHY_TPC_7, AR_PHY_TPC_7_TX_GAIN_TABLE_MAX);
3457
3458    for (i = 0; i <= tx_gain_table_max; i++) {
3459        tx_gain = OS_REG_READ(ah, AR_PHY_TXGAIN_TAB(1) + i * 4);
3460        cal_gain[i] = (((tx_gain >> 5)& 0x7) << 2) |
3461            (((tx_gain >> 1) & 0x3) << 0);
3462        if (i == 0) {
3463            cal_gain_index[i] = cal_run;
3464            new_gain[i] = 1;
3465            cal_run++;
3466        } else {
3467            new_gain[i] = 1;
3468            for (j = 0; j < i; j++) {
3469                /*
3470                printf("i=%d, j=%d cal_gain[$i]=0x%04x\n", i, j, cal_gain[i]);
3471                 */
3472                if (new_gain[i]) {
3473                    if ((cal_gain[i] != cal_gain[j])) {
3474                        new_gain[i] = 1;
3475                    } else {
3476                        /* if old gain found, use old cal_run value. */
3477                        new_gain[i] = 0;
3478                        cal_gain_index[i] = cal_gain_index[j];
3479                    }
3480                }
3481            }
3482            /* if new gain found, increase cal_run */
3483            if (new_gain[i] == 1) {
3484                cal_gain_index[i] = cal_run;
3485                cal_run++;
3486            }
3487        }
3488
3489        reg_bb_cl_map_0_b0 = (reg_bb_cl_map_0_b0 & ~(0x1 << i)) |
3490            ((cal_gain_index[i] >> 0 & 0x1) << i);
3491        reg_bb_cl_map_1_b0 = (reg_bb_cl_map_1_b0 & ~(0x1 << i)) |
3492            ((cal_gain_index[i] >> 1 & 0x1) << i);
3493        reg_bb_cl_map_2_b0 = (reg_bb_cl_map_2_b0 & ~(0x1 << i)) |
3494            ((cal_gain_index[i] >> 2 & 0x1) << i);
3495        reg_bb_cl_map_3_b0 = (reg_bb_cl_map_3_b0 & ~(0x1 << i)) |
3496            ((cal_gain_index[i] >> 3 & 0x1) << i);
3497
3498        /*
3499        printf("i=%2d, cal_gain[$i]= 0x%04x, cal_run= %d, "
3500            "cal_gain_index[i]=%d, new_gain[i] = %d\n",
3501            i, cal_gain[i], cal_run, cal_gain_index[i], new_gain[i]);
3502         */
3503    }
3504    OS_REG_WRITE(ah, AR_PHY_CL_MAP_0_B0, reg_bb_cl_map_0_b0);
3505    OS_REG_WRITE(ah, AR_PHY_CL_MAP_1_B0, reg_bb_cl_map_1_b0);
3506    OS_REG_WRITE(ah, AR_PHY_CL_MAP_2_B0, reg_bb_cl_map_2_b0);
3507    OS_REG_WRITE(ah, AR_PHY_CL_MAP_3_B0, reg_bb_cl_map_3_b0);
3508    if (AR_SREV_WASP(ah)) {
3509        OS_REG_WRITE(ah, AR_PHY_CL_MAP_0_B1, reg_bb_cl_map_0_b0);
3510        OS_REG_WRITE(ah, AR_PHY_CL_MAP_1_B1, reg_bb_cl_map_1_b0);
3511        OS_REG_WRITE(ah, AR_PHY_CL_MAP_2_B1, reg_bb_cl_map_2_b0);
3512        OS_REG_WRITE(ah, AR_PHY_CL_MAP_3_B1, reg_bb_cl_map_3_b0);
3513    }
3514}
3515#endif
3516
3517
3518static inline void
3519ar9300_invalidate_saved_cals(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
3520{
3521#if ATH_SUPPORT_CAL_REUSE
3522    if (AH_PRIVATE(ah)->ah_config.ath_hal_cal_reuse &
3523        ATH_CAL_REUSE_REDO_IN_FULL_RESET)
3524    {
3525        ichan->one_time_txiqcal_done = AH_FALSE;
3526        ichan->one_time_txclcal_done = AH_FALSE;
3527    }
3528#endif
3529}
3530
3531static inline HAL_BOOL
3532ar9300_restore_rtt_cals(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
3533{
3534    HAL_BOOL restore_status = AH_FALSE;
3535
3536    return restore_status;
3537}
3538
3539/* ar9300_init_cal
3540 * Initialize Calibration infrastructure
3541 */
3542static inline HAL_BOOL
3543ar9300_init_cal_internal(struct ath_hal *ah, struct ieee80211_channel *chan,
3544                         HAL_CHANNEL_INTERNAL *ichan,
3545                         HAL_BOOL enable_rtt, HAL_BOOL do_rtt_cal, HAL_BOOL skip_if_none, HAL_BOOL apply_last_iqcorr)
3546{
3547    struct ath_hal_9300 *ahp = AH9300(ah);
3548    HAL_BOOL txiqcal_success_flag = AH_FALSE;
3549    HAL_BOOL cal_done = AH_FALSE;
3550    int iqcal_idx = 0;
3551    HAL_BOOL do_sep_iq_cal = AH_FALSE;
3552    HAL_BOOL do_agc_cal = do_rtt_cal;
3553    HAL_BOOL is_cal_reusable = AH_TRUE;
3554#if ATH_SUPPORT_CAL_REUSE
3555    HAL_BOOL      cal_reuse_enable = AH_PRIVATE(ah)->ah_config.ath_hal_cal_reuse &
3556                                 ATH_CAL_REUSE_ENABLE;
3557    HAL_BOOL      clc_success = AH_FALSE;
3558    int32_t   ch_idx, j, cl_tab_reg;
3559    u_int32_t BB_cl_tab_entry = MAX_BB_CL_TABLE_ENTRY;
3560    u_int32_t BB_cl_tab_b[AR9300_MAX_CHAINS] = {
3561                    AR_PHY_CL_TAB_0,
3562                    AR_PHY_CL_TAB_1,
3563                    AR_PHY_CL_TAB_2
3564                };
3565#endif
3566
3567    if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
3568        /* Hornet: 1 x 1 */
3569        ahp->ah_rx_cal_chainmask = 0x1;
3570        ahp->ah_tx_cal_chainmask = 0x1;
3571    } else if (AR_SREV_WASP(ah) || AR_SREV_JUPITER(ah) || AR_SREV_HONEYBEE(ah)) {
3572        /* Wasp/Jupiter: 2 x 2 */
3573        ahp->ah_rx_cal_chainmask = 0x3;
3574        ahp->ah_tx_cal_chainmask = 0x3;
3575    } else {
3576        /*
3577         * Osprey needs to be configured for the correct chain mode
3578         * before running AGC/TxIQ cals.
3579         */
3580        if (ahp->ah_enterprise_mode & AR_ENT_OTP_CHAIN2_DISABLE) {
3581            /* chain 2 disabled - 2 chain mode */
3582            ahp->ah_rx_cal_chainmask = 0x3;
3583            ahp->ah_tx_cal_chainmask = 0x3;
3584        } else {
3585            ahp->ah_rx_cal_chainmask = 0x7;
3586            ahp->ah_tx_cal_chainmask = 0x7;
3587        }
3588    }
3589        ar9300_init_chain_masks(ah, ahp->ah_rx_cal_chainmask, ahp->ah_tx_cal_chainmask);
3590
3591
3592    if (ahp->tx_cl_cal_enable) {
3593#if ATH_SUPPORT_CAL_REUSE
3594        /* disable Carrie Leak or set do_agc_cal accordingly */
3595        if (cal_reuse_enable && ichan->one_time_txclcal_done)
3596        {
3597            OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
3598        } else
3599#endif /* ATH_SUPPORT_CAL_REUSE */
3600        {
3601            OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
3602            do_agc_cal = AH_TRUE;
3603        }
3604    }
3605
3606    /* Do Tx IQ Calibration here for osprey hornet and wasp */
3607    /* XXX: For initial wasp bringup - check and enable this */
3608    /* EV 74233: Tx IQ fails to complete for half/quarter rates */
3609    if (!(IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) {
3610        if (ahp->tx_iq_cal_enable) {
3611            /* this should be eventually moved to INI file */
3612            OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1(ah),
3613                AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT);
3614
3615            /*
3616             * For poseidon and later chips,
3617             * Tx IQ cal HW run will be a part of AGC calibration
3618             */
3619            if (ahp->tx_iq_cal_during_agc_cal) {
3620                /*
3621                 * txiqcal_success_flag always set to 1 to run
3622                 *     ar9300_tx_iq_cal_post_proc
3623                 * if following AGC cal passes
3624                */
3625#if ATH_SUPPORT_CAL_REUSE
3626                if (!cal_reuse_enable || !ichan->one_time_txiqcal_done)
3627                {
3628                    txiqcal_success_flag = AH_TRUE;
3629                    OS_REG_WRITE(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah),
3630                        OS_REG_READ(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah)) |
3631                        AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
3632                } else {
3633                    OS_REG_WRITE(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah),
3634                        OS_REG_READ(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah)) &
3635                        (~AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL));
3636                }
3637#else
3638		if (OS_REG_READ_FIELD(ah,
3639					AR_PHY_TX_IQCAL_CONTROL_0(ah),
3640					AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)){
3641			if (apply_last_iqcorr == AH_TRUE) {
3642				OS_REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0(ah),
3643						AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
3644				txiqcal_success_flag = AH_FALSE;
3645			} else {
3646				txiqcal_success_flag = AH_TRUE;
3647			}
3648		}else{
3649			txiqcal_success_flag = AH_FALSE;
3650		}
3651#endif
3652                if (txiqcal_success_flag) {
3653                    do_agc_cal = AH_TRUE;
3654                }
3655            } else
3656#if ATH_SUPPORT_CAL_REUSE
3657            if (!cal_reuse_enable || !ichan->one_time_txiqcal_done)
3658#endif
3659            {
3660                do_sep_iq_cal = AH_TRUE;
3661                do_agc_cal = AH_TRUE;
3662            }
3663        }
3664    }
3665
3666#if ATH_SUPPORT_MCI
3667    if (AH_PRIVATE(ah)->ah_caps.halMciSupport &&
3668        IS_CHAN_2GHZ(ichan) &&
3669        (ahp->ah_mci_bt_state == MCI_BT_AWAKE) &&
3670        do_agc_cal &&
3671        !(ah->ah_config.ath_hal_mci_config &
3672        ATH_MCI_CONFIG_DISABLE_MCI_CAL))
3673    {
3674        u_int32_t payload[4] = {0, 0, 0, 0};
3675
3676        /* Send CAL_REQ only when BT is AWAKE. */
3677        HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send WLAN_CAL_REQ 0x%X\n",
3678            __func__, ahp->ah_mci_wlan_cal_seq);
3679        MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_REQ);
3680        payload[MCI_GPM_WLAN_CAL_W_SEQUENCE] = ahp->ah_mci_wlan_cal_seq++;
3681        ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, AH_TRUE, AH_FALSE);
3682
3683        /* Wait BT_CAL_GRANT for 50ms */
3684        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
3685            "(MCI) %s: Wait for BT_CAL_GRANT\n", __func__);
3686        if (ar9300_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000))
3687        {
3688            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
3689                "(MCI) %s: Got BT_CAL_GRANT.\n", __func__);
3690        }
3691        else {
3692            is_cal_reusable = AH_FALSE;
3693            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
3694                "(MCI) %s: BT is not responding.\n", __func__);
3695        }
3696    }
3697#endif /* ATH_SUPPORT_MCI */
3698
3699    if (do_sep_iq_cal)
3700    {
3701        /* enable Tx IQ Calibration HW for osprey/hornet/wasp */
3702        txiqcal_success_flag = ar9300_tx_iq_cal_hw_run(ah);
3703        OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
3704        OS_DELAY(5);
3705        OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
3706    }
3707#if 0
3708    if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) {
3709        ar9300_tx_carrier_leak_war(ah);
3710    }
3711#endif
3712    /*
3713     * Calibrate the AGC
3714     *
3715     * Tx IQ cal is a part of AGC cal for Jupiter/Poseidon, etc.
3716     * please enable the bit of txiqcal_control_0[31] in INI file
3717     * for Jupiter/Poseidon/etc.
3718     */
3719    if(!AR_SREV_SCORPION(ah)) {
3720        if (do_agc_cal || !skip_if_none) {
3721            OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
3722                OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
3723
3724            /* Poll for offset calibration complete */
3725            cal_done = ath_hal_wait(ah,
3726                    AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0);
3727            if (!cal_done) {
3728                HALDEBUG(ah, HAL_DEBUG_FCS_RTT,
3729                    "(FCS) CAL NOT DONE!!! - %d\n", ichan->channel);
3730            }
3731        } else {
3732            cal_done = AH_TRUE;
3733        }
3734            /*
3735             * Tx IQ cal post-processing in SW
3736             * This part of code should be common to all chips,
3737             * no chip specific code for Jupiter/Posdeion except for register names.
3738             */
3739            if (txiqcal_success_flag) {
3740                ar9300_tx_iq_cal_post_proc(ah,ichan, 1, 1,is_cal_reusable, AH_FALSE);
3741            }
3742    } else {
3743        if (!txiqcal_success_flag) {
3744            OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
3745                OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
3746            if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
3747                    0)) {
3748                HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3749                    "%s: offset calibration failed to complete in 1ms; "
3750                    "noisy environment?\n", __func__);
3751                return AH_FALSE;
3752            }
3753            if (apply_last_iqcorr == AH_TRUE) {
3754                ar9300_tx_iq_cal_post_proc(ah, ichan, 0, 0, is_cal_reusable, AH_TRUE);
3755            }
3756        } else {
3757            for (iqcal_idx=0;iqcal_idx<MAXIQCAL;iqcal_idx++) {
3758                OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
3759                    OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL);
3760
3761                /* Poll for offset calibration complete */
3762                if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL,
3763                        AR_PHY_AGC_CONTROL_CAL, 0)) {
3764                    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3765                        "%s: offset calibration failed to complete in 1ms; "
3766                        "noisy environment?\n", __func__);
3767                    return AH_FALSE;
3768                }
3769                /*
3770                 * Tx IQ cal post-processing in SW
3771                 * This part of code should be common to all chips,
3772                 * no chip specific code for Jupiter/Posdeion except for register names.
3773                 */
3774                ar9300_tx_iq_cal_post_proc(ah, ichan, iqcal_idx+1, MAXIQCAL, is_cal_reusable, AH_FALSE);
3775            }
3776       }
3777    }
3778
3779
3780#if ATH_SUPPORT_MCI
3781    if (AH_PRIVATE(ah)->ah_caps.halMciSupport &&
3782        IS_CHAN_2GHZ(ichan) &&
3783        (ahp->ah_mci_bt_state == MCI_BT_AWAKE) &&
3784        do_agc_cal &&
3785        !(ah->ah_config.ath_hal_mci_config &
3786        ATH_MCI_CONFIG_DISABLE_MCI_CAL))
3787    {
3788        u_int32_t payload[4] = {0, 0, 0, 0};
3789
3790        HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send WLAN_CAL_DONE 0x%X\n",
3791            __func__, ahp->ah_mci_wlan_cal_done);
3792        MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE);
3793        payload[MCI_GPM_WLAN_CAL_W_SEQUENCE] = ahp->ah_mci_wlan_cal_done++;
3794        ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, AH_TRUE, AH_FALSE);
3795    }
3796#endif /* ATH_SUPPORT_MCI */
3797
3798
3799    if (!cal_done && !AR_SREV_SCORPION(ah) )
3800    {
3801        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3802            "%s: offset calibration failed to complete in 1ms; "
3803            "noisy environment?\n", __func__);
3804        return AH_FALSE;
3805    }
3806
3807#if 0
3808     /* Beacon stuck fix, refer to EV 120056 */
3809    if(IS_CHAN_2GHZ(chan) && AR_SREV_SCORPION(ah))
3810        OS_REG_WRITE(ah, AR_PHY_TIMING5, OS_REG_READ(ah,AR_PHY_TIMING5) & ~AR_PHY_TIMING5_CYCPWR_THR1_ENABLE);
3811#endif
3812
3813#if 0
3814    /* Do PA Calibration */
3815    if (AR_SREV_KITE(ah) && AR_SREV_KITE_11_OR_LATER(ah)) {
3816        ar9285_pa_cal(ah);
3817    }
3818#endif
3819
3820#if ATH_SUPPORT_CAL_REUSE
3821     if (ichan->one_time_txiqcal_done) {
3822        ar9300_tx_iq_cal_apply(ah, ichan);
3823        HALDEBUG(ah, HAL_DEBUG_FCS_RTT,
3824            "(FCS) TXIQCAL applied - %d\n", ichan->channel);
3825    }
3826#endif /* ATH_SUPPORT_CAL_REUSE */
3827
3828#if ATH_SUPPORT_CAL_REUSE
3829    if (cal_reuse_enable && ahp->tx_cl_cal_enable)
3830    {
3831        clc_success = (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) &
3832                  AR_PHY_AGC_CONTROL_CLC_SUCCESS) ? 1 : 0;
3833
3834        if (ichan->one_time_txclcal_done)
3835        {
3836            /* reapply CL cal results */
3837            for (ch_idx = 0; ch_idx < AR9300_MAX_CHAINS; ch_idx++) {
3838                if ((ahp->ah_tx_cal_chainmask & (1 << ch_idx)) == 0) {
3839                    continue;
3840                }
3841                cl_tab_reg = BB_cl_tab_b[ch_idx];
3842                for (j = 0; j < BB_cl_tab_entry; j++) {
3843                    OS_REG_WRITE(ah, cl_tab_reg, ichan->tx_clcal[ch_idx][j]);
3844                    cl_tab_reg += 4;;
3845                }
3846            }
3847            HALDEBUG(ah, HAL_DEBUG_FCS_RTT,
3848                "(FCS) TX CL CAL applied - %d\n", ichan->channel);
3849        }
3850        else if (is_cal_reusable && clc_success) {
3851            /* save CL cal results */
3852            for (ch_idx = 0; ch_idx < AR9300_MAX_CHAINS; ch_idx++) {
3853                if ((ahp->ah_tx_cal_chainmask & (1 << ch_idx)) == 0) {
3854                    continue;
3855                }
3856                cl_tab_reg = BB_cl_tab_b[ch_idx];
3857                for (j = 0; j < BB_cl_tab_entry; j++) {
3858                    ichan->tx_clcal[ch_idx][j] = OS_REG_READ(ah, cl_tab_reg);
3859                    cl_tab_reg += 4;
3860                }
3861            }
3862            ichan->one_time_txclcal_done = AH_TRUE;
3863            HALDEBUG(ah, HAL_DEBUG_FCS_RTT,
3864                "(FCS) TX CL CAL saved - %d\n", ichan->channel);
3865        }
3866    }
3867#endif /* ATH_SUPPORT_CAL_REUSE */
3868
3869    /* Revert chainmasks to their original values before NF cal */
3870    ar9300_init_chain_masks(ah, ahp->ah_rx_chainmask, ahp->ah_tx_chainmask);
3871
3872#if !FIX_NOISE_FLOOR
3873    /*
3874     * Do NF calibration after DC offset and other CALs.
3875     * Per system engineers, noise floor value can sometimes be 20 dB
3876     * higher than normal value if DC offset and noise floor cal are
3877     * triggered at the same time.
3878     */
3879    OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
3880        OS_REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
3881#endif
3882
3883    /* Initialize list pointers */
3884    ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = AH_NULL;
3885
3886    /*
3887     * Enable IQ, ADC Gain, ADC DC Offset Cals
3888     */
3889    /* Setup all non-periodic, init time only calibrations */
3890    /* XXX: Init DC Offset not working yet */
3891#ifdef not_yet
3892    if (AH_TRUE == ar9300_is_cal_supp(ah, chan, ADC_DC_INIT_CAL)) {
3893        INIT_CAL(&ahp->ah_adc_dc_cal_init_data);
3894        INSERT_CAL(ahp, &ahp->ah_adc_dc_cal_init_data);
3895    }
3896
3897    /* Initialize current pointer to first element in list */
3898    ahp->ah_cal_list_curr = ahp->ah_cal_list;
3899
3900    if (ahp->ah_cal_list_curr) {
3901        if (ar9300_run_init_cals(ah, 0) == AH_FALSE) {
3902            return AH_FALSE;
3903        }
3904    }
3905#endif
3906    /* end - Init time calibrations */
3907
3908    /* Do not do RX cal in case of offchan, or cal data already exists on same channel*/
3909    if (ahp->ah_skip_rx_iq_cal) {
3910        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3911                "Skip RX IQ Cal\n");
3912        return AH_TRUE;
3913    }
3914
3915    /* If Cals are supported, add them to list via INIT/INSERT_CAL */
3916    if (AH_TRUE == ar9300_is_cal_supp(ah, chan, IQ_MISMATCH_CAL)) {
3917        INIT_CAL(&ahp->ah_iq_cal_data);
3918        INSERT_CAL(ahp, &ahp->ah_iq_cal_data);
3919        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3920            "%s: enabling IQ Calibration.\n", __func__);
3921    }
3922    if (AH_TRUE == ar9300_is_cal_supp(ah, chan, TEMP_COMP_CAL)) {
3923        INIT_CAL(&ahp->ah_temp_comp_cal_data);
3924        INSERT_CAL(ahp, &ahp->ah_temp_comp_cal_data);
3925        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3926            "%s: enabling Temperature Compensation Calibration.\n", __func__);
3927    }
3928
3929    /* Initialize current pointer to first element in list */
3930    ahp->ah_cal_list_curr = ahp->ah_cal_list;
3931
3932    /* Reset state within current cal */
3933    if (ahp->ah_cal_list_curr) {
3934        ar9300_reset_calibration(ah, ahp->ah_cal_list_curr);
3935    }
3936
3937    /* Mark all calibrations on this channel as being invalid */
3938    ichan->calValid = 0;
3939
3940    return AH_TRUE;
3941}
3942
3943static inline HAL_BOOL
3944ar9300_init_cal(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_BOOL skip_if_none, HAL_BOOL apply_last_iqcorr)
3945{
3946    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
3947    HAL_BOOL do_rtt_cal = AH_TRUE;
3948    HAL_BOOL enable_rtt = AH_FALSE;
3949
3950    HALASSERT(ichan);
3951
3952    return ar9300_init_cal_internal(ah, chan, ichan, enable_rtt, do_rtt_cal, skip_if_none, apply_last_iqcorr);
3953}
3954
3955/* ar9300_reset_cal_valid
3956 * Entry point for upper layers to restart current cal.
3957 * Reset the calibration valid bit in channel.
3958 */
3959void
3960ar9300_reset_cal_valid(struct ath_hal *ah, const struct ieee80211_channel *chan,
3961    HAL_BOOL *is_cal_done, u_int32_t cal_type)
3962{
3963    struct ath_hal_9300 *ahp = AH9300(ah);
3964    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
3965    HAL_CAL_LIST *curr_cal = ahp->ah_cal_list_curr;
3966
3967    *is_cal_done = AH_TRUE;
3968
3969    if (curr_cal == AH_NULL) {
3970        return;
3971    }
3972    if (ichan == AH_NULL) {
3973        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3974            "%s: invalid channel %u/0x%x; no mapping\n",
3975            __func__, chan->ic_freq, chan->ic_flags);
3976        return;
3977    }
3978
3979    if (!(cal_type & IQ_MISMATCH_CAL)) {
3980        *is_cal_done = AH_FALSE;
3981        return;
3982    }
3983
3984    /* Expected that this calibration has run before, post-reset.
3985     * Current state should be done
3986     */
3987    if (curr_cal->cal_state != CAL_DONE) {
3988        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3989            "%s: Calibration state incorrect, %d\n",
3990            __func__, curr_cal->cal_state);
3991        return;
3992    }
3993
3994    /* Verify Cal is supported on this channel */
3995    if (ar9300_is_cal_supp(ah, chan, curr_cal->cal_data->cal_type) == AH_FALSE) {
3996        return;
3997    }
3998
3999    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
4000        "%s: Resetting Cal %d state for channel %u/0x%x\n", __func__,
4001        curr_cal->cal_data->cal_type, chan->ic_freq, chan->ic_flags);
4002
4003    /* Disable cal validity in channel */
4004    ichan->calValid &= ~curr_cal->cal_data->cal_type;
4005    curr_cal->cal_state = CAL_WAITING;
4006    /* Indicate to upper layers that we need polling */
4007    *is_cal_done = AH_FALSE;
4008}
4009
4010static inline void
4011ar9300_set_dma(struct ath_hal *ah)
4012{
4013    u_int32_t   regval;
4014    struct ath_hal_9300 *ahp = AH9300(ah);
4015    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
4016    HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
4017
4018#if 0
4019    /*
4020     * set AHB_MODE not to do cacheline prefetches
4021     */
4022    regval = OS_REG_READ(ah, AR_AHB_MODE);
4023    OS_REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
4024#endif
4025
4026    /*
4027     * let mac dma reads be in 128 byte chunks
4028     */
4029    regval = OS_REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
4030    OS_REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
4031
4032    /*
4033     * Restore TX Trigger Level to its pre-reset value.
4034     * The initial value depends on whether aggregation is enabled, and is
4035     * adjusted whenever underruns are detected.
4036     */
4037    /*
4038    OS_REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, AH_PRIVATE(ah)->ah_tx_trig_level);
4039     */
4040    /*
4041     * Osprey 1.0 bug (EV 61936). Don't change trigger level from .ini default.
4042     * Osprey 2.0 - hardware recommends using the default INI settings.
4043     */
4044#if 0
4045    OS_REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, 0x3f);
4046#endif
4047    /*
4048     * let mac dma writes be in 128 byte chunks
4049     */
4050    regval = OS_REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
4051    OS_REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
4052
4053    /*
4054     * Setup receive FIFO threshold to hold off TX activities
4055     */
4056    OS_REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
4057
4058    /*
4059     * reduce the number of usable entries in PCU TXBUF to avoid
4060     * wrap around bugs. (bug 20428)
4061     */
4062
4063    if (AR_SREV_WASP(ah) &&
4064        (AH_PRIVATE((ah))->ah_macRev > AR_SREV_REVISION_WASP_12)) {
4065        /* Wasp 1.3 fix for EV#85395 requires usable entries
4066         * to be set to 0x500
4067         */
4068        OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, 0x500);
4069    } else {
4070        OS_REG_WRITE(ah, AR_PCU_TXBUF_CTRL, AR_PCU_TXBUF_CTRL_USABLE_SIZE);
4071    }
4072
4073    /*
4074     * Enable HPQ for UAPSD
4075     */
4076    if (pCap->halHwUapsdTrig == AH_TRUE) {
4077    /* Only enable this if HAL capabilities says it is OK */
4078        if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
4079            OS_REG_WRITE(ah, AR_HP_Q_CONTROL,
4080                    AR_HPQ_ENABLE | AR_HPQ_UAPSD | AR_HPQ_UAPSD_TRIGGER_EN);
4081        }
4082    } else {
4083        /* use default value from ini file - which disable HPQ queue usage */
4084    }
4085
4086    /*
4087     * set the transmit status ring
4088     */
4089    ar9300_reset_tx_status_ring(ah);
4090
4091    /*
4092     * set rxbp threshold.  Must be non-zero for RX_EOL to occur.
4093     * For Osprey 2.0+, keep the original thresholds
4094     * otherwise performance is lost due to excessive RX EOL interrupts.
4095     */
4096    OS_REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1);
4097    OS_REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1);
4098
4099    /*
4100     * set receive buffer size.
4101     */
4102    if (ahp->rx_buf_size) {
4103        OS_REG_WRITE(ah, AR_DATABUF, ahp->rx_buf_size);
4104    }
4105}
4106
4107static inline void
4108ar9300_init_bb(struct ath_hal *ah, struct ieee80211_channel *chan)
4109{
4110    u_int32_t synth_delay;
4111
4112    /*
4113     * Wait for the frequency synth to settle (synth goes on
4114     * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
4115     * Value is in 100ns increments.
4116     */
4117    synth_delay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
4118    if (IEEE80211_IS_CHAN_CCK(chan)) {
4119        synth_delay = (4 * synth_delay) / 22;
4120    } else {
4121        synth_delay /= 10;
4122    }
4123
4124    /* Activate the PHY (includes baseband activate + synthesizer on) */
4125    OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
4126
4127    /*
4128     * There is an issue if the AP starts the calibration before
4129     * the base band timeout completes.  This could result in the
4130     * rx_clear false triggering.  As a workaround we add delay an
4131     * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
4132     * does not happen.
4133     */
4134    OS_DELAY(synth_delay + BASE_ACTIVATE_DELAY);
4135}
4136
4137static inline void
4138ar9300_init_interrupt_masks(struct ath_hal *ah, HAL_OPMODE opmode)
4139{
4140    struct ath_hal_9300 *ahp = AH9300(ah);
4141    u_int32_t msi_cfg = 0;
4142    u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
4143
4144    /*
4145     * Setup interrupt handling.  Note that ar9300_reset_tx_queue
4146     * manipulates the secondary IMR's as queues are enabled
4147     * and disabled.  This is done with RMW ops to insure the
4148     * settings we make here are preserved.
4149     */
4150    ahp->ah_mask_reg =
4151        AR_IMR_TXERR | AR_IMR_TXURN |
4152        AR_IMR_RXERR | AR_IMR_RXORN |
4153        AR_IMR_BCNMISC;
4154
4155    if (ahp->ah_intr_mitigation_rx) {
4156        /* enable interrupt mitigation for rx */
4157        ahp->ah_mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR | AR_IMR_RXOK_HP;
4158        msi_cfg |= AR_INTCFG_MSI_RXINTM | AR_INTCFG_MSI_RXMINTR;
4159    } else {
4160        ahp->ah_mask_reg |= AR_IMR_RXOK_LP | AR_IMR_RXOK_HP;
4161        msi_cfg |= AR_INTCFG_MSI_RXOK;
4162    }
4163    if (ahp->ah_intr_mitigation_tx) {
4164        /* enable interrupt mitigation for tx */
4165        ahp->ah_mask_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR;
4166        msi_cfg |= AR_INTCFG_MSI_TXINTM | AR_INTCFG_MSI_TXMINTR;
4167    } else {
4168        ahp->ah_mask_reg |= AR_IMR_TXOK;
4169        msi_cfg |= AR_INTCFG_MSI_TXOK;
4170    }
4171    if (opmode == HAL_M_HOSTAP) {
4172        ahp->ah_mask_reg |= AR_IMR_MIB;
4173    }
4174
4175    OS_REG_WRITE(ah, AR_IMR, ahp->ah_mask_reg);
4176    OS_REG_WRITE(ah, AR_IMR_S2, OS_REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
4177    ahp->ah_mask2Reg = OS_REG_READ(ah, AR_IMR_S2);
4178
4179    if (ah->ah_config.ath_hal_enable_msi) {
4180        /* Cache MSI register value */
4181        ahp->ah_msi_reg = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI));
4182        ahp->ah_msi_reg |= AR_PCIE_MSI_HW_DBI_WR_EN;
4183        if (AR_SREV_POSEIDON(ah)) {
4184            ahp->ah_msi_reg &= AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
4185        } else {
4186            ahp->ah_msi_reg &= AR_PCIE_MSI_HW_INT_PENDING_ADDR;
4187        }
4188        /* Program MSI configuration */
4189        OS_REG_WRITE(ah, AR_INTCFG, msi_cfg);
4190    }
4191
4192    /*
4193     * debug - enable to see all synchronous interrupts status
4194     */
4195    /* Clear any pending sync cause interrupts */
4196    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE), 0xFFFFFFFF);
4197
4198    /* Allow host interface sync interrupt sources to set cause bit */
4199    if (AR_SREV_POSEIDON(ah)) {
4200        sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
4201    }
4202    else if (AR_SREV_WASP(ah)) {
4203        sync_en_def = AR9340_INTR_SYNC_DEFAULT;
4204    }
4205    OS_REG_WRITE(ah,
4206        AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), sync_en_def);
4207
4208    /* _Disable_ host interface sync interrupt when cause bits set */
4209    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK), 0);
4210
4211    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE), 0);
4212    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_MASK), 0);
4213    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_ENABLE), 0);
4214    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_SYNC_MASK), 0);
4215}
4216
4217static inline void
4218ar9300_init_qos(struct ath_hal *ah)
4219{
4220    OS_REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);  /* XXX magic */
4221    OS_REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);    /* XXX magic */
4222
4223    /* Turn on NOACK Support for QoS packets */
4224    OS_REG_WRITE(ah, AR_QOS_NO_ACK,
4225        SM(2, AR_QOS_NO_ACK_TWO_BIT) |
4226        SM(5, AR_QOS_NO_ACK_BIT_OFF) |
4227        SM(0, AR_QOS_NO_ACK_BYTE_OFF));
4228
4229    /*
4230     * initialize TXOP for all TIDs
4231     */
4232    OS_REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
4233    OS_REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
4234    OS_REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
4235    OS_REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
4236    OS_REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
4237}
4238
4239static inline void
4240ar9300_init_user_settings(struct ath_hal *ah)
4241{
4242    struct ath_hal_9300 *ahp = AH9300(ah);
4243
4244    /* Restore user-specified settings */
4245    HALDEBUG(ah, HAL_DEBUG_RESET,
4246        "--AP %s ahp->ah_misc_mode 0x%x\n", __func__, ahp->ah_misc_mode);
4247    if (ahp->ah_misc_mode != 0) {
4248        OS_REG_WRITE(ah,
4249            AR_PCU_MISC, OS_REG_READ(ah, AR_PCU_MISC) | ahp->ah_misc_mode);
4250    }
4251    if (ahp->ah_get_plcp_hdr) {
4252        OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);
4253    }
4254    if (ahp->ah_slot_time != (u_int) -1) {
4255        ar9300_set_slot_time(ah, ahp->ah_slot_time);
4256    }
4257    if (ahp->ah_ack_timeout != (u_int) -1) {
4258        ar9300_set_ack_timeout(ah, ahp->ah_ack_timeout);
4259    }
4260    if (AH_PRIVATE(ah)->ah_diagreg != 0) {
4261        OS_REG_SET_BIT(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
4262    }
4263    if (ahp->ah_beacon_rssi_threshold != 0) {
4264        ar9300_set_hw_beacon_rssi_threshold(ah, ahp->ah_beacon_rssi_threshold);
4265    }
4266#ifdef ATH_SUPPORT_DFS
4267    if (ahp->ah_cac_quiet_enabled) {
4268        ar9300_cac_tx_quiet(ah, 1);
4269    }
4270#endif /* ATH_SUPPORT_DFS */
4271}
4272
4273int
4274ar9300_get_spur_info(struct ath_hal * ah, int *enable, int len, u_int16_t *freq)
4275{
4276//    struct ath_hal_private *ap = AH_PRIVATE(ah);
4277    int i, j;
4278
4279    for (i = 0; i < len; i++) {
4280        freq[i] =  0;
4281    }
4282
4283    *enable = ah->ah_config.ath_hal_spur_mode;
4284    for (i = 0, j = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
4285        if (AH9300(ah)->ath_hal_spur_chans[i][0] != AR_NO_SPUR) {
4286            freq[j++] = AH9300(ah)->ath_hal_spur_chans[i][0];
4287            HALDEBUG(ah, HAL_DEBUG_ANI,
4288                "1. get spur %d\n", AH9300(ah)->ath_hal_spur_chans[i][0]);
4289        }
4290        if (AH9300(ah)->ath_hal_spur_chans[i][1] != AR_NO_SPUR) {
4291            freq[j++] = AH9300(ah)->ath_hal_spur_chans[i][1];
4292            HALDEBUG(ah, HAL_DEBUG_ANI,
4293                "2. get spur %d\n", AH9300(ah)->ath_hal_spur_chans[i][1]);
4294        }
4295    }
4296
4297    return 0;
4298}
4299
4300#define ATH_HAL_2GHZ_FREQ_MIN   20000
4301#define ATH_HAL_2GHZ_FREQ_MAX   29999
4302#define ATH_HAL_5GHZ_FREQ_MIN   50000
4303#define ATH_HAL_5GHZ_FREQ_MAX   59999
4304
4305#if 0
4306int
4307ar9300_set_spur_info(struct ath_hal * ah, int enable, int len, u_int16_t *freq)
4308{
4309    struct ath_hal_private *ap = AH_PRIVATE(ah);
4310    int i, j, k;
4311
4312    ap->ah_config.ath_hal_spur_mode = enable;
4313
4314    if (ap->ah_config.ath_hal_spur_mode == SPUR_ENABLE_IOCTL) {
4315        for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
4316            AH9300(ah)->ath_hal_spur_chans[i][0] = AR_NO_SPUR;
4317            AH9300(ah)->ath_hal_spur_chans[i][1] = AR_NO_SPUR;
4318        }
4319        for (i = 0, j = 0, k = 0; i < len; i++) {
4320            if (freq[i] > ATH_HAL_2GHZ_FREQ_MIN &&
4321                freq[i] < ATH_HAL_2GHZ_FREQ_MAX)
4322            {
4323                /* 2GHz Spur */
4324                if (j < AR_EEPROM_MODAL_SPURS) {
4325                    AH9300(ah)->ath_hal_spur_chans[j++][1] =  freq[i];
4326                    HALDEBUG(ah, HAL_DEBUG_ANI, "1 set spur %d\n", freq[i]);
4327                }
4328            } else if (freq[i] > ATH_HAL_5GHZ_FREQ_MIN &&
4329                       freq[i] < ATH_HAL_5GHZ_FREQ_MAX)
4330            {
4331                /* 5Ghz Spur */
4332                if (k < AR_EEPROM_MODAL_SPURS) {
4333                    AH9300(ah)->ath_hal_spur_chans[k++][0] =  freq[i];
4334                    HALDEBUG(ah, HAL_DEBUG_ANI, "2 set spur %d\n", freq[i]);
4335                }
4336            }
4337        }
4338    }
4339
4340    return 0;
4341}
4342#endif
4343
4344#define ar9300_check_op_mode(_opmode) \
4345    ((_opmode == HAL_M_STA) || (_opmode == HAL_M_IBSS) ||\
4346     (_opmode == HAL_M_HOSTAP) || (_opmode == HAL_M_MONITOR))
4347
4348
4349
4350
4351#ifndef ATH_NF_PER_CHAN
4352/*
4353* To fixed first reset noise floor value not correct issue
4354* For ART need it to fixed low rate sens too low issue
4355*/
4356static int
4357First_NFCal(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan,
4358    int is_scan, struct ieee80211_channel *chan)
4359{
4360    HAL_NFCAL_HIST_FULL *nfh;
4361    int i, j, k;
4362    int16_t nfarray[HAL_NUM_NF_READINGS] = {0};
4363    int is_2g = 0;
4364    int nf_hist_len;
4365    int stats = 0;
4366
4367    int16_t nf_buf[HAL_NUM_NF_READINGS];
4368#define IS(_c, _f)       (((_c)->channel_flags & _f) || 0)
4369
4370
4371    if ((!is_scan) &&
4372        chan->ic_freq == AH_PRIVATE(ah)->ah_curchan->ic_freq)
4373    {
4374        nfh = &AH_PRIVATE(ah)->nf_cal_hist;
4375    } else {
4376        nfh = (HAL_NFCAL_HIST_FULL *) &ichan->nf_cal_hist;
4377    }
4378
4379    ar9300_start_nf_cal(ah);
4380    for (j = 0; j < 10000; j++) {
4381        if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0){
4382            break;
4383		}
4384        OS_DELAY(10);
4385    }
4386	if (j < 10000) {
4387        is_2g = IEEE80211_IS_CHAN_2GHZ(chan);
4388        ar9300_upload_noise_floor(ah, is_2g, nfarray);
4389
4390	    if (is_scan) {
4391			/*
4392			 * This channel's NF cal info is just a HAL_NFCAL_HIST_SMALL struct
4393			 * rather than a HAL_NFCAL_HIST_FULL struct.
4394			 * As long as we only use the first history element of nf_cal_buffer
4395			 * (nf_cal_buffer[0][0:HAL_NUM_NF_READINGS-1]), we can use
4396			 * HAL_NFCAL_HIST_SMALL and HAL_NFCAL_HIST_FULL interchangeably.
4397			 */
4398            nfh = (HAL_NFCAL_HIST_FULL *) &ichan->nf_cal_hist;
4399            nf_hist_len = HAL_NF_CAL_HIST_LEN_SMALL;
4400		} else {
4401            nfh = &AH_PRIVATE(ah)->nf_cal_hist;
4402            nf_hist_len = HAL_NF_CAL_HIST_LEN_FULL;
4403		}
4404
4405  	    for (i = 0; i < HAL_NUM_NF_READINGS; i ++) {
4406    		for (k = 0; k < HAL_NF_CAL_HIST_LEN_FULL; k++) {
4407                nfh->nf_cal_buffer[k][i] = nfarray[i];
4408            }
4409            nfh->base.priv_nf[i] = ar9300_limit_nf_range(ah,
4410							ar9300_get_nf_hist_mid(ah, nfh, i, nf_hist_len));
4411  		}
4412
4413
4414		//ar9300StoreNewNf(ah, ichan, is_scan);
4415
4416		/*
4417		 * See if the NF value from the old channel should be
4418		 * retained when switching to a new channel.
4419		 * TBD: this may need to be changed, as it wipes out the
4420		 * purpose of saving NF values for each channel.
4421		 */
4422		for (i = 0; i < HAL_NUM_NF_READINGS; i++)
4423		{
4424    		if (IEEE80211_IS_CHAN_2GHZ(chan))
4425    		{
4426    			if (nfh->nf_cal_buffer[0][i] <
4427					AR_PHY_CCA_MAX_GOOD_VAL_OSPREY_2GHZ)
4428                {
4429                    ichan->nf_cal_hist.nf_cal_buffer[0][i] =
4430							AH_PRIVATE(ah)->nf_cal_hist.nf_cal_buffer[0][i];
4431				}
4432    		} else {
4433                if (AR_SREV_AR9580(ah)) {
4434                    if (nfh->nf_cal_buffer[0][i] <
4435                        AR_PHY_CCA_NOM_VAL_PEACOCK_5GHZ)
4436                    {
4437                       ichan->nf_cal_hist.nf_cal_buffer[0][i] =
4438                       AH_PRIVATE(ah)->nf_cal_hist.nf_cal_buffer[0][i];
4439                    }
4440                } else {
4441                   if (nfh->nf_cal_buffer[0][i] <
4442                       AR_PHY_CCA_NOM_VAL_OSPREY_5GHZ)
4443                    {
4444                        ichan->nf_cal_hist.nf_cal_buffer[0][i] =
4445                            AH_PRIVATE(ah)->nf_cal_hist.nf_cal_buffer[0][i];
4446                     }
4447                }
4448            }
4449        }
4450		/*
4451		 * Copy the channel's NF buffer, which may have been modified
4452		 * just above here, to the full NF history buffer.
4453		 */
4454        ar9300_reset_nf_hist_buff(ah, ichan);
4455        ar9300_get_nf_hist_base(ah, ichan, is_scan, nf_buf);
4456        ar9300_load_nf(ah, nf_buf);
4457        stats = 0;
4458	} else {
4459        stats = 1;
4460	}
4461#undef IS
4462    return stats;
4463}
4464#endif
4465
4466
4467/*
4468 * Places the device in and out of reset and then places sane
4469 * values in the registers based on EEPROM config, initialization
4470 * vectors (as determined by the mode), and station configuration
4471 *
4472 * b_channel_change is used to preserve DMA/PCU registers across
4473 * a HW Reset during channel change.
4474 */
4475HAL_BOOL
4476ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan,
4477    HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask,
4478    HAL_HT_EXTPROTSPACING extprotspacing, HAL_BOOL b_channel_change,
4479    HAL_STATUS *status, int is_scan)
4480{
4481#define FAIL(_code)     do { ecode = _code; goto bad; } while (0)
4482    u_int32_t               save_led_state;
4483    struct ath_hal_9300     *ahp = AH9300(ah);
4484    struct ath_hal_private  *ap  = AH_PRIVATE(ah);
4485    HAL_CHANNEL_INTERNAL    *ichan;
4486    //const struct ieee80211_channel *curchan = ap->ah_curchan;
4487#if ATH_SUPPORT_MCI
4488    HAL_BOOL                    save_full_sleep = ahp->ah_chip_full_sleep;
4489#endif
4490    u_int32_t               save_def_antenna;
4491    u_int32_t               mac_sta_id1;
4492    HAL_STATUS              ecode;
4493    int                     i, rx_chainmask;
4494    int                     nf_hist_buff_reset = 0;
4495    int16_t                 nf_buf[HAL_NUM_NF_READINGS];
4496#ifdef ATH_FORCE_PPM
4497    u_int32_t               save_force_val, tmp_reg;
4498#endif
4499    u_int8_t                clk_25mhz = AH9300(ah)->clk_25mhz;
4500    HAL_BOOL                    stopped, cal_ret;
4501    HAL_BOOL                    apply_last_iqcorr = AH_FALSE;
4502
4503
4504    if (OS_REG_READ(ah, AR_IER) == AR_IER_ENABLE) {
4505        HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "** Reset called with WLAN "
4506                "interrupt enabled %08x **\n", ar9300_get_interrupts(ah));
4507    }
4508
4509    /*
4510     * Set the status to "ok" by default to cover the cases
4511     * where we return false without going to "bad"
4512     */
4513    HALASSERT(status);
4514    *status = HAL_OK;
4515    if ((ah->ah_config.ath_hal_sta_update_tx_pwr_enable)) {
4516        AH9300(ah)->green_tx_status = HAL_RSSI_TX_POWER_NONE;
4517    }
4518
4519#if ATH_SUPPORT_MCI
4520    if (AH_PRIVATE(ah)->ah_caps.halMciSupport &&
4521        (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)))
4522    {
4523        ar9300_mci_2g5g_changed(ah, IEEE80211_IS_CHAN_2GHZ(chan));
4524    }
4525#endif
4526
4527    ahp->ah_ext_prot_spacing = extprotspacing;
4528    ahp->ah_tx_chainmask = txchainmask & ap->ah_caps.halTxChainMask;
4529    ahp->ah_rx_chainmask = rxchainmask & ap->ah_caps.halRxChainMask;
4530    ahp->ah_tx_cal_chainmask = ap->ah_caps.halTxChainMask;
4531    ahp->ah_rx_cal_chainmask = ap->ah_caps.halRxChainMask;
4532
4533    /*
4534     * Keep the previous optinal txchainmask value
4535     */
4536
4537    HALASSERT(ar9300_check_op_mode(opmode));
4538
4539    OS_MARK(ah, AH_MARK_RESET, b_channel_change);
4540
4541    /*
4542     * Map public channel to private.
4543     */
4544    ichan = ar9300_check_chan(ah, chan);
4545    if (ichan == AH_NULL) {
4546        HALDEBUG(ah, HAL_DEBUG_CHANNEL,
4547            "%s: invalid channel %u/0x%x; no mapping\n",
4548            __func__, chan->ic_freq, chan->ic_flags);
4549        FAIL(HAL_EINVAL);
4550    }
4551
4552    ichan->paprd_table_write_done = 0;  /* Clear PAPRD table write flag */
4553#if 0
4554    chan->paprd_table_write_done = 0;  /* Clear PAPRD table write flag */
4555#endif
4556
4557    if (ar9300_get_power_mode(ah) != HAL_PM_FULL_SLEEP) {
4558        /* Need to stop RX DMA before reset otherwise chip might hang */
4559        stopped = ar9300_set_rx_abort(ah, AH_TRUE); /* abort and disable PCU */
4560        ar9300_set_rx_filter(ah, 0);
4561        stopped &= ar9300_stop_dma_receive(ah, 0); /* stop and disable RX DMA */
4562        if (!stopped) {
4563            /*
4564             * During the transition from full sleep to reset,
4565             * recv DMA regs are not available to be read
4566             */
4567            HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
4568                "%s[%d]: ar9300_stop_dma_receive failed\n", __func__, __LINE__);
4569            b_channel_change = AH_FALSE;
4570        }
4571    } else {
4572        HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
4573            "%s[%d]: Chip is already in full sleep\n", __func__, __LINE__);
4574    }
4575
4576#if ATH_SUPPORT_MCI
4577    if ((AH_PRIVATE(ah)->ah_caps.halMciSupport) &&
4578        (ahp->ah_mci_bt_state == MCI_BT_CAL_START))
4579    {
4580        u_int32_t payload[4] = {0, 0, 0, 0};
4581
4582        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
4583            "(MCI) %s: Stop rx for BT cal.\n", __func__);
4584        ahp->ah_mci_bt_state = MCI_BT_CAL;
4585
4586        /*
4587         * MCIFIX: disable mci interrupt here. This is to avoid SW_MSG_DONE or
4588         * RX_MSG bits to trigger MCI_INT and lead to mci_intr reentry.
4589         */
4590        ar9300_mci_disable_interrupt(ah);
4591
4592        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
4593            "(MCI) %s: Send WLAN_CAL_GRANT\n", __func__);
4594        MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
4595        ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, AH_TRUE, AH_FALSE);
4596
4597        /* Wait BT calibration to be completed for 25ms */
4598        HALDEBUG(ah, HAL_DEBUG_BT_COEX,
4599            "(MCI) %s: BT is calibrating.\n", __func__);
4600        if (ar9300_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE, 0, 25000)) {
4601            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
4602                "(MCI) %s: Got BT_CAL_DONE.\n", __func__);
4603        }
4604        else {
4605            HALDEBUG(ah, HAL_DEBUG_BT_COEX,
4606                "(MCI) %s: ### BT cal takes too long. Force bt_state to be bt_awake.\n",
4607                __func__);
4608        }
4609        ahp->ah_mci_bt_state = MCI_BT_AWAKE;
4610        /* MCIFIX: enable mci interrupt here */
4611        ar9300_mci_enable_interrupt(ah);
4612
4613        return AH_TRUE;
4614    }
4615#endif
4616
4617    /* Bring out of sleep mode */
4618    if (!ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE)) {
4619        *status = HAL_INV_PMODE;
4620        return AH_FALSE;
4621    }
4622
4623    /* Check the Rx mitigation config again, it might have changed
4624     * during attach in ath_vap_attach.
4625     */
4626    if (ah->ah_config.ath_hal_intr_mitigation_rx != 0) {
4627        ahp->ah_intr_mitigation_rx = AH_TRUE;
4628    } else {
4629        ahp->ah_intr_mitigation_rx = AH_FALSE;
4630    }
4631
4632    /*
4633     * XXX TODO FreeBSD:
4634     *
4635     * This is painful because we don't have a non-const channel pointer
4636     * at this stage.
4637     *
4638     * Make sure this gets fixed!
4639     */
4640#if 0
4641    /* Get the value from the previous NF cal and update history buffer */
4642    if (curchan && (ahp->ah_chip_full_sleep != AH_TRUE)) {
4643
4644        if(ahp->ah_chip_reset_done){
4645            ahp->ah_chip_reset_done = 0;
4646        } else {
4647        	/*
4648         	 * is_scan controls updating NF for home channel or off channel.
4649         	 * Home -> Off, update home channel
4650         	 * Off -> Home, update off channel
4651         	 * Home -> Home, uppdate home channel
4652         	 */
4653        	if (ap->ah_curchan->channel != chan->channel)
4654            	ar9300_store_new_nf(ah, curchan, !is_scan);
4655        	else
4656            	ar9300_store_new_nf(ah, curchan, is_scan);
4657        }
4658    }
4659#endif
4660
4661    /*
4662     * Account for the effect of being in either the 2 GHz or 5 GHz band
4663     * on the nominal, max allowable, and min allowable noise floor values.
4664     */
4665    AH9300(ah)->nfp = IS_CHAN_2GHZ(ichan) ? &ahp->nf_2GHz : &ahp->nf_5GHz;
4666
4667    /*
4668     * XXX FreeBSD For now, don't apply the last IQ correction.
4669     *
4670     * This should be done when scorpion is enabled on FreeBSD; just be
4671     * sure to fix this channel match code so it uses net80211 flags
4672     * instead.
4673     */
4674#if 0
4675    if (AR_SREV_SCORPION(ah) && curchan && (chan->channel == curchan->channel) &&
4676        ((chan->channel_flags & (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)) ==
4677         (curchan->channel_flags &
4678          (CHANNEL_ALL | CHANNEL_HALF | CHANNEL_QUARTER)))) {
4679            apply_last_iqcorr = AH_TRUE;
4680    }
4681#endif
4682    apply_last_iqcorr = AH_FALSE;
4683
4684
4685#ifndef ATH_NF_PER_CHAN
4686    /*
4687     * If there's only one full-size home-channel NF history buffer
4688     * rather than a full-size NF history buffer per channel, decide
4689     * whether to (re)initialize the home-channel NF buffer.
4690     * If this is just a channel change for a scan, or if the channel
4691     * is not being changed, don't mess up the home channel NF history
4692     * buffer with NF values from this scanned channel.  If we're
4693     * changing the home channel to a new channel, reset the home-channel
4694     * NF history buffer with the most accurate NF known for the new channel.
4695     */
4696    if (!is_scan && (!ap->ah_curchan ||
4697        ap->ah_curchan->ic_freq != chan->ic_freq)) // ||
4698//        ap->ah_curchan->channel_flags != chan->channel_flags))
4699    {
4700        nf_hist_buff_reset = 1;
4701        ar9300_reset_nf_hist_buff(ah, ichan);
4702    }
4703#endif
4704    /*
4705     * In case of
4706     * - offchan scan, or
4707     * - same channel and RX IQ Cal already available
4708     * disable RX IQ Cal.
4709     */
4710    if (is_scan) {
4711        ahp->ah_skip_rx_iq_cal = AH_TRUE;
4712        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
4713                "Skip RX IQ Cal due to scanning\n");
4714    } else {
4715#if 0
4716        /* XXX FreeBSD: always just do the RX IQ cal */
4717	/* XXX I think it's just going to speed things up; I don't think it's to avoid chan bugs */
4718        if (ahp->ah_rx_cal_complete &&
4719            ahp->ah_rx_cal_chan == ichan->channel &&
4720            ahp->ah_rx_cal_chan_flag == chan->channel_flags) {
4721            ahp->ah_skip_rx_iq_cal = AH_TRUE;
4722            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
4723                    "Skip RX IQ Cal due to same channel with completed RX IQ Cal\n");
4724        } else
4725#endif
4726            ahp->ah_skip_rx_iq_cal = AH_FALSE;
4727    }
4728
4729    /* FreeBSD: clear the channel survey data */
4730    ath_hal_survey_clear(ah);
4731
4732    /*
4733     * Fast channel change (Change synthesizer based on channel freq
4734     * without resetting chip)
4735     * Don't do it when
4736     *   - Flag is not set
4737     *   - Chip is just coming out of full sleep
4738     *   - Channel to be set is same as current channel
4739     *   - Channel flags are different, like when moving from 2GHz to 5GHz
4740     *     channels
4741     *   - Merlin: Switching in/out of fast clock enabled channels
4742     *             (not currently coded, since fast clock is enabled
4743     *             across the 5GHz band
4744     *             and we already do a full reset when switching in/out
4745     *             of 5GHz channels)
4746     */
4747#if 0
4748    if (b_channel_change &&
4749        (ahp->ah_chip_full_sleep != AH_TRUE) &&
4750        (AH_PRIVATE(ah)->ah_curchan != AH_NULL) &&
4751        ((chan->channel != AH_PRIVATE(ah)->ah_curchan->channel) &&
4752        (((CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER) & chan->channel_flags) ==
4753        ((CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER) & AH_PRIVATE(ah)->ah_curchan->channel_flags))))
4754    {
4755        if (ar9300_channel_change(ah, chan, ichan, macmode)) {
4756            chan->channel_flags = ichan->channel_flags;
4757            chan->priv_flags = ichan->priv_flags;
4758            AH_PRIVATE(ah)->ah_curchan->ah_channel_time = 0;
4759            AH_PRIVATE(ah)->ah_curchan->ah_tsf_last = ar9300_get_tsf64(ah);
4760
4761            /*
4762             * Load the NF from history buffer of the current channel.
4763             * NF is slow time-variant, so it is OK to use a historical value.
4764             */
4765            ar9300_get_nf_hist_base(ah,
4766                AH_PRIVATE(ah)->ah_curchan, is_scan, nf_buf);
4767            ar9300_load_nf(ah, nf_buf);
4768
4769            /* start NF calibration, without updating BB NF register*/
4770            ar9300_start_nf_cal(ah);
4771
4772            /*
4773             * If channel_change completed and DMA was stopped
4774             * successfully - skip the rest of reset
4775             */
4776            if (AH9300(ah)->ah_dma_stuck != AH_TRUE) {
4777                WAR_USB_DISABLE_PLL_LOCK_DETECT(ah);
4778#if ATH_SUPPORT_MCI
4779                if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready)
4780                {
4781                    ar9300_mci_2g5g_switch(ah, AH_TRUE);
4782                }
4783#endif
4784                return HAL_OK;
4785            }
4786         }
4787    }
4788#endif /* #if 0 */
4789
4790#if ATH_SUPPORT_MCI
4791    if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
4792        ar9300_mci_disable_interrupt(ah);
4793        if (ahp->ah_mci_ready && !save_full_sleep) {
4794            ar9300_mci_mute_bt(ah);
4795            OS_DELAY(20);
4796            OS_REG_WRITE(ah, AR_BTCOEX_CTRL, 0);
4797        }
4798
4799        ahp->ah_mci_bt_state = MCI_BT_SLEEP;
4800        ahp->ah_mci_ready = AH_FALSE;
4801    }
4802#endif
4803
4804    AH9300(ah)->ah_dma_stuck = AH_FALSE;
4805#ifdef ATH_FORCE_PPM
4806    /* Preserve force ppm state */
4807    save_force_val =
4808        OS_REG_READ(ah, AR_PHY_TIMING2) &
4809        (AR_PHY_TIMING2_USE_FORCE | AR_PHY_TIMING2_FORCE_VAL);
4810#endif
4811    /*
4812     * Preserve the antenna on a channel change
4813     */
4814    save_def_antenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
4815    if (0 == ahp->ah_smartantenna_enable )
4816    {
4817        if (save_def_antenna == 0) {
4818            save_def_antenna = 1;
4819        }
4820    }
4821
4822    /* Save hardware flag before chip reset clears the register */
4823    mac_sta_id1 = OS_REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
4824
4825    /* Save led state from pci config register */
4826    save_led_state = OS_REG_READ(ah, AR_CFG_LED) &
4827        (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
4828        AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
4829
4830    /* Mark PHY inactive prior to reset, to be undone in ar9300_init_bb () */
4831    ar9300_mark_phy_inactive(ah);
4832
4833    if (!ar9300_chip_reset(ah, chan)) {
4834        HALDEBUG(ah, HAL_DEBUG_RESET, "%s: chip reset failed\n", __func__);
4835        FAIL(HAL_EIO);
4836    }
4837
4838    OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
4839
4840
4841    /* Disable JTAG */
4842    OS_REG_SET_BIT(ah,
4843        AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
4844
4845    /*
4846     * Note that ar9300_init_chain_masks() is called from within
4847     * ar9300_process_ini() to ensure the swap bit is set before
4848     * the pdadc table is written.
4849     */
4850    ecode = ar9300_process_ini(ah, chan, ichan, macmode);
4851    if (ecode != HAL_OK) {
4852        goto bad;
4853    }
4854
4855    /*
4856     * Configuring WMAC PLL values for 25/40 MHz
4857     */
4858    if(AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah) || AR_SREV_SCORPION(ah) ) {
4859        if(clk_25mhz) {
4860            OS_REG_WRITE(ah, AR_RTC_DERIVED_RTC_CLK, (0x17c << 1)); // 32KHz sleep clk
4861        } else {
4862            OS_REG_WRITE(ah, AR_RTC_DERIVED_RTC_CLK, (0x261 << 1)); // 32KHz sleep clk
4863        }
4864        OS_DELAY(100);
4865    }
4866
4867    ahp->ah_immunity_on = AH_FALSE;
4868
4869    if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
4870        ahp->tx_iq_cal_enable = OS_REG_READ_FIELD(ah,
4871                                AR_PHY_TX_IQCAL_CONTROL_0(ah),
4872                                AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL) ?
4873                                1 : 0;
4874    }
4875    ahp->tx_cl_cal_enable = (OS_REG_READ(ah, AR_PHY_CL_CAL_CTL) &
4876                                AR_PHY_CL_CAL_ENABLE) ? 1 : 0;
4877
4878    /* For devices with full HW RIFS Rx support (Sowl/Howl/Merlin, etc),
4879     * restore register settings from prior to reset.
4880     */
4881    if ((AH_PRIVATE(ah)->ah_curchan != AH_NULL) &&
4882        (ar9300_get_capability(ah, HAL_CAP_LDPCWAR, 0, AH_NULL) == HAL_OK))
4883    {
4884        /* Re-program RIFS Rx policy after reset */
4885        ar9300_set_rifs_delay(ah, ahp->ah_rifs_enabled);
4886    }
4887
4888#if ATH_SUPPORT_MCI
4889    if (AH_PRIVATE(ah)->ah_caps.halMciSupport) {
4890        ar9300_mci_reset(ah, AH_FALSE, IS_CHAN_2GHZ(ichan), save_full_sleep);
4891    }
4892#endif
4893
4894    /* Initialize Management Frame Protection */
4895    ar9300_init_mfp(ah);
4896
4897    ahp->ah_immunity_vals[0] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR_LOW,
4898        AR_PHY_SFCORR_LOW_M1_THRESH_LOW);
4899    ahp->ah_immunity_vals[1] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR_LOW,
4900        AR_PHY_SFCORR_LOW_M2_THRESH_LOW);
4901    ahp->ah_immunity_vals[2] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR,
4902        AR_PHY_SFCORR_M1_THRESH);
4903    ahp->ah_immunity_vals[3] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR,
4904        AR_PHY_SFCORR_M2_THRESH);
4905    ahp->ah_immunity_vals[4] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR,
4906        AR_PHY_SFCORR_M2COUNT_THR);
4907    ahp->ah_immunity_vals[5] = OS_REG_READ_FIELD(ah, AR_PHY_SFCORR_LOW,
4908        AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);
4909
4910    /* Write delta slope for OFDM enabled modes (A, G, Turbo) */
4911    if (IEEE80211_IS_CHAN_OFDM(chan) || IEEE80211_IS_CHAN_HT(chan)) {
4912        ar9300_set_delta_slope(ah, chan);
4913    }
4914
4915    ar9300_spur_mitigate(ah, chan);
4916    if (!ar9300_eeprom_set_board_values(ah, chan)) {
4917        HALDEBUG(ah, HAL_DEBUG_EEPROM,
4918            "%s: error setting board options\n", __func__);
4919        FAIL(HAL_EIO);
4920    }
4921
4922#ifdef ATH_HAL_WAR_REG16284_APH128
4923    /* temp work around, will be removed. */
4924    if (AR_SREV_WASP(ah)) {
4925        OS_REG_WRITE(ah, 0x16284, 0x1553e000);
4926    }
4927#endif
4928
4929    OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
4930
4931    OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
4932    OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
4933            | mac_sta_id1
4934            | AR_STA_ID1_RTS_USE_DEF
4935            | (ah->ah_config.ath_hal_6mb_ack ? AR_STA_ID1_ACKCTS_6MB : 0)
4936            | ahp->ah_sta_id1_defaults
4937    );
4938    ar9300_set_operating_mode(ah, opmode);
4939
4940    /* Set Venice BSSID mask according to current state */
4941    OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssid_mask));
4942    OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssid_mask + 4));
4943
4944    /* Restore previous antenna */
4945    OS_REG_WRITE(ah, AR_DEF_ANTENNA, save_def_antenna);
4946#ifdef ATH_FORCE_PPM
4947    /* Restore force ppm state */
4948    tmp_reg = OS_REG_READ(ah, AR_PHY_TIMING2) &
4949        ~(AR_PHY_TIMING2_USE_FORCE | AR_PHY_TIMING2_FORCE_VAL);
4950    OS_REG_WRITE(ah, AR_PHY_TIMING2, tmp_reg | save_force_val);
4951#endif
4952
4953    /* then our BSSID and assocID */
4954    OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
4955    OS_REG_WRITE(ah, AR_BSS_ID1,
4956        LE_READ_2(ahp->ah_bssid + 4) |
4957        ((ahp->ah_assoc_id & 0x3fff) << AR_BSS_ID1_AID_S));
4958
4959    OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */
4960
4961    OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, INIT_RSSI_THR);
4962
4963    /* HW beacon processing */
4964    /*
4965     * XXX what happens if I just leave filter_interval=0?
4966     * it stays disabled?
4967     */
4968    OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_BCN_WEIGHT,
4969            INIT_RSSI_BEACON_WEIGHT);
4970    OS_REG_SET_BIT(ah, AR_HWBCNPROC1, AR_HWBCNPROC1_CRC_ENABLE |
4971            AR_HWBCNPROC1_EXCLUDE_TIM_ELM);
4972    if (ah->ah_config.ath_hal_beacon_filter_interval) {
4973        OS_REG_RMW_FIELD(ah, AR_HWBCNPROC2, AR_HWBCNPROC2_FILTER_INTERVAL,
4974                ah->ah_config.ath_hal_beacon_filter_interval);
4975        OS_REG_SET_BIT(ah, AR_HWBCNPROC2,
4976                AR_HWBCNPROC2_FILTER_INTERVAL_ENABLE);
4977    }
4978
4979
4980    /*
4981     * Set Channel now modifies bank 6 parameters for FOWL workaround
4982     * to force rf_pwd_icsyndiv bias current as function of synth
4983     * frequency.Thus must be called after ar9300_process_ini() to ensure
4984     * analog register cache is valid.
4985     */
4986    if (!ahp->ah_rf_hal.set_channel(ah, chan)) {
4987        FAIL(HAL_EIO);
4988    }
4989
4990
4991    OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
4992
4993    /* Set 1:1 QCU to DCU mapping for all queues */
4994    for (i = 0; i < AR_NUM_DCU; i++) {
4995        OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
4996    }
4997
4998    ahp->ah_intr_txqs = 0;
4999    for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) {
5000        ar9300_reset_tx_queue(ah, i);
5001    }
5002
5003    ar9300_init_interrupt_masks(ah, opmode);
5004
5005    /* Reset ier reference count to disabled */
5006//    OS_ATOMIC_SET(&ahp->ah_ier_ref_count, 1);
5007    if (ath_hal_isrfkillenabled(ah)) {
5008        ar9300_enable_rf_kill(ah);
5009    }
5010
5011    /* must be called AFTER ini is processed */
5012    ar9300_ani_init_defaults(ah, macmode);
5013
5014    ar9300_init_qos(ah);
5015
5016    ar9300_init_user_settings(ah);
5017
5018
5019    AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */
5020
5021    OS_MARK(ah, AH_MARK_RESET_DONE, 0);
5022
5023    /*
5024     * disable seq number generation in hw
5025     */
5026    OS_REG_WRITE(ah, AR_STA_ID1,
5027        OS_REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
5028
5029    ar9300_set_dma(ah);
5030
5031    /*
5032     * program OBS bus to see MAC interrupts
5033     */
5034#if ATH_SUPPORT_MCI
5035    if (!AH_PRIVATE(ah)->ah_caps.halMciSupport) {
5036        OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_OBS), 8);
5037    }
5038#else
5039    OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_OBS), 8);
5040#endif
5041
5042
5043    /* enabling AR_GTTM_IGNORE_IDLE in GTTM register so that
5044       GTT timer will not increment if the channel idle indicates
5045       the air is busy or NAV is still counting down */
5046    OS_REG_WRITE(ah, AR_GTTM, AR_GTTM_IGNORE_IDLE);
5047
5048    /*
5049     * GTT debug mode setting
5050     */
5051    /*
5052    OS_REG_WRITE(ah, 0x64, 0x00320000);
5053    OS_REG_WRITE(ah, 0x68, 7);
5054    OS_REG_WRITE(ah, 0x4080, 0xC);
5055     */
5056    /*
5057     * Disable general interrupt mitigation by setting MIRT = 0x0
5058     * Rx and tx interrupt mitigation are conditionally enabled below.
5059     */
5060    OS_REG_WRITE(ah, AR_MIRT, 0);
5061    if (ahp->ah_intr_mitigation_rx) {
5062        /*
5063         * Enable Interrupt Mitigation for Rx.
5064         * If no build-specific limits for the rx interrupt mitigation
5065         * timer have been specified, use conservative defaults.
5066         */
5067        #ifndef AH_RIMT_VAL_LAST
5068            #define AH_RIMT_LAST_MICROSEC 500
5069        #endif
5070        #ifndef AH_RIMT_VAL_FIRST
5071            #define AH_RIMT_FIRST_MICROSEC 2000
5072        #endif
5073#ifndef HOST_OFFLOAD
5074        OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, AH_RIMT_LAST_MICROSEC);
5075        OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, AH_RIMT_FIRST_MICROSEC);
5076#else
5077        /* lower mitigation level to reduce latency for offload arch. */
5078        OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST,
5079            (AH_RIMT_LAST_MICROSEC >> 2));
5080        OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST,
5081            (AH_RIMT_FIRST_MICROSEC >> 2));
5082#endif
5083    }
5084
5085    if (ahp->ah_intr_mitigation_tx) {
5086        /*
5087         * Enable Interrupt Mitigation for Tx.
5088         * If no build-specific limits for the tx interrupt mitigation
5089         * timer have been specified, use the values preferred for
5090         * the carrier group's products.
5091         */
5092        #ifndef AH_TIMT_LAST
5093            #define AH_TIMT_LAST_MICROSEC 300
5094        #endif
5095        #ifndef AH_TIMT_FIRST
5096            #define AH_TIMT_FIRST_MICROSEC 750
5097        #endif
5098        OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, AH_TIMT_LAST_MICROSEC);
5099        OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, AH_TIMT_FIRST_MICROSEC);
5100    }
5101
5102    rx_chainmask = ahp->ah_rx_chainmask;
5103
5104    OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
5105    OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
5106
5107    ar9300_init_bb(ah, chan);
5108
5109    /* BB Step 7: Calibration */
5110    /*
5111     * Only kick off calibration not on offchan.
5112     * If coming back from offchan, restore prevous Cal results
5113     * since chip reset will clear existings.
5114     */
5115    if (!ahp->ah_skip_rx_iq_cal) {
5116        int i;
5117        /* clear existing RX cal data */
5118        for (i=0; i<AR9300_MAX_CHAINS; i++)
5119            ahp->ah_rx_cal_corr[i] = 0;
5120
5121        ahp->ah_rx_cal_complete = AH_FALSE;
5122//        ahp->ah_rx_cal_chan = chan->channel;
5123//        ahp->ah_rx_cal_chan_flag = ichan->channel_flags;
5124        ahp->ah_rx_cal_chan = 0;
5125        ahp->ah_rx_cal_chan_flag = 0; /* XXX FreeBSD */
5126    }
5127    ar9300_invalidate_saved_cals(ah, ichan);
5128    cal_ret = ar9300_init_cal(ah, chan, AH_FALSE, apply_last_iqcorr);
5129
5130#if ATH_SUPPORT_MCI
5131    if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) {
5132        if (IS_CHAN_2GHZ(ichan) &&
5133            (ahp->ah_mci_bt_state == MCI_BT_SLEEP))
5134        {
5135            if (ar9300_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) ||
5136                ar9300_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE))
5137            {
5138                /*
5139                 * BT is sleeping. Check if BT wakes up duing WLAN
5140                 * calibration. If BT wakes up during WLAN calibration, need
5141                 * to go through all message exchanges again and recal.
5142                 */
5143                HALDEBUG(ah, HAL_DEBUG_BT_COEX,
5144                    "(MCI) ### %s: BT wakes up during WLAN calibration.\n",
5145                    __func__);
5146                OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
5147                        AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |
5148                        AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE);
5149                HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) send REMOTE_RESET\n");
5150                ar9300_mci_remote_reset(ah, AH_TRUE);
5151                ar9300_mci_send_sys_waking(ah, AH_TRUE);
5152                OS_DELAY(1);
5153                if (IS_CHAN_2GHZ(ichan)) {
5154                    ar9300_mci_send_lna_transfer(ah, AH_TRUE);
5155                }
5156                ahp->ah_mci_bt_state = MCI_BT_AWAKE;
5157
5158                /* Redo calibration */
5159                HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Re-calibrate.\n",
5160                    __func__);
5161                ar9300_invalidate_saved_cals(ah, ichan);
5162                cal_ret = ar9300_init_cal(ah, chan, AH_FALSE, apply_last_iqcorr);
5163            }
5164        }
5165        ar9300_mci_enable_interrupt(ah);
5166    }
5167#endif
5168
5169    if (!cal_ret) {
5170        HALDEBUG(ah, HAL_DEBUG_RESET, "%s: Init Cal Failed\n", __func__);
5171        FAIL(HAL_ESELFTEST);
5172    }
5173
5174    ar9300_init_txbf(ah);
5175#if 0
5176    /*
5177     * WAR for owl 1.0 - restore chain mask for 2-chain cfgs after cal
5178     */
5179    rx_chainmask = ahp->ah_rx_chainmask;
5180    if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
5181        OS_REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
5182        OS_REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
5183    }
5184#endif
5185
5186    /* Restore previous led state */
5187    OS_REG_WRITE(ah, AR_CFG_LED, save_led_state | AR_CFG_SCLK_32KHZ);
5188
5189#if ATH_BT_COEX
5190    if (ahp->ah_bt_coex_config_type != HAL_BT_COEX_CFG_NONE) {
5191        ar9300_init_bt_coex(ah);
5192
5193#if ATH_SUPPORT_MCI
5194        if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) {
5195            /* Check BT state again to make sure it's not changed. */
5196            ar9300_mci_sync_bt_state(ah);
5197            ar9300_mci_2g5g_switch(ah, AH_TRUE);
5198
5199            if ((ahp->ah_mci_bt_state == MCI_BT_AWAKE) &&
5200                (ahp->ah_mci_query_bt == AH_TRUE))
5201            {
5202                ahp->ah_mci_need_flush_btinfo = AH_TRUE;
5203            }
5204        }
5205#endif
5206    }
5207#endif
5208
5209    /* Start TSF2 for generic timer 8-15. */
5210    ar9300_start_tsf2(ah);
5211
5212    /* MIMO Power save setting */
5213    if (ar9300_get_capability(ah, HAL_CAP_DYNAMIC_SMPS, 0, AH_NULL) == HAL_OK) {
5214        ar9300_set_sm_power_mode(ah, ahp->ah_sm_power_mode);
5215    }
5216
5217    /*
5218     * For big endian systems turn on swapping for descriptors
5219     */
5220#if AH_BYTE_ORDER == AH_BIG_ENDIAN
5221    if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {
5222        OS_REG_RMW(ah, AR_CFG, AR_CFG_SWTB | AR_CFG_SWRB, 0);
5223    } else {
5224        ar9300_init_cfg_reg(ah);
5225    }
5226#endif
5227
5228    if ( AR_SREV_OSPREY(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah) ) {
5229        OS_REG_RMW(ah, AR_CFG_LED, AR_CFG_LED_ASSOC_CTL, AR_CFG_LED_ASSOC_CTL);
5230    }
5231
5232#if !(defined(ART_BUILD)) && defined(ATH_SUPPORT_LED)
5233#define REG_WRITE(_reg, _val)   *((volatile u_int32_t *)(_reg)) = (_val);
5234#define REG_READ(_reg)          *((volatile u_int32_t *)(_reg))
5235#define ATH_GPIO_OUT_FUNCTION3  0xB8040038
5236#define ATH_GPIO_OE             0xB8040000
5237    if ( AR_SREV_WASP(ah)) {
5238        if (IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan))) {
5239            REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff << 8))) | (0x33 << 8) );
5240            REG_WRITE(ATH_GPIO_OE, ( REG_READ(ATH_GPIO_OE) & (~(0x1 << 13) )));
5241        }
5242        else {
5243
5244            /* Disable 2G WLAN LED. During ath_open, reset function is called even before channel is set.
5245            So 2GHz is taken as default and it also blinks. Hence
5246            to avoid both from blinking, disable 2G led while in 5G mode */
5247
5248            REG_WRITE(ATH_GPIO_OE, ( REG_READ(ATH_GPIO_OE) | (1 << 13) ));
5249            REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff))) | (0x33) );
5250            REG_WRITE(ATH_GPIO_OE, ( REG_READ(ATH_GPIO_OE) & (~(0x1 << 12) )));
5251        }
5252
5253    }
5254    else if (AR_SREV_SCORPION(ah)) {
5255        if (IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan))) {
5256            REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff << 8))) | (0x2F << 8) );
5257    	    REG_WRITE(ATH_GPIO_OE, (( REG_READ(ATH_GPIO_OE) & (~(0x1 << 13) )) | (0x1 << 12)));
5258        } else if (IS_CHAN_5GHZ((AH_PRIVATE(ah)->ah_curchan))) {
5259            REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff))) | (0x2F) );
5260    	    REG_WRITE(ATH_GPIO_OE, (( REG_READ(ATH_GPIO_OE) & (~(0x1 << 12) )) | (0x1 << 13)));
5261        }
5262    }
5263    else if (AR_SREV_HONEYBEE(ah)) {
5264            REG_WRITE(ATH_GPIO_OUT_FUNCTION3, ( REG_READ(ATH_GPIO_OUT_FUNCTION3) & (~(0xff))) | (0x32) );
5265            REG_WRITE(ATH_GPIO_OE, (( REG_READ(ATH_GPIO_OE) & (~(0x1 << 12) ))));
5266    }
5267#undef REG_READ
5268#undef REG_WRITE
5269#endif
5270
5271    /* XXX FreeBSD What's this? -adrian */
5272#if 0
5273    chan->channel_flags = ichan->channel_flags;
5274    chan->priv_flags = ichan->priv_flags;
5275#endif
5276
5277#if FIX_NOISE_FLOOR
5278    /* XXX FreeBSD is ichan appropariate? It was curchan.. */
5279    ar9300_get_nf_hist_base(ah, ichan, is_scan, nf_buf);
5280    ar9300_load_nf(ah, nf_buf);
5281    if (nf_hist_buff_reset == 1)
5282    {
5283        nf_hist_buff_reset = 0;
5284    #ifndef ATH_NF_PER_CHAN
5285	    if (First_NFCal(ah, ichan, is_scan, chan)){
5286            if (ahp->ah_skip_rx_iq_cal && !is_scan) {
5287                /* restore RX Cal result if existing */
5288                ar9300_rx_iq_cal_restore(ah);
5289                ahp->ah_skip_rx_iq_cal = AH_FALSE;
5290            }
5291        }
5292    #endif /* ATH_NF_PER_CHAN */
5293    }
5294    else{
5295        ar9300_start_nf_cal(ah);
5296    }
5297#endif
5298
5299#ifdef AH_SUPPORT_AR9300
5300    /* BB Panic Watchdog */
5301    if (ar9300_get_capability(ah, HAL_CAP_BB_PANIC_WATCHDOG, 0, AH_NULL) ==
5302        HAL_OK)
5303    {
5304        ar9300_config_bb_panic_watchdog(ah);
5305    }
5306#endif
5307
5308    /* While receiving unsupported rate frame receive state machine
5309     * gets into a state 0xb and if phy_restart happens when rx
5310     * state machine is in 0xb state, BB would go hang, if we
5311     * see 0xb state after first bb panic, make sure that we
5312     * disable the phy_restart.
5313     *
5314     * There may be multiple panics, make sure that we always do
5315     * this if we see this panic at least once. This is required
5316     * because reset seems to be writing from INI file.
5317     */
5318    if ((ar9300_get_capability(ah, HAL_CAP_PHYRESTART_CLR_WAR, 0, AH_NULL)
5319         == HAL_OK) && (((MS((AH9300(ah)->ah_bb_panic_last_status),
5320                AR_PHY_BB_WD_RX_OFDM_SM)) == 0xb) ||
5321            AH9300(ah)->ah_phyrestart_disabled) )
5322    {
5323        ar9300_disable_phy_restart(ah, 1);
5324    }
5325
5326
5327
5328    ahp->ah_radar1 = MS(OS_REG_READ(ah, AR_PHY_RADAR_1),
5329                        AR_PHY_RADAR_1_CF_BIN_THRESH);
5330    ahp->ah_dc_offset = MS(OS_REG_READ(ah, AR_PHY_TIMING2),
5331                        AR_PHY_TIMING2_DC_OFFSET);
5332    ahp->ah_disable_cck = MS(OS_REG_READ(ah, AR_PHY_MODE),
5333                        AR_PHY_MODE_DISABLE_CCK);
5334
5335    if (AH9300(ah)->ah_enable_keysearch_always) {
5336        ar9300_enable_keysearch_always(ah, 1);
5337    }
5338
5339#if ATH_LOW_POWER_ENABLE
5340#define REG_WRITE(_reg, _val)   *((volatile u_int32_t *)(_reg)) = (_val)
5341#define REG_READ(_reg)      *((volatile u_int32_t *)(_reg))
5342    if (AR_SREV_OSPREY(ah)) {
5343        REG_WRITE(0xb4000080, REG_READ(0xb4000080) | 3);
5344        OS_REG_WRITE(ah, AR_RTC_RESET, 1);
5345        OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_PCIE_PM_CTRL),
5346                        AR_PCIE_PM_CTRL_ENA);
5347        OS_REG_SET_BIT(ah, AR_HOSTIF_REG(ah, AR_SPARE), 0xffffffff);
5348    }
5349#undef REG_READ
5350#undef REG_WRITE
5351#endif  /* ATH_LOW_POWER_ENABLE */
5352
5353    WAR_USB_DISABLE_PLL_LOCK_DETECT(ah);
5354
5355    /* H/W Green TX */
5356    ar9300_control_signals_for_green_tx_mode(ah);
5357    /* Smart Antenna, only for 5GHz on Scropion */
5358    if (IEEE80211_IS_CHAN_2GHZ((AH_PRIVATE(ah)->ah_curchan)) && AR_SREV_SCORPION(ah)) {
5359        ahp->ah_smartantenna_enable = 0;
5360    }
5361
5362    ar9300_set_smart_antenna(ah, ahp->ah_smartantenna_enable);
5363
5364    if (AR_SREV_APHRODITE(ah) && ahp->ah_lna_div_use_bt_ant_enable)
5365        OS_REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
5366
5367    if (ahp->ah_skip_rx_iq_cal && !is_scan) {
5368        /* restore RX Cal result if existing */
5369        ar9300_rx_iq_cal_restore(ah);
5370        ahp->ah_skip_rx_iq_cal = AH_FALSE;
5371    }
5372
5373
5374    return AH_TRUE;
5375bad:
5376    OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
5377    *status = ecode;
5378
5379    if (ahp->ah_skip_rx_iq_cal && !is_scan) {
5380        /* restore RX Cal result if existing */
5381        ar9300_rx_iq_cal_restore(ah);
5382        ahp->ah_skip_rx_iq_cal = AH_FALSE;
5383    }
5384
5385    return AH_FALSE;
5386#undef FAIL
5387}
5388
5389void
5390ar9300_green_ap_ps_on_off( struct ath_hal *ah, u_int16_t on_off)
5391{
5392    /* Set/reset the ps flag */
5393    AH9300(ah)->green_ap_ps_on = !!on_off;
5394}
5395
5396/*
5397 * This function returns 1, where it is possible to do
5398 * single-chain power save.
5399 */
5400u_int16_t
5401ar9300_is_single_ant_power_save_possible(struct ath_hal *ah)
5402{
5403    return AH_TRUE;
5404}
5405
5406/* To avoid compilation warnings. Functions not used when EMULATION. */
5407/*
5408 * ar9300_find_mag_approx()
5409 */
5410static int32_t
5411ar9300_find_mag_approx(struct ath_hal *ah, int32_t in_re, int32_t in_im)
5412{
5413    int32_t abs_i = abs(in_re);
5414    int32_t abs_q = abs(in_im);
5415    int32_t max_abs, min_abs;
5416
5417    if (abs_i > abs_q) {
5418        max_abs = abs_i;
5419        min_abs = abs_q;
5420    } else {
5421        max_abs = abs_q;
5422        min_abs = abs_i;
5423    }
5424
5425    return (max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4));
5426}
5427
5428/*
5429 * ar9300_solve_iq_cal()
5430 * solve 4x4 linear equation used in loopback iq cal.
5431 */
5432static HAL_BOOL
5433ar9300_solve_iq_cal(
5434    struct ath_hal *ah,
5435    int32_t sin_2phi_1,
5436    int32_t cos_2phi_1,
5437    int32_t sin_2phi_2,
5438    int32_t cos_2phi_2,
5439    int32_t mag_a0_d0,
5440    int32_t phs_a0_d0,
5441    int32_t mag_a1_d0,
5442    int32_t phs_a1_d0,
5443    int32_t solved_eq[])
5444{
5445    int32_t f1 = cos_2phi_1 - cos_2phi_2;
5446    int32_t f3 = sin_2phi_1 - sin_2phi_2;
5447    int32_t f2;
5448    int32_t mag_tx, phs_tx, mag_rx, phs_rx;
5449    const int32_t result_shift = 1 << 15;
5450
5451    f2 = (((int64_t)f1 * (int64_t)f1) / result_shift) + (((int64_t)f3 * (int64_t)f3) / result_shift);
5452
5453    if (0 == f2) {
5454        HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: Divide by 0(%d).\n",
5455            __func__, __LINE__);
5456        return AH_FALSE;
5457    }
5458
5459    /* magnitude mismatch, tx */
5460    mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
5461    /* phase mismatch, tx */
5462    phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
5463
5464    mag_tx = (mag_tx / f2);
5465    phs_tx = (phs_tx / f2);
5466
5467    /* magnitude mismatch, rx */
5468    mag_rx =
5469        mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) / result_shift;
5470    /* phase mismatch, rx */
5471    phs_rx =
5472        phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) / result_shift;
5473
5474    solved_eq[0] = mag_tx;
5475    solved_eq[1] = phs_tx;
5476    solved_eq[2] = mag_rx;
5477    solved_eq[3] = phs_rx;
5478
5479    return AH_TRUE;
5480}
5481
5482/*
5483 * ar9300_calc_iq_corr()
5484 */
5485static HAL_BOOL
5486ar9300_calc_iq_corr(struct ath_hal *ah, int32_t chain_idx,
5487    const int32_t iq_res[], int32_t iqc_coeff[])
5488{
5489    int32_t i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0;
5490    int32_t i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1;
5491    int32_t i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0;
5492    int32_t i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
5493    int32_t mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1;
5494    int32_t phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1;
5495    int32_t sin_2phi_1, cos_2phi_1, sin_2phi_2, cos_2phi_2;
5496    int32_t mag_tx, phs_tx, mag_rx, phs_rx;
5497    int32_t solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx;
5498    int32_t q_q_coff, q_i_coff;
5499    const int32_t res_scale = 1 << 15;
5500    const int32_t delpt_shift = 1 << 8;
5501    int32_t mag1, mag2;
5502
5503    i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
5504    i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
5505    iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
5506
5507    if (i2_m_q2_a0_d0 > 0x800)  {
5508        i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
5509    }
5510    if (iq_corr_a0_d0 > 0x800)  {
5511        iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
5512    }
5513
5514    i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
5515    i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
5516    iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
5517
5518    if (i2_m_q2_a0_d1 > 0x800)  {
5519        i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
5520    }
5521    if (iq_corr_a0_d1 > 0x800)  {
5522        iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
5523    }
5524
5525    i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
5526    i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
5527    iq_corr_a1_d0 = iq_res[4] & 0xfff;
5528
5529    if (i2_m_q2_a1_d0 > 0x800)  {
5530        i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
5531    }
5532    if (iq_corr_a1_d0 > 0x800)  {
5533        iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
5534    }
5535
5536    i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
5537    i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
5538    iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
5539
5540    if (i2_m_q2_a1_d1 > 0x800)  {
5541        i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
5542    }
5543    if (iq_corr_a1_d1 > 0x800)  {
5544        iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
5545    }
5546
5547    if ((i2_p_q2_a0_d0 == 0) ||
5548        (i2_p_q2_a0_d1 == 0) ||
5549        (i2_p_q2_a1_d0 == 0) ||
5550        (i2_p_q2_a1_d1 == 0)) {
5551        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5552            "%s: Divide by 0(%d):\na0_d0=%d\na0_d1=%d\na2_d0=%d\na1_d1=%d\n",
5553            __func__, __LINE__,
5554            i2_p_q2_a0_d0, i2_p_q2_a0_d1, i2_p_q2_a1_d0, i2_p_q2_a1_d1);
5555        return AH_FALSE;
5556    }
5557
5558    if ((i2_p_q2_a0_d0 <= 1024) || (i2_p_q2_a0_d0 > 2047) ||
5559            (i2_p_q2_a1_d0 < 0) || (i2_p_q2_a1_d1 < 0) ||
5560            (i2_p_q2_a0_d0 <= i2_m_q2_a0_d0) ||
5561            (i2_p_q2_a0_d0 <= iq_corr_a0_d0) ||
5562            (i2_p_q2_a0_d1 <= i2_m_q2_a0_d1) ||
5563            (i2_p_q2_a0_d1 <= iq_corr_a0_d1) ||
5564            (i2_p_q2_a1_d0 <= i2_m_q2_a1_d0) ||
5565            (i2_p_q2_a1_d0 <= iq_corr_a1_d0) ||
5566            (i2_p_q2_a1_d1 <= i2_m_q2_a1_d1) ||
5567            (i2_p_q2_a1_d1 <= iq_corr_a1_d1)) {
5568        return AH_FALSE;
5569    }
5570
5571    mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
5572    phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
5573
5574    mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
5575    phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
5576
5577    mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
5578    phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
5579
5580    mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
5581    phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
5582
5583    /* without analog phase shift */
5584    sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
5585    /* without analog phase shift */
5586    cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
5587    /* with  analog phase shift */
5588    sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
5589    /* with analog phase shift */
5590    cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
5591
5592    /* force sin^2 + cos^2 = 1; */
5593    /* find magnitude by approximation */
5594    mag1 = ar9300_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
5595    mag2 = ar9300_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
5596
5597    if ((mag1 == 0) || (mag2 == 0)) {
5598        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5599            "%s: Divide by 0(%d): mag1=%d, mag2=%d\n",
5600            __func__, __LINE__, mag1, mag2);
5601        return AH_FALSE;
5602    }
5603
5604    /* normalization sin and cos by mag */
5605    sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
5606    cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
5607    sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
5608    cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
5609
5610    /* calculate IQ mismatch */
5611    if (AH_FALSE == ar9300_solve_iq_cal(ah,
5612            sin_2phi_1, cos_2phi_1, sin_2phi_2, cos_2phi_2, mag_a0_d0,
5613            phs_a0_d0, mag_a1_d0, phs_a1_d0, solved_eq))
5614    {
5615        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5616            "%s: Call to ar9300_solve_iq_cal failed.\n", __func__);
5617        return AH_FALSE;
5618    }
5619
5620    mag_tx = solved_eq[0];
5621    phs_tx = solved_eq[1];
5622    mag_rx = solved_eq[2];
5623    phs_rx = solved_eq[3];
5624
5625    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5626        "%s: chain %d: mag mismatch=%d phase mismatch=%d\n",
5627        __func__, chain_idx, mag_tx / res_scale, phs_tx / res_scale);
5628
5629    if (res_scale == mag_tx) {
5630        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5631            "%s: Divide by 0(%d): mag_tx=%d, res_scale=%d\n",
5632            __func__, __LINE__, mag_tx, res_scale);
5633        return AH_FALSE;
5634    }
5635
5636    /* calculate and quantize Tx IQ correction factor */
5637    mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
5638    phs_corr_tx = -phs_tx;
5639
5640    q_q_coff = (mag_corr_tx * 128 / res_scale);
5641    q_i_coff = (phs_corr_tx * 256 / res_scale);
5642
5643    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5644        "%s: tx chain %d: mag corr=%d  phase corr=%d\n",
5645        __func__, chain_idx, q_q_coff, q_i_coff);
5646
5647    if (q_i_coff < -63) {
5648        q_i_coff = -63;
5649    }
5650    if (q_i_coff > 63) {
5651        q_i_coff = 63;
5652    }
5653    if (q_q_coff < -63) {
5654        q_q_coff = -63;
5655    }
5656    if (q_q_coff > 63) {
5657        q_q_coff = 63;
5658    }
5659
5660    iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
5661
5662    HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: tx chain %d: iq corr coeff=%x\n",
5663        __func__, chain_idx, iqc_coeff[0]);
5664
5665    if (-mag_rx == res_scale) {
5666        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5667            "%s: Divide by 0(%d): mag_rx=%d, res_scale=%d\n",
5668            __func__, __LINE__, mag_rx, res_scale);
5669        return AH_FALSE;
5670    }
5671
5672    /* calculate and quantize Rx IQ correction factors */
5673    mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
5674    phs_corr_rx = -phs_rx;
5675
5676    q_q_coff = (mag_corr_rx * 128 / res_scale);
5677    q_i_coff = (phs_corr_rx * 256 / res_scale);
5678
5679    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5680        "%s: rx chain %d: mag corr=%d  phase corr=%d\n",
5681        __func__, chain_idx, q_q_coff, q_i_coff);
5682
5683    if (q_i_coff < -63) {
5684        q_i_coff = -63;
5685    }
5686    if (q_i_coff > 63) {
5687        q_i_coff = 63;
5688    }
5689    if (q_q_coff < -63) {
5690        q_q_coff = -63;
5691    }
5692    if (q_q_coff > 63) {
5693        q_q_coff = 63;
5694    }
5695
5696    iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
5697
5698    HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s: rx chain %d: iq corr coeff=%x\n",
5699        __func__, chain_idx, iqc_coeff[1]);
5700
5701    return AH_TRUE;
5702}
5703
5704#define MAX_MAG_DELTA 11 //maximum magnitude mismatch delta across gains
5705#define MAX_PHS_DELTA 10 //maximum phase mismatch delta across gains
5706#define ABS(x) ((x) >= 0 ? (x) : (-(x)))
5707
5708    u_int32_t tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS] = {
5709    {   AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
5710        AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
5711        AR_PHY_TX_IQCAL_CORR_COEFF_01_B2},
5712    {   AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
5713        AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
5714        AR_PHY_TX_IQCAL_CORR_COEFF_01_B2},
5715    {   AR_PHY_TX_IQCAL_CORR_COEFF_23_B0,
5716        AR_PHY_TX_IQCAL_CORR_COEFF_23_B1,
5717        AR_PHY_TX_IQCAL_CORR_COEFF_23_B2},
5718    {   AR_PHY_TX_IQCAL_CORR_COEFF_23_B0,
5719        AR_PHY_TX_IQCAL_CORR_COEFF_23_B1,
5720        AR_PHY_TX_IQCAL_CORR_COEFF_23_B2},
5721    {   AR_PHY_TX_IQCAL_CORR_COEFF_45_B0,
5722        AR_PHY_TX_IQCAL_CORR_COEFF_45_B1,
5723        AR_PHY_TX_IQCAL_CORR_COEFF_45_B2},
5724    {   AR_PHY_TX_IQCAL_CORR_COEFF_45_B0,
5725        AR_PHY_TX_IQCAL_CORR_COEFF_45_B1,
5726        AR_PHY_TX_IQCAL_CORR_COEFF_45_B2},
5727    {   AR_PHY_TX_IQCAL_CORR_COEFF_67_B0,
5728        AR_PHY_TX_IQCAL_CORR_COEFF_67_B1,
5729        AR_PHY_TX_IQCAL_CORR_COEFF_67_B2},
5730    {   AR_PHY_TX_IQCAL_CORR_COEFF_67_B0,
5731        AR_PHY_TX_IQCAL_CORR_COEFF_67_B1,
5732        AR_PHY_TX_IQCAL_CORR_COEFF_67_B2},
5733    };
5734
5735static void
5736ar9300_tx_iq_cal_outlier_detection(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan, u_int32_t num_chains,
5737    struct coeff_t *coeff, HAL_BOOL is_cal_reusable)
5738{
5739    int nmeasurement, ch_idx, im;
5740    int32_t magnitude, phase;
5741    int32_t magnitude_max, phase_max;
5742    int32_t magnitude_min, phase_min;
5743
5744    int32_t magnitude_max_idx, phase_max_idx;
5745    int32_t magnitude_min_idx, phase_min_idx;
5746
5747    int32_t magnitude_avg, phase_avg;
5748    int32_t outlier_mag_idx = 0;
5749    int32_t outlier_phs_idx = 0;
5750
5751
5752    if (AR_SREV_POSEIDON(ah)) {
5753        HALASSERT(num_chains == 0x1);
5754
5755        tx_corr_coeff[0][0] = AR_PHY_TX_IQCAL_CORR_COEFF_01_B0_POSEIDON;
5756        tx_corr_coeff[1][0] = AR_PHY_TX_IQCAL_CORR_COEFF_01_B0_POSEIDON;
5757        tx_corr_coeff[2][0] = AR_PHY_TX_IQCAL_CORR_COEFF_23_B0_POSEIDON;
5758        tx_corr_coeff[3][0] = AR_PHY_TX_IQCAL_CORR_COEFF_23_B0_POSEIDON;
5759        tx_corr_coeff[4][0] = AR_PHY_TX_IQCAL_CORR_COEFF_45_B0_POSEIDON;
5760        tx_corr_coeff[5][0] = AR_PHY_TX_IQCAL_CORR_COEFF_45_B0_POSEIDON;
5761        tx_corr_coeff[6][0] = AR_PHY_TX_IQCAL_CORR_COEFF_67_B0_POSEIDON;
5762        tx_corr_coeff[7][0] = AR_PHY_TX_IQCAL_CORR_COEFF_67_B0_POSEIDON;
5763    }
5764
5765    for (ch_idx = 0; ch_idx < num_chains; ch_idx++) {
5766        nmeasurement = OS_REG_READ_FIELD(ah,
5767            AR_PHY_TX_IQCAL_STATUS_B0(ah), AR_PHY_CALIBRATED_GAINS_0);
5768        if (nmeasurement > MAX_MEASUREMENT) {
5769            nmeasurement = MAX_MEASUREMENT;
5770        }
5771
5772        if (!AR_SREV_SCORPION(ah)) {
5773            /*
5774             * reset max/min variable to min/max values so that
5775             * we always start with 1st calibrated gain value
5776             */
5777            magnitude_max = -64;
5778            phase_max     = -64;
5779            magnitude_min = 63;
5780            phase_min     = 63;
5781            magnitude_avg = 0;
5782            phase_avg     = 0;
5783            magnitude_max_idx = 0;
5784            magnitude_min_idx = 0;
5785            phase_max_idx = 0;
5786            phase_min_idx = 0;
5787
5788            /* detect outlier only if nmeasurement > 1 */
5789            if (nmeasurement > 1) {
5790                /* printf("----------- start outlier detection -----------\n"); */
5791                /*
5792                 * find max/min and phase/mag mismatch across all calibrated gains
5793                 */
5794                for (im = 0; im < nmeasurement; im++) {
5795                    magnitude = coeff->mag_coeff[ch_idx][im][0];
5796                    phase = coeff->phs_coeff[ch_idx][im][0];
5797
5798                    magnitude_avg = magnitude_avg + magnitude;
5799                    phase_avg = phase_avg + phase;
5800                    if (magnitude > magnitude_max) {
5801                        magnitude_max = magnitude;
5802                        magnitude_max_idx = im;
5803                    }
5804                    if (magnitude < magnitude_min) {
5805                        magnitude_min = magnitude;
5806                        magnitude_min_idx = im;
5807                    }
5808                    if (phase > phase_max) {
5809                        phase_max = phase;
5810                        phase_max_idx = im;
5811                    }
5812                    if (phase < phase_min) {
5813                        phase_min = phase;
5814                        phase_min_idx = im;
5815                    }
5816                }
5817                /* find average (exclude max abs value) */
5818                for (im = 0; im < nmeasurement; im++) {
5819                    magnitude = coeff->mag_coeff[ch_idx][im][0];
5820                    phase = coeff->phs_coeff[ch_idx][im][0];
5821                    if ((ABS(magnitude) < ABS(magnitude_max)) ||
5822                        (ABS(magnitude) < ABS(magnitude_min)))
5823                    {
5824                        magnitude_avg = magnitude_avg + magnitude;
5825                    }
5826                    if ((ABS(phase) < ABS(phase_max)) ||
5827                        (ABS(phase) < ABS(phase_min)))
5828                    {
5829                        phase_avg = phase_avg + phase;
5830                    }
5831                }
5832                magnitude_avg = magnitude_avg / (nmeasurement - 1);
5833                phase_avg = phase_avg / (nmeasurement - 1);
5834
5835                /* detect magnitude outlier */
5836                if (ABS(magnitude_max - magnitude_min) > MAX_MAG_DELTA) {
5837                    if (ABS(magnitude_max - magnitude_avg) >
5838                        ABS(magnitude_min - magnitude_avg))
5839                    {
5840                        /* max is outlier, force to avg */
5841                        outlier_mag_idx = magnitude_max_idx;
5842                    } else {
5843                        /* min is outlier, force to avg */
5844                        outlier_mag_idx = magnitude_min_idx;
5845                    }
5846                    coeff->mag_coeff[ch_idx][outlier_mag_idx][0] = magnitude_avg;
5847                    coeff->phs_coeff[ch_idx][outlier_mag_idx][0] = phase_avg;
5848                    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5849                        "[ch%d][outlier mag gain%d]:: "
5850                        "mag_avg = %d (/128), phase_avg = %d (/256)\n",
5851                        ch_idx, outlier_mag_idx, magnitude_avg, phase_avg);
5852                }
5853                /* detect phase outlier */
5854                if (ABS(phase_max - phase_min) > MAX_PHS_DELTA) {
5855                    if (ABS(phase_max-phase_avg) > ABS(phase_min - phase_avg)) {
5856                        /* max is outlier, force to avg */
5857                        outlier_phs_idx = phase_max_idx;
5858                    } else{
5859                        /* min is outlier, force to avg */
5860                        outlier_phs_idx = phase_min_idx;
5861                    }
5862                    coeff->mag_coeff[ch_idx][outlier_phs_idx][0] = magnitude_avg;
5863                    coeff->phs_coeff[ch_idx][outlier_phs_idx][0] = phase_avg;
5864                    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
5865                        "[ch%d][outlier phs gain%d]:: "
5866                        "mag_avg = %d (/128), phase_avg = %d (/256)\n",
5867                        ch_idx, outlier_phs_idx, magnitude_avg, phase_avg);
5868                }
5869            }
5870        }
5871
5872        /*printf("------------ after outlier detection -------------\n");*/
5873        for (im = 0; im < nmeasurement; im++) {
5874            magnitude = coeff->mag_coeff[ch_idx][im][0];
5875            phase = coeff->phs_coeff[ch_idx][im][0];
5876
5877            #if 0
5878            printf("[ch%d][gain%d]:: mag = %d (/128), phase = %d (/256)\n",
5879                ch_idx, im, magnitude, phase);
5880            #endif
5881
5882            coeff->iqc_coeff[0] = (phase & 0x7f) | ((magnitude & 0x7f) << 7);
5883
5884            if ((im % 2) == 0) {
5885                OS_REG_RMW_FIELD(ah,
5886                    tx_corr_coeff[im][ch_idx],
5887                    AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
5888                    coeff->iqc_coeff[0]);
5889            } else {
5890                OS_REG_RMW_FIELD(ah,
5891                    tx_corr_coeff[im][ch_idx],
5892                    AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
5893                    coeff->iqc_coeff[0]);
5894            }
5895#if ATH_SUPPORT_CAL_REUSE
5896            ichan->tx_corr_coeff[im][ch_idx] = coeff->iqc_coeff[0];
5897#endif
5898        }
5899#if ATH_SUPPORT_CAL_REUSE
5900        ichan->num_measures[ch_idx] = nmeasurement;
5901#endif
5902    }
5903
5904    OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
5905                     AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
5906    OS_REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
5907                     AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
5908
5909#if ATH_SUPPORT_CAL_REUSE
5910    if (is_cal_reusable) {
5911        ichan->one_time_txiqcal_done = AH_TRUE;
5912        HALDEBUG(ah, HAL_DEBUG_FCS_RTT,
5913            "(FCS) TXIQCAL saved - %d\n", ichan->channel);
5914    }
5915#endif
5916}
5917
5918#if ATH_SUPPORT_CAL_REUSE
5919static void
5920ar9300_tx_iq_cal_apply(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan)
5921{
5922    struct ath_hal_9300 *ahp = AH9300(ah);
5923    int nmeasurement, ch_idx, im;
5924
5925    u_int32_t tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS] = {
5926        {   AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
5927            AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
5928            AR_PHY_TX_IQCAL_CORR_COEFF_01_B2},
5929        {   AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
5930            AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
5931            AR_PHY_TX_IQCAL_CORR_COEFF_01_B2},
5932        {   AR_PHY_TX_IQCAL_CORR_COEFF_23_B0,
5933            AR_PHY_TX_IQCAL_CORR_COEFF_23_B1,
5934            AR_PHY_TX_IQCAL_CORR_COEFF_23_B2},
5935        {   AR_PHY_TX_IQCAL_CORR_COEFF_23_B0,
5936            AR_PHY_TX_IQCAL_CORR_COEFF_23_B1,
5937            AR_PHY_TX_IQCAL_CORR_COEFF_23_B2},
5938        {   AR_PHY_TX_IQCAL_CORR_COEFF_45_B0,
5939            AR_PHY_TX_IQCAL_CORR_COEFF_45_B1,
5940            AR_PHY_TX_IQCAL_CORR_COEFF_45_B2},
5941        {   AR_PHY_TX_IQCAL_CORR_COEFF_45_B0,
5942            AR_PHY_TX_IQCAL_CORR_COEFF_45_B1,
5943            AR_PHY_TX_IQCAL_CORR_COEFF_45_B2},
5944        {   AR_PHY_TX_IQCAL_CORR_COEFF_67_B0,
5945            AR_PHY_TX_IQCAL_CORR_COEFF_67_B1,
5946            AR_PHY_TX_IQCAL_CORR_COEFF_67_B2},
5947        {   AR_PHY_TX_IQCAL_CORR_COEFF_67_B0,
5948            AR_PHY_TX_IQCAL_CORR_COEFF_67_B1,
5949            AR_PHY_TX_IQCAL_CORR_COEFF_67_B2},
5950    };
5951
5952    if (AR_SREV_POSEIDON(ah)) {
5953        HALASSERT(ahp->ah_tx_cal_chainmask == 0x1);
5954
5955        tx_corr_coeff[0][0] = AR_PHY_TX_IQCAL_CORR_COEFF_01_B0_POSEIDON;
5956        tx_corr_coeff[1][0] = AR_PHY_TX_IQCAL_CORR_COEFF_01_B0_POSEIDON;
5957        tx_corr_coeff[2][0] = AR_PHY_TX_IQCAL_CORR_COEFF_23_B0_POSEIDON;
5958        tx_corr_coeff[3][0] = AR_PHY_TX_IQCAL_CORR_COEFF_23_B0_POSEIDON;
5959        tx_corr_coeff[4][0] = AR_PHY_TX_IQCAL_CORR_COEFF_45_B0_POSEIDON;
5960        tx_corr_coeff[5][0] = AR_PHY_TX_IQCAL_CORR_COEFF_45_B0_POSEIDON;
5961        tx_corr_coeff[6][0] = AR_PHY_TX_IQCAL_CORR_COEFF_67_B0_POSEIDON;
5962        tx_corr_coeff[7][0] = AR_PHY_TX_IQCAL_CORR_COEFF_67_B0_POSEIDON;
5963    }
5964
5965    for (ch_idx = 0; ch_idx < AR9300_MAX_CHAINS; ch_idx++) {
5966        if ((ahp->ah_tx_cal_chainmask & (1 << ch_idx)) == 0) {
5967            continue;
5968        }
5969        nmeasurement = ichan->num_measures[ch_idx];
5970
5971        for (im = 0; im < nmeasurement; im++) {
5972            if ((im % 2) == 0) {
5973                OS_REG_RMW_FIELD(ah,
5974                    tx_corr_coeff[im][ch_idx],
5975                    AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
5976                    ichan->tx_corr_coeff[im][ch_idx]);
5977            } else {
5978                OS_REG_RMW_FIELD(ah,
5979                    tx_corr_coeff[im][ch_idx],
5980                    AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
5981                    ichan->tx_corr_coeff[im][ch_idx]);
5982            }
5983        }
5984    }
5985
5986    OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
5987                     AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
5988    OS_REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
5989                     AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
5990}
5991#endif
5992
5993/*
5994 * ar9300_tx_iq_cal_hw_run is only needed for osprey/wasp/hornet
5995 * It is not needed for jupiter/poseidon.
5996 */
5997HAL_BOOL
5998ar9300_tx_iq_cal_hw_run(struct ath_hal *ah)
5999{
6000    int is_tx_gain_forced;
6001
6002    is_tx_gain_forced = OS_REG_READ_FIELD(ah,
6003        AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE);
6004    if (is_tx_gain_forced) {
6005        /*printf("Tx gain can not be forced during tx I/Q cal!\n");*/
6006        OS_REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE, 0);
6007    }
6008
6009    /* enable tx IQ cal */
6010    OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START(ah),
6011        AR_PHY_TX_IQCAL_START_DO_CAL, AR_PHY_TX_IQCAL_START_DO_CAL);
6012
6013    if (!ath_hal_wait(ah,
6014            AR_PHY_TX_IQCAL_START(ah), AR_PHY_TX_IQCAL_START_DO_CAL, 0))
6015    {
6016        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
6017            "%s: Tx IQ Cal is never completed.\n", __func__);
6018        return AH_FALSE;
6019    }
6020    return AH_TRUE;
6021}
6022
6023static void
6024ar9300_tx_iq_cal_post_proc(struct ath_hal *ah,HAL_CHANNEL_INTERNAL *ichan,
6025                           int iqcal_idx, int max_iqcal,HAL_BOOL is_cal_reusable, HAL_BOOL apply_last_corr)
6026{
6027    int nmeasurement=0, im, ix, iy, temp;
6028    struct ath_hal_9300     *ahp = AH9300(ah);
6029    u_int32_t txiqcal_status[AR9300_MAX_CHAINS] = {
6030        AR_PHY_TX_IQCAL_STATUS_B0(ah),
6031        AR_PHY_TX_IQCAL_STATUS_B1,
6032        AR_PHY_TX_IQCAL_STATUS_B2,
6033    };
6034    const u_int32_t chan_info_tab[] = {
6035        AR_PHY_CHAN_INFO_TAB_0,
6036        AR_PHY_CHAN_INFO_TAB_1,
6037        AR_PHY_CHAN_INFO_TAB_2,
6038    };
6039    int32_t iq_res[6];
6040    int32_t ch_idx, j;
6041    u_int32_t num_chains = 0;
6042    static struct coeff_t coeff;
6043    txiqcal_status[0] = AR_PHY_TX_IQCAL_STATUS_B0(ah);
6044
6045    for (ch_idx = 0; ch_idx < AR9300_MAX_CHAINS; ch_idx++) {
6046        if (ahp->ah_tx_chainmask & (1 << ch_idx)) {
6047            num_chains++;
6048        }
6049    }
6050
6051    if (apply_last_corr) {
6052	    if (coeff.last_cal == AH_TRUE) {
6053		    int32_t magnitude, phase;
6054		    int ch_idx, im;
6055		    u_int32_t tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS] = {
6056			    {   AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
6057				    AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
6058				    AR_PHY_TX_IQCAL_CORR_COEFF_01_B2},
6059			    {   AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
6060				    AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
6061				    AR_PHY_TX_IQCAL_CORR_COEFF_01_B2},
6062			    {   AR_PHY_TX_IQCAL_CORR_COEFF_23_B0,
6063				    AR_PHY_TX_IQCAL_CORR_COEFF_23_B1,
6064				    AR_PHY_TX_IQCAL_CORR_COEFF_23_B2},
6065			    {   AR_PHY_TX_IQCAL_CORR_COEFF_23_B0,
6066				    AR_PHY_TX_IQCAL_CORR_COEFF_23_B1,
6067				    AR_PHY_TX_IQCAL_CORR_COEFF_23_B2},
6068			    {   AR_PHY_TX_IQCAL_CORR_COEFF_45_B0,
6069				    AR_PHY_TX_IQCAL_CORR_COEFF_45_B1,
6070				    AR_PHY_TX_IQCAL_CORR_COEFF_45_B2},
6071			    {   AR_PHY_TX_IQCAL_CORR_COEFF_45_B0,
6072				    AR_PHY_TX_IQCAL_CORR_COEFF_45_B1,
6073				    AR_PHY_TX_IQCAL_CORR_COEFF_45_B2},
6074			    {   AR_PHY_TX_IQCAL_CORR_COEFF_67_B0,
6075				    AR_PHY_TX_IQCAL_CORR_COEFF_67_B1,
6076				    AR_PHY_TX_IQCAL_CORR_COEFF_67_B2},
6077			    {   AR_PHY_TX_IQCAL_CORR_COEFF_67_B0,
6078				    AR_PHY_TX_IQCAL_CORR_COEFF_67_B1,
6079				    AR_PHY_TX_IQCAL_CORR_COEFF_67_B2},
6080		    };
6081		    for (ch_idx = 0; ch_idx < num_chains; ch_idx++) {
6082			    for (im = 0; im < coeff.last_nmeasurement; im++) {
6083				    magnitude = coeff.mag_coeff[ch_idx][im][0];
6084				    phase = coeff.phs_coeff[ch_idx][im][0];
6085
6086#if 0
6087				    printf("[ch%d][gain%d]:: mag = %d (/128), phase = %d (/256)\n",
6088						    ch_idx, im, magnitude, phase);
6089#endif
6090
6091				    coeff.iqc_coeff[0] = (phase & 0x7f) | ((magnitude & 0x7f) << 7);
6092				    if ((im % 2) == 0) {
6093					    OS_REG_RMW_FIELD(ah,
6094							    tx_corr_coeff[im][ch_idx],
6095							    AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
6096							    coeff.iqc_coeff[0]);
6097				    } else {
6098					    OS_REG_RMW_FIELD(ah,
6099							    tx_corr_coeff[im][ch_idx],
6100							    AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
6101							    coeff.iqc_coeff[0]);
6102				    }
6103			    }
6104		    }
6105		    OS_REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
6106				    AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
6107	    }
6108	    return;
6109    }
6110
6111
6112    for (ch_idx = 0; ch_idx < num_chains; ch_idx++) {
6113        nmeasurement = OS_REG_READ_FIELD(ah,
6114            AR_PHY_TX_IQCAL_STATUS_B0(ah), AR_PHY_CALIBRATED_GAINS_0);
6115        if (nmeasurement > MAX_MEASUREMENT) {
6116            nmeasurement = MAX_MEASUREMENT;
6117        }
6118
6119        for (im = 0; im < nmeasurement; im++) {
6120            HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
6121                "%s: Doing Tx IQ Cal for chain %d.\n", __func__, ch_idx);
6122            if (OS_REG_READ(ah, txiqcal_status[ch_idx]) &
6123                AR_PHY_TX_IQCAL_STATUS_FAILED)
6124            {
6125                HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
6126                    "%s: Tx IQ Cal failed for chain %d.\n", __func__, ch_idx);
6127                goto TX_IQ_CAL_FAILED_;
6128            }
6129
6130            for (j = 0; j < 3; j++) {
6131                u_int32_t idx = 2 * j;
6132                /* 3 registers for each calibration result */
6133                u_int32_t offset = 4 * (3 * im + j);
6134
6135                OS_REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
6136                    AR_PHY_CHAN_INFO_TAB_S2_READ, 0);
6137                /* 32 bits */
6138                iq_res[idx] = OS_REG_READ(ah, chan_info_tab[ch_idx] + offset);
6139                OS_REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
6140                    AR_PHY_CHAN_INFO_TAB_S2_READ, 1);
6141                /* 16 bits */
6142                iq_res[idx + 1] = 0xffff &
6143                    OS_REG_READ(ah, chan_info_tab[ch_idx] + offset);
6144
6145                HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
6146                    "%s: IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
6147                    __func__, idx, iq_res[idx], idx + 1, iq_res[idx + 1]);
6148            }
6149
6150            if (AH_FALSE == ar9300_calc_iq_corr(
6151                             ah, ch_idx, iq_res, coeff.iqc_coeff))
6152            {
6153                HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
6154                    "%s: Failed in calculation of IQ correction.\n",
6155                     __func__);
6156                goto TX_IQ_CAL_FAILED_;
6157            }
6158
6159            coeff.phs_coeff[ch_idx][im][iqcal_idx-1] = coeff.iqc_coeff[0] & 0x7f;
6160            coeff.mag_coeff[ch_idx][im][iqcal_idx-1] = (coeff.iqc_coeff[0] >> 7) & 0x7f;
6161            if (coeff.mag_coeff[ch_idx][im][iqcal_idx-1] > 63) {
6162                coeff.mag_coeff[ch_idx][im][iqcal_idx-1] -= 128;
6163            }
6164            if (coeff.phs_coeff[ch_idx][im][iqcal_idx-1] > 63) {
6165                coeff.phs_coeff[ch_idx][im][iqcal_idx-1] -= 128;
6166            }
6167#if 0
6168            ath_hal_printf(ah, "IQCAL::[ch%d][gain%d]:: mag = %d phase = %d \n",
6169                ch_idx, im, coeff.mag_coeff[ch_idx][im][iqcal_idx-1],
6170                coeff.phs_coeff[ch_idx][im][iqcal_idx-1]);
6171#endif
6172        }
6173    }
6174    //last iteration; calculate mag and phs
6175    if (iqcal_idx == max_iqcal) {
6176        if (max_iqcal>1) {
6177            for (ch_idx = 0; ch_idx < num_chains; ch_idx++) {
6178                for (im = 0; im < nmeasurement; im++) {
6179                    //sort mag and phs
6180                    for( ix=0;ix<max_iqcal-1;ix++){
6181                        for( iy=ix+1;iy<=max_iqcal-1;iy++){
6182                            if(coeff.mag_coeff[ch_idx][im][iy] <
6183                                coeff.mag_coeff[ch_idx][im][ix]) {
6184                                //swap
6185                                temp=coeff.mag_coeff[ch_idx][im][ix];
6186                                coeff.mag_coeff[ch_idx][im][ix] = coeff.mag_coeff[ch_idx][im][iy];
6187                                coeff.mag_coeff[ch_idx][im][iy] = temp;
6188                            }
6189                            if(coeff.phs_coeff[ch_idx][im][iy] <
6190                                coeff.phs_coeff[ch_idx][im][ix]){
6191                                //swap
6192                                temp=coeff.phs_coeff[ch_idx][im][ix];
6193                                coeff.phs_coeff[ch_idx][im][ix]=coeff.phs_coeff[ch_idx][im][iy];
6194                                coeff.phs_coeff[ch_idx][im][iy]=temp;
6195                            }
6196                        }
6197                    }
6198                    //select median; 3rd entry in the sorted array
6199                    coeff.mag_coeff[ch_idx][im][0] =
6200                        coeff.mag_coeff[ch_idx][im][max_iqcal/2];
6201                    coeff.phs_coeff[ch_idx][im][0] =
6202                        coeff.phs_coeff[ch_idx][im][max_iqcal/2];
6203                    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
6204                        "IQCAL: Median [ch%d][gain%d]:: mag = %d phase = %d \n",
6205                        ch_idx, im,coeff.mag_coeff[ch_idx][im][0],
6206                        coeff.phs_coeff[ch_idx][im][0]);
6207                }
6208            }
6209        }
6210        ar9300_tx_iq_cal_outlier_detection(ah,ichan, num_chains, &coeff,is_cal_reusable);
6211    }
6212
6213
6214    coeff.last_nmeasurement = nmeasurement;
6215    coeff.last_cal = AH_TRUE;
6216
6217    return;
6218
6219TX_IQ_CAL_FAILED_:
6220    /* no need to print this, it is AGC failure not chip stuck */
6221    /*ath_hal_printf(ah, "Tx IQ Cal failed(%d)\n", line);*/
6222    coeff.last_cal = AH_FALSE;
6223    return;
6224}
6225
6226
6227/*
6228 * ar9300_disable_phy_restart
6229 *
6230 * In some BBpanics, we can disable the phyrestart
6231 * disable_phy_restart
6232 *      != 0, disable the phy restart in h/w
6233 *      == 0, enable the phy restart in h/w
6234 */
6235void ar9300_disable_phy_restart(struct ath_hal *ah, int disable_phy_restart)
6236{
6237    u_int32_t val;
6238
6239    val = OS_REG_READ(ah, AR_PHY_RESTART);
6240    if (disable_phy_restart) {
6241        val &= ~AR_PHY_RESTART_ENA;
6242        AH9300(ah)->ah_phyrestart_disabled = 1;
6243    } else {
6244        val |= AR_PHY_RESTART_ENA;
6245        AH9300(ah)->ah_phyrestart_disabled = 0;
6246    }
6247    OS_REG_WRITE(ah, AR_PHY_RESTART, val);
6248
6249    val = OS_REG_READ(ah, AR_PHY_RESTART);
6250}
6251
6252HAL_BOOL
6253ar9300_interference_is_present(struct ath_hal *ah)
6254{
6255    int i;
6256    struct ath_hal_private  *ahpriv = AH_PRIVATE(ah);
6257    const struct ieee80211_channel *chan = ahpriv->ah_curchan;
6258    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
6259
6260    if (ichan == NULL) {
6261        ath_hal_printf(ah, "%s: called with ichan=NULL\n", __func__);
6262        return AH_FALSE;
6263    }
6264
6265    /* This function is called after a stuck beacon, if EACS is enabled.
6266     * If CW interference is severe, then HW goes into a loop of continuous
6267     * stuck beacons and resets. On reset the NF cal history is cleared.
6268     * So the median value of the history cannot be used -
6269     * hence check if any value (Chain 0/Primary Channel)
6270     * is outside the bounds.
6271     */
6272    HAL_NFCAL_HIST_FULL *h = AH_HOME_CHAN_NFCAL_HIST(ah, ichan);
6273    for (i = 0; i < HAL_NF_CAL_HIST_LEN_FULL; i++) {
6274        if (h->nf_cal_buffer[i][0] >
6275            AH9300(ah)->nfp->nominal + AH9300(ah)->nf_cw_int_delta)
6276        {
6277            return AH_TRUE;
6278        }
6279
6280    }
6281    return AH_FALSE;
6282}
6283
6284#if ATH_SUPPORT_CRDC
6285void
6286ar9300_crdc_rx_notify(struct ath_hal *ah, struct ath_rx_status *rxs)
6287{
6288    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
6289    int rssi_index;
6290
6291    if ((!AR_SREV_WASP(ah)) ||
6292        (!ahpriv->ah_config.ath_hal_crdc_enable)) {
6293        return;
6294    }
6295
6296    if (rxs->rs_isaggr && rxs->rs_moreaggr) {
6297        return;
6298    }
6299
6300    if ((rxs->rs_rssi_ctl0 >= HAL_RSSI_BAD) ||
6301        (rxs->rs_rssi_ctl1 >= HAL_RSSI_BAD)) {
6302        return;
6303    }
6304
6305    rssi_index = ah->ah_crdc_rssi_ptr % HAL_MAX_CRDC_RSSI_SAMPLE;
6306
6307    ah->ah_crdc_rssi_sample[0][rssi_index] = rxs->rs_rssi_ctl0;
6308    ah->ah_crdc_rssi_sample[1][rssi_index] = rxs->rs_rssi_ctl1;
6309
6310    ah->ah_crdc_rssi_ptr++;
6311}
6312
6313static int
6314ar9300_crdc_avg_rssi(struct ath_hal *ah, int chain)
6315{
6316    int crdc_rssi_sum = 0;
6317    int crdc_rssi_ptr = ah->ah_crdc_rssi_ptr, i;
6318    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
6319    int crdc_window = ahpriv->ah_config.ath_hal_crdc_window;
6320
6321    if (crdc_window > HAL_MAX_CRDC_RSSI_SAMPLE) {
6322        crdc_window = HAL_MAX_CRDC_RSSI_SAMPLE;
6323    }
6324
6325    for (i = 1; i <= crdc_window; i++) {
6326        crdc_rssi_sum +=
6327            ah->ah_crdc_rssi_sample[chain]
6328            [(crdc_rssi_ptr - i) % HAL_MAX_CRDC_RSSI_SAMPLE];
6329    }
6330
6331    return crdc_rssi_sum / crdc_window;
6332}
6333
6334static void
6335ar9300_crdc_activate(struct ath_hal *ah, int rssi_diff, int enable)
6336{
6337    int val, orig_val;
6338    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
6339    int crdc_numerator = ahpriv->ah_config.ath_hal_crdc_numerator;
6340    int crdc_denominator = ahpriv->ah_config.ath_hal_crdc_denominator;
6341    int c = (rssi_diff * crdc_numerator) / crdc_denominator;
6342
6343    val = orig_val = OS_REG_READ(ah, AR_PHY_MULTICHAIN_CTRL);
6344    val &= 0xffffff00;
6345    if (enable) {
6346        val |= 0x1;
6347        val |= ((c << 1) & 0xff);
6348    }
6349    OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_CTRL, val);
6350    HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "diff: %02d comp: %02d reg: %08x %08x\n",
6351        rssi_diff, c, orig_val, val);
6352}
6353
6354
6355void ar9300_chain_rssi_diff_compensation(struct ath_hal *ah)
6356{
6357    struct ath_hal_private  *ahpriv = AH_PRIVATE(ah);
6358    int crdc_window = ahpriv->ah_config.ath_hal_crdc_window;
6359    int crdc_rssi_ptr = ah->ah_crdc_rssi_ptr;
6360    int crdc_rssi_thresh = ahpriv->ah_config.ath_hal_crdc_rssithresh;
6361    int crdc_diff_thresh = ahpriv->ah_config.ath_hal_crdc_diffthresh;
6362    int avg_rssi[2], avg_rssi_diff;
6363
6364    if ((!AR_SREV_WASP(ah)) ||
6365        (!ahpriv->ah_config.ath_hal_crdc_enable)) {
6366        if (ah->ah_crdc_rssi_ptr) {
6367            ar9300_crdc_activate(ah, 0, 0);
6368            ah->ah_crdc_rssi_ptr = 0;
6369        }
6370        return;
6371    }
6372
6373    if (crdc_window > HAL_MAX_CRDC_RSSI_SAMPLE) {
6374        crdc_window = HAL_MAX_CRDC_RSSI_SAMPLE;
6375    }
6376
6377    if (crdc_rssi_ptr < crdc_window) {
6378        return;
6379    }
6380
6381    avg_rssi[0] = ar9300_crdc_avg_rssi(ah, 0);
6382    avg_rssi[1] = ar9300_crdc_avg_rssi(ah, 1);
6383    avg_rssi_diff = avg_rssi[1] - avg_rssi[0];
6384
6385    HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "crdc: avg: %02d %02d ",
6386        avg_rssi[0], avg_rssi[1]);
6387
6388    if ((avg_rssi[0] < crdc_rssi_thresh) &&
6389        (avg_rssi[1] < crdc_rssi_thresh)) {
6390        ar9300_crdc_activate(ah, 0, 0);
6391    } else {
6392        if (ABS(avg_rssi_diff) >= crdc_diff_thresh) {
6393            ar9300_crdc_activate(ah, avg_rssi_diff, 1);
6394        } else {
6395            ar9300_crdc_activate(ah, 0, 1);
6396        }
6397    }
6398}
6399#endif
6400
6401#if ATH_ANT_DIV_COMB
6402HAL_BOOL
6403ar9300_ant_ctrl_set_lna_div_use_bt_ant(struct ath_hal *ah, HAL_BOOL enable, const struct ieee80211_channel *chan)
6404{
6405    u_int32_t value;
6406    u_int32_t regval;
6407    struct ath_hal_9300 *ahp = AH9300(ah);
6408    HAL_CHANNEL_INTERNAL *ichan;
6409    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
6410    HAL_CAPABILITIES *pcap = &ahpriv->ah_caps;
6411
6412    HALDEBUG(ah, HAL_DEBUG_RESET | HAL_DEBUG_BT_COEX,
6413      "%s: called; enable=%d\n", __func__, enable);
6414
6415    if (AR_SREV_POSEIDON(ah)) {
6416        // Make sure this scheme is only used for WB225(Astra)
6417        ahp->ah_lna_div_use_bt_ant_enable = enable;
6418
6419        ichan = ar9300_check_chan(ah, chan);
6420        if ( ichan == AH_NULL ) {
6421            HALDEBUG(ah, HAL_DEBUG_CHANNEL, "%s: invalid channel %u/0x%x; no mapping\n",
6422                     __func__, chan->ic_freq, chan->ic_flags);
6423            return AH_FALSE;
6424        }
6425
6426        if ( enable == TRUE ) {
6427            pcap->halAntDivCombSupport = TRUE;
6428        } else {
6429            pcap->halAntDivCombSupport = pcap->halAntDivCombSupportOrg;
6430        }
6431
6432#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
6433#define AR_SWITCH_TABLE_COM2_ALL_S (0)
6434        value = ar9300_ant_ctrl_common2_get(ah, IS_CHAN_2GHZ(ichan));
6435        if ( enable == TRUE ) {
6436            value &= ~AR_SWITCH_TABLE_COM2_ALL;
6437            value |= ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable;
6438        }
6439	HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, value);
6440        OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
6441
6442        value = ar9300_eeprom_get(ahp, EEP_ANTDIV_control);
6443        /* main_lnaconf, alt_lnaconf, main_tb, alt_tb */
6444        regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
6445        regval &= (~ANT_DIV_CONTROL_ALL); /* clear bit 25~30 */
6446        regval |= (value & 0x3f) << ANT_DIV_CONTROL_ALL_S;
6447        /* enable_lnadiv */
6448        regval &= (~MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__MASK);
6449        regval |= ((value >> 6) & 0x1) <<
6450                  MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__SHIFT;
6451        if ( enable == TRUE ) {
6452            regval |= ANT_DIV_ENABLE;
6453        }
6454        OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
6455
6456        /* enable fast_div */
6457        regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
6458        regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK);
6459        regval |= ((value >> 7) & 0x1) <<
6460                  BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__SHIFT;
6461        if ( enable == TRUE ) {
6462            regval |= FAST_DIV_ENABLE;
6463        }
6464        OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
6465
6466        if ( AR_SREV_POSEIDON_11_OR_LATER(ah) ) {
6467            if (pcap->halAntDivCombSupport) {
6468                /* If support DivComb, set MAIN to LNA1 and ALT to LNA2 at the first beginning */
6469                regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
6470                /* clear bit 25~30 main_lnaconf, alt_lnaconf, main_tb, alt_tb */
6471                regval &= (~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK |
6472                             MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK |
6473                             MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK |
6474                             MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK));
6475                regval |= (HAL_ANT_DIV_COMB_LNA1 <<
6476                           MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT);
6477                regval |= (HAL_ANT_DIV_COMB_LNA2 <<
6478                           MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT);
6479                OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
6480            }
6481        }
6482
6483        return AH_TRUE;
6484    } else if (AR_SREV_APHRODITE(ah)) {
6485        ahp->ah_lna_div_use_bt_ant_enable = enable;
6486        if (enable) {
6487                OS_REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, ANT_DIV_ENABLE);
6488                OS_REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, (1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT));
6489                OS_REG_SET_BIT(ah, AR_PHY_CCK_DETECT, AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
6490                OS_REG_SET_BIT(ah, AR_PHY_RESTART, RESTART__ENABLE_ANT_FAST_DIV_M2FLAG__MASK);
6491                OS_REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
6492        } else {
6493                OS_REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, ANT_DIV_ENABLE);
6494                OS_REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, (1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT));
6495                OS_REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
6496                OS_REG_CLR_BIT(ah, AR_PHY_RESTART, RESTART__ENABLE_ANT_FAST_DIV_M2FLAG__MASK);
6497                OS_REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
6498
6499                regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
6500                regval &= (~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK |
6501                             MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK |
6502                             MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK |
6503                             MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK));
6504                regval |= (HAL_ANT_DIV_COMB_LNA1 <<
6505                           MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT);
6506                regval |= (HAL_ANT_DIV_COMB_LNA2 <<
6507                           MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT);
6508
6509                OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
6510        }
6511        return AH_TRUE;
6512    }
6513    return AH_TRUE;
6514}
6515#endif /* ATH_ANT_DIV_COMB */
6516