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