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