ath9k: Refactor hw.c
Split hw.c into more manageable files: ani.c calib.c eeprom.c mac.c Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
5640b08ef7
commit
f1dc56003b
9 changed files with 6909 additions and 7007 deletions
|
@ -1,4 +1,8 @@
|
|||
ath9k-y += hw.o \
|
||||
eeprom.o \
|
||||
mac.o \
|
||||
calib.o \
|
||||
ani.o \
|
||||
phy.o \
|
||||
regd.o \
|
||||
beacon.o \
|
||||
|
|
854
drivers/net/wireless/ath9k/ani.c
Normal file
854
drivers/net/wireless/ath9k/ani.c
Normal file
|
@ -0,0 +1,854 @@
|
|||
/*
|
||||
* Copyright (c) 2008 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "hw.h"
|
||||
#include "reg.h"
|
||||
#include "phy.h"
|
||||
|
||||
static int ath9k_hw_get_ani_channel_idx(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
|
||||
if (ahp->ah_ani[i].c.channel == chan->channel)
|
||||
return i;
|
||||
if (ahp->ah_ani[i].c.channel == 0) {
|
||||
ahp->ah_ani[i].c.channel = chan->channel;
|
||||
ahp->ah_ani[i].c.channelFlags = chan->channelFlags;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"No more channel states left. Using channel 0\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool ath9k_hw_ani_control(struct ath_hal *ah,
|
||||
enum ath9k_ani_cmd cmd, int param)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ar5416AniState *aniState = ahp->ah_curani;
|
||||
|
||||
switch (cmd & ahp->ah_ani_function) {
|
||||
case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
|
||||
u32 level = param;
|
||||
|
||||
if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"%s: level out of range (%u > %u)\n",
|
||||
__func__, level,
|
||||
(unsigned)ARRAY_SIZE(ahp->ah_totalSizeDesired));
|
||||
return false;
|
||||
}
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
|
||||
AR_PHY_DESIRED_SZ_TOT_DES,
|
||||
ahp->ah_totalSizeDesired[level]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
|
||||
AR_PHY_AGC_CTL1_COARSE_LOW,
|
||||
ahp->ah_coarseLow[level]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
|
||||
AR_PHY_AGC_CTL1_COARSE_HIGH,
|
||||
ahp->ah_coarseHigh[level]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
|
||||
AR_PHY_FIND_SIG_FIRPWR,
|
||||
ahp->ah_firpwr[level]);
|
||||
|
||||
if (level > aniState->noiseImmunityLevel)
|
||||
ahp->ah_stats.ast_ani_niup++;
|
||||
else if (level < aniState->noiseImmunityLevel)
|
||||
ahp->ah_stats.ast_ani_nidown++;
|
||||
aniState->noiseImmunityLevel = level;
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
|
||||
const int m1ThreshLow[] = { 127, 50 };
|
||||
const int m2ThreshLow[] = { 127, 40 };
|
||||
const int m1Thresh[] = { 127, 0x4d };
|
||||
const int m2Thresh[] = { 127, 0x40 };
|
||||
const int m2CountThr[] = { 31, 16 };
|
||||
const int m2CountThrLow[] = { 63, 48 };
|
||||
u32 on = param ? 1 : 0;
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
|
||||
AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
|
||||
m1ThreshLow[on]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
|
||||
AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
|
||||
m2ThreshLow[on]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR,
|
||||
AR_PHY_SFCORR_M1_THRESH,
|
||||
m1Thresh[on]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR,
|
||||
AR_PHY_SFCORR_M2_THRESH,
|
||||
m2Thresh[on]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR,
|
||||
AR_PHY_SFCORR_M2COUNT_THR,
|
||||
m2CountThr[on]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
|
||||
AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
|
||||
m2CountThrLow[on]);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
|
||||
AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
|
||||
m1ThreshLow[on]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
|
||||
AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
|
||||
m2ThreshLow[on]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
|
||||
AR_PHY_SFCORR_EXT_M1_THRESH,
|
||||
m1Thresh[on]);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
|
||||
AR_PHY_SFCORR_EXT_M2_THRESH,
|
||||
m2Thresh[on]);
|
||||
|
||||
if (on)
|
||||
REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
|
||||
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
|
||||
else
|
||||
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
|
||||
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
|
||||
|
||||
if (!on != aniState->ofdmWeakSigDetectOff) {
|
||||
if (on)
|
||||
ahp->ah_stats.ast_ani_ofdmon++;
|
||||
else
|
||||
ahp->ah_stats.ast_ani_ofdmoff++;
|
||||
aniState->ofdmWeakSigDetectOff = !on;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
|
||||
const int weakSigThrCck[] = { 8, 6 };
|
||||
u32 high = param ? 1 : 0;
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
|
||||
AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
|
||||
weakSigThrCck[high]);
|
||||
if (high != aniState->cckWeakSigThreshold) {
|
||||
if (high)
|
||||
ahp->ah_stats.ast_ani_cckhigh++;
|
||||
else
|
||||
ahp->ah_stats.ast_ani_ccklow++;
|
||||
aniState->cckWeakSigThreshold = high;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_FIRSTEP_LEVEL:{
|
||||
const int firstep[] = { 0, 4, 8 };
|
||||
u32 level = param;
|
||||
|
||||
if (level >= ARRAY_SIZE(firstep)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"%s: level out of range (%u > %u)\n",
|
||||
__func__, level,
|
||||
(unsigned) ARRAY_SIZE(firstep));
|
||||
return false;
|
||||
}
|
||||
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
|
||||
AR_PHY_FIND_SIG_FIRSTEP,
|
||||
firstep[level]);
|
||||
if (level > aniState->firstepLevel)
|
||||
ahp->ah_stats.ast_ani_stepup++;
|
||||
else if (level < aniState->firstepLevel)
|
||||
ahp->ah_stats.ast_ani_stepdown++;
|
||||
aniState->firstepLevel = level;
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
|
||||
const int cycpwrThr1[] =
|
||||
{ 2, 4, 6, 8, 10, 12, 14, 16 };
|
||||
u32 level = param;
|
||||
|
||||
if (level >= ARRAY_SIZE(cycpwrThr1)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"%s: level out of range (%u > %u)\n",
|
||||
__func__, level,
|
||||
(unsigned)
|
||||
ARRAY_SIZE(cycpwrThr1));
|
||||
return false;
|
||||
}
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING5,
|
||||
AR_PHY_TIMING5_CYCPWR_THR1,
|
||||
cycpwrThr1[level]);
|
||||
if (level > aniState->spurImmunityLevel)
|
||||
ahp->ah_stats.ast_ani_spurup++;
|
||||
else if (level < aniState->spurImmunityLevel)
|
||||
ahp->ah_stats.ast_ani_spurdown++;
|
||||
aniState->spurImmunityLevel = level;
|
||||
break;
|
||||
}
|
||||
case ATH9K_ANI_PRESENT:
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"%s: invalid cmd %u\n", __func__, cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "%s: ANI parameters:\n", __func__);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"noiseImmunityLevel=%d, spurImmunityLevel=%d, "
|
||||
"ofdmWeakSigDetectOff=%d\n",
|
||||
aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
|
||||
!aniState->ofdmWeakSigDetectOff);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"cckWeakSigThreshold=%d, "
|
||||
"firstepLevel=%d, listenTime=%d\n",
|
||||
aniState->cckWeakSigThreshold, aniState->firstepLevel,
|
||||
aniState->listenTime);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
|
||||
aniState->cycleCount, aniState->ofdmPhyErrCount,
|
||||
aniState->cckPhyErrCount);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ath9k_hw_update_mibstats(struct ath_hal *ah,
|
||||
struct ath9k_mib_stats *stats)
|
||||
{
|
||||
stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
|
||||
stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
|
||||
stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
|
||||
stats->rts_good += REG_READ(ah, AR_RTS_OK);
|
||||
stats->beacons += REG_READ(ah, AR_BEACON_CNT);
|
||||
}
|
||||
|
||||
static void ath9k_ani_restart(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ar5416AniState *aniState;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
aniState = ahp->ah_curani;
|
||||
|
||||
aniState->listenTime = 0;
|
||||
if (ahp->ah_hasHwPhyCounters) {
|
||||
if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
|
||||
aniState->ofdmPhyErrBase = 0;
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"OFDM Trigger is too high for hw counters\n");
|
||||
} else {
|
||||
aniState->ofdmPhyErrBase =
|
||||
AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
|
||||
}
|
||||
if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
|
||||
aniState->cckPhyErrBase = 0;
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"CCK Trigger is too high for hw counters\n");
|
||||
} else {
|
||||
aniState->cckPhyErrBase =
|
||||
AR_PHY_COUNTMAX - aniState->cckTrigHigh;
|
||||
}
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"%s: Writing ofdmbase=%u cckbase=%u\n",
|
||||
__func__, aniState->ofdmPhyErrBase,
|
||||
aniState->cckPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
|
||||
|
||||
ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
|
||||
}
|
||||
aniState->ofdmPhyErrCount = 0;
|
||||
aniState->cckPhyErrCount = 0;
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ath9k_channel *chan = ah->ah_curchan;
|
||||
struct ar5416AniState *aniState;
|
||||
enum wireless_mode mode;
|
||||
int32_t rssi;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
aniState = ahp->ah_curani;
|
||||
|
||||
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
aniState->spurImmunityLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ah->ah_opmode == ATH9K_M_HOSTAP) {
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
rssi = BEACON_RSSI(ahp);
|
||||
if (rssi > aniState->rssiThrHigh) {
|
||||
if (!aniState->ofdmWeakSigDetectOff) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
false)) {
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
return;
|
||||
}
|
||||
} else if (rssi > aniState->rssiThrLow) {
|
||||
if (aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
true);
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
return;
|
||||
} else {
|
||||
mode = ath9k_hw_chan2wmode(ah, chan);
|
||||
if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
|
||||
if (!aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
false);
|
||||
if (aniState->firstepLevel > 0)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ath9k_channel *chan = ah->ah_curchan;
|
||||
struct ar5416AniState *aniState;
|
||||
enum wireless_mode mode;
|
||||
int32_t rssi;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
aniState = ahp->ah_curani;
|
||||
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ah->ah_opmode == ATH9K_M_HOSTAP) {
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
rssi = BEACON_RSSI(ahp);
|
||||
if (rssi > aniState->rssiThrLow) {
|
||||
if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
} else {
|
||||
mode = ath9k_hw_chan2wmode(ah, chan);
|
||||
if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
|
||||
if (aniState->firstepLevel > 0)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_ani_lower_immunity(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t rssi;
|
||||
|
||||
aniState = ahp->ah_curani;
|
||||
|
||||
if (ah->ah_opmode == ATH9K_M_HOSTAP) {
|
||||
if (aniState->firstepLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel - 1))
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
rssi = BEACON_RSSI(ahp);
|
||||
if (rssi > aniState->rssiThrHigh) {
|
||||
/* XXX: Handle me */
|
||||
} else if (rssi > aniState->rssiThrLow) {
|
||||
if (aniState->ofdmWeakSigDetectOff) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
true) == true)
|
||||
return;
|
||||
}
|
||||
if (aniState->firstepLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel - 1) == true)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (aniState->firstepLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel - 1) == true)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aniState->spurImmunityLevel > 0) {
|
||||
if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
aniState->spurImmunityLevel - 1))
|
||||
return;
|
||||
}
|
||||
|
||||
if (aniState->noiseImmunityLevel > 0) {
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t ath9k_hw_ani_get_listen_time(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ar5416AniState *aniState;
|
||||
u32 txFrameCount, rxFrameCount, cycleCount;
|
||||
int32_t listenTime;
|
||||
|
||||
txFrameCount = REG_READ(ah, AR_TFCNT);
|
||||
rxFrameCount = REG_READ(ah, AR_RFCNT);
|
||||
cycleCount = REG_READ(ah, AR_CCCNT);
|
||||
|
||||
aniState = ahp->ah_curani;
|
||||
if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
|
||||
|
||||
listenTime = 0;
|
||||
ahp->ah_stats.ast_ani_lzero++;
|
||||
} else {
|
||||
int32_t ccdelta = cycleCount - aniState->cycleCount;
|
||||
int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
|
||||
int32_t tfdelta = txFrameCount - aniState->txFrameCount;
|
||||
listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
|
||||
}
|
||||
aniState->cycleCount = cycleCount;
|
||||
aniState->txFrameCount = txFrameCount;
|
||||
aniState->rxFrameCount = rxFrameCount;
|
||||
|
||||
return listenTime;
|
||||
}
|
||||
|
||||
void ath9k_ani_reset(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ar5416AniState *aniState;
|
||||
struct ath9k_channel *chan = ah->ah_curchan;
|
||||
int index;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
index = ath9k_hw_get_ani_channel_idx(ah, chan);
|
||||
aniState = &ahp->ah_ani[index];
|
||||
ahp->ah_curani = aniState;
|
||||
|
||||
if (DO_ANI(ah) && ah->ah_opmode != ATH9K_M_STA
|
||||
&& ah->ah_opmode != ATH9K_M_IBSS) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"%s: Reset ANI state opmode %u\n", __func__,
|
||||
ah->ah_opmode);
|
||||
ahp->ah_stats.ast_ani_reset++;
|
||||
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
!ATH9K_ANI_USE_OFDM_WEAK_SIG);
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
|
||||
ATH9K_ANI_CCK_WEAK_SIG_THR);
|
||||
|
||||
ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
|
||||
ATH9K_RX_FILTER_PHYERR);
|
||||
|
||||
if (ah->ah_opmode == ATH9K_M_HOSTAP) {
|
||||
ahp->ah_curani->ofdmTrigHigh =
|
||||
ah->ah_config.ofdm_trig_high;
|
||||
ahp->ah_curani->ofdmTrigLow =
|
||||
ah->ah_config.ofdm_trig_low;
|
||||
ahp->ah_curani->cckTrigHigh =
|
||||
ah->ah_config.cck_trig_high;
|
||||
ahp->ah_curani->cckTrigLow =
|
||||
ah->ah_config.cck_trig_low;
|
||||
}
|
||||
ath9k_ani_restart(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aniState->noiseImmunityLevel != 0)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
|
||||
aniState->noiseImmunityLevel);
|
||||
if (aniState->spurImmunityLevel != 0)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
|
||||
aniState->spurImmunityLevel);
|
||||
if (aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
!aniState->ofdmWeakSigDetectOff);
|
||||
if (aniState->cckWeakSigThreshold)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
|
||||
aniState->cckWeakSigThreshold);
|
||||
if (aniState->firstepLevel != 0)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel);
|
||||
if (ahp->ah_hasHwPhyCounters) {
|
||||
ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
|
||||
~ATH9K_RX_FILTER_PHYERR);
|
||||
ath9k_ani_restart(ah);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
|
||||
|
||||
} else {
|
||||
ath9k_ani_restart(ah);
|
||||
ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
|
||||
ATH9K_RX_FILTER_PHYERR);
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_monitor(struct ath_hal *ah,
|
||||
const struct ath9k_node_stats *stats,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t listenTime;
|
||||
|
||||
aniState = ahp->ah_curani;
|
||||
ahp->ah_stats.ast_nodestats = *stats;
|
||||
|
||||
listenTime = ath9k_hw_ani_get_listen_time(ah);
|
||||
if (listenTime < 0) {
|
||||
ahp->ah_stats.ast_ani_lneg++;
|
||||
ath9k_ani_restart(ah);
|
||||
return;
|
||||
}
|
||||
|
||||
aniState->listenTime += listenTime;
|
||||
|
||||
if (ahp->ah_hasHwPhyCounters) {
|
||||
u32 phyCnt1, phyCnt2;
|
||||
u32 ofdmPhyErrCnt, cckPhyErrCnt;
|
||||
|
||||
ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
|
||||
|
||||
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
|
||||
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
|
||||
|
||||
if (phyCnt1 < aniState->ofdmPhyErrBase ||
|
||||
phyCnt2 < aniState->cckPhyErrBase) {
|
||||
if (phyCnt1 < aniState->ofdmPhyErrBase) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"%s: phyCnt1 0x%x, resetting "
|
||||
"counter value to 0x%x\n",
|
||||
__func__, phyCnt1,
|
||||
aniState->ofdmPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1,
|
||||
aniState->ofdmPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1,
|
||||
AR_PHY_ERR_OFDM_TIMING);
|
||||
}
|
||||
if (phyCnt2 < aniState->cckPhyErrBase) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"%s: phyCnt2 0x%x, resetting "
|
||||
"counter value to 0x%x\n",
|
||||
__func__, phyCnt2,
|
||||
aniState->cckPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2,
|
||||
aniState->cckPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2,
|
||||
AR_PHY_ERR_CCK_TIMING);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
|
||||
ahp->ah_stats.ast_ani_ofdmerrs +=
|
||||
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
|
||||
aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
|
||||
|
||||
cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
|
||||
ahp->ah_stats.ast_ani_cckerrs +=
|
||||
cckPhyErrCnt - aniState->cckPhyErrCount;
|
||||
aniState->cckPhyErrCount = cckPhyErrCnt;
|
||||
}
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
|
||||
if (aniState->ofdmPhyErrCount <= aniState->listenTime *
|
||||
aniState->ofdmTrigLow / 1000 &&
|
||||
aniState->cckPhyErrCount <= aniState->listenTime *
|
||||
aniState->cckTrigLow / 1000)
|
||||
ath9k_hw_ani_lower_immunity(ah);
|
||||
ath9k_ani_restart(ah);
|
||||
} else if (aniState->listenTime > ahp->ah_aniPeriod) {
|
||||
if (aniState->ofdmPhyErrCount > aniState->listenTime *
|
||||
aniState->ofdmTrigHigh / 1000) {
|
||||
ath9k_hw_ani_ofdm_err_trigger(ah);
|
||||
ath9k_ani_restart(ah);
|
||||
} else if (aniState->cckPhyErrCount >
|
||||
aniState->listenTime * aniState->cckTrigHigh /
|
||||
1000) {
|
||||
ath9k_hw_ani_cck_err_trigger(ah);
|
||||
ath9k_ani_restart(ah);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ath9k_hw_phycounters(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
|
||||
return ahp->ah_hasHwPhyCounters ? true : false;
|
||||
}
|
||||
|
||||
void ath9k_enable_mib_counters(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
|
||||
|
||||
ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
|
||||
|
||||
REG_WRITE(ah, AR_FILT_OFDM, 0);
|
||||
REG_WRITE(ah, AR_FILT_CCK, 0);
|
||||
REG_WRITE(ah, AR_MIBC,
|
||||
~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
|
||||
& 0x0f);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
|
||||
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
|
||||
}
|
||||
|
||||
void ath9k_hw_disable_mib_counters(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n");
|
||||
|
||||
REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
|
||||
|
||||
ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
|
||||
|
||||
REG_WRITE(ah, AR_FILT_OFDM, 0);
|
||||
REG_WRITE(ah, AR_FILT_CCK, 0);
|
||||
}
|
||||
|
||||
u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
|
||||
u32 *rxc_pcnt,
|
||||
u32 *rxf_pcnt,
|
||||
u32 *txf_pcnt)
|
||||
{
|
||||
static u32 cycles, rx_clear, rx_frame, tx_frame;
|
||||
u32 good = 1;
|
||||
|
||||
u32 rc = REG_READ(ah, AR_RCCNT);
|
||||
u32 rf = REG_READ(ah, AR_RFCNT);
|
||||
u32 tf = REG_READ(ah, AR_TFCNT);
|
||||
u32 cc = REG_READ(ah, AR_CCCNT);
|
||||
|
||||
if (cycles == 0 || cycles > cc) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
|
||||
"%s: cycle counter wrap. ExtBusy = 0\n",
|
||||
__func__);
|
||||
good = 0;
|
||||
} else {
|
||||
u32 cc_d = cc - cycles;
|
||||
u32 rc_d = rc - rx_clear;
|
||||
u32 rf_d = rf - rx_frame;
|
||||
u32 tf_d = tf - tx_frame;
|
||||
|
||||
if (cc_d != 0) {
|
||||
*rxc_pcnt = rc_d * 100 / cc_d;
|
||||
*rxf_pcnt = rf_d * 100 / cc_d;
|
||||
*txf_pcnt = tf_d * 100 / cc_d;
|
||||
} else {
|
||||
good = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cycles = cc;
|
||||
rx_frame = rf;
|
||||
rx_clear = rc;
|
||||
tx_frame = tf;
|
||||
|
||||
return good;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a MIB interrupt. We may potentially be invoked because
|
||||
* any of the MIB counters overflow/trigger so don't assume we're
|
||||
* here because a PHY error counter triggered.
|
||||
*/
|
||||
void ath9k_hw_procmibevent(struct ath_hal *ah,
|
||||
const struct ath9k_node_stats *stats)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
u32 phyCnt1, phyCnt2;
|
||||
|
||||
/* Reset these counters regardless */
|
||||
REG_WRITE(ah, AR_FILT_OFDM, 0);
|
||||
REG_WRITE(ah, AR_FILT_CCK, 0);
|
||||
if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
|
||||
REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
|
||||
|
||||
/* Clear the mib counters and save them in the stats */
|
||||
ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
|
||||
ahp->ah_stats.ast_nodestats = *stats;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
/* NB: these are not reset-on-read */
|
||||
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
|
||||
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
|
||||
if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
|
||||
((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
|
||||
struct ar5416AniState *aniState = ahp->ah_curani;
|
||||
u32 ofdmPhyErrCnt, cckPhyErrCnt;
|
||||
|
||||
/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
|
||||
ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
|
||||
ahp->ah_stats.ast_ani_ofdmerrs +=
|
||||
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
|
||||
aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
|
||||
|
||||
cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
|
||||
ahp->ah_stats.ast_ani_cckerrs +=
|
||||
cckPhyErrCnt - aniState->cckPhyErrCount;
|
||||
aniState->cckPhyErrCount = cckPhyErrCnt;
|
||||
|
||||
/*
|
||||
* NB: figure out which counter triggered. If both
|
||||
* trigger we'll only deal with one as the processing
|
||||
* clobbers the error counter so the trigger threshold
|
||||
* check will never be true.
|
||||
*/
|
||||
if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
|
||||
ath9k_hw_ani_ofdm_err_trigger(ah);
|
||||
if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
|
||||
ath9k_hw_ani_cck_err_trigger(ah);
|
||||
/* NB: always restart to insure the h/w counters are reset */
|
||||
ath9k_ani_restart(ah);
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_setup(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
int i;
|
||||
|
||||
const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
|
||||
const int coarseHigh[] = { -14, -14, -14, -14, -12 };
|
||||
const int coarseLow[] = { -64, -64, -64, -64, -70 };
|
||||
const int firpwr[] = { -78, -78, -78, -78, -80 };
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
ahp->ah_totalSizeDesired[i] = totalSizeDesired[i];
|
||||
ahp->ah_coarseHigh[i] = coarseHigh[i];
|
||||
ahp->ah_coarseLow[i] = coarseLow[i];
|
||||
ahp->ah_firpwr[i] = firpwr[i];
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_attach(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
int i;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n");
|
||||
|
||||
ahp->ah_hasHwPhyCounters = 1;
|
||||
|
||||
memset(ahp->ah_ani, 0, sizeof(ahp->ah_ani));
|
||||
for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
|
||||
ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
|
||||
ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
|
||||
ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
|
||||
ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
|
||||
ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
|
||||
ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
|
||||
ahp->ah_ani[i].ofdmWeakSigDetectOff =
|
||||
!ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
ahp->ah_ani[i].cckWeakSigThreshold =
|
||||
ATH9K_ANI_CCK_WEAK_SIG_THR;
|
||||
ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
|
||||
ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
|
||||
if (ahp->ah_hasHwPhyCounters) {
|
||||
ahp->ah_ani[i].ofdmPhyErrBase =
|
||||
AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
|
||||
ahp->ah_ani[i].cckPhyErrBase =
|
||||
AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
|
||||
}
|
||||
}
|
||||
if (ahp->ah_hasHwPhyCounters) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI,
|
||||
"Setting OfdmErrBase = 0x%08x\n",
|
||||
ahp->ah_ani[0].ofdmPhyErrBase);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
|
||||
ahp->ah_ani[0].cckPhyErrBase);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase);
|
||||
ath9k_enable_mib_counters(ah);
|
||||
}
|
||||
ahp->ah_aniPeriod = ATH9K_ANI_PERIOD;
|
||||
if (ah->ah_config.enable_ani)
|
||||
ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_detach(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n");
|
||||
|
||||
if (ahp->ah_hasHwPhyCounters) {
|
||||
ath9k_hw_disable_mib_counters(ah);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, 0);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, 0);
|
||||
}
|
||||
}
|
|
@ -828,195 +828,251 @@ struct chan_centers {
|
|||
u16 ext_center;
|
||||
};
|
||||
|
||||
int ath_hal_getcapability(struct ath_hal *ah,
|
||||
enum ath9k_capability_type type,
|
||||
u32 capability,
|
||||
u32 *result);
|
||||
const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
|
||||
u32 mode);
|
||||
void ath9k_hw_detach(struct ath_hal *ah);
|
||||
struct ath_hal *ath9k_hw_attach(u16 devid,
|
||||
struct ath_softc *sc,
|
||||
void __iomem *mem,
|
||||
int *error);
|
||||
bool ath9k_regd_init_channels(struct ath_hal *ah,
|
||||
u32 maxchans, u32 *nchans,
|
||||
u8 *regclassids,
|
||||
u32 maxregids, u32 *nregids,
|
||||
u16 cc,
|
||||
bool enableOutdoor,
|
||||
bool enableExtendedChannels);
|
||||
/* Helpers */
|
||||
|
||||
enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
|
||||
const struct ath9k_channel *chan);
|
||||
bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val);
|
||||
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
|
||||
bool ath9k_get_channel_edges(struct ath_hal *ah,
|
||||
u16 flags, u16 *low,
|
||||
u16 *high);
|
||||
u16 ath9k_hw_computetxtime(struct ath_hal *ah,
|
||||
const struct ath9k_rate_table *rates,
|
||||
u32 frameLen, u16 rateix,
|
||||
bool shortPreamble);
|
||||
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
|
||||
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah,
|
||||
enum ath9k_int ints);
|
||||
bool ath9k_hw_reset(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
void ath9k_hw_get_channel_centers(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct chan_centers *centers);
|
||||
|
||||
/* Attach, Detach */
|
||||
|
||||
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
|
||||
void ath9k_hw_detach(struct ath_hal *ah);
|
||||
struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc,
|
||||
void __iomem *mem, int *error);
|
||||
void ath9k_hw_rfdetach(struct ath_hal *ah);
|
||||
|
||||
|
||||
/* HW Reset */
|
||||
|
||||
bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
enum ath9k_ht_macmode macmode,
|
||||
u8 txchainmask, u8 rxchainmask,
|
||||
enum ath9k_ht_extprotspacing extprotspacing,
|
||||
bool bChannelChange,
|
||||
int *status);
|
||||
bool ath9k_hw_phy_disable(struct ath_hal *ah);
|
||||
void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
bool *isCalDone);
|
||||
void ath9k_hw_ani_monitor(struct ath_hal *ah,
|
||||
const struct ath9k_node_stats *stats,
|
||||
struct ath9k_channel *chan);
|
||||
bool ath9k_hw_calibrate(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u8 rxchainmask,
|
||||
bool longcal,
|
||||
bool *isCalDone);
|
||||
s16 ath9k_hw_getchan_noise(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
|
||||
u16 assocId);
|
||||
void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits);
|
||||
void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
|
||||
u16 assocId);
|
||||
bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q);
|
||||
void ath9k_hw_reset_tsf(struct ath_hal *ah);
|
||||
bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry);
|
||||
bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry,
|
||||
const u8 *mac);
|
||||
bool ath9k_hw_set_keycache_entry(struct ath_hal *ah,
|
||||
u16 entry,
|
||||
const struct ath9k_keyval *k,
|
||||
const u8 *mac,
|
||||
int xorKey);
|
||||
bool ath9k_hw_set_tsfadjust(struct ath_hal *ah,
|
||||
u32 setting);
|
||||
void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
|
||||
bool ath9k_hw_intrpend(struct ath_hal *ah);
|
||||
bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked);
|
||||
bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah,
|
||||
bool bIncTrigLevel);
|
||||
void ath9k_hw_procmibevent(struct ath_hal *ah,
|
||||
const struct ath9k_node_stats *stats);
|
||||
bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set);
|
||||
void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
|
||||
bool ath9k_hw_phycounters(struct ath_hal *ah);
|
||||
bool bChannelChange, int *status);
|
||||
|
||||
/* Key Cache Management */
|
||||
|
||||
bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry);
|
||||
bool ath9k_hw_getcapability(struct ath_hal *ah,
|
||||
enum ath9k_capability_type type,
|
||||
u32 capability,
|
||||
u32 *result);
|
||||
bool ath9k_hw_setcapability(struct ath_hal *ah,
|
||||
enum ath9k_capability_type type,
|
||||
u32 capability,
|
||||
u32 setting,
|
||||
int *status);
|
||||
u32 ath9k_hw_getdefantenna(struct ath_hal *ah);
|
||||
void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac);
|
||||
void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
|
||||
bool ath9k_hw_setbssidmask(struct ath_hal *ah,
|
||||
const u8 *mask);
|
||||
bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, const u8 *mac);
|
||||
bool ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
|
||||
const struct ath9k_keyval *k,
|
||||
const u8 *mac, int xorKey);
|
||||
bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry);
|
||||
|
||||
/* Power Management */
|
||||
|
||||
bool ath9k_hw_setpower(struct ath_hal *ah,
|
||||
enum ath9k_power_mode mode);
|
||||
enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah);
|
||||
u64 ath9k_hw_gettsf64(struct ath_hal *ah);
|
||||
void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
|
||||
|
||||
/* Beacon timers */
|
||||
|
||||
void ath9k_hw_beaconinit(struct ath_hal *ah, u32 next_beacon, u32 beacon_period);
|
||||
void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
|
||||
const struct ath9k_beacon_state *bs);
|
||||
|
||||
/* Rate table */
|
||||
|
||||
const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
|
||||
u32 mode);
|
||||
|
||||
/* HW Capabilities */
|
||||
|
||||
bool ath9k_hw_fill_cap_info(struct ath_hal *ah);
|
||||
bool ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type,
|
||||
u32 capability, u32 *result);
|
||||
bool ath9k_hw_setcapability(struct ath_hal *ah, enum ath9k_capability_type type,
|
||||
u32 capability, u32 setting, int *status);
|
||||
|
||||
/* GPIO / RFKILL / Antennae */
|
||||
|
||||
void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
|
||||
u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
|
||||
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
||||
u32 ah_signal_type);
|
||||
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val);
|
||||
#ifdef CONFIG_RFKILL
|
||||
void ath9k_enable_rfkill(struct ath_hal *ah);
|
||||
#endif
|
||||
int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg);
|
||||
u32 ath9k_hw_getdefantenna(struct ath_hal *ah);
|
||||
bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
|
||||
void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
|
||||
bool ath9k_hw_setantennaswitch(struct ath_hal *ah,
|
||||
enum ath9k_ant_setting settings,
|
||||
struct ath9k_channel *chan,
|
||||
u8 *tx_chainmask,
|
||||
u8 *rx_chainmask,
|
||||
u8 *antenna_cfgd);
|
||||
void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
|
||||
int ath9k_hw_select_antconfig(struct ath_hal *ah,
|
||||
u32 cfg);
|
||||
bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q,
|
||||
u32 txdp);
|
||||
|
||||
/* General Operation */
|
||||
|
||||
u32 ath9k_hw_getrxfilter(struct ath_hal *ah);
|
||||
void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits);
|
||||
bool ath9k_hw_phy_disable(struct ath_hal *ah);
|
||||
bool ath9k_hw_disable(struct ath_hal *ah);
|
||||
bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit);
|
||||
void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac);
|
||||
bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac);
|
||||
void ath9k_hw_setopmode(struct ath_hal *ah);
|
||||
void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, u32 filter1);
|
||||
void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
|
||||
bool ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask);
|
||||
void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId);
|
||||
u64 ath9k_hw_gettsf64(struct ath_hal *ah);
|
||||
void ath9k_hw_reset_tsf(struct ath_hal *ah);
|
||||
bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting);
|
||||
bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
|
||||
void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
|
||||
|
||||
/* Regulatory */
|
||||
|
||||
bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
|
||||
struct ath9k_channel* ath9k_regd_check_channel(struct ath_hal *ah,
|
||||
const struct ath9k_channel *c);
|
||||
u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
|
||||
u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
bool ath9k_regd_init_channels(struct ath_hal *ah,
|
||||
u32 maxchans, u32 *nchans, u8 *regclassids,
|
||||
u32 maxregids, u32 *nregids, u16 cc,
|
||||
bool enableOutdoor, bool enableExtendedChannels);
|
||||
|
||||
/* ANI */
|
||||
|
||||
void ath9k_ani_reset(struct ath_hal *ah);
|
||||
void ath9k_hw_ani_monitor(struct ath_hal *ah,
|
||||
const struct ath9k_node_stats *stats,
|
||||
struct ath9k_channel *chan);
|
||||
bool ath9k_hw_phycounters(struct ath_hal *ah);
|
||||
void ath9k_enable_mib_counters(struct ath_hal *ah);
|
||||
void ath9k_hw_disable_mib_counters(struct ath_hal *ah);
|
||||
u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
|
||||
u32 *rxc_pcnt,
|
||||
u32 *rxf_pcnt,
|
||||
u32 *txf_pcnt);
|
||||
void ath9k_hw_procmibevent(struct ath_hal *ah,
|
||||
const struct ath9k_node_stats *stats);
|
||||
void ath9k_hw_ani_setup(struct ath_hal *ah);
|
||||
void ath9k_hw_ani_attach(struct ath_hal *ah);
|
||||
void ath9k_hw_ani_detach(struct ath_hal *ah);
|
||||
|
||||
/* Calibration */
|
||||
|
||||
void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
bool *isCalDone);
|
||||
void ath9k_hw_start_nfcal(struct ath_hal *ah);
|
||||
void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan);
|
||||
int16_t ath9k_hw_getnf(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah);
|
||||
s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan);
|
||||
bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
u8 rxchainmask, bool longcal,
|
||||
bool *isCalDone);
|
||||
bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
|
||||
|
||||
/* EEPROM */
|
||||
|
||||
int ath9k_hw_set_txpower(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u16 cfgCtl,
|
||||
u8 twiceAntennaReduction,
|
||||
u8 twiceMaxRegulatoryPower,
|
||||
u8 powerLimit);
|
||||
void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan);
|
||||
bool ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
int16_t *ratesArray,
|
||||
u16 cfgCtl,
|
||||
u8 AntennaReduction,
|
||||
u8 twiceMaxRegulatoryPower,
|
||||
u8 powerLimit);
|
||||
bool ath9k_hw_set_power_cal_table(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
int16_t *pTxPowerIndexOffset);
|
||||
bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u8 index, u16 *config);
|
||||
u8 ath9k_hw_get_num_ant_config(struct ath_hal *ah,
|
||||
enum ieee80211_band freq_band);
|
||||
u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, u16 i, bool is2GHz);
|
||||
int ath9k_hw_eeprom_attach(struct ath_hal *ah);
|
||||
|
||||
/* Interrupt Handling */
|
||||
|
||||
bool ath9k_hw_intrpend(struct ath_hal *ah);
|
||||
bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked);
|
||||
enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah);
|
||||
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints);
|
||||
|
||||
/* MAC (PCU/QCU) */
|
||||
|
||||
void ath9k_hw_dmaRegDump(struct ath_hal *ah);
|
||||
u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q);
|
||||
bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, u32 txdp);
|
||||
bool ath9k_hw_txstart(struct ath_hal *ah, u32 q);
|
||||
u16 ath9k_hw_computetxtime(struct ath_hal *ah,
|
||||
const struct ath9k_rate_table *rates,
|
||||
u32 frameLen, u16 rateix,
|
||||
bool shortPreamble);
|
||||
u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q);
|
||||
bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel);
|
||||
bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q);
|
||||
bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 segLen, bool firstSeg,
|
||||
bool lastSeg, const struct ath_desc *ds0);
|
||||
void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds);
|
||||
int ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds);
|
||||
void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
|
||||
u32 keyIx, enum ath9k_key_type keyType, u32 flags);
|
||||
void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
|
||||
struct ath_desc *lastds,
|
||||
u32 durUpdateEn, u32 rtsctsRate,
|
||||
u32 rtsctsDuration,
|
||||
struct ath9k_11n_rate_series series[],
|
||||
u32 nseries, u32 flags);
|
||||
void ath9k_hw_set11n_burstduration(struct ath_hal *ah,
|
||||
struct ath_desc *ds,
|
||||
void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 aggrLen);
|
||||
void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 numDelims);
|
||||
void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds);
|
||||
void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds);
|
||||
void ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 burstDuration);
|
||||
void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds);
|
||||
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
|
||||
bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q);
|
||||
u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
|
||||
u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
|
||||
bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
|
||||
struct ath9k_tx_queue_info *qinfo);
|
||||
void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 vmf);
|
||||
void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs);
|
||||
bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
|
||||
const struct ath9k_tx_queue_info *qinfo);
|
||||
struct ath9k_channel *ath9k_regd_check_channel(struct ath_hal *ah,
|
||||
const struct ath9k_channel *c);
|
||||
void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 pktLen, enum ath9k_pkt_type type,
|
||||
u32 txPower, u32 keyIx,
|
||||
enum ath9k_key_type keyType, u32 flags);
|
||||
bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 segLen, bool firstSeg,
|
||||
bool lastSeg,
|
||||
const struct ath_desc *ds0);
|
||||
u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
|
||||
u32 *rxc_pcnt,
|
||||
u32 *rxf_pcnt,
|
||||
u32 *txf_pcnt);
|
||||
void ath9k_hw_dmaRegDump(struct ath_hal *ah);
|
||||
void ath9k_hw_beaconinit(struct ath_hal *ah,
|
||||
u32 next_beacon, u32 beacon_period);
|
||||
void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
|
||||
const struct ath9k_beacon_state *bs);
|
||||
bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
|
||||
struct ath9k_tx_queue_info *qinfo);
|
||||
int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
|
||||
const struct ath9k_tx_queue_info *qinfo);
|
||||
bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q);
|
||||
bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q);
|
||||
int ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 pa, struct ath_desc *nds, u64 tsf);
|
||||
bool ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 size, u32 flags);
|
||||
bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set);
|
||||
void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp);
|
||||
void ath9k_hw_rxena(struct ath_hal *ah);
|
||||
void ath9k_hw_setopmode(struct ath_hal *ah);
|
||||
bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac);
|
||||
void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0,
|
||||
u32 filter1);
|
||||
u32 ath9k_hw_getrxfilter(struct ath_hal *ah);
|
||||
void ath9k_hw_startpcureceive(struct ath_hal *ah);
|
||||
void ath9k_hw_stoppcurecv(struct ath_hal *ah);
|
||||
bool ath9k_hw_stopdmarecv(struct ath_hal *ah);
|
||||
int ath9k_hw_rxprocdesc(struct ath_hal *ah,
|
||||
struct ath_desc *ds, u32 pa,
|
||||
struct ath_desc *nds, u64 tsf);
|
||||
u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q);
|
||||
int ath9k_hw_txprocdesc(struct ath_hal *ah,
|
||||
struct ath_desc *ds);
|
||||
void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 numDelims);
|
||||
void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
|
||||
u32 aggrLen);
|
||||
void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds);
|
||||
bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q);
|
||||
void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs);
|
||||
void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds);
|
||||
void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah,
|
||||
struct ath_desc *ds, u32 vmf);
|
||||
bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit);
|
||||
bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
|
||||
int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
|
||||
const struct ath9k_tx_queue_info *qinfo);
|
||||
u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q);
|
||||
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
|
||||
bool ath9k_hw_disable(struct ath_hal *ah);
|
||||
void ath9k_hw_rfdetach(struct ath_hal *ah);
|
||||
void ath9k_hw_get_channel_centers(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct chan_centers *centers);
|
||||
bool ath9k_get_channel_edges(struct ath_hal *ah,
|
||||
u16 flags, u16 *low,
|
||||
u16 *high);
|
||||
void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
|
||||
u32 ah_signal_type);
|
||||
void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
|
||||
u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
|
||||
void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
|
||||
|
||||
#endif
|
||||
|
|
930
drivers/net/wireless/ath9k/calib.c
Normal file
930
drivers/net/wireless/ath9k/calib.c
Normal file
|
@ -0,0 +1,930 @@
|
|||
/*
|
||||
* Copyright (c) 2008 Atheros Communications Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "hw.h"
|
||||
#include "reg.h"
|
||||
#include "phy.h"
|
||||
|
||||
static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
|
||||
|
||||
/* We can tune this as we go by monitoring really low values */
|
||||
#define ATH9K_NF_TOO_LOW -60
|
||||
|
||||
/* AR5416 may return very high value (like -31 dBm), in those cases the nf
|
||||
* is incorrect and we should use the static NF value. Later we can try to
|
||||
* find out why they are reporting these values */
|
||||
|
||||
static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf)
|
||||
{
|
||||
if (nf > ATH9K_NF_TOO_LOW) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
|
||||
"%s: noise floor value detected (%d) is "
|
||||
"lower than what we think is a "
|
||||
"reasonable value (%d)\n",
|
||||
__func__, nf, ATH9K_NF_TOO_LOW);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
|
||||
{
|
||||
int16_t nfval;
|
||||
int16_t sort[ATH9K_NF_CAL_HIST_MAX];
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
|
||||
sort[i] = nfCalBuffer[i];
|
||||
|
||||
for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
|
||||
for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
|
||||
if (sort[j] > sort[j - 1]) {
|
||||
nfval = sort[j];
|
||||
sort[j] = sort[j - 1];
|
||||
sort[j - 1] = nfval;
|
||||
}
|
||||
}
|
||||
}
|
||||
nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
|
||||
|
||||
return nfval;
|
||||
}
|
||||
|
||||
static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
|
||||
int16_t *nfarray)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
|
||||
|
||||
if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
|
||||
h[i].currIndex = 0;
|
||||
|
||||
if (h[i].invalidNFcount > 0) {
|
||||
if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
|
||||
nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
|
||||
h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
|
||||
} else {
|
||||
h[i].invalidNFcount--;
|
||||
h[i].privNF = nfarray[i];
|
||||
}
|
||||
} else {
|
||||
h[i].privNF =
|
||||
ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void ath9k_hw_do_getnf(struct ath_hal *ah,
|
||||
int16_t nfarray[NUM_NF_READINGS])
|
||||
{
|
||||
int16_t nf;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
|
||||
else
|
||||
nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 0] is %d\n", nf);
|
||||
nfarray[0] = nf;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
|
||||
AR9280_PHY_CH1_MINCCA_PWR);
|
||||
else
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
|
||||
AR_PHY_CH1_MINCCA_PWR);
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
|
||||
"NF calibrated [ctl] [chain 1] is %d\n", nf);
|
||||
nfarray[1] = nf;
|
||||
|
||||
if (!AR_SREV_9280(ah)) {
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
|
||||
AR_PHY_CH2_MINCCA_PWR);
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
|
||||
"NF calibrated [ctl] [chain 2] is %d\n", nf);
|
||||
nfarray[2] = nf;
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
|
||||
AR9280_PHY_EXT_MINCCA_PWR);
|
||||
else
|
||||
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
|
||||
AR_PHY_EXT_MINCCA_PWR);
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
|
||||
"NF calibrated [ext] [chain 0] is %d\n", nf);
|
||||
nfarray[3] = nf;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
|
||||
AR9280_PHY_CH1_EXT_MINCCA_PWR);
|
||||
else
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
|
||||
AR_PHY_CH1_EXT_MINCCA_PWR);
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 1] is %d\n", nf);
|
||||
nfarray[4] = nf;
|
||||
|
||||
if (!AR_SREV_9280(ah)) {
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
|
||||
AR_PHY_CH2_EXT_MINCCA_PWR);
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
|
||||
"NF calibrated [ext] [chain 2] is %d\n", nf);
|
||||
nfarray[5] = nf;
|
||||
}
|
||||
}
|
||||
|
||||
static bool getNoiseFloorThresh(struct ath_hal *ah,
|
||||
const struct ath9k_channel *chan,
|
||||
int16_t *nft)
|
||||
{
|
||||
switch (chan->chanmode) {
|
||||
case CHANNEL_A:
|
||||
case CHANNEL_A_HT20:
|
||||
case CHANNEL_A_HT40PLUS:
|
||||
case CHANNEL_A_HT40MINUS:
|
||||
*nft = (int16_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
|
||||
break;
|
||||
case CHANNEL_B:
|
||||
case CHANNEL_G:
|
||||
case CHANNEL_G_HT20:
|
||||
case CHANNEL_G_HT40PLUS:
|
||||
case CHANNEL_G_HT40MINUS:
|
||||
*nft = (int16_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
|
||||
"%s: invalid channel flags 0x%x\n", __func__,
|
||||
chan->channelFlags);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ath9k_hw_setup_calibration(struct ath_hal *ah,
|
||||
struct hal_cal_list *currCal)
|
||||
{
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
|
||||
AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
|
||||
currCal->calData->calCountMax);
|
||||
|
||||
switch (currCal->calData->calType) {
|
||||
case IQ_MISMATCH_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: starting IQ Mismatch Calibration\n",
|
||||
__func__);
|
||||
break;
|
||||
case ADC_GAIN_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: starting ADC Gain Calibration\n", __func__);
|
||||
break;
|
||||
case ADC_DC_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: starting ADC DC Calibration\n", __func__);
|
||||
break;
|
||||
case ADC_DC_INIT_CAL:
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: starting Init ADC DC Calibration\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
|
||||
AR_PHY_TIMING_CTRL4_DO_CAL);
|
||||
}
|
||||
|
||||
static void ath9k_hw_reset_calibration(struct ath_hal *ah,
|
||||
struct hal_cal_list *currCal)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
int i;
|
||||
|
||||
ath9k_hw_setup_calibration(ah, currCal);
|
||||
|
||||
currCal->calState = CAL_RUNNING;
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
ahp->ah_Meas0.sign[i] = 0;
|
||||
ahp->ah_Meas1.sign[i] = 0;
|
||||
ahp->ah_Meas2.sign[i] = 0;
|
||||
ahp->ah_Meas3.sign[i] = 0;
|
||||
}
|
||||
|
||||
ahp->ah_CalSamples = 0;
|
||||
}
|
||||
|
||||
static void ath9k_hw_per_calibration(struct ath_hal *ah,
|
||||
struct ath9k_channel *ichan,
|
||||
u8 rxchainmask,
|
||||
struct hal_cal_list *currCal,
|
||||
bool *isCalDone)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
|
||||
*isCalDone = false;
|
||||
|
||||
if (currCal->calState == CAL_RUNNING) {
|
||||
if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
|
||||
AR_PHY_TIMING_CTRL4_DO_CAL)) {
|
||||
|
||||
currCal->calData->calCollect(ah);
|
||||
ahp->ah_CalSamples++;
|
||||
|
||||
if (ahp->ah_CalSamples >= currCal->calData->calNumSamples) {
|
||||
int i, numChains = 0;
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
if (rxchainmask & (1 << i))
|
||||
numChains++;
|
||||
}
|
||||
|
||||
currCal->calData->calPostProc(ah, numChains);
|
||||
ichan->CalValid |= currCal->calData->calType;
|
||||
currCal->calState = CAL_DONE;
|
||||
*isCalDone = true;
|
||||
} else {
|
||||
ath9k_hw_setup_calibration(ah, currCal);
|
||||
}
|
||||
}
|
||||
} else if (!(ichan->CalValid & currCal->calData->calType)) {
|
||||
ath9k_hw_reset_calibration(ah, currCal);
|
||||
}
|
||||
}
|
||||
|
||||
static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum hal_cal_types calType)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
bool retval = false;
|
||||
|
||||
switch (calType & ahp->ah_suppCals) {
|
||||
case IQ_MISMATCH_CAL:
|
||||
if (!IS_CHAN_B(chan))
|
||||
retval = true;
|
||||
break;
|
||||
case ADC_GAIN_CAL:
|
||||
case ADC_DC_CAL:
|
||||
if (!IS_CHAN_B(chan)
|
||||
&& !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
ahp->ah_totalPowerMeasI[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
|
||||
ahp->ah_totalPowerMeasQ[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
|
||||
ahp->ah_totalIqCorrMeas[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
|
||||
ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
|
||||
ahp->ah_totalPowerMeasQ[i],
|
||||
ahp->ah_totalIqCorrMeas[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
ahp->ah_totalAdcIOddPhase[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
|
||||
ahp->ah_totalAdcIEvenPhase[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
|
||||
ahp->ah_totalAdcQOddPhase[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
|
||||
ahp->ah_totalAdcQEvenPhase[i] +=
|
||||
REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
|
||||
"oddq=0x%08x; evenq=0x%08x;\n",
|
||||
ahp->ah_CalSamples, i,
|
||||
ahp->ah_totalAdcIOddPhase[i],
|
||||
ahp->ah_totalAdcIEvenPhase[i],
|
||||
ahp->ah_totalAdcQOddPhase[i],
|
||||
ahp->ah_totalAdcQEvenPhase[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
|
||||
ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
|
||||
ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
|
||||
ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
|
||||
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
|
||||
"oddq=0x%08x; evenq=0x%08x;\n",
|
||||
ahp->ah_CalSamples, i,
|
||||
ahp->ah_totalAdcDcOffsetIOddPhase[i],
|
||||
ahp->ah_totalAdcDcOffsetIEvenPhase[i],
|
||||
ahp->ah_totalAdcDcOffsetQOddPhase[i],
|
||||
ahp->ah_totalAdcDcOffsetQEvenPhase[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
u32 powerMeasQ, powerMeasI, iqCorrMeas;
|
||||
u32 qCoffDenom, iCoffDenom;
|
||||
int32_t qCoff, iCoff;
|
||||
int iqCorrNeg, i;
|
||||
|
||||
for (i = 0; i < numChains; i++) {
|
||||
powerMeasI = ahp->ah_totalPowerMeasI[i];
|
||||
powerMeasQ = ahp->ah_totalPowerMeasQ[i];
|
||||
iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Starting IQ Cal and Correction for Chain %d\n",
|
||||
i);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Orignal: Chn %diq_corr_meas = 0x%08x\n",
|
||||
i, ahp->ah_totalIqCorrMeas[i]);
|
||||
|
||||
iqCorrNeg = 0;
|
||||
|
||||
if (iqCorrMeas > 0x80000000) {
|
||||
iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
|
||||
iqCorrNeg = 1;
|
||||
}
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
|
||||
iqCorrNeg);
|
||||
|
||||
iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
|
||||
qCoffDenom = powerMeasQ / 64;
|
||||
|
||||
if (powerMeasQ != 0) {
|
||||
iCoff = iqCorrMeas / iCoffDenom;
|
||||
qCoff = powerMeasI / qCoffDenom - 64;
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d iCoff = 0x%08x\n", i, iCoff);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d qCoff = 0x%08x\n", i, qCoff);
|
||||
|
||||
iCoff = iCoff & 0x3f;
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
|
||||
if (iqCorrNeg == 0x0)
|
||||
iCoff = 0x40 - iCoff;
|
||||
|
||||
if (qCoff > 15)
|
||||
qCoff = 15;
|
||||
else if (qCoff <= -16)
|
||||
qCoff = 16;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
|
||||
i, iCoff, qCoff);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
|
||||
AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
|
||||
iCoff);
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
|
||||
AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
|
||||
qCoff);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"IQ Cal and Correction done for Chain %d\n",
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
|
||||
AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
|
||||
}
|
||||
|
||||
static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
|
||||
u32 qGainMismatch, iGainMismatch, val, i;
|
||||
|
||||
for (i = 0; i < numChains; i++) {
|
||||
iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
|
||||
iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
|
||||
qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
|
||||
qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Starting ADC Gain Cal for Chain %d\n", i);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_i = 0x%08x\n", i,
|
||||
iOddMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_i = 0x%08x\n", i,
|
||||
iEvenMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_q = 0x%08x\n", i,
|
||||
qOddMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_q = 0x%08x\n", i,
|
||||
qEvenMeasOffset);
|
||||
|
||||
if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
|
||||
iGainMismatch =
|
||||
((iEvenMeasOffset * 32) /
|
||||
iOddMeasOffset) & 0x3f;
|
||||
qGainMismatch =
|
||||
((qOddMeasOffset * 32) /
|
||||
qEvenMeasOffset) & 0x3f;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d gain_mismatch_i = 0x%08x\n", i,
|
||||
iGainMismatch);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d gain_mismatch_q = 0x%08x\n", i,
|
||||
qGainMismatch);
|
||||
|
||||
val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
|
||||
val &= 0xfffff000;
|
||||
val |= (qGainMismatch) | (iGainMismatch << 6);
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"ADC Gain Cal done for Chain %d\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
|
||||
REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
|
||||
AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
|
||||
}
|
||||
|
||||
static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
u32 iOddMeasOffset, iEvenMeasOffset, val, i;
|
||||
int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
|
||||
const struct hal_percal_data *calData =
|
||||
ahp->ah_cal_list_curr->calData;
|
||||
u32 numSamples =
|
||||
(1 << (calData->calCountMax + 5)) * calData->calNumSamples;
|
||||
|
||||
for (i = 0; i < numChains; i++) {
|
||||
iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
|
||||
iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
|
||||
qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
|
||||
qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Starting ADC DC Offset Cal for Chain %d\n", i);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_i = %d\n", i,
|
||||
iOddMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_i = %d\n", i,
|
||||
iEvenMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_odd_q = %d\n", i,
|
||||
qOddMeasOffset);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d pwr_meas_even_q = %d\n", i,
|
||||
qEvenMeasOffset);
|
||||
|
||||
iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
|
||||
numSamples) & 0x1ff;
|
||||
qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
|
||||
numSamples) & 0x1ff;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
|
||||
iDcMismatch);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
|
||||
qDcMismatch);
|
||||
|
||||
val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
|
||||
val &= 0xc0000fff;
|
||||
val |= (qDcMismatch << 12) | (iDcMismatch << 21);
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"ADC DC Offset Cal done for Chain %d\n", i);
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
|
||||
REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
|
||||
AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
|
||||
}
|
||||
|
||||
void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
bool *isCalDone)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ath9k_channel *ichan =
|
||||
ath9k_regd_check_channel(ah, chan);
|
||||
struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
|
||||
|
||||
*isCalDone = true;
|
||||
|
||||
if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
|
||||
return;
|
||||
|
||||
if (currCal == NULL)
|
||||
return;
|
||||
|
||||
if (ichan == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: invalid channel %u/0x%x; no mapping\n",
|
||||
__func__, chan->channel, chan->channelFlags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (currCal->calState != CAL_DONE) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: Calibration state incorrect, %d\n",
|
||||
__func__, currCal->calState);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
|
||||
return;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: Resetting Cal %d state for channel %u/0x%x\n",
|
||||
__func__, currCal->calData->calType, chan->channel,
|
||||
chan->channelFlags);
|
||||
|
||||
ichan->CalValid &= ~currCal->calData->calType;
|
||||
currCal->calState = CAL_WAITING;
|
||||
|
||||
*isCalDone = false;
|
||||
}
|
||||
|
||||
void ath9k_hw_start_nfcal(struct ath_hal *ah)
|
||||
{
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_ENABLE_NF);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
|
||||
}
|
||||
|
||||
void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath9k_nfcal_hist *h;
|
||||
int i, j;
|
||||
int32_t val;
|
||||
const u32 ar5416_cca_regs[6] = {
|
||||
AR_PHY_CCA,
|
||||
AR_PHY_CH1_CCA,
|
||||
AR_PHY_CH2_CCA,
|
||||
AR_PHY_EXT_CCA,
|
||||
AR_PHY_CH1_EXT_CCA,
|
||||
AR_PHY_CH2_EXT_CCA
|
||||
};
|
||||
u8 chainmask;
|
||||
|
||||
if (AR_SREV_9280(ah))
|
||||
chainmask = 0x1B;
|
||||
else
|
||||
chainmask = 0x3F;
|
||||
|
||||
#ifdef ATH_NF_PER_CHAN
|
||||
h = chan->nfCalHist;
|
||||
#else
|
||||
h = ah->nfCalHist;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
if (chainmask & (1 << i)) {
|
||||
val = REG_READ(ah, ar5416_cca_regs[i]);
|
||||
val &= 0xFFFFFE00;
|
||||
val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
|
||||
REG_WRITE(ah, ar5416_cca_regs[i], val);
|
||||
}
|
||||
}
|
||||
|
||||
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_ENABLE_NF);
|
||||
REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
|
||||
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
|
||||
|
||||
for (j = 0; j < 1000; j++) {
|
||||
if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
|
||||
AR_PHY_AGC_CONTROL_NF) == 0)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
if (chainmask & (1 << i)) {
|
||||
val = REG_READ(ah, ar5416_cca_regs[i]);
|
||||
val &= 0xFFFFFE00;
|
||||
val |= (((u32) (-50) << 1) & 0x1ff);
|
||||
REG_WRITE(ah, ar5416_cca_regs[i], val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t ath9k_hw_getnf(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
int16_t nf, nfThresh;
|
||||
int16_t nfarray[NUM_NF_READINGS] = { 0 };
|
||||
struct ath9k_nfcal_hist *h;
|
||||
u8 chainmask;
|
||||
|
||||
if (AR_SREV_9280(ah))
|
||||
chainmask = 0x1B;
|
||||
else
|
||||
chainmask = 0x3F;
|
||||
|
||||
chan->channelFlags &= (~CHANNEL_CW_INT);
|
||||
if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: NF did not complete in calibration window\n",
|
||||
__func__);
|
||||
nf = 0;
|
||||
chan->rawNoiseFloor = nf;
|
||||
return chan->rawNoiseFloor;
|
||||
} else {
|
||||
ath9k_hw_do_getnf(ah, nfarray);
|
||||
nf = nfarray[0];
|
||||
if (getNoiseFloorThresh(ah, chan, &nfThresh)
|
||||
&& nf > nfThresh) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: noise floor failed detected; "
|
||||
"detected %d, threshold %d\n", __func__,
|
||||
nf, nfThresh);
|
||||
chan->channelFlags |= CHANNEL_CW_INT;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ATH_NF_PER_CHAN
|
||||
h = chan->nfCalHist;
|
||||
#else
|
||||
h = ah->nfCalHist;
|
||||
#endif
|
||||
|
||||
ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
|
||||
chan->rawNoiseFloor = h[0].privNF;
|
||||
|
||||
return chan->rawNoiseFloor;
|
||||
}
|
||||
|
||||
void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
ah->nfCalHist[i].currIndex = 0;
|
||||
ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
|
||||
ah->nfCalHist[i].invalidNFcount =
|
||||
AR_PHY_CCA_FILTERWINDOW_LENGTH;
|
||||
for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
|
||||
ah->nfCalHist[i].nfCalBuffer[j] =
|
||||
AR_PHY_CCA_MAX_GOOD_VALUE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath9k_channel *ichan;
|
||||
s16 nf;
|
||||
|
||||
ichan = ath9k_regd_check_channel(ah, chan);
|
||||
if (ichan == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
|
||||
"%s: invalid channel %u/0x%x; no mapping\n",
|
||||
__func__, chan->channel, chan->channelFlags);
|
||||
return ATH_DEFAULT_NOISE_FLOOR;
|
||||
}
|
||||
if (ichan->rawNoiseFloor == 0) {
|
||||
enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
|
||||
nf = NOISE_FLOOR[mode];
|
||||
} else
|
||||
nf = ichan->rawNoiseFloor;
|
||||
|
||||
if (!ath9k_hw_nf_in_range(ah, nf))
|
||||
nf = ATH_DEFAULT_NOISE_FLOOR;
|
||||
|
||||
return nf;
|
||||
}
|
||||
|
||||
bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
u8 rxchainmask, bool longcal,
|
||||
bool *isCalDone)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
|
||||
struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
|
||||
|
||||
*isCalDone = true;
|
||||
|
||||
if (ichan == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
|
||||
"%s: invalid channel %u/0x%x; no mapping\n",
|
||||
__func__, chan->channel, chan->channelFlags);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currCal &&
|
||||
(currCal->calState == CAL_RUNNING ||
|
||||
currCal->calState == CAL_WAITING)) {
|
||||
ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
|
||||
isCalDone);
|
||||
if (*isCalDone) {
|
||||
ahp->ah_cal_list_curr = currCal = currCal->calNext;
|
||||
|
||||
if (currCal->calState == CAL_WAITING) {
|
||||
*isCalDone = false;
|
||||
ath9k_hw_reset_calibration(ah, currCal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (longcal) {
|
||||
ath9k_hw_getnf(ah, ichan);
|
||||
ath9k_hw_loadnf(ah, ah->ah_curchan);
|
||||
ath9k_hw_start_nfcal(ah);
|
||||
|
||||
if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
|
||||
chan->channelFlags |= CHANNEL_CW_INT;
|
||||
ichan->channelFlags &= ~CHANNEL_CW_INT;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
AR_PHY_AGC_CONTROL_CAL);
|
||||
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: offset calibration failed to complete in 1ms; "
|
||||
"noisy environment?\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
AR_PHY_AGC_CONTROL_NF);
|
||||
|
||||
ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
|
||||
|
||||
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
|
||||
if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
|
||||
INIT_CAL(&ahp->ah_adcGainCalData);
|
||||
INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: enabling ADC Gain Calibration.\n",
|
||||
__func__);
|
||||
}
|
||||
if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
|
||||
INIT_CAL(&ahp->ah_adcDcCalData);
|
||||
INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: enabling ADC DC Calibration.\n",
|
||||
__func__);
|
||||
}
|
||||
if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
|
||||
INIT_CAL(&ahp->ah_iqCalData);
|
||||
INSERT_CAL(ahp, &ahp->ah_iqCalData);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"%s: enabling IQ Calibration.\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
ahp->ah_cal_list_curr = ahp->ah_cal_list;
|
||||
|
||||
if (ahp->ah_cal_list_curr)
|
||||
ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
|
||||
}
|
||||
|
||||
ichan->CalValid = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const struct hal_percal_data iq_cal_multi_sample = {
|
||||
IQ_MISMATCH_CAL,
|
||||
MAX_CAL_SAMPLES,
|
||||
PER_MIN_LOG_COUNT,
|
||||
ath9k_hw_iqcal_collect,
|
||||
ath9k_hw_iqcalibrate
|
||||
};
|
||||
const struct hal_percal_data iq_cal_single_sample = {
|
||||
IQ_MISMATCH_CAL,
|
||||
MIN_CAL_SAMPLES,
|
||||
PER_MAX_LOG_COUNT,
|
||||
ath9k_hw_iqcal_collect,
|
||||
ath9k_hw_iqcalibrate
|
||||
};
|
||||
const struct hal_percal_data adc_gain_cal_multi_sample = {
|
||||
ADC_GAIN_CAL,
|
||||
MAX_CAL_SAMPLES,
|
||||
PER_MIN_LOG_COUNT,
|
||||
ath9k_hw_adc_gaincal_collect,
|
||||
ath9k_hw_adc_gaincal_calibrate
|
||||
};
|
||||
const struct hal_percal_data adc_gain_cal_single_sample = {
|
||||
ADC_GAIN_CAL,
|
||||
MIN_CAL_SAMPLES,
|
||||
PER_MAX_LOG_COUNT,
|
||||
ath9k_hw_adc_gaincal_collect,
|
||||
ath9k_hw_adc_gaincal_calibrate
|
||||
};
|
||||
const struct hal_percal_data adc_dc_cal_multi_sample = {
|
||||
ADC_DC_CAL,
|
||||
MAX_CAL_SAMPLES,
|
||||
PER_MIN_LOG_COUNT,
|
||||
ath9k_hw_adc_dccal_collect,
|
||||
ath9k_hw_adc_dccal_calibrate
|
||||
};
|
||||
const struct hal_percal_data adc_dc_cal_single_sample = {
|
||||
ADC_DC_CAL,
|
||||
MIN_CAL_SAMPLES,
|
||||
PER_MAX_LOG_COUNT,
|
||||
ath9k_hw_adc_dccal_collect,
|
||||
ath9k_hw_adc_dccal_calibrate
|
||||
};
|
||||
const struct hal_percal_data adc_init_dc_cal = {
|
||||
ADC_DC_INIT_CAL,
|
||||
MIN_CAL_SAMPLES,
|
||||
INIT_LOG_COUNT,
|
||||
ath9k_hw_adc_dccal_collect,
|
||||
ath9k_hw_adc_dccal_calibrate
|
||||
};
|
1605
drivers/net/wireless/ath9k/eeprom.c
Normal file
1605
drivers/net/wireless/ath9k/eeprom.c
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -923,7 +923,7 @@ struct ath_hal_5416 {
|
|||
#define OFDM_PLCP_BITS_QUARTER 22
|
||||
#define OFDM_SYMBOL_TIME_QUARTER 16
|
||||
|
||||
u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
|
||||
u32 ath9k_hw_get_eeprom(struct ath_hal *ah,
|
||||
enum eeprom_param param);
|
||||
|
||||
#endif
|
||||
|
|
1031
drivers/net/wireless/ath9k/mac.c
Normal file
1031
drivers/net/wireless/ath9k/mac.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -215,7 +215,7 @@ ath9k_hw_set_rf_regs(struct ath_hal *ah, struct ath9k_channel *chan,
|
|||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
return true;
|
||||
|
||||
eepMinorRev = ath9k_hw_get_eeprom(ahp, EEP_MINOR_REV);
|
||||
eepMinorRev = ath9k_hw_get_eeprom(ah, EEP_MINOR_REV);
|
||||
|
||||
RF_BANK_SETUP(ahp->ah_analogBank0Data, &ahp->ah_iniBank0, 1);
|
||||
|
||||
|
@ -235,15 +235,15 @@ ath9k_hw_set_rf_regs(struct ath_hal *ah, struct ath9k_channel *chan,
|
|||
|
||||
if (eepMinorRev >= 2) {
|
||||
if (IS_CHAN_2GHZ(chan)) {
|
||||
ob2GHz = ath9k_hw_get_eeprom(ahp, EEP_OB_2);
|
||||
db2GHz = ath9k_hw_get_eeprom(ahp, EEP_DB_2);
|
||||
ob2GHz = ath9k_hw_get_eeprom(ah, EEP_OB_2);
|
||||
db2GHz = ath9k_hw_get_eeprom(ah, EEP_DB_2);
|
||||
ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
|
||||
ob2GHz, 3, 197, 0);
|
||||
ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
|
||||
db2GHz, 3, 194, 0);
|
||||
} else {
|
||||
ob5GHz = ath9k_hw_get_eeprom(ahp, EEP_OB_5);
|
||||
db5GHz = ath9k_hw_get_eeprom(ahp, EEP_DB_5);
|
||||
ob5GHz = ath9k_hw_get_eeprom(ah, EEP_OB_5);
|
||||
db5GHz = ath9k_hw_get_eeprom(ah, EEP_DB_5);
|
||||
ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
|
||||
ob5GHz, 3, 203, 0);
|
||||
ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
|
||||
|
|
Loading…
Reference in a new issue