2010-04-15 17:38:14 -04:00
/*
2011-05-17 13:36:18 +05:30
* Copyright ( c ) 2008 - 2011 Atheros Communications Inc .
2010-04-15 17:38:14 -04:00
*
* 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 .
*/
/**
* DOC : Programming Atheros 802.11 n analog front end radios
*
* AR5416 MAC based PCI devices and AR518 MAC based PCI - Express
* devices have either an external AR2133 analog front end radio for single
* band 2.4 GHz communication or an AR5133 analog front end radio for dual
* band 2.4 GHz / 5 GHz communication .
*
* All devices after the AR5416 and AR5418 family starting with the AR9280
* have their analog front radios , MAC / BB and host PCIe / USB interface embedded
* into a single - chip and require less programming .
*
* The following single - chips exist with a respective embedded radio :
*
* AR9280 - 11 n dual - band 2 x2 MIMO for PCIe
* AR9281 - 11 n single - band 1 x2 MIMO for PCIe
* AR9285 - 11 n single - band 1 x1 for PCIe
* AR9287 - 11 n single - band 2 x2 MIMO for PCIe
*
* AR9220 - 11 n dual - band 2 x2 MIMO for PCI
* AR9223 - 11 n single - band 2 x2 MIMO for PCI
*
* AR9287 - 11 n single - band 1 x1 MIMO for USB
*/
# include "hw.h"
# include "ar9002_phy.h"
/**
* ar9002_hw_set_channel - set channel on single - chip device
* @ ah : atheros hardware structure
* @ chan :
*
* This is the function to change channel on single - chip devices , that is
* all devices after ar9280 .
*
* This function takes the channel value in MHz and sets
* hardware channel value . Assumes writes have been enabled to analog bus .
*
* Actual Expression ,
*
* For 2 GHz channel ,
* Channel Frequency = ( 3 / 4 ) * freq_ref * ( chansel [ 8 : 0 ] + chanfrac [ 16 : 0 ] / 2 ^ 17 )
* ( freq_ref = 40 MHz )
*
* For 5 GHz channel ,
* Channel Frequency = ( 3 / 2 ) * freq_ref * ( chansel [ 8 : 0 ] + chanfrac [ 16 : 0 ] / 2 ^ 10 )
* ( freq_ref = 40 MHz / ( 24 > > amodeRefSel ) )
*/
static int ar9002_hw_set_channel ( struct ath_hw * ah , struct ath9k_channel * chan )
{
u16 bMode , fracMode , aModeRefSel = 0 ;
u32 freq , ndiv , channelSel = 0 , channelFrac = 0 , reg32 = 0 ;
struct chan_centers centers ;
u32 refDivA = 24 ;
ath9k_hw_get_channel_centers ( ah , chan , & centers ) ;
freq = centers . synth_center ;
reg32 = REG_READ ( ah , AR_PHY_SYNTH_CONTROL ) ;
reg32 & = 0xc0000000 ;
if ( freq < 4800 ) { /* 2 GHz, fractional mode */
u32 txctl ;
int regWrites = 0 ;
bMode = 1 ;
fracMode = 1 ;
aModeRefSel = 0 ;
2010-04-15 17:38:32 -04:00
channelSel = CHANSEL_2G ( freq ) ;
2010-04-15 17:38:14 -04:00
if ( AR_SREV_9287_11_OR_LATER ( ah ) ) {
if ( freq = = 2484 ) {
/* Enable channel spreading for channel 14 */
REG_WRITE_ARRAY ( & ah - > iniCckfirJapan2484 ,
1 , regWrites ) ;
} else {
REG_WRITE_ARRAY ( & ah - > iniCckfirNormal ,
1 , regWrites ) ;
}
} else {
txctl = REG_READ ( ah , AR_PHY_CCK_TX_CTRL ) ;
if ( freq = = 2484 ) {
/* Enable channel spreading for channel 14 */
REG_WRITE ( ah , AR_PHY_CCK_TX_CTRL ,
txctl | AR_PHY_CCK_TX_CTRL_JAPAN ) ;
} else {
REG_WRITE ( ah , AR_PHY_CCK_TX_CTRL ,
txctl & ~ AR_PHY_CCK_TX_CTRL_JAPAN ) ;
}
}
} else {
bMode = 0 ;
fracMode = 0 ;
switch ( ah - > eep_ops - > get_eeprom ( ah , EEP_FRAC_N_5G ) ) {
case 0 :
2011-07-09 11:12:52 +07:00
if ( IS_CHAN_HALF_RATE ( chan ) | | IS_CHAN_QUARTER_RATE ( chan ) )
aModeRefSel = 0 ;
else if ( ( freq % 20 ) = = 0 )
2010-04-15 17:38:14 -04:00
aModeRefSel = 3 ;
else if ( ( freq % 10 ) = = 0 )
aModeRefSel = 2 ;
if ( aModeRefSel )
break ;
case 1 :
default :
aModeRefSel = 0 ;
/*
* Enable 2 G ( fractional ) mode for channels
* which are 5 MHz spaced .
*/
fracMode = 1 ;
refDivA = 1 ;
2010-04-15 17:38:32 -04:00
channelSel = CHANSEL_5G ( freq ) ;
2010-04-15 17:38:14 -04:00
/* RefDivA setting */
2011-07-09 11:12:54 +07:00
ath9k_hw_analog_shift_rmw ( ah , AR_AN_SYNTH9 ,
AR_AN_SYNTH9_REFDIVA ,
AR_AN_SYNTH9_REFDIVA_S , refDivA ) ;
2010-04-15 17:38:14 -04:00
}
if ( ! fracMode ) {
ndiv = ( freq * ( refDivA > > aModeRefSel ) ) / 60 ;
channelSel = ndiv & 0x1ff ;
channelFrac = ( ndiv & 0xfffffe00 ) * 2 ;
channelSel = ( channelSel < < 17 ) | channelFrac ;
}
}
reg32 = reg32 |
( bMode < < 29 ) |
( fracMode < < 28 ) | ( aModeRefSel < < 26 ) | ( channelSel ) ;
REG_WRITE ( ah , AR_PHY_SYNTH_CONTROL , reg32 ) ;
ah - > curchan = chan ;
return 0 ;
}
/**
* ar9002_hw_spur_mitigate - convert baseband spur frequency
* @ ah : atheros hardware structure
* @ chan :
*
* For single - chip solutions . Converts to baseband spur frequency given the
* input channel frequency and compute register settings below .
*/
static void ar9002_hw_spur_mitigate ( struct ath_hw * ah ,
struct ath9k_channel * chan )
{
int bb_spur = AR_NO_SPUR ;
int freq ;
2015-05-17 21:49:19 +02:00
int bin ;
2010-04-15 17:38:14 -04:00
int bb_spur_off , spur_subchannel_sd ;
int spur_freq_sd ;
int spur_delta_phase ;
int denominator ;
int tmp , newVal ;
int i ;
struct chan_centers centers ;
int8_t mask_m [ 123 ] ;
int8_t mask_p [ 123 ] ;
int cur_bb_spur ;
bool is2GHz = IS_CHAN_2GHZ ( chan ) ;
memset ( & mask_m , 0 , sizeof ( int8_t ) * 123 ) ;
memset ( & mask_p , 0 , sizeof ( int8_t ) * 123 ) ;
ath9k_hw_get_channel_centers ( ah , chan , & centers ) ;
freq = centers . synth_center ;
for ( i = 0 ; i < AR_EEPROM_MODAL_SPURS ; i + + ) {
cur_bb_spur = ah - > eep_ops - > get_spur_channel ( ah , i , is2GHz ) ;
2010-12-25 14:34:43 -05:00
if ( AR_NO_SPUR = = cur_bb_spur )
break ;
2010-04-15 17:38:14 -04:00
if ( is2GHz )
cur_bb_spur = ( cur_bb_spur / 10 ) + AR_BASE_FREQ_2GHZ ;
else
cur_bb_spur = ( cur_bb_spur / 10 ) + AR_BASE_FREQ_5GHZ ;
cur_bb_spur = cur_bb_spur - freq ;
if ( IS_CHAN_HT40 ( chan ) ) {
if ( ( cur_bb_spur > - AR_SPUR_FEEQ_BOUND_HT40 ) & &
( cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40 ) ) {
bb_spur = cur_bb_spur ;
break ;
}
} else if ( ( cur_bb_spur > - AR_SPUR_FEEQ_BOUND_HT20 ) & &
( cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20 ) ) {
bb_spur = cur_bb_spur ;
break ;
}
}
if ( AR_NO_SPUR = = bb_spur ) {
REG_CLR_BIT ( ah , AR_PHY_FORCE_CLKEN_CCK ,
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX ) ;
return ;
} else {
REG_CLR_BIT ( ah , AR_PHY_FORCE_CLKEN_CCK ,
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX ) ;
}
bin = bb_spur * 320 ;
tmp = REG_READ ( ah , AR_PHY_TIMING_CTRL4 ( 0 ) ) ;
2010-04-16 11:53:57 +05:30
ENABLE_REGWRITE_BUFFER ( ah ) ;
2010-04-15 17:38:14 -04:00
newVal = tmp | ( AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK ) ;
REG_WRITE ( ah , AR_PHY_TIMING_CTRL4 ( 0 ) , newVal ) ;
newVal = ( AR_PHY_SPUR_REG_MASK_RATE_CNTL |
AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
AR_PHY_SPUR_REG_MASK_RATE_SELECT |
AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
SM ( SPUR_RSSI_THRESH , AR_PHY_SPUR_REG_SPUR_RSSI_THRESH ) ) ;
REG_WRITE ( ah , AR_PHY_SPUR_REG , newVal ) ;
if ( IS_CHAN_HT40 ( chan ) ) {
if ( bb_spur < 0 ) {
spur_subchannel_sd = 1 ;
bb_spur_off = bb_spur + 10 ;
} else {
spur_subchannel_sd = 0 ;
bb_spur_off = bb_spur - 10 ;
}
} else {
spur_subchannel_sd = 0 ;
bb_spur_off = bb_spur ;
}
if ( IS_CHAN_HT40 ( chan ) )
spur_delta_phase =
( ( bb_spur * 262144 ) /
10 ) & AR_PHY_TIMING11_SPUR_DELTA_PHASE ;
else
spur_delta_phase =
( ( bb_spur * 524288 ) /
10 ) & AR_PHY_TIMING11_SPUR_DELTA_PHASE ;
denominator = IS_CHAN_2GHZ ( chan ) ? 44 : 40 ;
spur_freq_sd = ( ( bb_spur_off * 2048 ) / denominator ) & 0x3ff ;
newVal = ( AR_PHY_TIMING11_USE_SPUR_IN_AGC |
SM ( spur_freq_sd , AR_PHY_TIMING11_SPUR_FREQ_SD ) |
SM ( spur_delta_phase , AR_PHY_TIMING11_SPUR_DELTA_PHASE ) ) ;
REG_WRITE ( ah , AR_PHY_TIMING11 , newVal ) ;
newVal = spur_subchannel_sd < < AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S ;
REG_WRITE ( ah , AR_PHY_SFCORR_EXT , newVal ) ;
2015-05-17 21:49:19 +02:00
ar5008_hw_cmn_spur_mitigate ( ah , chan , bin ) ;
2010-04-16 11:53:57 +05:30
REGWRITE_BUFFER_FLUSH ( ah ) ;
2010-04-15 17:38:14 -04:00
}
static void ar9002_olc_init ( struct ath_hw * ah )
{
u32 i ;
if ( ! OLC_FOR_AR9280_20_LATER )
return ;
if ( OLC_FOR_AR9287_10_LATER ) {
REG_SET_BIT ( ah , AR_PHY_TX_PWRCTRL9 ,
AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL ) ;
ath9k_hw_analog_shift_rmw ( ah , AR9287_AN_TXPC0 ,
AR9287_AN_TXPC0_TXPCMODE ,
AR9287_AN_TXPC0_TXPCMODE_S ,
AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE ) ;
udelay ( 100 ) ;
} else {
for ( i = 0 ; i < AR9280_TX_GAIN_TABLE_SIZE ; i + + )
ah - > originalGain [ i ] =
MS ( REG_READ ( ah , AR_PHY_TX_GAIN_TBL1 + i * 4 ) ,
AR_PHY_TX_GAIN ) ;
ah - > PDADCdelta = 0 ;
}
}
2010-04-15 17:38:17 -04:00
static u32 ar9002_hw_compute_pll_control ( struct ath_hw * ah ,
struct ath9k_channel * chan )
{
2011-07-09 11:12:46 +07:00
int ref_div = 5 ;
int pll_div = 0x2c ;
2010-04-15 17:38:17 -04:00
u32 pll ;
2011-07-09 11:12:46 +07:00
if ( chan & & IS_CHAN_5GHZ ( chan ) & & ! IS_CHAN_A_FAST_CLOCK ( ah , chan ) ) {
if ( AR_SREV_9280_20 ( ah ) ) {
ref_div = 10 ;
pll_div = 0x50 ;
} else {
pll_div = 0x28 ;
}
}
pll = SM ( ref_div , AR_RTC_9160_PLL_REFDIV ) ;
pll | = SM ( pll_div , AR_RTC_9160_PLL_DIV ) ;
2010-04-15 17:38:17 -04:00
if ( chan & & IS_CHAN_HALF_RATE ( chan ) )
pll | = SM ( 0x1 , AR_RTC_9160_PLL_CLKSEL ) ;
else if ( chan & & IS_CHAN_QUARTER_RATE ( chan ) )
pll | = SM ( 0x2 , AR_RTC_9160_PLL_CLKSEL ) ;
return pll ;
}
2010-04-15 17:38:49 -04:00
static void ar9002_hw_do_getnf ( struct ath_hw * ah ,
int16_t nfarray [ NUM_NF_READINGS ] )
{
int16_t nf ;
nf = MS ( REG_READ ( ah , AR_PHY_CCA ) , AR9280_PHY_MINCCA_PWR ) ;
2010-08-30 19:04:01 +00:00
nfarray [ 0 ] = sign_extend32 ( nf , 8 ) ;
2010-04-15 17:38:49 -04:00
2010-07-02 00:09:51 +02:00
nf = MS ( REG_READ ( ah , AR_PHY_EXT_CCA ) , AR9280_PHY_EXT_MINCCA_PWR ) ;
2010-07-23 04:07:48 +02:00
if ( IS_CHAN_HT40 ( ah - > curchan ) )
2010-08-30 19:04:01 +00:00
nfarray [ 3 ] = sign_extend32 ( nf , 8 ) ;
2010-04-15 17:38:49 -04:00
2013-09-16 10:36:59 +05:30
if ( ! ( ah - > rxchainmask & BIT ( 1 ) ) )
2010-07-02 00:09:51 +02:00
return ;
2010-04-15 17:38:49 -04:00
2010-07-02 00:09:51 +02:00
nf = MS ( REG_READ ( ah , AR_PHY_CH1_CCA ) , AR9280_PHY_CH1_MINCCA_PWR ) ;
2010-08-30 19:04:01 +00:00
nfarray [ 1 ] = sign_extend32 ( nf , 8 ) ;
2010-04-15 17:38:49 -04:00
2010-07-02 00:09:51 +02:00
nf = MS ( REG_READ ( ah , AR_PHY_CH1_EXT_CCA ) , AR9280_PHY_CH1_EXT_MINCCA_PWR ) ;
2010-07-23 04:07:48 +02:00
if ( IS_CHAN_HT40 ( ah - > curchan ) )
2010-08-30 19:04:01 +00:00
nfarray [ 4 ] = sign_extend32 ( nf , 8 ) ;
2010-04-15 17:38:49 -04:00
}
2010-07-02 00:09:50 +02:00
static void ar9002_hw_set_nf_limits ( struct ath_hw * ah )
{
if ( AR_SREV_9285 ( ah ) ) {
ah - > nf_2g . max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ ;
ah - > nf_2g . min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ ;
ah - > nf_2g . nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ ;
} else if ( AR_SREV_9287 ( ah ) ) {
ah - > nf_2g . max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ ;
ah - > nf_2g . min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ ;
ah - > nf_2g . nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ ;
} else if ( AR_SREV_9271 ( ah ) ) {
ah - > nf_2g . max = AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ ;
ah - > nf_2g . min = AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ ;
ah - > nf_2g . nominal = AR_PHY_CCA_NOM_VAL_9271_2GHZ ;
} else {
ah - > nf_2g . max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ ;
ah - > nf_2g . min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ ;
ah - > nf_2g . nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ ;
ah - > nf_5g . max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ ;
ah - > nf_5g . min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ ;
ah - > nf_5g . nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ ;
}
}
2011-05-13 20:29:04 +05:30
static void ar9002_hw_antdiv_comb_conf_get ( struct ath_hw * ah ,
2010-09-02 01:34:42 -07:00
struct ath_hw_antcomb_conf * antconf )
{
u32 regval ;
regval = REG_READ ( ah , AR_PHY_MULTICHAIN_GAIN_CTL ) ;
antconf - > main_lna_conf = ( regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF ) > >
AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S ;
antconf - > alt_lna_conf = ( regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF ) > >
AR_PHY_9285_ANT_DIV_ALT_LNACONF_S ;
antconf - > fast_div_bias = ( regval & AR_PHY_9285_FAST_DIV_BIAS ) > >
AR_PHY_9285_FAST_DIV_BIAS_S ;
2013-09-02 13:59:03 +05:30
antconf - > lna1_lna2_switch_delta = - 1 ;
2011-05-13 20:30:56 +05:30
antconf - > lna1_lna2_delta = - 3 ;
antconf - > div_group = 0 ;
2010-09-02 01:34:42 -07:00
}
2011-05-13 20:29:04 +05:30
static void ar9002_hw_antdiv_comb_conf_set ( struct ath_hw * ah ,
2010-09-02 01:34:42 -07:00
struct ath_hw_antcomb_conf * antconf )
{
u32 regval ;
regval = REG_READ ( ah , AR_PHY_MULTICHAIN_GAIN_CTL ) ;
regval & = ~ ( AR_PHY_9285_ANT_DIV_MAIN_LNACONF |
AR_PHY_9285_ANT_DIV_ALT_LNACONF |
AR_PHY_9285_FAST_DIV_BIAS ) ;
regval | = ( ( antconf - > main_lna_conf < < AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S )
& AR_PHY_9285_ANT_DIV_MAIN_LNACONF ) ;
regval | = ( ( antconf - > alt_lna_conf < < AR_PHY_9285_ANT_DIV_ALT_LNACONF_S )
& AR_PHY_9285_ANT_DIV_ALT_LNACONF ) ;
regval | = ( ( antconf - > fast_div_bias < < AR_PHY_9285_FAST_DIV_BIAS_S )
& AR_PHY_9285_FAST_DIV_BIAS ) ;
REG_WRITE ( ah , AR_PHY_MULTICHAIN_GAIN_CTL , regval ) ;
}
2011-05-13 20:29:04 +05:30
2013-08-06 12:44:15 +05:30
# ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
2013-08-04 14:21:59 +05:30
static void ar9002_hw_set_bt_ant_diversity ( struct ath_hw * ah , bool enable )
{
struct ath_btcoex_hw * btcoex = & ah - > btcoex_hw ;
u8 antdiv_ctrl1 , antdiv_ctrl2 ;
u32 regval ;
if ( enable ) {
antdiv_ctrl1 = ATH_BT_COEX_ANTDIV_CONTROL1_ENABLE ;
antdiv_ctrl2 = ATH_BT_COEX_ANTDIV_CONTROL2_ENABLE ;
/*
* Don ' t disable BT ant to allow BB to control SWCOM .
*/
btcoex - > bt_coex_mode2 & = ( ~ ( AR_BT_DISABLE_BT_ANT ) ) ;
REG_WRITE ( ah , AR_BT_COEX_MODE2 , btcoex - > bt_coex_mode2 ) ;
REG_WRITE ( ah , AR_PHY_SWITCH_COM , ATH_BT_COEX_ANT_DIV_SWITCH_COM ) ;
REG_RMW ( ah , AR_PHY_SWITCH_CHAIN_0 , 0 , 0xf0000000 ) ;
} else {
/*
* Disable antenna diversity , use LNA1 only .
*/
antdiv_ctrl1 = ATH_BT_COEX_ANTDIV_CONTROL1_FIXED_A ;
antdiv_ctrl2 = ATH_BT_COEX_ANTDIV_CONTROL2_FIXED_A ;
/*
* Disable BT Ant . to allow concurrent BT and WLAN receive .
*/
btcoex - > bt_coex_mode2 | = AR_BT_DISABLE_BT_ANT ;
REG_WRITE ( ah , AR_BT_COEX_MODE2 , btcoex - > bt_coex_mode2 ) ;
/*
* Program SWCOM table to make sure RF switch always parks
* at BT side .
*/
REG_WRITE ( ah , AR_PHY_SWITCH_COM , 0 ) ;
REG_RMW ( ah , AR_PHY_SWITCH_CHAIN_0 , 0 , 0xf0000000 ) ;
}
regval = REG_READ ( ah , AR_PHY_MULTICHAIN_GAIN_CTL ) ;
regval & = ( ~ ( AR_PHY_9285_ANT_DIV_CTL_ALL ) ) ;
/*
* Clear ant_fast_div_bias [ 14 : 9 ] since for WB195 ,
* the main LNA is always LNA1 .
*/
regval & = ( ~ ( AR_PHY_9285_FAST_DIV_BIAS ) ) ;
regval | = SM ( antdiv_ctrl1 , AR_PHY_9285_ANT_DIV_CTL ) ;
regval | = SM ( antdiv_ctrl2 , AR_PHY_9285_ANT_DIV_ALT_LNACONF ) ;
regval | = SM ( ( antdiv_ctrl2 > > 2 ) , AR_PHY_9285_ANT_DIV_MAIN_LNACONF ) ;
regval | = SM ( ( antdiv_ctrl1 > > 1 ) , AR_PHY_9285_ANT_DIV_ALT_GAINTB ) ;
regval | = SM ( ( antdiv_ctrl1 > > 2 ) , AR_PHY_9285_ANT_DIV_MAIN_GAINTB ) ;
REG_WRITE ( ah , AR_PHY_MULTICHAIN_GAIN_CTL , regval ) ;
regval = REG_READ ( ah , AR_PHY_CCK_DETECT ) ;
regval & = ( ~ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV ) ;
regval | = SM ( ( antdiv_ctrl1 > > 3 ) , AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV ) ;
REG_WRITE ( ah , AR_PHY_CCK_DETECT , regval ) ;
}
2013-08-06 12:44:15 +05:30
# endif
2013-01-12 10:28:12 +08:00
static void ar9002_hw_spectral_scan_config ( struct ath_hw * ah ,
2013-01-08 14:48:58 +01:00
struct ath_spec_scan * param )
{
u8 count ;
if ( ! param - > enabled ) {
REG_CLR_BIT ( ah , AR_PHY_SPECTRAL_SCAN ,
AR_PHY_SPECTRAL_SCAN_ENABLE ) ;
return ;
}
REG_SET_BIT ( ah , AR_PHY_RADAR_0 , AR_PHY_RADAR_0_FFT_ENA ) ;
REG_SET_BIT ( ah , AR_PHY_SPECTRAL_SCAN , AR_PHY_SPECTRAL_SCAN_ENABLE ) ;
if ( param - > short_repeat )
REG_SET_BIT ( ah , AR_PHY_SPECTRAL_SCAN ,
AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT ) ;
else
REG_CLR_BIT ( ah , AR_PHY_SPECTRAL_SCAN ,
AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT ) ;
/* on AR92xx, the highest bit of count will make the the chip send
* spectral samples endlessly . Check if this really was intended ,
* and fix otherwise .
*/
count = param - > count ;
2014-11-06 08:53:31 +01:00
if ( param - > endless ) {
if ( AR_SREV_9271 ( ah ) )
count = 0 ;
else
count = 0x80 ;
} else if ( count & 0x80 )
2013-01-08 14:48:58 +01:00
count = 0x7f ;
REG_RMW_FIELD ( ah , AR_PHY_SPECTRAL_SCAN ,
AR_PHY_SPECTRAL_SCAN_COUNT , count ) ;
REG_RMW_FIELD ( ah , AR_PHY_SPECTRAL_SCAN ,
AR_PHY_SPECTRAL_SCAN_PERIOD , param - > period ) ;
REG_RMW_FIELD ( ah , AR_PHY_SPECTRAL_SCAN ,
AR_PHY_SPECTRAL_SCAN_FFT_PERIOD , param - > fft_period ) ;
return ;
}
static void ar9002_hw_spectral_scan_trigger ( struct ath_hw * ah )
{
REG_SET_BIT ( ah , AR_PHY_SPECTRAL_SCAN , AR_PHY_SPECTRAL_SCAN_ENABLE ) ;
/* Activate spectral scan */
REG_SET_BIT ( ah , AR_PHY_SPECTRAL_SCAN ,
AR_PHY_SPECTRAL_SCAN_ACTIVE ) ;
}
static void ar9002_hw_spectral_scan_wait ( struct ath_hw * ah )
{
struct ath_common * common = ath9k_hw_common ( ah ) ;
/* Poll for spectral scan complete */
if ( ! ath9k_hw_wait ( ah , AR_PHY_SPECTRAL_SCAN ,
AR_PHY_SPECTRAL_SCAN_ACTIVE ,
0 , AH_WAIT_TIMEOUT ) ) {
ath_err ( common , " spectral scan wait failed \n " ) ;
return ;
}
}
2013-10-14 17:42:11 -07:00
static void ar9002_hw_tx99_start ( struct ath_hw * ah , u32 qnum )
{
REG_SET_BIT ( ah , 0x9864 , 0x7f000 ) ;
REG_SET_BIT ( ah , 0x9924 , 0x7f00fe ) ;
REG_CLR_BIT ( ah , AR_DIAG_SW , AR_DIAG_RX_DIS ) ;
REG_WRITE ( ah , AR_CR , AR_CR_RXD ) ;
REG_WRITE ( ah , AR_DLCL_IFS ( qnum ) , 0 ) ;
REG_WRITE ( ah , AR_D_GBL_IFS_SIFS , 20 ) ;
REG_WRITE ( ah , AR_D_GBL_IFS_EIFS , 20 ) ;
REG_WRITE ( ah , AR_D_FPCTL , 0x10 | qnum ) ;
REG_WRITE ( ah , AR_TIME_OUT , 0x00000400 ) ;
REG_WRITE ( ah , AR_DRETRY_LIMIT ( qnum ) , 0xffffffff ) ;
REG_SET_BIT ( ah , AR_QMISC ( qnum ) , AR_Q_MISC_DCU_EARLY_TERM_REQ ) ;
}
static void ar9002_hw_tx99_stop ( struct ath_hw * ah )
{
REG_SET_BIT ( ah , AR_DIAG_SW , AR_DIAG_RX_DIS ) ;
}
2011-05-13 20:29:04 +05:30
void ar9002_hw_attach_phy_ops ( struct ath_hw * ah )
{
struct ath_hw_private_ops * priv_ops = ath9k_hw_private_ops ( ah ) ;
struct ath_hw_ops * ops = ath9k_hw_ops ( ah ) ;
priv_ops - > set_rf_regs = NULL ;
priv_ops - > rf_set_freq = ar9002_hw_set_channel ;
priv_ops - > spur_mitigate_freq = ar9002_hw_spur_mitigate ;
priv_ops - > olc_init = ar9002_olc_init ;
priv_ops - > compute_pll_control = ar9002_hw_compute_pll_control ;
priv_ops - > do_getnf = ar9002_hw_do_getnf ;
ops - > antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get ;
ops - > antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set ;
2013-01-08 14:48:58 +01:00
ops - > spectral_scan_config = ar9002_hw_spectral_scan_config ;
ops - > spectral_scan_trigger = ar9002_hw_spectral_scan_trigger ;
ops - > spectral_scan_wait = ar9002_hw_spectral_scan_wait ;
2011-05-13 20:29:04 +05:30
2013-08-06 12:44:15 +05:30
# ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
ops - > set_bt_ant_diversity = ar9002_hw_set_bt_ant_diversity ;
# endif
2013-10-14 17:42:11 -07:00
ops - > tx99_start = ar9002_hw_tx99_start ;
ops - > tx99_stop = ar9002_hw_tx99_stop ;
2013-08-06 12:44:15 +05:30
2011-05-13 20:29:04 +05:30
ar9002_hw_set_nf_limits ( ah ) ;
}