2009-08-07 09:45:15 +05:30
/*
* Copyright ( c ) 2008 - 2009 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 .
*/
2009-09-13 02:42:02 -07:00
# include "hw.h"
2010-04-15 17:38:14 -04:00
# include "ar9002_phy.h"
2009-08-07 09:45:15 +05:30
2010-06-01 15:14:04 +05:30
# define NUM_EEP_WORDS (sizeof(struct ar9287_eeprom) / sizeof(u16))
static int ath9k_hw_ar9287_get_eeprom_ver ( struct ath_hw * ah )
2009-08-07 09:45:15 +05:30
{
return ( ah - > eeprom . map9287 . baseEepHeader . version > > 12 ) & 0xF ;
}
2010-06-01 15:14:04 +05:30
static int ath9k_hw_ar9287_get_eeprom_rev ( struct ath_hw * ah )
2009-08-07 09:45:15 +05:30
{
return ( ah - > eeprom . map9287 . baseEepHeader . version ) & 0xFFF ;
}
2010-06-01 15:14:04 +05:30
static bool ath9k_hw_ar9287_fill_eeprom ( struct ath_hw * ah )
2009-08-07 09:45:15 +05:30
{
struct ar9287_eeprom * eep = & ah - > eeprom . map9287 ;
2009-09-13 02:42:02 -07:00
struct ath_common * common = ath9k_hw_common ( ah ) ;
2009-08-07 09:45:15 +05:30
u16 * eep_data ;
2010-08-13 18:36:40 +05:30
int addr , eep_start_loc ;
2009-08-07 09:45:15 +05:30
eep_data = ( u16 * ) eep ;
2010-11-19 16:53:21 +05:30
if ( ! common - > driver_info )
2010-08-13 18:36:40 +05:30
eep_start_loc = AR9287_EEP_START_LOC ;
2010-11-19 16:53:21 +05:30
else
eep_start_loc = AR9287_HTC_EEP_START_LOC ;
2010-08-13 18:36:40 +05:30
2009-08-07 09:45:15 +05:30
if ( ! ath9k_hw_use_flash ( ah ) ) {
2010-12-02 19:12:37 -08:00
ath_dbg ( common , ATH_DBG_EEPROM ,
" Reading from EEPROM, not flash \n " ) ;
2009-08-07 09:45:15 +05:30
}
2010-06-01 15:14:04 +05:30
for ( addr = 0 ; addr < NUM_EEP_WORDS ; addr + + ) {
if ( ! ath9k_hw_nvram_read ( common , addr + eep_start_loc ,
eep_data ) ) {
2010-12-02 19:12:37 -08:00
ath_dbg ( common , ATH_DBG_EEPROM ,
" Unable to read eeprom region \n " ) ;
2009-08-07 09:45:15 +05:30
return false ;
}
eep_data + + ;
}
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
return true ;
}
2010-06-01 15:14:04 +05:30
static int ath9k_hw_ar9287_check_eeprom ( struct ath_hw * ah )
2009-08-07 09:45:15 +05:30
{
u32 sum = 0 , el , integer ;
u16 temp , word , magic , magic2 , * eepdata ;
int i , addr ;
bool need_swap = false ;
struct ar9287_eeprom * eep = & ah - > eeprom . map9287 ;
2009-09-13 02:42:02 -07:00
struct ath_common * common = ath9k_hw_common ( ah ) ;
2009-08-07 09:45:15 +05:30
if ( ! ath9k_hw_use_flash ( ah ) ) {
2010-06-01 15:14:04 +05:30
if ( ! ath9k_hw_nvram_read ( common , AR5416_EEPROM_MAGIC_OFFSET ,
& magic ) ) {
2010-12-02 19:12:36 -08:00
ath_err ( common , " Reading Magic # failed \n " ) ;
2009-08-07 09:45:15 +05:30
return false ;
}
2010-12-02 19:12:37 -08:00
ath_dbg ( common , ATH_DBG_EEPROM ,
" Read Magic = 0x%04X \n " , magic ) ;
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
if ( magic ! = AR5416_EEPROM_MAGIC ) {
magic2 = swab16 ( magic ) ;
if ( magic2 = = AR5416_EEPROM_MAGIC ) {
need_swap = true ;
eepdata = ( u16 * ) ( & ah - > eeprom ) ;
2010-06-01 15:14:04 +05:30
for ( addr = 0 ; addr < NUM_EEP_WORDS ; addr + + ) {
2009-08-07 09:45:15 +05:30
temp = swab16 ( * eepdata ) ;
* eepdata = temp ;
eepdata + + ;
}
} else {
2010-12-02 19:12:36 -08:00
ath_err ( common ,
" Invalid EEPROM Magic. Endianness mismatch. \n " ) ;
2009-08-07 09:45:15 +05:30
return - EINVAL ;
}
}
}
2010-06-01 15:14:04 +05:30
2010-12-02 19:12:37 -08:00
ath_dbg ( common , ATH_DBG_EEPROM , " need_swap = %s. \n " ,
need_swap ? " True " : " False " ) ;
2009-08-07 09:45:15 +05:30
if ( need_swap )
el = swab16 ( ah - > eeprom . map9287 . baseEepHeader . length ) ;
else
el = ah - > eeprom . map9287 . baseEepHeader . length ;
if ( el > sizeof ( struct ar9287_eeprom ) )
el = sizeof ( struct ar9287_eeprom ) / sizeof ( u16 ) ;
else
el = el / sizeof ( u16 ) ;
eepdata = ( u16 * ) ( & ah - > eeprom ) ;
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
for ( i = 0 ; i < el ; i + + )
sum ^ = * eepdata + + ;
if ( need_swap ) {
word = swab16 ( eep - > baseEepHeader . length ) ;
eep - > baseEepHeader . length = word ;
word = swab16 ( eep - > baseEepHeader . checksum ) ;
eep - > baseEepHeader . checksum = word ;
word = swab16 ( eep - > baseEepHeader . version ) ;
eep - > baseEepHeader . version = word ;
word = swab16 ( eep - > baseEepHeader . regDmn [ 0 ] ) ;
eep - > baseEepHeader . regDmn [ 0 ] = word ;
word = swab16 ( eep - > baseEepHeader . regDmn [ 1 ] ) ;
eep - > baseEepHeader . regDmn [ 1 ] = word ;
word = swab16 ( eep - > baseEepHeader . rfSilent ) ;
eep - > baseEepHeader . rfSilent = word ;
word = swab16 ( eep - > baseEepHeader . blueToothOptions ) ;
eep - > baseEepHeader . blueToothOptions = word ;
word = swab16 ( eep - > baseEepHeader . deviceCap ) ;
eep - > baseEepHeader . deviceCap = word ;
integer = swab32 ( eep - > modalHeader . antCtrlCommon ) ;
eep - > modalHeader . antCtrlCommon = integer ;
for ( i = 0 ; i < AR9287_MAX_CHAINS ; i + + ) {
integer = swab32 ( eep - > modalHeader . antCtrlChain [ i ] ) ;
eep - > modalHeader . antCtrlChain [ i ] = integer ;
}
for ( i = 0 ; i < AR9287_EEPROM_MODAL_SPURS ; i + + ) {
word = swab16 ( eep - > modalHeader . spurChans [ i ] . spurChan ) ;
eep - > modalHeader . spurChans [ i ] . spurChan = word ;
}
}
if ( sum ! = 0xffff | | ah - > eep_ops - > get_eeprom_ver ( ah ) ! = AR9287_EEP_VER
| | ah - > eep_ops - > get_eeprom_rev ( ah ) < AR5416_EEP_NO_BACK_VER ) {
2010-12-02 19:12:36 -08:00
ath_err ( common , " Bad EEPROM checksum 0x%x or revision 0x%04x \n " ,
sum , ah - > eep_ops - > get_eeprom_ver ( ah ) ) ;
2009-08-07 09:45:15 +05:30
return - EINVAL ;
}
return 0 ;
}
2010-06-01 15:14:04 +05:30
static u32 ath9k_hw_ar9287_get_eeprom ( struct ath_hw * ah ,
2009-08-07 09:45:15 +05:30
enum eeprom_param param )
{
struct ar9287_eeprom * eep = & ah - > eeprom . map9287 ;
struct modal_eep_ar9287_header * pModal = & eep - > modalHeader ;
struct base_eep_ar9287_header * pBase = & eep - > baseEepHeader ;
u16 ver_minor ;
ver_minor = pBase - > version & AR9287_EEP_VER_MINOR_MASK ;
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
switch ( param ) {
case EEP_NFTHRESH_2 :
return pModal - > noiseFloorThreshCh [ 0 ] ;
2010-04-15 17:39:13 -04:00
case EEP_MAC_LSW :
2009-08-07 09:45:15 +05:30
return pBase - > macAddr [ 0 ] < < 8 | pBase - > macAddr [ 1 ] ;
2010-04-15 17:39:13 -04:00
case EEP_MAC_MID :
2009-08-07 09:45:15 +05:30
return pBase - > macAddr [ 2 ] < < 8 | pBase - > macAddr [ 3 ] ;
2010-04-15 17:39:13 -04:00
case EEP_MAC_MSW :
2009-08-07 09:45:15 +05:30
return pBase - > macAddr [ 4 ] < < 8 | pBase - > macAddr [ 5 ] ;
case EEP_REG_0 :
return pBase - > regDmn [ 0 ] ;
case EEP_REG_1 :
return pBase - > regDmn [ 1 ] ;
case EEP_OP_CAP :
return pBase - > deviceCap ;
case EEP_OP_MODE :
return pBase - > opCapFlags ;
case EEP_RF_SILENT :
return pBase - > rfSilent ;
case EEP_MINOR_REV :
return ver_minor ;
case EEP_TX_MASK :
return pBase - > txMask ;
case EEP_RX_MASK :
return pBase - > rxMask ;
case EEP_DEV_TYPE :
return pBase - > deviceType ;
case EEP_OL_PWRCTRL :
return pBase - > openLoopPwrCntl ;
case EEP_TEMPSENSE_SLOPE :
if ( ver_minor > = AR9287_EEP_MINOR_VER_2 )
return pBase - > tempSensSlope ;
else
return 0 ;
case EEP_TEMPSENSE_SLOPE_PAL_ON :
if ( ver_minor > = AR9287_EEP_MINOR_VER_3 )
return pBase - > tempSensSlopePalOn ;
else
return 0 ;
default :
return 0 ;
}
}
2010-06-01 15:14:04 +05:30
static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs ( struct ath_hw * ah ,
struct ath9k_channel * chan ,
struct cal_data_per_freq_ar9287 * pRawDataSet ,
u8 * bChans , u16 availPiers ,
u16 tPdGainOverlap ,
u16 * pPdGainBoundaries ,
u8 * pPDADCValues ,
u16 numXpdGains )
2009-08-07 09:45:15 +05:30
{
2010-06-01 15:14:04 +05:30
# define TMP_VAL_VPD_TABLE \
2009-08-07 09:45:15 +05:30
( ( vpdTableI [ i ] [ sizeCurrVpdTable - 1 ] + ( ss - maxIndex + 1 ) * vpdStep ) ) ;
2010-06-01 15:14:04 +05:30
int i , j , k ;
int16_t ss ;
u16 idxL = 0 , idxR = 0 , numPiers ;
u8 * pVpdL , * pVpdR , * pPwrL , * pPwrR ;
u8 minPwrT4 [ AR9287_NUM_PD_GAINS ] ;
u8 maxPwrT4 [ AR9287_NUM_PD_GAINS ] ;
int16_t vpdStep ;
int16_t tmpVal ;
u16 sizeCurrVpdTable , maxIndex , tgtIndex ;
bool match ;
int16_t minDelta = 0 ;
2009-08-07 09:45:15 +05:30
struct chan_centers centers ;
static u8 vpdTableL [ AR5416_EEP4K_NUM_PD_GAINS ]
[ AR5416_MAX_PWR_RANGE_IN_HALF_DB ] ;
static u8 vpdTableR [ AR5416_EEP4K_NUM_PD_GAINS ]
[ AR5416_MAX_PWR_RANGE_IN_HALF_DB ] ;
static u8 vpdTableI [ AR5416_EEP4K_NUM_PD_GAINS ]
[ AR5416_MAX_PWR_RANGE_IN_HALF_DB ] ;
2010-05-27 14:14:54 -04:00
memset ( & minPwrT4 , 0 , AR9287_NUM_PD_GAINS ) ;
2009-08-07 09:45:15 +05:30
ath9k_hw_get_channel_centers ( ah , chan , & centers ) ;
for ( numPiers = 0 ; numPiers < availPiers ; numPiers + + ) {
if ( bChans [ numPiers ] = = AR9287_BCHAN_UNUSED )
break ;
}
match = ath9k_hw_get_lower_upper_index (
2010-06-01 15:14:04 +05:30
( u8 ) FREQ2FBIN ( centers . synth_center , IS_CHAN_2GHZ ( chan ) ) ,
bChans , numPiers , & idxL , & idxR ) ;
2009-08-07 09:45:15 +05:30
if ( match ) {
for ( i = 0 ; i < numXpdGains ; i + + ) {
minPwrT4 [ i ] = pRawDataSet [ idxL ] . pwrPdg [ i ] [ 0 ] ;
maxPwrT4 [ i ] = pRawDataSet [ idxL ] . pwrPdg [ i ] [ 4 ] ;
ath9k_hw_fill_vpd_table ( minPwrT4 [ i ] , maxPwrT4 [ i ] ,
2010-06-01 15:14:04 +05:30
pRawDataSet [ idxL ] . pwrPdg [ i ] ,
pRawDataSet [ idxL ] . vpdPdg [ i ] ,
AR9287_PD_GAIN_ICEPTS ,
vpdTableI [ i ] ) ;
2009-08-07 09:45:15 +05:30
}
} else {
for ( i = 0 ; i < numXpdGains ; i + + ) {
pVpdL = pRawDataSet [ idxL ] . vpdPdg [ i ] ;
pPwrL = pRawDataSet [ idxL ] . pwrPdg [ i ] ;
pVpdR = pRawDataSet [ idxR ] . vpdPdg [ i ] ;
pPwrR = pRawDataSet [ idxR ] . pwrPdg [ i ] ;
minPwrT4 [ i ] = max ( pPwrL [ 0 ] , pPwrR [ 0 ] ) ;
2010-06-01 15:14:04 +05:30
maxPwrT4 [ i ] = min ( pPwrL [ AR9287_PD_GAIN_ICEPTS - 1 ] ,
pPwrR [ AR9287_PD_GAIN_ICEPTS - 1 ] ) ;
2009-08-07 09:45:15 +05:30
ath9k_hw_fill_vpd_table ( minPwrT4 [ i ] , maxPwrT4 [ i ] ,
2010-06-01 15:14:04 +05:30
pPwrL , pVpdL ,
AR9287_PD_GAIN_ICEPTS ,
vpdTableL [ i ] ) ;
2009-08-07 09:45:15 +05:30
ath9k_hw_fill_vpd_table ( minPwrT4 [ i ] , maxPwrT4 [ i ] ,
2010-06-01 15:14:04 +05:30
pPwrR , pVpdR ,
AR9287_PD_GAIN_ICEPTS ,
vpdTableR [ i ] ) ;
2009-08-07 09:45:15 +05:30
for ( j = 0 ; j < = ( maxPwrT4 [ i ] - minPwrT4 [ i ] ) / 2 ; j + + ) {
2010-06-01 15:14:04 +05:30
vpdTableI [ i ] [ j ] = ( u8 ) ( ath9k_hw_interpolate (
( u16 ) FREQ2FBIN ( centers . synth_center ,
IS_CHAN_2GHZ ( chan ) ) ,
bChans [ idxL ] , bChans [ idxR ] ,
vpdTableL [ i ] [ j ] , vpdTableR [ i ] [ j ] ) ) ;
2009-08-07 09:45:15 +05:30
}
}
}
k = 0 ;
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
for ( i = 0 ; i < numXpdGains ; i + + ) {
if ( i = = ( numXpdGains - 1 ) )
2010-06-01 15:14:04 +05:30
pPdGainBoundaries [ i ] =
( u16 ) ( maxPwrT4 [ i ] / 2 ) ;
2009-08-07 09:45:15 +05:30
else
2010-06-01 15:14:04 +05:30
pPdGainBoundaries [ i ] =
( u16 ) ( ( maxPwrT4 [ i ] + minPwrT4 [ i + 1 ] ) / 4 ) ;
2009-08-07 09:45:15 +05:30
pPdGainBoundaries [ i ] = min ( ( u16 ) AR5416_MAX_RATE_POWER ,
2010-06-01 15:14:04 +05:30
pPdGainBoundaries [ i ] ) ;
2009-08-07 09:45:15 +05:30
2010-06-01 15:14:07 +05:30
minDelta = 0 ;
2009-08-07 09:45:15 +05:30
if ( i = = 0 ) {
2010-09-22 12:34:52 +02:00
if ( AR_SREV_9280_20_OR_LATER ( ah ) )
2009-08-07 09:45:15 +05:30
ss = ( int16_t ) ( 0 - ( minPwrT4 [ i ] / 2 ) ) ;
else
ss = 0 ;
2010-06-01 15:14:07 +05:30
} else {
2009-08-07 09:45:15 +05:30
ss = ( int16_t ) ( ( pPdGainBoundaries [ i - 1 ] -
2010-06-01 15:14:04 +05:30
( minPwrT4 [ i ] / 2 ) ) -
2009-08-07 09:45:15 +05:30
tPdGainOverlap + 1 + minDelta ) ;
2010-06-01 15:14:07 +05:30
}
2009-08-07 09:45:15 +05:30
vpdStep = ( int16_t ) ( vpdTableI [ i ] [ 1 ] - vpdTableI [ i ] [ 0 ] ) ;
vpdStep = ( int16_t ) ( ( vpdStep < 1 ) ? 1 : vpdStep ) ;
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
while ( ( ss < 0 ) & & ( k < ( AR9287_NUM_PDADC_VALUES - 1 ) ) ) {
tmpVal = ( int16_t ) ( vpdTableI [ i ] [ 0 ] + ss * vpdStep ) ;
pPDADCValues [ k + + ] = ( u8 ) ( ( tmpVal < 0 ) ? 0 : tmpVal ) ;
ss + + ;
}
sizeCurrVpdTable = ( u8 ) ( ( maxPwrT4 [ i ] - minPwrT4 [ i ] ) / 2 + 1 ) ;
tgtIndex = ( u8 ) ( pPdGainBoundaries [ i ] +
tPdGainOverlap - ( minPwrT4 [ i ] / 2 ) ) ;
maxIndex = ( tgtIndex < sizeCurrVpdTable ) ?
tgtIndex : sizeCurrVpdTable ;
while ( ( ss < maxIndex ) & & ( k < ( AR9287_NUM_PDADC_VALUES - 1 ) ) )
pPDADCValues [ k + + ] = vpdTableI [ i ] [ ss + + ] ;
vpdStep = ( int16_t ) ( vpdTableI [ i ] [ sizeCurrVpdTable - 1 ] -
vpdTableI [ i ] [ sizeCurrVpdTable - 2 ] ) ;
vpdStep = ( int16_t ) ( ( vpdStep < 1 ) ? 1 : vpdStep ) ;
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
if ( tgtIndex > maxIndex ) {
while ( ( ss < = tgtIndex ) & &
( k < ( AR9287_NUM_PDADC_VALUES - 1 ) ) ) {
tmpVal = ( int16_t ) TMP_VAL_VPD_TABLE ;
2010-06-01 15:14:04 +05:30
pPDADCValues [ k + + ] =
( u8 ) ( ( tmpVal > 255 ) ? 255 : tmpVal ) ;
2009-08-07 09:45:15 +05:30
ss + + ;
}
}
}
while ( i < AR9287_PD_GAINS_IN_MASK ) {
pPdGainBoundaries [ i ] = pPdGainBoundaries [ i - 1 ] ;
i + + ;
}
while ( k < AR9287_NUM_PDADC_VALUES ) {
pPDADCValues [ k ] = pPDADCValues [ k - 1 ] ;
k + + ;
}
# undef TMP_VAL_VPD_TABLE
}
static void ar9287_eeprom_get_tx_gain_index ( struct ath_hw * ah ,
struct ath9k_channel * chan ,
struct cal_data_op_loop_ar9287 * pRawDatasetOpLoop ,
2010-06-01 15:14:04 +05:30
u8 * pCalChans , u16 availPiers , int8_t * pPwr )
2009-08-07 09:45:15 +05:30
{
2010-06-01 15:14:04 +05:30
u16 idxL = 0 , idxR = 0 , numPiers ;
2009-08-07 09:45:15 +05:30
bool match ;
struct chan_centers centers ;
ath9k_hw_get_channel_centers ( ah , chan , & centers ) ;
for ( numPiers = 0 ; numPiers < availPiers ; numPiers + + ) {
if ( pCalChans [ numPiers ] = = AR9287_BCHAN_UNUSED )
break ;
}
match = ath9k_hw_get_lower_upper_index (
2010-06-01 15:14:07 +05:30
( u8 ) FREQ2FBIN ( centers . synth_center , IS_CHAN_2GHZ ( chan ) ) ,
pCalChans , numPiers , & idxL , & idxR ) ;
2009-08-07 09:45:15 +05:30
if ( match ) {
2009-08-14 11:32:04 +05:30
* pPwr = ( int8_t ) pRawDatasetOpLoop [ idxL ] . pwrPdg [ 0 ] [ 0 ] ;
2009-08-07 09:45:15 +05:30
} else {
2009-08-14 11:32:04 +05:30
* pPwr = ( ( int8_t ) pRawDatasetOpLoop [ idxL ] . pwrPdg [ 0 ] [ 0 ] +
2010-06-01 15:14:04 +05:30
( int8_t ) pRawDatasetOpLoop [ idxR ] . pwrPdg [ 0 ] [ 0 ] ) / 2 ;
2009-08-07 09:45:15 +05:30
}
}
static void ar9287_eeprom_olpc_set_pdadcs ( struct ath_hw * ah ,
int32_t txPower , u16 chain )
{
u32 tmpVal ;
u32 a ;
2010-06-01 15:14:04 +05:30
/* Enable OLPC for chain 0 */
2009-08-07 09:45:15 +05:30
tmpVal = REG_READ ( ah , 0xa270 ) ;
tmpVal = tmpVal & 0xFCFFFFFF ;
tmpVal = tmpVal | ( 0x3 < < 24 ) ;
REG_WRITE ( ah , 0xa270 , tmpVal ) ;
2010-06-01 15:14:04 +05:30
/* Enable OLPC for chain 1 */
2009-08-07 09:45:15 +05:30
tmpVal = REG_READ ( ah , 0xb270 ) ;
tmpVal = tmpVal & 0xFCFFFFFF ;
tmpVal = tmpVal | ( 0x3 < < 24 ) ;
REG_WRITE ( ah , 0xb270 , tmpVal ) ;
2010-06-01 15:14:04 +05:30
/* Write the OLPC ref power for chain 0 */
2009-08-07 09:45:15 +05:30
if ( chain = = 0 ) {
tmpVal = REG_READ ( ah , 0xa398 ) ;
tmpVal = tmpVal & 0xff00ffff ;
a = ( txPower ) & 0xff ;
tmpVal = tmpVal | ( a < < 16 ) ;
REG_WRITE ( ah , 0xa398 , tmpVal ) ;
}
2010-06-01 15:14:04 +05:30
/* Write the OLPC ref power for chain 1 */
2009-08-07 09:45:15 +05:30
if ( chain = = 1 ) {
tmpVal = REG_READ ( ah , 0xb398 ) ;
tmpVal = tmpVal & 0xff00ffff ;
a = ( txPower ) & 0xff ;
tmpVal = tmpVal | ( a < < 16 ) ;
REG_WRITE ( ah , 0xb398 , tmpVal ) ;
}
}
2010-06-01 15:14:04 +05:30
static void ath9k_hw_set_ar9287_power_cal_table ( struct ath_hw * ah ,
2009-08-07 09:45:15 +05:30
struct ath9k_channel * chan ,
int16_t * pTxPowerIndexOffset )
{
struct cal_data_per_freq_ar9287 * pRawDataset ;
struct cal_data_op_loop_ar9287 * pRawDatasetOpenLoop ;
2010-06-01 15:14:04 +05:30
u8 * pCalBChans = NULL ;
2009-08-07 09:45:15 +05:30
u16 pdGainOverlap_t2 ;
2010-06-01 15:14:04 +05:30
u8 pdadcValues [ AR9287_NUM_PDADC_VALUES ] ;
2009-08-07 09:45:15 +05:30
u16 gainBoundaries [ AR9287_PD_GAINS_IN_MASK ] ;
u16 numPiers = 0 , i , j ;
u16 numXpdGain , xpdMask ;
u16 xpdGainValues [ AR9287_NUM_PD_GAINS ] = { 0 , 0 , 0 , 0 } ;
2010-06-01 15:14:07 +05:30
u32 reg32 , regOffset , regChainOffset , regval ;
2010-06-01 15:14:04 +05:30
int16_t modalIdx , diff = 0 ;
2009-08-07 09:45:15 +05:30
struct ar9287_eeprom * pEepData = & ah - > eeprom . map9287 ;
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
modalIdx = IS_CHAN_2GHZ ( chan ) ? 1 : 0 ;
xpdMask = pEepData - > modalHeader . xpdGain ;
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
if ( ( pEepData - > baseEepHeader . version & AR9287_EEP_VER_MINOR_MASK ) > =
2010-06-01 15:14:07 +05:30
AR9287_EEP_MINOR_VER_2 )
2009-08-07 09:45:15 +05:30
pdGainOverlap_t2 = pEepData - > modalHeader . pdGainOverlap ;
else
pdGainOverlap_t2 = ( u16 ) ( MS ( REG_READ ( ah , AR_PHY_TPCRG5 ) ,
AR_PHY_TPCRG5_PD_GAIN_OVERLAP ) ) ;
if ( IS_CHAN_2GHZ ( chan ) ) {
pCalBChans = pEepData - > calFreqPier2G ;
numPiers = AR9287_NUM_2G_CAL_PIERS ;
2010-06-01 15:14:04 +05:30
if ( ath9k_hw_ar9287_get_eeprom ( ah , EEP_OL_PWRCTRL ) ) {
2009-08-07 09:45:15 +05:30
pRawDatasetOpenLoop =
2010-06-01 15:14:07 +05:30
( struct cal_data_op_loop_ar9287 * ) pEepData - > calPierData2G [ 0 ] ;
2009-08-07 09:45:15 +05:30
ah - > initPDADC = pRawDatasetOpenLoop - > vpdPdg [ 0 ] [ 0 ] ;
}
}
numXpdGain = 0 ;
2010-06-01 15:14:04 +05:30
2010-06-01 15:14:07 +05:30
/* Calculate the value of xpdgains from the xpdGain Mask */
2009-08-07 09:45:15 +05:30
for ( i = 1 ; i < = AR9287_PD_GAINS_IN_MASK ; i + + ) {
if ( ( xpdMask > > ( AR9287_PD_GAINS_IN_MASK - i ) ) & 1 ) {
if ( numXpdGain > = AR9287_NUM_PD_GAINS )
break ;
xpdGainValues [ numXpdGain ] =
( u16 ) ( AR9287_PD_GAINS_IN_MASK - i ) ;
numXpdGain + + ;
}
}
REG_RMW_FIELD ( ah , AR_PHY_TPCRG1 , AR_PHY_TPCRG1_NUM_PD_GAIN ,
( numXpdGain - 1 ) & 0x3 ) ;
REG_RMW_FIELD ( ah , AR_PHY_TPCRG1 , AR_PHY_TPCRG1_PD_GAIN_1 ,
xpdGainValues [ 0 ] ) ;
REG_RMW_FIELD ( ah , AR_PHY_TPCRG1 , AR_PHY_TPCRG1_PD_GAIN_2 ,
xpdGainValues [ 1 ] ) ;
REG_RMW_FIELD ( ah , AR_PHY_TPCRG1 , AR_PHY_TPCRG1_PD_GAIN_3 ,
xpdGainValues [ 2 ] ) ;
for ( i = 0 ; i < AR9287_MAX_CHAINS ; i + + ) {
regChainOffset = i * 0x1000 ;
2010-06-01 15:14:07 +05:30
2009-08-07 09:45:15 +05:30
if ( pEepData - > baseEepHeader . txMask & ( 1 < < i ) ) {
2010-06-01 15:14:07 +05:30
pRawDatasetOpenLoop =
( struct cal_data_op_loop_ar9287 * ) pEepData - > calPierData2G [ i ] ;
2010-06-01 15:14:04 +05:30
if ( ath9k_hw_ar9287_get_eeprom ( ah , EEP_OL_PWRCTRL ) ) {
2009-08-07 09:45:15 +05:30
int8_t txPower ;
ar9287_eeprom_get_tx_gain_index ( ah , chan ,
2010-06-01 15:14:07 +05:30
pRawDatasetOpenLoop ,
pCalBChans , numPiers ,
& txPower ) ;
2009-08-07 09:45:15 +05:30
ar9287_eeprom_olpc_set_pdadcs ( ah , txPower , i ) ;
} else {
pRawDataset =
( struct cal_data_per_freq_ar9287 * )
pEepData - > calPierData2G [ i ] ;
2010-06-01 15:14:07 +05:30
ath9k_hw_get_ar9287_gain_boundaries_pdadcs ( ah , chan ,
pRawDataset ,
pCalBChans , numPiers ,
pdGainOverlap_t2 ,
gainBoundaries ,
pdadcValues ,
numXpdGain ) ;
2009-08-07 09:45:15 +05:30
}
if ( i = = 0 ) {
2010-06-01 15:14:07 +05:30
if ( ! ath9k_hw_ar9287_get_eeprom ( ah ,
EEP_OL_PWRCTRL ) ) {
regval = SM ( pdGainOverlap_t2 ,
AR_PHY_TPCRG5_PD_GAIN_OVERLAP )
| SM ( gainBoundaries [ 0 ] ,
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 )
| SM ( gainBoundaries [ 1 ] ,
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 )
| SM ( gainBoundaries [ 2 ] ,
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 )
| SM ( gainBoundaries [ 3 ] ,
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 ) ;
REG_WRITE ( ah ,
AR_PHY_TPCRG5 + regChainOffset ,
regval ) ;
2009-08-07 09:45:15 +05:30
}
}
if ( ( int32_t ) AR9287_PWR_TABLE_OFFSET_DB ! =
2010-06-01 15:14:07 +05:30
pEepData - > baseEepHeader . pwrTableOffset ) {
diff = ( u16 ) ( pEepData - > baseEepHeader . pwrTableOffset -
( int32_t ) AR9287_PWR_TABLE_OFFSET_DB ) ;
2009-08-07 09:45:15 +05:30
diff * = 2 ;
2010-06-01 15:14:07 +05:30
for ( j = 0 ; j < ( ( u16 ) AR9287_NUM_PDADC_VALUES - diff ) ; j + + )
2009-08-07 09:45:15 +05:30
pdadcValues [ j ] = pdadcValues [ j + diff ] ;
for ( j = ( u16 ) ( AR9287_NUM_PDADC_VALUES - diff ) ;
j < AR9287_NUM_PDADC_VALUES ; j + + )
pdadcValues [ j ] =
2010-06-01 15:14:07 +05:30
pdadcValues [ AR9287_NUM_PDADC_VALUES - diff ] ;
2009-08-07 09:45:15 +05:30
}
2010-06-01 15:14:04 +05:30
if ( ! ath9k_hw_ar9287_get_eeprom ( ah , EEP_OL_PWRCTRL ) ) {
2010-06-01 15:14:07 +05:30
regOffset = AR_PHY_BASE +
( 672 < < 2 ) + regChainOffset ;
2009-08-07 09:45:15 +05:30
for ( j = 0 ; j < 32 ; j + + ) {
2010-06-01 15:14:07 +05:30
reg32 = ( ( pdadcValues [ 4 * j + 0 ] & 0xFF ) < < 0 )
| ( ( pdadcValues [ 4 * j + 1 ] & 0xFF ) < < 8 )
| ( ( pdadcValues [ 4 * j + 2 ] & 0xFF ) < < 16 )
| ( ( pdadcValues [ 4 * j + 3 ] & 0xFF ) < < 24 ) ;
2009-08-07 09:45:15 +05:30
REG_WRITE ( ah , regOffset , reg32 ) ;
regOffset + = 4 ;
}
}
}
}
* pTxPowerIndexOffset = 0 ;
}
2010-06-01 15:14:04 +05:30
static void ath9k_hw_set_ar9287_power_per_rate_table ( struct ath_hw * ah ,
struct ath9k_channel * chan ,
int16_t * ratesArray ,
u16 cfgCtl ,
u16 AntennaReduction ,
u16 twiceMaxRegulatoryPower ,
u16 powerLimit )
2009-08-07 09:45:15 +05:30
{
2010-06-01 15:14:07 +05:30
# define CMP_CTL \
( ( ( cfgCtl & ~ CTL_MODE_M ) | ( pCtlMode [ ctlMode ] & CTL_MODE_M ) ) = = \
pEepData - > ctlIndex [ i ] )
# define CMP_NO_CTL \
( ( ( cfgCtl & ~ CTL_MODE_M ) | ( pCtlMode [ ctlMode ] & CTL_MODE_M ) ) = = \
( ( pEepData - > ctlIndex [ i ] & CTL_MODE_M ) | SD_NO_CTL ) )
2009-08-07 09:45:15 +05:30
# define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
# define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
2010-06-01 15:14:04 +05:30
2009-08-17 18:07:23 -07:00
struct ath_regulatory * regulatory = ath9k_hw_regulatory ( ah ) ;
2009-08-07 09:45:15 +05:30
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER ;
static const u16 tpScaleReductionTable [ 5 ] =
{ 0 , 3 , 6 , 9 , AR5416_MAX_RATE_POWER } ;
int i ;
2010-06-01 15:14:04 +05:30
int16_t twiceLargestAntenna ;
2009-08-07 09:45:15 +05:30
struct cal_ctl_data_ar9287 * rep ;
struct cal_target_power_leg targetPowerOfdm = { 0 , { 0 , 0 , 0 , 0 } } ,
targetPowerCck = { 0 , { 0 , 0 , 0 , 0 } } ;
struct cal_target_power_leg targetPowerOfdmExt = { 0 , { 0 , 0 , 0 , 0 } } ,
targetPowerCckExt = { 0 , { 0 , 0 , 0 , 0 } } ;
2010-06-01 15:14:04 +05:30
struct cal_target_power_ht targetPowerHt20 ,
2009-08-07 09:45:15 +05:30
targetPowerHt40 = { 0 , { 0 , 0 , 0 , 0 } } ;
u16 scaledPower = 0 , minCtlPower , maxRegAllowedPower ;
2010-11-20 18:38:53 -08:00
static const u16 ctlModesFor11g [ ] = {
CTL_11B , CTL_11G , CTL_2GHT20 ,
CTL_11B_EXT , CTL_11G_EXT , CTL_2GHT40
} ;
u16 numCtlModes = 0 ;
const u16 * pCtlMode = NULL ;
u16 ctlMode , freq ;
2009-08-07 09:45:15 +05:30
struct chan_centers centers ;
int tx_chainmask ;
u16 twiceMinEdgePower ;
struct ar9287_eeprom * pEepData = & ah - > eeprom . map9287 ;
tx_chainmask = ah - > txchainmask ;
ath9k_hw_get_channel_centers ( ah , chan , & centers ) ;
2010-06-01 15:14:07 +05:30
/* Compute TxPower reduction due to Antenna Gain */
2009-08-07 09:45:15 +05:30
twiceLargestAntenna = max ( pEepData - > modalHeader . antennaGainCh [ 0 ] ,
pEepData - > modalHeader . antennaGainCh [ 1 ] ) ;
2010-06-01 15:14:04 +05:30
twiceLargestAntenna = ( int16_t ) min ( ( AntennaReduction ) -
twiceLargestAntenna , 0 ) ;
2009-08-07 09:45:15 +05:30
2010-06-01 15:14:07 +05:30
/*
* scaledPower is the minimum of the user input power level
* and the regulatory allowed power level .
*/
2009-08-07 09:45:15 +05:30
maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna ;
2010-06-01 15:14:07 +05:30
2009-08-17 18:07:23 -07:00
if ( regulatory - > tp_scale ! = ATH9K_TP_SCALE_MAX )
2009-08-07 09:45:15 +05:30
maxRegAllowedPower - =
2009-08-17 18:07:23 -07:00
( tpScaleReductionTable [ ( regulatory - > tp_scale ) ] * 2 ) ;
2009-08-07 09:45:15 +05:30
scaledPower = min ( powerLimit , maxRegAllowedPower ) ;
2010-06-01 15:14:07 +05:30
/*
* Reduce scaled Power by number of chains active
* to get the per chain tx power level .
*/
2009-08-07 09:45:15 +05:30
switch ( ar5416_get_ntxchains ( tx_chainmask ) ) {
case 1 :
break ;
case 2 :
scaledPower - = REDUCE_SCALED_POWER_BY_TWO_CHAIN ;
break ;
case 3 :
scaledPower - = REDUCE_SCALED_POWER_BY_THREE_CHAIN ;
break ;
}
scaledPower = max ( ( u16 ) 0 , scaledPower ) ;
2010-06-01 15:14:07 +05:30
/*
* Get TX power from EEPROM .
*/
2009-08-07 09:45:15 +05:30
if ( IS_CHAN_2GHZ ( chan ) ) {
2010-06-01 15:14:07 +05:30
/* CTL_11B, CTL_11G, CTL_2GHT20 */
2009-08-07 09:45:15 +05:30
numCtlModes =
ARRAY_SIZE ( ctlModesFor11g ) - SUB_NUM_CTL_MODES_AT_2G_40 ;
2010-06-01 15:14:04 +05:30
2009-08-07 09:45:15 +05:30
pCtlMode = ctlModesFor11g ;
ath9k_hw_get_legacy_target_powers ( ah , chan ,
pEepData - > calTargetPowerCck ,
AR9287_NUM_2G_CCK_TARGET_POWERS ,
& targetPowerCck , 4 , false ) ;
ath9k_hw_get_legacy_target_powers ( ah , chan ,
pEepData - > calTargetPower2G ,
AR9287_NUM_2G_20_TARGET_POWERS ,
& targetPowerOfdm , 4 , false ) ;
ath9k_hw_get_target_powers ( ah , chan ,
pEepData - > calTargetPower2GHT20 ,
AR9287_NUM_2G_20_TARGET_POWERS ,
& targetPowerHt20 , 8 , false ) ;
if ( IS_CHAN_HT40 ( chan ) ) {
2010-06-01 15:14:07 +05:30
/* All 2G CTLs */
2009-08-07 09:45:15 +05:30
numCtlModes = ARRAY_SIZE ( ctlModesFor11g ) ;
ath9k_hw_get_target_powers ( ah , chan ,
pEepData - > calTargetPower2GHT40 ,
AR9287_NUM_2G_40_TARGET_POWERS ,
& targetPowerHt40 , 8 , true ) ;
ath9k_hw_get_legacy_target_powers ( ah , chan ,
pEepData - > calTargetPowerCck ,
AR9287_NUM_2G_CCK_TARGET_POWERS ,
& targetPowerCckExt , 4 , true ) ;
ath9k_hw_get_legacy_target_powers ( ah , chan ,
pEepData - > calTargetPower2G ,
AR9287_NUM_2G_20_TARGET_POWERS ,
& targetPowerOfdmExt , 4 , true ) ;
}
}
for ( ctlMode = 0 ; ctlMode < numCtlModes ; ctlMode + + ) {
2010-06-01 15:14:07 +05:30
bool isHt40CtlMode =
( pCtlMode [ ctlMode ] = = CTL_2GHT40 ) ? true : false ;
2009-08-07 09:45:15 +05:30
if ( isHt40CtlMode )
freq = centers . synth_center ;
else if ( pCtlMode [ ctlMode ] & EXT_ADDITIVE )
freq = centers . ext_center ;
else
freq = centers . ctl_center ;
2010-06-01 15:14:07 +05:30
/* Walk through the CTL indices stored in EEPROM */
2009-08-07 09:45:15 +05:30
for ( i = 0 ; ( i < AR9287_NUM_CTLS ) & & pEepData - > ctlIndex [ i ] ; i + + ) {
2010-06-01 15:14:07 +05:30
struct cal_ctl_edges * pRdEdgesPower ;
2009-08-07 09:45:15 +05:30
2010-06-01 15:14:07 +05:30
/*
* Compare test group from regulatory channel list
* with test mode from pCtlMode list
*/
if ( CMP_CTL | | CMP_NO_CTL ) {
2009-08-07 09:45:15 +05:30
rep = & ( pEepData - > ctlData [ i ] ) ;
2010-06-01 15:14:07 +05:30
pRdEdgesPower =
rep - > ctlEdges [ ar5416_get_ntxchains ( tx_chainmask ) - 1 ] ;
twiceMinEdgePower = ath9k_hw_get_max_edge_power ( freq ,
pRdEdgesPower ,
IS_CHAN_2GHZ ( chan ) ,
AR5416_NUM_BAND_EDGES ) ;
if ( ( cfgCtl & ~ CTL_MODE_M ) = = SD_NO_CTL ) {
twiceMaxEdgePower = min ( twiceMaxEdgePower ,
twiceMinEdgePower ) ;
} else {
2009-08-07 09:45:15 +05:30
twiceMaxEdgePower = twiceMinEdgePower ;
break ;
}
}
}
minCtlPower = ( u8 ) min ( twiceMaxEdgePower , scaledPower ) ;
2010-06-01 15:14:07 +05:30
/* Apply ctl mode to correct target power set */
2009-08-07 09:45:15 +05:30
switch ( pCtlMode [ ctlMode ] ) {
case CTL_11B :
2010-06-01 15:14:07 +05:30
for ( i = 0 ; i < ARRAY_SIZE ( targetPowerCck . tPow2x ) ; i + + ) {
targetPowerCck . tPow2x [ i ] =
( u8 ) min ( ( u16 ) targetPowerCck . tPow2x [ i ] ,
minCtlPower ) ;
2009-08-07 09:45:15 +05:30
}
break ;
case CTL_11A :
case CTL_11G :
2010-06-01 15:14:07 +05:30
for ( i = 0 ; i < ARRAY_SIZE ( targetPowerOfdm . tPow2x ) ; i + + ) {
targetPowerOfdm . tPow2x [ i ] =
( u8 ) min ( ( u16 ) targetPowerOfdm . tPow2x [ i ] ,
minCtlPower ) ;
2009-08-07 09:45:15 +05:30
}
break ;
case CTL_5GHT20 :
case CTL_2GHT20 :
2010-06-01 15:14:07 +05:30
for ( i = 0 ; i < ARRAY_SIZE ( targetPowerHt20 . tPow2x ) ; i + + ) {
targetPowerHt20 . tPow2x [ i ] =
( u8 ) min ( ( u16 ) targetPowerHt20 . tPow2x [ i ] ,
minCtlPower ) ;
2009-08-07 09:45:15 +05:30
}
break ;
case CTL_11B_EXT :
2010-06-01 15:14:07 +05:30
targetPowerCckExt . tPow2x [ 0 ] =
( u8 ) min ( ( u16 ) targetPowerCckExt . tPow2x [ 0 ] ,
minCtlPower ) ;
2009-08-07 09:45:15 +05:30
break ;
case CTL_11A_EXT :
case CTL_11G_EXT :
2010-06-01 15:14:07 +05:30
targetPowerOfdmExt . tPow2x [ 0 ] =
( u8 ) min ( ( u16 ) targetPowerOfdmExt . tPow2x [ 0 ] ,
minCtlPower ) ;
2009-08-07 09:45:15 +05:30
break ;
case CTL_5GHT40 :
case CTL_2GHT40 :
2010-06-01 15:14:07 +05:30
for ( i = 0 ; i < ARRAY_SIZE ( targetPowerHt40 . tPow2x ) ; i + + ) {
targetPowerHt40 . tPow2x [ i ] =
( u8 ) min ( ( u16 ) targetPowerHt40 . tPow2x [ i ] ,
minCtlPower ) ;
2009-08-07 09:45:15 +05:30
}
break ;
default :
break ;
}
}
2010-06-01 15:14:07 +05:30
/* Now set the rates array */
2009-08-07 09:45:15 +05:30
ratesArray [ rate6mb ] =
ratesArray [ rate9mb ] =
ratesArray [ rate12mb ] =
ratesArray [ rate18mb ] =
2010-06-01 15:14:07 +05:30
ratesArray [ rate24mb ] = targetPowerOfdm . tPow2x [ 0 ] ;
2009-08-07 09:45:15 +05:30
ratesArray [ rate36mb ] = targetPowerOfdm . tPow2x [ 1 ] ;
ratesArray [ rate48mb ] = targetPowerOfdm . tPow2x [ 2 ] ;
ratesArray [ rate54mb ] = targetPowerOfdm . tPow2x [ 3 ] ;
ratesArray [ rateXr ] = targetPowerOfdm . tPow2x [ 0 ] ;
for ( i = 0 ; i < ARRAY_SIZE ( targetPowerHt20 . tPow2x ) ; i + + )
ratesArray [ rateHt20_0 + i ] = targetPowerHt20 . tPow2x [ i ] ;
if ( IS_CHAN_2GHZ ( chan ) ) {
ratesArray [ rate1l ] = targetPowerCck . tPow2x [ 0 ] ;
2010-06-01 15:14:07 +05:30
ratesArray [ rate2s ] =
ratesArray [ rate2l ] = targetPowerCck . tPow2x [ 1 ] ;
ratesArray [ rate5_5s ] =
ratesArray [ rate5_5l ] = targetPowerCck . tPow2x [ 2 ] ;
ratesArray [ rate11s ] =
ratesArray [ rate11l ] = targetPowerCck . tPow2x [ 3 ] ;
2009-08-07 09:45:15 +05:30
}
if ( IS_CHAN_HT40 ( chan ) ) {
for ( i = 0 ; i < ARRAY_SIZE ( targetPowerHt40 . tPow2x ) ; i + + )
ratesArray [ rateHt40_0 + i ] = targetPowerHt40 . tPow2x [ i ] ;
ratesArray [ rateDupOfdm ] = targetPowerHt40 . tPow2x [ 0 ] ;
ratesArray [ rateDupCck ] = targetPowerHt40 . tPow2x [ 0 ] ;
ratesArray [ rateExtOfdm ] = targetPowerOfdmExt . tPow2x [ 0 ] ;
2010-06-01 15:14:07 +05:30
2009-08-07 09:45:15 +05:30
if ( IS_CHAN_2GHZ ( chan ) )
ratesArray [ rateExtCck ] = targetPowerCckExt . tPow2x [ 0 ] ;
}
2010-06-01 15:14:07 +05:30
# undef CMP_CTL
# undef CMP_NO_CTL
2009-08-07 09:45:15 +05:30
# undef REDUCE_SCALED_POWER_BY_TWO_CHAIN
# undef REDUCE_SCALED_POWER_BY_THREE_CHAIN
}
2010-06-01 15:14:04 +05:30
static void ath9k_hw_ar9287_set_txpower ( struct ath_hw * ah ,
2009-08-07 09:45:15 +05:30
struct ath9k_channel * chan , u16 cfgCtl ,
u8 twiceAntennaReduction ,
u8 twiceMaxRegulatoryPower ,
2010-10-20 03:08:53 +02:00
u8 powerLimit , bool test )
2009-08-07 09:45:15 +05:30
{
2009-08-17 18:07:23 -07:00
struct ath_regulatory * regulatory = ath9k_hw_regulatory ( ah ) ;
2009-08-07 09:45:15 +05:30
struct ar9287_eeprom * pEepData = & ah - > eeprom . map9287 ;
struct modal_eep_ar9287_header * pModal = & pEepData - > modalHeader ;
int16_t ratesArray [ Ar5416RateSize ] ;
2010-06-01 15:14:04 +05:30
int16_t txPowerIndexOffset = 0 ;
2009-08-07 09:45:15 +05:30
u8 ht40PowerIncForPdadc = 2 ;
int i ;
memset ( ratesArray , 0 , sizeof ( ratesArray ) ) ;
if ( ( pEepData - > baseEepHeader . version & AR9287_EEP_VER_MINOR_MASK ) > =
AR9287_EEP_MINOR_VER_2 )
ht40PowerIncForPdadc = pModal - > ht40PowerIncForPdadc ;
2010-06-01 15:14:04 +05:30
ath9k_hw_set_ar9287_power_per_rate_table ( ah , chan ,
2009-08-07 09:45:15 +05:30
& ratesArray [ 0 ] , cfgCtl ,
twiceAntennaReduction ,
twiceMaxRegulatoryPower ,
powerLimit ) ;
2010-06-01 15:14:04 +05:30
ath9k_hw_set_ar9287_power_cal_table ( ah , chan , & txPowerIndexOffset ) ;
2009-08-07 09:45:15 +05:30
2010-10-20 03:08:53 +02:00
regulatory - > max_power_level = 0 ;
2009-08-07 09:45:15 +05:30
for ( i = 0 ; i < ARRAY_SIZE ( ratesArray ) ; i + + ) {
ratesArray [ i ] = ( int16_t ) ( txPowerIndexOffset + ratesArray [ i ] ) ;
if ( ratesArray [ i ] > AR9287_MAX_RATE_POWER )
ratesArray [ i ] = AR9287_MAX_RATE_POWER ;
2010-10-20 03:08:53 +02:00
if ( ratesArray [ i ] > regulatory - > max_power_level )
regulatory - > max_power_level = ratesArray [ i ] ;
2009-08-07 09:45:15 +05:30
}
2010-10-20 03:08:53 +02:00
if ( test )
return ;
if ( IS_CHAN_2GHZ ( chan ) )
i = rate1l ;
else
i = rate6mb ;
regulatory - > max_power_level = ratesArray [ i ] ;
2010-09-22 12:34:52 +02:00
if ( AR_SREV_9280_20_OR_LATER ( ah ) ) {
2009-08-07 09:45:15 +05:30
for ( i = 0 ; i < Ar5416RateSize ; i + + )
ratesArray [ i ] - = AR9287_PWR_TABLE_OFFSET_DB * 2 ;
}
2010-06-01 15:14:07 +05:30
/* OFDM power per rate */
2009-08-07 09:45:15 +05:30
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE1 ,
ATH9K_POW_SM ( ratesArray [ rate18mb ] , 24 )
| ATH9K_POW_SM ( ratesArray [ rate12mb ] , 16 )
| ATH9K_POW_SM ( ratesArray [ rate9mb ] , 8 )
| ATH9K_POW_SM ( ratesArray [ rate6mb ] , 0 ) ) ;
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE2 ,
ATH9K_POW_SM ( ratesArray [ rate54mb ] , 24 )
| ATH9K_POW_SM ( ratesArray [ rate48mb ] , 16 )
| ATH9K_POW_SM ( ratesArray [ rate36mb ] , 8 )
| ATH9K_POW_SM ( ratesArray [ rate24mb ] , 0 ) ) ;
2010-06-01 15:14:07 +05:30
/* CCK power per rate */
2009-08-07 09:45:15 +05:30
if ( IS_CHAN_2GHZ ( chan ) ) {
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE3 ,
ATH9K_POW_SM ( ratesArray [ rate2s ] , 24 )
| ATH9K_POW_SM ( ratesArray [ rate2l ] , 16 )
| ATH9K_POW_SM ( ratesArray [ rateXr ] , 8 )
| ATH9K_POW_SM ( ratesArray [ rate1l ] , 0 ) ) ;
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE4 ,
ATH9K_POW_SM ( ratesArray [ rate11s ] , 24 )
| ATH9K_POW_SM ( ratesArray [ rate11l ] , 16 )
| ATH9K_POW_SM ( ratesArray [ rate5_5s ] , 8 )
| ATH9K_POW_SM ( ratesArray [ rate5_5l ] , 0 ) ) ;
}
2010-06-01 15:14:07 +05:30
/* HT20 power per rate */
2009-08-07 09:45:15 +05:30
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE5 ,
ATH9K_POW_SM ( ratesArray [ rateHt20_3 ] , 24 )
| ATH9K_POW_SM ( ratesArray [ rateHt20_2 ] , 16 )
| ATH9K_POW_SM ( ratesArray [ rateHt20_1 ] , 8 )
| ATH9K_POW_SM ( ratesArray [ rateHt20_0 ] , 0 ) ) ;
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE6 ,
ATH9K_POW_SM ( ratesArray [ rateHt20_7 ] , 24 )
| ATH9K_POW_SM ( ratesArray [ rateHt20_6 ] , 16 )
| ATH9K_POW_SM ( ratesArray [ rateHt20_5 ] , 8 )
| ATH9K_POW_SM ( ratesArray [ rateHt20_4 ] , 0 ) ) ;
2010-06-01 15:14:07 +05:30
/* HT40 power per rate */
2009-08-07 09:45:15 +05:30
if ( IS_CHAN_HT40 ( chan ) ) {
2010-06-01 15:14:04 +05:30
if ( ath9k_hw_ar9287_get_eeprom ( ah , EEP_OL_PWRCTRL ) ) {
2009-08-07 09:45:15 +05:30
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE7 ,
ATH9K_POW_SM ( ratesArray [ rateHt40_3 ] , 24 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_2 ] , 16 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_1 ] , 8 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_0 ] , 0 ) ) ;
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE8 ,
ATH9K_POW_SM ( ratesArray [ rateHt40_7 ] , 24 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_6 ] , 16 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_5 ] , 8 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_4 ] , 0 ) ) ;
} else {
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE7 ,
ATH9K_POW_SM ( ratesArray [ rateHt40_3 ] +
ht40PowerIncForPdadc , 24 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_2 ] +
ht40PowerIncForPdadc , 16 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_1 ] +
ht40PowerIncForPdadc , 8 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_0 ] +
ht40PowerIncForPdadc , 0 ) ) ;
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE8 ,
ATH9K_POW_SM ( ratesArray [ rateHt40_7 ] +
ht40PowerIncForPdadc , 24 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_6 ] +
ht40PowerIncForPdadc , 16 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_5 ] +
ht40PowerIncForPdadc , 8 )
| ATH9K_POW_SM ( ratesArray [ rateHt40_4 ] +
ht40PowerIncForPdadc , 0 ) ) ;
}
2010-06-01 15:14:07 +05:30
/* Dup/Ext power per rate */
2009-08-07 09:45:15 +05:30
REG_WRITE ( ah , AR_PHY_POWER_TX_RATE9 ,
ATH9K_POW_SM ( ratesArray [ rateExtOfdm ] , 24 )
| ATH9K_POW_SM ( ratesArray [ rateExtCck ] , 16 )
| ATH9K_POW_SM ( ratesArray [ rateDupOfdm ] , 8 )
| ATH9K_POW_SM ( ratesArray [ rateDupCck ] , 0 ) ) ;
}
}
2010-06-01 15:14:04 +05:30
static void ath9k_hw_ar9287_set_addac ( struct ath_hw * ah ,
2009-08-07 09:45:15 +05:30
struct ath9k_channel * chan )
{
}
2010-06-01 15:14:04 +05:30
static void ath9k_hw_ar9287_set_board_values ( struct ath_hw * ah ,
2009-08-07 09:45:15 +05:30
struct ath9k_channel * chan )
{
struct ar9287_eeprom * eep = & ah - > eeprom . map9287 ;
struct modal_eep_ar9287_header * pModal = & eep - > modalHeader ;
u16 antWrites [ AR9287_ANT_16S ] ;
2010-06-01 15:14:06 +05:30
u32 regChainOffset , regval ;
2009-08-07 09:45:15 +05:30
u8 txRxAttenLocal ;
int i , j , offset_num ;
pModal = & eep - > modalHeader ;
antWrites [ 0 ] = ( u16 ) ( ( pModal - > antCtrlCommon > > 28 ) & 0xF ) ;
antWrites [ 1 ] = ( u16 ) ( ( pModal - > antCtrlCommon > > 24 ) & 0xF ) ;
antWrites [ 2 ] = ( u16 ) ( ( pModal - > antCtrlCommon > > 20 ) & 0xF ) ;
antWrites [ 3 ] = ( u16 ) ( ( pModal - > antCtrlCommon > > 16 ) & 0xF ) ;
antWrites [ 4 ] = ( u16 ) ( ( pModal - > antCtrlCommon > > 12 ) & 0xF ) ;
antWrites [ 5 ] = ( u16 ) ( ( pModal - > antCtrlCommon > > 8 ) & 0xF ) ;
antWrites [ 6 ] = ( u16 ) ( ( pModal - > antCtrlCommon > > 4 ) & 0xF ) ;
antWrites [ 7 ] = ( u16 ) ( pModal - > antCtrlCommon & 0xF ) ;
offset_num = 8 ;
for ( i = 0 , j = offset_num ; i < AR9287_MAX_CHAINS ; i + + ) {
antWrites [ j + + ] = ( u16 ) ( ( pModal - > antCtrlChain [ i ] > > 28 ) & 0xf ) ;
antWrites [ j + + ] = ( u16 ) ( ( pModal - > antCtrlChain [ i ] > > 10 ) & 0x3 ) ;
antWrites [ j + + ] = ( u16 ) ( ( pModal - > antCtrlChain [ i ] > > 8 ) & 0x3 ) ;
antWrites [ j + + ] = 0 ;
antWrites [ j + + ] = ( u16 ) ( ( pModal - > antCtrlChain [ i ] > > 6 ) & 0x3 ) ;
antWrites [ j + + ] = ( u16 ) ( ( pModal - > antCtrlChain [ i ] > > 4 ) & 0x3 ) ;
antWrites [ j + + ] = ( u16 ) ( ( pModal - > antCtrlChain [ i ] > > 2 ) & 0x3 ) ;
antWrites [ j + + ] = ( u16 ) ( pModal - > antCtrlChain [ i ] & 0x3 ) ;
}
REG_WRITE ( ah , AR_PHY_SWITCH_COM ,
ah - > eep_ops - > get_eeprom_antenna_cfg ( ah , chan ) ) ;
for ( i = 0 ; i < AR9287_MAX_CHAINS ; i + + ) {
regChainOffset = i * 0x1000 ;
REG_WRITE ( ah , AR_PHY_SWITCH_CHAIN_0 + regChainOffset ,
pModal - > antCtrlChain [ i ] ) ;
REG_WRITE ( ah , AR_PHY_TIMING_CTRL4 ( 0 ) + regChainOffset ,
( REG_READ ( ah , AR_PHY_TIMING_CTRL4 ( 0 ) + regChainOffset )
& ~ ( AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF ) ) |
SM ( pModal - > iqCalICh [ i ] ,
AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF ) |
SM ( pModal - > iqCalQCh [ i ] ,
AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF ) ) ;
txRxAttenLocal = pModal - > txRxAttenCh [ i ] ;
REG_RMW_FIELD ( ah , AR_PHY_GAIN_2GHZ + regChainOffset ,
AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN ,
pModal - > bswMargin [ i ] ) ;
REG_RMW_FIELD ( ah , AR_PHY_GAIN_2GHZ + regChainOffset ,
AR_PHY_GAIN_2GHZ_XATTEN1_DB ,
pModal - > bswAtten [ i ] ) ;
REG_RMW_FIELD ( ah , AR_PHY_RXGAIN + regChainOffset ,
AR9280_PHY_RXGAIN_TXRX_ATTEN ,
txRxAttenLocal ) ;
REG_RMW_FIELD ( ah , AR_PHY_RXGAIN + regChainOffset ,
AR9280_PHY_RXGAIN_TXRX_MARGIN ,
pModal - > rxTxMarginCh [ i ] ) ;
}
if ( IS_CHAN_HT40 ( chan ) )
REG_RMW_FIELD ( ah , AR_PHY_SETTLING ,
AR_PHY_SETTLING_SWITCH , pModal - > swSettleHt40 ) ;
else
REG_RMW_FIELD ( ah , AR_PHY_SETTLING ,
AR_PHY_SETTLING_SWITCH , pModal - > switchSettling ) ;
REG_RMW_FIELD ( ah , AR_PHY_DESIRED_SZ ,
AR_PHY_DESIRED_SZ_ADC , pModal - > adcDesiredSize ) ;
REG_WRITE ( ah , AR_PHY_RF_CTL4 ,
SM ( pModal - > txEndToXpaOff , AR_PHY_RF_CTL4_TX_END_XPAA_OFF )
| SM ( pModal - > txEndToXpaOff , AR_PHY_RF_CTL4_TX_END_XPAB_OFF )
| SM ( pModal - > txFrameToXpaOn , AR_PHY_RF_CTL4_FRAME_XPAA_ON )
| SM ( pModal - > txFrameToXpaOn , AR_PHY_RF_CTL4_FRAME_XPAB_ON ) ) ;
REG_RMW_FIELD ( ah , AR_PHY_RF_CTL3 ,
AR_PHY_TX_END_TO_A2_RX_ON , pModal - > txEndToRxOn ) ;
REG_RMW_FIELD ( ah , AR_PHY_CCA ,
AR9280_PHY_CCA_THRESH62 , pModal - > thresh62 ) ;
REG_RMW_FIELD ( ah , AR_PHY_EXT_CCA0 ,
AR_PHY_EXT_CCA0_THRESH62 , pModal - > thresh62 ) ;
2010-06-01 15:14:06 +05:30
regval = REG_READ ( ah , AR9287_AN_RF2G3_CH0 ) ;
regval & = ~ ( AR9287_AN_RF2G3_DB1 |
AR9287_AN_RF2G3_DB2 |
AR9287_AN_RF2G3_OB_CCK |
AR9287_AN_RF2G3_OB_PSK |
AR9287_AN_RF2G3_OB_QAM |
AR9287_AN_RF2G3_OB_PAL_OFF ) ;
regval | = ( SM ( pModal - > db1 , AR9287_AN_RF2G3_DB1 ) |
SM ( pModal - > db2 , AR9287_AN_RF2G3_DB2 ) |
SM ( pModal - > ob_cck , AR9287_AN_RF2G3_OB_CCK ) |
SM ( pModal - > ob_psk , AR9287_AN_RF2G3_OB_PSK ) |
SM ( pModal - > ob_qam , AR9287_AN_RF2G3_OB_QAM ) |
SM ( pModal - > ob_pal_off , AR9287_AN_RF2G3_OB_PAL_OFF ) ) ;
ath9k_hw_analog_shift_regwrite ( ah , AR9287_AN_RF2G3_CH0 , regval ) ;
regval = REG_READ ( ah , AR9287_AN_RF2G3_CH1 ) ;
regval & = ~ ( AR9287_AN_RF2G3_DB1 |
AR9287_AN_RF2G3_DB2 |
AR9287_AN_RF2G3_OB_CCK |
AR9287_AN_RF2G3_OB_PSK |
AR9287_AN_RF2G3_OB_QAM |
AR9287_AN_RF2G3_OB_PAL_OFF ) ;
regval | = ( SM ( pModal - > db1 , AR9287_AN_RF2G3_DB1 ) |
SM ( pModal - > db2 , AR9287_AN_RF2G3_DB2 ) |
SM ( pModal - > ob_cck , AR9287_AN_RF2G3_OB_CCK ) |
SM ( pModal - > ob_psk , AR9287_AN_RF2G3_OB_PSK ) |
SM ( pModal - > ob_qam , AR9287_AN_RF2G3_OB_QAM ) |
SM ( pModal - > ob_pal_off , AR9287_AN_RF2G3_OB_PAL_OFF ) ) ;
ath9k_hw_analog_shift_regwrite ( ah , AR9287_AN_RF2G3_CH1 , regval ) ;
2009-08-07 09:45:15 +05:30
REG_RMW_FIELD ( ah , AR_PHY_RF_CTL2 ,
AR_PHY_TX_END_DATA_START , pModal - > txFrameToDataStart ) ;
REG_RMW_FIELD ( ah , AR_PHY_RF_CTL2 ,
AR_PHY_TX_END_PA_ON , pModal - > txFrameToPaOn ) ;
ath9k_hw_analog_shift_rmw ( ah , AR9287_AN_TOP2 ,
AR9287_AN_TOP2_XPABIAS_LVL ,
AR9287_AN_TOP2_XPABIAS_LVL_S ,
pModal - > xpaBiasLvl ) ;
}
2010-06-01 15:14:04 +05:30
static u8 ath9k_hw_ar9287_get_num_ant_config ( struct ath_hw * ah ,
2010-09-16 11:40:06 +05:30
enum ath9k_hal_freq_band freq_band )
2009-08-07 09:45:15 +05:30
{
return 1 ;
}
2010-07-11 12:48:39 +02:00
static u32 ath9k_hw_ar9287_get_eeprom_antenna_cfg ( struct ath_hw * ah ,
2009-08-07 09:45:15 +05:30
struct ath9k_channel * chan )
{
struct ar9287_eeprom * eep = & ah - > eeprom . map9287 ;
struct modal_eep_ar9287_header * pModal = & eep - > modalHeader ;
2010-07-11 12:48:39 +02:00
return pModal - > antCtrlCommon ;
2009-08-07 09:45:15 +05:30
}
2010-06-01 15:14:04 +05:30
static u16 ath9k_hw_ar9287_get_spur_channel ( struct ath_hw * ah ,
2009-08-07 09:45:15 +05:30
u16 i , bool is2GHz )
{
# define EEP_MAP9287_SPURCHAN \
( ah - > eeprom . map9287 . modalHeader . spurChans [ i ] . spurChan )
2010-06-01 15:14:04 +05:30
2009-09-13 02:42:02 -07:00
struct ath_common * common = ath9k_hw_common ( ah ) ;
2009-08-07 09:45:15 +05:30
u16 spur_val = AR_NO_SPUR ;
2010-12-02 19:12:37 -08:00
ath_dbg ( common , ATH_DBG_ANI ,
" Getting spur idx:%d is2Ghz:%d val:%x \n " ,
i , is2GHz , ah - > config . spurchans [ i ] [ is2GHz ] ) ;
2009-08-07 09:45:15 +05:30
switch ( ah - > config . spurmode ) {
case SPUR_DISABLE :
break ;
case SPUR_ENABLE_IOCTL :
spur_val = ah - > config . spurchans [ i ] [ is2GHz ] ;
2010-12-02 19:12:37 -08:00
ath_dbg ( common , ATH_DBG_ANI ,
" Getting spur val from new loc. %d \n " , spur_val ) ;
2009-08-07 09:45:15 +05:30
break ;
case SPUR_ENABLE_EEPROM :
spur_val = EEP_MAP9287_SPURCHAN ;
break ;
}
return spur_val ;
# undef EEP_MAP9287_SPURCHAN
}
2010-04-15 17:39:12 -04:00
const struct eeprom_ops eep_ar9287_ops = {
2010-06-01 15:14:04 +05:30
. check_eeprom = ath9k_hw_ar9287_check_eeprom ,
. get_eeprom = ath9k_hw_ar9287_get_eeprom ,
. fill_eeprom = ath9k_hw_ar9287_fill_eeprom ,
. get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver ,
. get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev ,
. get_num_ant_config = ath9k_hw_ar9287_get_num_ant_config ,
. get_eeprom_antenna_cfg = ath9k_hw_ar9287_get_eeprom_antenna_cfg ,
. set_board_values = ath9k_hw_ar9287_set_board_values ,
. set_addac = ath9k_hw_ar9287_set_addac ,
. set_txpower = ath9k_hw_ar9287_set_txpower ,
. get_spur_channel = ath9k_hw_ar9287_get_spur_channel
2009-08-07 09:45:15 +05:30
} ;