1 /* 2 * Copyright (c) 2008-2011 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "hw.h" 18 #include "hw-ops.h" 19 #include <linux/sort.h> 20 #include <linux/export.h> 21 22 /* Common calibration code */ 23 24 static int rcmp_i16(const void *x, const void *y) 25 { 26 /* Sort in reverse order. */ 27 return *(int16_t *)y - *(int16_t *)x; 28 } 29 30 static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) 31 { 32 int16_t nfcal[ATH9K_NF_CAL_HIST_MAX]; 33 34 memcpy(nfcal, nfCalBuffer, sizeof(nfcal)); 35 sort(nfcal, ATH9K_NF_CAL_HIST_MAX, sizeof(int16_t), rcmp_i16, NULL); 36 37 return nfcal[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1]; 38 } 39 40 static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah, 41 struct ath9k_channel *chan) 42 { 43 struct ath_nf_limits *limit; 44 45 if (!chan || IS_CHAN_2GHZ(chan)) 46 limit = &ah->nf_2g; 47 else 48 limit = &ah->nf_5g; 49 50 return limit; 51 } 52 53 static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, 54 struct ath9k_channel *chan, 55 int chain) 56 { 57 s16 calib_nf = ath9k_hw_get_nf_limits(ah, chan)->cal[chain]; 58 59 if (calib_nf) 60 return calib_nf; 61 else 62 return ath9k_hw_get_nf_limits(ah, chan)->nominal; 63 } 64 65 s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan, 66 s16 nf) 67 { 68 s8 noise = ATH_DEFAULT_NOISE_FLOOR; 69 70 if (nf) { 71 s8 delta = nf - ATH9K_NF_CAL_NOISE_THRESH - 72 ath9k_hw_get_default_nf(ah, chan, 0); 73 if (delta > 0) 74 noise += delta; 75 } 76 return noise; 77 } 78 EXPORT_SYMBOL(ath9k_hw_getchan_noise); 79 80 static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, 81 struct ath9k_hw_cal_data *cal, 82 int16_t *nfarray) 83 { 84 struct ath_common *common = ath9k_hw_common(ah); 85 struct ath_nf_limits *limit; 86 struct ath9k_nfcal_hist *h; 87 bool high_nf_mid = false; 88 u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; 89 int i; 90 91 h = cal->nfCalHist; 92 limit = ath9k_hw_get_nf_limits(ah, ah->curchan); 93 94 for (i = 0; i < NUM_NF_READINGS; i++) { 95 if (!(chainmask & (1 << i)) || 96 ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan))) 97 continue; 98 99 h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; 100 101 if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) 102 h[i].currIndex = 0; 103 104 if (h[i].invalidNFcount > 0) { 105 h[i].invalidNFcount--; 106 h[i].privNF = nfarray[i]; 107 } else { 108 h[i].privNF = 109 ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); 110 } 111 112 if (!h[i].privNF) 113 continue; 114 115 if (h[i].privNF > limit->max) { 116 high_nf_mid = true; 117 118 ath_dbg(common, CALIBRATE, 119 "NFmid[%d] (%d) > MAX (%d), %s\n", 120 i, h[i].privNF, limit->max, 121 (test_bit(NFCAL_INTF, &cal->cal_flags) ? 122 "not corrected (due to interference)" : 123 "correcting to MAX")); 124 125 /* 126 * Normally we limit the average noise floor by the 127 * hardware specific maximum here. However if we have 128 * encountered stuck beacons because of interference, 129 * we bypass this limit here in order to better deal 130 * with our environment. 131 */ 132 if (!test_bit(NFCAL_INTF, &cal->cal_flags)) 133 h[i].privNF = limit->max; 134 } 135 } 136 137 /* 138 * If the noise floor seems normal for all chains, assume that 139 * there is no significant interference in the environment anymore. 140 * Re-enable the enforcement of the NF maximum again. 141 */ 142 if (!high_nf_mid) 143 clear_bit(NFCAL_INTF, &cal->cal_flags); 144 } 145 146 static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, 147 enum nl80211_band band, 148 int16_t *nft) 149 { 150 switch (band) { 151 case NL80211_BAND_5GHZ: 152 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5); 153 break; 154 case NL80211_BAND_2GHZ: 155 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2); 156 break; 157 default: 158 BUG_ON(1); 159 return false; 160 } 161 162 return true; 163 } 164 165 void ath9k_hw_reset_calibration(struct ath_hw *ah, 166 struct ath9k_cal_list *currCal) 167 { 168 int i; 169 170 ath9k_hw_setup_calibration(ah, currCal); 171 172 ah->cal_start_time = jiffies; 173 currCal->calState = CAL_RUNNING; 174 175 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 176 ah->meas0.sign[i] = 0; 177 ah->meas1.sign[i] = 0; 178 ah->meas2.sign[i] = 0; 179 ah->meas3.sign[i] = 0; 180 } 181 182 ah->cal_samples = 0; 183 } 184 185 /* This is done for the currently configured channel */ 186 bool ath9k_hw_reset_calvalid(struct ath_hw *ah) 187 { 188 struct ath_common *common = ath9k_hw_common(ah); 189 struct ath9k_cal_list *currCal = ah->cal_list_curr; 190 191 if (!ah->caldata) 192 return true; 193 194 if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) 195 return true; 196 197 if (currCal == NULL) 198 return true; 199 200 if (currCal->calState != CAL_DONE) { 201 ath_dbg(common, CALIBRATE, "Calibration state incorrect, %d\n", 202 currCal->calState); 203 return true; 204 } 205 206 currCal = ah->cal_list; 207 do { 208 ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n", 209 currCal->calData->calType, 210 ah->curchan->chan->center_freq); 211 212 ah->caldata->CalValid &= ~currCal->calData->calType; 213 currCal->calState = CAL_WAITING; 214 215 currCal = currCal->calNext; 216 } while (currCal != ah->cal_list); 217 218 return false; 219 } 220 EXPORT_SYMBOL(ath9k_hw_reset_calvalid); 221 222 void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update) 223 { 224 if (ah->caldata) 225 set_bit(NFCAL_PENDING, &ah->caldata->cal_flags); 226 227 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), 228 AR_PHY_AGC_CONTROL_ENABLE_NF); 229 230 if (update) 231 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL(ah), 232 AR_PHY_AGC_CONTROL_NO_UPDATE_NF); 233 else 234 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), 235 AR_PHY_AGC_CONTROL_NO_UPDATE_NF); 236 237 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), AR_PHY_AGC_CONTROL_NF); 238 } 239 240 int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) 241 { 242 struct ath9k_nfcal_hist *h = NULL; 243 unsigned i, j; 244 u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; 245 struct ath_common *common = ath9k_hw_common(ah); 246 s16 default_nf = ath9k_hw_get_nf_limits(ah, chan)->nominal; 247 u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL(ah)); 248 249 if (ah->caldata) 250 h = ah->caldata->nfCalHist; 251 252 ENABLE_REG_RMW_BUFFER(ah); 253 for (i = 0; i < NUM_NF_READINGS; i++) { 254 if (chainmask & (1 << i)) { 255 s16 nfval; 256 257 if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) 258 continue; 259 260 if (ah->nf_override) 261 nfval = ah->nf_override; 262 else if (h) 263 nfval = h[i].privNF; 264 else { 265 /* Try to get calibrated noise floor value */ 266 nfval = 267 ath9k_hw_get_nf_limits(ah, chan)->cal[i]; 268 if (nfval > -60 || nfval < -127) 269 nfval = default_nf; 270 } 271 272 REG_RMW(ah, ah->nf_regs[i], 273 (((u32) nfval << 1) & 0x1ff), 0x1ff); 274 } 275 } 276 277 /* 278 * stop NF cal if ongoing to ensure NF load completes immediately 279 * (or after end rx/tx frame if ongoing) 280 */ 281 if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) { 282 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL(ah), AR_PHY_AGC_CONTROL_NF); 283 REG_RMW_BUFFER_FLUSH(ah); 284 ENABLE_REG_RMW_BUFFER(ah); 285 } 286 287 /* 288 * Load software filtered NF value into baseband internal minCCApwr 289 * variable. 290 */ 291 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL(ah), 292 AR_PHY_AGC_CONTROL_ENABLE_NF); 293 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL(ah), 294 AR_PHY_AGC_CONTROL_NO_UPDATE_NF); 295 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), AR_PHY_AGC_CONTROL_NF); 296 REG_RMW_BUFFER_FLUSH(ah); 297 298 /* 299 * Wait for load to complete, should be fast, a few 10s of us. 300 * The max delay was changed from an original 250us to 22.2 msec. 301 * This would increase timeout to the longest possible frame 302 * (11n max length 22.1 msec) 303 */ 304 for (j = 0; j < 22200; j++) { 305 if ((REG_READ(ah, AR_PHY_AGC_CONTROL(ah)) & 306 AR_PHY_AGC_CONTROL_NF) == 0) 307 break; 308 udelay(10); 309 } 310 311 /* 312 * Restart NF so it can continue. 313 */ 314 if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) { 315 ENABLE_REG_RMW_BUFFER(ah); 316 if (bb_agc_ctl & AR_PHY_AGC_CONTROL_ENABLE_NF) 317 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), 318 AR_PHY_AGC_CONTROL_ENABLE_NF); 319 if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NO_UPDATE_NF) 320 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), 321 AR_PHY_AGC_CONTROL_NO_UPDATE_NF); 322 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), AR_PHY_AGC_CONTROL_NF); 323 REG_RMW_BUFFER_FLUSH(ah); 324 } 325 326 /* 327 * We timed out waiting for the noisefloor to load, probably due to an 328 * in-progress rx. Simply return here and allow the load plenty of time 329 * to complete before the next calibration interval. We need to avoid 330 * trying to load -50 (which happens below) while the previous load is 331 * still in progress as this can cause rx deafness. Instead by returning 332 * here, the baseband nf cal will just be capped by our present 333 * noisefloor until the next calibration timer. 334 */ 335 if (j == 22200) { 336 ath_dbg(common, ANY, 337 "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", 338 REG_READ(ah, AR_PHY_AGC_CONTROL(ah))); 339 return -ETIMEDOUT; 340 } 341 342 /* 343 * Restore maxCCAPower register parameter again so that we're not capped 344 * by the median we just loaded. This will be initial (and max) value 345 * of next noise floor calibration the baseband does. 346 */ 347 ENABLE_REG_RMW_BUFFER(ah); 348 for (i = 0; i < NUM_NF_READINGS; i++) { 349 if (chainmask & (1 << i)) { 350 if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) 351 continue; 352 353 REG_RMW(ah, ah->nf_regs[i], 354 (((u32) (-50) << 1) & 0x1ff), 0x1ff); 355 } 356 } 357 REG_RMW_BUFFER_FLUSH(ah); 358 359 return 0; 360 } 361 EXPORT_SYMBOL(ath9k_hw_loadnf); 362 363 364 static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) 365 { 366 struct ath_common *common = ath9k_hw_common(ah); 367 struct ath_nf_limits *limit; 368 int i; 369 370 if (IS_CHAN_2GHZ(ah->curchan)) 371 limit = &ah->nf_2g; 372 else 373 limit = &ah->nf_5g; 374 375 for (i = 0; i < NUM_NF_READINGS; i++) { 376 if (!nf[i]) 377 continue; 378 379 ath_dbg(common, CALIBRATE, 380 "NF calibrated [%s] [chain %d] is %d\n", 381 (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); 382 383 if (nf[i] > limit->max) { 384 ath_dbg(common, CALIBRATE, 385 "NF[%d] (%d) > MAX (%d), correcting to MAX\n", 386 i, nf[i], limit->max); 387 nf[i] = limit->max; 388 } else if (nf[i] < limit->min) { 389 ath_dbg(common, CALIBRATE, 390 "NF[%d] (%d) < MIN (%d), correcting to NOM\n", 391 i, nf[i], limit->min); 392 nf[i] = limit->nominal; 393 } 394 } 395 } 396 397 bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) 398 { 399 struct ath_common *common = ath9k_hw_common(ah); 400 int16_t nf, nfThresh; 401 int16_t nfarray[NUM_NF_READINGS] = { 0 }; 402 struct ath9k_nfcal_hist *h; 403 struct ieee80211_channel *c = chan->chan; 404 struct ath9k_hw_cal_data *caldata = ah->caldata; 405 406 if (REG_READ(ah, AR_PHY_AGC_CONTROL(ah)) & AR_PHY_AGC_CONTROL_NF) { 407 ath_dbg(common, CALIBRATE, 408 "NF did not complete in calibration window\n"); 409 return false; 410 } 411 412 ath9k_hw_do_getnf(ah, nfarray); 413 ath9k_hw_nf_sanitize(ah, nfarray); 414 nf = nfarray[0]; 415 if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh) 416 && nf > nfThresh) { 417 ath_dbg(common, CALIBRATE, 418 "noise floor failed detected; detected %d, threshold %d\n", 419 nf, nfThresh); 420 } 421 422 if (!caldata) { 423 chan->noisefloor = nf; 424 return false; 425 } 426 427 h = caldata->nfCalHist; 428 clear_bit(NFCAL_PENDING, &caldata->cal_flags); 429 ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); 430 chan->noisefloor = h[0].privNF; 431 ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor); 432 return true; 433 } 434 EXPORT_SYMBOL(ath9k_hw_getnf); 435 436 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, 437 struct ath9k_channel *chan) 438 { 439 struct ath9k_nfcal_hist *h; 440 int i, j, k = 0; 441 442 ah->caldata->channel = chan->channel; 443 ah->caldata->channelFlags = chan->channelFlags; 444 h = ah->caldata->nfCalHist; 445 for (i = 0; i < NUM_NF_READINGS; i++) { 446 h[i].currIndex = 0; 447 h[i].privNF = ath9k_hw_get_default_nf(ah, chan, k); 448 h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH; 449 for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) 450 h[i].nfCalBuffer[j] = h[i].privNF; 451 if (++k >= AR5416_MAX_CHAINS) 452 k = 0; 453 } 454 } 455 456 457 void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) 458 { 459 struct ath9k_hw_cal_data *caldata = ah->caldata; 460 461 if (unlikely(!caldata)) 462 return; 463 464 /* 465 * If beacons are stuck, the most likely cause is interference. 466 * Triggering a noise floor calibration at this point helps the 467 * hardware adapt to a noisy environment much faster. 468 * To ensure that we recover from stuck beacons quickly, let 469 * the baseband update the internal NF value itself, similar to 470 * what is being done after a full reset. 471 */ 472 if (!test_bit(NFCAL_PENDING, &caldata->cal_flags)) 473 ath9k_hw_start_nfcal(ah, true); 474 else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL(ah)) & AR_PHY_AGC_CONTROL_NF)) 475 ath9k_hw_getnf(ah, ah->curchan); 476 477 set_bit(NFCAL_INTF, &caldata->cal_flags); 478 } 479 EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal); 480 481