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