1389 lines · c
1/*2 * Copyright (c) 2008-2011 Atheros Communications Inc.3 *4 * Permission to use, copy, modify, and/or distribute this software for any5 * purpose with or without fee is hereby granted, provided that the above6 * copyright notice and this permission notice appear in all copies.7 *8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15 */16 17#include "hw.h"18#include "hw-ops.h"19#include "../regd.h"20#include "ar9002_phy.h"21 22/* All code below is for AR5008, AR9001, AR9002 */23 24#define AR5008_OFDM_RATES 825#define AR5008_HT_SS_RATES 826#define AR5008_HT_DS_RATES 827 28#define AR5008_HT20_SHIFT 1629#define AR5008_HT40_SHIFT 2430 31#define AR5008_11NA_OFDM_SHIFT 032#define AR5008_11NA_HT_SS_SHIFT 833#define AR5008_11NA_HT_DS_SHIFT 1634 35#define AR5008_11NG_OFDM_SHIFT 436#define AR5008_11NG_HT_SS_SHIFT 1237#define AR5008_11NG_HT_DS_SHIFT 2038 39/*40 * register values to turn OFDM weak signal detection OFF41 */42static const int m1ThreshLow_off = 127;43static const int m2ThreshLow_off = 127;44static const int m1Thresh_off = 127;45static const int m2Thresh_off = 127;46static const int m2CountThr_off = 31;47static const int m2CountThrLow_off = 63;48static const int m1ThreshLowExt_off = 127;49static const int m2ThreshLowExt_off = 127;50static const int m1ThreshExt_off = 127;51static const int m2ThreshExt_off = 127;52 53static const u32 ar5416Bank0[][2] = {54 /* Addr allmodes */55 {0x000098b0, 0x1e5795e5},56 {0x000098e0, 0x02008020},57};58 59static const u32 ar5416Bank1[][2] = {60 /* Addr allmodes */61 {0x000098b0, 0x02108421},62 {0x000098ec, 0x00000008},63};64 65static const u32 ar5416Bank2[][2] = {66 /* Addr allmodes */67 {0x000098b0, 0x0e73ff17},68 {0x000098e0, 0x00000420},69};70 71static const u32 ar5416Bank3[][3] = {72 /* Addr 5G 2G */73 {0x000098f0, 0x01400018, 0x01c00018},74};75 76static const u32 ar5416Bank7[][2] = {77 /* Addr allmodes */78 {0x0000989c, 0x00000500},79 {0x0000989c, 0x00000800},80 {0x000098cc, 0x0000000e},81};82 83static const struct ar5416IniArray bank0 = STATIC_INI_ARRAY(ar5416Bank0);84static const struct ar5416IniArray bank1 = STATIC_INI_ARRAY(ar5416Bank1);85static const struct ar5416IniArray bank2 = STATIC_INI_ARRAY(ar5416Bank2);86static const struct ar5416IniArray bank3 = STATIC_INI_ARRAY(ar5416Bank3);87static const struct ar5416IniArray bank7 = STATIC_INI_ARRAY(ar5416Bank7);88 89static void ar5008_write_bank6(struct ath_hw *ah, unsigned int *writecnt)90{91 struct ar5416IniArray *array = &ah->iniBank6;92 u32 *data = ah->analogBank6Data;93 int r;94 95 ENABLE_REGWRITE_BUFFER(ah);96 97 for (r = 0; r < array->ia_rows; r++) {98 REG_WRITE(ah, INI_RA(array, r, 0), data[r]);99 DO_DELAY(*writecnt);100 }101 102 REGWRITE_BUFFER_FLUSH(ah);103}104 105/*106 * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters107 *108 * Performs analog "swizzling" of parameters into their location.109 * Used on external AR2133/AR5133 radios.110 */111static void ar5008_hw_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,112 u32 numBits, u32 firstBit,113 u32 column)114{115 u32 tmp32, mask, arrayEntry, lastBit;116 int32_t bitPosition, bitsLeft;117 118 tmp32 = ath9k_hw_reverse_bits(reg32, numBits);119 arrayEntry = (firstBit - 1) / 8;120 bitPosition = (firstBit - 1) % 8;121 bitsLeft = numBits;122 while (bitsLeft > 0) {123 lastBit = (bitPosition + bitsLeft > 8) ?124 8 : bitPosition + bitsLeft;125 mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<126 (column * 8);127 rfBuf[arrayEntry] &= ~mask;128 rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<129 (column * 8)) & mask;130 bitsLeft -= 8 - bitPosition;131 tmp32 = tmp32 >> (8 - bitPosition);132 bitPosition = 0;133 arrayEntry++;134 }135}136 137/*138 * Fix on 2.4 GHz band for orientation sensitivity issue by increasing139 * rf_pwd_icsyndiv.140 *141 * Theoretical Rules:142 * if 2 GHz band143 * if forceBiasAuto144 * if synth_freq < 2412145 * bias = 0146 * else if 2412 <= synth_freq <= 2422147 * bias = 1148 * else // synth_freq > 2422149 * bias = 2150 * else if forceBias > 0151 * bias = forceBias & 7152 * else153 * no change, use value from ini file154 * else155 * no change, invalid band156 *157 * 1st Mod:158 * 2422 also uses value of 2159 * <approved>160 *161 * 2nd Mod:162 * Less than 2412 uses value of 0, 2412 and above uses value of 2163 */164static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq)165{166 struct ath_common *common = ath9k_hw_common(ah);167 u32 tmp_reg;168 int reg_writes = 0;169 u32 new_bias = 0;170 171 if (!AR_SREV_5416(ah) || synth_freq >= 3000)172 return;173 174 BUG_ON(AR_SREV_9280_20_OR_LATER(ah));175 176 if (synth_freq < 2412)177 new_bias = 0;178 else if (synth_freq < 2422)179 new_bias = 1;180 else181 new_bias = 2;182 183 /* pre-reverse this field */184 tmp_reg = ath9k_hw_reverse_bits(new_bias, 3);185 186 ath_dbg(common, CONFIG, "Force rf_pwd_icsyndiv to %1d on %4d\n",187 new_bias, synth_freq);188 189 /* swizzle rf_pwd_icsyndiv */190 ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);191 192 /* write Bank 6 with new params */193 ar5008_write_bank6(ah, ®_writes);194}195 196/*197 * ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios198 *199 * For the external AR2133/AR5133 radios, takes the MHz channel value and set200 * the channel value. Assumes writes enabled to analog bus and bank6 register201 * cache in ah->analogBank6Data.202 */203static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)204{205 struct ath_common *common = ath9k_hw_common(ah);206 u32 channelSel = 0;207 u32 bModeSynth = 0;208 u32 aModeRefSel = 0;209 u32 reg32 = 0;210 u16 freq;211 struct chan_centers centers;212 213 ath9k_hw_get_channel_centers(ah, chan, ¢ers);214 freq = centers.synth_center;215 216 if (freq < 4800) {217 u32 txctl;218 219 if (((freq - 2192) % 5) == 0) {220 channelSel = ((freq - 672) * 2 - 3040) / 10;221 bModeSynth = 0;222 } else if (((freq - 2224) % 5) == 0) {223 channelSel = ((freq - 704) * 2 - 3040) / 10;224 bModeSynth = 1;225 } else {226 ath_err(common, "Invalid channel %u MHz\n", freq);227 return -EINVAL;228 }229 230 channelSel = (channelSel << 2) & 0xff;231 channelSel = ath9k_hw_reverse_bits(channelSel, 8);232 233 txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);234 if (freq == 2484) {235 236 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,237 txctl | AR_PHY_CCK_TX_CTRL_JAPAN);238 } else {239 REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,240 txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);241 }242 243 } else if ((freq % 20) == 0 && freq >= 5120) {244 channelSel =245 ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);246 aModeRefSel = ath9k_hw_reverse_bits(1, 2);247 } else if ((freq % 10) == 0) {248 channelSel =249 ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);250 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))251 aModeRefSel = ath9k_hw_reverse_bits(2, 2);252 else253 aModeRefSel = ath9k_hw_reverse_bits(1, 2);254 } else if ((freq % 5) == 0) {255 channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);256 aModeRefSel = ath9k_hw_reverse_bits(1, 2);257 } else {258 ath_err(common, "Invalid channel %u MHz\n", freq);259 return -EINVAL;260 }261 262 ar5008_hw_force_bias(ah, freq);263 264 reg32 =265 (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |266 (1 << 5) | 0x1;267 268 REG_WRITE(ah, AR_PHY(0x37), reg32);269 270 ah->curchan = chan;271 272 return 0;273}274 275void ar5008_hw_cmn_spur_mitigate(struct ath_hw *ah,276 struct ath9k_channel *chan, int bin)277{278 int cur_bin;279 int upper, lower, cur_vit_mask;280 int i;281 int8_t mask_m[123] = {0};282 int8_t mask_p[123] = {0};283 int8_t mask_amt;284 int tmp_mask;285 static const int pilot_mask_reg[4] = {286 AR_PHY_TIMING7, AR_PHY_TIMING8,287 AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60288 };289 static const int chan_mask_reg[4] = {290 AR_PHY_TIMING9, AR_PHY_TIMING10,291 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60292 };293 static const int inc[4] = { 0, 100, 0, 0 };294 295 cur_bin = -6000;296 upper = bin + 100;297 lower = bin - 100;298 299 for (i = 0; i < 4; i++) {300 int pilot_mask = 0;301 int chan_mask = 0;302 int bp = 0;303 304 for (bp = 0; bp < 30; bp++) {305 if ((cur_bin > lower) && (cur_bin < upper)) {306 pilot_mask = pilot_mask | 0x1 << bp;307 chan_mask = chan_mask | 0x1 << bp;308 }309 cur_bin += 100;310 }311 cur_bin += inc[i];312 REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);313 REG_WRITE(ah, chan_mask_reg[i], chan_mask);314 }315 316 cur_vit_mask = 6100;317 upper = bin + 120;318 lower = bin - 120;319 320 for (i = 0; i < ARRAY_SIZE(mask_m); i++) {321 if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {322 /* workaround for gcc bug #37014 */323 volatile int tmp_v = abs(cur_vit_mask - bin);324 325 if (tmp_v < 75)326 mask_amt = 1;327 else328 mask_amt = 0;329 if (cur_vit_mask < 0)330 mask_m[abs(cur_vit_mask / 100)] = mask_amt;331 else332 mask_p[cur_vit_mask / 100] = mask_amt;333 }334 cur_vit_mask -= 100;335 }336 337 tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)338 | (mask_m[48] << 26) | (mask_m[49] << 24)339 | (mask_m[50] << 22) | (mask_m[51] << 20)340 | (mask_m[52] << 18) | (mask_m[53] << 16)341 | (mask_m[54] << 14) | (mask_m[55] << 12)342 | (mask_m[56] << 10) | (mask_m[57] << 8)343 | (mask_m[58] << 6) | (mask_m[59] << 4)344 | (mask_m[60] << 2) | (mask_m[61] << 0);345 REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);346 REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);347 348 tmp_mask = (mask_m[31] << 28)349 | (mask_m[32] << 26) | (mask_m[33] << 24)350 | (mask_m[34] << 22) | (mask_m[35] << 20)351 | (mask_m[36] << 18) | (mask_m[37] << 16)352 | (mask_m[48] << 14) | (mask_m[39] << 12)353 | (mask_m[40] << 10) | (mask_m[41] << 8)354 | (mask_m[42] << 6) | (mask_m[43] << 4)355 | (mask_m[44] << 2) | (mask_m[45] << 0);356 REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);357 REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);358 359 tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)360 | (mask_m[18] << 26) | (mask_m[18] << 24)361 | (mask_m[20] << 22) | (mask_m[20] << 20)362 | (mask_m[22] << 18) | (mask_m[22] << 16)363 | (mask_m[24] << 14) | (mask_m[24] << 12)364 | (mask_m[25] << 10) | (mask_m[26] << 8)365 | (mask_m[27] << 6) | (mask_m[28] << 4)366 | (mask_m[29] << 2) | (mask_m[30] << 0);367 REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);368 REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);369 370 tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)371 | (mask_m[2] << 26) | (mask_m[3] << 24)372 | (mask_m[4] << 22) | (mask_m[5] << 20)373 | (mask_m[6] << 18) | (mask_m[7] << 16)374 | (mask_m[8] << 14) | (mask_m[9] << 12)375 | (mask_m[10] << 10) | (mask_m[11] << 8)376 | (mask_m[12] << 6) | (mask_m[13] << 4)377 | (mask_m[14] << 2) | (mask_m[15] << 0);378 REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);379 REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);380 381 tmp_mask = (mask_p[15] << 28)382 | (mask_p[14] << 26) | (mask_p[13] << 24)383 | (mask_p[12] << 22) | (mask_p[11] << 20)384 | (mask_p[10] << 18) | (mask_p[9] << 16)385 | (mask_p[8] << 14) | (mask_p[7] << 12)386 | (mask_p[6] << 10) | (mask_p[5] << 8)387 | (mask_p[4] << 6) | (mask_p[3] << 4)388 | (mask_p[2] << 2) | (mask_p[1] << 0);389 REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);390 REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);391 392 tmp_mask = (mask_p[30] << 28)393 | (mask_p[29] << 26) | (mask_p[28] << 24)394 | (mask_p[27] << 22) | (mask_p[26] << 20)395 | (mask_p[25] << 18) | (mask_p[24] << 16)396 | (mask_p[23] << 14) | (mask_p[22] << 12)397 | (mask_p[21] << 10) | (mask_p[20] << 8)398 | (mask_p[19] << 6) | (mask_p[18] << 4)399 | (mask_p[17] << 2) | (mask_p[16] << 0);400 REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);401 REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);402 403 tmp_mask = (mask_p[45] << 28)404 | (mask_p[44] << 26) | (mask_p[43] << 24)405 | (mask_p[42] << 22) | (mask_p[41] << 20)406 | (mask_p[40] << 18) | (mask_p[39] << 16)407 | (mask_p[38] << 14) | (mask_p[37] << 12)408 | (mask_p[36] << 10) | (mask_p[35] << 8)409 | (mask_p[34] << 6) | (mask_p[33] << 4)410 | (mask_p[32] << 2) | (mask_p[31] << 0);411 REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);412 REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);413 414 tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)415 | (mask_p[59] << 26) | (mask_p[58] << 24)416 | (mask_p[57] << 22) | (mask_p[56] << 20)417 | (mask_p[55] << 18) | (mask_p[54] << 16)418 | (mask_p[53] << 14) | (mask_p[52] << 12)419 | (mask_p[51] << 10) | (mask_p[50] << 8)420 | (mask_p[49] << 6) | (mask_p[48] << 4)421 | (mask_p[47] << 2) | (mask_p[46] << 0);422 REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);423 REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);424}425 426/*427 * ar5008_hw_spur_mitigate - convert baseband spur frequency for external radios428 *429 * For non single-chip solutions. Converts to baseband spur frequency given the430 * input channel frequency and compute register settings below.431 */432static void ar5008_hw_spur_mitigate(struct ath_hw *ah,433 struct ath9k_channel *chan)434{435 int bb_spur = AR_NO_SPUR;436 int bin;437 int spur_freq_sd;438 int spur_delta_phase;439 int denominator;440 int tmp, new;441 int i;442 443 int cur_bb_spur;444 bool is2GHz = IS_CHAN_2GHZ(chan);445 446 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {447 cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);448 if (AR_NO_SPUR == cur_bb_spur)449 break;450 cur_bb_spur = cur_bb_spur - (chan->channel * 10);451 if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {452 bb_spur = cur_bb_spur;453 break;454 }455 }456 457 if (AR_NO_SPUR == bb_spur)458 return;459 460 bin = bb_spur * 32;461 462 tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));463 new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |464 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |465 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |466 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);467 468 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);469 470 new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |471 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |472 AR_PHY_SPUR_REG_MASK_RATE_SELECT |473 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |474 SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));475 REG_WRITE(ah, AR_PHY_SPUR_REG, new);476 477 spur_delta_phase = ((bb_spur * 524288) / 100) &478 AR_PHY_TIMING11_SPUR_DELTA_PHASE;479 480 denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;481 spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;482 483 new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |484 SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |485 SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));486 REG_WRITE(ah, AR_PHY_TIMING11, new);487 488 ar5008_hw_cmn_spur_mitigate(ah, chan, bin);489}490 491/**492 * ar5008_hw_rf_alloc_ext_banks - allocates banks for external radio programming493 * @ah: atheros hardware structure494 *495 * Only required for older devices with external AR2133/AR5133 radios.496 */497static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)498{499 int size = ah->iniBank6.ia_rows * sizeof(u32);500 501 if (AR_SREV_9280_20_OR_LATER(ah))502 return 0;503 504 ah->analogBank6Data = devm_kzalloc(ah->dev, size, GFP_KERNEL);505 if (!ah->analogBank6Data)506 return -ENOMEM;507 508 return 0;509}510 511 512/* *513 * ar5008_hw_set_rf_regs - programs rf registers based on EEPROM514 * @ah: atheros hardware structure515 * @chan:516 * @modesIndex:517 *518 * Used for the external AR2133/AR5133 radios.519 *520 * Reads the EEPROM header info from the device structure and programs521 * all rf registers. This routine requires access to the analog522 * rf device. This is not required for single-chip devices.523 */524static bool ar5008_hw_set_rf_regs(struct ath_hw *ah,525 struct ath9k_channel *chan,526 u16 modesIndex)527{528 u32 eepMinorRev;529 u32 ob5GHz = 0, db5GHz = 0;530 u32 ob2GHz = 0, db2GHz = 0;531 int regWrites = 0;532 int i;533 534 /*535 * Software does not need to program bank data536 * for single chip devices, that is AR9280 or anything537 * after that.538 */539 if (AR_SREV_9280_20_OR_LATER(ah))540 return true;541 542 /* Setup rf parameters */543 eepMinorRev = ah->eep_ops->get_eeprom_rev(ah);544 545 for (i = 0; i < ah->iniBank6.ia_rows; i++)546 ah->analogBank6Data[i] = INI_RA(&ah->iniBank6, i, modesIndex);547 548 /* Only the 5 or 2 GHz OB/DB need to be set for a mode */549 if (eepMinorRev >= 2) {550 if (IS_CHAN_2GHZ(chan)) {551 ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2);552 db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2);553 ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,554 ob2GHz, 3, 197, 0);555 ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,556 db2GHz, 3, 194, 0);557 } else {558 ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5);559 db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5);560 ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,561 ob5GHz, 3, 203, 0);562 ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data,563 db5GHz, 3, 200, 0);564 }565 }566 567 /* Write Analog registers */568 REG_WRITE_ARRAY(&bank0, 1, regWrites);569 REG_WRITE_ARRAY(&bank1, 1, regWrites);570 REG_WRITE_ARRAY(&bank2, 1, regWrites);571 REG_WRITE_ARRAY(&bank3, modesIndex, regWrites);572 ar5008_write_bank6(ah, ®Writes);573 REG_WRITE_ARRAY(&bank7, 1, regWrites);574 575 return true;576}577 578static void ar5008_hw_init_bb(struct ath_hw *ah,579 struct ath9k_channel *chan)580{581 u32 synthDelay;582 583 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;584 585 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);586 587 ath9k_hw_synth_delay(ah, chan, synthDelay);588}589 590static void ar5008_hw_init_chain_masks(struct ath_hw *ah)591{592 int rx_chainmask, tx_chainmask;593 594 rx_chainmask = ah->rxchainmask;595 tx_chainmask = ah->txchainmask;596 597 598 switch (rx_chainmask) {599 case 0x5:600 REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,601 AR_PHY_SWAP_ALT_CHAIN);602 fallthrough;603 case 0x3:604 if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) {605 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);606 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);607 break;608 }609 fallthrough;610 case 0x1:611 case 0x2:612 case 0x7:613 ENABLE_REGWRITE_BUFFER(ah);614 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);615 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);616 break;617 default:618 ENABLE_REGWRITE_BUFFER(ah);619 break;620 }621 622 REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);623 624 REGWRITE_BUFFER_FLUSH(ah);625 626 if (tx_chainmask == 0x5) {627 REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,628 AR_PHY_SWAP_ALT_CHAIN);629 }630 if (AR_SREV_9100(ah))631 REG_WRITE(ah, AR_PHY_ANALOG_SWAP,632 REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);633}634 635static void ar5008_hw_override_ini(struct ath_hw *ah,636 struct ath9k_channel *chan)637{638 u32 val;639 640 /*641 * Set the RX_ABORT and RX_DIS and clear if off only after642 * RXE is set for MAC. This prevents frames with corrupted643 * descriptor status.644 */645 REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));646 647 if (AR_SREV_9280_20_OR_LATER(ah)) {648 /*649 * For AR9280 and above, there is a new feature that allows650 * Multicast search based on both MAC Address and Key ID.651 * By default, this feature is enabled. But since the driver652 * is not using this feature, we switch it off; otherwise653 * multicast search based on MAC addr only will fail.654 */655 val = REG_READ(ah, AR_PCU_MISC_MODE2) &656 (~AR_ADHOC_MCAST_KEYID_ENABLE);657 658 if (!AR_SREV_9271(ah))659 val &= ~AR_PCU_MISC_MODE2_HWWAR1;660 661 if (AR_SREV_9287_11_OR_LATER(ah))662 val = val & (~AR_PCU_MISC_MODE2_HWWAR2);663 664 val |= AR_PCU_MISC_MODE2_CFP_IGNORE;665 666 REG_WRITE(ah, AR_PCU_MISC_MODE2, val);667 }668 669 if (AR_SREV_9280_20_OR_LATER(ah))670 return;671 /*672 * Disable BB clock gating673 * Necessary to avoid issues on AR5416 2.0674 */675 REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);676 677 /*678 * Disable RIFS search on some chips to avoid baseband679 * hang issues.680 */681 if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {682 val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);683 val &= ~AR_PHY_RIFS_INIT_DELAY;684 REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);685 }686}687 688static void ar5008_hw_set_channel_regs(struct ath_hw *ah,689 struct ath9k_channel *chan)690{691 u32 phymode;692 u32 enableDacFifo = 0;693 694 if (AR_SREV_9285_12_OR_LATER(ah))695 enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &696 AR_PHY_FC_ENABLE_DAC_FIFO);697 698 phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40699 | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;700 701 if (IS_CHAN_HT40(chan)) {702 phymode |= AR_PHY_FC_DYN2040_EN;703 704 if (IS_CHAN_HT40PLUS(chan))705 phymode |= AR_PHY_FC_DYN2040_PRI_CH;706 707 }708 ENABLE_REGWRITE_BUFFER(ah);709 REG_WRITE(ah, AR_PHY_TURBO, phymode);710 711 /* This function do only REG_WRITE, so712 * we can include it to REGWRITE_BUFFER. */713 ath9k_hw_set11nmac2040(ah, chan);714 715 REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);716 REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);717 718 REGWRITE_BUFFER_FLUSH(ah);719}720 721 722static int ar5008_hw_process_ini(struct ath_hw *ah,723 struct ath9k_channel *chan)724{725 struct ath_common *common = ath9k_hw_common(ah);726 int i, regWrites = 0;727 u32 modesIndex, freqIndex;728 729 if (IS_CHAN_5GHZ(chan)) {730 freqIndex = 1;731 modesIndex = IS_CHAN_HT40(chan) ? 2 : 1;732 } else {733 freqIndex = 2;734 modesIndex = IS_CHAN_HT40(chan) ? 3 : 4;735 }736 737 /*738 * Set correct baseband to analog shift setting to739 * access analog chips.740 */741 REG_WRITE(ah, AR_PHY(0), 0x00000007);742 743 /* Write ADDAC shifts */744 REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);745 if (ah->eep_ops->set_addac)746 ah->eep_ops->set_addac(ah, chan);747 748 REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);749 REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);750 751 ENABLE_REGWRITE_BUFFER(ah);752 753 for (i = 0; i < ah->iniModes.ia_rows; i++) {754 u32 reg = INI_RA(&ah->iniModes, i, 0);755 u32 val = INI_RA(&ah->iniModes, i, modesIndex);756 757 if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup)758 val &= ~AR_AN_TOP2_PWDCLKIND;759 760 REG_WRITE(ah, reg, val);761 762 if (reg >= 0x7800 && reg < 0x78a0763 && ah->config.analog_shiftreg764 && (common->bus_ops->ath_bus_type != ATH_USB)) {765 udelay(100);766 }767 768 DO_DELAY(regWrites);769 }770 771 REGWRITE_BUFFER_FLUSH(ah);772 773 if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah))774 REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);775 776 if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) ||777 AR_SREV_9287_11_OR_LATER(ah))778 REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);779 780 if (AR_SREV_9271_10(ah)) {781 REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENA);782 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_ADC_ON, 0xa);783 }784 785 ENABLE_REGWRITE_BUFFER(ah);786 787 /* Write common array parameters */788 for (i = 0; i < ah->iniCommon.ia_rows; i++) {789 u32 reg = INI_RA(&ah->iniCommon, i, 0);790 u32 val = INI_RA(&ah->iniCommon, i, 1);791 792 REG_WRITE(ah, reg, val);793 794 if (reg >= 0x7800 && reg < 0x78a0795 && ah->config.analog_shiftreg796 && (common->bus_ops->ath_bus_type != ATH_USB)) {797 udelay(100);798 }799 800 DO_DELAY(regWrites);801 }802 803 REGWRITE_BUFFER_FLUSH(ah);804 805 REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);806 807 if (IS_CHAN_A_FAST_CLOCK(ah, chan))808 REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex,809 regWrites);810 811 ar5008_hw_override_ini(ah, chan);812 ar5008_hw_set_channel_regs(ah, chan);813 ar5008_hw_init_chain_masks(ah);814 ath9k_olc_init(ah);815 ath9k_hw_apply_txpower(ah, chan, false);816 817 /* Write analog registers */818 if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {819 ath_err(ath9k_hw_common(ah), "ar5416SetRfRegs failed\n");820 return -EIO;821 }822 823 return 0;824}825 826static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)827{828 u32 rfMode = 0;829 830 if (chan == NULL)831 return;832 833 if (IS_CHAN_2GHZ(chan))834 rfMode |= AR_PHY_MODE_DYNAMIC;835 else836 rfMode |= AR_PHY_MODE_OFDM;837 838 if (!AR_SREV_9280_20_OR_LATER(ah))839 rfMode |= (IS_CHAN_5GHZ(chan)) ?840 AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;841 842 if (IS_CHAN_A_FAST_CLOCK(ah, chan))843 rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);844 845 REG_WRITE(ah, AR_PHY_MODE, rfMode);846}847 848static void ar5008_hw_mark_phy_inactive(struct ath_hw *ah)849{850 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);851}852 853static void ar5008_hw_set_delta_slope(struct ath_hw *ah,854 struct ath9k_channel *chan)855{856 u32 coef_scaled, ds_coef_exp, ds_coef_man;857 u32 clockMhzScaled = 0x64000000;858 struct chan_centers centers;859 860 if (IS_CHAN_HALF_RATE(chan))861 clockMhzScaled = clockMhzScaled >> 1;862 else if (IS_CHAN_QUARTER_RATE(chan))863 clockMhzScaled = clockMhzScaled >> 2;864 865 ath9k_hw_get_channel_centers(ah, chan, ¢ers);866 coef_scaled = clockMhzScaled / centers.synth_center;867 868 ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,869 &ds_coef_exp);870 871 REG_RMW_FIELD(ah, AR_PHY_TIMING3,872 AR_PHY_TIMING3_DSC_MAN, ds_coef_man);873 REG_RMW_FIELD(ah, AR_PHY_TIMING3,874 AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);875 876 coef_scaled = (9 * coef_scaled) / 10;877 878 ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,879 &ds_coef_exp);880 881 REG_RMW_FIELD(ah, AR_PHY_HALFGI,882 AR_PHY_HALFGI_DSC_MAN, ds_coef_man);883 REG_RMW_FIELD(ah, AR_PHY_HALFGI,884 AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);885}886 887static bool ar5008_hw_rfbus_req(struct ath_hw *ah)888{889 REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);890 return ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,891 AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT);892}893 894static void ar5008_hw_rfbus_done(struct ath_hw *ah)895{896 u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;897 898 ath9k_hw_synth_delay(ah, ah->curchan, synthDelay);899 900 REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);901}902 903static void ar5008_restore_chainmask(struct ath_hw *ah)904{905 int rx_chainmask = ah->rxchainmask;906 907 if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {908 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);909 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);910 }911}912 913static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah,914 struct ath9k_channel *chan)915{916 u32 pll;917 918 pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);919 920 if (chan && IS_CHAN_HALF_RATE(chan))921 pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);922 else if (chan && IS_CHAN_QUARTER_RATE(chan))923 pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);924 925 if (chan && IS_CHAN_5GHZ(chan))926 pll |= SM(0x50, AR_RTC_9160_PLL_DIV);927 else928 pll |= SM(0x58, AR_RTC_9160_PLL_DIV);929 930 return pll;931}932 933static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah,934 struct ath9k_channel *chan)935{936 u32 pll;937 938 pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;939 940 if (chan && IS_CHAN_HALF_RATE(chan))941 pll |= SM(0x1, AR_RTC_PLL_CLKSEL);942 else if (chan && IS_CHAN_QUARTER_RATE(chan))943 pll |= SM(0x2, AR_RTC_PLL_CLKSEL);944 945 if (chan && IS_CHAN_5GHZ(chan))946 pll |= SM(0xa, AR_RTC_PLL_DIV);947 else948 pll |= SM(0xb, AR_RTC_PLL_DIV);949 950 return pll;951}952 953static bool ar5008_hw_ani_control_new(struct ath_hw *ah,954 enum ath9k_ani_cmd cmd,955 int param)956{957 struct ath_common *common = ath9k_hw_common(ah);958 struct ath9k_channel *chan = ah->curchan;959 struct ar5416AniState *aniState = &ah->ani;960 s32 value;961 962 switch (cmd & ah->ani_function) {963 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{964 /*965 * on == 1 means ofdm weak signal detection is ON966 * on == 1 is the default, for less noise immunity967 *968 * on == 0 means ofdm weak signal detection is OFF969 * on == 0 means more noise imm970 */971 u32 on = param ? 1 : 0;972 /*973 * make register setting for default974 * (weak sig detect ON) come from INI file975 */976 int m1ThreshLow = on ?977 aniState->iniDef.m1ThreshLow : m1ThreshLow_off;978 int m2ThreshLow = on ?979 aniState->iniDef.m2ThreshLow : m2ThreshLow_off;980 int m1Thresh = on ?981 aniState->iniDef.m1Thresh : m1Thresh_off;982 int m2Thresh = on ?983 aniState->iniDef.m2Thresh : m2Thresh_off;984 int m2CountThr = on ?985 aniState->iniDef.m2CountThr : m2CountThr_off;986 int m2CountThrLow = on ?987 aniState->iniDef.m2CountThrLow : m2CountThrLow_off;988 int m1ThreshLowExt = on ?989 aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;990 int m2ThreshLowExt = on ?991 aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;992 int m1ThreshExt = on ?993 aniState->iniDef.m1ThreshExt : m1ThreshExt_off;994 int m2ThreshExt = on ?995 aniState->iniDef.m2ThreshExt : m2ThreshExt_off;996 997 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,998 AR_PHY_SFCORR_LOW_M1_THRESH_LOW,999 m1ThreshLow);1000 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,1001 AR_PHY_SFCORR_LOW_M2_THRESH_LOW,1002 m2ThreshLow);1003 REG_RMW_FIELD(ah, AR_PHY_SFCORR,1004 AR_PHY_SFCORR_M1_THRESH, m1Thresh);1005 REG_RMW_FIELD(ah, AR_PHY_SFCORR,1006 AR_PHY_SFCORR_M2_THRESH, m2Thresh);1007 REG_RMW_FIELD(ah, AR_PHY_SFCORR,1008 AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);1009 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,1010 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,1011 m2CountThrLow);1012 1013 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,1014 AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);1015 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,1016 AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);1017 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,1018 AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);1019 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,1020 AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);1021 1022 if (on)1023 REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,1024 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);1025 else1026 REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,1027 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);1028 1029 if (on != aniState->ofdmWeakSigDetect) {1030 ath_dbg(common, ANI,1031 "** ch %d: ofdm weak signal: %s=>%s\n",1032 chan->channel,1033 aniState->ofdmWeakSigDetect ?1034 "on" : "off",1035 on ? "on" : "off");1036 if (on)1037 ah->stats.ast_ani_ofdmon++;1038 else1039 ah->stats.ast_ani_ofdmoff++;1040 aniState->ofdmWeakSigDetect = on;1041 }1042 break;1043 }1044 case ATH9K_ANI_FIRSTEP_LEVEL:{1045 u32 level = param;1046 1047 value = level * 2;1048 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,1049 AR_PHY_FIND_SIG_FIRSTEP, value);1050 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,1051 AR_PHY_FIND_SIG_FIRSTEP_LOW, value);1052 1053 if (level != aniState->firstepLevel) {1054 ath_dbg(common, ANI,1055 "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n",1056 chan->channel,1057 aniState->firstepLevel,1058 level,1059 ATH9K_ANI_FIRSTEP_LVL,1060 value,1061 aniState->iniDef.firstep);1062 ath_dbg(common, ANI,1063 "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n",1064 chan->channel,1065 aniState->firstepLevel,1066 level,1067 ATH9K_ANI_FIRSTEP_LVL,1068 value,1069 aniState->iniDef.firstepLow);1070 if (level > aniState->firstepLevel)1071 ah->stats.ast_ani_stepup++;1072 else if (level < aniState->firstepLevel)1073 ah->stats.ast_ani_stepdown++;1074 aniState->firstepLevel = level;1075 }1076 break;1077 }1078 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{1079 u32 level = param;1080 1081 value = (level + 1) * 2;1082 REG_RMW_FIELD(ah, AR_PHY_TIMING5,1083 AR_PHY_TIMING5_CYCPWR_THR1, value);1084 1085 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,1086 AR_PHY_EXT_TIMING5_CYCPWR_THR1, value - 1);1087 1088 if (level != aniState->spurImmunityLevel) {1089 ath_dbg(common, ANI,1090 "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n",1091 chan->channel,1092 aniState->spurImmunityLevel,1093 level,1094 ATH9K_ANI_SPUR_IMMUNE_LVL,1095 value,1096 aniState->iniDef.cycpwrThr1);1097 ath_dbg(common, ANI,1098 "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n",1099 chan->channel,1100 aniState->spurImmunityLevel,1101 level,1102 ATH9K_ANI_SPUR_IMMUNE_LVL,1103 value,1104 aniState->iniDef.cycpwrThr1Ext);1105 if (level > aniState->spurImmunityLevel)1106 ah->stats.ast_ani_spurup++;1107 else if (level < aniState->spurImmunityLevel)1108 ah->stats.ast_ani_spurdown++;1109 aniState->spurImmunityLevel = level;1110 }1111 break;1112 }1113 case ATH9K_ANI_MRC_CCK:1114 /*1115 * You should not see this as AR5008, AR9001, AR90021116 * does not have hardware support for MRC CCK.1117 */1118 WARN_ON(1);1119 break;1120 default:1121 ath_dbg(common, ANI, "invalid cmd %u\n", cmd);1122 return false;1123 }1124 1125 ath_dbg(common, ANI,1126 "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n",1127 aniState->spurImmunityLevel,1128 aniState->ofdmWeakSigDetect ? "on" : "off",1129 aniState->firstepLevel,1130 aniState->mrcCCK ? "on" : "off",1131 aniState->listenTime,1132 aniState->ofdmPhyErrCount,1133 aniState->cckPhyErrCount);1134 return true;1135}1136 1137static void ar5008_hw_do_getnf(struct ath_hw *ah,1138 int16_t nfarray[NUM_NF_READINGS])1139{1140 int16_t nf;1141 1142 nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);1143 nfarray[0] = sign_extend32(nf, 8);1144 1145 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);1146 nfarray[1] = sign_extend32(nf, 8);1147 1148 nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);1149 nfarray[2] = sign_extend32(nf, 8);1150 1151 if (!IS_CHAN_HT40(ah->curchan))1152 return;1153 1154 nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);1155 nfarray[3] = sign_extend32(nf, 8);1156 1157 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);1158 nfarray[4] = sign_extend32(nf, 8);1159 1160 nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);1161 nfarray[5] = sign_extend32(nf, 8);1162}1163 1164/*1165 * Initialize the ANI register values with default (ini) values.1166 * This routine is called during a (full) hardware reset after1167 * all the registers are initialised from the INI.1168 */1169static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)1170{1171 struct ath_common *common = ath9k_hw_common(ah);1172 struct ath9k_channel *chan = ah->curchan;1173 struct ar5416AniState *aniState = &ah->ani;1174 struct ath9k_ani_default *iniDef;1175 u32 val;1176 1177 iniDef = &aniState->iniDef;1178 1179 ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz\n",1180 ah->hw_version.macVersion,1181 ah->hw_version.macRev,1182 ah->opmode,1183 chan->channel);1184 1185 val = REG_READ(ah, AR_PHY_SFCORR);1186 iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);1187 iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH);1188 iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR);1189 1190 val = REG_READ(ah, AR_PHY_SFCORR_LOW);1191 iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW);1192 iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW);1193 iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);1194 1195 val = REG_READ(ah, AR_PHY_SFCORR_EXT);1196 iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH);1197 iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH);1198 iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW);1199 iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW);1200 iniDef->firstep = REG_READ_FIELD(ah,1201 AR_PHY_FIND_SIG,1202 AR_PHY_FIND_SIG_FIRSTEP);1203 iniDef->firstepLow = REG_READ_FIELD(ah,1204 AR_PHY_FIND_SIG_LOW,1205 AR_PHY_FIND_SIG_FIRSTEP_LOW);1206 iniDef->cycpwrThr1 = REG_READ_FIELD(ah,1207 AR_PHY_TIMING5,1208 AR_PHY_TIMING5_CYCPWR_THR1);1209 iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah,1210 AR_PHY_EXT_CCA,1211 AR_PHY_EXT_TIMING5_CYCPWR_THR1);1212 1213 /* these levels just got reset to defaults by the INI */1214 aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;1215 aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;1216 aniState->ofdmWeakSigDetect = true;1217 aniState->mrcCCK = false; /* not available on pre AR9003 */1218}1219 1220static void ar5008_hw_set_nf_limits(struct ath_hw *ah)1221{1222 ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ;1223 ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ;1224 ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ;1225 ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ;1226 ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ;1227 ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;1228}1229 1230static void ar5008_hw_set_radar_params(struct ath_hw *ah,1231 struct ath_hw_radar_conf *conf)1232{1233 u32 radar_0 = 0, radar_1;1234 1235 if (!conf) {1236 REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);1237 return;1238 }1239 1240 radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;1241 radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);1242 radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);1243 radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);1244 radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);1245 radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);1246 1247 radar_1 = REG_READ(ah, AR_PHY_RADAR_1);1248 radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH |1249 AR_PHY_RADAR_1_RELPWR_THRESH);1250 radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;1251 radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;1252 radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);1253 radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);1254 radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);1255 1256 REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);1257 REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);1258 if (conf->ext_channel)1259 REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);1260 else1261 REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);1262}1263 1264static void ar5008_hw_set_radar_conf(struct ath_hw *ah)1265{1266 struct ath_hw_radar_conf *conf = &ah->radar_conf;1267 1268 conf->fir_power = -33;1269 conf->radar_rssi = 20;1270 conf->pulse_height = 10;1271 conf->pulse_rssi = 15;1272 conf->pulse_inband = 15;1273 conf->pulse_maxlen = 255;1274 conf->pulse_inband_step = 12;1275 conf->radar_inband = 8;1276}1277 1278static void ar5008_hw_init_txpower_cck(struct ath_hw *ah, int16_t *rate_array)1279{1280#define CCK_DELTA(_ah, x) ((OLC_FOR_AR9280_20_LATER(_ah)) ? max((x) - 2, 0) : (x))1281 ah->tx_power[0] = CCK_DELTA(ah, rate_array[rate1l]);1282 ah->tx_power[1] = CCK_DELTA(ah, min(rate_array[rate2l],1283 rate_array[rate2s]));1284 ah->tx_power[2] = CCK_DELTA(ah, min(rate_array[rate5_5l],1285 rate_array[rate5_5s]));1286 ah->tx_power[3] = CCK_DELTA(ah, min(rate_array[rate11l],1287 rate_array[rate11s]));1288#undef CCK_DELTA1289}1290 1291static void ar5008_hw_init_txpower_ofdm(struct ath_hw *ah, int16_t *rate_array,1292 int offset)1293{1294 int i, idx = 0;1295 1296 for (i = offset; i < offset + AR5008_OFDM_RATES; i++) {1297 ah->tx_power[i] = rate_array[idx];1298 idx++;1299 }1300}1301 1302static void ar5008_hw_init_txpower_ht(struct ath_hw *ah, int16_t *rate_array,1303 int ss_offset, int ds_offset,1304 bool is_40, int ht40_delta)1305{1306 int i, mcs_idx = (is_40) ? AR5008_HT40_SHIFT : AR5008_HT20_SHIFT;1307 1308 for (i = ss_offset; i < ss_offset + AR5008_HT_SS_RATES; i++) {1309 ah->tx_power[i] = rate_array[mcs_idx] + ht40_delta;1310 mcs_idx++;1311 }1312 memcpy(&ah->tx_power[ds_offset], &ah->tx_power[ss_offset],1313 AR5008_HT_SS_RATES);1314}1315 1316void ar5008_hw_init_rate_txpower(struct ath_hw *ah, int16_t *rate_array,1317 struct ath9k_channel *chan, int ht40_delta)1318{1319 if (IS_CHAN_5GHZ(chan)) {1320 ar5008_hw_init_txpower_ofdm(ah, rate_array,1321 AR5008_11NA_OFDM_SHIFT);1322 if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) {1323 ar5008_hw_init_txpower_ht(ah, rate_array,1324 AR5008_11NA_HT_SS_SHIFT,1325 AR5008_11NA_HT_DS_SHIFT,1326 IS_CHAN_HT40(chan),1327 ht40_delta);1328 }1329 } else {1330 ar5008_hw_init_txpower_cck(ah, rate_array);1331 ar5008_hw_init_txpower_ofdm(ah, rate_array,1332 AR5008_11NG_OFDM_SHIFT);1333 if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) {1334 ar5008_hw_init_txpower_ht(ah, rate_array,1335 AR5008_11NG_HT_SS_SHIFT,1336 AR5008_11NG_HT_DS_SHIFT,1337 IS_CHAN_HT40(chan),1338 ht40_delta);1339 }1340 }1341}1342 1343int ar5008_hw_attach_phy_ops(struct ath_hw *ah)1344{1345 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);1346 static const u32 ar5416_cca_regs[6] = {1347 AR_PHY_CCA,1348 AR_PHY_CH1_CCA,1349 AR_PHY_CH2_CCA,1350 AR_PHY_EXT_CCA,1351 AR_PHY_CH1_EXT_CCA,1352 AR_PHY_CH2_EXT_CCA1353 };1354 int ret;1355 1356 ret = ar5008_hw_rf_alloc_ext_banks(ah);1357 if (ret)1358 return ret;1359 1360 priv_ops->rf_set_freq = ar5008_hw_set_channel;1361 priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;1362 1363 priv_ops->set_rf_regs = ar5008_hw_set_rf_regs;1364 priv_ops->set_channel_regs = ar5008_hw_set_channel_regs;1365 priv_ops->init_bb = ar5008_hw_init_bb;1366 priv_ops->process_ini = ar5008_hw_process_ini;1367 priv_ops->set_rfmode = ar5008_hw_set_rfmode;1368 priv_ops->mark_phy_inactive = ar5008_hw_mark_phy_inactive;1369 priv_ops->set_delta_slope = ar5008_hw_set_delta_slope;1370 priv_ops->rfbus_req = ar5008_hw_rfbus_req;1371 priv_ops->rfbus_done = ar5008_hw_rfbus_done;1372 priv_ops->restore_chainmask = ar5008_restore_chainmask;1373 priv_ops->do_getnf = ar5008_hw_do_getnf;1374 priv_ops->set_radar_params = ar5008_hw_set_radar_params;1375 1376 priv_ops->ani_control = ar5008_hw_ani_control_new;1377 priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;1378 1379 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))1380 priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;1381 else1382 priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;1383 1384 ar5008_hw_set_nf_limits(ah);1385 ar5008_hw_set_radar_conf(ah);1386 memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs));1387 return 0;1388}1389