Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2008-2011 Atheros Communications Inc.
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 /**
0018  * DOC: Programming Atheros 802.11n analog front end radios
0019  *
0020  * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express
0021  * devices have either an external AR2133 analog front end radio for single
0022  * band 2.4 GHz communication or an AR5133 analog front end radio for dual
0023  * band 2.4 GHz / 5 GHz communication.
0024  *
0025  * All devices after the AR5416 and AR5418 family starting with the AR9280
0026  * have their analog front radios, MAC/BB and host PCIe/USB interface embedded
0027  * into a single-chip and require less programming.
0028  *
0029  * The following single-chips exist with a respective embedded radio:
0030  *
0031  * AR9280 - 11n dual-band 2x2 MIMO for PCIe
0032  * AR9281 - 11n single-band 1x2 MIMO for PCIe
0033  * AR9285 - 11n single-band 1x1 for PCIe
0034  * AR9287 - 11n single-band 2x2 MIMO for PCIe
0035  *
0036  * AR9220 - 11n dual-band 2x2 MIMO for PCI
0037  * AR9223 - 11n single-band 2x2 MIMO for PCI
0038  *
0039  * AR9287 - 11n single-band 1x1 MIMO for USB
0040  */
0041 
0042 #include "hw.h"
0043 #include "ar9002_phy.h"
0044 
0045 /**
0046  * ar9002_hw_set_channel - set channel on single-chip device
0047  * @ah: atheros hardware structure
0048  * @chan:
0049  *
0050  * This is the function to change channel on single-chip devices, that is
0051  * all devices after ar9280.
0052  *
0053  * This function takes the channel value in MHz and sets
0054  * hardware channel value. Assumes writes have been enabled to analog bus.
0055  *
0056  * Actual Expression,
0057  *
0058  * For 2GHz channel,
0059  * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
0060  * (freq_ref = 40MHz)
0061  *
0062  * For 5GHz channel,
0063  * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
0064  * (freq_ref = 40MHz/(24>>amodeRefSel))
0065  */
0066 static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
0067 {
0068     u16 bMode, fracMode, aModeRefSel = 0;
0069     u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
0070     struct chan_centers centers;
0071     u32 refDivA = 24;
0072 
0073     ath9k_hw_get_channel_centers(ah, chan, &centers);
0074     freq = centers.synth_center;
0075 
0076     reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
0077     reg32 &= 0xc0000000;
0078 
0079     if (freq < 4800) { /* 2 GHz, fractional mode */
0080         u32 txctl;
0081         int regWrites = 0;
0082 
0083         bMode = 1;
0084         fracMode = 1;
0085         aModeRefSel = 0;
0086         channelSel = CHANSEL_2G(freq);
0087 
0088         if (AR_SREV_9287_11_OR_LATER(ah)) {
0089             if (freq == 2484) {
0090                 /* Enable channel spreading for channel 14 */
0091                 REG_WRITE_ARRAY(&ah->iniCckfirJapan2484,
0092                         1, regWrites);
0093             } else {
0094                 REG_WRITE_ARRAY(&ah->iniCckfirNormal,
0095                         1, regWrites);
0096             }
0097         } else {
0098             txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
0099             if (freq == 2484) {
0100                 /* Enable channel spreading for channel 14 */
0101                 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
0102                       txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
0103             } else {
0104                 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
0105                       txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
0106             }
0107         }
0108     } else {
0109         bMode = 0;
0110         fracMode = 0;
0111 
0112         switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
0113         case 0:
0114             if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
0115                 aModeRefSel = 0;
0116             else if ((freq % 20) == 0)
0117                 aModeRefSel = 3;
0118             else if ((freq % 10) == 0)
0119                 aModeRefSel = 2;
0120             if (aModeRefSel)
0121                 break;
0122             fallthrough;
0123         case 1:
0124         default:
0125             aModeRefSel = 0;
0126             /*
0127              * Enable 2G (fractional) mode for channels
0128              * which are 5MHz spaced.
0129              */
0130             fracMode = 1;
0131             refDivA = 1;
0132             channelSel = CHANSEL_5G(freq);
0133 
0134             /* RefDivA setting */
0135             ath9k_hw_analog_shift_rmw(ah, AR_AN_SYNTH9,
0136                       AR_AN_SYNTH9_REFDIVA,
0137                       AR_AN_SYNTH9_REFDIVA_S, refDivA);
0138 
0139         }
0140 
0141         if (!fracMode) {
0142             ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
0143             channelSel = ndiv & 0x1ff;
0144             channelFrac = (ndiv & 0xfffffe00) * 2;
0145             channelSel = (channelSel << 17) | channelFrac;
0146         }
0147     }
0148 
0149     reg32 = reg32 |
0150         (bMode << 29) |
0151         (fracMode << 28) | (aModeRefSel << 26) | (channelSel);
0152 
0153     REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
0154 
0155     ah->curchan = chan;
0156 
0157     return 0;
0158 }
0159 
0160 /**
0161  * ar9002_hw_spur_mitigate - convert baseband spur frequency
0162  * @ah: atheros hardware structure
0163  * @chan:
0164  *
0165  * For single-chip solutions. Converts to baseband spur frequency given the
0166  * input channel frequency and compute register settings below.
0167  */
0168 static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
0169                     struct ath9k_channel *chan)
0170 {
0171     int bb_spur = AR_NO_SPUR;
0172     int freq;
0173     int bin;
0174     int bb_spur_off, spur_subchannel_sd;
0175     int spur_freq_sd;
0176     int spur_delta_phase;
0177     int denominator;
0178     int tmp, newVal;
0179     int i;
0180     struct chan_centers centers;
0181 
0182     int cur_bb_spur;
0183     bool is2GHz = IS_CHAN_2GHZ(chan);
0184 
0185     ath9k_hw_get_channel_centers(ah, chan, &centers);
0186     freq = centers.synth_center;
0187 
0188     for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
0189         cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
0190 
0191         if (AR_NO_SPUR == cur_bb_spur)
0192             break;
0193 
0194         if (is2GHz)
0195             cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
0196         else
0197             cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
0198 
0199         cur_bb_spur = cur_bb_spur - freq;
0200 
0201         if (IS_CHAN_HT40(chan)) {
0202             if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
0203                 (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
0204                 bb_spur = cur_bb_spur;
0205                 break;
0206             }
0207         } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
0208                (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
0209             bb_spur = cur_bb_spur;
0210             break;
0211         }
0212     }
0213 
0214     if (AR_NO_SPUR == bb_spur) {
0215         REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
0216                 AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
0217         return;
0218     } else {
0219         REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
0220                 AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
0221     }
0222 
0223     bin = bb_spur * 320;
0224 
0225     tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
0226 
0227     ENABLE_REGWRITE_BUFFER(ah);
0228 
0229     newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
0230             AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
0231             AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
0232             AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
0233     REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
0234 
0235     newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
0236           AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
0237           AR_PHY_SPUR_REG_MASK_RATE_SELECT |
0238           AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
0239           SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
0240     REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
0241 
0242     if (IS_CHAN_HT40(chan)) {
0243         if (bb_spur < 0) {
0244             spur_subchannel_sd = 1;
0245             bb_spur_off = bb_spur + 10;
0246         } else {
0247             spur_subchannel_sd = 0;
0248             bb_spur_off = bb_spur - 10;
0249         }
0250     } else {
0251         spur_subchannel_sd = 0;
0252         bb_spur_off = bb_spur;
0253     }
0254 
0255     if (IS_CHAN_HT40(chan))
0256         spur_delta_phase =
0257             ((bb_spur * 262144) /
0258              10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
0259     else
0260         spur_delta_phase =
0261             ((bb_spur * 524288) /
0262              10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
0263 
0264     denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
0265     spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
0266 
0267     newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
0268           SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
0269           SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
0270     REG_WRITE(ah, AR_PHY_TIMING11, newVal);
0271 
0272     newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
0273     REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
0274 
0275     ar5008_hw_cmn_spur_mitigate(ah, chan, bin);
0276 
0277     REGWRITE_BUFFER_FLUSH(ah);
0278 }
0279 
0280 static void ar9002_olc_init(struct ath_hw *ah)
0281 {
0282     u32 i;
0283 
0284     if (!OLC_FOR_AR9280_20_LATER)
0285         return;
0286 
0287     if (OLC_FOR_AR9287_10_LATER) {
0288         REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9,
0289                 AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
0290         ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0,
0291                 AR9287_AN_TXPC0_TXPCMODE,
0292                 AR9287_AN_TXPC0_TXPCMODE_S,
0293                 AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
0294         udelay(100);
0295     } else {
0296         for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
0297             ah->originalGain[i] =
0298                 MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
0299                         AR_PHY_TX_GAIN);
0300         ah->PDADCdelta = 0;
0301     }
0302 }
0303 
0304 static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
0305                      struct ath9k_channel *chan)
0306 {
0307     int ref_div = 5;
0308     int pll_div = 0x2c;
0309     u32 pll;
0310 
0311     if (chan && IS_CHAN_5GHZ(chan) && !IS_CHAN_A_FAST_CLOCK(ah, chan)) {
0312         if (AR_SREV_9280_20(ah)) {
0313             ref_div = 10;
0314             pll_div = 0x50;
0315         } else {
0316             pll_div = 0x28;
0317         }
0318     }
0319 
0320     pll = SM(ref_div, AR_RTC_9160_PLL_REFDIV);
0321     pll |= SM(pll_div, AR_RTC_9160_PLL_DIV);
0322 
0323     if (chan && IS_CHAN_HALF_RATE(chan))
0324         pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
0325     else if (chan && IS_CHAN_QUARTER_RATE(chan))
0326         pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
0327 
0328     return pll;
0329 }
0330 
0331 static void ar9002_hw_do_getnf(struct ath_hw *ah,
0332                   int16_t nfarray[NUM_NF_READINGS])
0333 {
0334     int16_t nf;
0335 
0336     nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
0337     nfarray[0] = sign_extend32(nf, 8);
0338 
0339     nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
0340     if (IS_CHAN_HT40(ah->curchan))
0341         nfarray[3] = sign_extend32(nf, 8);
0342 
0343     if (!(ah->rxchainmask & BIT(1)))
0344         return;
0345 
0346     nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
0347     nfarray[1] = sign_extend32(nf, 8);
0348 
0349     nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
0350     if (IS_CHAN_HT40(ah->curchan))
0351         nfarray[4] = sign_extend32(nf, 8);
0352 }
0353 
0354 static void ar9002_hw_set_nf_limits(struct ath_hw *ah)
0355 {
0356     if (AR_SREV_9285(ah)) {
0357         ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ;
0358         ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ;
0359         ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ;
0360     } else if (AR_SREV_9287(ah)) {
0361         ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ;
0362         ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ;
0363         ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ;
0364     } else if (AR_SREV_9271(ah)) {
0365         ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ;
0366         ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ;
0367         ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9271_2GHZ;
0368     } else {
0369         ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ;
0370         ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ;
0371         ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ;
0372         ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ;
0373         ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ;
0374         ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ;
0375     }
0376 }
0377 
0378 static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah,
0379                    struct ath_hw_antcomb_conf *antconf)
0380 {
0381     u32 regval;
0382 
0383     regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
0384     antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >>
0385                   AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S;
0386     antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >>
0387                  AR_PHY_9285_ANT_DIV_ALT_LNACONF_S;
0388     antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >>
0389                   AR_PHY_9285_FAST_DIV_BIAS_S;
0390     antconf->lna1_lna2_switch_delta = -1;
0391     antconf->lna1_lna2_delta = -3;
0392     antconf->div_group = 0;
0393 }
0394 
0395 static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah,
0396                    struct ath_hw_antcomb_conf *antconf)
0397 {
0398     u32 regval;
0399 
0400     regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
0401     regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF |
0402             AR_PHY_9285_ANT_DIV_ALT_LNACONF |
0403             AR_PHY_9285_FAST_DIV_BIAS);
0404     regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S)
0405            & AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
0406     regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S)
0407            & AR_PHY_9285_ANT_DIV_ALT_LNACONF);
0408     regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S)
0409            & AR_PHY_9285_FAST_DIV_BIAS);
0410 
0411     REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
0412 }
0413 
0414 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
0415 
0416 static void ar9002_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
0417 {
0418     struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
0419     u8 antdiv_ctrl1, antdiv_ctrl2;
0420     u32 regval;
0421 
0422     if (enable) {
0423         antdiv_ctrl1 = ATH_BT_COEX_ANTDIV_CONTROL1_ENABLE;
0424         antdiv_ctrl2 = ATH_BT_COEX_ANTDIV_CONTROL2_ENABLE;
0425 
0426         /*
0427          * Don't disable BT ant to allow BB to control SWCOM.
0428          */
0429         btcoex->bt_coex_mode2 &= (~(AR_BT_DISABLE_BT_ANT));
0430         REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2);
0431 
0432         REG_WRITE(ah, AR_PHY_SWITCH_COM, ATH_BT_COEX_ANT_DIV_SWITCH_COM);
0433         REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000);
0434     } else {
0435         /*
0436          * Disable antenna diversity, use LNA1 only.
0437          */
0438         antdiv_ctrl1 = ATH_BT_COEX_ANTDIV_CONTROL1_FIXED_A;
0439         antdiv_ctrl2 = ATH_BT_COEX_ANTDIV_CONTROL2_FIXED_A;
0440 
0441         /*
0442          * Disable BT Ant. to allow concurrent BT and WLAN receive.
0443          */
0444         btcoex->bt_coex_mode2 |= AR_BT_DISABLE_BT_ANT;
0445         REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2);
0446 
0447         /*
0448          * Program SWCOM table to make sure RF switch always parks
0449          * at BT side.
0450          */
0451         REG_WRITE(ah, AR_PHY_SWITCH_COM, 0);
0452         REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000);
0453     }
0454 
0455     regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
0456     regval &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
0457         /*
0458      * Clear ant_fast_div_bias [14:9] since for WB195,
0459      * the main LNA is always LNA1.
0460      */
0461     regval &= (~(AR_PHY_9285_FAST_DIV_BIAS));
0462     regval |= SM(antdiv_ctrl1, AR_PHY_9285_ANT_DIV_CTL);
0463     regval |= SM(antdiv_ctrl2, AR_PHY_9285_ANT_DIV_ALT_LNACONF);
0464     regval |= SM((antdiv_ctrl2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
0465     regval |= SM((antdiv_ctrl1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB);
0466     regval |= SM((antdiv_ctrl1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
0467     REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
0468 
0469     regval = REG_READ(ah, AR_PHY_CCK_DETECT);
0470     regval &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
0471     regval |= SM((antdiv_ctrl1 >> 3), AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
0472     REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
0473 }
0474 
0475 #endif
0476 
0477 static void ar9002_hw_spectral_scan_config(struct ath_hw *ah,
0478                     struct ath_spec_scan *param)
0479 {
0480     u32 repeat_bit;
0481     u8 count;
0482 
0483     if (!param->enabled) {
0484         REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
0485                 AR_PHY_SPECTRAL_SCAN_ENABLE);
0486         return;
0487     }
0488     REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
0489     REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
0490 
0491     if (AR_SREV_9280(ah))
0492         repeat_bit = AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
0493     else
0494         repeat_bit = AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
0495 
0496     if (param->short_repeat)
0497         REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit);
0498     else
0499         REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit);
0500 
0501     /* on AR92xx, the highest bit of count will make the chip send
0502      * spectral samples endlessly. Check if this really was intended,
0503      * and fix otherwise.
0504      */
0505     count = param->count;
0506     if (param->endless) {
0507         if (AR_SREV_9280(ah))
0508             count = 0x80;
0509         else
0510             count = 0;
0511     } else if (count & 0x80)
0512         count = 0x7f;
0513     else if (!count)
0514         count = 1;
0515 
0516     if (AR_SREV_9280(ah)) {
0517         REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
0518                   AR_PHY_SPECTRAL_SCAN_COUNT, count);
0519     } else {
0520         REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
0521                   AR_PHY_SPECTRAL_SCAN_COUNT_KIWI, count);
0522         REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
0523                 AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT);
0524     }
0525 
0526     REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
0527               AR_PHY_SPECTRAL_SCAN_PERIOD, param->period);
0528     REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
0529               AR_PHY_SPECTRAL_SCAN_FFT_PERIOD, param->fft_period);
0530 
0531     return;
0532 }
0533 
0534 static void ar9002_hw_spectral_scan_trigger(struct ath_hw *ah)
0535 {
0536     REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
0537     /* Activate spectral scan */
0538     REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
0539             AR_PHY_SPECTRAL_SCAN_ACTIVE);
0540 }
0541 
0542 static void ar9002_hw_spectral_scan_wait(struct ath_hw *ah)
0543 {
0544     struct ath_common *common = ath9k_hw_common(ah);
0545 
0546     /* Poll for spectral scan complete */
0547     if (!ath9k_hw_wait(ah, AR_PHY_SPECTRAL_SCAN,
0548                AR_PHY_SPECTRAL_SCAN_ACTIVE,
0549                0, AH_WAIT_TIMEOUT)) {
0550         ath_err(common, "spectral scan wait failed\n");
0551         return;
0552     }
0553 }
0554 
0555 static void ar9002_hw_tx99_start(struct ath_hw *ah, u32 qnum)
0556 {
0557     REG_SET_BIT(ah, 0x9864, 0x7f000);
0558     REG_SET_BIT(ah, 0x9924, 0x7f00fe);
0559     REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
0560     REG_WRITE(ah, AR_CR, AR_CR_RXD);
0561     REG_WRITE(ah, AR_DLCL_IFS(qnum), 0);
0562     REG_WRITE(ah, AR_D_GBL_IFS_SIFS, 20);
0563     REG_WRITE(ah, AR_D_GBL_IFS_EIFS, 20);
0564     REG_WRITE(ah, AR_D_FPCTL, 0x10|qnum);
0565     REG_WRITE(ah, AR_TIME_OUT, 0x00000400);
0566     REG_WRITE(ah, AR_DRETRY_LIMIT(qnum), 0xffffffff);
0567     REG_SET_BIT(ah, AR_QMISC(qnum), AR_Q_MISC_DCU_EARLY_TERM_REQ);
0568 }
0569 
0570 static void ar9002_hw_tx99_stop(struct ath_hw *ah)
0571 {
0572     REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
0573 }
0574 
0575 void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
0576 {
0577     struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
0578     struct ath_hw_ops *ops = ath9k_hw_ops(ah);
0579 
0580     priv_ops->set_rf_regs = NULL;
0581     priv_ops->rf_set_freq = ar9002_hw_set_channel;
0582     priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate;
0583     priv_ops->olc_init = ar9002_olc_init;
0584     priv_ops->compute_pll_control = ar9002_hw_compute_pll_control;
0585     priv_ops->do_getnf = ar9002_hw_do_getnf;
0586 
0587     ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get;
0588     ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set;
0589     ops->spectral_scan_config = ar9002_hw_spectral_scan_config;
0590     ops->spectral_scan_trigger = ar9002_hw_spectral_scan_trigger;
0591     ops->spectral_scan_wait = ar9002_hw_spectral_scan_wait;
0592 
0593 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
0594     ops->set_bt_ant_diversity = ar9002_hw_set_bt_ant_diversity;
0595 #endif
0596     ops->tx99_start = ar9002_hw_tx99_start;
0597     ops->tx99_stop = ar9002_hw_tx99_stop;
0598 
0599     ar9002_hw_set_nf_limits(ah);
0600 }