1 /*- 2 * SPDX-License-Identifier: ISC 3 * 4 * Copyright (c) 2012 Qualcomm Atheros, All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 #include "opt_ah.h" 19 20 #include "ah.h" 21 #include "ah_internal.h" 22 #include "ah_devid.h" 23 #include "ah_desc.h" /* NB: for HAL_PHYERR* */ 24 25 #include "ar5416/ar5416.h" 26 #include "ar5416/ar5416reg.h" 27 #include "ar5416/ar5416phy.h" 28 29 /* 30 * Default AR9280 spectral scan parameters 31 */ 32 #define AR5416_SPECTRAL_SCAN_ENA 0 33 #define AR5416_SPECTRAL_SCAN_ACTIVE 0 34 #define AR5416_SPECTRAL_SCAN_FFT_PERIOD 8 35 #define AR5416_SPECTRAL_SCAN_PERIOD 1 36 #define AR5416_SPECTRAL_SCAN_COUNT 16 //used to be 128 37 #define AR5416_SPECTRAL_SCAN_SHORT_REPEAT 1 38 39 /* constants */ 40 #define MAX_RADAR_RSSI_THRESH 0x3f 41 #define MAX_RADAR_HEIGHT 0x3f 42 #define ENABLE_ALL_PHYERR 0xffffffff 43 44 static void ar5416DisableRadar(struct ath_hal *ah); 45 static void ar5416PrepSpectralScan(struct ath_hal *ah); 46 47 static void 48 ar5416DisableRadar(struct ath_hal *ah) 49 { 50 uint32_t val; 51 52 // Enable radar FFT 53 val = OS_REG_READ(ah, AR_PHY_RADAR_0); 54 val |= AR_PHY_RADAR_0_FFT_ENA; 55 56 // set radar detect thresholds to max to effectively disable radar 57 val &= ~AR_PHY_RADAR_0_RRSSI; 58 val |= SM(MAX_RADAR_RSSI_THRESH, AR_PHY_RADAR_0_RRSSI); 59 60 val &= ~AR_PHY_RADAR_0_HEIGHT; 61 val |= SM(MAX_RADAR_HEIGHT, AR_PHY_RADAR_0_HEIGHT); 62 63 val &= ~(AR_PHY_RADAR_0_ENA); 64 OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 65 66 // disable extension radar detect 67 val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); 68 OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA); 69 70 val = OS_REG_READ(ah, AR_RX_FILTER); 71 val |= (1<<13); 72 OS_REG_WRITE(ah, AR_RX_FILTER, val); 73 } 74 75 static void 76 ar5416PrepSpectralScan(struct ath_hal *ah) 77 { 78 79 ar5416DisableRadar(ah); 80 OS_REG_WRITE(ah, AR_PHY_ERR, ENABLE_ALL_PHYERR); 81 } 82 83 void 84 ar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) 85 { 86 uint32_t val; 87 88 ar5416PrepSpectralScan(ah); 89 90 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 91 92 if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) { 93 val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD; 94 val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); 95 } 96 97 if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { 98 val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; 99 val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); 100 } 101 102 if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { 103 val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; 104 val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); 105 } 106 107 /* This section is different for Kiwi and Merlin */ 108 if (AR_SREV_MERLIN(ah) ) { 109 if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) { 110 val &= ~AR_PHY_SPECTRAL_SCAN_COUNT; 111 val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT); 112 } 113 114 if (ss->ss_short_report == AH_TRUE) { 115 val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; 116 } else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) { 117 val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; 118 } 119 } else { 120 if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) { 121 /* 122 * In Merlin, for continuous scan, scan_count = 128. 123 * In case of Kiwi, this value should be 0 124 */ 125 if (ss->ss_count == 128) 126 ss->ss_count = 0; 127 val &= ~AR_PHY_SPECTRAL_SCAN_COUNT_KIWI; 128 val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI); 129 } 130 131 if (ss->ss_short_report == AH_TRUE) { 132 val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; 133 } else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) { 134 val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; 135 } 136 137 //Select the mask to be same as before 138 val |= AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI; 139 } 140 // Enable spectral scan 141 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENA); 142 143 ar5416GetSpectralParams(ah, ss); 144 } 145 146 /* 147 * Get the spectral parameter values and return them in the pe 148 * structure 149 */ 150 void 151 ar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) 152 { 153 uint32_t val; 154 155 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 156 157 ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); 158 ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD); 159 if (AR_SREV_MERLIN(ah) ) { 160 ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT); 161 ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); 162 } else { 163 ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI); 164 ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI); 165 } 166 val = OS_REG_READ(ah, AR_PHY_RADAR_1); 167 ss->radar_bin_thresh_sel = MS(val, AR_PHY_RADAR_1_BIN_THRESH_SELECT); 168 } 169 170 HAL_BOOL 171 ar5416IsSpectralActive(struct ath_hal *ah) 172 { 173 uint32_t val; 174 175 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 176 return MS(val, AR_PHY_SPECTRAL_SCAN_ACTIVE); 177 } 178 179 HAL_BOOL 180 ar5416IsSpectralEnabled(struct ath_hal *ah) 181 { 182 uint32_t val; 183 184 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 185 return MS(val,AR_PHY_SPECTRAL_SCAN_ENA); 186 } 187 188 void 189 ar5416StartSpectralScan(struct ath_hal *ah) 190 { 191 uint32_t val; 192 193 ar5416PrepSpectralScan(ah); 194 195 // Activate spectral scan 196 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 197 val |= AR_PHY_SPECTRAL_SCAN_ENA; 198 val |= AR_PHY_SPECTRAL_SCAN_ACTIVE; 199 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); 200 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 201 val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG); 202 OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR); 203 } 204 205 void 206 ar5416StopSpectralScan(struct ath_hal *ah) 207 { 208 uint32_t val; 209 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 210 211 // Deactivate spectral scan 212 val &= ~AR_PHY_SPECTRAL_SCAN_ENA; 213 val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE; 214 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); 215 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 216 val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR); 217 OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val); 218 } 219 220 uint32_t 221 ar5416GetSpectralConfig(struct ath_hal *ah) 222 { 223 uint32_t val; 224 225 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 226 return val; 227 } 228 229 void 230 ar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval) 231 { 232 uint32_t curval; 233 234 ar5416PrepSpectralScan(ah); 235 236 curval = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 237 238 if (restoreval != curval) { 239 restoreval |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; 240 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, restoreval); 241 } 242 return; 243 } 244