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 * $FreeBSD$ 19 */ 20 #include "opt_ah.h" 21 22 #include "ah.h" 23 #include "ah_internal.h" 24 #include "ah_devid.h" 25 #include "ah_desc.h" /* NB: for HAL_PHYERR* */ 26 27 #include "ar5416/ar5416.h" 28 #include "ar5416/ar5416reg.h" 29 #include "ar5416/ar5416phy.h" 30 31 /* 32 * Default AR9280 spectral scan parameters 33 */ 34 #define AR5416_SPECTRAL_SCAN_ENA 0 35 #define AR5416_SPECTRAL_SCAN_ACTIVE 0 36 #define AR5416_SPECTRAL_SCAN_FFT_PERIOD 8 37 #define AR5416_SPECTRAL_SCAN_PERIOD 1 38 #define AR5416_SPECTRAL_SCAN_COUNT 16 //used to be 128 39 #define AR5416_SPECTRAL_SCAN_SHORT_REPEAT 1 40 41 /* constants */ 42 #define MAX_RADAR_RSSI_THRESH 0x3f 43 #define MAX_RADAR_HEIGHT 0x3f 44 #define ENABLE_ALL_PHYERR 0xffffffff 45 46 static void ar5416DisableRadar(struct ath_hal *ah); 47 static void ar5416PrepSpectralScan(struct ath_hal *ah); 48 49 static void 50 ar5416DisableRadar(struct ath_hal *ah) 51 { 52 uint32_t val; 53 54 // Enable radar FFT 55 val = OS_REG_READ(ah, AR_PHY_RADAR_0); 56 val |= AR_PHY_RADAR_0_FFT_ENA; 57 58 // set radar detect thresholds to max to effectively disable radar 59 val &= ~AR_PHY_RADAR_0_RRSSI; 60 val |= SM(MAX_RADAR_RSSI_THRESH, AR_PHY_RADAR_0_RRSSI); 61 62 val &= ~AR_PHY_RADAR_0_HEIGHT; 63 val |= SM(MAX_RADAR_HEIGHT, AR_PHY_RADAR_0_HEIGHT); 64 65 val &= ~(AR_PHY_RADAR_0_ENA); 66 OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 67 68 // disable extension radar detect 69 val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); 70 OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA); 71 72 val = OS_REG_READ(ah, AR_RX_FILTER); 73 val |= (1<<13); 74 OS_REG_WRITE(ah, AR_RX_FILTER, val); 75 } 76 77 static void 78 ar5416PrepSpectralScan(struct ath_hal *ah) 79 { 80 81 ar5416DisableRadar(ah); 82 OS_REG_WRITE(ah, AR_PHY_ERR, ENABLE_ALL_PHYERR); 83 } 84 85 void 86 ar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) 87 { 88 uint32_t val; 89 90 ar5416PrepSpectralScan(ah); 91 92 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 93 94 if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) { 95 val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD; 96 val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); 97 } 98 99 if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { 100 val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; 101 val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); 102 } 103 104 if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { 105 val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; 106 val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); 107 } 108 109 /* This section is different for Kiwi and Merlin */ 110 if (AR_SREV_MERLIN(ah) ) { 111 if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) { 112 val &= ~AR_PHY_SPECTRAL_SCAN_COUNT; 113 val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT); 114 } 115 116 if (ss->ss_short_report == AH_TRUE) { 117 val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; 118 } else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) { 119 val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; 120 } 121 } else { 122 if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) { 123 /* 124 * In Merlin, for continuous scan, scan_count = 128. 125 * In case of Kiwi, this value should be 0 126 */ 127 if (ss->ss_count == 128) 128 ss->ss_count = 0; 129 val &= ~AR_PHY_SPECTRAL_SCAN_COUNT_KIWI; 130 val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI); 131 } 132 133 if (ss->ss_short_report == AH_TRUE) { 134 val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; 135 } else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) { 136 val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; 137 } 138 139 //Select the mask to be same as before 140 val |= AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI; 141 } 142 // Enable spectral scan 143 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENA); 144 145 ar5416GetSpectralParams(ah, ss); 146 } 147 148 /* 149 * Get the spectral parameter values and return them in the pe 150 * structure 151 */ 152 void 153 ar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) 154 { 155 uint32_t val; 156 157 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 158 159 ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); 160 ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD); 161 if (AR_SREV_MERLIN(ah) ) { 162 ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT); 163 ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); 164 } else { 165 ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI); 166 ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI); 167 } 168 val = OS_REG_READ(ah, AR_PHY_RADAR_1); 169 ss->radar_bin_thresh_sel = MS(val, AR_PHY_RADAR_1_BIN_THRESH_SELECT); 170 } 171 172 HAL_BOOL 173 ar5416IsSpectralActive(struct ath_hal *ah) 174 { 175 uint32_t val; 176 177 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 178 return MS(val, AR_PHY_SPECTRAL_SCAN_ACTIVE); 179 } 180 181 HAL_BOOL 182 ar5416IsSpectralEnabled(struct ath_hal *ah) 183 { 184 uint32_t val; 185 186 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 187 return MS(val,AR_PHY_SPECTRAL_SCAN_ENA); 188 } 189 190 void 191 ar5416StartSpectralScan(struct ath_hal *ah) 192 { 193 uint32_t val; 194 195 ar5416PrepSpectralScan(ah); 196 197 // Activate spectral scan 198 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 199 val |= AR_PHY_SPECTRAL_SCAN_ENA; 200 val |= AR_PHY_SPECTRAL_SCAN_ACTIVE; 201 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); 202 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 203 val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG); 204 OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR); 205 } 206 207 void 208 ar5416StopSpectralScan(struct ath_hal *ah) 209 { 210 uint32_t val; 211 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 212 213 // Deactivate spectral scan 214 val &= ~AR_PHY_SPECTRAL_SCAN_ENA; 215 val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE; 216 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); 217 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 218 val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR); 219 OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val); 220 } 221 222 uint32_t 223 ar5416GetSpectralConfig(struct ath_hal *ah) 224 { 225 uint32_t val; 226 227 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 228 return val; 229 } 230 231 void 232 ar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval) 233 { 234 uint32_t curval; 235 236 ar5416PrepSpectralScan(ah); 237 238 curval = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); 239 240 if (restoreval != curval) { 241 restoreval |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; 242 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, restoreval); 243 } 244 return; 245 } 246