1250003Sadrian/* 2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc. 3250003Sadrian * 4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any 5250003Sadrian * purpose with or without fee is hereby granted, provided that the above 6250003Sadrian * copyright notice and this permission notice appear in all copies. 7250003Sadrian * 8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14250003Sadrian * PERFORMANCE OF THIS SOFTWARE. 15250003Sadrian */ 16250003Sadrian#include "opt_ah.h" 17250003Sadrian 18250003Sadrian#ifdef AH_SUPPORT_AR9300 19250003Sadrian 20250003Sadrian#include "ah.h" 21250003Sadrian#include "ah_desc.h" 22250003Sadrian#include "ah_internal.h" 23250003Sadrian 24250003Sadrian#include "ar9300/ar9300phy.h" 25250003Sadrian#include "ar9300/ar9300.h" 26250003Sadrian#include "ar9300/ar9300reg.h" 27250003Sadrian#include "ar9300/ar9300desc.h" 28250003Sadrian 29250003Sadrian#if ATH_SUPPORT_SPECTRAL 30250003Sadrian 31250003Sadrian/* 32250003Sadrian * Default 9300 spectral scan parameters 33250003Sadrian */ 34250003Sadrian#define AR9300_SPECTRAL_SCAN_ENA 0 35250003Sadrian#define AR9300_SPECTRAL_SCAN_ACTIVE 0 36250003Sadrian#define AR9300_SPECTRAL_SCAN_FFT_PERIOD 8 37250003Sadrian#define AR9300_SPECTRAL_SCAN_PERIOD 1 38250003Sadrian#define AR9300_SPECTRAL_SCAN_COUNT 16 /* used to be 128 */ 39250003Sadrian#define AR9300_SPECTRAL_SCAN_SHORT_REPEAT 1 40250003Sadrian 41250003Sadrian/* constants */ 42250003Sadrian#define MAX_RADAR_DC_PWR_THRESH 127 43250003Sadrian#define MAX_RADAR_RSSI_THRESH 0x3f 44250003Sadrian#define MAX_RADAR_HEIGHT 0x3f 45250003Sadrian#define MAX_CCA_THRESH 127 46250003Sadrian#define ENABLE_ALL_PHYERR 0xffffffff 47250003Sadrian 48250003Sadrianvoid ar9300_disable_cck(struct ath_hal *ah); 49250003Sadrianvoid ar9300_disable_radar(struct ath_hal *ah); 50250003Sadrianvoid ar9300_disable_restart(struct ath_hal *ah); 51250003Sadrianvoid ar9300_set_radar_dc_thresh(struct ath_hal *ah); 52250003Sadrianvoid ar9300_disable_weak_signal(struct ath_hal *ah); 53250003Sadrianvoid ar9300_disable_strong_signal(struct ath_hal *ah); 54250003Sadrianvoid ar9300_prep_spectral_scan(struct ath_hal *ah); 55250003Sadrianvoid ar9300_disable_dc_offset(struct ath_hal *ah); 56250003Sadrianvoid ar9300_enable_cck_detect(struct ath_hal *ah); 57250003Sadrian 58250003Sadrianvoid 59250003Sadrianar9300_disable_cck(struct ath_hal *ah) 60250003Sadrian{ 61250003Sadrian u_int32_t val; 62250003Sadrian 63250003Sadrian val = OS_REG_READ(ah, AR_PHY_MODE); 64250003Sadrian val &= ~(AR_PHY_MODE_DYN_CCK_DISABLE); 65250003Sadrian 66250003Sadrian OS_REG_WRITE(ah, AR_PHY_MODE, val); 67250003Sadrian} 68250003Sadrian 69250003Sadrianvoid 70250003Sadrianar9300_disable_radar(struct ath_hal *ah) 71250003Sadrian{ 72250003Sadrian u_int32_t val; 73250003Sadrian 74250003Sadrian /* Enable radar FFT */ 75250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 76250003Sadrian val |= AR_PHY_RADAR_0_FFT_ENA; 77250003Sadrian 78250003Sadrian /* set radar detect thresholds to max to effectively disable radar */ 79250003Sadrian val &= ~AR_PHY_RADAR_0_RRSSI; 80250003Sadrian val |= SM(MAX_RADAR_RSSI_THRESH, AR_PHY_RADAR_0_RRSSI); 81250003Sadrian 82250003Sadrian val &= ~AR_PHY_RADAR_0_HEIGHT; 83250003Sadrian val |= SM(MAX_RADAR_HEIGHT, AR_PHY_RADAR_0_HEIGHT); 84250003Sadrian 85250003Sadrian val &= ~(AR_PHY_RADAR_0_ENA); 86250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 87250003Sadrian 88250003Sadrian /* disable extension radar detect */ 89250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); 90250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA); 91250003Sadrian 92250003Sadrian val = OS_REG_READ(ah, AR_RX_FILTER); 93250003Sadrian val |= (1 << 13); 94250003Sadrian OS_REG_WRITE(ah, AR_RX_FILTER, val); 95250003Sadrian} 96250003Sadrian 97250003Sadrianvoid ar9300_disable_restart(struct ath_hal *ah) 98250003Sadrian{ 99250003Sadrian u_int32_t val; 100250003Sadrian val = OS_REG_READ(ah, AR_PHY_RESTART); 101250003Sadrian val &= ~AR_PHY_RESTART_ENA; 102250003Sadrian OS_REG_WRITE(ah, AR_PHY_RESTART, val); 103250003Sadrian 104250003Sadrian val = OS_REG_READ(ah, AR_PHY_RESTART); 105250003Sadrian} 106250003Sadrian 107250003Sadrianvoid ar9300_set_radar_dc_thresh(struct ath_hal *ah) 108250003Sadrian{ 109250003Sadrian u_int32_t val; 110250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); 111250003Sadrian val &= ~AR_PHY_RADAR_DC_PWR_THRESH; 112250003Sadrian val |= SM(MAX_RADAR_DC_PWR_THRESH, AR_PHY_RADAR_DC_PWR_THRESH); 113250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val); 114250003Sadrian 115250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); 116250003Sadrian} 117250003Sadrian 118250003Sadrianvoid 119250003Sadrianar9300_disable_weak_signal(struct ath_hal *ah) 120250003Sadrian{ 121250003Sadrian /* set firpwr to max (signed) */ 122250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRPWR, 0x7f); 123250003Sadrian OS_REG_CLR_BIT(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRPWR_SIGN_BIT); 124250003Sadrian 125250003Sadrian /* set firstep to max */ 126250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRSTEP, 0x3f); 127250003Sadrian 128250003Sadrian /* set relpwr to max (signed) */ 129250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_RELPWR, 0x1f); 130250003Sadrian OS_REG_CLR_BIT(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_RELPWR_SIGN_BIT); 131250003Sadrian 132250003Sadrian /* set relstep to max (signed) */ 133250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_RELSTEP, 0x1f); 134250003Sadrian OS_REG_CLR_BIT(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT); 135250003Sadrian 136250003Sadrian /* set firpwr_low to max (signed) */ 137250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_FIRPWR, 0x7f); 138250003Sadrian OS_REG_CLR_BIT( 139250003Sadrian ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_FIRPWR_SIGN_BIT); 140250003Sadrian 141250003Sadrian /* set firstep_low to max */ 142250003Sadrian OS_REG_RMW_FIELD( 143250003Sadrian ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, 0x3f); 144250003Sadrian 145250003Sadrian /* set relstep_low to max (signed) */ 146250003Sadrian OS_REG_RMW_FIELD( 147250003Sadrian ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_RELSTEP, 0x1f); 148250003Sadrian OS_REG_CLR_BIT( 149250003Sadrian ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_RELSTEP_SIGN_BIT); 150250003Sadrian} 151250003Sadrian 152250003Sadrianvoid 153250003Sadrianar9300_disable_strong_signal(struct ath_hal *ah) 154250003Sadrian{ 155250003Sadrian u_int32_t val; 156250003Sadrian 157250003Sadrian val = OS_REG_READ(ah, AR_PHY_TIMING5); 158250003Sadrian val |= AR_PHY_TIMING5_RSSI_THR1A_ENA; 159250003Sadrian OS_REG_WRITE(ah, AR_PHY_TIMING5, val); 160250003Sadrian 161250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5, AR_PHY_TIMING5_RSSI_THR1A, 0x7f); 162250003Sadrian 163250003Sadrian} 164250003Sadrianvoid 165250003Sadrianar9300_set_cca_threshold(struct ath_hal *ah, u_int8_t thresh62) 166250003Sadrian{ 167250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_CCA_0, AR_PHY_CCA_THRESH62, thresh62); 168250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, thresh62); 169250003Sadrian /* 170250003Sadrian OS_REG_RMW_FIELD(ah, 171250003Sadrian AR_PHY_EXTCHN_PWRTHR1, AR_PHY_EXT_CCA0_THRESH62, thresh62); 172250003Sadrian */ 173250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_CCA_THRESH62, thresh62); 174250003Sadrian} 175250003Sadrian 176250003Sadrianstatic void ar9300_classify_strong_bins(struct ath_hal *ah) 177250003Sadrian{ 178250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_CF_BIN_THRESH, 0x1); 179250003Sadrian} 180250003Sadrian 181250003Sadrianvoid ar9300_disable_dc_offset(struct ath_hal *ah) 182250003Sadrian{ 183250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_TIMING2, AR_PHY_TIMING2_DC_OFFSET, 0); 184250003Sadrian} 185250003Sadrian 186250003Sadrianvoid ar9300_enable_cck_detect(struct ath_hal *ah) 187250003Sadrian{ 188250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DISABLE_CCK, 0); 189250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DYNAMIC, 1); 190250003Sadrian} 191250003Sadrian 192250003Sadrianvoid ar9300_prep_spectral_scan(struct ath_hal *ah) 193250003Sadrian{ 194250003Sadrian ar9300_disable_radar(ah); 195250003Sadrian ar9300_classify_strong_bins(ah); 196250003Sadrian ar9300_disable_dc_offset(ah); 197250003Sadrian if (AH_PRIVATE(ah)->ah_curchan && 198250003Sadrian IS_5GHZ_FAST_CLOCK_EN(ah, AH_PRIVATE(ah)->ah_curchan)) 199250003Sadrian { /* fast clock */ 200250003Sadrian ar9300_enable_cck_detect(ah); 201250003Sadrian } 202250003Sadrian#ifdef DEMO_MODE 203250003Sadrian ar9300_disable_strong_signal(ah); 204250003Sadrian ar9300_disable_weak_signal(ah); 205250003Sadrian ar9300_set_radar_dc_thresh(ah); 206250003Sadrian ar9300_set_cca_threshold(ah, MAX_CCA_THRESH); 207250003Sadrian /*ar9300_disable_restart(ah);*/ 208250003Sadrian#endif 209250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR, HAL_PHYERR_SPECTRAL); 210250003Sadrian} 211250003Sadrian 212250003Sadrian 213250003Sadrian//#define TEST_NOISE_PWR_WITHOUT_EEPROM 1 214250003Sadrian#ifdef TEST_NOISE_PWR_WITHOUT_EEPROM 215250003Sadrianstruct nf_cal { 216250003Sadrian int cal; 217250003Sadrian int pwr; 218250003Sadrian}; 219250003Sadrianstruct nf_cal_table_t { 220250003Sadrian int freq; 221250003Sadrian struct nf_cal chain[AH_MAX_CHAINS]; 222250003Sadrian}; 223250003Sadrian 224250003Sadrianstatic const struct nf_cal_table_t nf_cal_table[] = 225250003Sadrian{ 226250003Sadrian/* ch 1 */ {2412, { {N2DBM(-101, 00), N2DBM( -94, 25)}, 227250003Sadrian {N2DBM(-107, 75), N2DBM( -99, 75)}, 228250003Sadrian } }, 229250003Sadrian/* ch 6 */ {2437, { {N2DBM(-102, 25), N2DBM( -94, 25)}, 230250003Sadrian {N2DBM(-106, 00), N2DBM( -97, 25)}, 231250003Sadrian } }, 232250003Sadrian/* ch 11 */ {2462, { {N2DBM(-101, 50), N2DBM( -95, 00)}, 233250003Sadrian {N2DBM(-105, 50), N2DBM( -98, 00)}, 234250003Sadrian } }, 235250003Sadrian/* ch 36 */ {5180, { {N2DBM(-114, 25), N2DBM( -95, 00)}, 236250003Sadrian {N2DBM(-114, 75), N2DBM( -94, 00)}, 237250003Sadrian } }, 238250003Sadrian/* ch 44 */ {5220, { {N2DBM(-113, 00), N2DBM( -95, 00)}, 239250003Sadrian {N2DBM(-115, 00), N2DBM( -94, 50)}, 240250003Sadrian } }, 241250003Sadrian/* ch 64 */ {5320, { {N2DBM(-113, 00), N2DBM( -95, 00)}, // not cal'ed 242250003Sadrian {N2DBM(-115, 00), N2DBM( -94, 50)}, 243250003Sadrian } }, 244250003Sadrian/* ch 100*/ {5500, { {N2DBM(-111, 50), N2DBM( -93, 75)}, 245250003Sadrian {N2DBM(-112, 00), N2DBM( -95, 25)}, 246250003Sadrian } }, 247250003Sadrian/* ch 120*/ {5600, { {N2DBM(-111, 50), N2DBM( -93, 75)}, 248250003Sadrian {N2DBM(-112, 00), N2DBM( -95, 25)}, 249250003Sadrian } }, 250250003Sadrian/* ch 140*/ {5700, { {N2DBM(-111, 75), N2DBM( -95, 00)}, 251250003Sadrian {N2DBM(-111, 75), N2DBM( -96, 00)}, 252250003Sadrian } }, 253250003Sadrian/* ch 157*/ {5785, { {N2DBM(-112, 50), N2DBM( -94, 75)}, 254250003Sadrian {N2DBM(-111, 75), N2DBM( -95, 50)}, 255250003Sadrian } }, 256250003Sadrian/* ch 165*/ {5825, { {N2DBM(-111, 50), N2DBM( -95, 00)}, 257250003Sadrian {N2DBM(-112, 00), N2DBM( -95, 00)}, 258250003Sadrian } }, 259250003Sadrian {0} 260250003Sadrian}; 261250003Sadrian 262250003Sadrianstatic int 263250003Sadrianar9300_noise_floor_get(struct ath_hal *ah, int freq_mhz, int ch) 264250003Sadrian{ 265250003Sadrian int i; 266250003Sadrian for (i = 0; nf_cal_table[i].freq != 0; i++) { 267250003Sadrian if (nf_cal_table[i + 0].freq == freq_mhz || 268250003Sadrian nf_cal_table[i + 1].freq > freq_mhz || 269250003Sadrian nf_cal_table[i + 1].freq == 0) { 270250003Sadrian return nf_cal_table[i].chain[ch].cal; 271250003Sadrian } 272250003Sadrian } 273250003Sadrian 274250003Sadrian ath_hal_printf(ah, 275250003Sadrian "%s: **Warning: device %d.%d: " 276250003Sadrian "no nf cal offset found for freq %d chain %d\n", 277250003Sadrian __func__, (AH_PRIVATE(ah))->ah_macVersion, 278250003Sadrian (AH_PRIVATE(ah))->ah_macRev, freq_mhz, ch); 279250003Sadrian return 0; 280250003Sadrian} 281250003Sadrian 282250003Sadrianstatic int 283250003Sadrianar9300_noise_floor_power_get(struct ath_hal *ah, int freq_mhz, int ch) 284250003Sadrian{ 285250003Sadrian int i; 286250003Sadrian for (i = 0; nf_cal_table[i].freq != 0; i++) { 287250003Sadrian if (nf_cal_table[i + 0].freq == freq_mhz || 288250003Sadrian nf_cal_table[i + 1].freq > freq_mhz || 289250003Sadrian nf_cal_table[i + 1].freq == 0) { 290250003Sadrian return nf_cal_table[i].chain[ch].pwr; 291250003Sadrian } 292250003Sadrian } 293250003Sadrian 294250003Sadrian ath_hal_printf(ah, 295250003Sadrian "%s: **Warning: device %d.%d: " 296250003Sadrian "no nf pwr offset found for freq %d chain %d\n", 297250003Sadrian __func__, (AH_PRIVATE(ah))->ah_macVersion, 298250003Sadrian (AH_PRIVATE(ah))->ah_macRev, freq_mhz, ch); 299250003Sadrian return 0; 300250003Sadrian} 301250003Sadrian#else 302250003Sadrian#define ar9300_noise_floor_get(_ah,_f,_ich) ar9300_noise_floor_cal_or_power_get((_ah), (_f), (_ich), 1/*use_cal*/) 303250003Sadrian#define ar9300_noise_floor_power_get(_ah,_f,_ich) ar9300_noise_floor_cal_or_power_get((_ah), (_f), (_ich), 0/*use_cal*/) 304250003Sadrian#endif 305250003Sadrian 306250003Sadrian 307250003Sadrianvoid 308250003Sadrianar9300_configure_spectral_scan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) 309250003Sadrian{ 310250003Sadrian u_int32_t val, i; 311250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 312250003Sadrian HAL_BOOL asleep = ahp->ah_chip_full_sleep; 313250003Sadrian int16_t nf_buf[NUM_NF_READINGS]; 314250003Sadrian 315250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 316250003Sadrian ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE); 317250003Sadrian } 318250003Sadrian 319250003Sadrian ar9300_prep_spectral_scan(ah); 320250003Sadrian 321250003Sadrian if (ss->ss_spectral_pri) { 322250003Sadrian for (i = 0; i < NUM_NF_READINGS; i++) { 323250003Sadrian nf_buf[i] = NOISE_PWR_DBM_2_INT(ss->ss_nf_cal[i]); 324250003Sadrian } 325250003Sadrian ar9300_load_nf(ah, nf_buf); 326250003Sadrian#ifdef DEMO_MODE 327250003Sadrian ar9300_disable_strong_signal(ah); 328250003Sadrian ar9300_disable_weak_signal(ah); 329250003Sadrian ar9300_set_radar_dc_thresh(ah); 330250003Sadrian ar9300_set_cca_threshold(ah, MAX_CCA_THRESH); 331250003Sadrian /*ar9300_disable_restart(ah);*/ 332250003Sadrian#endif 333250003Sadrian } 334250003Sadrian 335250003Sadrian val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 336250003Sadrian 337250003Sadrian if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) { 338250003Sadrian val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD; 339250003Sadrian val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); 340250003Sadrian } 341250003Sadrian 342250003Sadrian if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { 343250003Sadrian val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; 344250003Sadrian val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); 345250003Sadrian } 346250003Sadrian 347250003Sadrian if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) { 348250003Sadrian val &= ~AR_PHY_SPECTRAL_SCAN_COUNT; 349250003Sadrian /* Remnants of a Merlin bug, 128 translates to 0 for 350250003Sadrian * continuous scanning. Instead we do piecemeal captures 351250003Sadrian * of 64 samples for Osprey. 352250003Sadrian */ 353250003Sadrian if (ss->ss_count == 128) { 354250003Sadrian val |= SM(0, AR_PHY_SPECTRAL_SCAN_COUNT); 355250003Sadrian } else { 356250003Sadrian val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT); 357250003Sadrian } 358250003Sadrian } 359250003Sadrian 360250003Sadrian if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { 361250003Sadrian val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; 362250003Sadrian val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); 363250003Sadrian } 364250003Sadrian 365250003Sadrian if (ss->ss_short_report == AH_TRUE) { 366250003Sadrian val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; 367250003Sadrian } else { 368250003Sadrian val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; 369250003Sadrian } 370250003Sadrian 371250003Sadrian /* if noise power cal, force high priority */ 372250003Sadrian if (ss->ss_spectral_pri) { 373250003Sadrian val |= AR_PHY_SPECTRAL_SCAN_PRIORITY_HI; 374250003Sadrian } else { 375250003Sadrian val &= ~AR_PHY_SPECTRAL_SCAN_PRIORITY_HI; 376250003Sadrian } 377250003Sadrian 378250003Sadrian /* enable spectral scan */ 379250003Sadrian OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENABLE); 380250003Sadrian 381250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 382250003Sadrian ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); 383250003Sadrian } 384250003Sadrian} 385250003Sadrian 386250003Sadrian/* 387250003Sadrian * Get the spectral parameter values and return them in the pe 388250003Sadrian * structure 389250003Sadrian */ 390250003Sadrian 391250003Sadrianvoid 392250003Sadrianar9300_get_spectral_params(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) 393250003Sadrian{ 394250003Sadrian u_int32_t val; 395250003Sadrian HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; 396250003Sadrian int i, ichain, rx_chain_status; 397250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 398250003Sadrian HAL_BOOL asleep = ahp->ah_chip_full_sleep; 399250003Sadrian 400250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 401250003Sadrian ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE); 402250003Sadrian } 403250003Sadrian 404250003Sadrian val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 405250003Sadrian 406250003Sadrian ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); 407250003Sadrian ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD); 408250003Sadrian ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT); 409250003Sadrian ss->ss_short_report = (val & AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT) ? 1:0; 410250003Sadrian ss->ss_spectral_pri = ( val & AR_PHY_SPECTRAL_SCAN_PRIORITY_HI) ? 1:0; 411250003Sadrian OS_MEMZERO(ss->ss_nf_cal, sizeof(ss->ss_nf_cal)); 412250003Sadrian OS_MEMZERO(ss->ss_nf_pwr, sizeof(ss->ss_nf_cal)); 413250003Sadrian ss->ss_nf_temp_data = 0; 414250003Sadrian 415250003Sadrian if (chan != NULL) { 416250003Sadrian rx_chain_status = OS_REG_READ(ah, AR_PHY_RX_CHAINMASK) & 0x7; 417250003Sadrian for (i = 0; i < NUM_NF_READINGS; i++) { 418250003Sadrian ichain = i % 3; 419250003Sadrian if (rx_chain_status & (1 << ichain)) { 420250003Sadrian ss->ss_nf_cal[i] = 421250003Sadrian ar9300_noise_floor_get(ah, chan->channel, ichain); 422250003Sadrian ss->ss_nf_pwr[i] = 423250003Sadrian ar9300_noise_floor_power_get(ah, chan->channel, ichain); 424250003Sadrian } 425250003Sadrian } 426250003Sadrian ss->ss_nf_temp_data = OS_REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, AR_PHY_BB_THERM_ADC_4_LATEST_THERM); 427250003Sadrian } else { 428250003Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, 429250003Sadrian "%s: chan is NULL - no ss nf values\n", __func__); 430250003Sadrian } 431250003Sadrian 432250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 433250003Sadrian ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); 434250003Sadrian } 435250003Sadrian} 436250003Sadrian 437250003SadrianHAL_BOOL 438250003Sadrianar9300_is_spectral_active(struct ath_hal *ah) 439250003Sadrian{ 440250003Sadrian u_int32_t val; 441250003Sadrian 442250003Sadrian val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 443250003Sadrian return MS(val, AR_PHY_SPECTRAL_SCAN_ACTIVE); 444250003Sadrian} 445250003Sadrian 446250003SadrianHAL_BOOL 447250003Sadrianar9300_is_spectral_enabled(struct ath_hal *ah) 448250003Sadrian{ 449250003Sadrian u_int32_t val; 450250003Sadrian 451250003Sadrian val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 452250003Sadrian return MS(val, AR_PHY_SPECTRAL_SCAN_ENABLE); 453250003Sadrian} 454250003Sadrian 455250003Sadrianvoid ar9300_start_spectral_scan(struct ath_hal *ah) 456250003Sadrian{ 457250003Sadrian u_int32_t val; 458250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 459250003Sadrian HAL_BOOL asleep = ahp->ah_chip_full_sleep; 460250003Sadrian 461250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 462250003Sadrian ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE); 463250003Sadrian } 464250003Sadrian 465250003Sadrian ar9300_prep_spectral_scan(ah); 466250003Sadrian 467250003Sadrian /* activate spectral scan */ 468250003Sadrian val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 469250003Sadrian /* This is a hardware bug fix, the enable and active bits should 470250003Sadrian * not be set/reset in the same write operation to the register 471250003Sadrian */ 472250003Sadrian if (!(val & AR_PHY_SPECTRAL_SCAN_ENABLE)) { 473250003Sadrian val |= AR_PHY_SPECTRAL_SCAN_ENABLE; 474250003Sadrian OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); 475250003Sadrian val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 476250003Sadrian } 477250003Sadrian val |= AR_PHY_SPECTRAL_SCAN_ACTIVE; 478250003Sadrian OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); 479250003Sadrian 480250003Sadrian /* Reset the PHY_ERR_MASK */ 481250003Sadrian val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG); 482250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR); 483250003Sadrian 484250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 485250003Sadrian ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); 486250003Sadrian } 487250003Sadrian} 488250003Sadrian 489250003Sadrianvoid ar9300_stop_spectral_scan(struct ath_hal *ah) 490250003Sadrian{ 491250003Sadrian u_int32_t val; 492250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 493250003Sadrian HAL_BOOL asleep = ahp->ah_chip_full_sleep; 494250003Sadrian 495250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 496250003Sadrian ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE); 497250003Sadrian } 498250003Sadrian val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 499250003Sadrian 500250003Sadrian /* deactivate spectral scan */ 501250003Sadrian /* HW Bug fix -- Do not disable the spectral scan 502250003Sadrian * only turn off the active bit 503250003Sadrian */ 504250003Sadrian //val &= ~AR_PHY_SPECTRAL_SCAN_ENABLE; 505250003Sadrian val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE; 506250003Sadrian OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); 507250003Sadrian val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 508250003Sadrian 509250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_CF_BIN_THRESH, 510250003Sadrian ahp->ah_radar1); 511250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_TIMING2, AR_PHY_TIMING2_DC_OFFSET, 512250003Sadrian ahp->ah_dc_offset); 513250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR, 0); 514250003Sadrian 515250003Sadrian if (AH_PRIVATE(ah)->ah_curchan && 516250003Sadrian IS_5GHZ_FAST_CLOCK_EN(ah, AH_PRIVATE(ah)->ah_curchan)) 517250003Sadrian { /* fast clock */ 518250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DISABLE_CCK, 519250003Sadrian ahp->ah_disable_cck); 520250003Sadrian } 521250003Sadrian 522250003Sadrian val = OS_REG_READ(ah, AR_PHY_ERR); 523250003Sadrian 524250003Sadrian val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR); 525250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val); 526250003Sadrian 527250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 528250003Sadrian ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); 529250003Sadrian } 530250003Sadrian} 531250003Sadrian 532250003Sadrianu_int32_t ar9300_get_spectral_config(struct ath_hal *ah) 533250003Sadrian{ 534250003Sadrian u_int32_t val; 535250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 536250003Sadrian HAL_BOOL asleep = ahp->ah_chip_full_sleep; 537250003Sadrian 538250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 539250003Sadrian ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE); 540250003Sadrian } 541250003Sadrian 542250003Sadrian val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 543250003Sadrian 544250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { 545250003Sadrian ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); 546250003Sadrian } 547250003Sadrian return val; 548250003Sadrian} 549250003Sadrian 550250003Sadrianint16_t ar9300_get_ctl_chan_nf(struct ath_hal *ah) 551250003Sadrian{ 552250003Sadrian int16_t nf; 553250003Sadrian struct ath_hal_private *ahpriv = AH_PRIVATE(ah); 554250003Sadrian 555250003Sadrian if ( (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) { 556250003Sadrian /* Noise floor calibration value is ready */ 557250003Sadrian nf = MS(OS_REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR); 558250003Sadrian } else { 559250003Sadrian /* NF calibration is not done, return nominal value */ 560250003Sadrian nf = ahpriv->nfp->nominal; 561250003Sadrian } 562250003Sadrian if (nf & 0x100) { 563250003Sadrian nf = (0 - ((nf ^ 0x1ff) + 1)); 564250003Sadrian } 565250003Sadrian return nf; 566250003Sadrian} 567250003Sadrian 568250003Sadrianint16_t ar9300_get_ext_chan_nf(struct ath_hal *ah) 569250003Sadrian{ 570250003Sadrian int16_t nf; 571250003Sadrian struct ath_hal_private *ahpriv = AH_PRIVATE(ah); 572250003Sadrian 573250003Sadrian if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) { 574250003Sadrian /* Noise floor calibration value is ready */ 575250003Sadrian nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); 576250003Sadrian } else { 577250003Sadrian /* NF calibration is not done, return nominal value */ 578250003Sadrian nf = ahpriv->nfp->nominal; 579250003Sadrian } 580250003Sadrian if (nf & 0x100) { 581250003Sadrian nf = (0 - ((nf ^ 0x1ff) + 1)); 582250003Sadrian } 583250003Sadrian return nf; 584250003Sadrian} 585250003Sadrian 586250003Sadrian#endif 587250003Sadrian#endif /* ATH_SUPPORT_SPECTRAL */ 588250003Sadrian 589