This source file includes following definitions.
- ath9k_hw_get_nf_hist_mid
- ath9k_hw_get_nf_limits
- ath9k_hw_get_default_nf
- ath9k_hw_getchan_noise
- ath9k_hw_update_nfcal_hist_buffer
- ath9k_hw_get_nf_thresh
- ath9k_hw_reset_calibration
- ath9k_hw_reset_calvalid
- ath9k_hw_start_nfcal
- ath9k_hw_loadnf
- ath9k_hw_nf_sanitize
- ath9k_hw_getnf
- ath9k_init_nfcal_hist_buffer
- ath9k_hw_bstuck_nfcal
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 #include "hw.h"
  18 #include "hw-ops.h"
  19 #include <linux/export.h>
  20 
  21 
  22 
  23 
  24 static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
  25 {
  26         int16_t nfval;
  27         int16_t sort[ATH9K_NF_CAL_HIST_MAX];
  28         int i, j;
  29 
  30         for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
  31                 sort[i] = nfCalBuffer[i];
  32 
  33         for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
  34                 for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
  35                         if (sort[j] > sort[j - 1]) {
  36                                 nfval = sort[j];
  37                                 sort[j] = sort[j - 1];
  38                                 sort[j - 1] = nfval;
  39                         }
  40                 }
  41         }
  42         nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
  43 
  44         return nfval;
  45 }
  46 
  47 static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah,
  48                                                     struct ath9k_channel *chan)
  49 {
  50         struct ath_nf_limits *limit;
  51 
  52         if (!chan || IS_CHAN_2GHZ(chan))
  53                 limit = &ah->nf_2g;
  54         else
  55                 limit = &ah->nf_5g;
  56 
  57         return limit;
  58 }
  59 
  60 static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
  61                                    struct ath9k_channel *chan,
  62                                    int chain)
  63 {
  64         s16 calib_nf = ath9k_hw_get_nf_limits(ah, chan)->cal[chain];
  65 
  66         if (calib_nf)
  67                 return calib_nf;
  68         else
  69                 return ath9k_hw_get_nf_limits(ah, chan)->nominal;
  70 }
  71 
  72 s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan,
  73                            s16 nf)
  74 {
  75         s8 noise = ATH_DEFAULT_NOISE_FLOOR;
  76 
  77         if (nf) {
  78                 s8 delta = nf - ATH9K_NF_CAL_NOISE_THRESH -
  79                            ath9k_hw_get_default_nf(ah, chan, 0);
  80                 if (delta > 0)
  81                         noise += delta;
  82         }
  83         return noise;
  84 }
  85 EXPORT_SYMBOL(ath9k_hw_getchan_noise);
  86 
  87 static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
  88                                               struct ath9k_hw_cal_data *cal,
  89                                               int16_t *nfarray)
  90 {
  91         struct ath_common *common = ath9k_hw_common(ah);
  92         struct ath_nf_limits *limit;
  93         struct ath9k_nfcal_hist *h;
  94         bool high_nf_mid = false;
  95         u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
  96         int i;
  97 
  98         h = cal->nfCalHist;
  99         limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
 100 
 101         for (i = 0; i < NUM_NF_READINGS; i++) {
 102                 if (!(chainmask & (1 << i)) ||
 103                     ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))
 104                         continue;
 105 
 106                 h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
 107 
 108                 if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
 109                         h[i].currIndex = 0;
 110 
 111                 if (h[i].invalidNFcount > 0) {
 112                         h[i].invalidNFcount--;
 113                         h[i].privNF = nfarray[i];
 114                 } else {
 115                         h[i].privNF =
 116                                 ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
 117                 }
 118 
 119                 if (!h[i].privNF)
 120                         continue;
 121 
 122                 if (h[i].privNF > limit->max) {
 123                         high_nf_mid = true;
 124 
 125                         ath_dbg(common, CALIBRATE,
 126                                 "NFmid[%d] (%d) > MAX (%d), %s\n",
 127                                 i, h[i].privNF, limit->max,
 128                                 (test_bit(NFCAL_INTF, &cal->cal_flags) ?
 129                                  "not corrected (due to interference)" :
 130                                  "correcting to MAX"));
 131 
 132                         
 133 
 134 
 135 
 136 
 137 
 138 
 139                         if (!test_bit(NFCAL_INTF, &cal->cal_flags))
 140                                 h[i].privNF = limit->max;
 141                 }
 142         }
 143 
 144         
 145 
 146 
 147 
 148 
 149         if (!high_nf_mid)
 150                 clear_bit(NFCAL_INTF, &cal->cal_flags);
 151 }
 152 
 153 static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah,
 154                                    enum nl80211_band band,
 155                                    int16_t *nft)
 156 {
 157         switch (band) {
 158         case NL80211_BAND_5GHZ:
 159                 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
 160                 break;
 161         case NL80211_BAND_2GHZ:
 162                 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
 163                 break;
 164         default:
 165                 BUG_ON(1);
 166                 return false;
 167         }
 168 
 169         return true;
 170 }
 171 
 172 void ath9k_hw_reset_calibration(struct ath_hw *ah,
 173                                 struct ath9k_cal_list *currCal)
 174 {
 175         int i;
 176 
 177         ath9k_hw_setup_calibration(ah, currCal);
 178 
 179         currCal->calState = CAL_RUNNING;
 180 
 181         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 182                 ah->meas0.sign[i] = 0;
 183                 ah->meas1.sign[i] = 0;
 184                 ah->meas2.sign[i] = 0;
 185                 ah->meas3.sign[i] = 0;
 186         }
 187 
 188         ah->cal_samples = 0;
 189 }
 190 
 191 
 192 bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
 193 {
 194         struct ath_common *common = ath9k_hw_common(ah);
 195         struct ath9k_cal_list *currCal = ah->cal_list_curr;
 196 
 197         if (!ah->caldata)
 198                 return true;
 199 
 200         if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
 201                 return true;
 202 
 203         if (currCal == NULL)
 204                 return true;
 205 
 206         if (currCal->calState != CAL_DONE) {
 207                 ath_dbg(common, CALIBRATE, "Calibration state incorrect, %d\n",
 208                         currCal->calState);
 209                 return true;
 210         }
 211 
 212         if (!(ah->supp_cals & currCal->calData->calType))
 213                 return true;
 214 
 215         ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n",
 216                 currCal->calData->calType, ah->curchan->chan->center_freq);
 217 
 218         ah->caldata->CalValid &= ~currCal->calData->calType;
 219         currCal->calState = CAL_WAITING;
 220 
 221         return false;
 222 }
 223 EXPORT_SYMBOL(ath9k_hw_reset_calvalid);
 224 
 225 void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update)
 226 {
 227         if (ah->caldata)
 228                 set_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
 229 
 230         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
 231                     AR_PHY_AGC_CONTROL_ENABLE_NF);
 232 
 233         if (update)
 234                 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
 235                     AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
 236         else
 237                 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
 238                     AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
 239 
 240         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 241 }
 242 
 243 int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
 244 {
 245         struct ath9k_nfcal_hist *h = NULL;
 246         unsigned i, j;
 247         u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
 248         struct ath_common *common = ath9k_hw_common(ah);
 249         s16 default_nf = ath9k_hw_get_nf_limits(ah, chan)->nominal;
 250         u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL);
 251 
 252         if (ah->caldata)
 253                 h = ah->caldata->nfCalHist;
 254 
 255         ENABLE_REG_RMW_BUFFER(ah);
 256         for (i = 0; i < NUM_NF_READINGS; i++) {
 257                 if (chainmask & (1 << i)) {
 258                         s16 nfval;
 259 
 260                         if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan))
 261                                 continue;
 262 
 263                         if (ah->nf_override)
 264                                 nfval = ah->nf_override;
 265                         else if (h)
 266                                 nfval = h[i].privNF;
 267                         else {
 268                                 
 269                                 nfval =
 270                                     ath9k_hw_get_nf_limits(ah, chan)->cal[i];
 271                                 if (nfval > -60 || nfval < -127)
 272                                         nfval = default_nf;
 273                         }
 274 
 275                         REG_RMW(ah, ah->nf_regs[i],
 276                                 (((u32) nfval << 1) & 0x1ff), 0x1ff);
 277                 }
 278         }
 279 
 280         
 281 
 282 
 283 
 284         if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
 285                 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 286                 REG_RMW_BUFFER_FLUSH(ah);
 287                 ENABLE_REG_RMW_BUFFER(ah);
 288         }
 289 
 290         
 291 
 292 
 293 
 294         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
 295                     AR_PHY_AGC_CONTROL_ENABLE_NF);
 296         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
 297                     AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
 298         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 299         REG_RMW_BUFFER_FLUSH(ah);
 300 
 301         
 302 
 303 
 304 
 305 
 306 
 307         for (j = 0; j < 22200; j++) {
 308                 if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
 309                               AR_PHY_AGC_CONTROL_NF) == 0)
 310                         break;
 311                 udelay(10);
 312         }
 313 
 314         
 315 
 316 
 317         if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
 318                 ENABLE_REG_RMW_BUFFER(ah);
 319                 if (bb_agc_ctl & AR_PHY_AGC_CONTROL_ENABLE_NF)
 320                         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
 321                                     AR_PHY_AGC_CONTROL_ENABLE_NF);
 322                 if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NO_UPDATE_NF)
 323                         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
 324                                     AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
 325                 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 326                 REG_RMW_BUFFER_FLUSH(ah);
 327         }
 328 
 329         
 330 
 331 
 332 
 333 
 334 
 335 
 336 
 337 
 338         if (j == 22200) {
 339                 ath_dbg(common, ANY,
 340                         "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
 341                         REG_READ(ah, AR_PHY_AGC_CONTROL));
 342                 return -ETIMEDOUT;
 343         }
 344 
 345         
 346 
 347 
 348 
 349 
 350         ENABLE_REG_RMW_BUFFER(ah);
 351         for (i = 0; i < NUM_NF_READINGS; i++) {
 352                 if (chainmask & (1 << i)) {
 353                         if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan))
 354                                 continue;
 355 
 356                         REG_RMW(ah, ah->nf_regs[i],
 357                                         (((u32) (-50) << 1) & 0x1ff), 0x1ff);
 358                 }
 359         }
 360         REG_RMW_BUFFER_FLUSH(ah);
 361 
 362         return 0;
 363 }
 364 EXPORT_SYMBOL(ath9k_hw_loadnf);
 365 
 366 
 367 static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
 368 {
 369         struct ath_common *common = ath9k_hw_common(ah);
 370         struct ath_nf_limits *limit;
 371         int i;
 372 
 373         if (IS_CHAN_2GHZ(ah->curchan))
 374                 limit = &ah->nf_2g;
 375         else
 376                 limit = &ah->nf_5g;
 377 
 378         for (i = 0; i < NUM_NF_READINGS; i++) {
 379                 if (!nf[i])
 380                         continue;
 381 
 382                 ath_dbg(common, CALIBRATE,
 383                         "NF calibrated [%s] [chain %d] is %d\n",
 384                         (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
 385 
 386                 if (nf[i] > limit->max) {
 387                         ath_dbg(common, CALIBRATE,
 388                                 "NF[%d] (%d) > MAX (%d), correcting to MAX\n",
 389                                 i, nf[i], limit->max);
 390                         nf[i] = limit->max;
 391                 } else if (nf[i] < limit->min) {
 392                         ath_dbg(common, CALIBRATE,
 393                                 "NF[%d] (%d) < MIN (%d), correcting to NOM\n",
 394                                 i, nf[i], limit->min);
 395                         nf[i] = limit->nominal;
 396                 }
 397         }
 398 }
 399 
 400 bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
 401 {
 402         struct ath_common *common = ath9k_hw_common(ah);
 403         int16_t nf, nfThresh;
 404         int16_t nfarray[NUM_NF_READINGS] = { 0 };
 405         struct ath9k_nfcal_hist *h;
 406         struct ieee80211_channel *c = chan->chan;
 407         struct ath9k_hw_cal_data *caldata = ah->caldata;
 408 
 409         if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
 410                 ath_dbg(common, CALIBRATE,
 411                         "NF did not complete in calibration window\n");
 412                 return false;
 413         }
 414 
 415         ath9k_hw_do_getnf(ah, nfarray);
 416         ath9k_hw_nf_sanitize(ah, nfarray);
 417         nf = nfarray[0];
 418         if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
 419             && nf > nfThresh) {
 420                 ath_dbg(common, CALIBRATE,
 421                         "noise floor failed detected; detected %d, threshold %d\n",
 422                         nf, nfThresh);
 423         }
 424 
 425         if (!caldata) {
 426                 chan->noisefloor = nf;
 427                 return false;
 428         }
 429 
 430         h = caldata->nfCalHist;
 431         clear_bit(NFCAL_PENDING, &caldata->cal_flags);
 432         ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
 433         chan->noisefloor = h[0].privNF;
 434         ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor);
 435         return true;
 436 }
 437 EXPORT_SYMBOL(ath9k_hw_getnf);
 438 
 439 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
 440                                   struct ath9k_channel *chan)
 441 {
 442         struct ath9k_nfcal_hist *h;
 443         int i, j, k = 0;
 444 
 445         ah->caldata->channel = chan->channel;
 446         ah->caldata->channelFlags = chan->channelFlags;
 447         h = ah->caldata->nfCalHist;
 448         for (i = 0; i < NUM_NF_READINGS; i++) {
 449                 h[i].currIndex = 0;
 450                 h[i].privNF = ath9k_hw_get_default_nf(ah, chan, k);
 451                 h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH;
 452                 for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++)
 453                         h[i].nfCalBuffer[j] = h[i].privNF;
 454                 if (++k >= AR5416_MAX_CHAINS)
 455                         k = 0;
 456         }
 457 }
 458 
 459 
 460 void ath9k_hw_bstuck_nfcal(struct ath_hw *ah)
 461 {
 462         struct ath9k_hw_cal_data *caldata = ah->caldata;
 463 
 464         if (unlikely(!caldata))
 465                 return;
 466 
 467         
 468 
 469 
 470 
 471 
 472 
 473 
 474 
 475         if (!test_bit(NFCAL_PENDING, &caldata->cal_flags))
 476                 ath9k_hw_start_nfcal(ah, true);
 477         else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF))
 478                 ath9k_hw_getnf(ah, ah->curchan);
 479 
 480         set_bit(NFCAL_INTF, &caldata->cal_flags);
 481 }
 482 EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal);
 483