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 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 * Normally we limit the average noise floor by the 134 * hardware specific maximum here. However if we have 135 * encountered stuck beacons because of interference, 136 * we bypass this limit here in order to better deal 137 * with our environment. 138 */ 139 if (!test_bit(NFCAL_INTF, &cal->cal_flags)) 140 h[i].privNF = limit->max; 141 } 142 } 143 144 /* 145 * If the noise floor seems normal for all chains, assume that 146 * there is no significant interference in the environment anymore. 147 * Re-enable the enforcement of the NF maximum again. 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 /* This is done for the currently configured channel */ 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 /* Try to get calibrated noise floor value */ 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 * stop NF cal if ongoing to ensure NF load completes immediately 282 * (or after end rx/tx frame if ongoing) 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 * Load software filtered NF value into baseband internal minCCApwr 292 * variable. 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 * Wait for load to complete, should be fast, a few 10s of us. 303 * The max delay was changed from an original 250us to 22.2 msec. 304 * This would increase timeout to the longest possible frame 305 * (11n max length 22.1 msec) 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 * Restart NF so it can continue. 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 * We timed out waiting for the noisefloor to load, probably due to an 331 * in-progress rx. Simply return here and allow the load plenty of time 332 * to complete before the next calibration interval. We need to avoid 333 * trying to load -50 (which happens below) while the previous load is 334 * still in progress as this can cause rx deafness. Instead by returning 335 * here, the baseband nf cal will just be capped by our present 336 * noisefloor until the next calibration timer. 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 * Restore maxCCAPower register parameter again so that we're not capped 347 * by the median we just loaded. This will be initial (and max) value 348 * of next noise floor calibration the baseband does. 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 * If beacons are stuck, the most likely cause is interference. 469 * Triggering a noise floor calibration at this point helps the 470 * hardware adapt to a noisy environment much faster. 471 * To ensure that we recover from stuck beacons quickly, let 472 * the baseband update the internal NF value itself, similar to 473 * what is being done after a full reset. 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 484