iPXE
ath9k_ar9003_phy.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010-2011 Atheros Communications Inc.
00003  *
00004  * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
00005  * Original from Linux kernel 3.0.1
00006  *
00007  * Permission to use, copy, modify, and/or distribute this software for any
00008  * purpose with or without fee is hereby granted, provided that the above
00009  * copyright notice and this permission notice appear in all copies.
00010  *
00011  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00012  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00013  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00014  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00015  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00016  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00017  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00018  */
00019 
00020 #include <ipxe/io.h>
00021 
00022 #include "hw.h"
00023 #include "ar9003_phy.h"
00024 
00025 static const int firstep_table[] =
00026 /* level:  0   1   2   3   4   5   6   7   8  */
00027         { -4, -2,  0,  2,  4,  6,  8, 10, 12 }; /* lvl 0-8, default 2 */
00028 
00029 static const int cycpwrThr1_table[] =
00030 /* level:  0   1   2   3   4   5   6   7   8  */
00031         { -6, -4, -2,  0,  2,  4,  6,  8 };     /* lvl 0-7, default 3 */
00032 
00033 /*
00034  * register values to turn OFDM weak signal detection OFF
00035  */
00036 static const int m1ThreshLow_off = 127;
00037 static const int m2ThreshLow_off = 127;
00038 static const int m1Thresh_off = 127;
00039 static const int m2Thresh_off = 127;
00040 static const int m2CountThr_off =  31;
00041 static const int m2CountThrLow_off =  63;
00042 static const int m1ThreshLowExt_off = 127;
00043 static const int m2ThreshLowExt_off = 127;
00044 static const int m1ThreshExt_off = 127;
00045 static const int m2ThreshExt_off = 127;
00046 
00047 /**
00048  * ar9003_hw_set_channel - set channel on single-chip device
00049  * @ah: atheros hardware structure
00050  * @chan:
00051  *
00052  * This is the function to change channel on single-chip devices, that is
00053  * all devices after ar9280.
00054  *
00055  * This function takes the channel value in MHz and sets
00056  * hardware channel value. Assumes writes have been enabled to analog bus.
00057  *
00058  * Actual Expression,
00059  *
00060  * For 2GHz channel,
00061  * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
00062  * (freq_ref = 40MHz)
00063  *
00064  * For 5GHz channel,
00065  * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
00066  * (freq_ref = 40MHz/(24>>amodeRefSel))
00067  *
00068  * For 5GHz channels which are 5MHz spaced,
00069  * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
00070  * (freq_ref = 40MHz)
00071  */
00072 static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
00073 {
00074         u16 bMode, fracMode = 0, aModeRefSel = 0;
00075         u32 freq, channelSel = 0, reg32 = 0;
00076         struct chan_centers centers;
00077         int loadSynthChannel;
00078 
00079         ath9k_hw_get_channel_centers(ah, chan, &centers);
00080         freq = centers.synth_center;
00081 
00082         if (freq < 4800) {     /* 2 GHz, fractional mode */
00083                 if (AR_SREV_9485(ah)) {
00084                         u32 chan_frac;
00085 
00086                         /*
00087                          * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0
00088                          * ndiv = ((chan_mhz * 4) / 3) / freq_ref;
00089                          * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000
00090                          */
00091                         channelSel = (freq * 4) / 120;
00092                         chan_frac = (((freq * 4) % 120) * 0x20000) / 120;
00093                         channelSel = (channelSel << 17) | chan_frac;
00094                 } else if (AR_SREV_9340(ah)) {
00095                         if (ah->is_clk_25mhz) {
00096                                 u32 chan_frac;
00097 
00098                                 channelSel = (freq * 2) / 75;
00099                                 chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
00100                                 channelSel = (channelSel << 17) | chan_frac;
00101                         } else
00102                                 channelSel = CHANSEL_2G(freq) >> 1;
00103                 } else
00104                         channelSel = CHANSEL_2G(freq);
00105                 /* Set to 2G mode */
00106                 bMode = 1;
00107         } else {
00108                 if (AR_SREV_9340(ah) && ah->is_clk_25mhz) {
00109                         u32 chan_frac;
00110 
00111                         channelSel = (freq * 2) / 75;
00112                         chan_frac = ((freq % 75) * 0x20000) / 75;
00113                         channelSel = (channelSel << 17) | chan_frac;
00114                 } else {
00115                         channelSel = CHANSEL_5G(freq);
00116                         /* Doubler is ON, so, divide channelSel by 2. */
00117                         channelSel >>= 1;
00118                 }
00119                 /* Set to 5G mode */
00120                 bMode = 0;
00121         }
00122 
00123         /* Enable fractional mode for all channels */
00124         fracMode = 1;
00125         aModeRefSel = 0;
00126         loadSynthChannel = 0;
00127 
00128         reg32 = (bMode << 29);
00129         REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
00130 
00131         /* Enable Long shift Select for Synthesizer */
00132         REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH4,
00133                       AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1);
00134 
00135         /* Program Synth. setting */
00136         reg32 = (channelSel << 2) | (fracMode << 30) |
00137                 (aModeRefSel << 28) | (loadSynthChannel << 31);
00138         REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
00139 
00140         /* Toggle Load Synth channel bit */
00141         loadSynthChannel = 1;
00142         reg32 = (channelSel << 2) | (fracMode << 30) |
00143                 (aModeRefSel << 28) | (loadSynthChannel << 31);
00144         REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
00145 
00146         ah->curchan = chan;
00147         ah->curchan_rad_index = -1;
00148 
00149         return 0;
00150 }
00151 
00152 /**
00153  * ar9003_hw_spur_mitigate_mrc_cck - convert baseband spur frequency
00154  * @ah: atheros hardware structure
00155  * @chan:
00156  *
00157  * For single-chip solutions. Converts to baseband spur frequency given the
00158  * input channel frequency and compute register settings below.
00159  *
00160  * Spur mitigation for MRC CCK
00161  */
00162 static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
00163                                             struct ath9k_channel *chan)
00164 {
00165         static const u32 spur_freq[4] = { 2420, 2440, 2464, 2480 };
00166         int cur_bb_spur, negative = 0, cck_spur_freq;
00167         int i;
00168         int range, max_spur_cnts, synth_freq;
00169         u8 *spur_fbin_ptr = NULL;
00170 
00171         /*
00172          * Need to verify range +/- 10 MHz in control channel, otherwise spur
00173          * is out-of-band and can be ignored.
00174          */
00175 
00176         if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) {
00177                 spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
00178                                                          IS_CHAN_2GHZ(chan));
00179                 if (spur_fbin_ptr[0] == 0) /* No spur */
00180                         return;
00181                 max_spur_cnts = 5;
00182                 if (IS_CHAN_HT40(chan)) {
00183                         range = 19;
00184                         if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
00185                                            AR_PHY_GC_DYN2040_PRI_CH) == 0)
00186                                 synth_freq = chan->channel + 10;
00187                         else
00188                                 synth_freq = chan->channel - 10;
00189                 } else {
00190                         range = 10;
00191                         synth_freq = chan->channel;
00192                 }
00193         } else {
00194                 range = 10;
00195                 max_spur_cnts = 4;
00196                 synth_freq = chan->channel;
00197         }
00198 
00199         for (i = 0; i < max_spur_cnts; i++) {
00200                 negative = 0;
00201                 if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
00202                         cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
00203                                         IS_CHAN_2GHZ(chan)) - synth_freq;
00204                 else
00205                         cur_bb_spur = spur_freq[i] - synth_freq;
00206 
00207                 if (cur_bb_spur < 0) {
00208                         negative = 1;
00209                         cur_bb_spur = -cur_bb_spur;
00210                 }
00211                 if (cur_bb_spur < range) {
00212                         cck_spur_freq = (int)((cur_bb_spur << 19) / 11);
00213 
00214                         if (negative == 1)
00215                                 cck_spur_freq = -cck_spur_freq;
00216 
00217                         cck_spur_freq = cck_spur_freq & 0xfffff;
00218 
00219                         REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL,
00220                                       AR_PHY_AGC_CONTROL_YCOK_MAX, 0x7);
00221                         REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
00222                                       AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR, 0x7f);
00223                         REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
00224                                       AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE,
00225                                       0x2);
00226                         REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
00227                                       AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT,
00228                                       0x1);
00229                         REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
00230                                       AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ,
00231                                       cck_spur_freq);
00232 
00233                         return;
00234                 }
00235         }
00236 
00237         REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL,
00238                       AR_PHY_AGC_CONTROL_YCOK_MAX, 0x5);
00239         REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
00240                       AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, 0x0);
00241         REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT,
00242                       AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0x0);
00243 }
00244 
00245 /* Clean all spur register fields */
00246 static void ar9003_hw_spur_ofdm_clear(struct ath_hw *ah)
00247 {
00248         REG_RMW_FIELD(ah, AR_PHY_TIMING4,
00249                       AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0);
00250         REG_RMW_FIELD(ah, AR_PHY_TIMING11,
00251                       AR_PHY_TIMING11_SPUR_FREQ_SD, 0);
00252         REG_RMW_FIELD(ah, AR_PHY_TIMING11,
00253                       AR_PHY_TIMING11_SPUR_DELTA_PHASE, 0);
00254         REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
00255                       AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, 0);
00256         REG_RMW_FIELD(ah, AR_PHY_TIMING11,
00257                       AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0);
00258         REG_RMW_FIELD(ah, AR_PHY_TIMING11,
00259                       AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0);
00260         REG_RMW_FIELD(ah, AR_PHY_TIMING4,
00261                       AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0);
00262         REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
00263                       AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 0);
00264         REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
00265                       AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 0);
00266 
00267         REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
00268                       AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0);
00269         REG_RMW_FIELD(ah, AR_PHY_TIMING4,
00270                       AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0);
00271         REG_RMW_FIELD(ah, AR_PHY_TIMING4,
00272                       AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0);
00273         REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
00274                       AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, 0);
00275         REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
00276                       AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, 0);
00277         REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
00278                       AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, 0);
00279         REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
00280                       AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0);
00281         REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
00282                       AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0);
00283         REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
00284                       AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0);
00285         REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
00286                       AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0);
00287 }
00288 
00289 static void ar9003_hw_spur_ofdm(struct ath_hw *ah,
00290                                 int freq_offset,
00291                                 int spur_freq_sd,
00292                                 int spur_delta_phase,
00293                                 int spur_subchannel_sd)
00294 {
00295         int mask_index = 0;
00296 
00297         /* OFDM Spur mitigation */
00298         REG_RMW_FIELD(ah, AR_PHY_TIMING4,
00299                  AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0x1);
00300         REG_RMW_FIELD(ah, AR_PHY_TIMING11,
00301                       AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd);
00302         REG_RMW_FIELD(ah, AR_PHY_TIMING11,
00303                       AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase);
00304         REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
00305                       AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, spur_subchannel_sd);
00306         REG_RMW_FIELD(ah, AR_PHY_TIMING11,
00307                       AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1);
00308         REG_RMW_FIELD(ah, AR_PHY_TIMING11,
00309                       AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0x1);
00310         REG_RMW_FIELD(ah, AR_PHY_TIMING4,
00311                       AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1);
00312         REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
00313                       AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34);
00314         REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
00315                       AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1);
00316 
00317         if (REG_READ_FIELD(ah, AR_PHY_MODE,
00318                            AR_PHY_MODE_DYNAMIC) == 0x1)
00319                 REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
00320                               AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1);
00321 
00322         mask_index = (freq_offset << 4) / 5;
00323         if (mask_index < 0)
00324                 mask_index = mask_index - 1;
00325 
00326         mask_index = mask_index & 0x7f;
00327 
00328         REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
00329                       AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0x1);
00330         REG_RMW_FIELD(ah, AR_PHY_TIMING4,
00331                       AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0x1);
00332         REG_RMW_FIELD(ah, AR_PHY_TIMING4,
00333                       AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0x1);
00334         REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
00335                       AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, mask_index);
00336         REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
00337                       AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, mask_index);
00338         REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
00339                       AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, mask_index);
00340         REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK,
00341                       AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0xc);
00342         REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK,
00343                       AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0xc);
00344         REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A,
00345                       AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0);
00346         REG_RMW_FIELD(ah, AR_PHY_SPUR_REG,
00347                       AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff);
00348 }
00349 
00350 static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
00351                                      struct ath9k_channel *chan,
00352                                      int freq_offset)
00353 {
00354         int spur_freq_sd = 0;
00355         int spur_subchannel_sd = 0;
00356         int spur_delta_phase = 0;
00357 
00358         if (IS_CHAN_HT40(chan)) {
00359                 if (freq_offset < 0) {
00360                         if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
00361                                            AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
00362                                 spur_subchannel_sd = 1;
00363                         else
00364                                 spur_subchannel_sd = 0;
00365 
00366                         spur_freq_sd = ((freq_offset + 10) << 9) / 11;
00367 
00368                 } else {
00369                         if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
00370                             AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
00371                                 spur_subchannel_sd = 0;
00372                         else
00373                                 spur_subchannel_sd = 1;
00374 
00375                         spur_freq_sd = ((freq_offset - 10) << 9) / 11;
00376 
00377                 }
00378 
00379                 spur_delta_phase = (freq_offset << 17) / 5;
00380 
00381         } else {
00382                 spur_subchannel_sd = 0;
00383                 spur_freq_sd = (freq_offset << 9) /11;
00384                 spur_delta_phase = (freq_offset << 18) / 5;
00385         }
00386 
00387         spur_freq_sd = spur_freq_sd & 0x3ff;
00388         spur_delta_phase = spur_delta_phase & 0xfffff;
00389 
00390         ar9003_hw_spur_ofdm(ah,
00391                             freq_offset,
00392                             spur_freq_sd,
00393                             spur_delta_phase,
00394                             spur_subchannel_sd);
00395 }
00396 
00397 /* Spur mitigation for OFDM */
00398 static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,
00399                                          struct ath9k_channel *chan)
00400 {
00401         int synth_freq;
00402         int range = 10;
00403         int freq_offset = 0;
00404         int mode;
00405         u8* spurChansPtr;
00406         unsigned int i;
00407         struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
00408 
00409         if (IS_CHAN_5GHZ(chan)) {
00410                 spurChansPtr = &(eep->modalHeader5G.spurChans[0]);
00411                 mode = 0;
00412         }
00413         else {
00414                 spurChansPtr = &(eep->modalHeader2G.spurChans[0]);
00415                 mode = 1;
00416         }
00417 
00418         if (spurChansPtr[0] == 0)
00419                 return; /* No spur in the mode */
00420 
00421         if (IS_CHAN_HT40(chan)) {
00422                 range = 19;
00423                 if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
00424                                    AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
00425                         synth_freq = chan->channel - 10;
00426                 else
00427                         synth_freq = chan->channel + 10;
00428         } else {
00429                 range = 10;
00430                 synth_freq = chan->channel;
00431         }
00432 
00433         ar9003_hw_spur_ofdm_clear(ah);
00434 
00435         for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) {
00436                 freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq;
00437                 if (abs(freq_offset) < range) {
00438                         ar9003_hw_spur_ofdm_work(ah, chan, freq_offset);
00439                         break;
00440                 }
00441         }
00442 }
00443 
00444 static void ar9003_hw_spur_mitigate(struct ath_hw *ah,
00445                                     struct ath9k_channel *chan)
00446 {
00447         ar9003_hw_spur_mitigate_mrc_cck(ah, chan);
00448         ar9003_hw_spur_mitigate_ofdm(ah, chan);
00449 }
00450 
00451 static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah __unused,
00452                                          struct ath9k_channel *chan)
00453 {
00454         u32 pll;
00455 
00456         pll = SM(0x5, AR_RTC_9300_PLL_REFDIV);
00457 
00458         if (chan && IS_CHAN_HALF_RATE(chan))
00459                 pll |= SM(0x1, AR_RTC_9300_PLL_CLKSEL);
00460         else if (chan && IS_CHAN_QUARTER_RATE(chan))
00461                 pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL);
00462 
00463         pll |= SM(0x2c, AR_RTC_9300_PLL_DIV);
00464 
00465         return pll;
00466 }
00467 
00468 static void ar9003_hw_set_channel_regs(struct ath_hw *ah,
00469                                        struct ath9k_channel *chan)
00470 {
00471         u32 phymode;
00472         u32 enableDacFifo = 0;
00473 
00474         enableDacFifo =
00475                 (REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);
00476 
00477         /* Enable 11n HT, 20 MHz */
00478         phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH |
00479                   AR_PHY_GC_SHORT_GI_40 | enableDacFifo;
00480 
00481         /* Configure baseband for dynamic 20/40 operation */
00482         if (IS_CHAN_HT40(chan)) {
00483                 phymode |= AR_PHY_GC_DYN2040_EN;
00484                 /* Configure control (primary) channel at +-10MHz */
00485                 if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
00486                     (chan->chanmode == CHANNEL_G_HT40PLUS))
00487                         phymode |= AR_PHY_GC_DYN2040_PRI_CH;
00488 
00489         }
00490 
00491         /* make sure we preserve INI settings */
00492         phymode |= REG_READ(ah, AR_PHY_GEN_CTRL);
00493         /* turn off Green Field detection for STA for now */
00494         phymode &= ~AR_PHY_GC_GF_DETECT_EN;
00495 
00496         REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode);
00497 
00498         /* Configure MAC for 20/40 operation */
00499         ath9k_hw_set11nmac2040(ah);
00500 
00501         /* global transmit timeout (25 TUs default)*/
00502         REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
00503         /* carrier sense timeout */
00504         REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
00505 }
00506 
00507 static void ar9003_hw_init_bb(struct ath_hw *ah,
00508                               struct ath9k_channel *chan)
00509 {
00510         u32 synthDelay;
00511 
00512         /*
00513          * Wait for the frequency synth to settle (synth goes on
00514          * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
00515          * Value is in 100ns increments.
00516          */
00517         synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
00518         if (IS_CHAN_B(chan))
00519                 synthDelay = (4 * synthDelay) / 22;
00520         else
00521                 synthDelay /= 10;
00522 
00523         /* Activate the PHY (includes baseband activate + synthesizer on) */
00524         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
00525 
00526         /*
00527          * There is an issue if the AP starts the calibration before
00528          * the base band timeout completes.  This could result in the
00529          * rx_clear false triggering.  As a workaround we add delay an
00530          * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
00531          * does not happen.
00532          */
00533         udelay(synthDelay + BASE_ACTIVATE_DELAY);
00534 }
00535 
00536 void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
00537 {
00538         switch (rx) {
00539         case 0x5:
00540                 REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
00541                             AR_PHY_SWAP_ALT_CHAIN);
00542                 /* Fall through */
00543         case 0x3:
00544         case 0x1:
00545         case 0x2:
00546         case 0x7:
00547                 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
00548                 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
00549                 break;
00550         default:
00551                 break;
00552         }
00553 
00554         if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
00555                 REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
00556         else
00557                 REG_WRITE(ah, AR_SELFGEN_MASK, tx);
00558 
00559         if (tx == 0x5) {
00560                 REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
00561                             AR_PHY_SWAP_ALT_CHAIN);
00562         }
00563 }
00564 
00565 /*
00566  * Override INI values with chip specific configuration.
00567  */
00568 static void ar9003_hw_override_ini(struct ath_hw *ah)
00569 {
00570         u32 val;
00571 
00572         /*
00573          * Set the RX_ABORT and RX_DIS and clear it only after
00574          * RXE is set for MAC. This prevents frames with
00575          * corrupted descriptor status.
00576          */
00577         REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
00578 
00579         /*
00580          * For AR9280 and above, there is a new feature that allows
00581          * Multicast search based on both MAC Address and Key ID. By default,
00582          * this feature is enabled. But since the driver is not using this
00583          * feature, we switch it off; otherwise multicast search based on
00584          * MAC addr only will fail.
00585          */
00586         val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
00587         REG_WRITE(ah, AR_PCU_MISC_MODE2,
00588                   val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
00589 }
00590 
00591 static void ar9003_hw_prog_ini(struct ath_hw *ah,
00592                                struct ar5416IniArray *iniArr,
00593                                int column)
00594 {
00595         unsigned int i, regWrites = 0;
00596 
00597         /* New INI format: Array may be undefined (pre, core, post arrays) */
00598         if (!iniArr->ia_array)
00599                 return;
00600 
00601         /*
00602          * New INI format: Pre, core, and post arrays for a given subsystem
00603          * may be modal (> 2 columns) or non-modal (2 columns). Determine if
00604          * the array is non-modal and force the column to 1.
00605          */
00606         if ((unsigned int)column >= iniArr->ia_columns)
00607                 column = 1;
00608 
00609         for (i = 0; i < iniArr->ia_rows; i++) {
00610                 u32 reg = INI_RA(iniArr, i, 0);
00611                 u32 val = INI_RA(iniArr, i, column);
00612 
00613                 REG_WRITE(ah, reg, val);
00614 
00615                 DO_DELAY(regWrites);
00616         }
00617 }
00618 
00619 static int ar9003_hw_process_ini(struct ath_hw *ah,
00620                                  struct ath9k_channel *chan)
00621 {
00622         struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
00623         unsigned int regWrites = 0, i;
00624         struct net80211_channel *channel = chan->chan;
00625         u32 modesIndex;
00626 
00627         switch (chan->chanmode) {
00628         case CHANNEL_A:
00629         case CHANNEL_A_HT20:
00630                 modesIndex = 1;
00631                 break;
00632         case CHANNEL_A_HT40PLUS:
00633         case CHANNEL_A_HT40MINUS:
00634                 modesIndex = 2;
00635                 break;
00636         case CHANNEL_G:
00637         case CHANNEL_G_HT20:
00638         case CHANNEL_B:
00639                 modesIndex = 4;
00640                 break;
00641         case CHANNEL_G_HT40PLUS:
00642         case CHANNEL_G_HT40MINUS:
00643                 modesIndex = 3;
00644                 break;
00645 
00646         default:
00647                 return -EINVAL;
00648         }
00649 
00650         for (i = 0; i < ATH_INI_NUM_SPLIT; i++) {
00651                 ar9003_hw_prog_ini(ah, &ah->iniSOC[i], modesIndex);
00652                 ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex);
00653                 ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex);
00654                 ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex);
00655         }
00656 
00657         REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
00658         REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
00659 
00660         /*
00661          * For 5GHz channels requiring Fast Clock, apply
00662          * different modal values.
00663          */
00664         if (IS_CHAN_A_FAST_CLOCK(ah, chan))
00665                 REG_WRITE_ARRAY(&ah->iniModesAdditional,
00666                                 modesIndex, regWrites);
00667 
00668         if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
00669                 REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
00670 
00671         ar9003_hw_override_ini(ah);
00672         ar9003_hw_set_channel_regs(ah, chan);
00673         ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
00674 
00675         /* Set TX power */
00676         ah->eep_ops->set_txpower(ah, chan,
00677                                  ath9k_regd_get_ctl(regulatory, chan),
00678                                  0,
00679                                  channel->maxpower * 2,
00680                                  min((u32) MAX_RATE_POWER,
00681                                  (u32) regulatory->power_limit), 0);
00682 
00683         return 0;
00684 }
00685 
00686 static void ar9003_hw_set_rfmode(struct ath_hw *ah,
00687                                  struct ath9k_channel *chan)
00688 {
00689         u32 rfMode = 0;
00690 
00691         if (chan == NULL)
00692                 return;
00693 
00694         rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
00695                 ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
00696 
00697         if (IS_CHAN_A_FAST_CLOCK(ah, chan))
00698                 rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
00699 
00700         REG_WRITE(ah, AR_PHY_MODE, rfMode);
00701 }
00702 
00703 static void ar9003_hw_mark_phy_inactive(struct ath_hw *ah)
00704 {
00705         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
00706 }
00707 
00708 static void ar9003_hw_set_delta_slope(struct ath_hw *ah,
00709                                       struct ath9k_channel *chan)
00710 {
00711         u32 coef_scaled, ds_coef_exp, ds_coef_man;
00712         u32 clockMhzScaled = 0x64000000;
00713         struct chan_centers centers;
00714 
00715         /*
00716          * half and quarter rate can divide the scaled clock by 2 or 4
00717          * scale for selected channel bandwidth
00718          */
00719         if (IS_CHAN_HALF_RATE(chan))
00720                 clockMhzScaled = clockMhzScaled >> 1;
00721         else if (IS_CHAN_QUARTER_RATE(chan))
00722                 clockMhzScaled = clockMhzScaled >> 2;
00723 
00724         /*
00725          * ALGO -> coef = 1e8/fcarrier*fclock/40;
00726          * scaled coef to provide precision for this floating calculation
00727          */
00728         ath9k_hw_get_channel_centers(ah, chan, &centers);
00729         coef_scaled = clockMhzScaled / centers.synth_center;
00730 
00731         ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
00732                                       &ds_coef_exp);
00733 
00734         REG_RMW_FIELD(ah, AR_PHY_TIMING3,
00735                       AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
00736         REG_RMW_FIELD(ah, AR_PHY_TIMING3,
00737                       AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
00738 
00739         /*
00740          * For Short GI,
00741          * scaled coeff is 9/10 that of normal coeff
00742          */
00743         coef_scaled = (9 * coef_scaled) / 10;
00744 
00745         ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
00746                                       &ds_coef_exp);
00747 
00748         /* for short gi */
00749         REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA,
00750                       AR_PHY_SGI_DSC_MAN, ds_coef_man);
00751         REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA,
00752                       AR_PHY_SGI_DSC_EXP, ds_coef_exp);
00753 }
00754 
00755 static int ar9003_hw_rfbus_req(struct ath_hw *ah)
00756 {
00757         REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
00758         return ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
00759                              AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT);
00760 }
00761 
00762 /*
00763  * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN).
00764  * Read the phy active delay register. Value is in 100ns increments.
00765  */
00766 static void ar9003_hw_rfbus_done(struct ath_hw *ah)
00767 {
00768         u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
00769         if (IS_CHAN_B(ah->curchan))
00770                 synthDelay = (4 * synthDelay) / 22;
00771         else
00772                 synthDelay /= 10;
00773 
00774         udelay(synthDelay + BASE_ACTIVATE_DELAY);
00775 
00776         REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
00777 }
00778 
00779 static void ar9003_hw_set_diversity(struct ath_hw *ah, int value)
00780 {
00781         u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
00782         if (value)
00783                 v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
00784         else
00785                 v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
00786         REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
00787 }
00788 
00789 static int ar9003_hw_ani_control(struct ath_hw *ah,
00790                                   enum ath9k_ani_cmd cmd, int param)
00791 {
00792         struct ath9k_channel *chan = ah->curchan;
00793         struct ar5416AniState *aniState = &chan->ani;
00794         s32 value, value2;
00795 
00796         switch (cmd & ah->ani_function) {
00797         case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
00798                 /*
00799                  * on == 1 means ofdm weak signal detection is ON
00800                  * on == 1 is the default, for less noise immunity
00801                  *
00802                  * on == 0 means ofdm weak signal detection is OFF
00803                  * on == 0 means more noise imm
00804                  */
00805                 u32 on = param ? 1 : 0;
00806                 /*
00807                  * make register setting for default
00808                  * (weak sig detect ON) come from INI file
00809                  */
00810                 int m1ThreshLow = on ?
00811                         aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
00812                 int m2ThreshLow = on ?
00813                         aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
00814                 int m1Thresh = on ?
00815                         aniState->iniDef.m1Thresh : m1Thresh_off;
00816                 int m2Thresh = on ?
00817                         aniState->iniDef.m2Thresh : m2Thresh_off;
00818                 int m2CountThr = on ?
00819                         aniState->iniDef.m2CountThr : m2CountThr_off;
00820                 int m2CountThrLow = on ?
00821                         aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
00822                 int m1ThreshLowExt = on ?
00823                         aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
00824                 int m2ThreshLowExt = on ?
00825                         aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
00826                 int m1ThreshExt = on ?
00827                         aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
00828                 int m2ThreshExt = on ?
00829                         aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
00830 
00831                 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
00832                               AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
00833                               m1ThreshLow);
00834                 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
00835                               AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
00836                               m2ThreshLow);
00837                 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
00838                               AR_PHY_SFCORR_M1_THRESH, m1Thresh);
00839                 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
00840                               AR_PHY_SFCORR_M2_THRESH, m2Thresh);
00841                 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
00842                               AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
00843                 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
00844                               AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
00845                               m2CountThrLow);
00846 
00847                 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
00848                               AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
00849                 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
00850                               AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
00851                 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
00852                               AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
00853                 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
00854                               AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
00855 
00856                 if (on)
00857                         REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
00858                                     AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
00859                 else
00860                         REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
00861                                     AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
00862 
00863                 if (on != aniState->ofdmWeakSigDetect) {
00864                         DBG2("ath9k: "
00865                                 "** ch %d: ofdm weak signal: %s=>%s\n",
00866                                 chan->channel,
00867                                 aniState->ofdmWeakSigDetect ?
00868                                 "on" : "off",
00869                                 on ? "on" : "off");
00870                         if (on)
00871                                 ah->stats.ast_ani_ofdmon++;
00872                         else
00873                                 ah->stats.ast_ani_ofdmoff++;
00874                         aniState->ofdmWeakSigDetect = on;
00875                 }
00876                 break;
00877         }
00878         case ATH9K_ANI_FIRSTEP_LEVEL:{
00879                 u32 level = param;
00880 
00881                 if (level >= ARRAY_SIZE(firstep_table)) {
00882                         DBG("ath9k: "
00883                                 "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%d > %zd)\n",
00884                                 level, ARRAY_SIZE(firstep_table));
00885                         return 0;
00886                 }
00887 
00888                 /*
00889                  * make register setting relative to default
00890                  * from INI file & cap value
00891                  */
00892                 value = firstep_table[level] -
00893                         firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
00894                         aniState->iniDef.firstep;
00895                 if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
00896                         value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
00897                 if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
00898                         value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
00899                 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
00900                               AR_PHY_FIND_SIG_FIRSTEP,
00901                               value);
00902                 /*
00903                  * we need to set first step low register too
00904                  * make register setting relative to default
00905                  * from INI file & cap value
00906                  */
00907                 value2 = firstep_table[level] -
00908                          firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
00909                          aniState->iniDef.firstepLow;
00910                 if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
00911                         value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
00912                 if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
00913                         value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
00914 
00915                 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
00916                               AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2);
00917 
00918                 if (level != aniState->firstepLevel) {
00919                         DBG2("ath9k: "
00920                                 "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",
00921                                 chan->channel,
00922                                 aniState->firstepLevel,
00923                                 level,
00924                                 ATH9K_ANI_FIRSTEP_LVL_NEW,
00925                                 value,
00926                                 aniState->iniDef.firstep);
00927                         DBG2("ath9k: "
00928                                 "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",
00929                                 chan->channel,
00930                                 aniState->firstepLevel,
00931                                 level,
00932                                 ATH9K_ANI_FIRSTEP_LVL_NEW,
00933                                 value2,
00934                                 aniState->iniDef.firstepLow);
00935                         if (level > aniState->firstepLevel)
00936                                 ah->stats.ast_ani_stepup++;
00937                         else if (level < aniState->firstepLevel)
00938                                 ah->stats.ast_ani_stepdown++;
00939                         aniState->firstepLevel = level;
00940                 }
00941                 break;
00942         }
00943         case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
00944                 u32 level = param;
00945 
00946                 if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
00947                         DBG("ath9k: "
00948                                 "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%d > %zd)\n",
00949                                 level, ARRAY_SIZE(cycpwrThr1_table));
00950                         return 0;
00951                 }
00952                 /*
00953                  * make register setting relative to default
00954                  * from INI file & cap value
00955                  */
00956                 value = cycpwrThr1_table[level] -
00957                         cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
00958                         aniState->iniDef.cycpwrThr1;
00959                 if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
00960                         value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
00961                 if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
00962                         value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
00963                 REG_RMW_FIELD(ah, AR_PHY_TIMING5,
00964                               AR_PHY_TIMING5_CYCPWR_THR1,
00965                               value);
00966 
00967                 /*
00968                  * set AR_PHY_EXT_CCA for extension channel
00969                  * make register setting relative to default
00970                  * from INI file & cap value
00971                  */
00972                 value2 = cycpwrThr1_table[level] -
00973                          cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
00974                          aniState->iniDef.cycpwrThr1Ext;
00975                 if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
00976                         value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
00977                 if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
00978                         value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
00979                 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
00980                               AR_PHY_EXT_CYCPWR_THR1, value2);
00981 
00982                 if (level != aniState->spurImmunityLevel) {
00983                         DBG2("ath9k: "
00984                                 "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",
00985                                 chan->channel,
00986                                 aniState->spurImmunityLevel,
00987                                 level,
00988                                 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
00989                                 value,
00990                                 aniState->iniDef.cycpwrThr1);
00991                         DBG2("ath9k: "
00992                                 "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",
00993                                 chan->channel,
00994                                 aniState->spurImmunityLevel,
00995                                 level,
00996                                 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
00997                                 value2,
00998                                 aniState->iniDef.cycpwrThr1Ext);
00999                         if (level > aniState->spurImmunityLevel)
01000                                 ah->stats.ast_ani_spurup++;
01001                         else if (level < aniState->spurImmunityLevel)
01002                                 ah->stats.ast_ani_spurdown++;
01003                         aniState->spurImmunityLevel = level;
01004                 }
01005                 break;
01006         }
01007         case ATH9K_ANI_MRC_CCK:{
01008                 /*
01009                  * is_on == 1 means MRC CCK ON (default, less noise imm)
01010                  * is_on == 0 means MRC CCK is OFF (more noise imm)
01011                  */
01012                 int is_on = param ? 1 : 0;
01013                 REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
01014                               AR_PHY_MRC_CCK_ENABLE, is_on);
01015                 REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
01016                               AR_PHY_MRC_CCK_MUX_REG, is_on);
01017                 if (!(is_on != aniState->mrcCCKOff)) {
01018                         DBG2("ath9k: "
01019                                 "** ch %d: MRC CCK: %s=>%s\n",
01020                                 chan->channel,
01021                                 !aniState->mrcCCKOff ? "on" : "off",
01022                                 is_on ? "on" : "off");
01023                 if (is_on)
01024                         ah->stats.ast_ani_ccklow++;
01025                 else
01026                         ah->stats.ast_ani_cckhigh++;
01027                 aniState->mrcCCKOff = !is_on;
01028                 }
01029         break;
01030         }
01031         case ATH9K_ANI_PRESENT:
01032                 break;
01033         default:
01034                 DBG2("ath9k: invalid cmd %d\n", cmd);
01035                 return 0;
01036         }
01037 
01038         DBG2("ath9k: "
01039                 "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",
01040                 aniState->spurImmunityLevel,
01041                 aniState->ofdmWeakSigDetect ? "on" : "off",
01042                 aniState->firstepLevel,
01043                 !aniState->mrcCCKOff ? "on" : "off",
01044                 aniState->listenTime,
01045                 aniState->ofdmPhyErrCount,
01046                 aniState->cckPhyErrCount);
01047         return 1;
01048 }
01049 
01050 static void ar9003_hw_do_getnf(struct ath_hw *ah,
01051                               int16_t nfarray[NUM_NF_READINGS])
01052 {
01053 #define AR_PHY_CH_MINCCA_PWR    0x1FF00000
01054 #define AR_PHY_CH_MINCCA_PWR_S  20
01055 #define AR_PHY_CH_EXT_MINCCA_PWR 0x01FF0000
01056 #define AR_PHY_CH_EXT_MINCCA_PWR_S 16
01057 
01058         int16_t nf;
01059         int i;
01060 
01061         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
01062                 if (ah->rxchainmask & BIT(i)) {
01063                         nf = MS(REG_READ(ah, ah->nf_regs[i]),
01064                                          AR_PHY_CH_MINCCA_PWR);
01065                         nfarray[i] = sign_extend32(nf, 8);
01066 
01067                         if (IS_CHAN_HT40(ah->curchan)) {
01068                                 u8 ext_idx = AR9300_MAX_CHAINS + i;
01069 
01070                                 nf = MS(REG_READ(ah, ah->nf_regs[ext_idx]),
01071                                                  AR_PHY_CH_EXT_MINCCA_PWR);
01072                                 nfarray[ext_idx] = sign_extend32(nf, 8);
01073                         }
01074                 }
01075         }
01076 }
01077 
01078 static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
01079 {
01080         ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
01081         ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
01082         ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
01083         ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
01084         ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
01085         ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ;
01086 }
01087 
01088 /*
01089  * Initialize the ANI register values with default (ini) values.
01090  * This routine is called during a (full) hardware reset after
01091  * all the registers are initialised from the INI.
01092  */
01093 static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
01094 {
01095         struct ar5416AniState *aniState;
01096         struct ath9k_channel *chan = ah->curchan;
01097         struct ath9k_ani_default *iniDef;
01098         u32 val;
01099 
01100         aniState = &ah->curchan->ani;
01101         iniDef = &aniState->iniDef;
01102 
01103         DBG2("ath9k: "
01104                 "ver %d.%d chan %d Mhz/0x%x\n",
01105                 ah->hw_version.macVersion,
01106                 ah->hw_version.macRev,
01107                 chan->channel,
01108                 chan->channelFlags);
01109 
01110         val = REG_READ(ah, AR_PHY_SFCORR);
01111         iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
01112         iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH);
01113         iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR);
01114 
01115         val = REG_READ(ah, AR_PHY_SFCORR_LOW);
01116         iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW);
01117         iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW);
01118         iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);
01119 
01120         val = REG_READ(ah, AR_PHY_SFCORR_EXT);
01121         iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH);
01122         iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH);
01123         iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW);
01124         iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW);
01125         iniDef->firstep = REG_READ_FIELD(ah,
01126                                          AR_PHY_FIND_SIG,
01127                                          AR_PHY_FIND_SIG_FIRSTEP);
01128         iniDef->firstepLow = REG_READ_FIELD(ah,
01129                                             AR_PHY_FIND_SIG_LOW,
01130                                             AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW);
01131         iniDef->cycpwrThr1 = REG_READ_FIELD(ah,
01132                                             AR_PHY_TIMING5,
01133                                             AR_PHY_TIMING5_CYCPWR_THR1);
01134         iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah,
01135                                                AR_PHY_EXT_CCA,
01136                                                AR_PHY_EXT_CYCPWR_THR1);
01137 
01138         /* these levels just got reset to defaults by the INI */
01139         aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
01140         aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
01141         aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
01142         aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
01143 }
01144 
01145 static void ar9003_hw_set_radar_params(struct ath_hw *ah,
01146                                        struct ath_hw_radar_conf *conf)
01147 {
01148         u32 radar_0 = 0, radar_1 = 0;
01149 
01150         if (!conf) {
01151                 REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
01152                 return;
01153         }
01154 
01155         radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;
01156         radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);
01157         radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);
01158         radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);
01159         radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
01160         radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
01161 
01162         radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
01163         radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
01164         radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
01165         radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);
01166         radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);
01167 
01168         REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);
01169         REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);
01170         if (conf->ext_channel)
01171                 REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
01172         else
01173                 REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
01174 }
01175 
01176 static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
01177 {
01178         struct ath_hw_radar_conf *conf = &ah->radar_conf;
01179 
01180         conf->fir_power = -28;
01181         conf->radar_rssi = 0;
01182         conf->pulse_height = 10;
01183         conf->pulse_rssi = 24;
01184         conf->pulse_inband = 8;
01185         conf->pulse_maxlen = 255;
01186         conf->pulse_inband_step = 12;
01187         conf->radar_inband = 8;
01188 }
01189 
01190 static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,
01191                                    struct ath_hw_antcomb_conf *antconf)
01192 {
01193         u32 regval;
01194 
01195         regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
01196         antconf->main_lna_conf = (regval & AR_PHY_9485_ANT_DIV_MAIN_LNACONF) >>
01197                                   AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S;
01198         antconf->alt_lna_conf = (regval & AR_PHY_9485_ANT_DIV_ALT_LNACONF) >>
01199                                  AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;
01200         antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>
01201                                   AR_PHY_9485_ANT_FAST_DIV_BIAS_S;
01202         antconf->lna1_lna2_delta = -9;
01203         antconf->div_group = 2;
01204 }
01205 
01206 static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
01207                                    struct ath_hw_antcomb_conf *antconf)
01208 {
01209         u32 regval;
01210 
01211         regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
01212         regval &= ~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF |
01213                     AR_PHY_9485_ANT_DIV_ALT_LNACONF |
01214                     AR_PHY_9485_ANT_FAST_DIV_BIAS |
01215                     AR_PHY_9485_ANT_DIV_MAIN_GAINTB |
01216                     AR_PHY_9485_ANT_DIV_ALT_GAINTB);
01217         regval |= ((antconf->main_lna_conf <<
01218                                         AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S)
01219                    & AR_PHY_9485_ANT_DIV_MAIN_LNACONF);
01220         regval |= ((antconf->alt_lna_conf << AR_PHY_9485_ANT_DIV_ALT_LNACONF_S)
01221                    & AR_PHY_9485_ANT_DIV_ALT_LNACONF);
01222         regval |= ((antconf->fast_div_bias << AR_PHY_9485_ANT_FAST_DIV_BIAS_S)
01223                    & AR_PHY_9485_ANT_FAST_DIV_BIAS);
01224         regval |= ((antconf->main_gaintb << AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S)
01225                    & AR_PHY_9485_ANT_DIV_MAIN_GAINTB);
01226         regval |= ((antconf->alt_gaintb << AR_PHY_9485_ANT_DIV_ALT_GAINTB_S)
01227                    & AR_PHY_9485_ANT_DIV_ALT_GAINTB);
01228 
01229         REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
01230 }
01231 
01232 void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
01233 {
01234         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
01235         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
01236         static const u32 ar9300_cca_regs[6] = {
01237                 AR_PHY_CCA_0,
01238                 AR_PHY_CCA_1,
01239                 AR_PHY_CCA_2,
01240                 AR_PHY_EXT_CCA,
01241                 AR_PHY_EXT_CCA_1,
01242                 AR_PHY_EXT_CCA_2,
01243         };
01244 
01245         priv_ops->rf_set_freq = ar9003_hw_set_channel;
01246         priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate;
01247         priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;
01248         priv_ops->set_channel_regs = ar9003_hw_set_channel_regs;
01249         priv_ops->init_bb = ar9003_hw_init_bb;
01250         priv_ops->process_ini = ar9003_hw_process_ini;
01251         priv_ops->set_rfmode = ar9003_hw_set_rfmode;
01252         priv_ops->mark_phy_inactive = ar9003_hw_mark_phy_inactive;
01253         priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
01254         priv_ops->rfbus_req = ar9003_hw_rfbus_req;
01255         priv_ops->rfbus_done = ar9003_hw_rfbus_done;
01256         priv_ops->set_diversity = ar9003_hw_set_diversity;
01257         priv_ops->ani_control = ar9003_hw_ani_control;
01258         priv_ops->do_getnf = ar9003_hw_do_getnf;
01259         priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
01260         priv_ops->set_radar_params = ar9003_hw_set_radar_params;
01261 
01262         ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
01263         ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
01264 
01265         ar9003_hw_set_nf_limits(ah);
01266         ar9003_hw_set_radar_conf(ah);
01267         memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs));
01268 }
01269 
01270 void ar9003_hw_disable_phy_restart(struct ath_hw *ah)
01271 {
01272         u32 val;
01273 
01274         val = REG_READ(ah, AR_PHY_RESTART);
01275         val &= ~AR_PHY_RESTART_ENA;
01276 
01277         REG_WRITE(ah, AR_PHY_RESTART, val);
01278 }