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 17250003Sadrian 18250003Sadrian#include "opt_ah.h" 19250003Sadrian 20250003Sadrian#include "ah.h" 21250003Sadrian#include "ah_desc.h" 22250003Sadrian#include "ah_internal.h" 23250003Sadrian 24250003Sadrian#include "ar9300/ar9300.h" 25250003Sadrian#include "ar9300/ar9300phy.h" 26250003Sadrian#include "ar9300/ar9300reg.h" 27250003Sadrian 28250003Sadrian/* 29250003Sadrian * Default 5413/9300 radar phy parameters 30250003Sadrian * Values adjusted to fix EV76432/EV76320 31250003Sadrian */ 32250003Sadrian#define AR9300_DFS_FIRPWR -28 33250003Sadrian#define AR9300_DFS_RRSSI 0 34250003Sadrian#define AR9300_DFS_HEIGHT 10 35250003Sadrian#define AR9300_DFS_PRSSI 6 36250003Sadrian#define AR9300_DFS_INBAND 8 37250003Sadrian#define AR9300_DFS_RELPWR 8 38250003Sadrian#define AR9300_DFS_RELSTEP 12 39250003Sadrian#define AR9300_DFS_MAXLEN 255 40250008Sadrian 41250008Sadrian/* 42250008Sadrian * This PRSSI value should be used during CAC. 43250008Sadrian */ 44250003Sadrian#define AR9300_DFS_PRSSI_CAC 10 45250003Sadrian 46250003Sadrian/* 47250003Sadrian * make sure that value matches value in ar9300_osprey_2p2_mac_core[][2] 48250003Sadrian * for register 0x1040 to 0x104c 49250003Sadrian*/ 50250003Sadrian#define AR9300_DEFAULT_DIFS 0x002ffc0f 51250003Sadrian#define AR9300_FCC_RADARS_FCC_OFFSET 4 52250003Sadrian 53250003Sadrianstruct dfs_pulse ar9300_etsi_radars[] = { 54250003Sadrian 55250003Sadrian /* for short pulses, RSSI threshold should be smaller than 56250003Sadrian * Kquick-drop. The chip has only one chance to drop the gain which 57250003Sadrian * will be reported as the estimated RSSI */ 58250003Sadrian 59250003Sadrian /* TYPE staggered pulse */ 60250003Sadrian /* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */ 61250003Sadrian {30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 31}, /* Type 5*/ 62250003Sadrian /* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */ 63250003Sadrian {30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 32}, /* Type 6 */ 64250003Sadrian 65250003Sadrian /* constant PRF based */ 66250003Sadrian /* 0.8-5us, 200 300 PRF, 10 pulses */ 67250003Sadrian {10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, /* Type 1 */ 68250003Sadrian {10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 37}, /* Type 1 */ 69250003Sadrian {10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 38}, /* Type 1 */ 70250003Sadrian {10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 39}, /* Type 1 */ 71250003Sadrian// {10, 5, 200, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, 72250003Sadrian 73250003Sadrian /* 0.8-15us, 200-1600 PRF, 15 pulses */ 74250003Sadrian {15, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 34}, /* Type 2 */ 75250003Sadrian 76250003Sadrian /* 0.8-15us, 2300-4000 PRF, 25 pulses*/ 77250003Sadrian {25, 15, 2300, 4000, 0, 24, 10, 0, 18, 24, 0, 0, 0, 35}, /* Type 3 */ 78250003Sadrian 79250003Sadrian /* 20-30us, 2000-4000 PRF, 20 pulses*/ 80250003Sadrian {20, 30, 2000, 4000, 0, 24, 8, 19, 33, 24, 0, 0, 0, 36}, /* Type 4 */ 81250003Sadrian}; 82250003Sadrian 83250003Sadrian 84250003Sadrian/* The following are for FCC Bin 1-4 pulses */ 85250003Sadrianstruct dfs_pulse ar9300_fcc_radars[] = { 86250003Sadrian 87250003Sadrian /* following two filters are specific to Japan/MKK4 */ 88250003Sadrian// {18, 1, 720, 720, 1, 6, 6, 0, 1, 18, 0, 3, 0, 17}, // 1389 +/- 6 us 89250003Sadrian// {18, 4, 250, 250, 1, 10, 5, 1, 6, 18, 0, 3, 0, 18}, // 4000 +/- 6 us 90250003Sadrian// {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 0, 19}, // 3846 +/- 7 us 91250003Sadrian {18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17}, // 1389 +/- 6 us 92250003Sadrian {18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18}, // 4000 +/- 6 us 93250003Sadrian {18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 19}, // 3846 +/- 7 us 94250003Sadrian// {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 1, 20}, // 3846 +/- 7 us 95250003Sadrian 96250003Sadrian {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 1, 20}, // 3846 +/- 7 us 97250003Sadrian 98250003Sadrian 99250003Sadrian /* following filters are common to both FCC and JAPAN */ 100250003Sadrian 101250003Sadrian // FCC TYPE 1 102250003Sadrian // {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0, 0}, // 518 to 3066 103250003Sadrian {18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 8}, 104250003Sadrian {18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0}, 105250003Sadrian 106250003Sadrian 107250003Sadrian // FCC TYPE 6 108250003Sadrian // {9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 0, 1}, // 333 +/- 7 us 109250003Sadrian //{9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 0, 1}, 110250003Sadrian {9, 1, 3003, 3003, 0, 7, 5, 0, 1, 18, 0, 0, 1, 1}, 111250003Sadrian 112250003Sadrian // FCC TYPE 2 113250003Sadrian {23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2}, 114250003Sadrian 115250003Sadrian // FCC TYPE 3 116250003Sadrian {18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5}, 117250003Sadrian 118250003Sadrian // FCC TYPE 4 119250003Sadrian {16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11}, 120250003Sadrian 121250003Sadrian}; 122250003Sadrian 123250003Sadrianstruct dfs_bin5pulse ar9300_bin5pulses[] = { 124250003Sadrian {2, 28, 105, 12, 22, 5}, 125250003Sadrian}; 126250003Sadrian 127250003Sadrian 128250008Sadrian#if 0 129250003Sadrian/* 130250003Sadrian * Find the internal HAL channel corresponding to the 131250003Sadrian * public HAL channel specified in c 132250003Sadrian */ 133250003Sadrian 134250003Sadrianstatic HAL_CHANNEL_INTERNAL * 135250008Sadriangetchannel(struct ath_hal *ah, const struct ieee80211_channel *c) 136250003Sadrian{ 137250003Sadrian#define CHAN_FLAGS (CHANNEL_ALL | CHANNEL_HALF | CHANNEL_QUARTER) 138250003Sadrian HAL_CHANNEL_INTERNAL *base, *cc; 139250003Sadrian int flags = c->channel_flags & CHAN_FLAGS; 140250003Sadrian int n, lim; 141250003Sadrian 142250003Sadrian /* 143250003Sadrian * Check current channel to avoid the lookup. 144250003Sadrian */ 145250003Sadrian cc = AH_PRIVATE(ah)->ah_curchan; 146250003Sadrian if (cc != AH_NULL && cc->channel == c->channel && 147250003Sadrian (cc->channel_flags & CHAN_FLAGS) == flags) { 148250003Sadrian return cc; 149250003Sadrian } 150250003Sadrian 151250003Sadrian /* binary search based on known sorting order */ 152250003Sadrian base = AH_TABLES(ah)->ah_channels; 153250003Sadrian n = AH_PRIVATE(ah)->ah_nchan; 154250003Sadrian /* binary search based on known sorting order */ 155250003Sadrian for (lim = n; lim != 0; lim >>= 1) { 156250003Sadrian int d; 157250003Sadrian cc = &base[lim >> 1]; 158250003Sadrian d = c->channel - cc->channel; 159250003Sadrian if (d == 0) { 160250003Sadrian if ((cc->channel_flags & CHAN_FLAGS) == flags) { 161250003Sadrian return cc; 162250003Sadrian } 163250003Sadrian d = flags - (cc->channel_flags & CHAN_FLAGS); 164250003Sadrian } 165250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: channel %u/0x%x d %d\n", __func__, 166250003Sadrian cc->channel, cc->channel_flags, d); 167250003Sadrian if (d > 0) { 168250003Sadrian base = cc + 1; 169250003Sadrian lim--; 170250003Sadrian } 171250003Sadrian } 172250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: no match for %u/0x%x\n", 173250003Sadrian __func__, c->channel, c->channel_flags); 174250003Sadrian return AH_NULL; 175250003Sadrian#undef CHAN_FLAGS 176250003Sadrian} 177250003Sadrian 178250003Sadrian/* 179250003Sadrian * Check the internal channel list to see if the desired channel 180250003Sadrian * is ok to release from the NOL. If not, then do nothing. If so, 181250003Sadrian * mark the channel as clear and reset the internal tsf time 182250003Sadrian */ 183250003Sadrianvoid 184250008Sadrianar9300_check_dfs(struct ath_hal *ah, struct ieee80211_channel *chan) 185250003Sadrian{ 186250003Sadrian HAL_CHANNEL_INTERNAL *ichan = AH_NULL; 187250003Sadrian 188250003Sadrian ichan = getchannel(ah, chan); 189250003Sadrian if (ichan == AH_NULL) { 190250003Sadrian return; 191250003Sadrian } 192250003Sadrian if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) { 193250003Sadrian return; 194250003Sadrian } 195250003Sadrian 196250003Sadrian ichan->priv_flags &= ~CHANNEL_INTERFERENCE; 197250003Sadrian ichan->dfs_tsf = 0; 198250003Sadrian} 199250003Sadrian 200250003Sadrian/* 201250003Sadrian * This function marks the channel as having found a dfs event 202250003Sadrian * It also marks the end time that the dfs event should be cleared 203250003Sadrian * If the channel is already marked, then tsf end time can only 204250003Sadrian * be increased 205250003Sadrian */ 206250003Sadrianvoid 207250008Sadrianar9300_dfs_found(struct ath_hal *ah, struct ieee80211_channel *chan, u_int64_t nol_time) 208250003Sadrian{ 209250003Sadrian HAL_CHANNEL_INTERNAL *ichan; 210250003Sadrian 211250003Sadrian ichan = getchannel(ah, chan); 212250003Sadrian if (ichan == AH_NULL) { 213250003Sadrian return; 214250003Sadrian } 215250003Sadrian if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) { 216250003Sadrian ichan->dfs_tsf = ar9300_get_tsf64(ah); 217250003Sadrian } 218250003Sadrian ichan->dfs_tsf += nol_time; 219250003Sadrian ichan->priv_flags |= CHANNEL_INTERFERENCE; 220250003Sadrian chan->priv_flags |= CHANNEL_INTERFERENCE; 221250003Sadrian} 222250008Sadrian#endif 223250003Sadrian 224250003Sadrian/* 225250003Sadrian * Enable radar detection and set the radar parameters per the 226250003Sadrian * values in pe 227250003Sadrian */ 228250003Sadrianvoid 229250003Sadrianar9300_enable_dfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 230250003Sadrian{ 231250003Sadrian u_int32_t val; 232250003Sadrian struct ath_hal_private *ahp = AH_PRIVATE(ah); 233250008Sadrian const struct ieee80211_channel *chan = ahp->ah_curchan; 234250003Sadrian struct ath_hal_9300 *ah9300 = AH9300(ah); 235250003Sadrian int reg_writes = 0; 236250003Sadrian 237250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 238250003Sadrian val |= AR_PHY_RADAR_0_FFT_ENA | AR_PHY_RADAR_0_ENA; 239250003Sadrian if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { 240250003Sadrian val &= ~AR_PHY_RADAR_0_FIRPWR; 241250003Sadrian val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); 242250003Sadrian } 243250003Sadrian if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { 244250003Sadrian val &= ~AR_PHY_RADAR_0_RRSSI; 245250003Sadrian val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); 246250003Sadrian } 247250003Sadrian if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { 248250003Sadrian val &= ~AR_PHY_RADAR_0_HEIGHT; 249250003Sadrian val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); 250250003Sadrian } 251250003Sadrian if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { 252250003Sadrian val &= ~AR_PHY_RADAR_0_PRSSI; 253250003Sadrian if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { 254250008Sadrian#if 0 255250003Sadrian if (ah->ah_use_cac_prssi) { 256250003Sadrian val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI); 257250003Sadrian } else { 258250008Sadrian#endif 259250003Sadrian val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); 260250008Sadrian// } 261250003Sadrian } else { 262250003Sadrian val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); 263250003Sadrian } 264250003Sadrian } 265250003Sadrian if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { 266250003Sadrian val &= ~AR_PHY_RADAR_0_INBAND; 267250003Sadrian val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); 268250003Sadrian } 269250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 270250003Sadrian 271250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_1); 272250003Sadrian val |= AR_PHY_RADAR_1_MAX_RRSSI | AR_PHY_RADAR_1_BLOCK_CHECK; 273250003Sadrian if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) { 274250003Sadrian val &= ~AR_PHY_RADAR_1_MAXLEN; 275250003Sadrian val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN); 276250003Sadrian } 277250003Sadrian if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) { 278250003Sadrian val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH; 279250003Sadrian val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH); 280250003Sadrian } 281250003Sadrian if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) { 282250003Sadrian val &= ~AR_PHY_RADAR_1_RELPWR_THRESH; 283250003Sadrian val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH); 284250003Sadrian } 285250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); 286250003Sadrian 287250003Sadrian if (ath_hal_getcapability(ah, HAL_CAP_EXT_CHAN_DFS, 0, 0) == HAL_OK) { 288250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); 289250008Sadrian if (IEEE80211_IS_CHAN_HT40(chan)) { 290250003Sadrian /* Enable extension channel radar detection */ 291250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val | AR_PHY_RADAR_EXT_ENA); 292250003Sadrian } else { 293250003Sadrian /* HT20 mode, disable extension channel radar detect */ 294250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA); 295250003Sadrian } 296250003Sadrian } 297250003Sadrian /* 298250003Sadrian apply DFS postamble array from INI 299250003Sadrian column 0 is register ID, column 1 is HT20 value, colum2 is HT40 value 300250003Sadrian */ 301250003Sadrian 302250003Sadrian if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_OSPREY_22(ah) || AR_SREV_SCORPION(ah)) { 303250008Sadrian REG_WRITE_ARRAY(&ah9300->ah_ini_dfs, IEEE80211_IS_CHAN_HT40(chan)? 2:1, reg_writes); 304250003Sadrian } 305250003Sadrian#ifdef ATH_HAL_DFS_CHIRPING_FIX_APH128 306250008Sadrian ath_hal_printf(ah, "DFS change the timing value\n"); 307250008Sadrian if (AR_SREV_AR9580(ah) && IEEE80211_IS_CHAN_HT40(chan)) { 308250008Sadrian OS_REG_WRITE(ah, AR_PHY_TIMING6, 0x3140c00a); 309250003Sadrian } 310250003Sadrian#endif 311250003Sadrian 312250003Sadrian} 313250003Sadrian 314250003Sadrian/* 315250003Sadrian * Get the radar parameter values and return them in the pe 316250003Sadrian * structure 317250003Sadrian */ 318250003Sadrianvoid 319250003Sadrianar9300_get_dfs_thresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 320250003Sadrian{ 321250003Sadrian u_int32_t val, temp; 322250003Sadrian 323250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 324250003Sadrian temp = MS(val, AR_PHY_RADAR_0_FIRPWR); 325250003Sadrian temp |= ~(AR_PHY_RADAR_0_FIRPWR >> AR_PHY_RADAR_0_FIRPWR_S); 326250003Sadrian pe->pe_firpwr = temp; 327250003Sadrian pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); 328250003Sadrian pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); 329250003Sadrian pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); 330250003Sadrian pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); 331250003Sadrian 332250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_1); 333250003Sadrian 334250003Sadrian pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH); 335250008Sadrian pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_1_RELPWR_ENA); 336250008Sadrian 337250003Sadrian pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH); 338250008Sadrian pe->pe_en_relstep_check = !! (val & AR_PHY_RADAR_1_RELSTEP_CHECK); 339250008Sadrian 340250003Sadrian pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN); 341250003Sadrian} 342250003Sadrian 343250008Sadrian#if 0 344250003SadrianHAL_BOOL 345250008Sadrianar9300_radar_wait(struct ath_hal *ah, struct ieee80211_channel *chan) 346250003Sadrian{ 347250003Sadrian struct ath_hal_private *ahp = AH_PRIVATE(ah); 348250003Sadrian 349250003Sadrian if (!ahp->ah_curchan) { 350250003Sadrian return AH_TRUE; 351250003Sadrian } 352250003Sadrian 353250003Sadrian /* 354250003Sadrian * Rely on the upper layers to determine that we have spent 355250003Sadrian * enough time waiting. 356250003Sadrian */ 357250003Sadrian chan->channel = ahp->ah_curchan->channel; 358250003Sadrian chan->channel_flags = ahp->ah_curchan->channel_flags; 359250003Sadrian chan->max_reg_tx_power = ahp->ah_curchan->max_reg_tx_power; 360250003Sadrian 361250003Sadrian ahp->ah_curchan->priv_flags |= CHANNEL_DFS_CLEAR; 362250003Sadrian chan->priv_flags = ahp->ah_curchan->priv_flags; 363250003Sadrian return AH_FALSE; 364250003Sadrian 365250003Sadrian} 366250008Sadrian#endif 367250003Sadrian 368250003Sadrianstruct dfs_pulse * 369250003Sadrianar9300_get_dfs_radars( 370250003Sadrian struct ath_hal *ah, 371250003Sadrian u_int32_t dfsdomain, 372250003Sadrian int *numradars, 373250003Sadrian struct dfs_bin5pulse **bin5pulses, 374250003Sadrian int *numb5radars, 375250003Sadrian HAL_PHYERR_PARAM *pe) 376250003Sadrian{ 377250003Sadrian struct dfs_pulse *dfs_radars = AH_NULL; 378250003Sadrian switch (dfsdomain) { 379250008Sadrian case HAL_DFS_FCC_DOMAIN: 380250003Sadrian dfs_radars = &ar9300_fcc_radars[AR9300_FCC_RADARS_FCC_OFFSET]; 381250003Sadrian *numradars = 382250003Sadrian ARRAY_LENGTH(ar9300_fcc_radars) - AR9300_FCC_RADARS_FCC_OFFSET; 383250003Sadrian *bin5pulses = &ar9300_bin5pulses[0]; 384250003Sadrian *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses); 385250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_FCC_DOMAIN_9300\n", __func__); 386250003Sadrian break; 387250008Sadrian case HAL_DFS_ETSI_DOMAIN: 388250003Sadrian dfs_radars = &ar9300_etsi_radars[0]; 389250003Sadrian *numradars = ARRAY_LENGTH(ar9300_etsi_radars); 390250003Sadrian *bin5pulses = &ar9300_bin5pulses[0]; 391250003Sadrian *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses); 392250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_ETSI_DOMAIN_9300\n", __func__); 393250003Sadrian break; 394250008Sadrian case HAL_DFS_MKK4_DOMAIN: 395250003Sadrian dfs_radars = &ar9300_fcc_radars[0]; 396250003Sadrian *numradars = ARRAY_LENGTH(ar9300_fcc_radars); 397250003Sadrian *bin5pulses = &ar9300_bin5pulses[0]; 398250003Sadrian *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses); 399250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_MKK4_DOMAIN_9300\n", __func__); 400250003Sadrian break; 401250003Sadrian default: 402250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: no domain\n", __func__); 403250003Sadrian return AH_NULL; 404250003Sadrian } 405250003Sadrian /* Set the default phy parameters per chip */ 406250003Sadrian pe->pe_firpwr = AR9300_DFS_FIRPWR; 407250003Sadrian pe->pe_rrssi = AR9300_DFS_RRSSI; 408250003Sadrian pe->pe_height = AR9300_DFS_HEIGHT; 409250003Sadrian pe->pe_prssi = AR9300_DFS_PRSSI; 410250003Sadrian /* 411250003Sadrian we have an issue with PRSSI. 412250003Sadrian For normal operation we use AR9300_DFS_PRSSI, which is set to 6. 413250003Sadrian Please refer to EV91563, 94164. 414250003Sadrian However, this causes problem during CAC as no radar is detected 415250003Sadrian during that period with PRSSI=6. Only PRSSI= 10 seems to fix this. 416250003Sadrian We use this flag to keep track of change in PRSSI. 417250003Sadrian */ 418250003Sadrian 419250008Sadrian// ah->ah_use_cac_prssi = 0; 420250003Sadrian 421250003Sadrian pe->pe_inband = AR9300_DFS_INBAND; 422250003Sadrian pe->pe_relpwr = AR9300_DFS_RELPWR; 423250003Sadrian pe->pe_relstep = AR9300_DFS_RELSTEP; 424250003Sadrian pe->pe_maxlen = AR9300_DFS_MAXLEN; 425250003Sadrian return dfs_radars; 426250003Sadrian} 427250003Sadrian 428250003Sadrianvoid ar9300_adjust_difs(struct ath_hal *ah, u_int32_t val) 429250003Sadrian{ 430250003Sadrian if (val == 0) { 431250003Sadrian /* 432250003Sadrian * EV 116936: 433250003Sadrian * Restore the register values with that of the HAL structure. 434250003Sadrian * Do not assume and overwrite these values to whatever 435250003Sadrian * is in ar9300_osprey22.ini. 436250003Sadrian */ 437250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 438250003Sadrian HAL_TX_QUEUE_INFO *qi; 439250003Sadrian int q; 440250003Sadrian 441250008Sadrian AH9300(ah)->ah_fccaifs = 0; 442250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: restore DIFS \n", __func__); 443250003Sadrian for (q = 0; q < 4; q++) { 444250003Sadrian qi = &ahp->ah_txq[q]; 445250003Sadrian OS_REG_WRITE(ah, AR_DLCL_IFS(q), 446250003Sadrian SM(qi->tqi_cwmin, AR_D_LCL_IFS_CWMIN) 447250003Sadrian | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) 448250003Sadrian | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); 449250003Sadrian } 450250003Sadrian } else { 451250003Sadrian /* 452250003Sadrian * These are values from George Lai and are specific to 453250003Sadrian * FCC domain. They are yet to be determined for other domains. 454250003Sadrian */ 455250003Sadrian 456250008Sadrian AH9300(ah)->ah_fccaifs = 1; 457250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: set DIFS to default\n", __func__); 458250003Sadrian /*printk("%s: modify DIFS\n", __func__);*/ 459250003Sadrian 460250003Sadrian OS_REG_WRITE(ah, AR_DLCL_IFS(0), 0x05fffc0f); 461250003Sadrian OS_REG_WRITE(ah, AR_DLCL_IFS(1), 0x05f0fc0f); 462250003Sadrian OS_REG_WRITE(ah, AR_DLCL_IFS(2), 0x05f03c07); 463250003Sadrian OS_REG_WRITE(ah, AR_DLCL_IFS(3), 0x05f01c03); 464250003Sadrian } 465250003Sadrian} 466250003Sadrian 467250003Sadrianu_int32_t ar9300_dfs_config_fft(struct ath_hal *ah, HAL_BOOL is_enable) 468250003Sadrian{ 469250003Sadrian u_int32_t val; 470250003Sadrian 471250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 472250003Sadrian 473250003Sadrian if (is_enable) { 474250003Sadrian val |= AR_PHY_RADAR_0_FFT_ENA; 475250003Sadrian } else { 476250003Sadrian val &= ~AR_PHY_RADAR_0_FFT_ENA; 477250003Sadrian } 478250003Sadrian 479250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 480250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 481250003Sadrian return val; 482250003Sadrian} 483250003Sadrian/* 484250003Sadrian function to adjust PRSSI value for CAC problem 485250003Sadrian 486250003Sadrian*/ 487250003Sadrianvoid 488250003Sadrianar9300_dfs_cac_war(struct ath_hal *ah, u_int32_t start) 489250003Sadrian{ 490250003Sadrian u_int32_t val; 491250003Sadrian 492250003Sadrian if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { 493250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 494250003Sadrian if (start) { 495250003Sadrian val &= ~AR_PHY_RADAR_0_PRSSI; 496250003Sadrian val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI); 497250003Sadrian } else { 498250003Sadrian val &= ~AR_PHY_RADAR_0_PRSSI; 499250003Sadrian val |= SM(AR9300_DFS_PRSSI, AR_PHY_RADAR_0_PRSSI); 500250003Sadrian } 501250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA); 502250008Sadrian// ah->ah_use_cac_prssi = start; 503250003Sadrian } 504250003Sadrian} 505250003Sadrian 506250008Sadrian#if 0 507250008Sadrianstruct ieee80211_channel * 508250003Sadrianar9300_get_extension_channel(struct ath_hal *ah) 509250003Sadrian{ 510250003Sadrian struct ath_hal_private *ahp = AH_PRIVATE(ah); 511250003Sadrian struct ath_hal_private_tables *aht = AH_TABLES(ah); 512250003Sadrian int i = 0; 513250003Sadrian 514250003Sadrian HAL_CHANNEL_INTERNAL *ichan = AH_NULL; 515250003Sadrian CHAN_CENTERS centers; 516250003Sadrian 517250003Sadrian ichan = ahp->ah_curchan; 518250003Sadrian ar9300_get_channel_centers(ah, ichan, ¢ers); 519250003Sadrian if (centers.ctl_center == centers.ext_center) { 520250003Sadrian return AH_NULL; 521250003Sadrian } 522250003Sadrian for (i = 0; i < ahp->ah_nchan; i++) { 523250003Sadrian ichan = &aht->ah_channels[i]; 524250003Sadrian if (ichan->channel == centers.ext_center) { 525250008Sadrian return (struct ieee80211_channel*)ichan; 526250003Sadrian } 527250003Sadrian } 528250003Sadrian return AH_NULL; 529250003Sadrian} 530250008Sadrian#endif 531250003Sadrian 532250003SadrianHAL_BOOL 533250003Sadrianar9300_is_fast_clock_enabled(struct ath_hal *ah) 534250003Sadrian{ 535250003Sadrian struct ath_hal_private *ahp = AH_PRIVATE(ah); 536250003Sadrian 537250003Sadrian if (IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan)) { 538250003Sadrian return AH_TRUE; 539250003Sadrian } 540250003Sadrian return AH_FALSE; 541250003Sadrian} 542250003Sadrian 543250008Sadrian/* 544250008Sadrian * This should be enabled and linked into the build once 545250008Sadrian * radar support is enabled. 546250008Sadrian */ 547250008Sadrian#if 0 548250003SadrianHAL_BOOL 549250003Sadrianar9300_handle_radar_bb_panic(struct ath_hal *ah) 550250003Sadrian{ 551250003Sadrian u_int32_t status; 552250003Sadrian u_int32_t val; 553250003Sadrian#ifdef AH_DEBUG 554250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 555250003Sadrian#endif 556250003Sadrian 557250003Sadrian status = AH_PRIVATE(ah)->ah_bb_panic_last_status; 558250003Sadrian 559250003Sadrian if ( status == 0x04000539 ) { 560250003Sadrian /* recover from this BB panic without reset*/ 561250003Sadrian /* set AR9300_DFS_FIRPWR to -1 */ 562250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 563250003Sadrian val &= (~AR_PHY_RADAR_0_FIRPWR); 564250003Sadrian val |= SM( 0x7f, AR_PHY_RADAR_0_FIRPWR); 565250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 566250003Sadrian OS_DELAY(1); 567250003Sadrian /* set AR9300_DFS_FIRPWR to its default value */ 568250003Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 569250003Sadrian val &= ~AR_PHY_RADAR_0_FIRPWR; 570250003Sadrian val |= SM( AR9300_DFS_FIRPWR, AR_PHY_RADAR_0_FIRPWR); 571250003Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 572250003Sadrian return AH_TRUE; 573250003Sadrian } else if (status == 0x0400000a) { 574250003Sadrian /* EV 92527 : reset required if we see this signature */ 575250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: BB Panic -- 0x0400000a\n", __func__); 576250003Sadrian return AH_FALSE; 577250003Sadrian } else if (status == 0x1300000a) { 578250003Sadrian /* EV92527: we do not need a reset if we see this signature */ 579250003Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: BB Panic -- 0x1300000a\n", __func__); 580250003Sadrian return AH_TRUE; 581291437Sadrian } else if ((AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) && (status == 0x04000409)) { 582250003Sadrian return AH_TRUE; 583250003Sadrian } else { 584250003Sadrian if (ar9300_get_capability(ah, HAL_CAP_LDPCWAR, 0, AH_NULL) == HAL_OK && 585250003Sadrian (status & 0xff00000f) == 0x04000009 && 586250003Sadrian status != 0x04000409 && 587250003Sadrian status != 0x04000b09 && 588250003Sadrian status != 0x04000e09 && 589250003Sadrian (status & 0x0000ff00)) 590250003Sadrian { 591250003Sadrian /* disable RIFS Rx */ 592250003Sadrian#ifdef AH_DEBUG 593250003Sadrian HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: BB status=0x%08x rifs=%d - disable\n", 594250003Sadrian __func__, status, ahp->ah_rifs_enabled); 595250003Sadrian ar9300_set_rifs_delay(ah, AH_FALSE); 596250003Sadrian } 597250003Sadrian return AH_FALSE; 598250003Sadrian } 599250003Sadrian} 600250003Sadrian#endif 601250008Sadrian#endif 602