2008-01-09 16:13:56 +01:00
/*
Broadcom B43 wireless driver
IEEE 802.11 n PHY support
2011-07-04 20:50:05 +02:00
Copyright ( c ) 2008 Michael Buesch < m @ bues . ch >
2011-09-03 21:01:02 +02:00
Copyright ( c ) 2010 - 2011 Rafał Miłecki < zajec5 @ gmail . com >
2008-01-09 16:13:56 +01:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; see the file COPYING . If not , write to
the Free Software Foundation , Inc . , 51 Franklin Steet , Fifth Floor ,
Boston , MA 02110 - 1301 , USA .
*/
2008-01-17 16:57:10 -05:00
# include <linux/delay.h>
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 17:04:11 +09:00
# include <linux/slab.h>
2008-01-17 16:57:10 -05:00
# include <linux/types.h>
2008-01-09 16:13:56 +01:00
# include "b43.h"
2008-08-30 02:27:19 +02:00
# include "phy_n.h"
2008-01-13 21:23:44 +01:00
# include "tables_nphy.h"
2010-10-14 19:33:36 +02:00
# include "radio_2055.h"
2010-10-14 21:16:33 +02:00
# include "radio_2056.h"
2012-07-26 00:07:39 +02:00
# include "radio_2057.h"
2010-01-15 14:31:39 +01:00
# include "main.h"
2014-07-31 21:59:48 +02:00
# include "ppr.h"
2008-01-09 16:13:56 +01:00
2010-01-15 12:34:21 +01:00
struct nphy_txgains {
2014-07-08 15:11:07 +02:00
u16 tx_lpf [ 2 ] ;
2010-01-15 12:34:21 +01:00
u16 txgm [ 2 ] ;
u16 pga [ 2 ] ;
u16 pad [ 2 ] ;
u16 ipa [ 2 ] ;
} ;
struct nphy_iqcal_params {
2014-07-08 15:11:07 +02:00
u16 tx_lpf ;
2010-01-15 12:34:21 +01:00
u16 txgm ;
u16 pga ;
u16 pad ;
u16 ipa ;
u16 cal_gain ;
u16 ncorr [ 5 ] ;
} ;
struct nphy_iq_est {
s32 iq0_prod ;
u32 i0_pwr ;
u32 q0_pwr ;
s32 iq1_prod ;
u32 i1_pwr ;
u32 q1_pwr ;
} ;
2008-01-09 16:13:56 +01:00
2010-01-17 13:04:02 +01:00
enum b43_nphy_rf_sequence {
B43_RFSEQ_RX2TX ,
B43_RFSEQ_TX2RX ,
B43_RFSEQ_RESET2RX ,
B43_RFSEQ_UPDATE_GAINH ,
B43_RFSEQ_UPDATE_GAINL ,
B43_RFSEQ_UPDATE_GAINU ,
} ;
2014-07-08 15:11:07 +02:00
enum n_rf_ctl_over_cmd {
N_RF_CTL_OVER_CMD_RXRF_PU = 0 ,
N_RF_CTL_OVER_CMD_RX_PU = 1 ,
N_RF_CTL_OVER_CMD_TX_PU = 2 ,
N_RF_CTL_OVER_CMD_RX_GAIN = 3 ,
N_RF_CTL_OVER_CMD_TX_GAIN = 4 ,
} ;
2013-03-29 11:37:02 +01:00
enum n_intc_override {
N_INTC_OVERRIDE_OFF = 0 ,
N_INTC_OVERRIDE_TRSW = 1 ,
N_INTC_OVERRIDE_PA = 2 ,
N_INTC_OVERRIDE_EXT_LNA_PU = 3 ,
N_INTC_OVERRIDE_EXT_LNA_GAIN = 4 ,
} ;
2013-03-20 17:30:38 +01:00
enum n_rssi_type {
N_RSSI_W1 = 0 ,
N_RSSI_W2 ,
N_RSSI_NB ,
N_RSSI_IQ ,
N_RSSI_TSSI_2G ,
N_RSSI_TSSI_5G ,
N_RSSI_TBD ,
2010-11-30 22:33:15 +01:00
} ;
2013-03-20 16:51:39 +01:00
enum n_rail_type {
N_RAIL_I = 0 ,
N_RAIL_Q = 1 ,
2010-11-30 22:33:15 +01:00
} ;
2011-09-04 23:18:22 +02:00
static inline bool b43_nphy_ipa ( struct b43_wldev * dev )
{
enum ieee80211_band band = b43_current_band ( dev - > wl ) ;
return ( ( dev - > phy . n - > ipa2g_on & & band = = IEEE80211_BAND_2GHZ ) | |
( dev - > phy . n - > ipa5g_on & & band = = IEEE80211_BAND_5GHZ ) ) ;
}
2012-01-05 01:05:30 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */
static u8 b43_nphy_get_rx_core_state ( struct b43_wldev * dev )
{
return ( b43_phy_read ( dev , B43_NPHY_RFSEQCA ) & B43_NPHY_RFSEQCA_RXEN ) > >
B43_NPHY_RFSEQCA_RXEN_SHIFT ;
}
2011-12-17 13:57:20 +01:00
/**************************************************
2013-03-29 11:37:02 +01:00
* RF ( just without b43_nphy_rf_ctl_intc_override )
2011-12-17 13:57:20 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-28 19:33:40 +02:00
2011-12-17 13:57:20 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
static void b43_nphy_force_rf_sequence ( struct b43_wldev * dev ,
enum b43_nphy_rf_sequence seq )
2008-01-14 00:05:57 +01:00
{
2011-12-17 13:57:20 +01:00
static const u16 trigger [ ] = {
[ B43_RFSEQ_RX2TX ] = B43_NPHY_RFSEQTR_RX2TX ,
[ B43_RFSEQ_TX2RX ] = B43_NPHY_RFSEQTR_TX2RX ,
[ B43_RFSEQ_RESET2RX ] = B43_NPHY_RFSEQTR_RST2RX ,
[ B43_RFSEQ_UPDATE_GAINH ] = B43_NPHY_RFSEQTR_UPGH ,
[ B43_RFSEQ_UPDATE_GAINL ] = B43_NPHY_RFSEQTR_UPGL ,
[ B43_RFSEQ_UPDATE_GAINU ] = B43_NPHY_RFSEQTR_UPGU ,
} ;
int i ;
u16 seq_mode = b43_phy_read ( dev , B43_NPHY_RFSEQMODE ) ;
2010-02-27 13:03:35 +01:00
2011-12-17 13:57:20 +01:00
B43_WARN_ON ( seq > = ARRAY_SIZE ( trigger ) ) ;
2010-02-27 13:03:35 +01:00
2011-12-17 13:57:20 +01:00
b43_phy_set ( dev , B43_NPHY_RFSEQMODE ,
B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER ) ;
b43_phy_set ( dev , B43_NPHY_RFSEQTR , trigger [ seq ] ) ;
for ( i = 0 ; i < 200 ; i + + ) {
if ( ! ( b43_phy_read ( dev , B43_NPHY_RFSEQST ) & trigger [ seq ] ) )
goto ok ;
msleep ( 1 ) ;
}
b43err ( dev - > wl , " RF sequence status timeout \n " ) ;
ok :
b43_phy_write ( dev , B43_NPHY_RFSEQMODE , seq_mode ) ;
}
2010-02-27 13:03:35 +01:00
2014-07-08 15:11:06 +02:00
static void b43_nphy_rf_ctl_override_rev19 ( struct b43_wldev * dev , u16 field ,
u16 value , u8 core , bool off ,
u8 override_id )
{
/* TODO */
}
2012-07-26 10:25:09 +02:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
2013-03-30 21:50:46 +01:00
static void b43_nphy_rf_ctl_override_rev7 ( struct b43_wldev * dev , u16 field ,
u16 value , u8 core , bool off ,
u8 override )
2012-07-26 10:25:09 +02:00
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2012-07-26 10:25:09 +02:00
const struct nphy_rf_control_override_rev7 * e ;
u16 en_addrs [ 3 ] [ 2 ] = {
{ 0x0E7 , 0x0EC } , { 0x342 , 0x343 } , { 0x346 , 0x347 }
} ;
u16 en_addr ;
u16 en_mask = field ;
u16 val_addr ;
u8 i ;
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 | | phy - > rev < 3 ) {
B43_WARN_ON ( 1 ) ;
return ;
}
2012-07-26 10:25:09 +02:00
/* Remember: we can get NULL! */
e = b43_nphy_get_rf_ctl_over_rev7 ( dev , field , override ) ;
for ( i = 0 ; i < 2 ; i + + ) {
if ( override > = ARRAY_SIZE ( en_addrs ) ) {
b43err ( dev - > wl , " Invalid override value %d \n " , override ) ;
return ;
}
en_addr = en_addrs [ override ] [ i ] ;
2013-10-16 21:40:24 -03:00
if ( e )
val_addr = ( i = = 0 ) ? e - > val_addr_core0 : e - > val_addr_core1 ;
2012-07-26 10:25:09 +02:00
if ( off ) {
b43_phy_mask ( dev , en_addr , ~ en_mask ) ;
if ( e ) /* Do it safer, better than wl */
b43_phy_mask ( dev , val_addr , ~ e - > val_mask ) ;
} else {
if ( ! core | | ( core & ( 1 < < i ) ) ) {
b43_phy_set ( dev , en_addr , en_mask ) ;
if ( e )
b43_phy_maskset ( dev , val_addr , ~ e - > val_mask , ( value < < e - > val_shift ) ) ;
}
}
}
}
2014-07-08 15:11:07 +02:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */
static void b43_nphy_rf_ctl_override_one_to_many ( struct b43_wldev * dev ,
enum n_rf_ctl_over_cmd cmd ,
u16 value , u8 core , bool off )
{
struct b43_phy * phy = & dev - > phy ;
u16 tmp ;
B43_WARN_ON ( phy - > rev < 7 ) ;
switch ( cmd ) {
case N_RF_CTL_OVER_CMD_RXRF_PU :
b43_nphy_rf_ctl_override_rev7 ( dev , 0x20 , value , core , off , 1 ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x10 , value , core , off , 1 ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x08 , value , core , off , 1 ) ;
break ;
case N_RF_CTL_OVER_CMD_RX_PU :
b43_nphy_rf_ctl_override_rev7 ( dev , 0x4 , value , core , off , 1 ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x2 , value , core , off , 1 ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x1 , value , core , off , 1 ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x2 , value , core , off , 2 ) ;
2014-07-22 21:31:05 +02:00
b43_nphy_rf_ctl_override_rev7 ( dev , 0x0800 , 0 , core , off , 1 ) ;
2014-07-08 15:11:07 +02:00
break ;
case N_RF_CTL_OVER_CMD_TX_PU :
b43_nphy_rf_ctl_override_rev7 ( dev , 0x4 , value , core , off , 0 ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x2 , value , core , off , 1 ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x1 , value , core , off , 2 ) ;
2014-07-22 21:31:05 +02:00
b43_nphy_rf_ctl_override_rev7 ( dev , 0x0800 , 1 , core , off , 1 ) ;
2014-07-08 15:11:07 +02:00
break ;
case N_RF_CTL_OVER_CMD_RX_GAIN :
tmp = value & 0xFF ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x0800 , tmp , core , off , 0 ) ;
tmp = value > > 8 ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x6000 , tmp , core , off , 0 ) ;
break ;
case N_RF_CTL_OVER_CMD_TX_GAIN :
tmp = value & 0x7FFF ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x1000 , tmp , core , off , 0 ) ;
tmp = value > > 14 ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x4000 , tmp , core , off , 0 ) ;
break ;
}
}
2011-12-17 13:57:20 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
2013-03-30 21:50:46 +01:00
static void b43_nphy_rf_ctl_override ( struct b43_wldev * dev , u16 field ,
u16 value , u8 core , bool off )
2011-12-17 13:57:20 +01:00
{
int i ;
u8 index = fls ( field ) ;
u8 addr , en_addr , val_addr ;
/* we expect only one bit set */
B43_WARN_ON ( field & ( ~ ( 1 < < ( index - 1 ) ) ) ) ;
2010-02-27 13:03:35 +01:00
2011-12-17 13:57:20 +01:00
if ( dev - > phy . rev > = 3 ) {
const struct nphy_rf_control_override_rev3 * rf_ctrl ;
for ( i = 0 ; i < 2 ; i + + ) {
if ( index = = 0 | | index = = 16 ) {
b43err ( dev - > wl ,
" Unsupported RF Ctrl Override call \n " ) ;
return ;
}
2010-02-27 13:03:35 +01:00
2011-12-17 13:57:20 +01:00
rf_ctrl = & tbl_rf_control_override_rev3 [ index - 1 ] ;
en_addr = B43_PHY_N ( ( i = = 0 ) ?
rf_ctrl - > en_addr0 : rf_ctrl - > en_addr1 ) ;
val_addr = B43_PHY_N ( ( i = = 0 ) ?
rf_ctrl - > val_addr0 : rf_ctrl - > val_addr1 ) ;
2008-01-14 00:05:57 +01:00
2011-12-17 13:57:20 +01:00
if ( off ) {
b43_phy_mask ( dev , en_addr , ~ ( field ) ) ;
b43_phy_mask ( dev , val_addr ,
~ ( rf_ctrl - > val_mask ) ) ;
} else {
2011-12-22 00:47:18 +01:00
if ( core = = 0 | | ( ( 1 < < i ) & core ) ) {
2011-12-17 13:57:20 +01:00
b43_phy_set ( dev , en_addr , field ) ;
b43_phy_maskset ( dev , val_addr ,
~ ( rf_ctrl - > val_mask ) ,
( value < < rf_ctrl - > val_shift ) ) ;
}
}
}
} else {
const struct nphy_rf_control_override_rev2 * rf_ctrl ;
if ( off ) {
b43_phy_mask ( dev , B43_NPHY_RFCTL_OVER , ~ ( field ) ) ;
value = 0 ;
} else {
b43_phy_set ( dev , B43_NPHY_RFCTL_OVER , field ) ;
}
2010-12-21 23:57:48 +01:00
2011-12-17 13:57:20 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
if ( index < = 1 | | index = = 16 ) {
b43err ( dev - > wl ,
" Unsupported RF Ctrl Override call \n " ) ;
return ;
}
2010-12-21 23:57:48 +01:00
2011-12-17 13:57:20 +01:00
if ( index = = 2 | | index = = 10 | |
( index > = 13 & & index < = 15 ) ) {
core = 1 ;
}
2010-12-21 23:57:48 +01:00
2011-12-17 13:57:20 +01:00
rf_ctrl = & tbl_rf_control_override_rev2 [ index - 2 ] ;
addr = B43_PHY_N ( ( i = = 0 ) ?
rf_ctrl - > addr0 : rf_ctrl - > addr1 ) ;
2010-12-21 23:57:48 +01:00
2011-12-22 00:47:18 +01:00
if ( ( 1 < < i ) & core )
2011-12-17 13:57:20 +01:00
b43_phy_maskset ( dev , addr , ~ ( rf_ctrl - > bmask ) ,
( value < < rf_ctrl - > shift ) ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_OVER , 0x1 ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_CMD_START ) ;
udelay ( 1 ) ;
b43_phy_mask ( dev , B43_NPHY_RFCTL_OVER , 0xFFFE ) ;
}
}
2010-12-21 23:57:48 +01:00
}
2014-04-20 13:05:47 +02:00
static void b43_nphy_rf_ctl_intc_override_rev7 ( struct b43_wldev * dev ,
enum n_intc_override intc_override ,
u16 value , u8 core_sel )
{
u16 reg , tmp , tmp2 , val ;
int core ;
2014-07-08 15:11:06 +02:00
/* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */
2014-04-20 13:05:47 +02:00
for ( core = 0 ; core < 2 ; core + + ) {
if ( ( core_sel = = 1 & & core ! = 0 ) | |
( core_sel = = 2 & & core ! = 1 ) )
continue ;
reg = ( core = = 0 ) ? B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2 ;
switch ( intc_override ) {
case N_INTC_OVERRIDE_OFF :
b43_phy_write ( dev , reg , 0 ) ;
2014-07-22 21:31:05 +02:00
b43_phy_mask ( dev , 0x2ff , ~ 0x2000 ) ;
2014-04-20 13:05:47 +02:00
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RESET2RX ) ;
break ;
case N_INTC_OVERRIDE_TRSW :
b43_phy_maskset ( dev , reg , ~ 0xC0 , value < < 6 ) ;
b43_phy_set ( dev , reg , 0x400 ) ;
b43_phy_mask ( dev , 0x2ff , ~ 0xC000 & 0xFFFF ) ;
b43_phy_set ( dev , 0x2ff , 0x2000 ) ;
b43_phy_set ( dev , 0x2ff , 0x0001 ) ;
break ;
case N_INTC_OVERRIDE_PA :
tmp = 0x0030 ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ )
val = value < < 5 ;
else
val = value < < 4 ;
b43_phy_maskset ( dev , reg , ~ tmp , val ) ;
b43_phy_set ( dev , reg , 0x1000 ) ;
break ;
case N_INTC_OVERRIDE_EXT_LNA_PU :
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
tmp = 0x0001 ;
tmp2 = 0x0004 ;
val = value ;
} else {
tmp = 0x0004 ;
tmp2 = 0x0001 ;
val = value < < 2 ;
}
b43_phy_maskset ( dev , reg , ~ tmp , val ) ;
b43_phy_mask ( dev , reg , ~ tmp2 ) ;
break ;
case N_INTC_OVERRIDE_EXT_LNA_GAIN :
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
tmp = 0x0002 ;
tmp2 = 0x0008 ;
val = value < < 1 ;
} else {
tmp = 0x0008 ;
tmp2 = 0x0002 ;
val = value < < 3 ;
}
b43_phy_maskset ( dev , reg , ~ tmp , val ) ;
b43_phy_mask ( dev , reg , ~ tmp2 ) ;
break ;
}
}
}
2011-12-17 13:57:20 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
2013-03-29 11:37:02 +01:00
static void b43_nphy_rf_ctl_intc_override ( struct b43_wldev * dev ,
enum n_intc_override intc_override ,
u16 value , u8 core )
2010-12-21 23:57:48 +01:00
{
2011-12-17 13:57:20 +01:00
u8 i , j ;
u16 reg , tmp , val ;
2011-12-11 02:55:34 +01:00
2014-04-20 13:05:47 +02:00
if ( dev - > phy . rev > = 7 ) {
b43_nphy_rf_ctl_intc_override_rev7 ( dev , intc_override , value ,
core ) ;
return ;
}
2010-12-21 23:57:48 +01:00
B43_WARN_ON ( dev - > phy . rev < 3 ) ;
2011-12-17 13:57:20 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
if ( ( core = = 1 & & i = = 1 ) | | ( core = = 2 & & ! i ) )
continue ;
2011-12-11 02:55:34 +01:00
2011-12-17 13:57:20 +01:00
reg = ( i = = 0 ) ?
B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2 ;
2012-01-03 22:49:18 +01:00
b43_phy_set ( dev , reg , 0x400 ) ;
2011-12-11 02:55:34 +01:00
2013-03-29 11:37:02 +01:00
switch ( intc_override ) {
case N_INTC_OVERRIDE_OFF :
2011-12-17 13:57:20 +01:00
b43_phy_write ( dev , reg , 0 ) ;
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RESET2RX ) ;
break ;
2013-03-29 11:37:02 +01:00
case N_INTC_OVERRIDE_TRSW :
2011-12-17 13:57:20 +01:00
if ( ! i ) {
b43_phy_maskset ( dev , B43_NPHY_RFCTL_INTC1 ,
0xFC3F , ( value < < 6 ) ) ;
b43_phy_maskset ( dev , B43_NPHY_TXF_40CO_B1S1 ,
0xFFFE , 1 ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_CMD_START ) ;
for ( j = 0 ; j < 100 ; j + + ) {
2012-01-03 22:49:18 +01:00
if ( ! ( b43_phy_read ( dev , B43_NPHY_RFCTL_CMD ) & B43_NPHY_RFCTL_CMD_START ) ) {
2011-12-17 13:57:20 +01:00
j = 0 ;
break ;
}
udelay ( 10 ) ;
2011-12-11 02:55:34 +01:00
}
2011-12-17 13:57:20 +01:00
if ( j )
b43err ( dev - > wl ,
" intc override timeout \n " ) ;
b43_phy_mask ( dev , B43_NPHY_TXF_40CO_B1S1 ,
0xFFFE ) ;
2011-12-11 02:55:34 +01:00
} else {
2011-12-17 13:57:20 +01:00
b43_phy_maskset ( dev , B43_NPHY_RFCTL_INTC2 ,
0xFC3F , ( value < < 6 ) ) ;
b43_phy_maskset ( dev , B43_NPHY_RFCTL_OVER ,
0xFFFE , 1 ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_CMD_RXTX ) ;
for ( j = 0 ; j < 100 ; j + + ) {
2012-01-03 22:49:18 +01:00
if ( ! ( b43_phy_read ( dev , B43_NPHY_RFCTL_CMD ) & B43_NPHY_RFCTL_CMD_RXTX ) ) {
2011-12-17 13:57:20 +01:00
j = 0 ;
break ;
}
udelay ( 10 ) ;
}
if ( j )
b43err ( dev - > wl ,
" intc override timeout \n " ) ;
b43_phy_mask ( dev , B43_NPHY_RFCTL_OVER ,
0xFFFE ) ;
2011-12-11 02:55:34 +01:00
}
2011-12-17 13:57:20 +01:00
break ;
2013-03-29 11:37:02 +01:00
case N_INTC_OVERRIDE_PA :
2011-12-17 13:57:20 +01:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
tmp = 0x0020 ;
val = value < < 5 ;
} else {
tmp = 0x0010 ;
val = value < < 4 ;
}
b43_phy_maskset ( dev , reg , ~ tmp , val ) ;
break ;
2013-03-29 11:37:02 +01:00
case N_INTC_OVERRIDE_EXT_LNA_PU :
2011-12-17 13:57:20 +01:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
tmp = 0x0001 ;
val = value ;
} else {
tmp = 0x0004 ;
val = value < < 2 ;
}
b43_phy_maskset ( dev , reg , ~ tmp , val ) ;
break ;
2013-03-29 11:37:02 +01:00
case N_INTC_OVERRIDE_EXT_LNA_GAIN :
2011-12-17 13:57:20 +01:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
tmp = 0x0002 ;
val = value < < 1 ;
} else {
tmp = 0x0008 ;
val = value < < 3 ;
}
b43_phy_maskset ( dev , reg , ~ tmp , val ) ;
break ;
2011-12-11 02:55:34 +01:00
}
}
2011-12-17 13:57:20 +01:00
}
2011-12-11 02:55:34 +01:00
2011-12-17 13:57:20 +01:00
/**************************************************
* Various PHY ops
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
static void b43_nphy_write_clip_detection ( struct b43_wldev * dev ,
const u16 * clip_st )
{
b43_phy_write ( dev , B43_NPHY_C1_CLIP1THRES , clip_st [ 0 ] ) ;
b43_phy_write ( dev , B43_NPHY_C2_CLIP1THRES , clip_st [ 1 ] ) ;
2010-12-21 23:57:48 +01:00
}
2011-12-17 13:57:20 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
static void b43_nphy_read_clip_detection ( struct b43_wldev * dev , u16 * clip_st )
2008-01-14 00:05:57 +01:00
{
2011-12-17 13:57:20 +01:00
clip_st [ 0 ] = b43_phy_read ( dev , B43_NPHY_C1_CLIP1THRES ) ;
clip_st [ 1 ] = b43_phy_read ( dev , B43_NPHY_C2_CLIP1THRES ) ;
2008-01-14 00:05:57 +01:00
}
2011-12-17 13:57:20 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
static u16 b43_nphy_classifier ( struct b43_wldev * dev , u16 mask , u16 val )
2010-11-28 12:59:43 +01:00
{
2011-12-17 13:57:20 +01:00
u16 tmp ;
2010-11-28 12:59:43 +01:00
2011-12-17 13:57:20 +01:00
if ( dev - > dev - > core_rev = = 16 )
b43_mac_suspend ( dev ) ;
2010-11-28 12:59:43 +01:00
2011-12-17 13:57:20 +01:00
tmp = b43_phy_read ( dev , B43_NPHY_CLASSCTL ) ;
tmp & = ( B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
B43_NPHY_CLASSCTL_WAITEDEN ) ;
tmp & = ~ mask ;
tmp | = ( val & mask ) ;
b43_phy_maskset ( dev , B43_NPHY_CLASSCTL , 0xFFF8 , tmp ) ;
2010-11-28 12:59:43 +01:00
2011-12-17 13:57:20 +01:00
if ( dev - > dev - > core_rev = = 16 )
b43_mac_enable ( dev ) ;
2010-11-28 12:59:43 +01:00
2011-12-17 13:57:20 +01:00
return tmp ;
}
2010-11-28 12:59:43 +01:00
2011-12-17 13:57:20 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
static void b43_nphy_reset_cca ( struct b43_wldev * dev )
{
u16 bbcfg ;
2010-11-28 12:59:43 +01:00
2011-12-17 13:57:20 +01:00
b43_phy_force_clock ( dev , 1 ) ;
bbcfg = b43_phy_read ( dev , B43_NPHY_BBCFG ) ;
b43_phy_write ( dev , B43_NPHY_BBCFG , bbcfg | B43_NPHY_BBCFG_RSTCCA ) ;
udelay ( 1 ) ;
b43_phy_write ( dev , B43_NPHY_BBCFG , bbcfg & ~ B43_NPHY_BBCFG_RSTCCA ) ;
b43_phy_force_clock ( dev , 0 ) ;
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RESET2RX ) ;
}
2010-11-28 12:59:43 +01:00
2011-12-17 13:57:20 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
static void b43_nphy_stay_in_carrier_search ( struct b43_wldev * dev , bool enable )
{
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = phy - > n ;
2010-11-28 12:59:43 +01:00
2011-12-17 13:57:20 +01:00
if ( enable ) {
static const u16 clip [ ] = { 0xFFFF , 0xFFFF } ;
if ( nphy - > deaf_count + + = = 0 ) {
nphy - > classifier_state = b43_nphy_classifier ( dev , 0 , 0 ) ;
2014-04-20 13:05:45 +02:00
b43_nphy_classifier ( dev , 0x7 ,
B43_NPHY_CLASSCTL_WAITEDEN ) ;
2011-12-17 13:57:20 +01:00
b43_nphy_read_clip_detection ( dev , nphy - > clip_state ) ;
b43_nphy_write_clip_detection ( dev , clip ) ;
}
b43_nphy_reset_cca ( dev ) ;
2010-11-28 12:59:43 +01:00
} else {
2011-12-17 13:57:20 +01:00
if ( - - nphy - > deaf_count = = 0 ) {
b43_nphy_classifier ( dev , 0x7 , nphy - > classifier_state ) ;
b43_nphy_write_clip_detection ( dev , nphy - > clip_state ) ;
2011-09-01 22:49:57 +02:00
}
2010-11-28 12:59:43 +01:00
}
}
2014-07-08 15:11:07 +02:00
/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
static u16 b43_nphy_read_lpf_ctl ( struct b43_wldev * dev , u16 offset )
{
if ( ! offset )
offset = b43_is_40mhz ( dev ) ? 0x159 : 0x154 ;
return b43_ntab_read ( dev , B43_NTAB16 ( 7 , offset ) ) & 0x7 ;
}
2011-12-17 13:57:24 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
static void b43_nphy_adjust_lna_gain_table ( struct b43_wldev * dev )
2008-01-14 00:05:57 +01:00
{
2010-11-28 12:59:43 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
2011-12-17 13:57:24 +01:00
u8 i ;
s16 tmp ;
u16 data [ 4 ] ;
s16 gain [ 2 ] ;
u16 minmax [ 2 ] ;
static const u16 lna_gain [ 4 ] = { - 2 , 10 , 19 , 25 } ;
2010-11-28 12:59:43 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 1 ) ;
2011-12-17 13:57:24 +01:00
if ( nphy - > gain_boost ) {
2010-11-28 12:59:43 +01:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
2011-12-17 13:57:24 +01:00
gain [ 0 ] = 6 ;
gain [ 1 ] = 6 ;
2010-11-28 12:59:43 +01:00
} else {
2011-12-17 13:57:24 +01:00
tmp = 40370 - 315 * dev - > phy . channel ;
gain [ 0 ] = ( ( tmp > > 13 ) + ( ( tmp > > 12 ) & 1 ) ) ;
tmp = 23242 - 224 * dev - > phy . channel ;
gain [ 1 ] = ( ( tmp > > 13 ) + ( ( tmp > > 12 ) & 1 ) ) ;
2010-11-28 12:59:43 +01:00
}
2011-12-17 13:57:24 +01:00
} else {
gain [ 0 ] = 0 ;
gain [ 1 ] = 0 ;
2010-11-28 12:59:43 +01:00
}
for ( i = 0 ; i < 2 ; i + + ) {
2011-12-17 13:57:24 +01:00
if ( nphy - > elna_gain_config ) {
data [ 0 ] = 19 + gain [ i ] ;
data [ 1 ] = 25 + gain [ i ] ;
data [ 2 ] = 25 + gain [ i ] ;
data [ 3 ] = 25 + gain [ i ] ;
2010-11-28 12:59:43 +01:00
} else {
2011-12-17 13:57:24 +01:00
data [ 0 ] = lna_gain [ 0 ] + gain [ i ] ;
data [ 1 ] = lna_gain [ 1 ] + gain [ i ] ;
data [ 2 ] = lna_gain [ 2 ] + gain [ i ] ;
data [ 3 ] = lna_gain [ 3 ] + gain [ i ] ;
2010-11-28 12:59:43 +01:00
}
2011-12-17 13:57:24 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( i , 8 ) , 4 , data ) ;
2010-11-28 12:59:43 +01:00
2011-12-17 13:57:24 +01:00
minmax [ i ] = 23 + gain [ i ] ;
2010-11-28 12:59:43 +01:00
}
2011-12-17 13:57:24 +01:00
b43_phy_maskset ( dev , B43_NPHY_C1_MINMAX_GAIN , ~ B43_NPHY_C1_MINGAIN ,
minmax [ 0 ] < < B43_NPHY_C1_MINGAIN_SHIFT ) ;
b43_phy_maskset ( dev , B43_NPHY_C2_MINMAX_GAIN , ~ B43_NPHY_C2_MINGAIN ,
minmax [ 1 ] < < B43_NPHY_C2_MINGAIN_SHIFT ) ;
2010-11-28 12:59:43 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 0 ) ;
2008-01-14 00:05:57 +01:00
}
2011-12-17 13:57:20 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
static void b43_nphy_set_rf_sequence ( struct b43_wldev * dev , u8 cmd ,
u8 * events , u8 * delays , u8 length )
2011-09-04 23:23:53 +02:00
{
2011-12-17 13:57:20 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
u8 i ;
u8 end = ( dev - > phy . rev > = 3 ) ? 0x1F : 0x0F ;
u16 offset1 = cmd < < 4 ;
u16 offset2 = offset1 + 0x80 ;
2011-09-04 23:23:53 +02:00
2011-12-17 13:57:20 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , true ) ;
2011-09-04 23:23:53 +02:00
2011-12-17 13:57:20 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 7 , offset1 ) , length , events ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 7 , offset2 ) , length , delays ) ;
2011-09-04 23:23:53 +02:00
2011-12-17 13:57:20 +01:00
for ( i = length ; i < 16 ; i + + ) {
b43_ntab_write ( dev , B43_NTAB8 ( 7 , offset1 + i ) , end ) ;
b43_ntab_write ( dev , B43_NTAB8 ( 7 , offset2 + i ) , 1 ) ;
2011-09-04 23:23:53 +02:00
}
2011-12-17 13:57:20 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , false ) ;
2011-09-04 23:23:53 +02:00
}
2010-02-27 13:03:39 +01:00
2012-07-26 00:07:39 +02:00
/**************************************************
* Radio 0x2057
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-07-01 16:19:08 +02:00
static void b43_radio_2057_chantab_upload ( struct b43_wldev * dev ,
const struct b43_nphy_chantabent_rev7 * e_r7 ,
const struct b43_nphy_chantabent_rev7_2g * e_r7_2g )
{
if ( e_r7_2g ) {
b43_radio_write ( dev , R2057_VCOCAL_COUNTVAL0 , e_r7_2g - > radio_vcocal_countval0 ) ;
b43_radio_write ( dev , R2057_VCOCAL_COUNTVAL1 , e_r7_2g - > radio_vcocal_countval1 ) ;
b43_radio_write ( dev , R2057_RFPLL_REFMASTER_SPAREXTALSIZE , e_r7_2g - > radio_rfpll_refmaster_sparextalsize ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_R1 , e_r7_2g - > radio_rfpll_loopfilter_r1 ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C2 , e_r7_2g - > radio_rfpll_loopfilter_c2 ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C1 , e_r7_2g - > radio_rfpll_loopfilter_c1 ) ;
b43_radio_write ( dev , R2057_CP_KPD_IDAC , e_r7_2g - > radio_cp_kpd_idac ) ;
b43_radio_write ( dev , R2057_RFPLL_MMD0 , e_r7_2g - > radio_rfpll_mmd0 ) ;
b43_radio_write ( dev , R2057_RFPLL_MMD1 , e_r7_2g - > radio_rfpll_mmd1 ) ;
b43_radio_write ( dev , R2057_VCOBUF_TUNE , e_r7_2g - > radio_vcobuf_tune ) ;
b43_radio_write ( dev , R2057_LOGEN_MX2G_TUNE , e_r7_2g - > radio_logen_mx2g_tune ) ;
b43_radio_write ( dev , R2057_LOGEN_INDBUF2G_TUNE , e_r7_2g - > radio_logen_indbuf2g_tune ) ;
b43_radio_write ( dev , R2057_TXMIX2G_TUNE_BOOST_PU_CORE0 , e_r7_2g - > radio_txmix2g_tune_boost_pu_core0 ) ;
b43_radio_write ( dev , R2057_PAD2G_TUNE_PUS_CORE0 , e_r7_2g - > radio_pad2g_tune_pus_core0 ) ;
b43_radio_write ( dev , R2057_LNA2G_TUNE_CORE0 , e_r7_2g - > radio_lna2g_tune_core0 ) ;
b43_radio_write ( dev , R2057_TXMIX2G_TUNE_BOOST_PU_CORE1 , e_r7_2g - > radio_txmix2g_tune_boost_pu_core1 ) ;
b43_radio_write ( dev , R2057_PAD2G_TUNE_PUS_CORE1 , e_r7_2g - > radio_pad2g_tune_pus_core1 ) ;
b43_radio_write ( dev , R2057_LNA2G_TUNE_CORE1 , e_r7_2g - > radio_lna2g_tune_core1 ) ;
} else {
b43_radio_write ( dev , R2057_VCOCAL_COUNTVAL0 , e_r7 - > radio_vcocal_countval0 ) ;
b43_radio_write ( dev , R2057_VCOCAL_COUNTVAL1 , e_r7 - > radio_vcocal_countval1 ) ;
b43_radio_write ( dev , R2057_RFPLL_REFMASTER_SPAREXTALSIZE , e_r7 - > radio_rfpll_refmaster_sparextalsize ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_R1 , e_r7 - > radio_rfpll_loopfilter_r1 ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C2 , e_r7 - > radio_rfpll_loopfilter_c2 ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C1 , e_r7 - > radio_rfpll_loopfilter_c1 ) ;
b43_radio_write ( dev , R2057_CP_KPD_IDAC , e_r7 - > radio_cp_kpd_idac ) ;
b43_radio_write ( dev , R2057_RFPLL_MMD0 , e_r7 - > radio_rfpll_mmd0 ) ;
b43_radio_write ( dev , R2057_RFPLL_MMD1 , e_r7 - > radio_rfpll_mmd1 ) ;
b43_radio_write ( dev , R2057_VCOBUF_TUNE , e_r7 - > radio_vcobuf_tune ) ;
b43_radio_write ( dev , R2057_LOGEN_MX2G_TUNE , e_r7 - > radio_logen_mx2g_tune ) ;
b43_radio_write ( dev , R2057_LOGEN_MX5G_TUNE , e_r7 - > radio_logen_mx5g_tune ) ;
b43_radio_write ( dev , R2057_LOGEN_INDBUF2G_TUNE , e_r7 - > radio_logen_indbuf2g_tune ) ;
b43_radio_write ( dev , R2057_LOGEN_INDBUF5G_TUNE , e_r7 - > radio_logen_indbuf5g_tune ) ;
b43_radio_write ( dev , R2057_TXMIX2G_TUNE_BOOST_PU_CORE0 , e_r7 - > radio_txmix2g_tune_boost_pu_core0 ) ;
b43_radio_write ( dev , R2057_PAD2G_TUNE_PUS_CORE0 , e_r7 - > radio_pad2g_tune_pus_core0 ) ;
b43_radio_write ( dev , R2057_PGA_BOOST_TUNE_CORE0 , e_r7 - > radio_pga_boost_tune_core0 ) ;
b43_radio_write ( dev , R2057_TXMIX5G_BOOST_TUNE_CORE0 , e_r7 - > radio_txmix5g_boost_tune_core0 ) ;
b43_radio_write ( dev , R2057_PAD5G_TUNE_MISC_PUS_CORE0 , e_r7 - > radio_pad5g_tune_misc_pus_core0 ) ;
b43_radio_write ( dev , R2057_LNA2G_TUNE_CORE0 , e_r7 - > radio_lna2g_tune_core0 ) ;
b43_radio_write ( dev , R2057_LNA5G_TUNE_CORE0 , e_r7 - > radio_lna5g_tune_core0 ) ;
b43_radio_write ( dev , R2057_TXMIX2G_TUNE_BOOST_PU_CORE1 , e_r7 - > radio_txmix2g_tune_boost_pu_core1 ) ;
b43_radio_write ( dev , R2057_PAD2G_TUNE_PUS_CORE1 , e_r7 - > radio_pad2g_tune_pus_core1 ) ;
b43_radio_write ( dev , R2057_PGA_BOOST_TUNE_CORE1 , e_r7 - > radio_pga_boost_tune_core1 ) ;
b43_radio_write ( dev , R2057_TXMIX5G_BOOST_TUNE_CORE1 , e_r7 - > radio_txmix5g_boost_tune_core1 ) ;
b43_radio_write ( dev , R2057_PAD5G_TUNE_MISC_PUS_CORE1 , e_r7 - > radio_pad5g_tune_misc_pus_core1 ) ;
b43_radio_write ( dev , R2057_LNA2G_TUNE_CORE1 , e_r7 - > radio_lna2g_tune_core1 ) ;
b43_radio_write ( dev , R2057_LNA5G_TUNE_CORE1 , e_r7 - > radio_lna5g_tune_core1 ) ;
}
}
static void b43_radio_2057_setup ( struct b43_wldev * dev ,
const struct b43_nphy_chantabent_rev7 * tabent_r7 ,
const struct b43_nphy_chantabent_rev7_2g * tabent_r7_2g )
{
struct b43_phy * phy = & dev - > phy ;
b43_radio_2057_chantab_upload ( dev , tabent_r7 , tabent_r7_2g ) ;
switch ( phy - > radio_rev ) {
case 0 . . . 4 :
case 6 :
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_R1 , 0x3f ) ;
b43_radio_write ( dev , R2057_CP_KPD_IDAC , 0x3f ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C1 , 0x8 ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C2 , 0x8 ) ;
} else {
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_R1 , 0x1f ) ;
b43_radio_write ( dev , R2057_CP_KPD_IDAC , 0x3f ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C1 , 0x8 ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C2 , 0x8 ) ;
}
break ;
2014-07-08 15:11:08 +02:00
case 9 : /* e.g. PHY rev 16 */
b43_radio_write ( dev , R2057_LOGEN_PTAT_RESETS , 0x20 ) ;
b43_radio_write ( dev , R2057_VCOBUF_IDACS , 0x18 ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
b43_radio_write ( dev , R2057_LOGEN_PTAT_RESETS , 0x38 ) ;
b43_radio_write ( dev , R2057_VCOBUF_IDACS , 0x0f ) ;
if ( b43_is_40mhz ( dev ) ) {
/* TODO */
} else {
b43_radio_write ( dev ,
R2057_PAD_BIAS_FILTER_BWS_CORE0 ,
0x3c ) ;
b43_radio_write ( dev ,
R2057_PAD_BIAS_FILTER_BWS_CORE1 ,
0x3c ) ;
}
}
break ;
2014-07-17 19:31:02 +02:00
case 14 : /* 2 GHz only */
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_R1 , 0x1b ) ;
b43_radio_write ( dev , R2057_CP_KPD_IDAC , 0x3f ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C1 , 0x1f ) ;
b43_radio_write ( dev , R2057_RFPLL_LOOPFILTER_C2 , 0x1f ) ;
break ;
2014-07-01 16:19:08 +02:00
}
2014-07-08 15:11:08 +02:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
u16 txmix2g_tune_boost_pu = 0 ;
u16 pad2g_tune_pus = 0 ;
if ( b43_nphy_ipa ( dev ) ) {
switch ( phy - > radio_rev ) {
case 9 :
txmix2g_tune_boost_pu = 0x0041 ;
/* TODO */
break ;
2014-07-17 19:31:02 +02:00
case 14 :
txmix2g_tune_boost_pu = 0x21 ;
pad2g_tune_pus = 0x23 ;
break ;
2014-07-08 15:11:08 +02:00
}
}
if ( txmix2g_tune_boost_pu )
b43_radio_write ( dev , R2057_TXMIX2G_TUNE_BOOST_PU_CORE0 ,
txmix2g_tune_boost_pu ) ;
if ( pad2g_tune_pus )
b43_radio_write ( dev , R2057_PAD2G_TUNE_PUS_CORE0 ,
pad2g_tune_pus ) ;
if ( txmix2g_tune_boost_pu )
b43_radio_write ( dev , R2057_TXMIX2G_TUNE_BOOST_PU_CORE1 ,
txmix2g_tune_boost_pu ) ;
if ( pad2g_tune_pus )
b43_radio_write ( dev , R2057_PAD2G_TUNE_PUS_CORE1 ,
pad2g_tune_pus ) ;
}
2014-07-01 16:19:08 +02:00
usleep_range ( 50 , 100 ) ;
/* VCO calibration */
b43_radio_mask ( dev , R2057_RFPLL_MISC_EN , ~ 0x01 ) ;
b43_radio_mask ( dev , R2057_RFPLL_MISC_CAL_RESETN , ~ 0x04 ) ;
b43_radio_set ( dev , R2057_RFPLL_MISC_CAL_RESETN , 0x4 ) ;
b43_radio_set ( dev , R2057_RFPLL_MISC_EN , 0x01 ) ;
usleep_range ( 300 , 600 ) ;
}
2014-07-01 16:19:07 +02:00
/* Calibrate resistors in LPF of PLL?
* http : //bcm-v4.sipsolutions.net/PHY/radio205x_rcal
*/
2012-07-26 00:07:39 +02:00
static u8 b43_radio_2057_rcal ( struct b43_wldev * dev )
{
struct b43_phy * phy = & dev - > phy ;
2014-07-17 19:31:03 +02:00
u16 saved_regs_phy [ 12 ] ;
u16 saved_regs_phy_rf [ 6 ] ;
u16 saved_regs_radio [ 2 ] = { } ;
static const u16 phy_to_store [ ] = {
B43_NPHY_RFCTL_RSSIO1 , B43_NPHY_RFCTL_RSSIO2 ,
B43_NPHY_RFCTL_LUT_TRSW_LO1 , B43_NPHY_RFCTL_LUT_TRSW_LO2 ,
B43_NPHY_RFCTL_RXG1 , B43_NPHY_RFCTL_RXG2 ,
B43_NPHY_RFCTL_TXG1 , B43_NPHY_RFCTL_TXG2 ,
B43_NPHY_REV7_RF_CTL_MISC_REG3 , B43_NPHY_REV7_RF_CTL_MISC_REG4 ,
B43_NPHY_REV7_RF_CTL_MISC_REG5 , B43_NPHY_REV7_RF_CTL_MISC_REG6 ,
} ;
static const u16 phy_to_store_rf [ ] = {
B43_NPHY_REV3_RFCTL_OVER0 , B43_NPHY_REV3_RFCTL_OVER1 ,
B43_NPHY_REV7_RF_CTL_OVER3 , B43_NPHY_REV7_RF_CTL_OVER4 ,
B43_NPHY_REV7_RF_CTL_OVER5 , B43_NPHY_REV7_RF_CTL_OVER6 ,
} ;
2012-07-26 00:07:39 +02:00
u16 tmp ;
2014-07-17 19:31:03 +02:00
int i ;
2012-07-26 00:07:39 +02:00
2014-07-17 19:31:03 +02:00
/* Save */
for ( i = 0 ; i < ARRAY_SIZE ( phy_to_store ) ; i + + )
saved_regs_phy [ i ] = b43_phy_read ( dev , phy_to_store [ i ] ) ;
for ( i = 0 ; i < ARRAY_SIZE ( phy_to_store_rf ) ; i + + )
saved_regs_phy_rf [ i ] = b43_phy_read ( dev , phy_to_store_rf [ i ] ) ;
/* Set */
for ( i = 0 ; i < ARRAY_SIZE ( phy_to_store ) ; i + + )
b43_phy_write ( dev , phy_to_store [ i ] , 0 ) ;
b43_phy_write ( dev , B43_NPHY_REV3_RFCTL_OVER0 , 0x07ff ) ;
b43_phy_write ( dev , B43_NPHY_REV3_RFCTL_OVER1 , 0x07ff ) ;
b43_phy_write ( dev , B43_NPHY_REV7_RF_CTL_OVER3 , 0x07ff ) ;
b43_phy_write ( dev , B43_NPHY_REV7_RF_CTL_OVER4 , 0x07ff ) ;
b43_phy_write ( dev , B43_NPHY_REV7_RF_CTL_OVER5 , 0x007f ) ;
b43_phy_write ( dev , B43_NPHY_REV7_RF_CTL_OVER6 , 0x007f ) ;
switch ( phy - > radio_rev ) {
case 5 :
b43_phy_mask ( dev , B43_NPHY_REV7_RF_CTL_OVER3 , ~ 0x2 ) ;
2012-07-26 00:07:39 +02:00
udelay ( 10 ) ;
b43_radio_set ( dev , R2057_IQTEST_SEL_PU , 0x1 ) ;
2014-07-17 19:31:03 +02:00
b43_radio_maskset ( dev , R2057v7_IQTEST_SEL_PU2 , ~ 0x2 , 0x1 ) ;
break ;
case 9 :
b43_phy_set ( dev , B43_NPHY_REV7_RF_CTL_OVER3 , 0x2 ) ;
b43_phy_set ( dev , B43_NPHY_REV7_RF_CTL_MISC_REG3 , 0x2 ) ;
saved_regs_radio [ 0 ] = b43_radio_read ( dev , R2057_IQTEST_SEL_PU ) ;
b43_radio_write ( dev , R2057_IQTEST_SEL_PU , 0x11 ) ;
break ;
case 14 :
saved_regs_radio [ 0 ] = b43_radio_read ( dev , R2057_IQTEST_SEL_PU ) ;
saved_regs_radio [ 1 ] = b43_radio_read ( dev , R2057v7_IQTEST_SEL_PU2 ) ;
b43_phy_set ( dev , B43_NPHY_REV7_RF_CTL_MISC_REG3 , 0x2 ) ;
b43_phy_set ( dev , B43_NPHY_REV7_RF_CTL_OVER3 , 0x2 ) ;
b43_radio_write ( dev , R2057v7_IQTEST_SEL_PU2 , 0x2 ) ;
b43_radio_write ( dev , R2057_IQTEST_SEL_PU , 0x1 ) ;
break ;
2012-07-26 00:07:39 +02:00
}
2014-07-01 16:19:07 +02:00
/* Enable */
2012-07-26 00:07:39 +02:00
b43_radio_set ( dev , R2057_RCAL_CONFIG , 0x1 ) ;
udelay ( 10 ) ;
2014-07-01 16:19:07 +02:00
/* Start */
b43_radio_set ( dev , R2057_RCAL_CONFIG , 0x2 ) ;
usleep_range ( 100 , 200 ) ;
/* Stop */
b43_radio_mask ( dev , R2057_RCAL_CONFIG , ~ 0x2 ) ;
/* Wait and check for result */
if ( ! b43_radio_wait_value ( dev , R2057_RCAL_STATUS , 1 , 1 , 100 , 1000000 ) ) {
2012-07-26 00:07:39 +02:00
b43err ( dev - > wl , " Radio 0x2057 rcal timeout \n " ) ;
return 0 ;
}
tmp = b43_radio_read ( dev , R2057_RCAL_STATUS ) & 0x3E ;
2014-07-01 16:19:07 +02:00
/* Disable */
2012-07-26 00:07:39 +02:00
b43_radio_mask ( dev , R2057_RCAL_CONFIG , ~ 0x1 ) ;
2014-07-17 19:31:03 +02:00
/* Restore */
for ( i = 0 ; i < ARRAY_SIZE ( phy_to_store_rf ) ; i + + )
b43_phy_write ( dev , phy_to_store_rf [ i ] , saved_regs_phy_rf [ i ] ) ;
for ( i = 0 ; i < ARRAY_SIZE ( phy_to_store ) ; i + + )
b43_phy_write ( dev , phy_to_store [ i ] , saved_regs_phy [ i ] ) ;
switch ( phy - > radio_rev ) {
case 0 . . . 4 :
case 6 :
2012-07-26 00:07:39 +02:00
b43_radio_maskset ( dev , R2057_TEMPSENSE_CONFIG , ~ 0x3C , tmp ) ;
b43_radio_maskset ( dev , R2057_BANDGAP_RCAL_TRIM , ~ 0xF0 ,
tmp < < 2 ) ;
2014-07-17 19:31:03 +02:00
break ;
case 5 :
b43_radio_mask ( dev , R2057_IPA2G_CASCONV_CORE0 , ~ 0x1 ) ;
b43_radio_mask ( dev , R2057v7_IQTEST_SEL_PU2 , ~ 0x2 ) ;
break ;
case 9 :
b43_radio_write ( dev , R2057_IQTEST_SEL_PU , saved_regs_radio [ 0 ] ) ;
break ;
case 14 :
b43_radio_write ( dev , R2057_IQTEST_SEL_PU , saved_regs_radio [ 0 ] ) ;
b43_radio_write ( dev , R2057v7_IQTEST_SEL_PU2 , saved_regs_radio [ 1 ] ) ;
break ;
2012-07-26 00:07:39 +02:00
}
return tmp & 0x3e ;
}
2014-07-01 16:19:07 +02:00
/* Calibrate the internal RC oscillator?
* http : //bcm-v4.sipsolutions.net/PHY/radio2057_rccal
*/
2012-07-26 00:07:39 +02:00
static u16 b43_radio_2057_rccal ( struct b43_wldev * dev )
{
struct b43_phy * phy = & dev - > phy ;
bool special = ( phy - > radio_rev = = 3 | | phy - > radio_rev = = 4 | |
phy - > radio_rev = = 6 ) ;
u16 tmp ;
2014-07-01 16:19:07 +02:00
/* Setup cal */
2012-07-26 00:07:39 +02:00
if ( special ) {
b43_radio_write ( dev , R2057_RCCAL_MASTER , 0x61 ) ;
b43_radio_write ( dev , R2057_RCCAL_TRC0 , 0xC0 ) ;
} else {
2014-07-01 16:19:07 +02:00
b43_radio_write ( dev , R2057v7_RCCAL_MASTER , 0x61 ) ;
2014-07-17 19:31:03 +02:00
b43_radio_write ( dev , R2057_RCCAL_TRC0 , 0xE9 ) ;
2012-07-26 00:07:39 +02:00
}
b43_radio_write ( dev , R2057_RCCAL_X1 , 0x6E ) ;
2014-07-01 16:19:07 +02:00
/* Start, wait, stop */
2012-07-26 00:07:39 +02:00
b43_radio_write ( dev , R2057_RCCAL_START_R1_Q1_P1 , 0x55 ) ;
2014-07-01 16:19:07 +02:00
if ( ! b43_radio_wait_value ( dev , R2057_RCCAL_DONE_OSCCAP , 2 , 2 , 500 ,
2012-07-26 00:07:39 +02:00
5000000 ) )
b43dbg ( dev - > wl , " Radio 0x2057 rccal timeout \n " ) ;
2014-07-01 16:19:07 +02:00
usleep_range ( 35 , 70 ) ;
2012-07-26 00:07:39 +02:00
b43_radio_write ( dev , R2057_RCCAL_START_R1_Q1_P1 , 0x15 ) ;
2014-07-01 16:19:07 +02:00
usleep_range ( 70 , 140 ) ;
/* Setup cal */
2012-07-26 00:07:39 +02:00
if ( special ) {
b43_radio_write ( dev , R2057_RCCAL_MASTER , 0x69 ) ;
b43_radio_write ( dev , R2057_RCCAL_TRC0 , 0xB0 ) ;
} else {
2014-07-01 16:19:07 +02:00
b43_radio_write ( dev , R2057v7_RCCAL_MASTER , 0x69 ) ;
2012-07-26 00:07:39 +02:00
b43_radio_write ( dev , R2057_RCCAL_TRC0 , 0xD5 ) ;
}
b43_radio_write ( dev , R2057_RCCAL_X1 , 0x6E ) ;
2014-07-01 16:19:07 +02:00
/* Start, wait, stop */
usleep_range ( 35 , 70 ) ;
2012-07-26 00:07:39 +02:00
b43_radio_write ( dev , R2057_RCCAL_START_R1_Q1_P1 , 0x55 ) ;
2014-07-01 16:19:07 +02:00
usleep_range ( 70 , 140 ) ;
if ( ! b43_radio_wait_value ( dev , R2057_RCCAL_DONE_OSCCAP , 2 , 2 , 500 ,
2012-07-26 00:07:39 +02:00
5000000 ) )
2012-08-08 19:10:15 +02:00
b43dbg ( dev - > wl , " Radio 0x2057 rccal timeout \n " ) ;
2014-07-01 16:19:07 +02:00
usleep_range ( 35 , 70 ) ;
2012-07-26 00:07:39 +02:00
b43_radio_write ( dev , R2057_RCCAL_START_R1_Q1_P1 , 0x15 ) ;
2014-07-01 16:19:07 +02:00
usleep_range ( 70 , 140 ) ;
/* Setup cal */
2012-07-26 00:07:39 +02:00
if ( special ) {
b43_radio_write ( dev , R2057_RCCAL_MASTER , 0x73 ) ;
b43_radio_write ( dev , R2057_RCCAL_X1 , 0x28 ) ;
b43_radio_write ( dev , R2057_RCCAL_TRC0 , 0xB0 ) ;
} else {
2014-07-01 16:19:07 +02:00
b43_radio_write ( dev , R2057v7_RCCAL_MASTER , 0x73 ) ;
2012-07-26 00:07:39 +02:00
b43_radio_write ( dev , R2057_RCCAL_X1 , 0x6E ) ;
b43_radio_write ( dev , R2057_RCCAL_TRC0 , 0x99 ) ;
}
2014-07-01 16:19:07 +02:00
/* Start, wait, stop */
usleep_range ( 35 , 70 ) ;
2012-07-26 00:07:39 +02:00
b43_radio_write ( dev , R2057_RCCAL_START_R1_Q1_P1 , 0x55 ) ;
2014-07-01 16:19:07 +02:00
usleep_range ( 70 , 140 ) ;
if ( ! b43_radio_wait_value ( dev , R2057_RCCAL_DONE_OSCCAP , 2 , 2 , 500 ,
2012-07-26 00:07:39 +02:00
5000000 ) ) {
b43err ( dev - > wl , " Radio 0x2057 rcal timeout \n " ) ;
return 0 ;
}
tmp = b43_radio_read ( dev , R2057_RCCAL_DONE_OSCCAP ) ;
2014-07-01 16:19:07 +02:00
usleep_range ( 35 , 70 ) ;
2012-07-26 00:07:39 +02:00
b43_radio_write ( dev , R2057_RCCAL_START_R1_Q1_P1 , 0x15 ) ;
2014-07-01 16:19:07 +02:00
usleep_range ( 70 , 140 ) ;
if ( special )
b43_radio_mask ( dev , R2057_RCCAL_MASTER , ~ 0x1 ) ;
else
b43_radio_mask ( dev , R2057v7_RCCAL_MASTER , ~ 0x1 ) ;
2012-07-26 00:07:39 +02:00
return tmp ;
}
static void b43_radio_2057_init_pre ( struct b43_wldev * dev )
{
b43_phy_mask ( dev , B43_NPHY_RFCTL_CMD , ~ B43_NPHY_RFCTL_CMD_CHIP0PU ) ;
/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
b43_phy_mask ( dev , B43_NPHY_RFCTL_CMD , B43_NPHY_RFCTL_CMD_OEPORFORCE ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD , ~ B43_NPHY_RFCTL_CMD_OEPORFORCE ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD , B43_NPHY_RFCTL_CMD_CHIP0PU ) ;
}
static void b43_radio_2057_init_post ( struct b43_wldev * dev )
{
b43_radio_set ( dev , R2057_XTALPUOVR_PINCTRL , 0x1 ) ;
2014-07-17 19:31:03 +02:00
if ( 0 ) /* FIXME: Is this BCM43217 specific? */
b43_radio_set ( dev , R2057_XTALPUOVR_PINCTRL , 0x2 ) ;
2012-07-26 00:07:39 +02:00
b43_radio_set ( dev , R2057_RFPLL_MISC_CAL_RESETN , 0x78 ) ;
b43_radio_set ( dev , R2057_XTAL_CONFIG2 , 0x80 ) ;
mdelay ( 2 ) ;
b43_radio_mask ( dev , R2057_RFPLL_MISC_CAL_RESETN , ~ 0x78 ) ;
b43_radio_mask ( dev , R2057_XTAL_CONFIG2 , ~ 0x80 ) ;
2014-05-27 22:07:32 +02:00
if ( dev - > phy . do_full_init ) {
2012-07-26 00:07:39 +02:00
b43_radio_2057_rcal ( dev ) ;
b43_radio_2057_rccal ( dev ) ;
}
b43_radio_mask ( dev , R2057_RFPLL_MASTER , ~ 0x8 ) ;
}
/* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
static void b43_radio_2057_init ( struct b43_wldev * dev )
{
b43_radio_2057_init_pre ( dev ) ;
r2057_upload_inittabs ( dev ) ;
b43_radio_2057_init_post ( dev ) ;
}
2011-12-17 13:57:20 +01:00
/**************************************************
2011-12-17 13:57:21 +01:00
* Radio 0x2056
2011-12-17 13:57:20 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-02-27 13:03:39 +01:00
2010-12-21 23:57:48 +01:00
static void b43_chantab_radio_2056_upload ( struct b43_wldev * dev ,
const struct b43_nphy_channeltab_entry_rev3 * e )
2008-01-13 21:23:44 +01:00
{
2010-12-21 23:57:48 +01:00
b43_radio_write ( dev , B2056_SYN_PLL_VCOCAL1 , e - > radio_syn_pll_vcocal1 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_VCOCAL2 , e - > radio_syn_pll_vcocal2 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_REFDIV , e - > radio_syn_pll_refdiv ) ;
b43_radio_write ( dev , B2056_SYN_PLL_MMD2 , e - > radio_syn_pll_mmd2 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_MMD1 , e - > radio_syn_pll_mmd1 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER1 ,
e - > radio_syn_pll_loopfilter1 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER2 ,
e - > radio_syn_pll_loopfilter2 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER3 ,
e - > radio_syn_pll_loopfilter3 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER4 ,
e - > radio_syn_pll_loopfilter4 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER5 ,
e - > radio_syn_pll_loopfilter5 ) ;
b43_radio_write ( dev , B2056_SYN_RESERVED_ADDR27 ,
e - > radio_syn_reserved_addr27 ) ;
b43_radio_write ( dev , B2056_SYN_RESERVED_ADDR28 ,
e - > radio_syn_reserved_addr28 ) ;
b43_radio_write ( dev , B2056_SYN_RESERVED_ADDR29 ,
e - > radio_syn_reserved_addr29 ) ;
b43_radio_write ( dev , B2056_SYN_LOGEN_VCOBUF1 ,
e - > radio_syn_logen_vcobuf1 ) ;
b43_radio_write ( dev , B2056_SYN_LOGEN_MIXER2 , e - > radio_syn_logen_mixer2 ) ;
b43_radio_write ( dev , B2056_SYN_LOGEN_BUF3 , e - > radio_syn_logen_buf3 ) ;
b43_radio_write ( dev , B2056_SYN_LOGEN_BUF4 , e - > radio_syn_logen_buf4 ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_LNAA_TUNE ,
e - > radio_rx0_lnaa_tune ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_LNAG_TUNE ,
e - > radio_rx0_lnag_tune ) ;
b43_radio_write ( dev , B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE ,
e - > radio_tx0_intpaa_boost_tune ) ;
b43_radio_write ( dev , B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE ,
e - > radio_tx0_intpag_boost_tune ) ;
b43_radio_write ( dev , B2056_TX0 | B2056_TX_PADA_BOOST_TUNE ,
e - > radio_tx0_pada_boost_tune ) ;
b43_radio_write ( dev , B2056_TX0 | B2056_TX_PADG_BOOST_TUNE ,
e - > radio_tx0_padg_boost_tune ) ;
b43_radio_write ( dev , B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE ,
e - > radio_tx0_pgaa_boost_tune ) ;
b43_radio_write ( dev , B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE ,
e - > radio_tx0_pgag_boost_tune ) ;
b43_radio_write ( dev , B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE ,
e - > radio_tx0_mixa_boost_tune ) ;
b43_radio_write ( dev , B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE ,
e - > radio_tx0_mixg_boost_tune ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_LNAA_TUNE ,
e - > radio_rx1_lnaa_tune ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_LNAG_TUNE ,
e - > radio_rx1_lnag_tune ) ;
b43_radio_write ( dev , B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE ,
e - > radio_tx1_intpaa_boost_tune ) ;
b43_radio_write ( dev , B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE ,
e - > radio_tx1_intpag_boost_tune ) ;
b43_radio_write ( dev , B2056_TX1 | B2056_TX_PADA_BOOST_TUNE ,
e - > radio_tx1_pada_boost_tune ) ;
b43_radio_write ( dev , B2056_TX1 | B2056_TX_PADG_BOOST_TUNE ,
e - > radio_tx1_padg_boost_tune ) ;
b43_radio_write ( dev , B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE ,
e - > radio_tx1_pgaa_boost_tune ) ;
b43_radio_write ( dev , B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE ,
e - > radio_tx1_pgag_boost_tune ) ;
b43_radio_write ( dev , B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE ,
e - > radio_tx1_mixa_boost_tune ) ;
b43_radio_write ( dev , B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE ,
e - > radio_tx1_mixg_boost_tune ) ;
2008-01-13 21:23:44 +01:00
}
2010-12-21 23:57:48 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
static void b43_radio_2056_setup ( struct b43_wldev * dev ,
const struct b43_nphy_channeltab_entry_rev3 * e )
2008-01-13 21:23:44 +01:00
{
2014-05-31 20:49:39 +02:00
struct b43_phy * phy = & dev - > phy ;
2011-05-18 02:06:39 +02:00
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
2011-12-11 02:55:34 +01:00
enum ieee80211_band band = b43_current_band ( dev - > wl ) ;
u16 offset ;
u8 i ;
2012-07-26 00:07:38 +02:00
u16 bias , cbias ;
u16 pag_boost , padg_boost , pgag_boost , mixg_boost ;
u16 paa_boost , pada_boost , pgaa_boost , mixa_boost ;
2014-04-26 20:56:05 +02:00
bool is_pkg_fab_smic ;
2010-02-27 13:03:36 +01:00
2010-12-21 23:57:48 +01:00
B43_WARN_ON ( dev - > phy . rev < 3 ) ;
2008-01-13 21:23:44 +01:00
2014-04-26 20:56:05 +02:00
is_pkg_fab_smic =
( ( dev - > dev - > chip_id = = BCMA_CHIP_ID_BCM43224 | |
dev - > dev - > chip_id = = BCMA_CHIP_ID_BCM43225 | |
dev - > dev - > chip_id = = BCMA_CHIP_ID_BCM43421 ) & &
dev - > dev - > chip_pkg = = BCMA_PKG_ID_BCM43224_FAB_SMIC ) ;
2010-12-21 23:57:48 +01:00
b43_chantab_radio_2056_upload ( dev , e ) ;
2011-12-11 02:55:34 +01:00
b2056_upload_syn_pll_cp2 ( dev , band = = IEEE80211_BAND_5GHZ ) ;
if ( sprom - > boardflags2_lo & B43_BFL2_GPLL_WAR & &
b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER1 , 0x1F ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER2 , 0x1F ) ;
2014-04-26 20:56:05 +02:00
if ( dev - > dev - > chip_id = = BCMA_CHIP_ID_BCM4716 | |
dev - > dev - > chip_id = = BCMA_CHIP_ID_BCM47162 ) {
2011-12-11 02:55:34 +01:00
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER4 , 0x14 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_CP2 , 0 ) ;
} else {
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER4 , 0x0B ) ;
b43_radio_write ( dev , B2056_SYN_PLL_CP2 , 0x14 ) ;
2010-02-27 13:03:36 +01:00
}
2008-01-13 21:23:44 +01:00
}
2014-04-26 20:56:05 +02:00
if ( sprom - > boardflags2_hi & B43_BFH2_GPLL_WAR2 & &
b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER1 , 0x1f ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER2 , 0x1f ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER4 , 0x0b ) ;
b43_radio_write ( dev , B2056_SYN_PLL_CP2 , 0x20 ) ;
}
2011-12-11 02:55:34 +01:00
if ( sprom - > boardflags2_lo & B43_BFL2_APLL_WAR & &
b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER1 , 0x1F ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER2 , 0x1F ) ;
b43_radio_write ( dev , B2056_SYN_PLL_LOOPFILTER4 , 0x05 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_CP2 , 0x0C ) ;
2010-02-27 13:03:36 +01:00
}
2008-01-13 21:23:44 +01:00
2011-12-11 02:55:34 +01:00
if ( dev - > phy . n - > ipa2g_on & & band = = IEEE80211_BAND_2GHZ ) {
for ( i = 0 ; i < 2 ; i + + ) {
offset = i ? B2056_TX1 : B2056_TX0 ;
if ( dev - > phy . rev > = 5 ) {
b43_radio_write ( dev ,
offset | B2056_TX_PADG_IDAC , 0xcc ) ;
2014-04-26 20:56:05 +02:00
if ( dev - > dev - > chip_id = = BCMA_CHIP_ID_BCM4716 | |
dev - > dev - > chip_id = = BCMA_CHIP_ID_BCM47162 ) {
2011-12-11 02:55:34 +01:00
bias = 0x40 ;
cbias = 0x45 ;
pag_boost = 0x5 ;
pgag_boost = 0x33 ;
mixg_boost = 0x55 ;
} else {
bias = 0x25 ;
cbias = 0x20 ;
2014-04-26 20:56:05 +02:00
if ( is_pkg_fab_smic ) {
bias = 0x2a ;
cbias = 0x38 ;
}
2011-12-11 02:55:34 +01:00
pag_boost = 0x4 ;
pgag_boost = 0x03 ;
mixg_boost = 0x65 ;
}
padg_boost = 0x77 ;
b43_radio_write ( dev ,
offset | B2056_TX_INTPAG_IMAIN_STAT ,
bias ) ;
b43_radio_write ( dev ,
offset | B2056_TX_INTPAG_IAUX_STAT ,
bias ) ;
b43_radio_write ( dev ,
offset | B2056_TX_INTPAG_CASCBIAS ,
cbias ) ;
b43_radio_write ( dev ,
offset | B2056_TX_INTPAG_BOOST_TUNE ,
pag_boost ) ;
b43_radio_write ( dev ,
offset | B2056_TX_PGAG_BOOST_TUNE ,
pgag_boost ) ;
b43_radio_write ( dev ,
offset | B2056_TX_PADG_BOOST_TUNE ,
padg_boost ) ;
b43_radio_write ( dev ,
offset | B2056_TX_MIXG_BOOST_TUNE ,
mixg_boost ) ;
} else {
2014-05-31 20:49:40 +02:00
bias = b43_is_40mhz ( dev ) ? 0x40 : 0x20 ;
2011-12-11 02:55:34 +01:00
b43_radio_write ( dev ,
offset | B2056_TX_INTPAG_IMAIN_STAT ,
bias ) ;
b43_radio_write ( dev ,
offset | B2056_TX_INTPAG_IAUX_STAT ,
bias ) ;
b43_radio_write ( dev ,
offset | B2056_TX_INTPAG_CASCBIAS ,
0x30 ) ;
}
b43_radio_write ( dev , offset | B2056_TX_PA_SPARE1 , 0xee ) ;
}
} else if ( dev - > phy . n - > ipa5g_on & & band = = IEEE80211_BAND_5GHZ ) {
2014-05-31 20:49:39 +02:00
u16 freq = phy - > chandef - > chan - > center_freq ;
2012-07-26 00:07:38 +02:00
if ( freq < 5100 ) {
paa_boost = 0xA ;
pada_boost = 0x77 ;
pgaa_boost = 0xF ;
mixa_boost = 0xF ;
} else if ( freq < 5340 ) {
paa_boost = 0x8 ;
pada_boost = 0x77 ;
pgaa_boost = 0xFB ;
mixa_boost = 0xF ;
} else if ( freq < 5650 ) {
paa_boost = 0x0 ;
pada_boost = 0x77 ;
pgaa_boost = 0xB ;
mixa_boost = 0xF ;
} else {
paa_boost = 0x0 ;
pada_boost = 0x77 ;
if ( freq ! = 5825 )
pgaa_boost = - ( freq - 18 ) / 36 + 168 ;
else
pgaa_boost = 6 ;
mixa_boost = 0xF ;
}
2014-04-26 20:56:05 +02:00
cbias = is_pkg_fab_smic ? 0x35 : 0x30 ;
2012-07-26 00:07:38 +02:00
for ( i = 0 ; i < 2 ; i + + ) {
offset = i ? B2056_TX1 : B2056_TX0 ;
b43_radio_write ( dev ,
offset | B2056_TX_INTPAA_BOOST_TUNE , paa_boost ) ;
b43_radio_write ( dev ,
offset | B2056_TX_PADA_BOOST_TUNE , pada_boost ) ;
b43_radio_write ( dev ,
offset | B2056_TX_PGAA_BOOST_TUNE , pgaa_boost ) ;
b43_radio_write ( dev ,
offset | B2056_TX_MIXA_BOOST_TUNE , mixa_boost ) ;
b43_radio_write ( dev ,
offset | B2056_TX_TXSPARE1 , 0x30 ) ;
b43_radio_write ( dev ,
offset | B2056_TX_PA_SPARE2 , 0xee ) ;
b43_radio_write ( dev ,
offset | B2056_TX_PADA_CASCBIAS , 0x03 ) ;
b43_radio_write ( dev ,
2014-04-26 20:56:05 +02:00
offset | B2056_TX_INTPAA_IAUX_STAT , 0x30 ) ;
2012-07-26 00:07:38 +02:00
b43_radio_write ( dev ,
2014-04-26 20:56:05 +02:00
offset | B2056_TX_INTPAA_IMAIN_STAT , 0x30 ) ;
2012-07-26 00:07:38 +02:00
b43_radio_write ( dev ,
2014-04-26 20:56:05 +02:00
offset | B2056_TX_INTPAA_CASCBIAS , cbias ) ;
2012-07-26 00:07:38 +02:00
}
2010-10-22 17:43:49 +02:00
}
2011-12-11 02:55:34 +01:00
2010-12-21 23:57:48 +01:00
udelay ( 50 ) ;
/* VCO calibration */
b43_radio_write ( dev , B2056_SYN_PLL_VCOCAL12 , 0x00 ) ;
b43_radio_write ( dev , B2056_TX_INTPAA_PA_MISC , 0x38 ) ;
b43_radio_write ( dev , B2056_TX_INTPAA_PA_MISC , 0x18 ) ;
b43_radio_write ( dev , B2056_TX_INTPAA_PA_MISC , 0x38 ) ;
b43_radio_write ( dev , B2056_TX_INTPAA_PA_MISC , 0x39 ) ;
udelay ( 300 ) ;
2008-01-13 21:23:44 +01:00
}
2012-07-26 00:07:38 +02:00
static u8 b43_radio_2056_rcal ( struct b43_wldev * dev )
{
struct b43_phy * phy = & dev - > phy ;
u16 mast2 , tmp ;
if ( phy - > rev ! = 3 )
return 0 ;
mast2 = b43_radio_read ( dev , B2056_SYN_PLL_MAST2 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_MAST2 , mast2 | 0x7 ) ;
udelay ( 10 ) ;
b43_radio_write ( dev , B2056_SYN_RCAL_MASTER , 0x01 ) ;
udelay ( 10 ) ;
b43_radio_write ( dev , B2056_SYN_RCAL_MASTER , 0x09 ) ;
if ( ! b43_radio_wait_value ( dev , B2056_SYN_RCAL_CODE_OUT , 0x80 , 0x80 , 100 ,
1000000 ) ) {
b43err ( dev - > wl , " Radio recalibration timeout \n " ) ;
return 0 ;
}
b43_radio_write ( dev , B2056_SYN_RCAL_MASTER , 0x01 ) ;
tmp = b43_radio_read ( dev , B2056_SYN_RCAL_CODE_OUT ) ;
b43_radio_write ( dev , B2056_SYN_RCAL_MASTER , 0x00 ) ;
b43_radio_write ( dev , B2056_SYN_PLL_MAST2 , mast2 ) ;
return tmp & 0x1f ;
}
2010-12-21 17:13:44 +01:00
static void b43_radio_init2056_pre ( struct b43_wldev * dev )
{
b43_phy_mask ( dev , B43_NPHY_RFCTL_CMD ,
~ B43_NPHY_RFCTL_CMD_CHIP0PU ) ;
/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
b43_phy_mask ( dev , B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_CMD_OEPORFORCE ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD ,
~ B43_NPHY_RFCTL_CMD_OEPORFORCE ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_CMD_CHIP0PU ) ;
}
static void b43_radio_init2056_post ( struct b43_wldev * dev )
{
b43_radio_set ( dev , B2056_SYN_COM_CTRL , 0xB ) ;
b43_radio_set ( dev , B2056_SYN_COM_PU , 0x2 ) ;
b43_radio_set ( dev , B2056_SYN_COM_RESET , 0x2 ) ;
msleep ( 1 ) ;
b43_radio_mask ( dev , B2056_SYN_COM_RESET , ~ 0x2 ) ;
b43_radio_mask ( dev , B2056_SYN_PLL_MAST2 , ~ 0xFC ) ;
b43_radio_mask ( dev , B2056_SYN_RCCAL_CTRL0 , ~ 0x1 ) ;
2014-05-27 22:07:32 +02:00
if ( dev - > phy . do_full_init )
2012-07-26 00:07:38 +02:00
b43_radio_2056_rcal ( dev ) ;
2010-12-21 17:13:44 +01:00
}
2010-03-29 00:53:12 +02:00
/*
* Initialize a Broadcom 2056 N - radio
* http : //bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
*/
static void b43_radio_init2056 ( struct b43_wldev * dev )
{
2010-12-21 17:13:44 +01:00
b43_radio_init2056_pre ( dev ) ;
b2056_upload_inittabs ( dev , 0 , 0 ) ;
b43_radio_init2056_post ( dev ) ;
2010-03-29 00:53:12 +02:00
}
2011-12-17 13:57:21 +01:00
/**************************************************
* Radio 0x2055
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void b43_chantab_radio_upload ( struct b43_wldev * dev ,
const struct b43_nphy_channeltab_entry_rev2 * e )
2008-01-18 01:09:25 +01:00
{
2011-12-17 13:57:21 +01:00
b43_radio_write ( dev , B2055_PLL_REF , e - > radio_pll_ref ) ;
b43_radio_write ( dev , B2055_RF_PLLMOD0 , e - > radio_rf_pllmod0 ) ;
b43_radio_write ( dev , B2055_RF_PLLMOD1 , e - > radio_rf_pllmod1 ) ;
b43_radio_write ( dev , B2055_VCO_CAPTAIL , e - > radio_vco_captail ) ;
b43_read32 ( dev , B43_MMIO_MACCTL ) ; /* flush writes */
2008-01-18 01:09:25 +01:00
2011-12-17 13:57:21 +01:00
b43_radio_write ( dev , B2055_VCO_CAL1 , e - > radio_vco_cal1 ) ;
b43_radio_write ( dev , B2055_VCO_CAL2 , e - > radio_vco_cal2 ) ;
b43_radio_write ( dev , B2055_PLL_LFC1 , e - > radio_pll_lfc1 ) ;
b43_radio_write ( dev , B2055_PLL_LFR1 , e - > radio_pll_lfr1 ) ;
b43_read32 ( dev , B43_MMIO_MACCTL ) ; /* flush writes */
2010-01-15 15:02:38 +01:00
2011-12-17 13:57:21 +01:00
b43_radio_write ( dev , B2055_PLL_LFC2 , e - > radio_pll_lfc2 ) ;
b43_radio_write ( dev , B2055_LGBUF_CENBUF , e - > radio_lgbuf_cenbuf ) ;
b43_radio_write ( dev , B2055_LGEN_TUNE1 , e - > radio_lgen_tune1 ) ;
b43_radio_write ( dev , B2055_LGEN_TUNE2 , e - > radio_lgen_tune2 ) ;
b43_read32 ( dev , B43_MMIO_MACCTL ) ; /* flush writes */
2010-01-15 15:02:38 +01:00
2011-12-17 13:57:21 +01:00
b43_radio_write ( dev , B2055_C1_LGBUF_ATUNE , e - > radio_c1_lgbuf_atune ) ;
b43_radio_write ( dev , B2055_C1_LGBUF_GTUNE , e - > radio_c1_lgbuf_gtune ) ;
b43_radio_write ( dev , B2055_C1_RX_RFR1 , e - > radio_c1_rx_rfr1 ) ;
b43_radio_write ( dev , B2055_C1_TX_PGAPADTN , e - > radio_c1_tx_pgapadtn ) ;
b43_read32 ( dev , B43_MMIO_MACCTL ) ; /* flush writes */
2010-01-15 15:51:55 +01:00
2011-12-17 13:57:21 +01:00
b43_radio_write ( dev , B2055_C1_TX_MXBGTRIM , e - > radio_c1_tx_mxbgtrim ) ;
b43_radio_write ( dev , B2055_C2_LGBUF_ATUNE , e - > radio_c2_lgbuf_atune ) ;
b43_radio_write ( dev , B2055_C2_LGBUF_GTUNE , e - > radio_c2_lgbuf_gtune ) ;
b43_radio_write ( dev , B2055_C2_RX_RFR1 , e - > radio_c2_rx_rfr1 ) ;
b43_read32 ( dev , B43_MMIO_MACCTL ) ; /* flush writes */
2010-01-15 15:51:55 +01:00
2011-12-17 13:57:21 +01:00
b43_radio_write ( dev , B2055_C2_TX_PGAPADTN , e - > radio_c2_tx_pgapadtn ) ;
b43_radio_write ( dev , B2055_C2_TX_MXBGTRIM , e - > radio_c2_tx_mxbgtrim ) ;
2010-01-15 15:51:55 +01:00
}
2011-12-17 13:57:21 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
static void b43_radio_2055_setup ( struct b43_wldev * dev ,
const struct b43_nphy_channeltab_entry_rev2 * e )
2008-01-18 01:09:25 +01:00
{
2011-12-17 13:57:21 +01:00
B43_WARN_ON ( dev - > phy . rev > = 3 ) ;
2008-01-18 01:09:25 +01:00
2011-12-17 13:57:21 +01:00
b43_chantab_radio_upload ( dev , e ) ;
udelay ( 50 ) ;
b43_radio_write ( dev , B2055_VCO_CAL10 , 0x05 ) ;
b43_radio_write ( dev , B2055_VCO_CAL10 , 0x45 ) ;
b43_read32 ( dev , B43_MMIO_MACCTL ) ; /* flush writes */
b43_radio_write ( dev , B2055_VCO_CAL10 , 0x65 ) ;
udelay ( 300 ) ;
2008-01-18 01:09:25 +01:00
}
2011-12-17 13:57:21 +01:00
static void b43_radio_init2055_pre ( struct b43_wldev * dev )
2010-01-17 13:03:40 +01:00
{
2011-12-17 13:57:21 +01:00
b43_phy_mask ( dev , B43_NPHY_RFCTL_CMD ,
~ B43_NPHY_RFCTL_CMD_PORFORCE ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_CMD_CHIP0PU |
B43_NPHY_RFCTL_CMD_OEPORFORCE ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_CMD_PORFORCE ) ;
2010-01-17 13:03:40 +01:00
}
2011-12-17 13:57:21 +01:00
static void b43_radio_init2055_post ( struct b43_wldev * dev )
2010-01-17 13:03:55 +01:00
{
struct b43_phy_n * nphy = dev - > phy . n ;
2011-12-17 13:57:21 +01:00
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
bool workaround = false ;
2010-01-15 15:26:12 +01:00
2011-12-17 13:57:21 +01:00
if ( sprom - > revision < 4 )
workaround = ( dev - > dev - > board_vendor ! = PCI_VENDOR_ID_BROADCOM
2013-03-28 22:25:38 +01:00
& & dev - > dev - > board_type = = SSB_BOARD_CB2_4321
2011-12-17 13:57:21 +01:00
& & dev - > dev - > board_rev > = 0x41 ) ;
2010-01-15 15:26:12 +01:00
else
2011-12-17 13:57:21 +01:00
workaround =
! ( sprom - > boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS ) ;
2010-01-15 15:26:12 +01:00
2011-12-17 13:57:21 +01:00
b43_radio_mask ( dev , B2055_MASTER1 , 0xFFF3 ) ;
if ( workaround ) {
b43_radio_mask ( dev , B2055_C1_RX_BB_REG , 0x7F ) ;
b43_radio_mask ( dev , B2055_C2_RX_BB_REG , 0x7F ) ;
}
b43_radio_maskset ( dev , B2055_RRCCAL_NOPTSEL , 0xFFC0 , 0x2C ) ;
b43_radio_write ( dev , B2055_CAL_MISC , 0x3C ) ;
b43_radio_mask ( dev , B2055_CAL_MISC , 0xFFBE ) ;
b43_radio_set ( dev , B2055_CAL_LPOCTL , 0x80 ) ;
b43_radio_set ( dev , B2055_CAL_MISC , 0x1 ) ;
msleep ( 1 ) ;
b43_radio_set ( dev , B2055_CAL_MISC , 0x40 ) ;
2012-07-26 00:07:37 +02:00
if ( ! b43_radio_wait_value ( dev , B2055_CAL_COUT2 , 0x80 , 0x80 , 10 , 2000 ) )
2011-12-17 13:57:21 +01:00
b43err ( dev - > wl , " radio post init timeout \n " ) ;
b43_radio_mask ( dev , B2055_CAL_LPOCTL , 0xFF7F ) ;
b43_switch_channel ( dev , dev - > phy . channel ) ;
b43_radio_write ( dev , B2055_C1_RX_BB_LPF , 0x9 ) ;
b43_radio_write ( dev , B2055_C2_RX_BB_LPF , 0x9 ) ;
b43_radio_write ( dev , B2055_C1_RX_BB_MIDACHP , 0x83 ) ;
b43_radio_write ( dev , B2055_C2_RX_BB_MIDACHP , 0x83 ) ;
b43_radio_maskset ( dev , B2055_C1_LNA_GAINBST , 0xFFF8 , 0x6 ) ;
b43_radio_maskset ( dev , B2055_C2_LNA_GAINBST , 0xFFF8 , 0x6 ) ;
if ( ! nphy - > gain_boost ) {
b43_radio_set ( dev , B2055_C1_RX_RFSPC1 , 0x2 ) ;
b43_radio_set ( dev , B2055_C2_RX_RFSPC1 , 0x2 ) ;
} else {
b43_radio_mask ( dev , B2055_C1_RX_RFSPC1 , 0xFFFD ) ;
b43_radio_mask ( dev , B2055_C2_RX_RFSPC1 , 0xFFFD ) ;
}
udelay ( 2 ) ;
2010-01-15 15:26:12 +01:00
}
2011-12-17 13:57:21 +01:00
/*
* Initialize a Broadcom 2055 N - radio
* http : //bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
*/
static void b43_radio_init2055 ( struct b43_wldev * dev )
2010-01-15 15:16:25 +01:00
{
2011-12-17 13:57:21 +01:00
b43_radio_init2055_pre ( dev ) ;
if ( b43_status ( dev ) < B43_STAT_INITIALIZED ) {
/* Follow wl, not specs. Do not force uploading all regs */
b2055_upload_inittab ( dev , 0 , 0 ) ;
2010-01-15 15:16:25 +01:00
} else {
2011-12-17 13:57:21 +01:00
bool ghz5 = b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ;
b2055_upload_inittab ( dev , ghz5 , 0 ) ;
2010-01-15 15:16:25 +01:00
}
2011-12-17 13:57:21 +01:00
b43_radio_init2055_post ( dev ) ;
2010-01-15 15:16:25 +01:00
}
2011-12-17 13:57:22 +01:00
/**************************************************
* Samples
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-01-17 13:03:28 +01:00
2011-12-17 13:57:22 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
static int b43_nphy_load_samples ( struct b43_wldev * dev ,
struct b43_c32 * samples , u16 len ) {
struct b43_phy_n * nphy = dev - > phy . n ;
u16 i ;
u32 * data ;
data = kzalloc ( len * sizeof ( u32 ) , GFP_KERNEL ) ;
if ( ! data ) {
b43err ( dev - > wl , " allocation for samples loading failed \n " ) ;
return - ENOMEM ;
}
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 1 ) ;
for ( i = 0 ; i < len ; i + + ) {
data [ i ] = ( samples [ i ] . i & 0x3FF < < 10 ) ;
data [ i ] | = samples [ i ] . q & 0x3FF ;
}
b43_ntab_write_bulk ( dev , B43_NTAB32 ( 17 , 0 ) , len , data ) ;
kfree ( data ) ;
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 0 ) ;
return 0 ;
2010-01-17 13:03:28 +01:00
}
2011-12-17 13:57:22 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
static u16 b43_nphy_gen_load_samples ( struct b43_wldev * dev , u32 freq , u16 max ,
bool test )
2010-01-17 13:03:28 +01:00
{
2011-12-17 13:57:22 +01:00
int i ;
u16 bw , len , rot , angle ;
struct b43_c32 * samples ;
2010-01-17 13:03:28 +01:00
2014-05-31 20:49:40 +02:00
bw = b43_is_40mhz ( dev ) ? 40 : 20 ;
2011-12-17 13:57:22 +01:00
len = bw < < 3 ;
2010-01-17 13:03:28 +01:00
2011-12-17 13:57:22 +01:00
if ( test ) {
if ( b43_phy_read ( dev , B43_NPHY_BBCFG ) & B43_NPHY_BBCFG_RSTRX )
bw = 82 ;
else
bw = 80 ;
2010-01-17 13:03:28 +01:00
2014-05-31 20:49:40 +02:00
if ( b43_is_40mhz ( dev ) )
2011-12-17 13:57:22 +01:00
bw < < = 1 ;
len = bw < < 1 ;
2010-01-17 13:03:28 +01:00
}
2011-12-17 13:57:22 +01:00
samples = kcalloc ( len , sizeof ( struct b43_c32 ) , GFP_KERNEL ) ;
if ( ! samples ) {
b43err ( dev - > wl , " allocation for samples generation failed \n " ) ;
return 0 ;
}
rot = ( ( ( freq * 36 ) / bw ) < < 16 ) / 100 ;
angle = 0 ;
2010-01-17 13:03:28 +01:00
2011-12-17 13:57:22 +01:00
for ( i = 0 ; i < len ; i + + ) {
samples [ i ] = b43_cordic ( angle ) ;
angle + = rot ;
samples [ i ] . q = CORDIC_CONVERT ( samples [ i ] . q * max ) ;
samples [ i ] . i = CORDIC_CONVERT ( samples [ i ] . i * max ) ;
2010-01-17 13:03:28 +01:00
}
2011-12-17 13:57:22 +01:00
i = b43_nphy_load_samples ( dev , samples , len ) ;
kfree ( samples ) ;
return ( i < 0 ) ? 0 : len ;
2010-01-17 13:03:28 +01:00
}
2011-12-17 13:57:22 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
static void b43_nphy_run_samples ( struct b43_wldev * dev , u16 samps , u16 loops ,
2014-06-22 23:18:21 +02:00
u16 wait , bool iqmode , bool dac_test ,
bool modify_bbmult )
2010-01-15 15:29:05 +01:00
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2011-12-17 13:57:22 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
2010-01-15 15:29:05 +01:00
int i ;
2011-12-17 13:57:22 +01:00
u16 seq_mode ;
u32 tmp ;
2010-01-15 15:29:05 +01:00
2014-04-20 13:05:45 +02:00
b43_nphy_stay_in_carrier_search ( dev , true ) ;
2010-01-15 15:29:05 +01:00
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 7 ) {
2014-07-08 15:11:07 +02:00
bool lpf_bw3 , lpf_bw4 ;
lpf_bw3 = b43_phy_read ( dev , B43_NPHY_REV7_RF_CTL_OVER3 ) & 0x80 ;
2014-07-22 21:31:05 +02:00
lpf_bw4 = b43_phy_read ( dev , B43_NPHY_REV7_RF_CTL_OVER4 ) & 0x80 ;
2014-07-08 15:11:07 +02:00
if ( lpf_bw3 | | lpf_bw4 ) {
/* TODO */
} else {
u16 value = b43_nphy_read_lpf_ctl ( dev , 0 ) ;
if ( phy - > rev > = 19 )
b43_nphy_rf_ctl_override_rev19 ( dev , 0x80 , value ,
0 , false , 1 ) ;
else
b43_nphy_rf_ctl_override_rev7 ( dev , 0x80 , value ,
0 , false , 1 ) ;
nphy - > lpf_bw_overrode_for_sample_play = true ;
}
2014-07-08 15:11:06 +02:00
}
2011-12-17 13:57:22 +01:00
if ( ( nphy - > bb_mult_save & 0x80000000 ) = = 0 ) {
tmp = b43_ntab_read ( dev , B43_NTAB16 ( 15 , 87 ) ) ;
nphy - > bb_mult_save = ( tmp & 0xFFFF ) | 0x80000000 ;
}
2010-01-15 15:29:05 +01:00
2014-06-22 23:18:21 +02:00
if ( modify_bbmult ) {
tmp = ! b43_is_40mhz ( dev ) ? 0x6464 : 0x4747 ;
b43_ntab_write ( dev , B43_NTAB16 ( 15 , 87 ) , tmp ) ;
}
2010-01-15 15:29:05 +01:00
2011-12-17 13:57:22 +01:00
b43_phy_write ( dev , B43_NPHY_SAMP_DEPCNT , ( samps - 1 ) ) ;
2010-01-15 15:29:05 +01:00
2011-12-17 13:57:22 +01:00
if ( loops ! = 0xFFFF )
b43_phy_write ( dev , B43_NPHY_SAMP_LOOPCNT , ( loops - 1 ) ) ;
else
b43_phy_write ( dev , B43_NPHY_SAMP_LOOPCNT , loops ) ;
2010-01-15 15:29:05 +01:00
2011-12-17 13:57:22 +01:00
b43_phy_write ( dev , B43_NPHY_SAMP_WAITCNT , wait ) ;
2010-01-15 15:29:05 +01:00
2011-12-17 13:57:22 +01:00
seq_mode = b43_phy_read ( dev , B43_NPHY_RFSEQMODE ) ;
2010-01-15 15:29:05 +01:00
2011-12-17 13:57:22 +01:00
b43_phy_set ( dev , B43_NPHY_RFSEQMODE , B43_NPHY_RFSEQMODE_CAOVER ) ;
if ( iqmode ) {
b43_phy_mask ( dev , B43_NPHY_IQLOCAL_CMDGCTL , 0x7FFF ) ;
b43_phy_set ( dev , B43_NPHY_IQLOCAL_CMDGCTL , 0x8000 ) ;
} else {
2014-06-22 23:18:21 +02:00
tmp = dac_test ? 5 : 1 ;
b43_phy_write ( dev , B43_NPHY_SAMP_CMD , tmp ) ;
2011-12-17 13:57:22 +01:00
}
for ( i = 0 ; i < 100 ; i + + ) {
2011-12-20 22:45:48 +01:00
if ( ! ( b43_phy_read ( dev , B43_NPHY_RFSEQST ) & 1 ) ) {
2011-12-17 13:57:22 +01:00
i = 0 ;
break ;
2010-01-15 15:29:05 +01:00
}
2011-12-17 13:57:22 +01:00
udelay ( 10 ) ;
2010-01-15 15:29:05 +01:00
}
2011-12-17 13:57:22 +01:00
if ( i )
b43err ( dev - > wl , " run samples timeout \n " ) ;
2010-01-15 15:29:05 +01:00
2011-12-17 13:57:22 +01:00
b43_phy_write ( dev , B43_NPHY_RFSEQMODE , seq_mode ) ;
2014-04-20 13:05:45 +02:00
b43_nphy_stay_in_carrier_search ( dev , false ) ;
2010-01-15 15:29:05 +01:00
}
2011-12-17 13:57:23 +01:00
/**************************************************
* RSSI
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
static void b43_nphy_scale_offset_rssi ( struct b43_wldev * dev , u16 scale ,
2013-03-20 16:51:39 +01:00
s8 offset , u8 core ,
enum n_rail_type rail ,
2013-03-20 17:30:38 +01:00
enum n_rssi_type rssi_type )
2010-01-15 15:17:10 +01:00
{
2011-12-17 13:57:23 +01:00
u16 tmp ;
bool core1or5 = ( core = = 1 ) | | ( core = = 5 ) ;
bool core2or5 = ( core = = 2 ) | | ( core = = 5 ) ;
2010-01-15 15:17:10 +01:00
2011-12-17 13:57:23 +01:00
offset = clamp_val ( offset , - 32 , 31 ) ;
tmp = ( ( scale & 0x3F ) < < 8 ) | ( offset & 0x3F ) ;
2010-01-15 15:17:10 +01:00
2013-03-20 16:57:04 +01:00
switch ( rssi_type ) {
2013-03-20 17:30:38 +01:00
case N_RSSI_NB :
2013-03-20 16:57:04 +01:00
if ( core1or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0I_RSSI_Z , tmp ) ;
if ( core1or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0Q_RSSI_Z , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1I_RSSI_Z , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1Q_RSSI_Z , tmp ) ;
break ;
2013-03-20 17:30:38 +01:00
case N_RSSI_W1 :
2013-03-20 16:57:04 +01:00
if ( core1or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0I_RSSI_X , tmp ) ;
if ( core1or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0Q_RSSI_X , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1I_RSSI_X , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1Q_RSSI_X , tmp ) ;
break ;
2013-03-20 17:30:38 +01:00
case N_RSSI_W2 :
2013-03-20 16:57:04 +01:00
if ( core1or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0I_RSSI_Y , tmp ) ;
if ( core1or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0Q_RSSI_Y , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1I_RSSI_Y , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1Q_RSSI_Y , tmp ) ;
break ;
2013-03-20 17:30:38 +01:00
case N_RSSI_TBD :
2013-03-20 16:57:04 +01:00
if ( core1or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0I_TBD , tmp ) ;
if ( core1or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0Q_TBD , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1I_TBD , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1Q_TBD , tmp ) ;
break ;
2013-03-20 17:30:38 +01:00
case N_RSSI_IQ :
2013-03-20 16:57:04 +01:00
if ( core1or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0I_PWRDET , tmp ) ;
if ( core1or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0Q_PWRDET , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_I )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1I_PWRDET , tmp ) ;
if ( core2or5 & & rail = = N_RAIL_Q )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1Q_PWRDET , tmp ) ;
break ;
2013-03-20 17:30:38 +01:00
case N_RSSI_TSSI_2G :
2013-03-20 16:57:04 +01:00
if ( core1or5 )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0I_TSSI , tmp ) ;
if ( core2or5 )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1I_TSSI , tmp ) ;
break ;
2013-03-20 17:30:38 +01:00
case N_RSSI_TSSI_5G :
2013-03-20 16:57:04 +01:00
if ( core1or5 )
b43_phy_write ( dev , B43_NPHY_RSSIMC_0Q_TSSI , tmp ) ;
if ( core2or5 )
b43_phy_write ( dev , B43_NPHY_RSSIMC_1Q_TSSI , tmp ) ;
break ;
}
2010-02-27 13:03:33 +01:00
}
2014-07-08 15:11:06 +02:00
static void b43_nphy_rssi_select_rev19 ( struct b43_wldev * dev , u8 code ,
enum n_rssi_type rssi_type )
{
/* TODO */
}
2013-03-20 18:24:47 +01:00
static void b43_nphy_rev3_rssi_select ( struct b43_wldev * dev , u8 code ,
enum n_rssi_type rssi_type )
2010-01-15 14:31:39 +01:00
{
2011-12-17 13:57:23 +01:00
u8 i ;
u16 reg , val ;
2010-01-15 14:31:39 +01:00
2011-12-17 13:57:23 +01:00
if ( code = = 0 ) {
b43_phy_mask ( dev , B43_NPHY_AFECTL_OVER1 , 0xFDFF ) ;
b43_phy_mask ( dev , B43_NPHY_AFECTL_OVER , 0xFDFF ) ;
b43_phy_mask ( dev , B43_NPHY_AFECTL_C1 , 0xFCFF ) ;
b43_phy_mask ( dev , B43_NPHY_AFECTL_C2 , 0xFCFF ) ;
b43_phy_mask ( dev , B43_NPHY_TXF_40CO_B1S0 , 0xFFDF ) ;
b43_phy_mask ( dev , B43_NPHY_TXF_40CO_B32S1 , 0xFFDF ) ;
b43_phy_mask ( dev , B43_NPHY_RFCTL_LUT_TRSW_UP1 , 0xFFC3 ) ;
b43_phy_mask ( dev , B43_NPHY_RFCTL_LUT_TRSW_UP2 , 0xFFC3 ) ;
} else {
for ( i = 0 ; i < 2 ; i + + ) {
if ( ( code = = 1 & & i = = 1 ) | | ( code = = 2 & & ! i ) )
continue ;
2010-01-15 14:31:39 +01:00
2011-12-17 13:57:23 +01:00
reg = ( i = = 0 ) ?
B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER ;
b43_phy_maskset ( dev , reg , 0xFDFF , 0x0200 ) ;
2010-01-15 14:31:39 +01:00
2013-03-20 18:24:47 +01:00
if ( rssi_type = = N_RSSI_W1 | |
rssi_type = = N_RSSI_W2 | |
rssi_type = = N_RSSI_NB ) {
2011-12-17 13:57:23 +01:00
reg = ( i = = 0 ) ?
B43_NPHY_AFECTL_C1 :
B43_NPHY_AFECTL_C2 ;
b43_phy_maskset ( dev , reg , 0xFCFF , 0 ) ;
2010-01-15 14:31:39 +01:00
2011-12-17 13:57:23 +01:00
reg = ( i = = 0 ) ?
B43_NPHY_RFCTL_LUT_TRSW_UP1 :
B43_NPHY_RFCTL_LUT_TRSW_UP2 ;
b43_phy_maskset ( dev , reg , 0xFFC3 , 0 ) ;
2010-01-15 14:31:39 +01:00
2013-03-20 18:24:47 +01:00
if ( rssi_type = = N_RSSI_W1 )
2011-12-17 13:57:23 +01:00
val = ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) ? 4 : 8 ;
2013-03-20 18:24:47 +01:00
else if ( rssi_type = = N_RSSI_W2 )
2011-12-17 13:57:23 +01:00
val = 16 ;
else
val = 32 ;
b43_phy_set ( dev , reg , val ) ;
2010-01-15 15:10:54 +01:00
2011-12-17 13:57:23 +01:00
reg = ( i = = 0 ) ?
B43_NPHY_TXF_40CO_B1S0 :
B43_NPHY_TXF_40CO_B32S1 ;
b43_phy_set ( dev , reg , 0x0020 ) ;
} else {
2013-03-20 18:24:47 +01:00
if ( rssi_type = = N_RSSI_TBD )
2011-12-17 13:57:23 +01:00
val = 0x0100 ;
2013-03-20 18:24:47 +01:00
else if ( rssi_type = = N_RSSI_IQ )
2011-12-17 13:57:23 +01:00
val = 0x0200 ;
else
val = 0x0300 ;
2010-01-15 15:10:54 +01:00
2011-12-17 13:57:23 +01:00
reg = ( i = = 0 ) ?
B43_NPHY_AFECTL_C1 :
B43_NPHY_AFECTL_C2 ;
2010-01-17 13:03:48 +01:00
2011-12-17 13:57:23 +01:00
b43_phy_maskset ( dev , reg , 0xFCFF , val ) ;
b43_phy_maskset ( dev , reg , 0xF3FF , val < < 2 ) ;
2010-01-17 13:03:48 +01:00
2013-03-20 18:24:47 +01:00
if ( rssi_type ! = N_RSSI_IQ & &
rssi_type ! = N_RSSI_TBD ) {
2011-12-17 13:57:23 +01:00
enum ieee80211_band band =
b43_current_band ( dev - > wl ) ;
2010-01-17 13:03:48 +01:00
2014-07-08 15:11:06 +02:00
if ( dev - > phy . rev < 7 ) {
if ( b43_nphy_ipa ( dev ) )
val = ( band = = IEEE80211_BAND_5GHZ ) ? 0xC : 0xE ;
else
val = 0x11 ;
reg = ( i = = 0 ) ? B2056_TX0 : B2056_TX1 ;
reg | = B2056_TX_TX_SSI_MUX ;
b43_radio_write ( dev , reg , val ) ;
}
2010-01-17 13:03:48 +01:00
2011-12-17 13:57:23 +01:00
reg = ( i = = 0 ) ?
B43_NPHY_AFECTL_OVER1 :
B43_NPHY_AFECTL_OVER ;
b43_phy_set ( dev , reg , 0x0200 ) ;
}
}
}
2010-01-17 13:03:48 +01:00
}
}
2013-03-20 18:24:47 +01:00
static void b43_nphy_rev2_rssi_select ( struct b43_wldev * dev , u8 code ,
enum n_rssi_type rssi_type )
2010-02-04 12:23:12 +01:00
{
2011-12-17 13:57:23 +01:00
u16 val ;
2013-03-20 18:24:47 +01:00
bool rssi_w1_w2_nb = false ;
2010-02-04 12:23:12 +01:00
2013-03-20 18:24:47 +01:00
switch ( rssi_type ) {
case N_RSSI_W1 :
case N_RSSI_W2 :
case N_RSSI_NB :
2011-12-17 13:57:23 +01:00
val = 0 ;
2013-03-20 18:24:47 +01:00
rssi_w1_w2_nb = true ;
break ;
case N_RSSI_TBD :
2011-12-17 13:57:23 +01:00
val = 1 ;
2013-03-20 18:24:47 +01:00
break ;
case N_RSSI_IQ :
2011-12-17 13:57:23 +01:00
val = 2 ;
2013-03-20 18:24:47 +01:00
break ;
default :
2011-12-17 13:57:23 +01:00
val = 3 ;
2013-03-20 18:24:47 +01:00
}
2010-02-04 12:23:12 +01:00
2011-12-17 13:57:23 +01:00
val = ( val < < 12 ) | ( val < < 14 ) ;
b43_phy_maskset ( dev , B43_NPHY_AFECTL_C1 , 0x0FFF , val ) ;
b43_phy_maskset ( dev , B43_NPHY_AFECTL_C2 , 0x0FFF , val ) ;
2010-02-04 12:23:12 +01:00
2013-03-20 18:24:47 +01:00
if ( rssi_w1_w2_nb ) {
2011-12-17 13:57:23 +01:00
b43_phy_maskset ( dev , B43_NPHY_RFCTL_RSSIO1 , 0xFFCF ,
2013-03-20 18:24:47 +01:00
( rssi_type + 1 ) < < 4 ) ;
2011-12-17 13:57:23 +01:00
b43_phy_maskset ( dev , B43_NPHY_RFCTL_RSSIO2 , 0xFFCF ,
2013-03-20 18:24:47 +01:00
( rssi_type + 1 ) < < 4 ) ;
2010-02-04 12:23:12 +01:00
}
2011-12-17 13:57:23 +01:00
if ( code = = 0 ) {
b43_phy_mask ( dev , B43_NPHY_AFECTL_OVER , ~ 0x3000 ) ;
2013-03-20 18:24:47 +01:00
if ( rssi_w1_w2_nb ) {
2011-12-17 13:57:23 +01:00
b43_phy_mask ( dev , B43_NPHY_RFCTL_CMD ,
~ ( B43_NPHY_RFCTL_CMD_RXEN |
B43_NPHY_RFCTL_CMD_CORESEL ) ) ;
b43_phy_mask ( dev , B43_NPHY_RFCTL_OVER ,
~ ( 0x1 < < 12 |
0x1 < < 5 |
0x1 < < 1 |
0x1 ) ) ;
b43_phy_mask ( dev , B43_NPHY_RFCTL_CMD ,
~ B43_NPHY_RFCTL_CMD_START ) ;
udelay ( 20 ) ;
b43_phy_mask ( dev , B43_NPHY_RFCTL_OVER , ~ 0x1 ) ;
}
} else {
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER , 0x3000 ) ;
2013-03-20 18:24:47 +01:00
if ( rssi_w1_w2_nb ) {
2011-12-17 13:57:23 +01:00
b43_phy_maskset ( dev , B43_NPHY_RFCTL_CMD ,
~ ( B43_NPHY_RFCTL_CMD_RXEN |
B43_NPHY_RFCTL_CMD_CORESEL ) ,
( B43_NPHY_RFCTL_CMD_RXEN |
code < < B43_NPHY_RFCTL_CMD_CORESEL_SHIFT ) ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_OVER ,
( 0x1 < < 12 |
0x1 < < 5 |
0x1 < < 1 |
0x1 ) ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_CMD_START ) ;
udelay ( 20 ) ;
b43_phy_mask ( dev , B43_NPHY_RFCTL_OVER , ~ 0x1 ) ;
2010-02-04 12:23:12 +01:00
}
}
}
2011-12-17 13:57:23 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
2013-03-20 18:24:47 +01:00
static void b43_nphy_rssi_select ( struct b43_wldev * dev , u8 code ,
enum n_rssi_type type )
2010-02-27 13:03:38 +01:00
{
2014-07-08 15:11:06 +02:00
if ( dev - > phy . rev > = 19 )
b43_nphy_rssi_select_rev19 ( dev , code , type ) ;
else if ( dev - > phy . rev > = 3 )
2011-12-17 13:57:23 +01:00
b43_nphy_rev3_rssi_select ( dev , code , type ) ;
else
b43_nphy_rev2_rssi_select ( dev , code , type ) ;
}
2010-02-27 13:03:38 +01:00
2011-12-17 13:57:25 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
2013-03-20 18:24:47 +01:00
static void b43_nphy_set_rssi_2055_vcm ( struct b43_wldev * dev ,
enum n_rssi_type rssi_type , u8 * buf )
2011-12-17 13:57:25 +01:00
{
int i ;
2010-02-27 13:03:38 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
2013-03-20 18:24:47 +01:00
if ( rssi_type = = N_RSSI_NB ) {
2011-12-17 13:57:25 +01:00
if ( i = = 0 ) {
b43_radio_maskset ( dev , B2055_C1_B0NB_RSSIVCM ,
0xFC , buf [ 0 ] ) ;
b43_radio_maskset ( dev , B2055_C1_RX_BB_RSSICTL5 ,
0xFC , buf [ 1 ] ) ;
} else {
b43_radio_maskset ( dev , B2055_C2_B0NB_RSSIVCM ,
0xFC , buf [ 2 * i ] ) ;
b43_radio_maskset ( dev , B2055_C2_RX_BB_RSSICTL5 ,
0xFC , buf [ 2 * i + 1 ] ) ;
}
2010-02-27 13:03:38 +01:00
} else {
2011-12-17 13:57:25 +01:00
if ( i = = 0 )
b43_radio_maskset ( dev , B2055_C1_RX_BB_RSSICTL5 ,
0xF3 , buf [ 0 ] < < 2 ) ;
else
b43_radio_maskset ( dev , B2055_C2_RX_BB_RSSICTL5 ,
0xF3 , buf [ 2 * i + 1 ] < < 2 ) ;
2010-02-27 13:03:38 +01:00
}
}
}
2011-12-17 13:57:25 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
2013-03-20 18:24:47 +01:00
static int b43_nphy_poll_rssi ( struct b43_wldev * dev , enum n_rssi_type rssi_type ,
s32 * buf , u8 nsamp )
2010-01-30 00:12:20 +01:00
{
2011-12-17 13:57:25 +01:00
int i ;
int out ;
u16 save_regs_phy [ 9 ] ;
u16 s [ 2 ] ;
2010-01-30 00:12:20 +01:00
2014-07-08 15:11:06 +02:00
/* TODO: rev7+ is treated like rev3+, what about rev19+? */
2010-01-30 00:12:20 +01:00
if ( dev - > phy . rev > = 3 ) {
2012-01-03 22:49:21 +01:00
save_regs_phy [ 0 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_C1 ) ;
save_regs_phy [ 1 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_C2 ) ;
save_regs_phy [ 2 ] = b43_phy_read ( dev ,
2011-12-17 13:57:25 +01:00
B43_NPHY_RFCTL_LUT_TRSW_UP1 ) ;
2012-01-03 22:49:21 +01:00
save_regs_phy [ 3 ] = b43_phy_read ( dev ,
2011-12-17 13:57:25 +01:00
B43_NPHY_RFCTL_LUT_TRSW_UP2 ) ;
save_regs_phy [ 4 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_OVER1 ) ;
save_regs_phy [ 5 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_OVER ) ;
save_regs_phy [ 6 ] = b43_phy_read ( dev , B43_NPHY_TXF_40CO_B1S0 ) ;
save_regs_phy [ 7 ] = b43_phy_read ( dev , B43_NPHY_TXF_40CO_B32S1 ) ;
save_regs_phy [ 8 ] = 0 ;
2010-01-30 00:12:20 +01:00
} else {
2011-12-17 13:57:25 +01:00
save_regs_phy [ 0 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_C1 ) ;
save_regs_phy [ 1 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_C2 ) ;
save_regs_phy [ 2 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_OVER ) ;
save_regs_phy [ 3 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_CMD ) ;
save_regs_phy [ 4 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_OVER ) ;
save_regs_phy [ 5 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_RSSIO1 ) ;
save_regs_phy [ 6 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_RSSIO2 ) ;
save_regs_phy [ 7 ] = 0 ;
save_regs_phy [ 8 ] = 0 ;
}
2010-01-30 00:12:20 +01:00
2013-03-20 18:24:47 +01:00
b43_nphy_rssi_select ( dev , 5 , rssi_type ) ;
2010-01-30 00:12:20 +01:00
2011-12-17 13:57:25 +01:00
if ( dev - > phy . rev < 2 ) {
save_regs_phy [ 8 ] = b43_phy_read ( dev , B43_NPHY_GPIO_SEL ) ;
b43_phy_write ( dev , B43_NPHY_GPIO_SEL , 5 ) ;
}
2010-01-30 00:12:20 +01:00
2011-12-17 13:57:25 +01:00
for ( i = 0 ; i < 4 ; i + + )
buf [ i ] = 0 ;
for ( i = 0 ; i < nsamp ; i + + ) {
if ( dev - > phy . rev < 2 ) {
s [ 0 ] = b43_phy_read ( dev , B43_NPHY_GPIO_LOOUT ) ;
s [ 1 ] = b43_phy_read ( dev , B43_NPHY_GPIO_HIOUT ) ;
2010-01-30 00:12:20 +01:00
} else {
2011-12-17 13:57:25 +01:00
s [ 0 ] = b43_phy_read ( dev , B43_NPHY_RSSI1 ) ;
s [ 1 ] = b43_phy_read ( dev , B43_NPHY_RSSI2 ) ;
2010-01-30 00:12:20 +01:00
}
2011-12-17 13:57:25 +01:00
buf [ 0 ] + = ( ( s8 ) ( ( s [ 0 ] & 0x3F ) < < 2 ) ) > > 2 ;
buf [ 1 ] + = ( ( s8 ) ( ( ( s [ 0 ] > > 8 ) & 0x3F ) < < 2 ) ) > > 2 ;
buf [ 2 ] + = ( ( s8 ) ( ( s [ 1 ] & 0x3F ) < < 2 ) ) > > 2 ;
buf [ 3 ] + = ( ( s8 ) ( ( ( s [ 1 ] > > 8 ) & 0x3F ) < < 2 ) ) > > 2 ;
}
out = ( buf [ 0 ] & 0xFF ) < < 24 | ( buf [ 1 ] & 0xFF ) < < 16 |
( buf [ 2 ] & 0xFF ) < < 8 | ( buf [ 3 ] & 0xFF ) ;
2010-01-30 00:12:20 +01:00
2011-12-17 13:57:25 +01:00
if ( dev - > phy . rev < 2 )
b43_phy_write ( dev , B43_NPHY_GPIO_SEL , save_regs_phy [ 8 ] ) ;
2010-01-30 00:12:20 +01:00
2011-12-17 13:57:25 +01:00
if ( dev - > phy . rev > = 3 ) {
2012-01-03 22:49:21 +01:00
b43_phy_write ( dev , B43_NPHY_AFECTL_C1 , save_regs_phy [ 0 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_C2 , save_regs_phy [ 1 ] ) ;
2011-12-17 13:57:25 +01:00
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_UP1 ,
2012-01-03 22:49:21 +01:00
save_regs_phy [ 2 ] ) ;
2011-12-17 13:57:25 +01:00
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_UP2 ,
2012-01-03 22:49:21 +01:00
save_regs_phy [ 3 ] ) ;
2011-12-17 13:57:25 +01:00
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER1 , save_regs_phy [ 4 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , save_regs_phy [ 5 ] ) ;
b43_phy_write ( dev , B43_NPHY_TXF_40CO_B1S0 , save_regs_phy [ 6 ] ) ;
b43_phy_write ( dev , B43_NPHY_TXF_40CO_B32S1 , save_regs_phy [ 7 ] ) ;
} else {
b43_phy_write ( dev , B43_NPHY_AFECTL_C1 , save_regs_phy [ 0 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_C2 , save_regs_phy [ 1 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , save_regs_phy [ 2 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_CMD , save_regs_phy [ 3 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_OVER , save_regs_phy [ 4 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_RSSIO1 , save_regs_phy [ 5 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_RSSIO2 , save_regs_phy [ 6 ] ) ;
}
2010-01-30 00:12:20 +01:00
2011-12-17 13:57:25 +01:00
return out ;
}
2010-01-30 00:12:20 +01:00
2012-01-05 01:05:30 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
static void b43_nphy_rev3_rssi_cal ( struct b43_wldev * dev )
{
2014-05-31 20:49:39 +02:00
struct b43_phy * phy = & dev - > phy ;
2012-01-05 01:05:30 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
u16 saved_regs_phy_rfctl [ 2 ] ;
2014-04-20 13:05:48 +02:00
u16 saved_regs_phy [ 22 ] ;
u16 regs_to_store_rev3 [ ] = {
2012-01-05 01:05:30 +01:00
B43_NPHY_AFECTL_OVER1 , B43_NPHY_AFECTL_OVER ,
B43_NPHY_AFECTL_C1 , B43_NPHY_AFECTL_C2 ,
B43_NPHY_TXF_40CO_B1S1 , B43_NPHY_RFCTL_OVER ,
B43_NPHY_TXF_40CO_B1S0 , B43_NPHY_TXF_40CO_B32S1 ,
B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_LUT_TRSW_UP1 , B43_NPHY_RFCTL_LUT_TRSW_UP2 ,
B43_NPHY_RFCTL_RSSIO1 , B43_NPHY_RFCTL_RSSIO2
} ;
2014-04-20 13:05:48 +02:00
u16 regs_to_store_rev7 [ ] = {
B43_NPHY_AFECTL_OVER1 , B43_NPHY_AFECTL_OVER ,
B43_NPHY_AFECTL_C1 , B43_NPHY_AFECTL_C2 ,
B43_NPHY_TXF_40CO_B1S1 , B43_NPHY_RFCTL_OVER ,
2014-07-08 15:11:07 +02:00
B43_NPHY_REV7_RF_CTL_OVER3 , B43_NPHY_REV7_RF_CTL_OVER4 ,
B43_NPHY_REV7_RF_CTL_OVER5 , B43_NPHY_REV7_RF_CTL_OVER6 ,
2014-04-20 13:05:48 +02:00
0x2ff ,
B43_NPHY_TXF_40CO_B1S0 , B43_NPHY_TXF_40CO_B32S1 ,
B43_NPHY_RFCTL_CMD ,
B43_NPHY_RFCTL_LUT_TRSW_UP1 , B43_NPHY_RFCTL_LUT_TRSW_UP2 ,
2014-07-08 15:11:07 +02:00
B43_NPHY_REV7_RF_CTL_MISC_REG3 , B43_NPHY_REV7_RF_CTL_MISC_REG4 ,
B43_NPHY_REV7_RF_CTL_MISC_REG5 , B43_NPHY_REV7_RF_CTL_MISC_REG6 ,
2014-04-20 13:05:48 +02:00
B43_NPHY_RFCTL_RSSIO1 , B43_NPHY_RFCTL_RSSIO2
} ;
u16 * regs_to_store ;
int regs_amount ;
2012-01-05 01:05:30 +01:00
u16 class ;
u16 clip_state [ 2 ] ;
u16 clip_off [ 2 ] = { 0xFFFF , 0xFFFF } ;
u8 vcm_final = 0 ;
2013-03-27 08:37:08 +01:00
s32 offset [ 4 ] ;
2012-01-05 01:05:30 +01:00
s32 results [ 8 ] [ 4 ] = { } ;
s32 results_min [ 4 ] = { } ;
s32 poll_results [ 4 ] = { } ;
u16 * rssical_radio_regs = NULL ;
u16 * rssical_phy_regs = NULL ;
u16 r ; /* routing */
u8 rx_core_state ;
2013-03-20 17:26:03 +01:00
int core , i , j , vcm ;
2012-01-05 01:05:30 +01:00
2014-04-20 13:05:48 +02:00
if ( dev - > phy . rev > = 7 ) {
regs_to_store = regs_to_store_rev7 ;
regs_amount = ARRAY_SIZE ( regs_to_store_rev7 ) ;
} else {
regs_to_store = regs_to_store_rev3 ;
regs_amount = ARRAY_SIZE ( regs_to_store_rev3 ) ;
}
BUG_ON ( regs_amount > ARRAY_SIZE ( saved_regs_phy ) ) ;
2012-01-05 01:05:30 +01:00
class = b43_nphy_classifier ( dev , 0 , 0 ) ;
b43_nphy_classifier ( dev , 7 , 4 ) ;
b43_nphy_read_clip_detection ( dev , clip_state ) ;
b43_nphy_write_clip_detection ( dev , clip_off ) ;
saved_regs_phy_rfctl [ 0 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC1 ) ;
saved_regs_phy_rfctl [ 1 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC2 ) ;
2014-04-20 13:05:48 +02:00
for ( i = 0 ; i < regs_amount ; i + + )
2012-01-05 01:05:30 +01:00
saved_regs_phy [ i ] = b43_phy_read ( dev , regs_to_store [ i ] ) ;
2013-03-29 11:37:02 +01:00
b43_nphy_rf_ctl_intc_override ( dev , N_INTC_OVERRIDE_OFF , 0 , 7 ) ;
b43_nphy_rf_ctl_intc_override ( dev , N_INTC_OVERRIDE_TRSW , 1 , 7 ) ;
2014-04-20 13:05:48 +02:00
if ( dev - > phy . rev > = 7 ) {
2014-07-08 15:11:07 +02:00
b43_nphy_rf_ctl_override_one_to_many ( dev ,
N_RF_CTL_OVER_CMD_RXRF_PU ,
0 , 0 , false ) ;
b43_nphy_rf_ctl_override_one_to_many ( dev ,
N_RF_CTL_OVER_CMD_RX_PU ,
1 , 0 , false ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x80 , 1 , 0 , false , 0 ) ;
2014-07-22 21:31:05 +02:00
b43_nphy_rf_ctl_override_rev7 ( dev , 0x40 , 1 , 0 , false , 0 ) ;
2014-04-20 13:05:48 +02:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
2014-07-08 15:11:07 +02:00
b43_nphy_rf_ctl_override_rev7 ( dev , 0x20 , 0 , 0 , false ,
0 ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x10 , 1 , 0 , false ,
0 ) ;
2014-04-20 13:05:48 +02:00
} else {
2014-07-08 15:11:07 +02:00
b43_nphy_rf_ctl_override_rev7 ( dev , 0x10 , 0 , 0 , false ,
0 ) ;
b43_nphy_rf_ctl_override_rev7 ( dev , 0x20 , 1 , 0 , false ,
0 ) ;
2014-04-20 13:05:48 +02:00
}
2012-01-05 01:05:30 +01:00
} else {
2014-04-20 13:05:48 +02:00
b43_nphy_rf_ctl_override ( dev , 0x1 , 0 , 0 , false ) ;
b43_nphy_rf_ctl_override ( dev , 0x2 , 1 , 0 , false ) ;
b43_nphy_rf_ctl_override ( dev , 0x80 , 1 , 0 , false ) ;
b43_nphy_rf_ctl_override ( dev , 0x40 , 1 , 0 , false ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
b43_nphy_rf_ctl_override ( dev , 0x20 , 0 , 0 , false ) ;
b43_nphy_rf_ctl_override ( dev , 0x10 , 1 , 0 , false ) ;
} else {
b43_nphy_rf_ctl_override ( dev , 0x10 , 0 , 0 , false ) ;
b43_nphy_rf_ctl_override ( dev , 0x20 , 1 , 0 , false ) ;
}
2012-01-05 01:05:30 +01:00
}
rx_core_state = b43_nphy_get_rx_core_state ( dev ) ;
for ( core = 0 ; core < 2 ; core + + ) {
if ( ! ( rx_core_state & ( 1 < < core ) ) )
continue ;
r = core ? B2056_RX1 : B2056_RX0 ;
2013-03-20 18:24:47 +01:00
b43_nphy_scale_offset_rssi ( dev , 0 , 0 , core + 1 , N_RAIL_I ,
N_RSSI_NB ) ;
b43_nphy_scale_offset_rssi ( dev , 0 , 0 , core + 1 , N_RAIL_Q ,
N_RSSI_NB ) ;
2013-03-20 17:26:03 +01:00
/* Grab RSSI results for every possible VCM */
for ( vcm = 0 ; vcm < 8 ; vcm + + ) {
2014-04-20 13:05:48 +02:00
if ( dev - > phy . rev > = 7 )
2014-07-08 15:11:07 +02:00
b43_radio_maskset ( dev ,
core ? R2057_NB_MASTER_CORE1 :
R2057_NB_MASTER_CORE0 ,
~ R2057_VCM_MASK , vcm ) ;
2014-04-20 13:05:48 +02:00
else
b43_radio_maskset ( dev , r | B2056_RX_RSSI_MISC ,
0xE3 , vcm < < 2 ) ;
2013-03-20 18:24:47 +01:00
b43_nphy_poll_rssi ( dev , N_RSSI_NB , results [ vcm ] , 8 ) ;
2012-01-05 01:05:30 +01:00
}
2013-03-20 17:26:03 +01:00
/* Find out which VCM got the best results */
2012-07-05 21:55:46 +02:00
for ( i = 0 ; i < 4 ; i + = 2 ) {
2013-03-20 17:26:03 +01:00
s32 currd ;
2013-03-19 07:52:48 +01:00
s32 mind = 0x100000 ;
2012-01-05 01:05:30 +01:00
s32 minpoll = 249 ;
u8 minvcm = 0 ;
if ( 2 * core ! = i )
continue ;
2013-03-20 17:26:03 +01:00
for ( vcm = 0 ; vcm < 8 ; vcm + + ) {
currd = results [ vcm ] [ i ] * results [ vcm ] [ i ] +
results [ vcm ] [ i + 1 ] * results [ vcm ] [ i ] ;
if ( currd < mind ) {
mind = currd ;
minvcm = vcm ;
2012-01-05 01:05:30 +01:00
}
2013-03-20 17:26:03 +01:00
if ( results [ vcm ] [ i ] < minpoll )
minpoll = results [ vcm ] [ i ] ;
2012-01-05 01:05:30 +01:00
}
vcm_final = minvcm ;
results_min [ i ] = minpoll ;
}
2013-03-20 17:26:03 +01:00
/* Select the best VCM */
2014-04-20 13:05:48 +02:00
if ( dev - > phy . rev > = 7 )
2014-07-08 15:11:07 +02:00
b43_radio_maskset ( dev ,
core ? R2057_NB_MASTER_CORE1 :
R2057_NB_MASTER_CORE0 ,
~ R2057_VCM_MASK , vcm ) ;
2014-04-20 13:05:48 +02:00
else
b43_radio_maskset ( dev , r | B2056_RX_RSSI_MISC ,
0xE3 , vcm_final < < 2 ) ;
2013-03-20 17:26:03 +01:00
2012-01-05 01:05:30 +01:00
for ( i = 0 ; i < 4 ; i + + ) {
if ( core ! = i / 2 )
continue ;
offset [ i ] = - results [ vcm_final ] [ i ] ;
if ( offset [ i ] < 0 )
offset [ i ] = - ( ( abs ( offset [ i ] ) + 4 ) / 8 ) ;
else
offset [ i ] = ( offset [ i ] + 4 ) / 8 ;
if ( results_min [ i ] = = 248 )
offset [ i ] = - 32 ;
b43_nphy_scale_offset_rssi ( dev , 0 , offset [ i ] ,
( i / 2 = = 0 ) ? 1 : 2 ,
2013-03-20 16:51:39 +01:00
( i % 2 = = 0 ) ? N_RAIL_I : N_RAIL_Q ,
2013-03-20 18:24:47 +01:00
N_RSSI_NB ) ;
2012-01-05 01:05:30 +01:00
}
}
2013-03-20 17:26:03 +01:00
2012-01-05 01:05:30 +01:00
for ( core = 0 ; core < 2 ; core + + ) {
if ( ! ( rx_core_state & ( 1 < < core ) ) )
continue ;
for ( i = 0 ; i < 2 ; i + + ) {
2013-03-20 16:51:39 +01:00
b43_nphy_scale_offset_rssi ( dev , 0 , 0 , core + 1 ,
N_RAIL_I , i ) ;
b43_nphy_scale_offset_rssi ( dev , 0 , 0 , core + 1 ,
N_RAIL_Q , i ) ;
2012-01-05 01:05:30 +01:00
b43_nphy_poll_rssi ( dev , i , poll_results , 8 ) ;
for ( j = 0 ; j < 4 ; j + + ) {
2012-07-05 21:55:46 +02:00
if ( j / 2 = = core ) {
2012-01-05 01:05:30 +01:00
offset [ j ] = 232 - poll_results [ j ] ;
2012-07-05 21:55:46 +02:00
if ( offset [ j ] < 0 )
offset [ j ] = - ( abs ( offset [ j ] + 4 ) / 8 ) ;
else
offset [ j ] = ( offset [ j ] + 4 ) / 8 ;
b43_nphy_scale_offset_rssi ( dev , 0 ,
offset [ 2 * core ] , core + 1 , j % 2 , i ) ;
}
2012-01-05 01:05:30 +01:00
}
}
}
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 , saved_regs_phy_rfctl [ 0 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 , saved_regs_phy_rfctl [ 1 ] ) ;
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RESET2RX ) ;
b43_phy_set ( dev , B43_NPHY_TXF_40CO_B1S1 , 0x1 ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD , B43_NPHY_RFCTL_CMD_START ) ;
b43_phy_mask ( dev , B43_NPHY_TXF_40CO_B1S1 , ~ 0x1 ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_OVER , 0x1 ) ;
b43_phy_set ( dev , B43_NPHY_RFCTL_CMD , B43_NPHY_RFCTL_CMD_RXTX ) ;
2014-04-20 13:05:45 +02:00
b43_phy_mask ( dev , B43_NPHY_RFCTL_OVER , ~ 0x1 ) ;
2012-01-05 01:05:30 +01:00
2014-04-20 13:05:48 +02:00
for ( i = 0 ; i < regs_amount ; i + + )
2012-01-05 01:05:30 +01:00
b43_phy_write ( dev , regs_to_store [ i ] , saved_regs_phy [ i ] ) ;
/* Store for future configuration */
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
rssical_radio_regs = nphy - > rssical_cache . rssical_radio_regs_2G ;
rssical_phy_regs = nphy - > rssical_cache . rssical_phy_regs_2G ;
} else {
rssical_radio_regs = nphy - > rssical_cache . rssical_radio_regs_5G ;
rssical_phy_regs = nphy - > rssical_cache . rssical_phy_regs_5G ;
}
2013-03-30 22:34:40 +01:00
if ( dev - > phy . rev > = 7 ) {
2014-07-08 15:11:07 +02:00
rssical_radio_regs [ 0 ] = b43_radio_read ( dev ,
R2057_NB_MASTER_CORE0 ) ;
rssical_radio_regs [ 1 ] = b43_radio_read ( dev ,
R2057_NB_MASTER_CORE1 ) ;
2013-03-30 22:34:40 +01:00
} else {
rssical_radio_regs [ 0 ] = b43_radio_read ( dev , B2056_RX0 |
B2056_RX_RSSI_MISC ) ;
rssical_radio_regs [ 1 ] = b43_radio_read ( dev , B2056_RX1 |
B2056_RX_RSSI_MISC ) ;
}
2012-01-05 01:05:30 +01:00
rssical_phy_regs [ 0 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_0I_RSSI_Z ) ;
rssical_phy_regs [ 1 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_0Q_RSSI_Z ) ;
rssical_phy_regs [ 2 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_1I_RSSI_Z ) ;
rssical_phy_regs [ 3 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_1Q_RSSI_Z ) ;
rssical_phy_regs [ 4 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_0I_RSSI_X ) ;
rssical_phy_regs [ 5 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_0Q_RSSI_X ) ;
rssical_phy_regs [ 6 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_1I_RSSI_X ) ;
rssical_phy_regs [ 7 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_1Q_RSSI_X ) ;
rssical_phy_regs [ 8 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_0I_RSSI_Y ) ;
rssical_phy_regs [ 9 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_0Q_RSSI_Y ) ;
rssical_phy_regs [ 10 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_1I_RSSI_Y ) ;
rssical_phy_regs [ 11 ] = b43_phy_read ( dev , B43_NPHY_RSSIMC_1Q_RSSI_Y ) ;
/* Remember for which channel we store configuration */
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
2014-05-31 20:49:39 +02:00
nphy - > rssical_chanspec_2G . center_freq = phy - > chandef - > chan - > center_freq ;
2012-01-05 01:05:30 +01:00
else
2014-05-31 20:49:39 +02:00
nphy - > rssical_chanspec_5G . center_freq = phy - > chandef - > chan - > center_freq ;
2012-01-05 01:05:30 +01:00
/* End of calibration, restore configuration */
b43_nphy_classifier ( dev , 7 , class ) ;
b43_nphy_write_clip_detection ( dev , clip_state ) ;
}
2011-12-17 13:57:25 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
2013-03-20 18:24:47 +01:00
static void b43_nphy_rev2_rssi_cal ( struct b43_wldev * dev , enum n_rssi_type type )
2011-12-17 13:57:25 +01:00
{
2013-03-20 17:26:03 +01:00
int i , j , vcm ;
2011-12-17 13:57:25 +01:00
u8 state [ 4 ] ;
u8 code , val ;
u16 class , override ;
u8 regs_save_radio [ 2 ] ;
u16 regs_save_phy [ 2 ] ;
2013-03-27 08:37:08 +01:00
s32 offset [ 4 ] ;
2011-12-17 13:57:25 +01:00
u8 core ;
u8 rail ;
u16 clip_state [ 2 ] ;
u16 clip_off [ 2 ] = { 0xFFFF , 0xFFFF } ;
s32 results_min [ 4 ] = { } ;
u8 vcm_final [ 4 ] = { } ;
s32 results [ 4 ] [ 4 ] = { } ;
s32 miniq [ 4 ] [ 2 ] = { } ;
2013-03-20 18:24:47 +01:00
if ( type = = N_RSSI_NB ) {
2011-12-17 13:57:25 +01:00
code = 0 ;
val = 6 ;
2013-03-20 18:24:47 +01:00
} else if ( type = = N_RSSI_W1 | | type = = N_RSSI_W2 ) {
2011-12-17 13:57:25 +01:00
code = 25 ;
val = 4 ;
} else {
B43_WARN_ON ( 1 ) ;
return ;
}
class = b43_nphy_classifier ( dev , 0 , 0 ) ;
b43_nphy_classifier ( dev , 7 , 4 ) ;
b43_nphy_read_clip_detection ( dev , clip_state ) ;
b43_nphy_write_clip_detection ( dev , clip_off ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ )
override = 0x140 ;
else
override = 0x110 ;
regs_save_phy [ 0 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC1 ) ;
2013-04-12 17:58:13 +02:00
regs_save_radio [ 0 ] = b43_radio_read ( dev , B2055_C1_PD_RXTX ) ;
2011-12-17 13:57:25 +01:00
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 , override ) ;
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , B2055_C1_PD_RXTX , val ) ;
2011-12-17 13:57:25 +01:00
regs_save_phy [ 1 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC2 ) ;
2013-04-12 17:58:13 +02:00
regs_save_radio [ 1 ] = b43_radio_read ( dev , B2055_C2_PD_RXTX ) ;
2011-12-17 13:57:25 +01:00
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 , override ) ;
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , B2055_C2_PD_RXTX , val ) ;
2011-12-17 13:57:25 +01:00
2013-04-12 17:58:13 +02:00
state [ 0 ] = b43_radio_read ( dev , B2055_C1_PD_RSSIMISC ) & 0x07 ;
state [ 1 ] = b43_radio_read ( dev , B2055_C2_PD_RSSIMISC ) & 0x07 ;
2011-12-17 13:57:25 +01:00
b43_radio_mask ( dev , B2055_C1_PD_RSSIMISC , 0xF8 ) ;
b43_radio_mask ( dev , B2055_C2_PD_RSSIMISC , 0xF8 ) ;
2013-04-12 17:58:13 +02:00
state [ 2 ] = b43_radio_read ( dev , B2055_C1_SP_RSSI ) & 0x07 ;
state [ 3 ] = b43_radio_read ( dev , B2055_C2_SP_RSSI ) & 0x07 ;
2011-12-17 13:57:25 +01:00
b43_nphy_rssi_select ( dev , 5 , type ) ;
2013-03-20 16:51:39 +01:00
b43_nphy_scale_offset_rssi ( dev , 0 , 0 , 5 , N_RAIL_I , type ) ;
b43_nphy_scale_offset_rssi ( dev , 0 , 0 , 5 , N_RAIL_Q , type ) ;
2011-12-17 13:57:25 +01:00
2013-03-20 17:26:03 +01:00
for ( vcm = 0 ; vcm < 4 ; vcm + + ) {
2011-12-17 13:57:25 +01:00
u8 tmp [ 4 ] ;
for ( j = 0 ; j < 4 ; j + + )
2013-03-20 17:26:03 +01:00
tmp [ j ] = vcm ;
2013-03-20 18:24:47 +01:00
if ( type ! = N_RSSI_W2 )
2011-12-17 13:57:25 +01:00
b43_nphy_set_rssi_2055_vcm ( dev , type , tmp ) ;
2013-03-20 17:26:03 +01:00
b43_nphy_poll_rssi ( dev , type , results [ vcm ] , 8 ) ;
2013-03-20 18:24:47 +01:00
if ( type = = N_RSSI_W1 | | type = = N_RSSI_W2 )
2011-12-17 13:57:25 +01:00
for ( j = 0 ; j < 2 ; j + + )
2013-03-20 17:26:03 +01:00
miniq [ vcm ] [ j ] = min ( results [ vcm ] [ 2 * j ] ,
results [ vcm ] [ 2 * j + 1 ] ) ;
2011-12-17 13:57:25 +01:00
}
for ( i = 0 ; i < 4 ; i + + ) {
2013-03-19 07:52:48 +01:00
s32 mind = 0x100000 ;
2011-12-17 13:57:25 +01:00
u8 minvcm = 0 ;
s32 minpoll = 249 ;
2013-03-20 17:26:03 +01:00
s32 currd ;
for ( vcm = 0 ; vcm < 4 ; vcm + + ) {
2013-03-20 18:24:47 +01:00
if ( type = = N_RSSI_NB )
2013-03-20 19:13:47 +01:00
currd = abs ( results [ vcm ] [ i ] - code * 8 ) ;
2011-12-17 13:57:25 +01:00
else
2013-03-20 17:26:03 +01:00
currd = abs ( miniq [ vcm ] [ i / 2 ] - code * 8 ) ;
2011-12-17 13:57:25 +01:00
2013-03-20 17:26:03 +01:00
if ( currd < mind ) {
mind = currd ;
minvcm = vcm ;
2011-12-17 13:57:25 +01:00
}
2013-03-20 17:26:03 +01:00
if ( results [ vcm ] [ i ] < minpoll )
minpoll = results [ vcm ] [ i ] ;
2011-02-21 19:45:34 +01:00
}
2011-12-17 13:57:25 +01:00
results_min [ i ] = minpoll ;
vcm_final [ i ] = minvcm ;
}
2010-01-30 00:12:20 +01:00
2013-03-20 18:24:47 +01:00
if ( type ! = N_RSSI_W2 )
2011-12-17 13:57:25 +01:00
b43_nphy_set_rssi_2055_vcm ( dev , type , vcm_final ) ;
2010-01-30 00:12:20 +01:00
2011-12-17 13:57:25 +01:00
for ( i = 0 ; i < 4 ; i + + ) {
offset [ i ] = ( code * 8 ) - results [ vcm_final [ i ] ] [ i ] ;
if ( offset [ i ] < 0 )
offset [ i ] = - ( ( abs ( offset [ i ] ) + 4 ) / 8 ) ;
else
offset [ i ] = ( offset [ i ] + 4 ) / 8 ;
if ( results_min [ i ] = = 248 )
offset [ i ] = code - 32 ;
core = ( i / 2 ) ? 2 : 1 ;
2013-03-20 16:51:39 +01:00
rail = ( i % 2 ) ? N_RAIL_Q : N_RAIL_I ;
2011-12-17 13:57:25 +01:00
b43_nphy_scale_offset_rssi ( dev , 0 , offset [ i ] , core , rail ,
type ) ;
}
b43_radio_maskset ( dev , B2055_C1_PD_RSSIMISC , 0xF8 , state [ 0 ] ) ;
b43_radio_maskset ( dev , B2055_C2_PD_RSSIMISC , 0xF8 , state [ 1 ] ) ;
switch ( state [ 2 ] ) {
case 1 :
2013-03-20 18:24:47 +01:00
b43_nphy_rssi_select ( dev , 1 , N_RSSI_NB ) ;
2011-12-17 13:57:25 +01:00
break ;
case 4 :
2013-03-20 18:24:47 +01:00
b43_nphy_rssi_select ( dev , 1 , N_RSSI_W1 ) ;
2011-12-17 13:57:25 +01:00
break ;
case 2 :
2013-03-20 18:24:47 +01:00
b43_nphy_rssi_select ( dev , 1 , N_RSSI_W2 ) ;
2011-12-17 13:57:25 +01:00
break ;
default :
2013-03-20 18:24:47 +01:00
b43_nphy_rssi_select ( dev , 1 , N_RSSI_W2 ) ;
2011-12-17 13:57:25 +01:00
break ;
}
switch ( state [ 3 ] ) {
case 1 :
2013-03-20 18:24:47 +01:00
b43_nphy_rssi_select ( dev , 2 , N_RSSI_NB ) ;
2011-12-17 13:57:25 +01:00
break ;
case 4 :
2013-03-20 18:24:47 +01:00
b43_nphy_rssi_select ( dev , 2 , N_RSSI_W1 ) ;
2011-12-17 13:57:25 +01:00
break ;
default :
2013-03-20 18:24:47 +01:00
b43_nphy_rssi_select ( dev , 2 , N_RSSI_W2 ) ;
2011-12-17 13:57:25 +01:00
break ;
}
b43_nphy_rssi_select ( dev , 0 , type ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 , regs_save_phy [ 0 ] ) ;
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , B2055_C1_PD_RXTX , regs_save_radio [ 0 ] ) ;
2011-12-17 13:57:25 +01:00
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 , regs_save_phy [ 1 ] ) ;
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , B2055_C2_PD_RXTX , regs_save_radio [ 1 ] ) ;
2011-12-17 13:57:25 +01:00
b43_nphy_classifier ( dev , 7 , class ) ;
b43_nphy_write_clip_detection ( dev , clip_state ) ;
/* Specs don't say about reset here, but it makes wl and b43 dumps
identical , it really seems wl performs this */
b43_nphy_reset_cca ( dev ) ;
}
/*
* RSSI Calibration
* http : //bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
*/
static void b43_nphy_rssi_cal ( struct b43_wldev * dev )
{
2014-07-08 15:11:06 +02:00
if ( dev - > phy . rev > = 19 ) {
/* TODO */
} else if ( dev - > phy . rev > = 3 ) {
2011-12-17 13:57:25 +01:00
b43_nphy_rev3_rssi_cal ( dev ) ;
} else {
2013-03-20 17:30:38 +01:00
b43_nphy_rev2_rssi_cal ( dev , N_RSSI_NB ) ;
b43_nphy_rev2_rssi_cal ( dev , N_RSSI_W1 ) ;
b43_nphy_rev2_rssi_cal ( dev , N_RSSI_W2 ) ;
2011-12-17 13:57:25 +01:00
}
}
2011-12-17 13:57:24 +01:00
/**************************************************
* Workarounds
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-07-08 15:11:06 +02:00
static void b43_nphy_gain_ctl_workarounds_rev19 ( struct b43_wldev * dev )
{
/* TODO */
}
static void b43_nphy_gain_ctl_workarounds_rev7 ( struct b43_wldev * dev )
{
struct b43_phy * phy = & dev - > phy ;
switch ( phy - > rev ) {
/* TODO */
}
}
static void b43_nphy_gain_ctl_workarounds_rev3 ( struct b43_wldev * dev )
2011-12-17 13:57:24 +01:00
{
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
bool ghz5 ;
bool ext_lna ;
u16 rssi_gain ;
struct nphy_gain_ctl_workaround_entry * e ;
u8 lpf_gain [ 6 ] = { 0x00 , 0x06 , 0x0C , 0x12 , 0x12 , 0x12 } ;
u8 lpf_bits [ 6 ] = { 0 , 1 , 2 , 3 , 3 , 3 } ;
/* Prepare values */
ghz5 = b43_phy_read ( dev , B43_NPHY_BANDCTL )
& B43_NPHY_BANDCTL_5GHZ ;
2011-12-22 00:47:17 +01:00
ext_lna = ghz5 ? sprom - > boardflags_hi & B43_BFH_EXTLNA_5GHZ :
sprom - > boardflags_lo & B43_BFL_EXTLNA ;
2011-12-17 13:57:24 +01:00
e = b43_nphy_get_gain_ctl_workaround_ent ( dev , ghz5 , ext_lna ) ;
if ( ghz5 & & dev - > phy . rev > = 5 )
rssi_gain = 0x90 ;
else
rssi_gain = 0x50 ;
b43_phy_set ( dev , B43_NPHY_RXCTL , 0x0040 ) ;
/* Set Clip 2 detect */
2013-03-29 11:13:40 +01:00
b43_phy_set ( dev , B43_NPHY_C1_CGAINI , B43_NPHY_C1_CGAINI_CL2DETECT ) ;
b43_phy_set ( dev , B43_NPHY_C2_CGAINI , B43_NPHY_C2_CGAINI_CL2DETECT ) ;
2011-12-17 13:57:24 +01:00
b43_radio_write ( dev , B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC ,
0x17 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC ,
0x17 ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_LNAG2_IDAC , 0xF0 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_LNAG2_IDAC , 0xF0 ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_RSSI_POLE , 0x00 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_RSSI_POLE , 0x00 ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_RSSI_GAIN ,
rssi_gain ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_RSSI_GAIN ,
rssi_gain ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC ,
0x17 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC ,
0x17 ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_LNAA2_IDAC , 0xFF ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_LNAA2_IDAC , 0xFF ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 0 , 8 ) , 4 , e - > lna1_gain ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 1 , 8 ) , 4 , e - > lna1_gain ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 0 , 16 ) , 4 , e - > lna2_gain ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 1 , 16 ) , 4 , e - > lna2_gain ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 0 , 32 ) , 10 , e - > gain_db ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 1 , 32 ) , 10 , e - > gain_db ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 2 , 32 ) , 10 , e - > gain_bits ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 3 , 32 ) , 10 , e - > gain_bits ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 0 , 0x40 ) , 6 , lpf_gain ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 1 , 0x40 ) , 6 , lpf_gain ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 2 , 0x40 ) , 6 , lpf_bits ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 3 , 0x40 ) , 6 , lpf_bits ) ;
2013-03-29 11:13:40 +01:00
b43_phy_write ( dev , B43_NPHY_REV3_C1_INITGAIN_A , e - > init_gain ) ;
b43_phy_write ( dev , B43_NPHY_REV3_C2_INITGAIN_A , e - > init_gain ) ;
2011-12-17 13:57:24 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 7 , 0x106 ) , 2 ,
e - > rfseq_init ) ;
2013-03-29 11:13:40 +01:00
b43_phy_write ( dev , B43_NPHY_REV3_C1_CLIP_HIGAIN_A , e - > cliphi_gain ) ;
b43_phy_write ( dev , B43_NPHY_REV3_C2_CLIP_HIGAIN_A , e - > cliphi_gain ) ;
b43_phy_write ( dev , B43_NPHY_REV3_C1_CLIP_MEDGAIN_A , e - > clipmd_gain ) ;
b43_phy_write ( dev , B43_NPHY_REV3_C2_CLIP_MEDGAIN_A , e - > clipmd_gain ) ;
b43_phy_write ( dev , B43_NPHY_REV3_C1_CLIP_LOGAIN_A , e - > cliplo_gain ) ;
b43_phy_write ( dev , B43_NPHY_REV3_C2_CLIP_LOGAIN_A , e - > cliplo_gain ) ;
b43_phy_maskset ( dev , B43_NPHY_CRSMINPOWER0 , 0xFF00 , e - > crsmin ) ;
b43_phy_maskset ( dev , B43_NPHY_CRSMINPOWERL0 , 0xFF00 , e - > crsminl ) ;
b43_phy_maskset ( dev , B43_NPHY_CRSMINPOWERU0 , 0xFF00 , e - > crsminu ) ;
2011-12-17 13:57:24 +01:00
b43_phy_write ( dev , B43_NPHY_C1_NBCLIPTHRES , e - > nbclip ) ;
b43_phy_write ( dev , B43_NPHY_C2_NBCLIPTHRES , e - > nbclip ) ;
b43_phy_maskset ( dev , B43_NPHY_C1_CLIPWBTHRES ,
~ B43_NPHY_C1_CLIPWBTHRES_CLIP2 , e - > wlclip ) ;
b43_phy_maskset ( dev , B43_NPHY_C2_CLIPWBTHRES ,
~ B43_NPHY_C2_CLIPWBTHRES_CLIP2 , e - > wlclip ) ;
b43_phy_write ( dev , B43_NPHY_CCK_SHIFTB_REF , 0x809C ) ;
}
static void b43_nphy_gain_ctl_workarounds_rev1_2 ( struct b43_wldev * dev )
{
struct b43_phy_n * nphy = dev - > phy . n ;
u8 i , j ;
u8 code ;
u16 tmp ;
u8 rfseq_events [ 3 ] = { 6 , 8 , 7 } ;
u8 rfseq_delays [ 3 ] = { 10 , 30 , 1 } ;
/* Set Clip 2 detect */
b43_phy_set ( dev , B43_NPHY_C1_CGAINI , B43_NPHY_C1_CGAINI_CL2DETECT ) ;
b43_phy_set ( dev , B43_NPHY_C2_CGAINI , B43_NPHY_C2_CGAINI_CL2DETECT ) ;
/* Set narrowband clip threshold */
b43_phy_write ( dev , B43_NPHY_C1_NBCLIPTHRES , 0x84 ) ;
b43_phy_write ( dev , B43_NPHY_C2_NBCLIPTHRES , 0x84 ) ;
2014-05-31 20:49:40 +02:00
if ( ! b43_is_40mhz ( dev ) ) {
2011-12-17 13:57:24 +01:00
/* Set dwell lengths */
b43_phy_write ( dev , B43_NPHY_CLIP1_NBDWELL_LEN , 0x002B ) ;
b43_phy_write ( dev , B43_NPHY_CLIP2_NBDWELL_LEN , 0x002B ) ;
b43_phy_write ( dev , B43_NPHY_W1CLIP1_DWELL_LEN , 0x0009 ) ;
b43_phy_write ( dev , B43_NPHY_W1CLIP2_DWELL_LEN , 0x0009 ) ;
}
/* Set wideband clip 2 threshold */
b43_phy_maskset ( dev , B43_NPHY_C1_CLIPWBTHRES ,
~ B43_NPHY_C1_CLIPWBTHRES_CLIP2 , 21 ) ;
b43_phy_maskset ( dev , B43_NPHY_C2_CLIPWBTHRES ,
~ B43_NPHY_C2_CLIPWBTHRES_CLIP2 , 21 ) ;
2014-05-31 20:49:40 +02:00
if ( ! b43_is_40mhz ( dev ) ) {
2011-12-17 13:57:24 +01:00
b43_phy_maskset ( dev , B43_NPHY_C1_CGAINI ,
~ B43_NPHY_C1_CGAINI_GAINBKOFF , 0x1 ) ;
b43_phy_maskset ( dev , B43_NPHY_C2_CGAINI ,
~ B43_NPHY_C2_CGAINI_GAINBKOFF , 0x1 ) ;
b43_phy_maskset ( dev , B43_NPHY_C1_CCK_CGAINI ,
~ B43_NPHY_C1_CCK_CGAINI_GAINBKOFF , 0x1 ) ;
b43_phy_maskset ( dev , B43_NPHY_C2_CCK_CGAINI ,
~ B43_NPHY_C2_CCK_CGAINI_GAINBKOFF , 0x1 ) ;
}
b43_phy_write ( dev , B43_NPHY_CCK_SHIFTB_REF , 0x809C ) ;
if ( nphy - > gain_boost ) {
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ & &
2014-05-31 20:49:40 +02:00
b43_is_40mhz ( dev ) )
2011-12-17 13:57:24 +01:00
code = 4 ;
else
code = 5 ;
} else {
2014-05-31 20:49:40 +02:00
code = b43_is_40mhz ( dev ) ? 6 : 7 ;
2011-12-17 13:57:24 +01:00
}
/* Set HPVGA2 index */
b43_phy_maskset ( dev , B43_NPHY_C1_INITGAIN , ~ B43_NPHY_C1_INITGAIN_HPVGA2 ,
code < < B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT ) ;
b43_phy_maskset ( dev , B43_NPHY_C2_INITGAIN , ~ B43_NPHY_C2_INITGAIN_HPVGA2 ,
code < < B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_ADDR , 0x1D06 ) ;
/* specs say about 2 loops, but wl does 4 */
for ( i = 0 ; i < 4 ; i + + )
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , ( code < < 8 | 0x7C ) ) ;
b43_nphy_adjust_lna_gain_table ( dev ) ;
if ( nphy - > elna_gain_config ) {
b43_phy_write ( dev , B43_NPHY_TABLE_ADDR , 0x0808 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0x0 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0x1 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0x1 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0x1 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_ADDR , 0x0C08 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0x0 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0x1 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0x1 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0x1 ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_ADDR , 0x1D06 ) ;
/* specs say about 2 loops, but wl does 4 */
for ( i = 0 ; i < 4 ; i + + )
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO ,
( code < < 8 | 0x74 ) ) ;
}
if ( dev - > phy . rev = = 2 ) {
for ( i = 0 ; i < 4 ; i + + ) {
b43_phy_write ( dev , B43_NPHY_TABLE_ADDR ,
( 0x0400 * i ) + 0x0020 ) ;
for ( j = 0 ; j < 21 ; j + + ) {
tmp = j * ( i < 2 ? 3 : 1 ) ;
b43_phy_write ( dev ,
B43_NPHY_TABLE_DATALO , tmp ) ;
}
}
2010-01-30 00:12:20 +01:00
}
2011-12-17 13:57:24 +01:00
b43_nphy_set_rf_sequence ( dev , 5 , rfseq_events , rfseq_delays , 3 ) ;
b43_phy_maskset ( dev , B43_NPHY_OVER_DGAIN1 ,
~ B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF ,
0x5A < < B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
b43_phy_maskset ( dev , B43_PHY_N ( 0xC5D ) , 0xFF80 , 4 ) ;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
static void b43_nphy_gain_ctl_workarounds ( struct b43_wldev * dev )
{
2014-07-08 15:11:06 +02:00
if ( dev - > phy . rev > = 19 )
b43_nphy_gain_ctl_workarounds_rev19 ( dev ) ;
else if ( dev - > phy . rev > = 7 )
b43_nphy_gain_ctl_workarounds_rev7 ( dev ) ;
2012-07-24 19:18:20 +02:00
else if ( dev - > phy . rev > = 3 )
2014-07-08 15:11:06 +02:00
b43_nphy_gain_ctl_workarounds_rev3 ( dev ) ;
2011-12-17 13:57:24 +01:00
else
b43_nphy_gain_ctl_workarounds_rev1_2 ( dev ) ;
2010-01-30 00:12:20 +01:00
}
2012-07-24 19:18:20 +02:00
static void b43_nphy_workarounds_rev7plus ( struct b43_wldev * dev )
{
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
struct b43_phy * phy = & dev - > phy ;
2014-07-19 12:52:43 +02:00
/* TX to RX */
u8 tx2rx_events [ 7 ] = { 4 , 3 , 5 , 2 , 1 , 8 , 31 , } ;
u8 tx2rx_delays [ 7 ] = { 8 , 4 , 4 , 4 , 4 , 6 , 1 , } ;
/* RX to TX */
2012-07-24 19:18:20 +02:00
u8 rx2tx_events_ipa [ 9 ] = { 0x0 , 0x1 , 0x2 , 0x8 , 0x5 , 0x6 , 0xF , 0x3 ,
0x1F } ;
u8 rx2tx_delays_ipa [ 9 ] = { 8 , 6 , 6 , 4 , 4 , 16 , 43 , 1 , 1 } ;
2014-07-19 12:52:43 +02:00
static const u16 ntab7_15e_16e [ ] = { 0 , 0x10f , 0x10f } ;
2012-07-24 19:18:20 +02:00
u8 ntab7_138_146 [ ] = { 0x11 , 0x11 } ;
u8 ntab7_133 [ ] = { 0x77 , 0x11 , 0x11 } ;
2014-07-19 12:52:44 +02:00
u16 lpf_ofdm_20mhz [ 2 ] , lpf_ofdm_40mhz [ 2 ] , lpf_11b [ 2 ] ;
u16 bcap_val ;
2014-07-19 12:52:45 +02:00
s16 bcap_val_11b [ 2 ] , bcap_val_11n_20 [ 2 ] , bcap_val_11n_40 [ 2 ] ;
2014-07-19 12:52:44 +02:00
u16 scap_val ;
2014-07-19 12:52:45 +02:00
s16 scap_val_11b [ 2 ] , scap_val_11n_20 [ 2 ] , scap_val_11n_40 [ 2 ] ;
2012-07-24 19:18:20 +02:00
bool rccal_ovrd = false ;
u16 bias , conv , filt ;
2014-07-19 12:52:46 +02:00
u32 noise_tbl [ 2 ] ;
2012-07-24 19:18:20 +02:00
u32 tmp32 ;
u8 core ;
2014-07-19 12:52:43 +02:00
b43_phy_write ( dev , B43_NPHY_PHASETR_A0 , 0x0125 ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_A1 , 0x01b3 ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_A2 , 0x0105 ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_B0 , 0x016e ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_B1 , 0x00cd ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_B2 , 0x0020 ) ;
2012-07-24 19:18:20 +02:00
if ( phy - > rev = = 7 ) {
b43_phy_set ( dev , B43_NPHY_FINERX2_CGC , 0x10 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN0 , 0xFF80 , 0x0020 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN0 , 0x80FF , 0x2700 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN1 , 0xFF80 , 0x002E ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN1 , 0x80FF , 0x3300 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN2 , 0xFF80 , 0x0037 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN2 , 0x80FF , 0x3A00 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN3 , 0xFF80 , 0x003C ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN3 , 0x80FF , 0x3E00 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN4 , 0xFF80 , 0x003E ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN4 , 0x80FF , 0x3F00 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN5 , 0xFF80 , 0x0040 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN5 , 0x80FF , 0x4000 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN6 , 0xFF80 , 0x0040 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN6 , 0x80FF , 0x4000 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN7 , 0xFF80 , 0x0040 ) ;
b43_phy_maskset ( dev , B43_NPHY_FREQGAIN7 , 0x80FF , 0x4000 ) ;
}
2014-07-19 12:52:43 +02:00
if ( phy - > rev > = 16 ) {
b43_phy_write ( dev , B43_NPHY_FORCEFRONT0 , 0x7ff ) ;
b43_phy_write ( dev , B43_NPHY_FORCEFRONT1 , 0x7ff ) ;
} else if ( phy - > rev < = 8 ) {
2013-03-29 11:13:40 +01:00
b43_phy_write ( dev , B43_NPHY_FORCEFRONT0 , 0x1B0 ) ;
b43_phy_write ( dev , B43_NPHY_FORCEFRONT1 , 0x1B0 ) ;
2012-07-24 19:18:20 +02:00
}
2014-07-19 12:52:43 +02:00
if ( phy - > rev > = 16 )
b43_phy_maskset ( dev , B43_NPHY_TXTAILCNT , ~ 0xFF , 0xa0 ) ;
else if ( phy - > rev > = 8 )
2012-07-24 19:18:20 +02:00
b43_phy_maskset ( dev , B43_NPHY_TXTAILCNT , ~ 0xFF , 0x72 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x00 ) , 2 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x10 ) , 2 ) ;
tmp32 = b43_ntab_read ( dev , B43_NTAB32 ( 30 , 0 ) ) ;
tmp32 & = 0xffffff ;
b43_ntab_write ( dev , B43_NTAB32 ( 30 , 0 ) , tmp32 ) ;
2014-07-19 12:52:43 +02:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 7 , 0x15d ) , 3 , ntab7_15e_16e ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 7 , 0x16d ) , 3 , ntab7_15e_16e ) ;
2012-07-24 19:18:20 +02:00
2014-07-19 12:52:43 +02:00
b43_nphy_set_rf_sequence ( dev , 1 , tx2rx_events , tx2rx_delays ,
ARRAY_SIZE ( tx2rx_events ) ) ;
2012-07-24 19:18:20 +02:00
if ( b43_nphy_ipa ( dev ) )
b43_nphy_set_rf_sequence ( dev , 0 , rx2tx_events_ipa ,
rx2tx_delays_ipa , ARRAY_SIZE ( rx2tx_events_ipa ) ) ;
2013-03-29 11:13:40 +01:00
b43_phy_maskset ( dev , B43_NPHY_EPS_OVERRIDEI_0 , 0x3FFF , 0x4000 ) ;
b43_phy_maskset ( dev , B43_NPHY_EPS_OVERRIDEI_1 , 0x3FFF , 0x4000 ) ;
2012-07-24 19:18:20 +02:00
2014-07-19 12:52:44 +02:00
for ( core = 0 ; core < 2 ; core + + ) {
lpf_ofdm_20mhz [ core ] = b43_nphy_read_lpf_ctl ( dev , 0x154 + core * 0x10 ) ;
lpf_ofdm_40mhz [ core ] = b43_nphy_read_lpf_ctl ( dev , 0x159 + core * 0x10 ) ;
lpf_11b [ core ] = b43_nphy_read_lpf_ctl ( dev , 0x152 + core * 0x10 ) ;
}
2014-07-19 12:52:43 +02:00
bcap_val = b43_radio_read ( dev , R2057_RCCAL_BCAP_VAL ) ;
scap_val = b43_radio_read ( dev , R2057_RCCAL_SCAP_VAL ) ;
2012-07-24 19:18:20 +02:00
if ( b43_nphy_ipa ( dev ) ) {
2014-07-19 12:52:45 +02:00
bool ghz2 = b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ;
2014-07-19 12:52:43 +02:00
switch ( phy - > radio_rev ) {
case 5 :
/* Check radio version (to be 0) by PHY rev for now */
if ( phy - > rev = = 8 & & b43_is_40mhz ( dev ) ) {
2014-07-19 12:52:44 +02:00
for ( core = 0 ; core < 2 ; core + + ) {
scap_val_11b [ core ] = scap_val ;
bcap_val_11b [ core ] = bcap_val ;
scap_val_11n_20 [ core ] = scap_val ;
bcap_val_11n_20 [ core ] = bcap_val ;
scap_val_11n_40 [ core ] = 0xc ;
bcap_val_11n_40 [ core ] = 0xc ;
}
2012-07-24 19:18:20 +02:00
rccal_ovrd = true ;
}
2014-07-19 12:52:43 +02:00
if ( phy - > rev = = 9 ) {
/* TODO: Radio version 1 (e.g. BCM5357B0) */
}
break ;
case 7 :
case 8 :
2014-07-19 12:52:44 +02:00
for ( core = 0 ; core < 2 ; core + + ) {
scap_val_11b [ core ] = scap_val ;
bcap_val_11b [ core ] = bcap_val ;
lpf_ofdm_20mhz [ core ] = 4 ;
lpf_11b [ core ] = 1 ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
scap_val_11n_20 [ core ] = 0xc ;
bcap_val_11n_20 [ core ] = 0xc ;
scap_val_11n_40 [ core ] = 0xa ;
bcap_val_11n_40 [ core ] = 0xa ;
} else {
scap_val_11n_20 [ core ] = 0x14 ;
bcap_val_11n_20 [ core ] = 0x14 ;
scap_val_11n_40 [ core ] = 0xf ;
bcap_val_11n_40 [ core ] = 0xf ;
}
2014-07-19 12:52:43 +02:00
}
2014-07-19 12:52:44 +02:00
2014-07-19 12:52:45 +02:00
rccal_ovrd = true ;
break ;
case 9 :
for ( core = 0 ; core < 2 ; core + + ) {
bcap_val_11b [ core ] = bcap_val ;
scap_val_11b [ core ] = scap_val ;
lpf_11b [ core ] = 1 ;
if ( ghz2 ) {
bcap_val_11n_20 [ core ] = bcap_val + 13 ;
scap_val_11n_20 [ core ] = scap_val + 15 ;
} else {
bcap_val_11n_20 [ core ] = bcap_val + 14 ;
scap_val_11n_20 [ core ] = scap_val + 15 ;
}
lpf_ofdm_20mhz [ core ] = 4 ;
if ( ghz2 ) {
bcap_val_11n_40 [ core ] = bcap_val - 7 ;
scap_val_11n_40 [ core ] = scap_val - 5 ;
} else {
bcap_val_11n_40 [ core ] = bcap_val + 2 ;
scap_val_11n_40 [ core ] = scap_val + 4 ;
}
lpf_ofdm_40mhz [ core ] = 4 ;
}
rccal_ovrd = true ;
break ;
case 14 :
for ( core = 0 ; core < 2 ; core + + ) {
bcap_val_11b [ core ] = bcap_val ;
scap_val_11b [ core ] = scap_val ;
lpf_11b [ core ] = 1 ;
}
bcap_val_11n_20 [ 0 ] = bcap_val + 20 ;
scap_val_11n_20 [ 0 ] = scap_val + 20 ;
lpf_ofdm_20mhz [ 0 ] = 3 ;
bcap_val_11n_20 [ 1 ] = bcap_val + 16 ;
scap_val_11n_20 [ 1 ] = scap_val + 16 ;
lpf_ofdm_20mhz [ 1 ] = 3 ;
bcap_val_11n_40 [ 0 ] = bcap_val + 20 ;
scap_val_11n_40 [ 0 ] = scap_val + 20 ;
lpf_ofdm_40mhz [ 0 ] = 4 ;
bcap_val_11n_40 [ 1 ] = bcap_val + 10 ;
scap_val_11n_40 [ 1 ] = scap_val + 10 ;
lpf_ofdm_40mhz [ 1 ] = 4 ;
2014-07-19 12:52:43 +02:00
rccal_ovrd = true ;
break ;
2012-07-24 19:18:20 +02:00
}
} else {
if ( phy - > radio_rev = = 5 ) {
2014-07-19 12:52:44 +02:00
for ( core = 0 ; core < 2 ; core + + ) {
lpf_ofdm_20mhz [ core ] = 1 ;
lpf_ofdm_40mhz [ core ] = 3 ;
scap_val_11b [ core ] = scap_val ;
bcap_val_11b [ core ] = bcap_val ;
scap_val_11n_20 [ core ] = 0x11 ;
scap_val_11n_40 [ core ] = 0x11 ;
bcap_val_11n_20 [ core ] = 0x13 ;
bcap_val_11n_40 [ core ] = 0x13 ;
}
2012-07-24 19:18:20 +02:00
rccal_ovrd = true ;
}
}
if ( rccal_ovrd ) {
2014-07-19 12:52:44 +02:00
u16 rx2tx_lut_20_11b [ 2 ] , rx2tx_lut_20_11n [ 2 ] , rx2tx_lut_40_11n [ 2 ] ;
2014-07-19 12:52:43 +02:00
u8 rx2tx_lut_extra = 1 ;
2014-07-19 12:52:44 +02:00
for ( core = 0 ; core < 2 ; core + + ) {
2014-07-19 12:52:45 +02:00
bcap_val_11b [ core ] = clamp_val ( bcap_val_11b [ core ] , 0 , 0x1f ) ;
scap_val_11b [ core ] = clamp_val ( scap_val_11b [ core ] , 0 , 0x1f ) ;
bcap_val_11n_20 [ core ] = clamp_val ( bcap_val_11n_20 [ core ] , 0 , 0x1f ) ;
scap_val_11n_20 [ core ] = clamp_val ( scap_val_11n_20 [ core ] , 0 , 0x1f ) ;
bcap_val_11n_40 [ core ] = clamp_val ( bcap_val_11n_40 [ core ] , 0 , 0x1f ) ;
scap_val_11n_40 [ core ] = clamp_val ( scap_val_11n_40 [ core ] , 0 , 0x1f ) ;
2014-07-19 12:52:44 +02:00
rx2tx_lut_20_11b [ core ] = ( rx2tx_lut_extra < < 13 ) |
( bcap_val_11b [ core ] < < 8 ) |
( scap_val_11b [ core ] < < 3 ) |
lpf_11b [ core ] ;
rx2tx_lut_20_11n [ core ] = ( rx2tx_lut_extra < < 13 ) |
( bcap_val_11n_20 [ core ] < < 8 ) |
( scap_val_11n_20 [ core ] < < 3 ) |
lpf_ofdm_20mhz [ core ] ;
rx2tx_lut_40_11n [ core ] = ( rx2tx_lut_extra < < 13 ) |
( bcap_val_11n_40 [ core ] < < 8 ) |
( scap_val_11n_40 [ core ] < < 3 ) |
lpf_ofdm_40mhz [ core ] ;
}
2012-07-24 19:18:20 +02:00
for ( core = 0 ; core < 2 ; core + + ) {
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x152 + core * 16 ) ,
2014-07-19 12:52:44 +02:00
rx2tx_lut_20_11b [ core ] ) ;
2012-07-24 19:18:20 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x153 + core * 16 ) ,
2014-07-19 12:52:44 +02:00
rx2tx_lut_20_11n [ core ] ) ;
2012-07-24 19:18:20 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x154 + core * 16 ) ,
2014-07-19 12:52:44 +02:00
rx2tx_lut_20_11n [ core ] ) ;
2012-07-24 19:18:20 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x155 + core * 16 ) ,
2014-07-19 12:52:44 +02:00
rx2tx_lut_40_11n [ core ] ) ;
2012-07-24 19:18:20 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x156 + core * 16 ) ,
2014-07-19 12:52:44 +02:00
rx2tx_lut_40_11n [ core ] ) ;
2012-07-24 19:18:20 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x157 + core * 16 ) ,
2014-07-19 12:52:44 +02:00
rx2tx_lut_40_11n [ core ] ) ;
2012-07-24 19:18:20 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x158 + core * 16 ) ,
2014-07-19 12:52:44 +02:00
rx2tx_lut_40_11n [ core ] ) ;
2012-07-24 19:18:20 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x159 + core * 16 ) ,
2014-07-19 12:52:44 +02:00
rx2tx_lut_40_11n [ core ] ) ;
2012-07-24 19:18:20 +02:00
}
}
2014-07-19 12:52:46 +02:00
2012-07-24 19:18:20 +02:00
b43_phy_write ( dev , 0x32F , 0x3 ) ;
2014-07-19 12:52:46 +02:00
2012-07-24 19:18:20 +02:00
if ( phy - > radio_rev = = 4 | | phy - > radio_rev = = 6 )
2013-03-30 21:50:46 +01:00
b43_nphy_rf_ctl_override_rev7 ( dev , 4 , 1 , 3 , false , 0 ) ;
2012-07-24 19:18:20 +02:00
if ( phy - > radio_rev = = 3 | | phy - > radio_rev = = 4 | | phy - > radio_rev = = 6 ) {
if ( sprom - > revision & &
sprom - > boardflags2_hi & B43_BFH2_IPALVLSHIFT_3P3 ) {
b43_radio_write ( dev , 0x5 , 0x05 ) ;
b43_radio_write ( dev , 0x6 , 0x30 ) ;
b43_radio_write ( dev , 0x7 , 0x00 ) ;
b43_radio_set ( dev , 0x4f , 0x1 ) ;
b43_radio_set ( dev , 0xd4 , 0x1 ) ;
bias = 0x1f ;
conv = 0x6f ;
filt = 0xaa ;
} else {
bias = 0x2b ;
conv = 0x7f ;
filt = 0xee ;
}
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
for ( core = 0 ; core < 2 ; core + + ) {
if ( core = = 0 ) {
b43_radio_write ( dev , 0x5F , bias ) ;
b43_radio_write ( dev , 0x64 , conv ) ;
b43_radio_write ( dev , 0x66 , filt ) ;
} else {
b43_radio_write ( dev , 0xE8 , bias ) ;
b43_radio_write ( dev , 0xE9 , conv ) ;
b43_radio_write ( dev , 0xEB , filt ) ;
}
}
}
}
if ( b43_nphy_ipa ( dev ) ) {
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
if ( phy - > radio_rev = = 3 | | phy - > radio_rev = = 4 | |
phy - > radio_rev = = 6 ) {
for ( core = 0 ; core < 2 ; core + + ) {
if ( core = = 0 )
b43_radio_write ( dev , 0x51 ,
0x7f ) ;
else
b43_radio_write ( dev , 0xd6 ,
0x7f ) ;
}
}
2014-07-19 12:52:43 +02:00
switch ( phy - > radio_rev ) {
case 3 :
2012-07-24 19:18:20 +02:00
for ( core = 0 ; core < 2 ; core + + ) {
if ( core = = 0 ) {
b43_radio_write ( dev , 0x64 ,
0x13 ) ;
b43_radio_write ( dev , 0x5F ,
0x1F ) ;
b43_radio_write ( dev , 0x66 ,
0xEE ) ;
b43_radio_write ( dev , 0x59 ,
0x8A ) ;
b43_radio_write ( dev , 0x80 ,
0x3E ) ;
} else {
b43_radio_write ( dev , 0x69 ,
0x13 ) ;
b43_radio_write ( dev , 0xE8 ,
0x1F ) ;
b43_radio_write ( dev , 0xEB ,
0xEE ) ;
b43_radio_write ( dev , 0xDE ,
0x8A ) ;
b43_radio_write ( dev , 0x105 ,
0x3E ) ;
}
}
2014-07-19 12:52:43 +02:00
break ;
case 7 :
case 8 :
2014-05-31 20:49:40 +02:00
if ( ! b43_is_40mhz ( dev ) ) {
2012-07-24 19:18:20 +02:00
b43_radio_write ( dev , 0x5F , 0x14 ) ;
b43_radio_write ( dev , 0xE8 , 0x12 ) ;
} else {
b43_radio_write ( dev , 0x5F , 0x16 ) ;
b43_radio_write ( dev , 0xE8 , 0x16 ) ;
}
2014-07-19 12:52:43 +02:00
break ;
2014-07-19 12:52:45 +02:00
case 14 :
for ( core = 0 ; core < 2 ; core + + ) {
int o = core ? 0x85 : 0 ;
b43_radio_write ( dev , o + R2057_IPA2G_CASCONV_CORE0 , 0x13 ) ;
b43_radio_write ( dev , o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0 , 0x21 ) ;
b43_radio_write ( dev , o + R2057_IPA2G_BIAS_FILTER_CORE0 , 0xff ) ;
b43_radio_write ( dev , o + R2057_PAD2G_IDACS_CORE0 , 0x88 ) ;
b43_radio_write ( dev , o + R2057_PAD2G_TUNE_PUS_CORE0 , 0x23 ) ;
b43_radio_write ( dev , o + R2057_IPA2G_IMAIN_CORE0 , 0x16 ) ;
b43_radio_write ( dev , o + R2057_PAD_BIAS_FILTER_BWS_CORE0 , 0x3e ) ;
b43_radio_write ( dev , o + R2057_BACKUP1_CORE0 , 0x10 ) ;
}
break ;
2012-07-24 19:18:20 +02:00
}
} else {
2014-05-31 20:49:39 +02:00
u16 freq = phy - > chandef - > chan - > center_freq ;
2012-07-24 19:18:20 +02:00
if ( ( freq > = 5180 & & freq < = 5230 ) | |
( freq > = 5745 & & freq < = 5805 ) ) {
b43_radio_write ( dev , 0x7D , 0xFF ) ;
b43_radio_write ( dev , 0xFE , 0xFF ) ;
}
}
} else {
if ( phy - > radio_rev ! = 5 ) {
for ( core = 0 ; core < 2 ; core + + ) {
if ( core = = 0 ) {
b43_radio_write ( dev , 0x5c , 0x61 ) ;
b43_radio_write ( dev , 0x51 , 0x70 ) ;
} else {
b43_radio_write ( dev , 0xe1 , 0x61 ) ;
b43_radio_write ( dev , 0xd6 , 0x70 ) ;
}
}
}
}
if ( phy - > radio_rev = = 4 ) {
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x05 ) , 0x20 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x15 ) , 0x20 ) ;
for ( core = 0 ; core < 2 ; core + + ) {
if ( core = = 0 ) {
b43_radio_write ( dev , 0x1a1 , 0x00 ) ;
b43_radio_write ( dev , 0x1a2 , 0x3f ) ;
b43_radio_write ( dev , 0x1a6 , 0x3f ) ;
} else {
b43_radio_write ( dev , 0x1a7 , 0x00 ) ;
b43_radio_write ( dev , 0x1ab , 0x3f ) ;
b43_radio_write ( dev , 0x1ac , 0x3f ) ;
}
}
} else {
b43_phy_set ( dev , B43_NPHY_AFECTL_C1 , 0x4 ) ;
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER1 , 0x4 ) ;
b43_phy_set ( dev , B43_NPHY_AFECTL_C2 , 0x4 ) ;
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER , 0x4 ) ;
b43_phy_mask ( dev , B43_NPHY_AFECTL_C1 , ~ 0x1 ) ;
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER1 , 0x1 ) ;
b43_phy_mask ( dev , B43_NPHY_AFECTL_C2 , ~ 0x1 ) ;
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER , 0x1 ) ;
2014-07-19 12:52:46 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x05 ) , 0 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x15 ) , 0 ) ;
2012-07-24 19:18:20 +02:00
b43_phy_mask ( dev , B43_NPHY_AFECTL_C1 , ~ 0x4 ) ;
b43_phy_mask ( dev , B43_NPHY_AFECTL_OVER1 , ~ 0x4 ) ;
b43_phy_mask ( dev , B43_NPHY_AFECTL_C2 , ~ 0x4 ) ;
b43_phy_mask ( dev , B43_NPHY_AFECTL_OVER , ~ 0x4 ) ;
}
b43_phy_write ( dev , B43_NPHY_ENDROP_TLEN , 0x2 ) ;
b43_ntab_write ( dev , B43_NTAB32 ( 16 , 0x100 ) , 20 ) ;
2014-07-19 12:52:46 +02:00
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 7 , 0x138 ) , 2 , ntab7_138_146 ) ;
2012-07-24 19:18:20 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x141 ) , 0x77 ) ;
2014-07-19 12:52:46 +02:00
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 7 , 0x133 ) , 3 , ntab7_133 ) ;
b43_ntab_write_bulk ( dev , B43_NTAB8 ( 7 , 0x146 ) , 2 , ntab7_138_146 ) ;
2012-07-24 19:18:20 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x123 ) , 0x77 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 7 , 0x12A ) , 0x77 ) ;
2014-07-19 12:52:46 +02:00
b43_ntab_read_bulk ( dev , B43_NTAB32 ( 16 , 0x02 ) , 1 , noise_tbl ) ;
noise_tbl [ 1 ] = b43_is_40mhz ( dev ) ? 0x14D : 0x18D ;
b43_ntab_write_bulk ( dev , B43_NTAB32 ( 16 , 0x02 ) , 2 , noise_tbl ) ;
b43_ntab_read_bulk ( dev , B43_NTAB32 ( 16 , 0x7E ) , 1 , noise_tbl ) ;
noise_tbl [ 1 ] = b43_is_40mhz ( dev ) ? 0x14D : 0x18D ;
b43_ntab_write_bulk ( dev , B43_NTAB32 ( 16 , 0x7E ) , 2 , noise_tbl ) ;
2012-07-24 19:18:20 +02:00
b43_nphy_gain_ctl_workarounds ( dev ) ;
/* TODO
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x08 ) , 4 ,
aux_adc_vmid_rev7_core0 ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x18 ) , 4 ,
aux_adc_vmid_rev7_core1 ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x0C ) , 4 ,
aux_adc_gain_rev7 ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x1C ) , 4 ,
aux_adc_gain_rev7 ) ;
*/
}
2011-09-04 23:23:52 +02:00
static void b43_nphy_workarounds_rev3plus ( struct b43_wldev * dev )
2010-01-30 00:12:19 +01:00
{
2011-09-04 23:23:53 +02:00
struct b43_phy_n * nphy = dev - > phy . n ;
2011-05-18 02:06:39 +02:00
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
2010-01-30 00:12:19 +01:00
2011-09-04 23:23:53 +02:00
/* TX to RX */
2014-04-20 13:05:44 +02:00
u8 tx2rx_events [ 7 ] = { 0x4 , 0x3 , 0x5 , 0x2 , 0x1 , 0x8 , 0x1F } ;
u8 tx2rx_delays [ 7 ] = { 8 , 4 , 4 , 4 , 4 , 6 , 1 } ;
2011-09-04 23:23:53 +02:00
/* RX to TX */
u8 rx2tx_events_ipa [ 9 ] = { 0x0 , 0x1 , 0x2 , 0x8 , 0x5 , 0x6 , 0xF , 0x3 ,
0x1F } ;
u8 rx2tx_delays_ipa [ 9 ] = { 8 , 6 , 6 , 4 , 4 , 16 , 43 , 1 , 1 } ;
u8 rx2tx_events [ 9 ] = { 0x0 , 0x1 , 0x2 , 0x8 , 0x5 , 0x6 , 0x3 , 0x4 , 0x1F } ;
u8 rx2tx_delays [ 9 ] = { 8 , 6 , 6 , 4 , 4 , 18 , 42 , 1 , 1 } ;
2014-04-20 13:05:44 +02:00
u16 vmids [ 5 ] [ 4 ] = {
{ 0xa2 , 0xb4 , 0xb4 , 0x89 , } , /* 0 */
{ 0xb4 , 0xb4 , 0xb4 , 0x24 , } , /* 1 */
{ 0xa2 , 0xb4 , 0xb4 , 0x74 , } , /* 2 */
{ 0xa2 , 0xb4 , 0xb4 , 0x270 , } , /* 3 */
{ 0xa2 , 0xb4 , 0xb4 , 0x00 , } , /* 4 and 5 */
} ;
u16 gains [ 5 ] [ 4 ] = {
{ 0x02 , 0x02 , 0x02 , 0x00 , } , /* 0 */
{ 0x02 , 0x02 , 0x02 , 0x02 , } , /* 1 */
{ 0x02 , 0x02 , 0x02 , 0x04 , } , /* 2 */
{ 0x02 , 0x02 , 0x02 , 0x00 , } , /* 3 */
{ 0x02 , 0x02 , 0x02 , 0x00 , } , /* 4 and 5 */
} ;
u16 * vmid , * gain ;
u8 pdet_range ;
2011-03-01 21:40:41 +01:00
u16 tmp16 ;
u32 tmp32 ;
2013-03-29 11:13:40 +01:00
b43_phy_write ( dev , B43_NPHY_FORCEFRONT0 , 0x1f8 ) ;
b43_phy_write ( dev , B43_NPHY_FORCEFRONT1 , 0x1f8 ) ;
2011-12-11 02:55:29 +01:00
2011-09-04 23:23:52 +02:00
tmp32 = b43_ntab_read ( dev , B43_NTAB32 ( 30 , 0 ) ) ;
tmp32 & = 0xffffff ;
b43_ntab_write ( dev , B43_NTAB32 ( 30 , 0 ) , tmp32 ) ;
2010-01-30 00:12:19 +01:00
2011-09-04 23:23:52 +02:00
b43_phy_write ( dev , B43_NPHY_PHASETR_A0 , 0x0125 ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_A1 , 0x01B3 ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_A2 , 0x0105 ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_B0 , 0x016E ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_B1 , 0x00CD ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_B2 , 0x0020 ) ;
2010-01-30 00:12:19 +01:00
2013-03-29 11:13:40 +01:00
b43_phy_write ( dev , B43_NPHY_REV3_C1_CLIP_LOGAIN_B , 0x000C ) ;
b43_phy_write ( dev , B43_NPHY_REV3_C2_CLIP_LOGAIN_B , 0x000C ) ;
2011-03-01 21:40:41 +01:00
2011-09-04 23:23:53 +02:00
/* TX to RX */
2011-12-11 02:55:29 +01:00
b43_nphy_set_rf_sequence ( dev , 1 , tx2rx_events , tx2rx_delays ,
ARRAY_SIZE ( tx2rx_events ) ) ;
2011-09-04 23:23:53 +02:00
/* RX to TX */
if ( b43_nphy_ipa ( dev ) )
2011-12-11 02:55:29 +01:00
b43_nphy_set_rf_sequence ( dev , 0 , rx2tx_events_ipa ,
rx2tx_delays_ipa , ARRAY_SIZE ( rx2tx_events_ipa ) ) ;
2011-09-04 23:23:53 +02:00
if ( nphy - > hw_phyrxchain ! = 3 & &
nphy - > hw_phyrxchain ! = nphy - > hw_phytxchain ) {
if ( b43_nphy_ipa ( dev ) ) {
rx2tx_delays [ 5 ] = 59 ;
rx2tx_delays [ 6 ] = 1 ;
rx2tx_events [ 7 ] = 0x1F ;
}
2012-07-24 19:18:19 +02:00
b43_nphy_set_rf_sequence ( dev , 0 , rx2tx_events , rx2tx_delays ,
2011-12-11 02:55:29 +01:00
ARRAY_SIZE ( rx2tx_events ) ) ;
2011-09-04 23:23:53 +02:00
}
2011-03-01 21:40:41 +01:00
2011-09-04 23:23:52 +02:00
tmp16 = ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) ?
0x2 : 0x9C40 ;
b43_phy_write ( dev , B43_NPHY_ENDROP_TLEN , tmp16 ) ;
2011-03-01 21:40:41 +01:00
2013-03-29 11:13:40 +01:00
b43_phy_maskset ( dev , B43_NPHY_SGILTRNOFFSET , 0xF0FF , 0x0700 ) ;
2011-03-01 21:40:41 +01:00
2014-05-31 20:49:40 +02:00
if ( ! b43_is_40mhz ( dev ) ) {
2012-07-24 19:18:19 +02:00
b43_ntab_write ( dev , B43_NTAB32 ( 16 , 3 ) , 0x18D ) ;
b43_ntab_write ( dev , B43_NTAB32 ( 16 , 127 ) , 0x18D ) ;
} else {
b43_ntab_write ( dev , B43_NTAB32 ( 16 , 3 ) , 0x14D ) ;
b43_ntab_write ( dev , B43_NTAB32 ( 16 , 127 ) , 0x14D ) ;
}
2011-03-01 21:40:41 +01:00
2011-12-17 13:57:26 +01:00
b43_nphy_gain_ctl_workarounds ( dev ) ;
2011-03-01 21:40:41 +01:00
2011-12-11 02:55:29 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0 ) , 2 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 16 ) , 2 ) ;
2011-03-01 21:40:41 +01:00
2014-04-20 13:05:44 +02:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
pdet_range = sprom - > fem . ghz2 . pdet_range ;
else
pdet_range = sprom - > fem . ghz5 . pdet_range ;
vmid = vmids [ min_t ( u16 , pdet_range , 4 ) ] ;
gain = gains [ min_t ( u16 , pdet_range , 4 ) ] ;
switch ( pdet_range ) {
case 3 :
if ( ! ( dev - > phy . rev > = 4 & &
b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) )
break ;
/* FALL THROUGH */
case 0 :
case 1 :
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x08 ) , 4 , vmid ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x18 ) , 4 , vmid ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x0c ) , 4 , gain ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x1c ) , 4 , gain ) ;
break ;
case 2 :
if ( dev - > phy . rev > = 6 ) {
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
vmid [ 3 ] = 0x94 ;
else
vmid [ 3 ] = 0x8e ;
gain [ 3 ] = 3 ;
} else if ( dev - > phy . rev = = 5 ) {
vmid [ 3 ] = 0x84 ;
gain [ 3 ] = 2 ;
}
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x08 ) , 4 , vmid ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x18 ) , 4 , vmid ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x0c ) , 4 , gain ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x1c ) , 4 , gain ) ;
break ;
case 4 :
case 5 :
if ( b43_current_band ( dev - > wl ) ! = IEEE80211_BAND_2GHZ ) {
if ( pdet_range = = 4 ) {
vmid [ 3 ] = 0x8e ;
tmp16 = 0x96 ;
gain [ 3 ] = 0x2 ;
} else {
vmid [ 3 ] = 0x89 ;
tmp16 = 0x89 ;
gain [ 3 ] = 0 ;
}
} else {
if ( pdet_range = = 4 ) {
vmid [ 3 ] = 0x89 ;
tmp16 = 0x8b ;
gain [ 3 ] = 0x2 ;
} else {
vmid [ 3 ] = 0x74 ;
tmp16 = 0x70 ;
gain [ 3 ] = 0 ;
}
}
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x08 ) , 4 , vmid ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x0c ) , 4 , gain ) ;
vmid [ 3 ] = tmp16 ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x18 ) , 4 , vmid ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 8 , 0x1c ) , 4 , gain ) ;
break ;
}
2011-03-01 21:40:41 +01:00
2011-09-04 23:23:52 +02:00
b43_radio_write ( dev , B2056_RX0 | B2056_RX_MIXA_MAST_BIAS , 0x00 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_MIXA_MAST_BIAS , 0x00 ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN , 0x06 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN , 0x06 ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_MIXA_BIAS_AUX , 0x07 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_MIXA_BIAS_AUX , 0x07 ) ;
b43_radio_write ( dev , B2056_RX0 | B2056_RX_MIXA_LOB_BIAS , 0x88 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_MIXA_LOB_BIAS , 0x88 ) ;
2011-12-11 02:55:29 +01:00
b43_radio_write ( dev , B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC , 0x00 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC , 0x00 ) ;
2011-09-04 23:23:52 +02:00
b43_radio_write ( dev , B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC , 0x00 ) ;
b43_radio_write ( dev , B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC , 0x00 ) ;
/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
if ( ( sprom - > boardflags2_lo & B43_BFL2_APLL_WAR & &
b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) | |
( sprom - > boardflags2_lo & B43_BFL2_GPLL_WAR & &
b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) )
tmp32 = 0x00088888 ;
else
tmp32 = 0x88888888 ;
b43_ntab_write ( dev , B43_NTAB32 ( 30 , 1 ) , tmp32 ) ;
b43_ntab_write ( dev , B43_NTAB32 ( 30 , 2 ) , tmp32 ) ;
b43_ntab_write ( dev , B43_NTAB32 ( 30 , 3 ) , tmp32 ) ;
if ( dev - > phy . rev = = 4 & &
2012-07-24 19:18:19 +02:00
b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
2011-09-04 23:23:52 +02:00
b43_radio_write ( dev , B2056_TX0 | B2056_TX_GMBB_IDAC ,
0x70 ) ;
b43_radio_write ( dev , B2056_TX1 | B2056_TX_GMBB_IDAC ,
0x70 ) ;
}
2011-03-01 21:40:41 +01:00
2012-07-24 19:18:19 +02:00
/* Dropped probably-always-true condition */
2013-03-29 11:13:40 +01:00
b43_phy_write ( dev , B43_NPHY_ED_CRS40ASSERTTHRESH0 , 0x03eb ) ;
b43_phy_write ( dev , B43_NPHY_ED_CRS40ASSERTTHRESH1 , 0x03eb ) ;
2014-04-20 13:05:45 +02:00
b43_phy_write ( dev , B43_NPHY_ED_CRS40DEASSERTTHRESH0 , 0x0341 ) ;
2013-03-29 11:13:40 +01:00
b43_phy_write ( dev , B43_NPHY_ED_CRS40DEASSERTTHRESH1 , 0x0341 ) ;
b43_phy_write ( dev , B43_NPHY_ED_CRS20LASSERTTHRESH0 , 0x042b ) ;
b43_phy_write ( dev , B43_NPHY_ED_CRS20LASSERTTHRESH1 , 0x042b ) ;
b43_phy_write ( dev , B43_NPHY_ED_CRS20LDEASSERTTHRESH0 , 0x0381 ) ;
b43_phy_write ( dev , B43_NPHY_ED_CRS20LDEASSERTTHRESH1 , 0x0381 ) ;
b43_phy_write ( dev , B43_NPHY_ED_CRS20UASSERTTHRESH0 , 0x042b ) ;
b43_phy_write ( dev , B43_NPHY_ED_CRS20UASSERTTHRESH1 , 0x042b ) ;
b43_phy_write ( dev , B43_NPHY_ED_CRS20UDEASSERTTHRESH0 , 0x0381 ) ;
b43_phy_write ( dev , B43_NPHY_ED_CRS20UDEASSERTTHRESH1 , 0x0381 ) ;
2012-07-24 19:18:19 +02:00
if ( dev - > phy . rev > = 6 & & sprom - > boardflags2_lo & B43_BFL2_SINGLEANT_CCK )
; /* TODO: 0x0080000000000000 HF */
2011-09-04 23:23:52 +02:00
}
2011-03-01 21:40:41 +01:00
2011-09-04 23:23:52 +02:00
static void b43_nphy_workarounds_rev1_2 ( struct b43_wldev * dev )
{
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = phy - > n ;
2011-03-01 21:40:41 +01:00
2011-09-04 23:23:52 +02:00
u8 events1 [ 7 ] = { 0x0 , 0x1 , 0x2 , 0x8 , 0x4 , 0x5 , 0x3 } ;
u8 delays1 [ 7 ] = { 0x8 , 0x6 , 0x6 , 0x2 , 0x4 , 0x3C , 0x1 } ;
2011-03-01 21:40:41 +01:00
2011-09-04 23:23:52 +02:00
u8 events2 [ 7 ] = { 0x0 , 0x3 , 0x5 , 0x4 , 0x2 , 0x1 , 0x8 } ;
u8 delays2 [ 7 ] = { 0x8 , 0x6 , 0x2 , 0x4 , 0x4 , 0x6 , 0x1 } ;
2011-03-01 21:40:41 +01:00
2012-07-24 19:18:19 +02:00
if ( sprom - > boardflags2_lo & B43_BFL2_SKWRKFEM_BRD | |
2013-03-28 22:25:38 +01:00
dev - > dev - > board_type = = BCMA_BOARD_TYPE_BCM943224M93 ) {
2012-07-24 19:18:19 +02:00
delays1 [ 0 ] = 0x1 ;
delays1 [ 5 ] = 0x14 ;
}
2011-09-04 23:23:52 +02:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ & &
nphy - > band5g_pwrgain ) {
b43_radio_mask ( dev , B2055_C1_TX_RF_SPARE , ~ 0x8 ) ;
b43_radio_mask ( dev , B2055_C2_TX_RF_SPARE , ~ 0x8 ) ;
2010-01-30 00:12:19 +01:00
} else {
2011-09-04 23:23:52 +02:00
b43_radio_set ( dev , B2055_C1_TX_RF_SPARE , 0x8 ) ;
b43_radio_set ( dev , B2055_C2_TX_RF_SPARE , 0x8 ) ;
}
2010-01-30 00:12:19 +01:00
2011-09-04 23:23:52 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x00 ) , 0x000A ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x10 ) , 0x000A ) ;
2012-07-24 19:18:19 +02:00
if ( dev - > phy . rev < 3 ) {
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x02 ) , 0xCDAA ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x12 ) , 0xCDAA ) ;
}
2011-09-04 23:23:52 +02:00
if ( dev - > phy . rev < 2 ) {
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x08 ) , 0x0000 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x18 ) , 0x0000 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x07 ) , 0x7AAB ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x17 ) , 0x7AAB ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x06 ) , 0x0800 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 0x16 ) , 0x0800 ) ;
}
2010-01-30 00:12:19 +01:00
2011-09-04 23:23:52 +02:00
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_LO1 , 0x2D8 ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_UP1 , 0x301 ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_LO2 , 0x2D8 ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_UP2 , 0x301 ) ;
2010-01-30 00:12:19 +01:00
2011-09-04 23:23:52 +02:00
b43_nphy_set_rf_sequence ( dev , 0 , events1 , delays1 , 7 ) ;
b43_nphy_set_rf_sequence ( dev , 1 , events2 , delays2 , 7 ) ;
2011-12-17 13:57:26 +01:00
b43_nphy_gain_ctl_workarounds ( dev ) ;
2011-09-04 23:23:52 +02:00
if ( dev - > phy . rev < 2 ) {
if ( b43_phy_read ( dev , B43_NPHY_RXCTL ) & 0x2 )
b43_hf_write ( dev , b43_hf_read ( dev ) |
B43_HF_MLADVW ) ;
} else if ( dev - > phy . rev = = 2 ) {
b43_phy_write ( dev , B43_NPHY_CRSCHECK2 , 0 ) ;
b43_phy_write ( dev , B43_NPHY_CRSCHECK3 , 0 ) ;
}
2010-01-30 00:12:19 +01:00
2011-09-04 23:23:52 +02:00
if ( dev - > phy . rev < 2 )
b43_phy_mask ( dev , B43_NPHY_SCRAM_SIGCTL ,
~ B43_NPHY_SCRAM_SIGCTL_SCM ) ;
/* Set phase track alpha and beta */
b43_phy_write ( dev , B43_NPHY_PHASETR_A0 , 0x125 ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_A1 , 0x1B3 ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_A2 , 0x105 ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_B0 , 0x16E ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_B1 , 0xCD ) ;
b43_phy_write ( dev , B43_NPHY_PHASETR_B2 , 0x20 ) ;
2012-07-24 19:18:19 +02:00
if ( dev - > phy . rev < 3 ) {
b43_phy_mask ( dev , B43_NPHY_PIL_DW1 ,
~ B43_NPHY_PIL_DW_64QAM & 0xFFFF ) ;
b43_phy_write ( dev , B43_NPHY_TXF_20CO_S2B1 , 0xB5 ) ;
b43_phy_write ( dev , B43_NPHY_TXF_20CO_S2B2 , 0xA4 ) ;
b43_phy_write ( dev , B43_NPHY_TXF_20CO_S2B3 , 0x00 ) ;
}
2011-09-04 23:23:52 +02:00
if ( dev - > phy . rev = = 2 )
b43_phy_set ( dev , B43_NPHY_FINERX2_CGC ,
B43_NPHY_FINERX2_CGC_DECGC ) ;
}
2010-01-30 00:12:19 +01:00
2011-09-04 23:23:52 +02:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
static void b43_nphy_workarounds ( struct b43_wldev * dev )
{
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = phy - > n ;
2010-01-30 00:12:19 +01:00
2011-09-04 23:23:52 +02:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ )
b43_nphy_classifier ( dev , 1 , 0 ) ;
else
b43_nphy_classifier ( dev , 1 , 1 ) ;
2010-01-30 00:12:19 +01:00
2011-09-04 23:23:52 +02:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 1 ) ;
b43_phy_set ( dev , B43_NPHY_IQFLIP ,
B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2 ) ;
2014-07-08 15:11:06 +02:00
/* TODO: rev19+ */
2012-07-24 19:18:20 +02:00
if ( dev - > phy . rev > = 7 )
b43_nphy_workarounds_rev7plus ( dev ) ;
else if ( dev - > phy . rev > = 3 )
2011-09-04 23:23:52 +02:00
b43_nphy_workarounds_rev3plus ( dev ) ;
else
b43_nphy_workarounds_rev1_2 ( dev ) ;
2010-01-30 00:12:19 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 0 ) ;
}
2011-12-20 22:45:47 +01:00
/**************************************************
* Tx / Rx common
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Transmits a known value for LO calibration
* http : //bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
*/
static int b43_nphy_tx_tone ( struct b43_wldev * dev , u32 freq , u16 max_val ,
2014-06-22 23:18:21 +02:00
bool iqmode , bool dac_test , bool modify_bbmult )
2011-12-20 22:45:47 +01:00
{
u16 samp = b43_nphy_gen_load_samples ( dev , freq , max_val , dac_test ) ;
if ( samp = = 0 )
return - 1 ;
2014-06-22 23:18:21 +02:00
b43_nphy_run_samples ( dev , samp , 0xFFFF , 0 , iqmode , dac_test ,
modify_bbmult ) ;
2011-12-20 22:45:47 +01:00
return 0 ;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
static void b43_nphy_update_txrx_chain ( struct b43_wldev * dev )
{
struct b43_phy_n * nphy = dev - > phy . n ;
bool override = false ;
u16 chain = 0x33 ;
if ( nphy - > txrx_chain = = 0 ) {
chain = 0x11 ;
override = true ;
} else if ( nphy - > txrx_chain = = 1 ) {
chain = 0x22 ;
override = true ;
}
b43_phy_maskset ( dev , B43_NPHY_RFSEQCA ,
~ ( B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN ) ,
chain ) ;
if ( override )
b43_phy_set ( dev , B43_NPHY_RFSEQMODE ,
B43_NPHY_RFSEQMODE_CAOVER ) ;
else
b43_phy_mask ( dev , B43_NPHY_RFSEQMODE ,
~ B43_NPHY_RFSEQMODE_CAOVER ) ;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
static void b43_nphy_stop_playback ( struct b43_wldev * dev )
{
2014-07-08 15:11:07 +02:00
struct b43_phy * phy = & dev - > phy ;
2011-12-20 22:45:47 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
u16 tmp ;
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 1 ) ;
tmp = b43_phy_read ( dev , B43_NPHY_SAMP_STAT ) ;
if ( tmp & 0x1 )
b43_phy_set ( dev , B43_NPHY_SAMP_CMD , B43_NPHY_SAMP_CMD_STOP ) ;
else if ( tmp & 0x2 )
b43_phy_mask ( dev , B43_NPHY_IQLOCAL_CMDGCTL , 0x7FFF ) ;
b43_phy_mask ( dev , B43_NPHY_SAMP_CMD , ~ 0x0004 ) ;
if ( nphy - > bb_mult_save & 0x80000000 ) {
tmp = nphy - > bb_mult_save & 0xFFFF ;
b43_ntab_write ( dev , B43_NTAB16 ( 15 , 87 ) , tmp ) ;
nphy - > bb_mult_save = 0 ;
}
2014-07-22 21:31:05 +02:00
if ( phy - > rev > = 7 & & nphy - > lpf_bw_overrode_for_sample_play ) {
2014-07-08 15:11:07 +02:00
if ( phy - > rev > = 19 )
b43_nphy_rf_ctl_override_rev19 ( dev , 0x80 , 0 , 0 , true ,
1 ) ;
else
b43_nphy_rf_ctl_override_rev7 ( dev , 0x80 , 0 , 0 , true , 1 ) ;
nphy - > lpf_bw_overrode_for_sample_play = false ;
2014-07-08 15:11:06 +02:00
}
2011-12-20 22:45:47 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 0 ) ;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
static void b43_nphy_iq_cal_gain_params ( struct b43_wldev * dev , u16 core ,
struct nphy_txgains target ,
struct nphy_iqcal_params * params )
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2011-12-20 22:45:47 +01:00
int i , j , indx ;
u16 gain ;
if ( dev - > phy . rev > = 3 ) {
2014-07-08 15:11:07 +02:00
params - > tx_lpf = target . tx_lpf [ core ] ; /* Rev 7+ */
2011-12-20 22:45:47 +01:00
params - > txgm = target . txgm [ core ] ;
params - > pga = target . pga [ core ] ;
params - > pad = target . pad [ core ] ;
params - > ipa = target . ipa [ core ] ;
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 7 ) {
2014-07-08 15:11:07 +02:00
params - > cal_gain = ( params - > txgm < < 12 ) | ( params - > pga < < 8 ) | ( params - > pad < < 3 ) | ( params - > ipa ) | ( params - > tx_lpf < < 15 ) ;
2014-07-08 15:11:06 +02:00
} else {
params - > cal_gain = ( params - > txgm < < 12 ) | ( params - > pga < < 8 ) | ( params - > pad < < 4 ) | ( params - > ipa ) ;
}
2011-12-20 22:45:47 +01:00
for ( j = 0 ; j < 5 ; j + + )
params - > ncorr [ j ] = 0x79 ;
} else {
gain = ( target . pad [ core ] ) | ( target . pga [ core ] < < 4 ) |
( target . txgm [ core ] < < 8 ) ;
indx = ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) ?
1 : 0 ;
for ( i = 0 ; i < 9 ; i + + )
if ( tbl_iqcal_gainparams [ indx ] [ i ] [ 0 ] = = gain )
break ;
i = min ( i , 8 ) ;
params - > txgm = tbl_iqcal_gainparams [ indx ] [ i ] [ 1 ] ;
params - > pga = tbl_iqcal_gainparams [ indx ] [ i ] [ 2 ] ;
params - > pad = tbl_iqcal_gainparams [ indx ] [ i ] [ 3 ] ;
params - > cal_gain = ( params - > txgm < < 7 ) | ( params - > pga < < 4 ) |
( params - > pad < < 2 ) ;
for ( j = 0 ; j < 4 ; j + + )
params - > ncorr [ j ] = tbl_iqcal_gainparams [ indx ] [ i ] [ 4 + j ] ;
}
}
2011-12-17 13:57:21 +01:00
/**************************************************
2011-12-17 13:57:27 +01:00
* Tx and Rx
2011-12-17 13:57:21 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-02-04 13:08:08 +01:00
2010-11-28 12:59:43 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
static void b43_nphy_tx_power_ctrl ( struct b43_wldev * dev , bool enable )
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2010-11-28 12:59:43 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
u8 i ;
2011-09-01 22:49:57 +02:00
u16 bmask , val , tmp ;
enum ieee80211_band band = b43_current_band ( dev - > wl ) ;
2010-01-22 01:53:16 +01:00
2010-11-28 12:59:43 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 1 ) ;
2010-01-22 01:53:16 +01:00
2010-11-28 12:59:43 +01:00
nphy - > txpwrctrl = enable ;
if ( ! enable ) {
2011-09-01 22:49:57 +02:00
if ( dev - > phy . rev > = 3 & &
( b43_phy_read ( dev , B43_NPHY_TXPCTL_CMD ) &
( B43_NPHY_TXPCTL_CMD_COEFF |
B43_NPHY_TXPCTL_CMD_HWPCTLEN |
B43_NPHY_TXPCTL_CMD_PCTLEN ) ) ) {
/* We disable enabled TX pwr ctl, save it's state */
nphy - > tx_pwr_idx [ 0 ] = b43_phy_read ( dev ,
B43_NPHY_C1_TXPCTL_STAT ) & 0x7f ;
nphy - > tx_pwr_idx [ 1 ] = b43_phy_read ( dev ,
B43_NPHY_C2_TXPCTL_STAT ) & 0x7f ;
}
2010-01-22 01:53:16 +01:00
2010-11-28 12:59:43 +01:00
b43_phy_write ( dev , B43_NPHY_TABLE_ADDR , 0x6840 ) ;
for ( i = 0 ; i < 84 ; i + + )
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0 ) ;
2010-01-22 01:53:16 +01:00
2010-11-28 12:59:43 +01:00
b43_phy_write ( dev , B43_NPHY_TABLE_ADDR , 0x6C40 ) ;
for ( i = 0 ; i < 84 ; i + + )
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO , 0 ) ;
2010-01-22 01:53:16 +01:00
2010-11-28 12:59:43 +01:00
tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN ;
if ( dev - > phy . rev > = 3 )
tmp | = B43_NPHY_TXPCTL_CMD_PCTLEN ;
b43_phy_mask ( dev , B43_NPHY_TXPCTL_CMD , ~ tmp ) ;
2010-01-22 01:53:16 +01:00
2010-11-28 12:59:43 +01:00
if ( dev - > phy . rev > = 3 ) {
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER1 , 0x0100 ) ;
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER , 0x0100 ) ;
} else {
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER , 0x4000 ) ;
}
2010-01-22 01:53:14 +01:00
2010-11-28 12:59:43 +01:00
if ( dev - > phy . rev = = 2 )
b43_phy_maskset ( dev , B43_NPHY_BPHY_CTL3 ,
~ B43_NPHY_BPHY_CTL3_SCALE , 0x53 ) ;
else if ( dev - > phy . rev < 2 )
b43_phy_maskset ( dev , B43_NPHY_BPHY_CTL3 ,
~ B43_NPHY_BPHY_CTL3_SCALE , 0x5A ) ;
2010-01-22 01:53:14 +01:00
2014-05-31 20:49:40 +02:00
if ( dev - > phy . rev < 2 & & b43_is_40mhz ( dev ) )
2011-09-01 22:49:57 +02:00
b43_hf_write ( dev , b43_hf_read ( dev ) | B43_HF_TSSIRPSMW ) ;
2010-11-28 12:59:43 +01:00
} else {
2011-09-01 22:49:57 +02:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 26 , 64 ) , 84 ,
nphy - > adj_pwr_tbl ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 27 , 64 ) , 84 ,
nphy - > adj_pwr_tbl ) ;
2010-01-22 01:53:14 +01:00
2011-09-01 22:49:57 +02:00
bmask = B43_NPHY_TXPCTL_CMD_COEFF |
B43_NPHY_TXPCTL_CMD_HWPCTLEN ;
/* wl does useless check for "enable" param here */
val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN ;
if ( dev - > phy . rev > = 3 ) {
bmask | = B43_NPHY_TXPCTL_CMD_PCTLEN ;
if ( val )
val | = B43_NPHY_TXPCTL_CMD_PCTLEN ;
}
b43_phy_maskset ( dev , B43_NPHY_TXPCTL_CMD , ~ ( bmask ) , val ) ;
2010-01-22 01:53:14 +01:00
2011-09-01 22:49:57 +02:00
if ( band = = IEEE80211_BAND_5GHZ ) {
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 7 ) {
2014-07-08 15:11:07 +02:00
b43_phy_maskset ( dev , B43_NPHY_TXPCTL_CMD ,
~ B43_NPHY_TXPCTL_CMD_INIT ,
0x32 ) ;
b43_phy_maskset ( dev , B43_NPHY_TXPCTL_INIT ,
~ B43_NPHY_TXPCTL_INIT_PIDXI1 ,
0x32 ) ;
2014-07-08 15:11:06 +02:00
} else {
b43_phy_maskset ( dev , B43_NPHY_TXPCTL_CMD ,
~ B43_NPHY_TXPCTL_CMD_INIT ,
2011-09-01 22:49:57 +02:00
0x64 ) ;
2014-07-08 15:11:06 +02:00
if ( phy - > rev > 1 )
b43_phy_maskset ( dev ,
B43_NPHY_TXPCTL_INIT ,
~ B43_NPHY_TXPCTL_INIT_PIDXI1 ,
0x64 ) ;
}
2011-09-01 22:49:57 +02:00
}
2010-01-22 01:53:14 +01:00
2011-09-01 22:49:57 +02:00
if ( dev - > phy . rev > = 3 ) {
if ( nphy - > tx_pwr_idx [ 0 ] ! = 128 & &
nphy - > tx_pwr_idx [ 1 ] ! = 128 ) {
/* Recover TX pwr ctl state */
b43_phy_maskset ( dev , B43_NPHY_TXPCTL_CMD ,
~ B43_NPHY_TXPCTL_CMD_INIT ,
nphy - > tx_pwr_idx [ 0 ] ) ;
if ( dev - > phy . rev > 1 )
b43_phy_maskset ( dev ,
B43_NPHY_TXPCTL_INIT ,
~ 0xff , nphy - > tx_pwr_idx [ 1 ] ) ;
}
}
2010-01-22 01:53:14 +01:00
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 7 ) {
/* TODO */
}
2011-09-01 22:49:57 +02:00
if ( dev - > phy . rev > = 3 ) {
b43_phy_mask ( dev , B43_NPHY_AFECTL_OVER1 , ~ 0x100 ) ;
b43_phy_mask ( dev , B43_NPHY_AFECTL_OVER , ~ 0x100 ) ;
} else {
b43_phy_mask ( dev , B43_NPHY_AFECTL_OVER , ~ 0x4000 ) ;
}
2010-01-22 01:53:14 +01:00
2011-09-01 22:49:57 +02:00
if ( dev - > phy . rev = = 2 )
b43_phy_maskset ( dev , B43_NPHY_BPHY_CTL3 , ~ 0xFF , 0x3b ) ;
else if ( dev - > phy . rev < 2 )
b43_phy_maskset ( dev , B43_NPHY_BPHY_CTL3 , ~ 0xFF , 0x40 ) ;
2010-01-22 01:53:14 +01:00
2014-05-31 20:49:40 +02:00
if ( dev - > phy . rev < 2 & & b43_is_40mhz ( dev ) )
2011-09-01 22:49:57 +02:00
b43_hf_write ( dev , b43_hf_read ( dev ) & ~ B43_HF_TSSIRPSMW ) ;
2010-01-22 01:53:14 +01:00
2011-09-04 23:18:22 +02:00
if ( b43_nphy_ipa ( dev ) ) {
2011-09-01 22:49:57 +02:00
b43_phy_mask ( dev , B43_NPHY_PAPD_EN0 , ~ 0x4 ) ;
b43_phy_mask ( dev , B43_NPHY_PAPD_EN1 , ~ 0x4 ) ;
2010-01-22 01:53:14 +01:00
}
}
2010-11-28 12:59:43 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 0 ) ;
2010-01-22 01:53:16 +01:00
}
2010-11-28 12:59:43 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
2008-01-14 00:05:57 +01:00
static void b43_nphy_tx_power_fix ( struct b43_wldev * dev )
2010-01-15 16:24:57 +01:00
{
2014-05-31 20:49:39 +02:00
struct b43_phy * phy = & dev - > phy ;
2010-01-15 16:24:57 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
2011-05-18 02:06:39 +02:00
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
2010-01-15 16:24:57 +01:00
2010-11-28 12:59:43 +01:00
u8 txpi [ 2 ] , bbmult , i ;
u16 tmp , radio_gain , dac_gain ;
2014-05-31 20:49:39 +02:00
u16 freq = phy - > chandef - > chan - > center_freq ;
2010-11-28 12:59:43 +01:00
u32 txgain ;
/* u32 gaintbl; rev3+ */
2010-01-15 16:24:57 +01:00
if ( nphy - > hang_avoid )
2010-11-28 12:59:43 +01:00
b43_nphy_stay_in_carrier_search ( dev , 1 ) ;
2010-01-15 16:24:57 +01:00
2014-07-08 15:11:06 +02:00
/* TODO: rev19+ */
2011-12-12 23:40:22 +01:00
if ( dev - > phy . rev > = 7 ) {
txpi [ 0 ] = txpi [ 1 ] = 30 ;
} else if ( dev - > phy . rev > = 3 ) {
2010-11-28 12:59:43 +01:00
txpi [ 0 ] = 40 ;
txpi [ 1 ] = 40 ;
} else if ( sprom - > revision < 4 ) {
txpi [ 0 ] = 72 ;
txpi [ 1 ] = 72 ;
} else {
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
txpi [ 0 ] = sprom - > txpid2g [ 0 ] ;
txpi [ 1 ] = sprom - > txpid2g [ 1 ] ;
} else if ( freq > = 4900 & & freq < 5100 ) {
txpi [ 0 ] = sprom - > txpid5gl [ 0 ] ;
txpi [ 1 ] = sprom - > txpid5gl [ 1 ] ;
} else if ( freq > = 5100 & & freq < 5500 ) {
txpi [ 0 ] = sprom - > txpid5g [ 0 ] ;
txpi [ 1 ] = sprom - > txpid5g [ 1 ] ;
} else if ( freq > = 5500 ) {
txpi [ 0 ] = sprom - > txpid5gh [ 0 ] ;
txpi [ 1 ] = sprom - > txpid5gh [ 1 ] ;
} else {
txpi [ 0 ] = 91 ;
txpi [ 1 ] = 91 ;
2010-01-15 16:24:57 +01:00
}
}
2011-12-12 23:40:22 +01:00
if ( dev - > phy . rev < 7 & &
2011-12-22 00:47:19 +01:00
( txpi [ 0 ] < 40 | | txpi [ 0 ] > 100 | | txpi [ 1 ] < 40 | | txpi [ 1 ] > 100 ) )
2011-12-12 23:40:22 +01:00
txpi [ 0 ] = txpi [ 1 ] = 91 ;
2010-01-15 16:24:57 +01:00
2010-11-28 12:59:43 +01:00
/*
for ( i = 0 ; i < 2 ; i + + ) {
nphy - > txpwrindex [ i ] . index_internal = txpi [ i ] ;
nphy - > txpwrindex [ i ] . index_internal_save = txpi [ i ] ;
2008-01-18 01:09:25 +01:00
}
2010-11-28 12:59:43 +01:00
*/
2010-01-22 01:53:13 +01:00
2010-11-28 12:59:43 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
2014-07-02 22:42:45 +02:00
const u32 * table = b43_nphy_get_tx_gain_table ( dev ) ;
if ( ! table )
break ;
txgain = * ( table + txpi [ i ] ) ;
2012-01-03 22:49:17 +01:00
if ( dev - > phy . rev > = 3 )
2010-11-28 12:59:43 +01:00
radio_gain = ( txgain > > 16 ) & 0x1FFFF ;
2012-01-03 22:49:17 +01:00
else
2010-11-28 12:59:43 +01:00
radio_gain = ( txgain > > 16 ) & 0x1FFF ;
2010-01-22 01:53:13 +01:00
2011-12-12 23:40:22 +01:00
if ( dev - > phy . rev > = 7 )
dac_gain = ( txgain > > 8 ) & 0x7 ;
else
dac_gain = ( txgain > > 8 ) & 0x3F ;
2010-11-28 12:59:43 +01:00
bbmult = txgain & 0xFF ;
2010-01-22 01:53:13 +01:00
2010-11-28 12:59:43 +01:00
if ( dev - > phy . rev > = 3 ) {
if ( i = = 0 )
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER1 , 0x0100 ) ;
else
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER , 0x0100 ) ;
} else {
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER , 0x4000 ) ;
}
2010-01-22 01:53:13 +01:00
2010-11-28 12:59:43 +01:00
if ( i = = 0 )
b43_phy_write ( dev , B43_NPHY_AFECTL_DACGAIN1 , dac_gain ) ;
else
b43_phy_write ( dev , B43_NPHY_AFECTL_DACGAIN2 , dac_gain ) ;
2010-01-22 01:53:13 +01:00
2011-09-04 23:23:51 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 0x7 , 0x110 + i ) , radio_gain ) ;
2010-01-22 01:53:13 +01:00
2011-09-04 23:23:51 +02:00
tmp = b43_ntab_read ( dev , B43_NTAB16 ( 0xF , 0x57 ) ) ;
2010-11-28 12:59:43 +01:00
if ( i = = 0 )
tmp = ( tmp & 0x00FF ) | ( bbmult < < 8 ) ;
else
tmp = ( tmp & 0xFF00 ) | bbmult ;
2011-09-04 23:23:51 +02:00
b43_ntab_write ( dev , B43_NTAB16 ( 0xF , 0x57 ) , tmp ) ;
2010-11-28 12:59:43 +01:00
2011-09-04 23:23:53 +02:00
if ( b43_nphy_ipa ( dev ) ) {
u32 tmp32 ;
u16 reg = ( i = = 0 ) ?
B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1 ;
2011-12-12 23:40:22 +01:00
tmp32 = b43_ntab_read ( dev , B43_NTAB32 ( 26 + i ,
576 + txpi [ i ] ) ) ;
2011-09-04 23:23:53 +02:00
b43_phy_maskset ( dev , reg , 0xE00F , ( u32 ) tmp32 < < 4 ) ;
b43_phy_set ( dev , reg , 0x4 ) ;
2010-01-22 01:53:13 +01:00
}
}
2010-11-28 12:59:43 +01:00
b43_phy_mask ( dev , B43_NPHY_BPHY_CTL2 , ~ B43_NPHY_BPHY_CTL2_LUT ) ;
2010-02-04 12:23:08 +01:00
2010-11-28 12:59:43 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 0 ) ;
2008-01-14 00:05:57 +01:00
}
2010-02-04 12:23:08 +01:00
2011-12-20 22:45:49 +01:00
static void b43_nphy_ipa_internal_tssi_setup ( struct b43_wldev * dev )
{
struct b43_phy * phy = & dev - > phy ;
u8 core ;
u16 r ; /* routing */
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 7 ) {
2011-12-20 22:45:49 +01:00
for ( core = 0 ; core < 2 ; core + + ) {
r = core ? 0x190 : 0x170 ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
b43_radio_write ( dev , r + 0x5 , 0x5 ) ;
b43_radio_write ( dev , r + 0x9 , 0xE ) ;
if ( phy - > rev ! = 5 )
b43_radio_write ( dev , r + 0xA , 0 ) ;
if ( phy - > rev ! = 7 )
b43_radio_write ( dev , r + 0xB , 1 ) ;
else
b43_radio_write ( dev , r + 0xB , 0x31 ) ;
} else {
b43_radio_write ( dev , r + 0x5 , 0x9 ) ;
b43_radio_write ( dev , r + 0x9 , 0xC ) ;
b43_radio_write ( dev , r + 0xB , 0x0 ) ;
if ( phy - > rev ! = 5 )
b43_radio_write ( dev , r + 0xA , 1 ) ;
else
b43_radio_write ( dev , r + 0xA , 0x31 ) ;
}
b43_radio_write ( dev , r + 0x6 , 0 ) ;
b43_radio_write ( dev , r + 0x7 , 0 ) ;
b43_radio_write ( dev , r + 0x8 , 3 ) ;
b43_radio_write ( dev , r + 0xC , 0 ) ;
}
} else {
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
b43_radio_write ( dev , B2056_SYN_RESERVED_ADDR31 , 0x128 ) ;
else
b43_radio_write ( dev , B2056_SYN_RESERVED_ADDR31 , 0x80 ) ;
b43_radio_write ( dev , B2056_SYN_RESERVED_ADDR30 , 0 ) ;
b43_radio_write ( dev , B2056_SYN_GPIO_MASTER1 , 0x29 ) ;
for ( core = 0 ; core < 2 ; core + + ) {
r = core ? B2056_TX1 : B2056_TX0 ;
b43_radio_write ( dev , r | B2056_TX_IQCAL_VCM_HG , 0 ) ;
b43_radio_write ( dev , r | B2056_TX_IQCAL_IDAC , 0 ) ;
b43_radio_write ( dev , r | B2056_TX_TSSI_VCM , 3 ) ;
b43_radio_write ( dev , r | B2056_TX_TX_AMP_DET , 0 ) ;
b43_radio_write ( dev , r | B2056_TX_TSSI_MISC1 , 8 ) ;
b43_radio_write ( dev , r | B2056_TX_TSSI_MISC2 , 0 ) ;
b43_radio_write ( dev , r | B2056_TX_TSSI_MISC3 , 0 ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
b43_radio_write ( dev , r | B2056_TX_TX_SSI_MASTER ,
0x5 ) ;
if ( phy - > rev ! = 5 )
b43_radio_write ( dev , r | B2056_TX_TSSIA ,
0x00 ) ;
if ( phy - > rev > = 5 )
b43_radio_write ( dev , r | B2056_TX_TSSIG ,
0x31 ) ;
else
b43_radio_write ( dev , r | B2056_TX_TSSIG ,
0x11 ) ;
b43_radio_write ( dev , r | B2056_TX_TX_SSI_MUX ,
0xE ) ;
} else {
b43_radio_write ( dev , r | B2056_TX_TX_SSI_MASTER ,
0x9 ) ;
b43_radio_write ( dev , r | B2056_TX_TSSIA , 0x31 ) ;
b43_radio_write ( dev , r | B2056_TX_TSSIG , 0x0 ) ;
b43_radio_write ( dev , r | B2056_TX_TX_SSI_MUX ,
0xC ) ;
}
}
}
}
/*
* Stop radio and transmit known signal . Then check received signal strength to
* get TSSI ( Transmit Signal Strength Indicator ) .
* http : //bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi
*/
static void b43_nphy_tx_power_ctl_idle_tssi ( struct b43_wldev * dev )
{
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = dev - > phy . n ;
u32 tmp ;
s32 rssi [ 4 ] = { } ;
2014-07-23 18:54:48 +02:00
if ( phy - > chandef - > chan - > flags & IEEE80211_CHAN_NO_IR )
return ;
2011-12-20 22:45:49 +01:00
if ( b43_nphy_ipa ( dev ) )
b43_nphy_ipa_internal_tssi_setup ( dev ) ;
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 )
2014-07-22 21:31:05 +02:00
b43_nphy_rf_ctl_override_rev19 ( dev , 0x1000 , 0 , 3 , false , 0 ) ;
2014-07-08 15:11:06 +02:00
else if ( phy - > rev > = 7 )
2014-07-22 21:31:05 +02:00
b43_nphy_rf_ctl_override_rev7 ( dev , 0x1000 , 0 , 3 , false , 0 ) ;
2011-12-20 22:45:49 +01:00
else if ( phy - > rev > = 3 )
2013-03-30 21:50:46 +01:00
b43_nphy_rf_ctl_override ( dev , 0x2000 , 0 , 3 , false ) ;
2011-12-20 22:45:49 +01:00
b43_nphy_stop_playback ( dev ) ;
2014-06-22 23:18:21 +02:00
b43_nphy_tx_tone ( dev , 4000 , 0 , false , false , false ) ;
2011-12-20 22:45:49 +01:00
udelay ( 20 ) ;
2013-03-20 18:24:47 +01:00
tmp = b43_nphy_poll_rssi ( dev , N_RSSI_TSSI_2G , rssi , 1 ) ;
2011-12-20 22:45:49 +01:00
b43_nphy_stop_playback ( dev ) ;
2014-07-08 15:11:06 +02:00
2013-03-20 18:24:47 +01:00
b43_nphy_rssi_select ( dev , 0 , N_RSSI_W1 ) ;
2011-12-20 22:45:49 +01:00
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 )
2014-07-22 21:31:05 +02:00
b43_nphy_rf_ctl_override_rev19 ( dev , 0x1000 , 0 , 3 , true , 0 ) ;
2014-07-08 15:11:06 +02:00
else if ( phy - > rev > = 7 )
2014-07-22 21:31:05 +02:00
b43_nphy_rf_ctl_override_rev7 ( dev , 0x1000 , 0 , 3 , true , 0 ) ;
2011-12-20 22:45:49 +01:00
else if ( phy - > rev > = 3 )
2013-03-30 21:50:46 +01:00
b43_nphy_rf_ctl_override ( dev , 0x2000 , 0 , 3 , true ) ;
2011-12-20 22:45:49 +01:00
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
return ;
} else if ( phy - > rev > = 3 ) {
2011-12-20 22:45:49 +01:00
nphy - > pwr_ctl_info [ 0 ] . idle_tssi_5g = ( tmp > > 24 ) & 0xFF ;
nphy - > pwr_ctl_info [ 1 ] . idle_tssi_5g = ( tmp > > 8 ) & 0xFF ;
} else {
nphy - > pwr_ctl_info [ 0 ] . idle_tssi_5g = ( tmp > > 16 ) & 0xFF ;
nphy - > pwr_ctl_info [ 1 ] . idle_tssi_5g = tmp & 0xFF ;
}
nphy - > pwr_ctl_info [ 0 ] . idle_tssi_2g = ( tmp > > 24 ) & 0xFF ;
nphy - > pwr_ctl_info [ 1 ] . idle_tssi_2g = ( tmp > > 8 ) & 0xFF ;
}
2012-01-02 19:31:22 +01:00
/* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */
static void b43_nphy_tx_prepare_adjusted_power_table ( struct b43_wldev * dev )
{
struct b43_phy_n * nphy = dev - > phy . n ;
u8 idx , delta ;
u8 i , stf_mode ;
2014-04-20 13:05:51 +02:00
/* Array adj_pwr_tbl corresponds to the hardware table. It consists of
* 21 groups , each containing 4 entries .
*
* First group has entries for CCK modulation .
* The rest of groups has 1 entry per modulation ( SISO , CDD , STBC , SDM ) .
*
* Group 0 is for CCK
* Groups 1. .4 use BPSK ( group per coding rate )
* Groups 5. .8 use QPSK ( group per coding rate )
* Groups 9. .12 use 16 - QAM ( group per coding rate )
* Groups 13. .16 use 64 - QAM ( group per coding rate )
* Groups 17. .20 are unknown
*/
2012-01-02 19:31:22 +01:00
for ( i = 0 ; i < 4 ; i + + )
nphy - > adj_pwr_tbl [ i ] = nphy - > tx_power_offset [ i ] ;
for ( stf_mode = 0 ; stf_mode < 4 ; stf_mode + + ) {
delta = 0 ;
switch ( stf_mode ) {
case 0 :
2014-05-31 20:49:40 +02:00
if ( b43_is_40mhz ( dev ) & & dev - > phy . rev > = 5 ) {
2012-01-02 19:31:22 +01:00
idx = 68 ;
} else {
delta = 1 ;
2014-05-31 20:49:40 +02:00
idx = b43_is_40mhz ( dev ) ? 52 : 4 ;
2012-01-02 19:31:22 +01:00
}
break ;
case 1 :
2014-05-31 20:49:40 +02:00
idx = b43_is_40mhz ( dev ) ? 76 : 28 ;
2012-01-02 19:31:22 +01:00
break ;
case 2 :
2014-05-31 20:49:40 +02:00
idx = b43_is_40mhz ( dev ) ? 84 : 36 ;
2012-01-02 19:31:22 +01:00
break ;
case 3 :
2014-05-31 20:49:40 +02:00
idx = b43_is_40mhz ( dev ) ? 92 : 44 ;
2012-01-02 19:31:22 +01:00
break ;
}
for ( i = 0 ; i < 20 ; i + + ) {
nphy - > adj_pwr_tbl [ 4 + 4 * i + stf_mode ] =
nphy - > tx_power_offset [ idx ] ;
if ( i = = 0 )
idx + = delta ;
if ( i = = 14 )
idx + = 1 - delta ;
if ( i = = 3 | | i = = 4 | | i = = 7 | | i = = 8 | | i = = 11 | |
i = = 13 )
idx + = 1 ;
}
}
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */
static void b43_nphy_tx_power_ctl_setup ( struct b43_wldev * dev )
{
2014-05-31 20:49:39 +02:00
struct b43_phy * phy = & dev - > phy ;
2012-01-02 19:31:22 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
s16 a1 [ 2 ] , b0 [ 2 ] , b1 [ 2 ] ;
u8 idle [ 2 ] ;
2014-07-31 21:59:48 +02:00
u8 ppr_max ;
2012-01-02 19:31:22 +01:00
s8 target [ 2 ] ;
s32 num , den , pwr ;
u32 regval [ 64 ] ;
2014-05-31 20:49:39 +02:00
u16 freq = phy - > chandef - > chan - > center_freq ;
2012-01-02 19:31:22 +01:00
u16 tmp ;
u16 r ; /* routing */
u8 i , c ;
if ( dev - > dev - > core_rev = = 11 | | dev - > dev - > core_rev = = 12 ) {
b43_maskset32 ( dev , B43_MMIO_MACCTL , ~ 0 , 0x200000 ) ;
b43_read32 ( dev , B43_MMIO_MACCTL ) ;
udelay ( 1 ) ;
}
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , true ) ;
b43_phy_set ( dev , B43_NPHY_TSSIMODE , B43_NPHY_TSSIMODE_EN ) ;
if ( dev - > phy . rev > = 3 )
b43_phy_mask ( dev , B43_NPHY_TXPCTL_CMD ,
~ B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF ) ;
else
b43_phy_set ( dev , B43_NPHY_TXPCTL_CMD ,
B43_NPHY_TXPCTL_CMD_PCTLEN ) ;
if ( dev - > dev - > core_rev = = 11 | | dev - > dev - > core_rev = = 12 )
b43_maskset32 ( dev , B43_MMIO_MACCTL , ~ 0x200000 , 0 ) ;
if ( sprom - > revision < 4 ) {
idle [ 0 ] = nphy - > pwr_ctl_info [ 0 ] . idle_tssi_2g ;
idle [ 1 ] = nphy - > pwr_ctl_info [ 1 ] . idle_tssi_2g ;
target [ 0 ] = target [ 1 ] = 52 ;
a1 [ 0 ] = a1 [ 1 ] = - 424 ;
b0 [ 0 ] = b0 [ 1 ] = 5612 ;
b1 [ 0 ] = b1 [ 1 ] = - 1393 ;
} else {
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
for ( c = 0 ; c < 2 ; c + + ) {
idle [ c ] = nphy - > pwr_ctl_info [ c ] . idle_tssi_2g ;
target [ c ] = sprom - > core_pwr_info [ c ] . maxpwr_2g ;
a1 [ c ] = sprom - > core_pwr_info [ c ] . pa_2g [ 0 ] ;
b0 [ c ] = sprom - > core_pwr_info [ c ] . pa_2g [ 1 ] ;
b1 [ c ] = sprom - > core_pwr_info [ c ] . pa_2g [ 2 ] ;
}
} else if ( freq > = 4900 & & freq < 5100 ) {
for ( c = 0 ; c < 2 ; c + + ) {
idle [ c ] = nphy - > pwr_ctl_info [ c ] . idle_tssi_5g ;
target [ c ] = sprom - > core_pwr_info [ c ] . maxpwr_5gl ;
a1 [ c ] = sprom - > core_pwr_info [ c ] . pa_5gl [ 0 ] ;
b0 [ c ] = sprom - > core_pwr_info [ c ] . pa_5gl [ 1 ] ;
b1 [ c ] = sprom - > core_pwr_info [ c ] . pa_5gl [ 2 ] ;
}
} else if ( freq > = 5100 & & freq < 5500 ) {
for ( c = 0 ; c < 2 ; c + + ) {
idle [ c ] = nphy - > pwr_ctl_info [ c ] . idle_tssi_5g ;
target [ c ] = sprom - > core_pwr_info [ c ] . maxpwr_5g ;
a1 [ c ] = sprom - > core_pwr_info [ c ] . pa_5g [ 0 ] ;
b0 [ c ] = sprom - > core_pwr_info [ c ] . pa_5g [ 1 ] ;
b1 [ c ] = sprom - > core_pwr_info [ c ] . pa_5g [ 2 ] ;
}
} else if ( freq > = 5500 ) {
for ( c = 0 ; c < 2 ; c + + ) {
idle [ c ] = nphy - > pwr_ctl_info [ c ] . idle_tssi_5g ;
target [ c ] = sprom - > core_pwr_info [ c ] . maxpwr_5gh ;
a1 [ c ] = sprom - > core_pwr_info [ c ] . pa_5gh [ 0 ] ;
b0 [ c ] = sprom - > core_pwr_info [ c ] . pa_5gh [ 1 ] ;
b1 [ c ] = sprom - > core_pwr_info [ c ] . pa_5gh [ 2 ] ;
}
} else {
idle [ 0 ] = nphy - > pwr_ctl_info [ 0 ] . idle_tssi_5g ;
idle [ 1 ] = nphy - > pwr_ctl_info [ 1 ] . idle_tssi_5g ;
target [ 0 ] = target [ 1 ] = 52 ;
a1 [ 0 ] = a1 [ 1 ] = - 424 ;
b0 [ 0 ] = b0 [ 1 ] = 5612 ;
b1 [ 0 ] = b1 [ 1 ] = - 1393 ;
}
}
2014-07-31 21:59:48 +02:00
ppr_max = b43_ppr_get_max ( dev , & nphy - > tx_pwr_max_ppr ) ;
if ( ppr_max ) {
target [ 0 ] = ppr_max ;
target [ 1 ] = ppr_max ;
}
2012-01-02 19:31:22 +01:00
if ( dev - > phy . rev > = 3 ) {
if ( sprom - > fem . ghz2 . tssipos )
b43_phy_set ( dev , B43_NPHY_TXPCTL_ITSSI , 0x4000 ) ;
if ( dev - > phy . rev > = 7 ) {
for ( c = 0 ; c < 2 ; c + + ) {
r = c ? 0x190 : 0x170 ;
if ( b43_nphy_ipa ( dev ) )
b43_radio_write ( dev , r + 0x9 , ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) ? 0xE : 0xC ) ;
}
} else {
if ( b43_nphy_ipa ( dev ) ) {
tmp = ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) ? 0xC : 0xE ;
b43_radio_write ( dev ,
B2056_TX0 | B2056_TX_TX_SSI_MUX , tmp ) ;
b43_radio_write ( dev ,
B2056_TX1 | B2056_TX_TX_SSI_MUX , tmp ) ;
} else {
b43_radio_write ( dev ,
B2056_TX0 | B2056_TX_TX_SSI_MUX , 0x11 ) ;
b43_radio_write ( dev ,
B2056_TX1 | B2056_TX_TX_SSI_MUX , 0x11 ) ;
}
}
}
if ( dev - > dev - > core_rev = = 11 | | dev - > dev - > core_rev = = 12 ) {
b43_maskset32 ( dev , B43_MMIO_MACCTL , ~ 0 , 0x200000 ) ;
b43_read32 ( dev , B43_MMIO_MACCTL ) ;
udelay ( 1 ) ;
}
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 7 ) {
2012-01-02 19:31:22 +01:00
b43_phy_maskset ( dev , B43_NPHY_TXPCTL_CMD ,
~ B43_NPHY_TXPCTL_CMD_INIT , 0x19 ) ;
b43_phy_maskset ( dev , B43_NPHY_TXPCTL_INIT ,
~ B43_NPHY_TXPCTL_INIT_PIDXI1 , 0x19 ) ;
} else {
b43_phy_maskset ( dev , B43_NPHY_TXPCTL_CMD ,
~ B43_NPHY_TXPCTL_CMD_INIT , 0x40 ) ;
if ( dev - > phy . rev > 1 )
b43_phy_maskset ( dev , B43_NPHY_TXPCTL_INIT ,
~ B43_NPHY_TXPCTL_INIT_PIDXI1 , 0x40 ) ;
}
if ( dev - > dev - > core_rev = = 11 | | dev - > dev - > core_rev = = 12 )
b43_maskset32 ( dev , B43_MMIO_MACCTL , ~ 0x200000 , 0 ) ;
b43_phy_write ( dev , B43_NPHY_TXPCTL_N ,
0xF0 < < B43_NPHY_TXPCTL_N_TSSID_SHIFT |
3 < < B43_NPHY_TXPCTL_N_NPTIL2_SHIFT ) ;
b43_phy_write ( dev , B43_NPHY_TXPCTL_ITSSI ,
idle [ 0 ] < < B43_NPHY_TXPCTL_ITSSI_0_SHIFT |
idle [ 1 ] < < B43_NPHY_TXPCTL_ITSSI_1_SHIFT |
B43_NPHY_TXPCTL_ITSSI_BINF ) ;
b43_phy_write ( dev , B43_NPHY_TXPCTL_TPWR ,
target [ 0 ] < < B43_NPHY_TXPCTL_TPWR_0_SHIFT |
target [ 1 ] < < B43_NPHY_TXPCTL_TPWR_1_SHIFT ) ;
for ( c = 0 ; c < 2 ; c + + ) {
for ( i = 0 ; i < 64 ; i + + ) {
num = 8 * ( 16 * b0 [ c ] + b1 [ c ] * i ) ;
den = 32768 + a1 [ c ] * i ;
pwr = max ( ( 4 * num + den / 2 ) / den , - 8 ) ;
if ( dev - > phy . rev < 3 & & ( i < = ( 31 - idle [ c ] + 1 ) ) )
pwr = max ( pwr , target [ c ] + 1 ) ;
regval [ i ] = pwr ;
}
b43_ntab_write_bulk ( dev , B43_NTAB32 ( 26 + c , 0 ) , 64 , regval ) ;
}
b43_nphy_tx_prepare_adjusted_power_table ( dev ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 26 , 64 ) , 84 , nphy - > adj_pwr_tbl ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 27 , 64 ) , 84 , nphy - > adj_pwr_tbl ) ;
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , false ) ;
}
2011-09-04 23:23:53 +02:00
static void b43_nphy_tx_gain_table_upload ( struct b43_wldev * dev )
{
struct b43_phy * phy = & dev - > phy ;
2010-02-04 12:23:08 +01:00
2011-09-04 23:23:53 +02:00
const u32 * table = NULL ;
u32 rfpwr_offset ;
2014-07-31 21:59:46 +02:00
u8 pga_gain , pad_gain ;
2011-09-04 23:23:53 +02:00
int i ;
2014-07-31 21:59:46 +02:00
const s16 * uninitialized_var ( rf_pwr_offset_table ) ;
2011-09-04 23:23:53 +02:00
2012-01-03 22:49:17 +01:00
table = b43_nphy_get_tx_gain_table ( dev ) ;
2014-07-02 22:42:45 +02:00
if ( ! table )
return ;
2011-09-04 23:23:53 +02:00
b43_ntab_write_bulk ( dev , B43_NTAB32 ( 26 , 192 ) , 128 , table ) ;
b43_ntab_write_bulk ( dev , B43_NTAB32 ( 27 , 192 ) , 128 , table ) ;
2014-07-08 15:11:06 +02:00
if ( phy - > rev < 3 )
return ;
2011-09-04 23:23:53 +02:00
#if 0
2014-07-08 15:11:06 +02:00
nphy - > gmval = ( table [ 0 ] > > 16 ) & 0x7000 ;
2012-01-03 22:49:19 +01:00
# endif
2011-09-04 23:23:53 +02:00
2014-07-31 21:59:46 +02:00
if ( phy - > rev > = 19 ) {
return ;
} else if ( phy - > rev > = 7 ) {
rf_pwr_offset_table = b43_ntab_get_rf_pwr_offset_table ( dev ) ;
if ( ! rf_pwr_offset_table )
return ;
/* TODO: Enable this once we have gains configured */
return ;
}
2014-07-08 15:11:06 +02:00
for ( i = 0 ; i < 128 ; i + + ) {
if ( phy - > rev > = 19 ) {
/* TODO */
return ;
} else if ( phy - > rev > = 7 ) {
2014-07-31 21:59:46 +02:00
pga_gain = ( table [ i ] > > 24 ) & 0xf ;
pad_gain = ( table [ i ] > > 19 ) & 0x1f ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
rfpwr_offset = rf_pwr_offset_table [ pad_gain ] ;
else
rfpwr_offset = rf_pwr_offset_table [ pga_gain ] ;
2014-07-08 15:11:06 +02:00
} else {
2011-09-04 23:23:53 +02:00
pga_gain = ( table [ i ] > > 24 ) & 0xF ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
2014-07-08 15:11:06 +02:00
rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g [ pga_gain ] ;
2011-09-04 23:23:53 +02:00
else
2014-07-08 15:11:06 +02:00
rfpwr_offset = 0 ; /* FIXME */
2011-09-04 23:23:53 +02:00
}
2014-07-08 15:11:06 +02:00
b43_ntab_write ( dev , B43_NTAB32 ( 26 , 576 + i ) , rfpwr_offset ) ;
b43_ntab_write ( dev , B43_NTAB32 ( 27 , 576 + i ) , rfpwr_offset ) ;
2010-02-04 12:23:08 +01:00
}
}
2010-01-15 15:02:38 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
static void b43_nphy_pa_override ( struct b43_wldev * dev , bool enable )
2008-01-18 01:09:25 +01:00
{
2010-01-15 15:02:38 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
enum ieee80211_band band ;
u16 tmp ;
2008-01-18 01:09:25 +01:00
2010-01-15 15:02:38 +01:00
if ( ! enable ) {
nphy - > rfctrl_intc1_save = b43_phy_read ( dev ,
B43_NPHY_RFCTL_INTC1 ) ;
nphy - > rfctrl_intc2_save = b43_phy_read ( dev ,
B43_NPHY_RFCTL_INTC2 ) ;
band = b43_current_band ( dev - > wl ) ;
2014-07-08 15:11:06 +02:00
if ( dev - > phy . rev > = 7 ) {
2014-07-08 15:11:07 +02:00
tmp = 0x1480 ;
2014-07-08 15:11:06 +02:00
} else if ( dev - > phy . rev > = 3 ) {
2010-01-15 15:02:38 +01:00
if ( band = = IEEE80211_BAND_5GHZ )
tmp = 0x600 ;
else
tmp = 0x480 ;
} else {
if ( band = = IEEE80211_BAND_5GHZ )
tmp = 0x180 ;
else
tmp = 0x120 ;
}
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 , tmp ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 , tmp ) ;
} else {
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 ,
nphy - > rfctrl_intc1_save ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 ,
nphy - > rfctrl_intc2_save ) ;
2008-01-18 01:09:25 +01:00
}
}
2014-06-22 23:18:22 +02:00
/*
* TX low - pass filter bandwidth setup
* http : //bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw
*/
static void b43_nphy_tx_lpf_bw ( struct b43_wldev * dev )
2010-01-15 14:38:32 +01:00
{
u16 tmp ;
2014-06-22 23:18:22 +02:00
if ( dev - > phy . rev < 3 | | dev - > phy . rev > = 7 )
return ;
2010-11-30 22:33:15 +01:00
2014-06-22 23:18:22 +02:00
if ( b43_nphy_ipa ( dev ) )
tmp = b43_is_40mhz ( dev ) ? 5 : 4 ;
else
tmp = b43_is_40mhz ( dev ) ? 3 : 1 ;
b43_phy_write ( dev , B43_NPHY_TXF_40CO_B32S2 ,
( tmp < < 9 ) | ( tmp < < 6 ) | ( tmp < < 3 ) | tmp ) ;
if ( b43_nphy_ipa ( dev ) ) {
tmp = b43_is_40mhz ( dev ) ? 4 : 1 ;
2010-01-15 15:51:55 +01:00
b43_phy_write ( dev , B43_NPHY_TXF_40CO_B1S2 ,
2014-06-22 23:18:22 +02:00
( tmp < < 9 ) | ( tmp < < 6 ) | ( tmp < < 3 ) | tmp ) ;
2010-01-15 15:51:55 +01:00
}
}
2010-11-30 22:33:15 +01:00
2010-01-15 15:26:12 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
static void b43_nphy_rx_iq_est ( struct b43_wldev * dev , struct nphy_iq_est * est ,
u16 samps , u8 time , bool wait )
2010-01-15 14:38:32 +01:00
{
2010-01-15 15:26:12 +01:00
int i ;
u16 tmp ;
2010-01-15 14:38:32 +01:00
2010-01-15 15:26:12 +01:00
b43_phy_write ( dev , B43_NPHY_IQEST_SAMCNT , samps ) ;
b43_phy_maskset ( dev , B43_NPHY_IQEST_WT , ~ B43_NPHY_IQEST_WT_VAL , time ) ;
if ( wait )
b43_phy_set ( dev , B43_NPHY_IQEST_CMD , B43_NPHY_IQEST_CMD_MODE ) ;
2010-01-30 20:18:03 +01:00
else
2010-01-15 15:26:12 +01:00
b43_phy_mask ( dev , B43_NPHY_IQEST_CMD , ~ B43_NPHY_IQEST_CMD_MODE ) ;
2010-01-30 20:18:03 +01:00
2010-01-15 15:26:12 +01:00
b43_phy_set ( dev , B43_NPHY_IQEST_CMD , B43_NPHY_IQEST_CMD_START ) ;
2010-01-15 14:38:32 +01:00
2010-01-15 15:26:12 +01:00
for ( i = 1000 ; i ; i - - ) {
tmp = b43_phy_read ( dev , B43_NPHY_IQEST_CMD ) ;
if ( ! ( tmp & B43_NPHY_IQEST_CMD_START ) ) {
est - > i0_pwr = ( b43_phy_read ( dev , B43_NPHY_IQEST_IPACC_HI0 ) < < 16 ) |
b43_phy_read ( dev , B43_NPHY_IQEST_IPACC_LO0 ) ;
est - > q0_pwr = ( b43_phy_read ( dev , B43_NPHY_IQEST_QPACC_HI0 ) < < 16 ) |
b43_phy_read ( dev , B43_NPHY_IQEST_QPACC_LO0 ) ;
est - > iq0_prod = ( b43_phy_read ( dev , B43_NPHY_IQEST_IQACC_HI0 ) < < 16 ) |
b43_phy_read ( dev , B43_NPHY_IQEST_IQACC_LO0 ) ;
2010-01-15 14:38:32 +01:00
2010-01-15 15:26:12 +01:00
est - > i1_pwr = ( b43_phy_read ( dev , B43_NPHY_IQEST_IPACC_HI1 ) < < 16 ) |
b43_phy_read ( dev , B43_NPHY_IQEST_IPACC_LO1 ) ;
est - > q1_pwr = ( b43_phy_read ( dev , B43_NPHY_IQEST_QPACC_HI1 ) < < 16 ) |
b43_phy_read ( dev , B43_NPHY_IQEST_QPACC_LO1 ) ;
est - > iq1_prod = ( b43_phy_read ( dev , B43_NPHY_IQEST_IQACC_HI1 ) < < 16 ) |
b43_phy_read ( dev , B43_NPHY_IQEST_IQACC_LO1 ) ;
return ;
2010-01-15 14:38:32 +01:00
}
2010-01-15 15:26:12 +01:00
udelay ( 10 ) ;
2010-01-15 14:38:32 +01:00
}
2010-01-15 15:26:12 +01:00
memset ( est , 0 , sizeof ( * est ) ) ;
2010-01-15 14:38:32 +01:00
}
2010-01-15 15:16:25 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
static void b43_nphy_rx_iq_coeffs ( struct b43_wldev * dev , bool write ,
struct b43_phy_n_iq_comp * pcomp )
2010-01-30 20:18:03 +01:00
{
2010-01-15 15:16:25 +01:00
if ( write ) {
b43_phy_write ( dev , B43_NPHY_C1_RXIQ_COMPA0 , pcomp - > a0 ) ;
b43_phy_write ( dev , B43_NPHY_C1_RXIQ_COMPB0 , pcomp - > b0 ) ;
b43_phy_write ( dev , B43_NPHY_C2_RXIQ_COMPA1 , pcomp - > a1 ) ;
b43_phy_write ( dev , B43_NPHY_C2_RXIQ_COMPB1 , pcomp - > b1 ) ;
2010-01-30 20:18:04 +01:00
} else {
2010-01-15 15:16:25 +01:00
pcomp - > a0 = b43_phy_read ( dev , B43_NPHY_C1_RXIQ_COMPA0 ) ;
pcomp - > b0 = b43_phy_read ( dev , B43_NPHY_C1_RXIQ_COMPB0 ) ;
pcomp - > a1 = b43_phy_read ( dev , B43_NPHY_C2_RXIQ_COMPA1 ) ;
pcomp - > b1 = b43_phy_read ( dev , B43_NPHY_C2_RXIQ_COMPB1 ) ;
}
}
2010-01-30 20:18:04 +01:00
2010-12-07 21:55:57 +01:00
#if 0
/* Ready but not used anywhere */
2010-01-17 13:03:28 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
static void b43_nphy_rx_cal_phy_cleanup ( struct b43_wldev * dev , u8 core )
{
u16 * regs = dev - > phy . n - > tx_rx_cal_phy_saveregs ;
2010-01-30 20:18:04 +01:00
2010-01-17 13:03:28 +01:00
b43_phy_write ( dev , B43_NPHY_RFSEQCA , regs [ 0 ] ) ;
if ( core = = 0 ) {
b43_phy_write ( dev , B43_NPHY_AFECTL_C1 , regs [ 1 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER1 , regs [ 2 ] ) ;
} else {
b43_phy_write ( dev , B43_NPHY_AFECTL_C2 , regs [ 1 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , regs [ 2 ] ) ;
}
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 , regs [ 3 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 , regs [ 4 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_RSSIO1 , regs [ 5 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_RSSIO2 , regs [ 6 ] ) ;
b43_phy_write ( dev , B43_NPHY_TXF_40CO_B1S1 , regs [ 7 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_OVER , regs [ 8 ] ) ;
b43_phy_write ( dev , B43_NPHY_PAPD_EN0 , regs [ 9 ] ) ;
b43_phy_write ( dev , B43_NPHY_PAPD_EN1 , regs [ 10 ] ) ;
}
2010-01-30 20:18:04 +01:00
2010-01-17 13:03:28 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
static void b43_nphy_rx_cal_phy_setup ( struct b43_wldev * dev , u8 core )
{
u8 rxval , txval ;
u16 * regs = dev - > phy . n - > tx_rx_cal_phy_saveregs ;
2010-01-30 20:18:04 +01:00
2010-01-17 13:03:28 +01:00
regs [ 0 ] = b43_phy_read ( dev , B43_NPHY_RFSEQCA ) ;
if ( core = = 0 ) {
regs [ 1 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_C1 ) ;
regs [ 2 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_OVER1 ) ;
} else {
regs [ 1 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_C2 ) ;
regs [ 2 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_OVER ) ;
}
regs [ 3 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC1 ) ;
regs [ 4 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC2 ) ;
regs [ 5 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_RSSIO1 ) ;
regs [ 6 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_RSSIO2 ) ;
regs [ 7 ] = b43_phy_read ( dev , B43_NPHY_TXF_40CO_B1S1 ) ;
regs [ 8 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_OVER ) ;
regs [ 9 ] = b43_phy_read ( dev , B43_NPHY_PAPD_EN0 ) ;
regs [ 10 ] = b43_phy_read ( dev , B43_NPHY_PAPD_EN1 ) ;
2010-01-30 20:18:04 +01:00
2010-01-17 13:03:28 +01:00
b43_phy_mask ( dev , B43_NPHY_PAPD_EN0 , ~ 0x0001 ) ;
b43_phy_mask ( dev , B43_NPHY_PAPD_EN1 , ~ 0x0001 ) ;
2010-01-30 20:18:04 +01:00
2010-07-21 11:48:05 -05:00
b43_phy_maskset ( dev , B43_NPHY_RFSEQCA ,
~ B43_NPHY_RFSEQCA_RXDIS & 0xFFFF ,
2010-01-17 13:03:28 +01:00
( ( 1 - core ) < < B43_NPHY_RFSEQCA_RXDIS_SHIFT ) ) ;
b43_phy_maskset ( dev , B43_NPHY_RFSEQCA , ~ B43_NPHY_RFSEQCA_TXEN ,
( ( 1 - core ) < < B43_NPHY_RFSEQCA_TXEN_SHIFT ) ) ;
b43_phy_maskset ( dev , B43_NPHY_RFSEQCA , ~ B43_NPHY_RFSEQCA_RXEN ,
( core < < B43_NPHY_RFSEQCA_RXEN_SHIFT ) ) ;
b43_phy_maskset ( dev , B43_NPHY_RFSEQCA , ~ B43_NPHY_RFSEQCA_TXDIS ,
( core < < B43_NPHY_RFSEQCA_TXDIS_SHIFT ) ) ;
2010-01-30 20:18:04 +01:00
2010-01-17 13:03:28 +01:00
if ( core = = 0 ) {
b43_phy_mask ( dev , B43_NPHY_AFECTL_C1 , ~ 0x0007 ) ;
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER1 , 0x0007 ) ;
} else {
b43_phy_mask ( dev , B43_NPHY_AFECTL_C2 , ~ 0x0007 ) ;
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER , 0x0007 ) ;
}
2010-01-30 20:18:04 +01:00
2013-03-29 11:37:02 +01:00
b43_nphy_rf_ctl_intc_override ( dev , N_INTC_OVERRIDE_PA , 0 , 3 ) ;
2013-03-30 21:50:46 +01:00
b43_nphy_rf_ctl_override ( dev , 8 , 0 , 3 , false ) ;
2010-01-17 13:04:02 +01:00
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RX2TX ) ;
2010-01-30 20:18:04 +01:00
2010-01-17 13:03:28 +01:00
if ( core = = 0 ) {
rxval = 1 ;
txval = 8 ;
} else {
rxval = 4 ;
txval = 2 ;
2010-01-30 20:18:04 +01:00
}
2013-03-29 11:37:02 +01:00
b43_nphy_rf_ctl_intc_override ( dev , N_INTC_OVERRIDE_TRSW , rxval ,
core + 1 ) ;
b43_nphy_rf_ctl_intc_override ( dev , N_INTC_OVERRIDE_TRSW , txval ,
2 - core ) ;
2010-01-30 20:18:03 +01:00
}
2010-12-07 21:55:57 +01:00
# endif
2010-01-30 20:18:03 +01:00
2010-01-15 15:29:05 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
static void b43_nphy_calc_rx_iq_comp ( struct b43_wldev * dev , u8 mask )
2010-01-15 14:45:13 +01:00
{
int i ;
2010-01-15 15:29:05 +01:00
s32 iq ;
u32 ii ;
u32 qq ;
int iq_nbits , qq_nbits ;
int arsh , brsh ;
u16 tmp , a , b ;
struct nphy_iq_est est ;
struct b43_phy_n_iq_comp old ;
struct b43_phy_n_iq_comp new = { } ;
bool error = false ;
if ( mask = = 0 )
return ;
b43_nphy_rx_iq_coeffs ( dev , false , & old ) ;
b43_nphy_rx_iq_coeffs ( dev , true , & new ) ;
b43_nphy_rx_iq_est ( dev , & est , 0x4000 , 32 , false ) ;
new = old ;
2010-01-15 14:45:13 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
2010-01-15 15:29:05 +01:00
if ( i = = 0 & & ( mask & 1 ) ) {
iq = est . iq0_prod ;
ii = est . i0_pwr ;
qq = est . q0_pwr ;
} else if ( i = = 1 & & ( mask & 2 ) ) {
iq = est . iq1_prod ;
ii = est . i1_pwr ;
qq = est . q1_pwr ;
2010-01-15 14:45:13 +01:00
} else {
2010-01-15 15:29:05 +01:00
continue ;
2010-01-15 14:45:13 +01:00
}
2010-01-15 15:29:05 +01:00
if ( ii + qq < 2 ) {
error = true ;
break ;
}
2010-01-15 14:45:13 +01:00
2010-01-15 15:29:05 +01:00
iq_nbits = fls ( abs ( iq ) ) ;
qq_nbits = fls ( qq ) ;
2010-01-15 14:45:13 +01:00
2010-01-15 15:29:05 +01:00
arsh = iq_nbits - 20 ;
if ( arsh > = 0 ) {
a = - ( ( iq < < ( 30 - iq_nbits ) ) + ( ii > > ( 1 + arsh ) ) ) ;
tmp = ii > > arsh ;
} else {
a = - ( ( iq < < ( 30 - iq_nbits ) ) + ( ii < < ( - 1 - arsh ) ) ) ;
tmp = ii < < - arsh ;
}
if ( tmp = = 0 ) {
error = true ;
break ;
}
a / = tmp ;
2010-01-15 14:45:13 +01:00
2010-01-15 15:29:05 +01:00
brsh = qq_nbits - 11 ;
if ( brsh > = 0 ) {
b = ( qq < < ( 31 - qq_nbits ) ) ;
tmp = ii > > brsh ;
2010-01-15 14:45:13 +01:00
} else {
2010-01-15 15:29:05 +01:00
b = ( qq < < ( 31 - qq_nbits ) ) ;
tmp = ii < < - brsh ;
}
if ( tmp = = 0 ) {
error = true ;
break ;
2010-01-15 14:45:13 +01:00
}
2010-01-15 15:29:05 +01:00
b = int_sqrt ( b / tmp - a * a ) - ( 1 < < 10 ) ;
2010-01-15 14:45:13 +01:00
2010-01-15 15:29:05 +01:00
if ( i = = 0 & & ( mask & 0x1 ) ) {
if ( dev - > phy . rev > = 3 ) {
new . a0 = a & 0x3FF ;
new . b0 = b & 0x3FF ;
} else {
new . a0 = b & 0x3FF ;
new . b0 = a & 0x3FF ;
}
} else if ( i = = 1 & & ( mask & 0x2 ) ) {
if ( dev - > phy . rev > = 3 ) {
new . a1 = a & 0x3FF ;
new . b1 = b & 0x3FF ;
} else {
new . a1 = b & 0x3FF ;
new . b1 = a & 0x3FF ;
}
}
2010-01-15 14:45:13 +01:00
}
2010-01-15 15:29:05 +01:00
if ( error )
new = old ;
2010-01-15 14:45:13 +01:00
2010-01-15 15:29:05 +01:00
b43_nphy_rx_iq_coeffs ( dev , true , & new ) ;
}
2010-01-15 14:45:13 +01:00
2010-01-15 15:17:10 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
static void b43_nphy_tx_iq_workaround ( struct b43_wldev * dev )
{
u16 array [ 4 ] ;
2011-09-04 23:23:51 +02:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 0xF , 0x50 ) , 4 , array ) ;
2010-01-15 15:17:10 +01:00
b43_shm_write16 ( dev , B43_SHM_SHARED , B43_SHM_SH_NPHY_TXIQW0 , array [ 0 ] ) ;
b43_shm_write16 ( dev , B43_SHM_SHARED , B43_SHM_SH_NPHY_TXIQW1 , array [ 1 ] ) ;
b43_shm_write16 ( dev , B43_SHM_SHARED , B43_SHM_SH_NPHY_TXIQW2 , array [ 2 ] ) ;
b43_shm_write16 ( dev , B43_SHM_SHARED , B43_SHM_SH_NPHY_TXIQW3 , array [ 3 ] ) ;
2010-01-15 14:45:13 +01:00
}
2010-02-04 12:23:12 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
static void b43_nphy_spur_workaround ( struct b43_wldev * dev )
{
struct b43_phy_n * nphy = dev - > phy . n ;
2010-01-15 14:48:21 +01:00
2010-10-14 19:33:34 +02:00
u8 channel = dev - > phy . channel ;
2010-02-04 12:23:12 +01:00
int tone [ 2 ] = { 57 , 58 } ;
u32 noise [ 2 ] = { 0x3FF , 0x3FF } ;
2010-01-15 14:48:21 +01:00
2010-02-04 12:23:12 +01:00
B43_WARN_ON ( dev - > phy . rev < 3 ) ;
2010-01-15 14:48:21 +01:00
2010-02-04 12:23:12 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 1 ) ;
2010-01-15 14:48:21 +01:00
2010-02-04 12:23:12 +01:00
if ( nphy - > gband_spurwar_en ) {
/* TODO: N PHY Adjust Analog Pfbw (7) */
2014-05-31 20:49:40 +02:00
if ( channel = = 11 & & b43_is_40mhz ( dev ) )
2010-02-04 12:23:12 +01:00
; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
else
; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
/* TODO: N PHY Adjust CRS Min Power (0x1E) */
2010-01-15 14:48:21 +01:00
}
2010-02-04 12:23:12 +01:00
if ( nphy - > aband_spurwar_en ) {
if ( channel = = 54 ) {
tone [ 0 ] = 0x20 ;
noise [ 0 ] = 0x25F ;
} else if ( channel = = 38 | | channel = = 102 | | channel = = 118 ) {
if ( 0 /* FIXME */ ) {
tone [ 0 ] = 0x20 ;
noise [ 0 ] = 0x21F ;
} else {
tone [ 0 ] = 0 ;
noise [ 0 ] = 0 ;
2010-01-15 14:48:21 +01:00
}
2010-02-04 12:23:12 +01:00
} else if ( channel = = 134 ) {
tone [ 0 ] = 0x20 ;
noise [ 0 ] = 0x21F ;
} else if ( channel = = 151 ) {
tone [ 0 ] = 0x10 ;
noise [ 0 ] = 0x23F ;
} else if ( channel = = 153 | | channel = = 161 ) {
tone [ 0 ] = 0x30 ;
noise [ 0 ] = 0x23F ;
} else {
tone [ 0 ] = 0 ;
noise [ 0 ] = 0 ;
2010-01-15 14:48:21 +01:00
}
2010-02-04 12:23:12 +01:00
if ( ! tone [ 0 ] & & ! noise [ 0 ] )
; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
2010-01-15 14:48:21 +01:00
else
2010-02-04 12:23:12 +01:00
; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
}
2010-01-15 14:48:21 +01:00
2010-02-04 12:23:12 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 0 ) ;
}
2010-01-15 14:48:21 +01:00
2011-12-17 13:57:25 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
static void b43_nphy_tx_pwr_ctrl_coef_setup ( struct b43_wldev * dev )
{
struct b43_phy_n * nphy = dev - > phy . n ;
int i , j ;
u32 tmp ;
u32 cur_real , cur_imag , real_part , imag_part ;
2010-01-15 14:48:21 +01:00
2011-12-17 13:57:25 +01:00
u16 buffer [ 7 ] ;
2010-01-15 14:48:21 +01:00
2011-12-17 13:57:25 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , true ) ;
2010-01-15 14:48:21 +01:00
2011-12-17 13:57:25 +01:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 15 , 80 ) , 7 , buffer ) ;
2010-01-15 14:48:21 +01:00
2011-12-17 13:57:25 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
tmp = ( ( buffer [ i * 2 ] & 0x3FF ) < < 10 ) |
( buffer [ i * 2 + 1 ] & 0x3FF ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_ADDR ,
( ( ( i + 26 ) < < 10 ) | 320 ) ) ;
for ( j = 0 ; j < 128 ; j + + ) {
b43_phy_write ( dev , B43_NPHY_TABLE_DATAHI ,
( ( tmp > > 16 ) & 0xFFFF ) ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO ,
( tmp & 0xFFFF ) ) ;
2010-01-15 14:48:21 +01:00
}
}
2011-12-17 13:57:25 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
tmp = buffer [ 5 + i ] ;
real_part = ( tmp > > 8 ) & 0xFF ;
imag_part = ( tmp & 0xFF ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_ADDR ,
( ( ( i + 26 ) < < 10 ) | 448 ) ) ;
2010-01-15 14:48:21 +01:00
2011-12-17 13:57:25 +01:00
if ( dev - > phy . rev > = 3 ) {
cur_real = real_part ;
cur_imag = imag_part ;
tmp = ( ( cur_real & 0xFF ) < < 8 ) | ( cur_imag & 0xFF ) ;
}
2010-01-15 13:40:58 +01:00
2011-12-17 13:57:25 +01:00
for ( j = 0 ; j < 128 ; j + + ) {
if ( dev - > phy . rev < 3 ) {
cur_real = ( real_part * loscale [ j ] + 128 ) > > 8 ;
cur_imag = ( imag_part * loscale [ j ] + 128 ) > > 8 ;
tmp = ( ( cur_real & 0xFF ) < < 8 ) |
( cur_imag & 0xFF ) ;
}
b43_phy_write ( dev , B43_NPHY_TABLE_DATAHI ,
( ( tmp > > 16 ) & 0xFFFF ) ) ;
b43_phy_write ( dev , B43_NPHY_TABLE_DATALO ,
( tmp & 0xFFFF ) ) ;
}
2010-01-15 14:48:21 +01:00
}
2010-01-15 13:40:58 +01:00
if ( dev - > phy . rev > = 3 ) {
2011-12-17 13:57:25 +01:00
b43_shm_write16 ( dev , B43_SHM_SHARED ,
B43_SHM_SH_NPHY_TXPWR_INDX0 , 0xFFFF ) ;
b43_shm_write16 ( dev , B43_SHM_SHARED ,
B43_SHM_SH_NPHY_TXPWR_INDX1 , 0xFFFF ) ;
2010-01-15 13:40:58 +01:00
}
2010-01-15 14:48:21 +01:00
2011-12-17 13:57:25 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , false ) ;
2008-01-18 01:09:25 +01:00
}
2010-01-15 15:06:47 +01:00
/*
* Restore RSSI Calibration
* http : //bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
*/
static void b43_nphy_restore_rssi_cal ( struct b43_wldev * dev )
{
struct b43_phy_n * nphy = dev - > phy . n ;
u16 * rssical_radio_regs = NULL ;
u16 * rssical_phy_regs = NULL ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
2010-10-14 19:33:34 +02:00
if ( ! nphy - > rssical_chanspec_2G . center_freq )
2010-01-15 15:06:47 +01:00
return ;
rssical_radio_regs = nphy - > rssical_cache . rssical_radio_regs_2G ;
rssical_phy_regs = nphy - > rssical_cache . rssical_phy_regs_2G ;
} else {
2010-10-14 19:33:34 +02:00
if ( ! nphy - > rssical_chanspec_5G . center_freq )
2010-01-15 15:06:47 +01:00
return ;
rssical_radio_regs = nphy - > rssical_cache . rssical_radio_regs_5G ;
rssical_phy_regs = nphy - > rssical_cache . rssical_phy_regs_5G ;
}
2014-07-08 15:11:06 +02:00
if ( dev - > phy . rev > = 19 ) {
/* TODO */
} else if ( dev - > phy . rev > = 7 ) {
2014-07-08 15:11:07 +02:00
b43_radio_maskset ( dev , R2057_NB_MASTER_CORE0 , ~ R2057_VCM_MASK ,
rssical_radio_regs [ 0 ] ) ;
b43_radio_maskset ( dev , R2057_NB_MASTER_CORE1 , ~ R2057_VCM_MASK ,
rssical_radio_regs [ 1 ] ) ;
2013-03-30 22:34:40 +01:00
} else {
b43_radio_maskset ( dev , B2056_RX0 | B2056_RX_RSSI_MISC , 0xE3 ,
rssical_radio_regs [ 0 ] ) ;
b43_radio_maskset ( dev , B2056_RX1 | B2056_RX_RSSI_MISC , 0xE3 ,
rssical_radio_regs [ 1 ] ) ;
}
2010-01-15 15:06:47 +01:00
b43_phy_write ( dev , B43_NPHY_RSSIMC_0I_RSSI_Z , rssical_phy_regs [ 0 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_0Q_RSSI_Z , rssical_phy_regs [ 1 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_1I_RSSI_Z , rssical_phy_regs [ 2 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_1Q_RSSI_Z , rssical_phy_regs [ 3 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_0I_RSSI_X , rssical_phy_regs [ 4 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_0Q_RSSI_X , rssical_phy_regs [ 5 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_1I_RSSI_X , rssical_phy_regs [ 6 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_1Q_RSSI_X , rssical_phy_regs [ 7 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_0I_RSSI_Y , rssical_phy_regs [ 8 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_0Q_RSSI_Y , rssical_phy_regs [ 9 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_1I_RSSI_Y , rssical_phy_regs [ 10 ] ) ;
b43_phy_write ( dev , B43_NPHY_RSSIMC_1Q_RSSI_Y , rssical_phy_regs [ 11 ] ) ;
}
2014-07-08 15:11:06 +02:00
static void b43_nphy_tx_cal_radio_setup_rev19 ( struct b43_wldev * dev )
{
/* TODO */
}
static void b43_nphy_tx_cal_radio_setup_rev7 ( struct b43_wldev * dev )
{
2014-07-08 15:11:07 +02:00
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = dev - > phy . n ;
u16 * save = nphy - > tx_rx_cal_radio_saveregs ;
int core , off ;
u16 r , tmp ;
for ( core = 0 ; core < 2 ; core + + ) {
r = core ? 0x20 : 0 ;
off = core * 11 ;
save [ off + 0 ] = b43_radio_read ( dev , r + R2057_TX0_TX_SSI_MASTER ) ;
save [ off + 1 ] = b43_radio_read ( dev , r + R2057_TX0_IQCAL_VCM_HG ) ;
save [ off + 2 ] = b43_radio_read ( dev , r + R2057_TX0_IQCAL_IDAC ) ;
save [ off + 3 ] = b43_radio_read ( dev , r + R2057_TX0_TSSI_VCM ) ;
save [ off + 4 ] = 0 ;
save [ off + 5 ] = b43_radio_read ( dev , r + R2057_TX0_TX_SSI_MUX ) ;
if ( phy - > radio_rev ! = 5 )
save [ off + 6 ] = b43_radio_read ( dev , r + R2057_TX0_TSSIA ) ;
save [ off + 7 ] = b43_radio_read ( dev , r + R2057_TX0_TSSIG ) ;
save [ off + 8 ] = b43_radio_read ( dev , r + R2057_TX0_TSSI_MISC1 ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
b43_radio_write ( dev , r + R2057_TX0_TX_SSI_MASTER , 0xA ) ;
b43_radio_write ( dev , r + R2057_TX0_IQCAL_VCM_HG , 0x43 ) ;
b43_radio_write ( dev , r + R2057_TX0_IQCAL_IDAC , 0x55 ) ;
b43_radio_write ( dev , r + R2057_TX0_TSSI_VCM , 0 ) ;
b43_radio_write ( dev , r + R2057_TX0_TSSIG , 0 ) ;
if ( nphy - > use_int_tx_iq_lo_cal ) {
b43_radio_write ( dev , r + R2057_TX0_TX_SSI_MUX , 0x4 ) ;
tmp = true ? 0x31 : 0x21 ; /* TODO */
b43_radio_write ( dev , r + R2057_TX0_TSSIA , tmp ) ;
}
b43_radio_write ( dev , r + R2057_TX0_TSSI_MISC1 , 0x00 ) ;
} else {
b43_radio_write ( dev , r + R2057_TX0_TX_SSI_MASTER , 0x6 ) ;
b43_radio_write ( dev , r + R2057_TX0_IQCAL_VCM_HG , 0x43 ) ;
b43_radio_write ( dev , r + R2057_TX0_IQCAL_IDAC , 0x55 ) ;
b43_radio_write ( dev , r + R2057_TX0_TSSI_VCM , 0 ) ;
if ( phy - > radio_rev ! = 5 )
b43_radio_write ( dev , r + R2057_TX0_TSSIA , 0 ) ;
if ( nphy - > use_int_tx_iq_lo_cal ) {
b43_radio_write ( dev , r + R2057_TX0_TX_SSI_MUX , 0x6 ) ;
tmp = true ? 0x31 : 0x21 ; /* TODO */
b43_radio_write ( dev , r + R2057_TX0_TSSIG , tmp ) ;
}
b43_radio_write ( dev , r + R2057_TX0_TSSI_MISC1 , 0 ) ;
}
}
2014-07-08 15:11:06 +02:00
}
2010-01-15 15:55:18 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
static void b43_nphy_tx_cal_radio_setup ( struct b43_wldev * dev )
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2010-01-15 15:55:18 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
u16 * save = nphy - > tx_rx_cal_radio_saveregs ;
2010-01-30 20:18:06 +01:00
u16 tmp ;
u8 offset , i ;
2010-01-15 15:55:18 +01:00
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
b43_nphy_tx_cal_radio_setup_rev19 ( dev ) ;
} else if ( phy - > rev > = 7 ) {
b43_nphy_tx_cal_radio_setup_rev7 ( dev ) ;
} else if ( phy - > rev > = 3 ) {
2010-01-30 20:18:06 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
tmp = ( i = = 0 ) ? 0x2000 : 0x3000 ;
offset = i * 11 ;
2013-04-12 17:58:13 +02:00
save [ offset + 0 ] = b43_radio_read ( dev , B2055_CAL_RVARCTL ) ;
save [ offset + 1 ] = b43_radio_read ( dev , B2055_CAL_LPOCTL ) ;
save [ offset + 2 ] = b43_radio_read ( dev , B2055_CAL_TS ) ;
save [ offset + 3 ] = b43_radio_read ( dev , B2055_CAL_RCCALRTS ) ;
save [ offset + 4 ] = b43_radio_read ( dev , B2055_CAL_RCALRTS ) ;
save [ offset + 5 ] = b43_radio_read ( dev , B2055_PADDRV ) ;
save [ offset + 6 ] = b43_radio_read ( dev , B2055_XOCTL1 ) ;
save [ offset + 7 ] = b43_radio_read ( dev , B2055_XOCTL2 ) ;
save [ offset + 8 ] = b43_radio_read ( dev , B2055_XOREGUL ) ;
save [ offset + 9 ] = b43_radio_read ( dev , B2055_XOMISC ) ;
save [ offset + 10 ] = b43_radio_read ( dev , B2055_PLL_LFC1 ) ;
2010-01-30 20:18:06 +01:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ ) {
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , tmp | B2055_CAL_RVARCTL , 0x0A ) ;
b43_radio_write ( dev , tmp | B2055_CAL_LPOCTL , 0x40 ) ;
b43_radio_write ( dev , tmp | B2055_CAL_TS , 0x55 ) ;
b43_radio_write ( dev , tmp | B2055_CAL_RCCALRTS , 0 ) ;
b43_radio_write ( dev , tmp | B2055_CAL_RCALRTS , 0 ) ;
2010-01-30 20:18:06 +01:00
if ( nphy - > ipa5g_on ) {
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , tmp | B2055_PADDRV , 4 ) ;
b43_radio_write ( dev , tmp | B2055_XOCTL1 , 1 ) ;
2010-01-30 20:18:06 +01:00
} else {
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , tmp | B2055_PADDRV , 0 ) ;
b43_radio_write ( dev , tmp | B2055_XOCTL1 , 0x2F ) ;
2010-01-30 20:18:06 +01:00
}
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , tmp | B2055_XOCTL2 , 0 ) ;
2010-01-30 20:18:06 +01:00
} else {
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , tmp | B2055_CAL_RVARCTL , 0x06 ) ;
b43_radio_write ( dev , tmp | B2055_CAL_LPOCTL , 0x40 ) ;
b43_radio_write ( dev , tmp | B2055_CAL_TS , 0x55 ) ;
b43_radio_write ( dev , tmp | B2055_CAL_RCCALRTS , 0 ) ;
b43_radio_write ( dev , tmp | B2055_CAL_RCALRTS , 0 ) ;
b43_radio_write ( dev , tmp | B2055_XOCTL1 , 0 ) ;
2010-01-30 20:18:06 +01:00
if ( nphy - > ipa2g_on ) {
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , tmp | B2055_PADDRV , 6 ) ;
b43_radio_write ( dev , tmp | B2055_XOCTL2 ,
2010-01-30 20:18:06 +01:00
( dev - > phy . rev < 5 ) ? 0x11 : 0x01 ) ;
} else {
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , tmp | B2055_PADDRV , 0 ) ;
b43_radio_write ( dev , tmp | B2055_XOCTL2 , 0 ) ;
2010-01-30 20:18:06 +01:00
}
}
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , tmp | B2055_XOREGUL , 0 ) ;
b43_radio_write ( dev , tmp | B2055_XOMISC , 0 ) ;
b43_radio_write ( dev , tmp | B2055_PLL_LFC1 , 0 ) ;
2010-01-30 20:18:06 +01:00
}
2010-01-15 15:55:18 +01:00
} else {
2013-04-12 17:58:13 +02:00
save [ 0 ] = b43_radio_read ( dev , B2055_C1_TX_RF_IQCAL1 ) ;
b43_radio_write ( dev , B2055_C1_TX_RF_IQCAL1 , 0x29 ) ;
2010-01-15 15:55:18 +01:00
2013-04-12 17:58:13 +02:00
save [ 1 ] = b43_radio_read ( dev , B2055_C1_TX_RF_IQCAL2 ) ;
b43_radio_write ( dev , B2055_C1_TX_RF_IQCAL2 , 0x54 ) ;
2010-01-15 15:55:18 +01:00
2013-04-12 17:58:13 +02:00
save [ 2 ] = b43_radio_read ( dev , B2055_C2_TX_RF_IQCAL1 ) ;
b43_radio_write ( dev , B2055_C2_TX_RF_IQCAL1 , 0x29 ) ;
2010-01-15 15:55:18 +01:00
2013-04-12 17:58:13 +02:00
save [ 3 ] = b43_radio_read ( dev , B2055_C2_TX_RF_IQCAL2 ) ;
b43_radio_write ( dev , B2055_C2_TX_RF_IQCAL2 , 0x54 ) ;
2010-01-15 15:55:18 +01:00
2013-04-12 17:58:13 +02:00
save [ 3 ] = b43_radio_read ( dev , B2055_C1_PWRDET_RXTX ) ;
save [ 4 ] = b43_radio_read ( dev , B2055_C2_PWRDET_RXTX ) ;
2010-01-15 15:55:18 +01:00
if ( ! ( b43_phy_read ( dev , B43_NPHY_BANDCTL ) &
B43_NPHY_BANDCTL_5GHZ ) ) {
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , B2055_C1_PWRDET_RXTX , 0x04 ) ;
b43_radio_write ( dev , B2055_C2_PWRDET_RXTX , 0x04 ) ;
2010-01-15 15:55:18 +01:00
} else {
2013-04-12 17:58:13 +02:00
b43_radio_write ( dev , B2055_C1_PWRDET_RXTX , 0x20 ) ;
b43_radio_write ( dev , B2055_C2_PWRDET_RXTX , 0x20 ) ;
2010-01-15 15:55:18 +01:00
}
if ( dev - > phy . rev < 2 ) {
b43_radio_set ( dev , B2055_C1_TX_BB_MXGM , 0x20 ) ;
b43_radio_set ( dev , B2055_C2_TX_BB_MXGM , 0x20 ) ;
} else {
b43_radio_mask ( dev , B2055_C1_TX_BB_MXGM , ~ 0x20 ) ;
b43_radio_mask ( dev , B2055_C2_TX_BB_MXGM , ~ 0x20 ) ;
}
}
}
2010-01-15 16:06:35 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
static void b43_nphy_update_tx_cal_ladder ( struct b43_wldev * dev , u16 core )
{
struct b43_phy_n * nphy = dev - > phy . n ;
int i ;
u16 scale , entry ;
u16 tmp = nphy - > txcal_bbmult ;
if ( core = = 0 )
tmp > > = 8 ;
tmp & = 0xff ;
for ( i = 0 ; i < 18 ; i + + ) {
scale = ( ladder_lo [ i ] . percent * tmp ) / 100 ;
entry = ( ( scale & 0xFF ) < < 8 ) | ladder_lo [ i ] . g_env ;
2010-01-18 00:21:17 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 15 , i ) , entry ) ;
2010-01-15 16:06:35 +01:00
scale = ( ladder_iq [ i ] . percent * tmp ) / 100 ;
entry = ( ( scale & 0xFF ) < < 8 ) | ladder_iq [ i ] . g_env ;
2010-01-18 00:21:17 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 15 , i + 32 ) , entry ) ;
2010-01-15 16:06:35 +01:00
}
}
2014-07-19 12:52:41 +02:00
static void b43_nphy_pa_set_tx_dig_filter ( struct b43_wldev * dev , u16 offset ,
const s16 * filter )
{
int i ;
offset = B43_PHY_N ( offset ) ;
for ( i = 0 ; i < 15 ; i + + , offset + + )
b43_phy_write ( dev , offset , filter [ i ] ) ;
}
2010-01-22 01:53:15 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
static void b43_nphy_ext_pa_set_tx_dig_filters ( struct b43_wldev * dev )
{
2014-07-19 12:52:41 +02:00
b43_nphy_pa_set_tx_dig_filter ( dev , 0x2C5 ,
tbl_tx_filter_coef_rev4 [ 2 ] ) ;
2010-01-22 01:53:15 +01:00
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
static void b43_nphy_int_pa_set_tx_dig_filters ( struct b43_wldev * dev )
{
/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
2010-11-20 18:38:57 -08:00
static const u16 offset [ ] = { 0x186 , 0x195 , 0x2C5 } ;
2014-07-19 12:52:42 +02:00
static const s16 dig_filter_phy_rev16 [ ] = {
- 375 , 136 , - 407 , 208 , - 1527 ,
956 , 93 , 186 , 93 , 230 ,
- 44 , 230 , 201 , - 191 , 201 ,
} ;
2014-07-19 12:52:41 +02:00
int i ;
2010-01-22 01:53:15 +01:00
for ( i = 0 ; i < 3 ; i + + )
2014-07-19 12:52:41 +02:00
b43_nphy_pa_set_tx_dig_filter ( dev , offset [ i ] ,
tbl_tx_filter_coef_rev4 [ i ] ) ;
2010-01-22 01:53:15 +01:00
2014-07-19 12:52:42 +02:00
/* Verified with BCM43227 and BCM43228 */
if ( dev - > phy . rev = = 16 )
b43_nphy_pa_set_tx_dig_filter ( dev , 0x186 , dig_filter_phy_rev16 ) ;
2014-07-24 15:29:18 +02:00
/* Verified with BCM43131 and BCM43217 */
if ( dev - > phy . rev = = 17 ) {
2014-07-19 12:52:42 +02:00
b43_nphy_pa_set_tx_dig_filter ( dev , 0x186 , dig_filter_phy_rev16 ) ;
b43_nphy_pa_set_tx_dig_filter ( dev , 0x195 ,
tbl_tx_filter_coef_rev4 [ 1 ] ) ;
}
2014-05-31 20:49:40 +02:00
if ( b43_is_40mhz ( dev ) ) {
2014-07-19 12:52:41 +02:00
b43_nphy_pa_set_tx_dig_filter ( dev , 0x186 ,
tbl_tx_filter_coef_rev4 [ 3 ] ) ;
2014-07-19 12:52:42 +02:00
} else {
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ )
b43_nphy_pa_set_tx_dig_filter ( dev , 0x186 ,
tbl_tx_filter_coef_rev4 [ 5 ] ) ;
if ( dev - > phy . channel = = 14 )
b43_nphy_pa_set_tx_dig_filter ( dev , 0x186 ,
tbl_tx_filter_coef_rev4 [ 6 ] ) ;
2010-01-22 01:53:15 +01:00
}
}
2010-01-15 15:40:50 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
static struct nphy_txgains b43_nphy_get_tx_gains ( struct b43_wldev * dev )
{
struct b43_phy_n * nphy = dev - > phy . n ;
u16 curr_gain [ 2 ] ;
struct nphy_txgains target ;
const u32 * table = NULL ;
2010-11-28 12:59:43 +01:00
if ( ! nphy - > txpwrctrl ) {
2010-01-15 15:40:50 +01:00
int i ;
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , true ) ;
2010-01-18 00:21:35 +01:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 7 , 0x110 ) , 2 , curr_gain ) ;
2010-01-15 15:40:50 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , false ) ;
for ( i = 0 ; i < 2 ; + + i ) {
2014-07-08 15:11:07 +02:00
if ( dev - > phy . rev > = 7 ) {
target . ipa [ i ] = curr_gain [ i ] & 0x0007 ;
target . pad [ i ] = ( curr_gain [ i ] & 0x00F8 ) > > 3 ;
target . pga [ i ] = ( curr_gain [ i ] & 0x0F00 ) > > 8 ;
target . txgm [ i ] = ( curr_gain [ i ] & 0x7000 ) > > 12 ;
target . tx_lpf [ i ] = ( curr_gain [ i ] & 0x8000 ) > > 15 ;
} else if ( dev - > phy . rev > = 3 ) {
2010-01-15 15:40:50 +01:00
target . ipa [ i ] = curr_gain [ i ] & 0x000F ;
target . pad [ i ] = ( curr_gain [ i ] & 0x00F0 ) > > 4 ;
target . pga [ i ] = ( curr_gain [ i ] & 0x0F00 ) > > 8 ;
target . txgm [ i ] = ( curr_gain [ i ] & 0x7000 ) > > 12 ;
} else {
target . ipa [ i ] = curr_gain [ i ] & 0x0003 ;
target . pad [ i ] = ( curr_gain [ i ] & 0x000C ) > > 2 ;
target . pga [ i ] = ( curr_gain [ i ] & 0x0070 ) > > 4 ;
target . txgm [ i ] = ( curr_gain [ i ] & 0x0380 ) > > 7 ;
}
}
} else {
int i ;
u16 index [ 2 ] ;
index [ 0 ] = ( b43_phy_read ( dev , B43_NPHY_C1_TXPCTL_STAT ) &
B43_NPHY_TXPCTL_STAT_BIDX ) > >
B43_NPHY_TXPCTL_STAT_BIDX_SHIFT ;
index [ 1 ] = ( b43_phy_read ( dev , B43_NPHY_C2_TXPCTL_STAT ) &
B43_NPHY_TXPCTL_STAT_BIDX ) > >
B43_NPHY_TXPCTL_STAT_BIDX_SHIFT ;
for ( i = 0 ; i < 2 ; + + i ) {
2012-01-03 22:49:17 +01:00
table = b43_nphy_get_tx_gain_table ( dev ) ;
2014-07-02 22:42:45 +02:00
if ( ! table )
break ;
2014-07-08 15:11:07 +02:00
if ( dev - > phy . rev > = 7 ) {
target . ipa [ i ] = ( table [ index [ i ] ] > > 16 ) & 0x7 ;
target . pad [ i ] = ( table [ index [ i ] ] > > 19 ) & 0x1F ;
target . pga [ i ] = ( table [ index [ i ] ] > > 24 ) & 0xF ;
target . txgm [ i ] = ( table [ index [ i ] ] > > 28 ) & 0x7 ;
target . tx_lpf [ i ] = ( table [ index [ i ] ] > > 31 ) & 0x1 ;
} else if ( dev - > phy . rev > = 3 ) {
2010-01-15 15:40:50 +01:00
target . ipa [ i ] = ( table [ index [ i ] ] > > 16 ) & 0xF ;
target . pad [ i ] = ( table [ index [ i ] ] > > 20 ) & 0xF ;
target . pga [ i ] = ( table [ index [ i ] ] > > 24 ) & 0xF ;
target . txgm [ i ] = ( table [ index [ i ] ] > > 28 ) & 0xF ;
} else {
target . ipa [ i ] = ( table [ index [ i ] ] > > 16 ) & 0x3 ;
target . pad [ i ] = ( table [ index [ i ] ] > > 18 ) & 0x3 ;
target . pga [ i ] = ( table [ index [ i ] ] > > 20 ) & 0x7 ;
target . txgm [ i ] = ( table [ index [ i ] ] > > 23 ) & 0x7 ;
}
}
}
return target ;
}
2010-01-17 13:03:32 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
static void b43_nphy_tx_cal_phy_cleanup ( struct b43_wldev * dev )
{
u16 * regs = dev - > phy . n - > tx_rx_cal_phy_saveregs ;
if ( dev - > phy . rev > = 3 ) {
b43_phy_write ( dev , B43_NPHY_AFECTL_C1 , regs [ 0 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_C2 , regs [ 1 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER1 , regs [ 2 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , regs [ 3 ] ) ;
b43_phy_write ( dev , B43_NPHY_BBCFG , regs [ 4 ] ) ;
2010-01-18 00:21:17 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 3 ) , regs [ 5 ] ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 19 ) , regs [ 6 ] ) ;
2010-01-17 13:03:32 +01:00
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 , regs [ 7 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 , regs [ 8 ] ) ;
b43_phy_write ( dev , B43_NPHY_PAPD_EN0 , regs [ 9 ] ) ;
b43_phy_write ( dev , B43_NPHY_PAPD_EN1 , regs [ 10 ] ) ;
b43_nphy_reset_cca ( dev ) ;
} else {
b43_phy_maskset ( dev , B43_NPHY_AFECTL_C1 , 0x0FFF , regs [ 0 ] ) ;
b43_phy_maskset ( dev , B43_NPHY_AFECTL_C2 , 0x0FFF , regs [ 1 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , regs [ 2 ] ) ;
2010-01-18 00:21:17 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 2 ) , regs [ 3 ] ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 18 ) , regs [ 4 ] ) ;
2010-01-17 13:03:32 +01:00
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 , regs [ 5 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 , regs [ 6 ] ) ;
}
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
static void b43_nphy_tx_cal_phy_setup ( struct b43_wldev * dev )
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2014-07-08 15:11:07 +02:00
struct b43_phy_n * nphy = dev - > phy . n ;
2010-01-17 13:03:32 +01:00
u16 * regs = dev - > phy . n - > tx_rx_cal_phy_saveregs ;
u16 tmp ;
regs [ 0 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_C1 ) ;
regs [ 1 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_C2 ) ;
if ( dev - > phy . rev > = 3 ) {
b43_phy_maskset ( dev , B43_NPHY_AFECTL_C1 , 0xF0FF , 0x0A00 ) ;
b43_phy_maskset ( dev , B43_NPHY_AFECTL_C2 , 0xF0FF , 0x0A00 ) ;
tmp = b43_phy_read ( dev , B43_NPHY_AFECTL_OVER1 ) ;
regs [ 2 ] = tmp ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER1 , tmp | 0x0600 ) ;
tmp = b43_phy_read ( dev , B43_NPHY_AFECTL_OVER ) ;
regs [ 3 ] = tmp ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , tmp | 0x0600 ) ;
regs [ 4 ] = b43_phy_read ( dev , B43_NPHY_BBCFG ) ;
2010-07-21 11:48:05 -05:00
b43_phy_mask ( dev , B43_NPHY_BBCFG ,
~ B43_NPHY_BBCFG_RSTRX & 0xFFFF ) ;
2010-01-17 13:03:32 +01:00
2010-01-18 00:21:27 +01:00
tmp = b43_ntab_read ( dev , B43_NTAB16 ( 8 , 3 ) ) ;
2010-01-17 13:03:32 +01:00
regs [ 5 ] = tmp ;
2010-01-18 00:21:17 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 3 ) , 0 ) ;
2010-01-18 00:21:27 +01:00
tmp = b43_ntab_read ( dev , B43_NTAB16 ( 8 , 19 ) ) ;
2010-01-17 13:03:32 +01:00
regs [ 6 ] = tmp ;
2010-01-18 00:21:17 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 19 ) , 0 ) ;
2010-01-17 13:03:32 +01:00
regs [ 7 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC1 ) ;
regs [ 8 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC2 ) ;
2014-07-08 15:11:07 +02:00
if ( ! nphy - > use_int_tx_iq_lo_cal )
b43_nphy_rf_ctl_intc_override ( dev , N_INTC_OVERRIDE_PA ,
1 , 3 ) ;
else
b43_nphy_rf_ctl_intc_override ( dev , N_INTC_OVERRIDE_PA ,
0 , 3 ) ;
2013-03-29 11:37:02 +01:00
b43_nphy_rf_ctl_intc_override ( dev , N_INTC_OVERRIDE_TRSW , 2 , 1 ) ;
b43_nphy_rf_ctl_intc_override ( dev , N_INTC_OVERRIDE_TRSW , 8 , 2 ) ;
2010-01-17 13:03:32 +01:00
regs [ 9 ] = b43_phy_read ( dev , B43_NPHY_PAPD_EN0 ) ;
regs [ 10 ] = b43_phy_read ( dev , B43_NPHY_PAPD_EN1 ) ;
b43_phy_mask ( dev , B43_NPHY_PAPD_EN0 , ~ 0x0001 ) ;
b43_phy_mask ( dev , B43_NPHY_PAPD_EN1 , ~ 0x0001 ) ;
2014-07-08 15:11:06 +02:00
2014-07-08 15:11:07 +02:00
tmp = b43_nphy_read_lpf_ctl ( dev , 0 ) ;
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 )
2014-07-08 15:11:07 +02:00
b43_nphy_rf_ctl_override_rev19 ( dev , 0x80 , tmp , 0 , false ,
1 ) ;
2014-07-08 15:11:06 +02:00
else if ( phy - > rev > = 7 )
2014-07-08 15:11:07 +02:00
b43_nphy_rf_ctl_override_rev7 ( dev , 0x80 , tmp , 0 , false ,
1 ) ;
2014-07-08 15:11:06 +02:00
2014-07-08 15:11:07 +02:00
if ( nphy - > use_int_tx_iq_lo_cal & & true /* FIXME */ ) {
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
2014-07-08 15:11:07 +02:00
b43_nphy_rf_ctl_override_rev19 ( dev , 0x8 , 0 , 0x3 ,
false , 0 ) ;
2014-07-08 15:11:06 +02:00
} else if ( phy - > rev > = 8 ) {
2014-07-08 15:11:07 +02:00
b43_nphy_rf_ctl_override_rev7 ( dev , 0x8 , 0 , 0x3 ,
false , 0 ) ;
2014-07-08 15:11:06 +02:00
} else if ( phy - > rev = = 7 ) {
2014-07-08 15:11:07 +02:00
b43_radio_maskset ( dev , R2057_OVR_REG0 , 1 < < 4 , 1 < < 4 ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
b43_radio_maskset ( dev , R2057_PAD2G_TUNE_PUS_CORE0 , ~ 1 , 0 ) ;
b43_radio_maskset ( dev , R2057_PAD2G_TUNE_PUS_CORE1 , ~ 1 , 0 ) ;
} else {
b43_radio_maskset ( dev , R2057_IPA5G_CASCOFFV_PU_CORE0 , ~ 1 , 0 ) ;
b43_radio_maskset ( dev , R2057_IPA5G_CASCOFFV_PU_CORE1 , ~ 1 , 0 ) ;
}
2014-07-08 15:11:06 +02:00
}
}
2010-01-17 13:03:32 +01:00
} else {
b43_phy_maskset ( dev , B43_NPHY_AFECTL_C1 , 0x0FFF , 0xA000 ) ;
b43_phy_maskset ( dev , B43_NPHY_AFECTL_C2 , 0x0FFF , 0xA000 ) ;
tmp = b43_phy_read ( dev , B43_NPHY_AFECTL_OVER ) ;
regs [ 2 ] = tmp ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , tmp | 0x3000 ) ;
2010-01-18 00:21:27 +01:00
tmp = b43_ntab_read ( dev , B43_NTAB16 ( 8 , 2 ) ) ;
2010-01-17 13:03:32 +01:00
regs [ 3 ] = tmp ;
tmp | = 0x2000 ;
2010-01-18 00:21:17 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 2 ) , tmp ) ;
2010-01-18 00:21:27 +01:00
tmp = b43_ntab_read ( dev , B43_NTAB16 ( 8 , 18 ) ) ;
2010-01-17 13:03:32 +01:00
regs [ 4 ] = tmp ;
tmp | = 0x2000 ;
2010-01-18 00:21:17 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 8 , 18 ) , tmp ) ;
2010-01-17 13:03:32 +01:00
regs [ 5 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC1 ) ;
regs [ 6 ] = b43_phy_read ( dev , B43_NPHY_RFCTL_INTC2 ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_5GHZ )
tmp = 0x0180 ;
else
tmp = 0x0120 ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 , tmp ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 , tmp ) ;
}
}
2010-02-04 12:23:11 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
static void b43_nphy_save_cal ( struct b43_wldev * dev )
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2010-02-04 12:23:11 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
struct b43_phy_n_iq_comp * rxcal_coeffs = NULL ;
u16 * txcal_radio_regs = NULL ;
2010-02-27 13:03:37 +01:00
struct b43_chanspec * iqcal_chanspec ;
2010-02-04 12:23:11 +01:00
u16 * table = NULL ;
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 1 ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
rxcal_coeffs = & nphy - > cal_cache . rxcal_coeffs_2G ;
txcal_radio_regs = nphy - > cal_cache . txcal_radio_regs_2G ;
iqcal_chanspec = & nphy - > iqcal_chanspec_2G ;
table = nphy - > cal_cache . txcal_coeffs_2G ;
} else {
rxcal_coeffs = & nphy - > cal_cache . rxcal_coeffs_5G ;
txcal_radio_regs = nphy - > cal_cache . txcal_radio_regs_5G ;
iqcal_chanspec = & nphy - > iqcal_chanspec_5G ;
table = nphy - > cal_cache . txcal_coeffs_5G ;
}
b43_nphy_rx_iq_coeffs ( dev , false , rxcal_coeffs ) ;
/* TODO use some definitions */
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 7 ) {
2014-07-08 15:11:07 +02:00
txcal_radio_regs [ 0 ] = b43_radio_read ( dev ,
R2057_TX0_LOFT_FINE_I ) ;
txcal_radio_regs [ 1 ] = b43_radio_read ( dev ,
R2057_TX0_LOFT_FINE_Q ) ;
txcal_radio_regs [ 4 ] = b43_radio_read ( dev ,
R2057_TX0_LOFT_COARSE_I ) ;
txcal_radio_regs [ 5 ] = b43_radio_read ( dev ,
R2057_TX0_LOFT_COARSE_Q ) ;
txcal_radio_regs [ 2 ] = b43_radio_read ( dev ,
R2057_TX1_LOFT_FINE_I ) ;
txcal_radio_regs [ 3 ] = b43_radio_read ( dev ,
R2057_TX1_LOFT_FINE_Q ) ;
txcal_radio_regs [ 6 ] = b43_radio_read ( dev ,
R2057_TX1_LOFT_COARSE_I ) ;
txcal_radio_regs [ 7 ] = b43_radio_read ( dev ,
R2057_TX1_LOFT_COARSE_Q ) ;
2014-07-08 15:11:06 +02:00
} else if ( phy - > rev > = 3 ) {
2010-02-04 12:23:11 +01:00
txcal_radio_regs [ 0 ] = b43_radio_read ( dev , 0x2021 ) ;
txcal_radio_regs [ 1 ] = b43_radio_read ( dev , 0x2022 ) ;
txcal_radio_regs [ 2 ] = b43_radio_read ( dev , 0x3021 ) ;
txcal_radio_regs [ 3 ] = b43_radio_read ( dev , 0x3022 ) ;
txcal_radio_regs [ 4 ] = b43_radio_read ( dev , 0x2023 ) ;
txcal_radio_regs [ 5 ] = b43_radio_read ( dev , 0x2024 ) ;
txcal_radio_regs [ 6 ] = b43_radio_read ( dev , 0x3023 ) ;
txcal_radio_regs [ 7 ] = b43_radio_read ( dev , 0x3024 ) ;
} else {
txcal_radio_regs [ 0 ] = b43_radio_read ( dev , 0x8B ) ;
txcal_radio_regs [ 1 ] = b43_radio_read ( dev , 0xBA ) ;
txcal_radio_regs [ 2 ] = b43_radio_read ( dev , 0x8D ) ;
txcal_radio_regs [ 3 ] = b43_radio_read ( dev , 0xBC ) ;
}
2014-05-31 20:49:39 +02:00
iqcal_chanspec - > center_freq = dev - > phy . chandef - > chan - > center_freq ;
2014-05-31 20:49:41 +02:00
iqcal_chanspec - > channel_type =
cfg80211_get_chandef_type ( dev - > phy . chandef ) ;
2010-10-14 19:33:35 +02:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 15 , 80 ) , 8 , table ) ;
2010-02-04 12:23:11 +01:00
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , 0 ) ;
}
2010-01-15 15:18:35 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
static void b43_nphy_restore_cal ( struct b43_wldev * dev )
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2010-01-15 15:18:35 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
u16 coef [ 4 ] ;
u16 * loft = NULL ;
u16 * table = NULL ;
int i ;
u16 * txcal_radio_regs = NULL ;
struct b43_phy_n_iq_comp * rxcal_coeffs = NULL ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
2010-10-14 19:33:34 +02:00
if ( ! nphy - > iqcal_chanspec_2G . center_freq )
2010-01-15 15:18:35 +01:00
return ;
table = nphy - > cal_cache . txcal_coeffs_2G ;
loft = & nphy - > cal_cache . txcal_coeffs_2G [ 5 ] ;
} else {
2010-10-14 19:33:34 +02:00
if ( ! nphy - > iqcal_chanspec_5G . center_freq )
2010-01-15 15:18:35 +01:00
return ;
table = nphy - > cal_cache . txcal_coeffs_5G ;
loft = & nphy - > cal_cache . txcal_coeffs_5G [ 5 ] ;
}
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 80 ) , 4 , table ) ;
2010-01-15 15:18:35 +01:00
for ( i = 0 ; i < 4 ; i + + ) {
if ( dev - > phy . rev > = 3 )
table [ i ] = coef [ i ] ;
else
coef [ i ] = 0 ;
}
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 88 ) , 4 , coef ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 85 ) , 2 , loft ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 93 ) , 2 , loft ) ;
2010-01-15 15:18:35 +01:00
if ( dev - > phy . rev < 2 )
b43_nphy_tx_iq_workaround ( dev ) ;
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
txcal_radio_regs = nphy - > cal_cache . txcal_radio_regs_2G ;
rxcal_coeffs = & nphy - > cal_cache . rxcal_coeffs_2G ;
} else {
txcal_radio_regs = nphy - > cal_cache . txcal_radio_regs_5G ;
rxcal_coeffs = & nphy - > cal_cache . rxcal_coeffs_5G ;
}
/* TODO use some definitions */
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 7 ) {
2014-07-08 15:11:07 +02:00
b43_radio_write ( dev , R2057_TX0_LOFT_FINE_I ,
txcal_radio_regs [ 0 ] ) ;
b43_radio_write ( dev , R2057_TX0_LOFT_FINE_Q ,
txcal_radio_regs [ 1 ] ) ;
b43_radio_write ( dev , R2057_TX0_LOFT_COARSE_I ,
txcal_radio_regs [ 4 ] ) ;
b43_radio_write ( dev , R2057_TX0_LOFT_COARSE_Q ,
txcal_radio_regs [ 5 ] ) ;
b43_radio_write ( dev , R2057_TX1_LOFT_FINE_I ,
txcal_radio_regs [ 2 ] ) ;
b43_radio_write ( dev , R2057_TX1_LOFT_FINE_Q ,
txcal_radio_regs [ 3 ] ) ;
b43_radio_write ( dev , R2057_TX1_LOFT_COARSE_I ,
txcal_radio_regs [ 6 ] ) ;
b43_radio_write ( dev , R2057_TX1_LOFT_COARSE_Q ,
txcal_radio_regs [ 7 ] ) ;
2014-07-08 15:11:06 +02:00
} else if ( phy - > rev > = 3 ) {
2010-01-15 15:18:35 +01:00
b43_radio_write ( dev , 0x2021 , txcal_radio_regs [ 0 ] ) ;
b43_radio_write ( dev , 0x2022 , txcal_radio_regs [ 1 ] ) ;
b43_radio_write ( dev , 0x3021 , txcal_radio_regs [ 2 ] ) ;
b43_radio_write ( dev , 0x3022 , txcal_radio_regs [ 3 ] ) ;
b43_radio_write ( dev , 0x2023 , txcal_radio_regs [ 4 ] ) ;
b43_radio_write ( dev , 0x2024 , txcal_radio_regs [ 5 ] ) ;
b43_radio_write ( dev , 0x3023 , txcal_radio_regs [ 6 ] ) ;
b43_radio_write ( dev , 0x3024 , txcal_radio_regs [ 7 ] ) ;
} else {
b43_radio_write ( dev , 0x8B , txcal_radio_regs [ 0 ] ) ;
b43_radio_write ( dev , 0xBA , txcal_radio_regs [ 1 ] ) ;
b43_radio_write ( dev , 0x8D , txcal_radio_regs [ 2 ] ) ;
b43_radio_write ( dev , 0xBC , txcal_radio_regs [ 3 ] ) ;
}
b43_nphy_rx_iq_coeffs ( dev , true , rxcal_coeffs ) ;
}
2010-01-15 16:10:48 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
static int b43_nphy_cal_tx_iq_lo ( struct b43_wldev * dev ,
struct nphy_txgains target ,
bool full , bool mphase )
{
2014-05-31 20:49:39 +02:00
struct b43_phy * phy = & dev - > phy ;
2010-01-15 16:10:48 +01:00
struct b43_phy_n * nphy = dev - > phy . n ;
int i ;
int error = 0 ;
int freq ;
bool avoid = false ;
u8 length ;
2011-05-20 01:04:46 +02:00
u16 tmp , core , type , count , max , numb , last = 0 , cmd ;
2010-01-15 16:10:48 +01:00
const u16 * table ;
bool phy6or5x ;
u16 buffer [ 11 ] ;
u16 diq_start = 0 ;
u16 save [ 2 ] ;
u16 gain [ 2 ] ;
struct nphy_iqcal_params params [ 2 ] ;
bool updated [ 2 ] = { } ;
b43_nphy_stay_in_carrier_search ( dev , true ) ;
if ( dev - > phy . rev > = 4 ) {
avoid = nphy - > hang_avoid ;
2011-12-19 13:56:45 +00:00
nphy - > hang_avoid = false ;
2010-01-15 16:10:48 +01:00
}
2010-01-18 00:21:35 +01:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 7 , 0x110 ) , 2 , save ) ;
2010-01-15 16:10:48 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
b43_nphy_iq_cal_gain_params ( dev , i , target , & params [ i ] ) ;
gain [ i ] = params [ i ] . cal_gain ;
}
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 7 , 0x110 ) , 2 , gain ) ;
2010-01-15 16:10:48 +01:00
b43_nphy_tx_cal_radio_setup ( dev ) ;
2010-01-17 13:03:32 +01:00
b43_nphy_tx_cal_phy_setup ( dev ) ;
2010-01-15 16:10:48 +01:00
phy6or5x = dev - > phy . rev > = 6 | |
( dev - > phy . rev = = 5 & & nphy - > ipa2g_on & &
b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) ;
if ( phy6or5x ) {
2014-05-31 20:49:40 +02:00
if ( b43_is_40mhz ( dev ) ) {
2010-01-30 20:18:05 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 0 ) , 18 ,
tbl_tx_iqlo_cal_loft_ladder_40 ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 32 ) , 18 ,
tbl_tx_iqlo_cal_iqimb_ladder_40 ) ;
} else {
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 0 ) , 18 ,
tbl_tx_iqlo_cal_loft_ladder_20 ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 32 ) , 18 ,
tbl_tx_iqlo_cal_iqimb_ladder_20 ) ;
}
2010-01-15 16:10:48 +01:00
}
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 7 ) {
2014-07-08 15:11:07 +02:00
b43_phy_write ( dev , B43_NPHY_IQLOCAL_CMDGCTL , 0x8AD9 ) ;
2014-07-08 15:11:06 +02:00
} else {
b43_phy_write ( dev , B43_NPHY_IQLOCAL_CMDGCTL , 0x8AA9 ) ;
}
2010-01-15 16:10:48 +01:00
2014-05-31 20:49:40 +02:00
if ( ! b43_is_40mhz ( dev ) )
2010-01-15 16:10:48 +01:00
freq = 2500 ;
else
freq = 5000 ;
if ( nphy - > mphase_cal_phase_id > 2 )
2014-05-31 20:49:40 +02:00
b43_nphy_run_samples ( dev , ( b43_is_40mhz ( dev ) ? 40 : 20 ) * 8 ,
2014-06-22 23:18:21 +02:00
0xFFFF , 0 , true , false , false ) ;
2010-01-15 16:10:48 +01:00
else
2014-06-22 23:18:21 +02:00
error = b43_nphy_tx_tone ( dev , freq , 250 , true , false , false ) ;
2010-01-15 16:10:48 +01:00
if ( error = = 0 ) {
if ( nphy - > mphase_cal_phase_id > 2 ) {
table = nphy - > mphase_txcal_bestcoeffs ;
length = 11 ;
if ( dev - > phy . rev < 3 )
length - = 2 ;
} else {
if ( ! full & & nphy - > txiqlocal_coeffsvalid ) {
table = nphy - > txiqlocal_bestc ;
length = 11 ;
if ( dev - > phy . rev < 3 )
length - = 2 ;
} else {
full = true ;
if ( dev - > phy . rev > = 3 ) {
table = tbl_tx_iqlo_cal_startcoefs_nphyrev3 ;
length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3 ;
} else {
table = tbl_tx_iqlo_cal_startcoefs ;
length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS ;
}
}
}
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 64 ) , length , table ) ;
2010-01-15 16:10:48 +01:00
if ( full ) {
if ( dev - > phy . rev > = 3 )
max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 ;
else
max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL ;
} else {
if ( dev - > phy . rev > = 3 )
max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3 ;
else
max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL ;
}
if ( mphase ) {
count = nphy - > mphase_txcal_cmdidx ;
numb = min ( max ,
( u16 ) ( count + nphy - > mphase_txcal_numcmds ) ) ;
} else {
count = 0 ;
numb = max ;
}
for ( ; count < numb ; count + + ) {
if ( full ) {
if ( dev - > phy . rev > = 3 )
cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3 [ count ] ;
else
cmd = tbl_tx_iqlo_cal_cmds_fullcal [ count ] ;
} else {
if ( dev - > phy . rev > = 3 )
cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3 [ count ] ;
else
cmd = tbl_tx_iqlo_cal_cmds_recal [ count ] ;
}
core = ( cmd & 0x3000 ) > > 12 ;
type = ( cmd & 0x0F00 ) > > 8 ;
if ( phy6or5x & & updated [ core ] = = 0 ) {
b43_nphy_update_tx_cal_ladder ( dev , core ) ;
2011-12-19 13:56:45 +00:00
updated [ core ] = true ;
2010-01-15 16:10:48 +01:00
}
tmp = ( params [ core ] . ncorr [ type ] < < 8 ) | 0x66 ;
b43_phy_write ( dev , B43_NPHY_IQLOCAL_CMDNNUM , tmp ) ;
if ( type = = 1 | | type = = 3 | | type = = 4 ) {
2010-01-18 00:21:27 +01:00
buffer [ 0 ] = b43_ntab_read ( dev ,
B43_NTAB16 ( 15 , 69 + core ) ) ;
2010-01-15 16:10:48 +01:00
diq_start = buffer [ 0 ] ;
buffer [ 0 ] = 0 ;
2010-01-18 00:21:17 +01:00
b43_ntab_write ( dev , B43_NTAB16 ( 15 , 69 + core ) ,
0 ) ;
2010-01-15 16:10:48 +01:00
}
b43_phy_write ( dev , B43_NPHY_IQLOCAL_CMD , cmd ) ;
for ( i = 0 ; i < 2000 ; i + + ) {
tmp = b43_phy_read ( dev , B43_NPHY_IQLOCAL_CMD ) ;
if ( tmp & 0xC000 )
break ;
udelay ( 10 ) ;
}
2010-01-18 00:21:35 +01:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 15 , 96 ) , length ,
buffer ) ;
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 64 ) , length ,
buffer ) ;
2010-01-15 16:10:48 +01:00
if ( type = = 1 | | type = = 3 | | type = = 4 )
buffer [ 0 ] = diq_start ;
}
if ( mphase )
nphy - > mphase_txcal_cmdidx = ( numb > = max ) ? 0 : numb ;
last = ( dev - > phy . rev < 3 ) ? 6 : 7 ;
if ( ! mphase | | nphy - > mphase_cal_phase_id = = last ) {
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 96 ) , 4 , buffer ) ;
2010-01-18 00:21:35 +01:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 15 , 80 ) , 4 , buffer ) ;
2010-01-15 16:10:48 +01:00
if ( dev - > phy . rev < 3 ) {
buffer [ 0 ] = 0 ;
buffer [ 1 ] = 0 ;
buffer [ 2 ] = 0 ;
buffer [ 3 ] = 0 ;
}
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 88 ) , 4 ,
buffer ) ;
2010-04-01 23:11:10 +02:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 15 , 101 ) , 2 ,
2010-01-18 00:21:21 +01:00
buffer ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 85 ) , 2 ,
buffer ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 93 ) , 2 ,
buffer ) ;
2010-01-15 16:10:48 +01:00
length = 11 ;
if ( dev - > phy . rev < 3 )
length - = 2 ;
2010-01-18 00:21:35 +01:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 15 , 96 ) , length ,
nphy - > txiqlocal_bestc ) ;
2010-01-15 16:10:48 +01:00
nphy - > txiqlocal_coeffsvalid = true ;
2010-10-14 19:33:34 +02:00
nphy - > txiqlocal_chanspec . center_freq =
2014-05-31 20:49:39 +02:00
phy - > chandef - > chan - > center_freq ;
2010-10-14 19:33:34 +02:00
nphy - > txiqlocal_chanspec . channel_type =
2014-05-31 20:49:41 +02:00
cfg80211_get_chandef_type ( phy - > chandef ) ;
2010-01-15 16:10:48 +01:00
} else {
length = 11 ;
if ( dev - > phy . rev < 3 )
length - = 2 ;
2010-01-18 00:21:35 +01:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 15 , 96 ) , length ,
nphy - > mphase_txcal_bestcoeffs ) ;
2010-01-15 16:10:48 +01:00
}
2010-01-17 13:03:48 +01:00
b43_nphy_stop_playback ( dev ) ;
2010-01-15 16:10:48 +01:00
b43_phy_write ( dev , B43_NPHY_IQLOCAL_CMDGCTL , 0 ) ;
}
2010-01-17 13:03:32 +01:00
b43_nphy_tx_cal_phy_cleanup ( dev ) ;
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 7 , 0x110 ) , 2 , save ) ;
2010-01-15 16:10:48 +01:00
if ( dev - > phy . rev < 2 & & ( ! mphase | | nphy - > mphase_cal_phase_id = = last ) )
b43_nphy_tx_iq_workaround ( dev ) ;
if ( dev - > phy . rev > = 4 )
nphy - > hang_avoid = avoid ;
b43_nphy_stay_in_carrier_search ( dev , false ) ;
return error ;
}
2010-02-04 12:23:10 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
static void b43_nphy_reapply_tx_cal_coeffs ( struct b43_wldev * dev )
{
struct b43_phy_n * nphy = dev - > phy . n ;
u8 i ;
u16 buffer [ 7 ] ;
bool equal = true ;
2010-02-27 13:03:37 +01:00
if ( ! nphy - > txiqlocal_coeffsvalid | |
2014-05-31 20:49:39 +02:00
nphy - > txiqlocal_chanspec . center_freq ! = dev - > phy . chandef - > chan - > center_freq | |
2014-05-31 20:49:41 +02:00
nphy - > txiqlocal_chanspec . channel_type ! = cfg80211_get_chandef_type ( dev - > phy . chandef ) )
2010-02-04 12:23:10 +01:00
return ;
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 15 , 80 ) , 7 , buffer ) ;
for ( i = 0 ; i < 4 ; i + + ) {
if ( buffer [ i ] ! = nphy - > txiqlocal_bestc [ i ] ) {
equal = false ;
break ;
}
}
if ( ! equal ) {
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 80 ) , 4 ,
nphy - > txiqlocal_bestc ) ;
for ( i = 0 ; i < 4 ; i + + )
buffer [ i ] = 0 ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 88 ) , 4 ,
buffer ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 85 ) , 2 ,
& nphy - > txiqlocal_bestc [ 5 ] ) ;
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 15 , 93 ) , 2 ,
& nphy - > txiqlocal_bestc [ 5 ] ) ;
}
}
2010-01-15 16:20:56 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
static int b43_nphy_rev2_cal_rx_iq ( struct b43_wldev * dev ,
struct nphy_txgains target , u8 type , bool debug )
{
struct b43_phy_n * nphy = dev - > phy . n ;
int i , j , index ;
u8 rfctl [ 2 ] ;
u8 afectl_core ;
u16 tmp [ 6 ] ;
2010-12-07 21:55:57 +01:00
u16 uninitialized_var ( cur_hpf1 ) , uninitialized_var ( cur_hpf2 ) , cur_lna ;
2010-01-15 16:20:56 +01:00
u32 real , imag ;
enum ieee80211_band band ;
u8 use ;
u16 cur_hpf ;
u16 lna [ 3 ] = { 3 , 3 , 1 } ;
u16 hpf1 [ 3 ] = { 7 , 2 , 0 } ;
u16 hpf2 [ 3 ] = { 2 , 0 , 0 } ;
2010-01-18 00:21:49 +01:00
u32 power [ 3 ] = { } ;
2010-01-15 16:20:56 +01:00
u16 gain_save [ 2 ] ;
u16 cal_gain [ 2 ] ;
struct nphy_iqcal_params cal_params [ 2 ] ;
struct nphy_iq_est est ;
int ret = 0 ;
bool playtone = true ;
int desired = 13 ;
b43_nphy_stay_in_carrier_search ( dev , 1 ) ;
if ( dev - > phy . rev < 2 )
2010-02-04 12:23:10 +01:00
b43_nphy_reapply_tx_cal_coeffs ( dev ) ;
2010-01-18 00:21:35 +01:00
b43_ntab_read_bulk ( dev , B43_NTAB16 ( 7 , 0x110 ) , 2 , gain_save ) ;
2010-01-15 16:20:56 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
b43_nphy_iq_cal_gain_params ( dev , i , target , & cal_params [ i ] ) ;
cal_gain [ i ] = cal_params [ i ] . cal_gain ;
}
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 7 , 0x110 ) , 2 , cal_gain ) ;
2010-01-15 16:20:56 +01:00
for ( i = 0 ; i < 2 ; i + + ) {
if ( i = = 0 ) {
rfctl [ 0 ] = B43_NPHY_RFCTL_INTC1 ;
rfctl [ 1 ] = B43_NPHY_RFCTL_INTC2 ;
afectl_core = B43_NPHY_AFECTL_C1 ;
} else {
rfctl [ 0 ] = B43_NPHY_RFCTL_INTC2 ;
rfctl [ 1 ] = B43_NPHY_RFCTL_INTC1 ;
afectl_core = B43_NPHY_AFECTL_C2 ;
}
tmp [ 1 ] = b43_phy_read ( dev , B43_NPHY_RFSEQCA ) ;
tmp [ 2 ] = b43_phy_read ( dev , afectl_core ) ;
tmp [ 3 ] = b43_phy_read ( dev , B43_NPHY_AFECTL_OVER ) ;
tmp [ 4 ] = b43_phy_read ( dev , rfctl [ 0 ] ) ;
tmp [ 5 ] = b43_phy_read ( dev , rfctl [ 1 ] ) ;
b43_phy_maskset ( dev , B43_NPHY_RFSEQCA ,
2010-07-21 11:48:05 -05:00
~ B43_NPHY_RFSEQCA_RXDIS & 0xFFFF ,
2010-01-15 16:20:56 +01:00
( ( 1 - i ) < < B43_NPHY_RFSEQCA_RXDIS_SHIFT ) ) ;
b43_phy_maskset ( dev , B43_NPHY_RFSEQCA , ~ B43_NPHY_RFSEQCA_TXEN ,
( 1 - i ) ) ;
b43_phy_set ( dev , afectl_core , 0x0006 ) ;
b43_phy_set ( dev , B43_NPHY_AFECTL_OVER , 0x0006 ) ;
band = b43_current_band ( dev - > wl ) ;
if ( nphy - > rxcalparams & 0xFF000000 ) {
if ( band = = IEEE80211_BAND_5GHZ )
b43_phy_write ( dev , rfctl [ 0 ] , 0x140 ) ;
else
b43_phy_write ( dev , rfctl [ 0 ] , 0x110 ) ;
} else {
if ( band = = IEEE80211_BAND_5GHZ )
b43_phy_write ( dev , rfctl [ 0 ] , 0x180 ) ;
else
b43_phy_write ( dev , rfctl [ 0 ] , 0x120 ) ;
}
if ( band = = IEEE80211_BAND_5GHZ )
b43_phy_write ( dev , rfctl [ 1 ] , 0x148 ) ;
else
b43_phy_write ( dev , rfctl [ 1 ] , 0x114 ) ;
if ( nphy - > rxcalparams & 0x10000 ) {
b43_radio_maskset ( dev , B2055_C1_GENSPARE2 , 0xFC ,
( i + 1 ) ) ;
b43_radio_maskset ( dev , B2055_C2_GENSPARE2 , 0xFC ,
( 2 - i ) ) ;
}
2010-10-22 17:43:45 +02:00
for ( j = 0 ; j < 4 ; j + + ) {
2010-01-15 16:20:56 +01:00
if ( j < 3 ) {
cur_lna = lna [ j ] ;
cur_hpf1 = hpf1 [ j ] ;
cur_hpf2 = hpf2 [ j ] ;
} else {
if ( power [ 1 ] > 10000 ) {
use = 1 ;
cur_hpf = cur_hpf1 ;
index = 2 ;
} else {
if ( power [ 0 ] > 10000 ) {
use = 1 ;
cur_hpf = cur_hpf1 ;
index = 1 ;
} else {
index = 0 ;
use = 2 ;
cur_hpf = cur_hpf2 ;
}
}
cur_lna = lna [ index ] ;
cur_hpf1 = hpf1 [ index ] ;
cur_hpf2 = hpf2 [ index ] ;
cur_hpf + = desired - hweight32 ( power [ index ] ) ;
cur_hpf = clamp_val ( cur_hpf , 0 , 10 ) ;
if ( use = = 1 )
cur_hpf1 = cur_hpf ;
else
cur_hpf2 = cur_hpf ;
}
tmp [ 0 ] = ( ( cur_hpf2 < < 8 ) | ( cur_hpf1 < < 4 ) |
( cur_lna < < 2 ) ) ;
2013-03-30 21:50:46 +01:00
b43_nphy_rf_ctl_override ( dev , 0x400 , tmp [ 0 ] , 3 ,
2010-01-22 01:53:13 +01:00
false ) ;
2010-01-18 00:21:49 +01:00
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RESET2RX ) ;
2010-01-17 13:03:48 +01:00
b43_nphy_stop_playback ( dev ) ;
2010-01-15 16:20:56 +01:00
if ( playtone ) {
2010-01-22 01:53:16 +01:00
ret = b43_nphy_tx_tone ( dev , 4000 ,
( nphy - > rxcalparams & 0xFFFF ) ,
2014-06-22 23:18:21 +02:00
false , false , true ) ;
2010-01-15 16:20:56 +01:00
playtone = false ;
} else {
2014-06-22 23:18:21 +02:00
b43_nphy_run_samples ( dev , 160 , 0xFFFF , 0 , false ,
false , true ) ;
2010-01-15 16:20:56 +01:00
}
if ( ret = = 0 ) {
if ( j < 3 ) {
b43_nphy_rx_iq_est ( dev , & est , 1024 , 32 ,
false ) ;
if ( i = = 0 ) {
real = est . i0_pwr ;
imag = est . q0_pwr ;
} else {
real = est . i1_pwr ;
imag = est . q1_pwr ;
}
power [ i ] = ( ( real + imag ) / 1024 ) + 1 ;
} else {
b43_nphy_calc_rx_iq_comp ( dev , 1 < < i ) ;
}
2010-01-17 13:03:48 +01:00
b43_nphy_stop_playback ( dev ) ;
2010-01-15 16:20:56 +01:00
}
if ( ret ! = 0 )
break ;
}
b43_radio_mask ( dev , B2055_C1_GENSPARE2 , 0xFC ) ;
b43_radio_mask ( dev , B2055_C2_GENSPARE2 , 0xFC ) ;
b43_phy_write ( dev , rfctl [ 1 ] , tmp [ 5 ] ) ;
b43_phy_write ( dev , rfctl [ 0 ] , tmp [ 4 ] ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , tmp [ 3 ] ) ;
b43_phy_write ( dev , afectl_core , tmp [ 2 ] ) ;
b43_phy_write ( dev , B43_NPHY_RFSEQCA , tmp [ 1 ] ) ;
if ( ret ! = 0 )
break ;
}
2013-03-30 21:50:46 +01:00
b43_nphy_rf_ctl_override ( dev , 0x400 , 0 , 3 , true ) ;
2010-01-17 13:04:02 +01:00
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RESET2RX ) ;
2010-01-18 00:21:21 +01:00
b43_ntab_write_bulk ( dev , B43_NTAB16 ( 7 , 0x110 ) , 2 , gain_save ) ;
2010-01-15 16:20:56 +01:00
b43_nphy_stay_in_carrier_search ( dev , 0 ) ;
return ret ;
}
static int b43_nphy_rev3_cal_rx_iq ( struct b43_wldev * dev ,
struct nphy_txgains target , u8 type , bool debug )
{
return - 1 ;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
static int b43_nphy_cal_rx_iq ( struct b43_wldev * dev ,
struct nphy_txgains target , u8 type , bool debug )
{
2014-07-08 15:11:06 +02:00
if ( dev - > phy . rev > = 7 )
type = 0 ;
2010-01-15 16:20:56 +01:00
if ( dev - > phy . rev > = 3 )
return b43_nphy_rev3_cal_rx_iq ( dev , target , type , debug ) ;
else
return b43_nphy_rev2_cal_rx_iq ( dev , target , type , debug ) ;
}
2010-08-16 22:39:17 +02:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
static void b43_nphy_set_rx_core_state ( struct b43_wldev * dev , u8 mask )
{
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = phy - > n ;
2010-11-18 21:11:43 +01:00
/* u16 buf[16]; it's rev3+ */
2010-08-16 22:39:17 +02:00
2010-08-22 21:47:32 +02:00
nphy - > phyrxchain = mask ;
2010-08-16 22:39:17 +02:00
if ( 0 /* FIXME clk */ )
return ;
b43_mac_suspend ( dev ) ;
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , true ) ;
b43_phy_maskset ( dev , B43_NPHY_RFSEQCA , ~ B43_NPHY_RFSEQCA_RXEN ,
( mask & 0x3 ) < < B43_NPHY_RFSEQCA_RXEN_SHIFT ) ;
2010-08-22 21:47:32 +02:00
if ( ( mask & 0x3 ) ! = 0x3 ) {
2010-08-16 22:39:17 +02:00
b43_phy_write ( dev , B43_NPHY_HPANT_SWTHRES , 1 ) ;
if ( dev - > phy . rev > = 3 ) {
/* TODO */
}
} else {
b43_phy_write ( dev , B43_NPHY_HPANT_SWTHRES , 0x1E ) ;
if ( dev - > phy . rev > = 3 ) {
/* TODO */
}
}
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RESET2RX ) ;
if ( nphy - > hang_avoid )
b43_nphy_stay_in_carrier_search ( dev , false ) ;
b43_mac_enable ( dev ) ;
}
2014-07-31 21:59:48 +02:00
static enum b43_txpwr_result b43_nphy_op_recalc_txpower ( struct b43_wldev * dev ,
bool ignore_tssi )
{
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = dev - > phy . n ;
struct ieee80211_channel * channel = dev - > wl - > hw - > conf . chandef . chan ;
struct b43_ppr * ppr = & nphy - > tx_pwr_max_ppr ;
u8 max ; /* qdBm */
bool tx_pwr_state ;
if ( nphy - > tx_pwr_last_recalc_freq = = channel - > center_freq & &
nphy - > tx_pwr_last_recalc_limit = = phy - > desired_txpower )
return B43_TXPWR_RES_DONE ;
/* Make sure we have a clean PPR */
b43_ppr_clear ( dev , ppr ) ;
/* HW limitations */
b43_ppr_load_max_from_sprom ( dev , ppr , B43_BAND_2G ) ;
/* Regulatory & user settings */
max = INT_TO_Q52 ( phy - > chandef - > chan - > max_power ) ;
if ( phy - > desired_txpower )
max = min_t ( u8 , max , INT_TO_Q52 ( phy - > desired_txpower ) ) ;
b43_ppr_apply_max ( dev , ppr , max ) ;
if ( b43_debug ( dev , B43_DBG_XMITPOWER ) )
b43dbg ( dev - > wl , " Calculated TX power: " Q52_FMT " \n " ,
Q52_ARG ( b43_ppr_get_max ( dev , ppr ) ) ) ;
/* TODO: Enable this once we get gains working */
#if 0
/* Some extra gains */
hw_gain = 6 ; /* N-PHY specific */
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
hw_gain + = sprom - > antenna_gain . a0 ;
else
hw_gain + = sprom - > antenna_gain . a1 ;
b43_ppr_add ( dev , ppr , - hw_gain ) ;
# endif
/* Make sure we didn't go too low */
b43_ppr_apply_min ( dev , ppr , INT_TO_Q52 ( 8 ) ) ;
/* Apply */
tx_pwr_state = nphy - > txpwrctrl ;
b43_mac_suspend ( dev ) ;
b43_nphy_tx_power_ctl_setup ( dev ) ;
if ( dev - > dev - > core_rev = = 11 | | dev - > dev - > core_rev = = 12 ) {
b43_maskset32 ( dev , B43_MMIO_MACCTL , ~ 0 , B43_MACCTL_PHY_LOCK ) ;
b43_read32 ( dev , B43_MMIO_MACCTL ) ;
udelay ( 1 ) ;
}
b43_nphy_tx_power_ctrl ( dev , nphy - > txpwrctrl ) ;
if ( dev - > dev - > core_rev = = 11 | | dev - > dev - > core_rev = = 12 )
b43_maskset32 ( dev , B43_MMIO_MACCTL , ~ B43_MACCTL_PHY_LOCK , 0 ) ;
b43_mac_enable ( dev ) ;
nphy - > tx_pwr_last_recalc_freq = channel - > center_freq ;
nphy - > tx_pwr_last_recalc_limit = phy - > desired_txpower ;
return B43_TXPWR_RES_DONE ;
}
2011-12-17 13:57:27 +01:00
/**************************************************
* N - PHY init
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
static void b43_nphy_update_mimo_config ( struct b43_wldev * dev , s32 preamble )
{
u16 mimocfg = b43_phy_read ( dev , B43_NPHY_MIMOCFG ) ;
mimocfg | = B43_NPHY_MIMOCFG_AUTO ;
if ( preamble = = 1 )
mimocfg | = B43_NPHY_MIMOCFG_GFMIX ;
else
mimocfg & = ~ B43_NPHY_MIMOCFG_GFMIX ;
b43_phy_write ( dev , B43_NPHY_MIMOCFG , mimocfg ) ;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
static void b43_nphy_bphy_init ( struct b43_wldev * dev )
{
unsigned int i ;
u16 val ;
val = 0x1E1F ;
for ( i = 0 ; i < 16 ; i + + ) {
b43_phy_write ( dev , B43_PHY_N_BMODE ( 0x88 + i ) , val ) ;
val - = 0x202 ;
}
val = 0x3E3F ;
for ( i = 0 ; i < 16 ; i + + ) {
b43_phy_write ( dev , B43_PHY_N_BMODE ( 0x98 + i ) , val ) ;
val - = 0x202 ;
}
b43_phy_write ( dev , B43_PHY_N_BMODE ( 0x38 ) , 0x668 ) ;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
static void b43_nphy_superswitch_init ( struct b43_wldev * dev , bool init )
{
2014-07-08 15:11:06 +02:00
if ( dev - > phy . rev > = 7 )
return ;
2011-12-17 13:57:27 +01:00
if ( dev - > phy . rev > = 3 ) {
if ( ! init )
return ;
if ( 0 /* FIXME */ ) {
b43_ntab_write ( dev , B43_NTAB16 ( 9 , 2 ) , 0x211 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 9 , 3 ) , 0x222 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 9 , 8 ) , 0x144 ) ;
b43_ntab_write ( dev , B43_NTAB16 ( 9 , 12 ) , 0x188 ) ;
}
} else {
b43_phy_write ( dev , B43_NPHY_GPIO_LOOEN , 0 ) ;
b43_phy_write ( dev , B43_NPHY_GPIO_HIOEN , 0 ) ;
switch ( dev - > dev - > bus_type ) {
# ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA :
bcma_chipco_gpio_control ( & dev - > dev - > bdev - > bus - > drv_cc ,
0xFC00 , 0xFC00 ) ;
break ;
# endif
# ifdef CONFIG_B43_SSB
case B43_BUS_SSB :
ssb_chipco_gpio_control ( & dev - > dev - > sdev - > bus - > chipco ,
0xFC00 , 0xFC00 ) ;
break ;
# endif
}
2012-01-02 19:31:21 +01:00
b43_maskset32 ( dev , B43_MMIO_MACCTL , ~ B43_MACCTL_GPOUTSMSK , 0 ) ;
b43_maskset16 ( dev , B43_MMIO_GPIO_MASK , ~ 0 , 0xFC00 ) ;
b43_maskset16 ( dev , B43_MMIO_GPIO_CONTROL , ( ~ 0xFC00 & 0xFFFF ) ,
0 ) ;
2011-12-17 13:57:27 +01:00
if ( init ) {
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_LO1 , 0x2D8 ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_UP1 , 0x301 ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_LO2 , 0x2D8 ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_LUT_TRSW_UP2 , 0x301 ) ;
}
}
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
2013-03-28 12:37:30 +01:00
static int b43_phy_initn ( struct b43_wldev * dev )
2008-01-09 16:13:56 +01:00
{
2011-05-18 02:06:39 +02:00
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
2008-01-18 01:09:25 +01:00
struct b43_phy * phy = & dev - > phy ;
2010-01-15 13:27:29 +01:00
struct b43_phy_n * nphy = phy - > n ;
u8 tx_pwr_state ;
struct nphy_txgains target ;
2008-01-18 01:09:25 +01:00
u16 tmp ;
2010-01-15 13:27:29 +01:00
enum ieee80211_band tmp2 ;
bool do_rssi_cal ;
u16 clip [ 2 ] ;
bool do_cal = false ;
2008-01-18 01:09:25 +01:00
2010-01-15 13:27:29 +01:00
if ( ( dev - > phy . rev > = 3 ) & &
2011-05-18 02:06:39 +02:00
( sprom - > boardflags_lo & B43_BFL_EXTLNA ) & &
2010-01-15 13:27:29 +01:00
( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) ) {
2011-07-06 15:45:26 +02:00
switch ( dev - > dev - > bus_type ) {
2011-07-06 15:45:27 +02:00
# ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA :
bcma_cc_set32 ( & dev - > dev - > bdev - > bus - > drv_cc ,
BCMA_CC_CHIPCTL , 0x40 ) ;
break ;
# endif
2011-07-06 15:45:26 +02:00
# ifdef CONFIG_B43_SSB
case B43_BUS_SSB :
chipco_set32 ( & dev - > dev - > sdev - > bus - > chipco ,
SSB_CHIPCO_CHIPCTL , 0x40 ) ;
break ;
# endif
}
2010-01-15 13:27:29 +01:00
}
2014-07-08 15:11:07 +02:00
nphy - > use_int_tx_iq_lo_cal = b43_nphy_ipa ( dev ) | |
phy - > rev > = 7 | |
( phy - > rev > = 5 & &
sprom - > boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL ) ;
2010-01-15 13:27:29 +01:00
nphy - > deaf_count = 0 ;
2008-01-18 01:09:25 +01:00
b43_nphy_tables_init ( dev ) ;
2010-01-15 13:27:29 +01:00
nphy - > crsminpwr_adjusted = false ;
nphy - > noisevars_adjusted = false ;
2008-01-18 01:09:25 +01:00
/* Clear all overrides */
2010-01-15 13:27:29 +01:00
if ( dev - > phy . rev > = 3 ) {
b43_phy_write ( dev , B43_NPHY_TXF_40CO_B1S1 , 0 ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_OVER , 0 ) ;
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 7 ) {
2014-07-08 15:11:07 +02:00
b43_phy_write ( dev , B43_NPHY_REV7_RF_CTL_OVER3 , 0 ) ;
b43_phy_write ( dev , B43_NPHY_REV7_RF_CTL_OVER4 , 0 ) ;
b43_phy_write ( dev , B43_NPHY_REV7_RF_CTL_OVER5 , 0 ) ;
b43_phy_write ( dev , B43_NPHY_REV7_RF_CTL_OVER6 , 0 ) ;
2014-07-08 15:11:06 +02:00
}
if ( phy - > rev > = 19 ) {
/* TODO */
}
2010-01-15 13:27:29 +01:00
b43_phy_write ( dev , B43_NPHY_TXF_40CO_B1S0 , 0 ) ;
b43_phy_write ( dev , B43_NPHY_TXF_40CO_B32S1 , 0 ) ;
} else {
b43_phy_write ( dev , B43_NPHY_RFCTL_OVER , 0 ) ;
}
2008-01-18 01:09:25 +01:00
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC1 , 0 ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC2 , 0 ) ;
2010-01-15 13:27:29 +01:00
if ( dev - > phy . rev < 6 ) {
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC3 , 0 ) ;
b43_phy_write ( dev , B43_NPHY_RFCTL_INTC4 , 0 ) ;
}
2008-01-18 01:09:25 +01:00
b43_phy_mask ( dev , B43_NPHY_RFSEQMODE ,
~ ( B43_NPHY_RFSEQMODE_CAOVER |
B43_NPHY_RFSEQMODE_TROVER ) ) ;
2010-01-15 13:27:29 +01:00
if ( dev - > phy . rev > = 3 )
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER1 , 0 ) ;
2008-01-18 01:09:25 +01:00
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , 0 ) ;
2010-01-15 13:27:29 +01:00
if ( dev - > phy . rev < = 2 ) {
tmp = ( dev - > phy . rev = = 2 ) ? 0x3B : 0x40 ;
b43_phy_maskset ( dev , B43_NPHY_BPHY_CTL3 ,
~ B43_NPHY_BPHY_CTL3_SCALE ,
tmp < < B43_NPHY_BPHY_CTL3_SCALE_SHIFT ) ;
}
2008-01-18 01:09:25 +01:00
b43_phy_write ( dev , B43_NPHY_AFESEQ_TX2RX_PUD_20M , 0x20 ) ;
b43_phy_write ( dev , B43_NPHY_AFESEQ_TX2RX_PUD_40M , 0x20 ) ;
2011-09-04 23:23:53 +02:00
if ( sprom - > boardflags2_lo & B43_BFL2_SKWRKFEM_BRD | |
2011-05-18 02:06:42 +02:00
( dev - > dev - > board_vendor = = PCI_VENDOR_ID_APPLE & &
2013-03-28 22:25:38 +01:00
dev - > dev - > board_type = = BCMA_BOARD_TYPE_BCM943224M93 ) )
2010-01-15 13:27:29 +01:00
b43_phy_write ( dev , B43_NPHY_TXREALFD , 0xA0 ) ;
else
b43_phy_write ( dev , B43_NPHY_TXREALFD , 0xB8 ) ;
b43_phy_write ( dev , B43_NPHY_MIMO_CRSTXEXT , 0xC8 ) ;
b43_phy_write ( dev , B43_NPHY_PLOAD_CSENSE_EXTLEN , 0x50 ) ;
b43_phy_write ( dev , B43_NPHY_TXRIFS_FRDEL , 0x30 ) ;
2008-01-09 16:13:56 +01:00
2014-07-08 15:11:06 +02:00
if ( phy - > rev < 8 )
b43_nphy_update_mimo_config ( dev , nphy - > preamble_override ) ;
2010-01-17 13:03:55 +01:00
b43_nphy_update_txrx_chain ( dev ) ;
2008-01-18 01:09:25 +01:00
if ( phy - > rev < 2 ) {
b43_phy_write ( dev , B43_NPHY_DUP40_GFBL , 0xAA8 ) ;
b43_phy_write ( dev , B43_NPHY_DUP40_BL , 0x9A4 ) ;
}
2010-01-15 13:27:29 +01:00
tmp2 = b43_current_band ( dev - > wl ) ;
2011-09-04 23:18:22 +02:00
if ( b43_nphy_ipa ( dev ) ) {
2010-01-15 13:27:29 +01:00
b43_phy_set ( dev , B43_NPHY_PAPD_EN0 , 0x1 ) ;
b43_phy_maskset ( dev , B43_NPHY_EPS_TABLE_ADJ0 , 0x007F ,
nphy - > papd_epsilon_offset [ 0 ] < < 7 ) ;
b43_phy_set ( dev , B43_NPHY_PAPD_EN1 , 0x1 ) ;
b43_phy_maskset ( dev , B43_NPHY_EPS_TABLE_ADJ1 , 0x007F ,
nphy - > papd_epsilon_offset [ 1 ] < < 7 ) ;
2010-01-22 01:53:15 +01:00
b43_nphy_int_pa_set_tx_dig_filters ( dev ) ;
2010-01-15 13:27:29 +01:00
} else if ( phy - > rev > = 5 ) {
2010-01-22 01:53:15 +01:00
b43_nphy_ext_pa_set_tx_dig_filters ( dev ) ;
2010-01-15 13:27:29 +01:00
}
2008-01-18 01:09:25 +01:00
b43_nphy_workarounds ( dev ) ;
2010-01-15 13:27:29 +01:00
/* Reset CCA, in init code it differs a little from standard way */
2011-08-12 00:03:26 +02:00
b43_phy_force_clock ( dev , 1 ) ;
2010-01-15 13:27:29 +01:00
tmp = b43_phy_read ( dev , B43_NPHY_BBCFG ) ;
b43_phy_write ( dev , B43_NPHY_BBCFG , tmp | B43_NPHY_BBCFG_RSTCCA ) ;
b43_phy_write ( dev , B43_NPHY_BBCFG , tmp & ~ B43_NPHY_BBCFG_RSTCCA ) ;
2011-08-12 00:03:26 +02:00
b43_phy_force_clock ( dev , 0 ) ;
2010-01-15 13:27:29 +01:00
2011-05-10 16:05:33 +02:00
b43_mac_phy_clock_set ( dev , true ) ;
2010-01-15 13:27:29 +01:00
2014-07-08 15:11:06 +02:00
if ( phy - > rev < 7 ) {
b43_nphy_pa_override ( dev , false ) ;
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RX2TX ) ;
b43_nphy_force_rf_sequence ( dev , B43_RFSEQ_RESET2RX ) ;
b43_nphy_pa_override ( dev , true ) ;
}
2010-01-15 13:27:29 +01:00
2010-01-15 14:31:39 +01:00
b43_nphy_classifier ( dev , 0 , 0 ) ;
b43_nphy_read_clip_detection ( dev , clip ) ;
2010-11-18 13:28:00 +01:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
b43_nphy_bphy_init ( dev ) ;
2010-01-15 13:27:29 +01:00
tx_pwr_state = nphy - > txpwrctrl ;
2010-11-28 12:59:43 +01:00
b43_nphy_tx_power_ctrl ( dev , false ) ;
b43_nphy_tx_power_fix ( dev ) ;
2011-12-20 22:45:49 +01:00
b43_nphy_tx_power_ctl_idle_tssi ( dev ) ;
2012-01-02 19:31:22 +01:00
b43_nphy_tx_power_ctl_setup ( dev ) ;
2011-09-04 23:23:53 +02:00
b43_nphy_tx_gain_table_upload ( dev ) ;
2008-01-18 01:09:25 +01:00
2010-01-15 13:27:29 +01:00
if ( nphy - > phyrxchain ! = 3 )
2010-08-16 22:39:17 +02:00
b43_nphy_set_rx_core_state ( dev , nphy - > phyrxchain ) ;
2010-01-15 13:27:29 +01:00
if ( nphy - > mphase_cal_phase_id > 0 )
; /* TODO PHY Periodic Calibration Multi-Phase Restart */
do_rssi_cal = false ;
if ( phy - > rev > = 3 ) {
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
2010-10-14 19:33:34 +02:00
do_rssi_cal = ! nphy - > rssical_chanspec_2G . center_freq ;
2010-01-15 13:27:29 +01:00
else
2010-10-14 19:33:34 +02:00
do_rssi_cal = ! nphy - > rssical_chanspec_5G . center_freq ;
2010-01-15 13:27:29 +01:00
if ( do_rssi_cal )
2010-01-15 13:40:58 +01:00
b43_nphy_rssi_cal ( dev ) ;
2010-01-15 13:27:29 +01:00
else
2010-01-15 15:06:47 +01:00
b43_nphy_restore_rssi_cal ( dev ) ;
2010-01-15 13:27:29 +01:00
} else {
2010-01-15 13:40:58 +01:00
b43_nphy_rssi_cal ( dev ) ;
2010-01-15 13:27:29 +01:00
}
if ( ! ( ( nphy - > measure_hold & 0x6 ) ! = 0 ) ) {
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
2010-10-14 19:33:34 +02:00
do_cal = ! nphy - > iqcal_chanspec_2G . center_freq ;
2010-01-15 13:27:29 +01:00
else
2010-10-14 19:33:34 +02:00
do_cal = ! nphy - > iqcal_chanspec_5G . center_freq ;
2010-01-15 13:27:29 +01:00
if ( nphy - > mute )
do_cal = false ;
if ( do_cal ) {
2010-01-15 15:40:50 +01:00
target = b43_nphy_get_tx_gains ( dev ) ;
2010-01-15 13:27:29 +01:00
if ( nphy - > antsel_type = = 2 )
2010-02-27 13:03:33 +01:00
b43_nphy_superswitch_init ( dev , true ) ;
2010-01-15 13:27:29 +01:00
if ( nphy - > perical ! = 2 ) {
2010-01-15 14:48:21 +01:00
b43_nphy_rssi_cal ( dev ) ;
2010-01-15 13:27:29 +01:00
if ( phy - > rev > = 3 ) {
nphy - > cal_orig_pwr_idx [ 0 ] =
nphy - > txpwrindex [ 0 ] . index_internal ;
nphy - > cal_orig_pwr_idx [ 1 ] =
nphy - > txpwrindex [ 1 ] . index_internal ;
/* TODO N PHY Pre Calibrate TX Gain */
2010-01-15 15:40:50 +01:00
target = b43_nphy_get_tx_gains ( dev ) ;
2010-01-15 13:27:29 +01:00
}
2010-11-30 22:33:16 +01:00
if ( ! b43_nphy_cal_tx_iq_lo ( dev , target , true , false ) )
if ( b43_nphy_cal_rx_iq ( dev , target , 2 , 0 ) = = 0 )
b43_nphy_save_cal ( dev ) ;
} else if ( nphy - > mphase_cal_phase_id = = 0 )
; /* N PHY Periodic Calibration with arg 3 */
} else {
b43_nphy_restore_cal ( dev ) ;
2010-01-15 13:27:29 +01:00
}
}
2010-01-15 16:24:57 +01:00
b43_nphy_tx_pwr_ctrl_coef_setup ( dev ) ;
2010-11-28 12:59:43 +01:00
b43_nphy_tx_power_ctrl ( dev , tx_pwr_state ) ;
2010-01-15 13:27:29 +01:00
b43_phy_write ( dev , B43_NPHY_TXMACIF_HOLDOFF , 0x0015 ) ;
b43_phy_write ( dev , B43_NPHY_TXMACDELAY , 0x0320 ) ;
if ( phy - > rev > = 3 & & phy - > rev < = 6 )
2014-04-20 13:05:45 +02:00
b43_phy_write ( dev , B43_NPHY_PLOAD_CSENSE_EXTLEN , 0x0032 ) ;
2014-06-22 23:18:22 +02:00
b43_nphy_tx_lpf_bw ( dev ) ;
2010-02-04 12:23:12 +01:00
if ( phy - > rev > = 3 )
b43_nphy_spur_workaround ( dev ) ;
2008-01-18 01:09:25 +01:00
2008-01-13 21:23:44 +01:00
return 0 ;
2008-01-09 16:13:56 +01:00
}
2008-08-27 18:53:02 +02:00
2011-12-17 13:57:27 +01:00
/**************************************************
* Channel switching ops .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void b43_chantab_phy_upload ( struct b43_wldev * dev ,
const struct b43_phy_n_sfo_cfg * e )
{
b43_phy_write ( dev , B43_NPHY_BW1A , e - > phy_bw1a ) ;
b43_phy_write ( dev , B43_NPHY_BW2 , e - > phy_bw2 ) ;
b43_phy_write ( dev , B43_NPHY_BW3 , e - > phy_bw3 ) ;
b43_phy_write ( dev , B43_NPHY_BW4 , e - > phy_bw4 ) ;
b43_phy_write ( dev , B43_NPHY_BW5 , e - > phy_bw5 ) ;
b43_phy_write ( dev , B43_NPHY_BW6 , e - > phy_bw6 ) ;
}
2011-12-11 13:16:51 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
static void b43_nphy_pmu_spur_avoid ( struct b43_wldev * dev , bool avoid )
{
2011-12-15 14:17:21 +01:00
switch ( dev - > dev - > bus_type ) {
# ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA :
2013-04-12 17:08:58 +02:00
bcma_pmu_spuravoid_pllupdate ( & dev - > dev - > bdev - > bus - > drv_cc ,
avoid ) ;
2011-12-15 14:17:21 +01:00
break ;
2011-12-14 09:03:52 -05:00
# endif
2011-12-15 14:17:21 +01:00
# ifdef CONFIG_B43_SSB
case B43_BUS_SSB :
2013-04-02 15:57:26 +02:00
ssb_pmu_spuravoid_pllupdate ( & dev - > dev - > sdev - > bus - > chipco ,
avoid ) ;
2011-12-15 14:17:21 +01:00
break ;
# endif
}
2011-12-11 13:16:51 +01:00
}
2010-02-27 13:03:40 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
2010-10-11 03:11:01 +02:00
static void b43_nphy_channel_setup ( struct b43_wldev * dev ,
2010-03-29 00:53:13 +02:00
const struct b43_phy_n_sfo_cfg * e ,
2010-10-11 03:11:01 +02:00
struct ieee80211_channel * new_channel )
2010-02-27 13:03:40 +01:00
{
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = dev - > phy . n ;
2011-12-11 13:16:51 +01:00
int ch = new_channel - > hw_value ;
2014-04-05 18:08:25 +02:00
u16 tmp16 ;
2010-02-27 13:03:40 +01:00
2014-07-17 19:31:04 +02:00
if ( new_channel - > band = = IEEE80211_BAND_5GHZ ) {
2014-07-30 23:02:30 +02:00
/* Switch to 2 GHz for a moment to access B43_PHY_B_BBCFG */
b43_phy_mask ( dev , B43_NPHY_BANDCTL , ~ B43_NPHY_BANDCTL_5GHZ ) ;
2014-04-05 18:08:25 +02:00
tmp16 = b43_read16 ( dev , B43_MMIO_PSM_PHY_HDR ) ;
b43_write16 ( dev , B43_MMIO_PSM_PHY_HDR , tmp16 | 4 ) ;
2014-07-17 19:31:04 +02:00
/* Put BPHY in the reset */
b43_phy_set ( dev , B43_PHY_B_BBCFG ,
B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX ) ;
2014-04-05 18:08:25 +02:00
b43_write16 ( dev , B43_MMIO_PSM_PHY_HDR , tmp16 ) ;
2010-02-27 13:03:40 +01:00
b43_phy_set ( dev , B43_NPHY_BANDCTL , B43_NPHY_BANDCTL_5GHZ ) ;
2014-07-17 19:31:04 +02:00
} else if ( new_channel - > band = = IEEE80211_BAND_2GHZ ) {
2010-02-27 13:03:40 +01:00
b43_phy_mask ( dev , B43_NPHY_BANDCTL , ~ B43_NPHY_BANDCTL_5GHZ ) ;
2014-04-05 18:08:25 +02:00
tmp16 = b43_read16 ( dev , B43_MMIO_PSM_PHY_HDR ) ;
b43_write16 ( dev , B43_MMIO_PSM_PHY_HDR , tmp16 | 4 ) ;
2014-07-17 19:31:04 +02:00
/* Take BPHY out of the reset */
b43_phy_mask ( dev , B43_PHY_B_BBCFG ,
( u16 ) ~ ( B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX ) ) ;
2014-04-05 18:08:25 +02:00
b43_write16 ( dev , B43_MMIO_PSM_PHY_HDR , tmp16 ) ;
2010-02-27 13:03:40 +01:00
}
b43_chantab_phy_upload ( dev , e ) ;
2010-10-11 03:11:01 +02:00
if ( new_channel - > hw_value = = 14 ) {
2010-02-27 13:03:40 +01:00
b43_nphy_classifier ( dev , 2 , 0 ) ;
b43_phy_set ( dev , B43_PHY_B_TEST , 0x0800 ) ;
} else {
b43_nphy_classifier ( dev , 2 , 2 ) ;
2010-10-11 03:11:01 +02:00
if ( new_channel - > band = = IEEE80211_BAND_2GHZ )
2010-02-27 13:03:40 +01:00
b43_phy_mask ( dev , B43_PHY_B_TEST , ~ 0x840 ) ;
}
2010-11-28 12:59:43 +01:00
if ( ! nphy - > txpwrctrl )
2010-02-27 13:03:40 +01:00
b43_nphy_tx_power_fix ( dev ) ;
if ( dev - > phy . rev < 3 )
b43_nphy_adjust_lna_gain_table ( dev ) ;
2014-06-22 23:18:22 +02:00
b43_nphy_tx_lpf_bw ( dev ) ;
2010-02-27 13:03:40 +01:00
2011-12-11 13:16:51 +01:00
if ( dev - > phy . rev > = 3 & &
dev - > phy . n - > spur_avoid ! = B43_SPUR_AVOID_DISABLE ) {
2014-07-17 19:31:06 +02:00
u8 spuravoid = 0 ;
2011-12-11 13:16:51 +01:00
if ( dev - > phy . n - > spur_avoid = = B43_SPUR_AVOID_FORCE ) {
2014-07-17 19:31:06 +02:00
spuravoid = 1 ;
} else if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 18 ) {
/* TODO */
} else if ( phy - > rev > = 17 ) {
/* TODO: Off for channels 1-11, but check 12-14! */
} else if ( phy - > rev > = 16 ) {
/* TODO: Off for 2 GHz, but check 5 GHz! */
} else if ( phy - > rev > = 7 ) {
if ( ! b43_is_40mhz ( dev ) ) { /* 20MHz */
if ( ch = = 13 | | ch = = 14 | | ch = = 153 )
spuravoid = 1 ;
} else { /* 40 MHz */
if ( ch = = 54 )
spuravoid = 1 ;
}
} else {
if ( ! b43_is_40mhz ( dev ) ) { /* 20MHz */
if ( ( ch > = 5 & & ch < = 8 ) | | ch = = 13 | | ch = = 14 )
spuravoid = 1 ;
} else { /* 40MHz */
if ( nphy - > aband_spurwar_en & &
( ch = = 38 | | ch = = 102 | | ch = = 118 ) )
spuravoid = dev - > dev - > chip_id = = 0x4716 ;
}
2011-12-11 13:16:51 +01:00
}
2014-07-17 19:31:06 +02:00
b43_nphy_pmu_spur_avoid ( dev , spuravoid ) ;
2011-12-11 13:16:51 +01:00
2014-07-17 19:31:06 +02:00
b43_mac_switch_freq ( dev , spuravoid ) ;
2011-12-11 13:16:51 +01:00
if ( dev - > phy . rev = = 3 | | dev - > phy . rev = = 4 )
2014-09-12 18:37:26 +02:00
b43_wireless_core_phy_pll_reset ( dev ) ;
2011-12-11 13:16:51 +01:00
2014-07-17 19:31:06 +02:00
if ( spuravoid )
2011-12-11 13:16:51 +01:00
b43_phy_set ( dev , B43_NPHY_BBCFG , B43_NPHY_BBCFG_RSTRX ) ;
else
b43_phy_mask ( dev , B43_NPHY_BBCFG ,
~ B43_NPHY_BBCFG_RSTRX & 0xFFFF ) ;
b43_nphy_reset_cca ( dev ) ;
/* wl sets useless phy_isspuravoid here */
2010-02-27 13:03:40 +01:00
}
b43_phy_write ( dev , B43_NPHY_NDATAT_DUP40 , 0x3830 ) ;
if ( phy - > rev > = 3 )
b43_nphy_spur_workaround ( dev ) ;
}
2010-02-27 13:03:41 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
2010-10-11 03:11:01 +02:00
static int b43_nphy_set_channel ( struct b43_wldev * dev ,
struct ieee80211_channel * channel ,
enum nl80211_channel_type channel_type )
2010-02-27 13:03:41 +01:00
{
2010-10-11 03:11:01 +02:00
struct b43_phy * phy = & dev - > phy ;
2010-02-27 13:03:41 +01:00
2011-04-29 14:54:27 -04:00
const struct b43_nphy_channeltab_entry_rev2 * tabent_r2 = NULL ;
const struct b43_nphy_channeltab_entry_rev3 * tabent_r3 = NULL ;
2014-07-01 16:19:08 +02:00
const struct b43_nphy_chantabent_rev7 * tabent_r7 = NULL ;
const struct b43_nphy_chantabent_rev7_2g * tabent_r7_2g = NULL ;
2010-02-27 13:03:41 +01:00
u8 tmp ;
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
return - ESRCH ;
/* TODO */
} else if ( phy - > rev > = 7 ) {
2014-07-01 16:19:08 +02:00
r2057_get_chantabent_rev7 ( dev , channel - > center_freq ,
& tabent_r7 , & tabent_r7_2g ) ;
if ( ! tabent_r7 & & ! tabent_r7_2g )
return - ESRCH ;
} else if ( phy - > rev > = 3 ) {
2010-10-11 03:19:22 +02:00
tabent_r3 = b43_nphy_get_chantabent_rev3 ( dev ,
channel - > center_freq ) ;
2010-03-29 00:53:15 +02:00
if ( ! tabent_r3 )
return - ESRCH ;
2010-03-29 00:53:14 +02:00
} else {
2010-10-11 03:11:01 +02:00
tabent_r2 = b43_nphy_get_chantabent_rev2 ( dev ,
channel - > hw_value ) ;
2010-03-29 00:53:15 +02:00
if ( ! tabent_r2 )
2010-03-29 00:53:14 +02:00
return - ESRCH ;
2010-02-27 13:03:41 +01:00
}
2010-10-14 19:33:34 +02:00
/* Channel is set later in common code, but we need to set it on our
own to let this function ' s subcalls work properly . */
phy - > channel = channel - > hw_value ;
2010-02-27 13:03:41 +01:00
2014-05-31 20:49:41 +02:00
#if 0
2010-10-11 03:11:02 +02:00
if ( b43_channel_type_is_40mhz ( phy - > channel_type ) ! =
b43_channel_type_is_40mhz ( channel_type ) )
; /* TODO: BMAC BW Set (channel_type) */
2014-05-31 20:49:41 +02:00
# endif
2010-02-27 13:03:41 +01:00
2014-07-01 16:19:08 +02:00
if ( channel_type = = NL80211_CHAN_HT40PLUS ) {
b43_phy_set ( dev , B43_NPHY_RXCTL , B43_NPHY_RXCTL_BSELU20 ) ;
if ( phy - > rev > = 7 )
b43_phy_set ( dev , 0x310 , 0x8000 ) ;
} else if ( channel_type = = NL80211_CHAN_HT40MINUS ) {
b43_phy_mask ( dev , B43_NPHY_RXCTL , ~ B43_NPHY_RXCTL_BSELU20 ) ;
if ( phy - > rev > = 7 )
b43_phy_mask ( dev , 0x310 , ( u16 ) ~ 0x8000 ) ;
}
2010-02-27 13:03:41 +01:00
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 7 ) {
2014-07-01 16:19:08 +02:00
const struct b43_phy_n_sfo_cfg * phy_regs = tabent_r7 ?
& ( tabent_r7 - > phy_regs ) : & ( tabent_r7_2g - > phy_regs ) ;
if ( phy - > radio_rev < = 4 | | phy - > radio_rev = = 6 ) {
tmp = ( channel - > band = = IEEE80211_BAND_5GHZ ) ? 2 : 0 ;
b43_radio_maskset ( dev , R2057_TIA_CONFIG_CORE0 , ~ 2 , tmp ) ;
b43_radio_maskset ( dev , R2057_TIA_CONFIG_CORE1 , ~ 2 , tmp ) ;
}
b43_radio_2057_setup ( dev , tabent_r7 , tabent_r7_2g ) ;
b43_nphy_channel_setup ( dev , phy_regs , channel ) ;
} else if ( phy - > rev > = 3 ) {
2010-10-11 03:11:01 +02:00
tmp = ( channel - > band = = IEEE80211_BAND_5GHZ ) ? 4 : 0 ;
2010-02-27 13:03:41 +01:00
b43_radio_maskset ( dev , 0x08 , 0xFFFB , tmp ) ;
2010-12-21 23:57:48 +01:00
b43_radio_2056_setup ( dev , tabent_r3 ) ;
2010-10-11 03:11:01 +02:00
b43_nphy_channel_setup ( dev , & ( tabent_r3 - > phy_regs ) , channel ) ;
2010-02-27 13:03:41 +01:00
} else {
2010-10-11 03:11:01 +02:00
tmp = ( channel - > band = = IEEE80211_BAND_5GHZ ) ? 0x0020 : 0x0050 ;
2010-02-27 13:03:41 +01:00
b43_radio_maskset ( dev , B2055_MASTER1 , 0xFF8F , tmp ) ;
2010-03-29 00:53:15 +02:00
b43_radio_2055_setup ( dev , tabent_r2 ) ;
2010-10-11 03:11:01 +02:00
b43_nphy_channel_setup ( dev , & ( tabent_r2 - > phy_regs ) , channel ) ;
2010-02-27 13:03:41 +01:00
}
return 0 ;
}
2011-12-17 13:57:27 +01:00
/**************************************************
* Basic PHY ops .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-27 18:53:02 +02:00
static int b43_nphy_op_allocate ( struct b43_wldev * dev )
{
struct b43_phy_n * nphy ;
nphy = kzalloc ( sizeof ( * nphy ) , GFP_KERNEL ) ;
if ( ! nphy )
return - ENOMEM ;
2014-07-31 21:59:48 +02:00
2008-08-27 18:53:02 +02:00
dev - > phy . n = nphy ;
return 0 ;
}
2008-09-02 13:00:34 +02:00
static void b43_nphy_op_prepare_structs ( struct b43_wldev * dev )
2008-08-27 18:53:02 +02:00
{
2008-09-02 13:00:34 +02:00
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = phy - > n ;
2011-12-11 02:55:33 +01:00
struct ssb_sprom * sprom = dev - > dev - > bus_sprom ;
2008-08-27 18:53:02 +02:00
2008-09-02 13:00:34 +02:00
memset ( nphy , 0 , sizeof ( * nphy ) ) ;
2008-08-27 18:53:02 +02:00
2010-12-21 11:50:22 +01:00
nphy - > hang_avoid = ( phy - > rev = = 3 | | phy - > rev = = 4 ) ;
2011-12-11 02:55:33 +01:00
nphy - > spur_avoid = ( phy - > rev > = 3 ) ?
B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE ;
2010-11-18 21:11:43 +01:00
nphy - > gain_boost = true ; /* this way we follow wl, assume it is true */
nphy - > txrx_chain = 2 ; /* sth different than 0 and 1 for now */
nphy - > phyrxchain = 3 ; /* to avoid b43_nphy_set_rx_core_state like wl */
2010-11-28 12:59:44 +01:00
nphy - > perical = 2 ; /* avoid additional rssi cal on init (like wl) */
2011-09-01 22:49:57 +02:00
/* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
* 0x7f = = 127 and we check for 128 when restoring TX pwr ctl . */
nphy - > tx_pwr_idx [ 0 ] = 128 ;
nphy - > tx_pwr_idx [ 1 ] = 128 ;
2011-12-11 02:55:33 +01:00
/* Hardware TX power control and 5GHz power gain */
nphy - > txpwrctrl = false ;
nphy - > pwg_gain_5ghz = false ;
if ( dev - > phy . rev > = 3 | |
( dev - > dev - > board_vendor = = PCI_VENDOR_ID_APPLE & &
( dev - > dev - > core_rev = = 11 | | dev - > dev - > core_rev = = 12 ) ) ) {
nphy - > txpwrctrl = true ;
nphy - > pwg_gain_5ghz = true ;
} else if ( sprom - > revision > = 4 ) {
if ( dev - > phy . rev > = 2 & &
( sprom - > boardflags2_lo & B43_BFL2_TXPWRCTRL_EN ) ) {
nphy - > txpwrctrl = true ;
# ifdef CONFIG_B43_SSB
if ( dev - > dev - > bus_type = = B43_BUS_SSB & &
dev - > dev - > sdev - > bus - > bustype = = SSB_BUSTYPE_PCI ) {
struct pci_dev * pdev =
dev - > dev - > sdev - > bus - > host_pci ;
if ( pdev - > device = = 0x4328 | |
pdev - > device = = 0x432a )
nphy - > pwg_gain_5ghz = true ;
}
# endif
} else if ( sprom - > boardflags2_lo & B43_BFL2_5G_PWRGAIN ) {
nphy - > pwg_gain_5ghz = true ;
}
}
if ( dev - > phy . rev > = 3 ) {
nphy - > ipa2g_on = sprom - > fem . ghz2 . extpa_gain = = 2 ;
nphy - > ipa5g_on = sprom - > fem . ghz5 . extpa_gain = = 2 ;
}
2008-08-27 18:53:02 +02:00
}
2008-09-02 13:00:34 +02:00
static void b43_nphy_op_free ( struct b43_wldev * dev )
2008-08-27 18:53:02 +02:00
{
2008-09-02 13:00:34 +02:00
struct b43_phy * phy = & dev - > phy ;
struct b43_phy_n * nphy = phy - > n ;
2008-08-27 18:53:02 +02:00
kfree ( nphy ) ;
2008-09-02 13:00:34 +02:00
phy - > n = NULL ;
}
static int b43_nphy_op_init ( struct b43_wldev * dev )
{
return b43_phy_initn ( dev ) ;
2008-08-27 18:53:02 +02:00
}
static inline void check_phyreg ( struct b43_wldev * dev , u16 offset )
{
# if B43_DEBUG
if ( ( offset & B43_PHYROUTE ) = = B43_PHYROUTE_OFDM_GPHY ) {
/* OFDM registers are onnly available on A/G-PHYs */
b43err ( dev - > wl , " Invalid OFDM PHY access at "
" 0x%04X on N-PHY \n " , offset ) ;
dump_stack ( ) ;
}
if ( ( offset & B43_PHYROUTE ) = = B43_PHYROUTE_EXT_GPHY ) {
/* Ext-G registers are only available on G-PHYs */
b43err ( dev - > wl , " Invalid EXT-G PHY access at "
" 0x%04X on N-PHY \n " , offset ) ;
dump_stack ( ) ;
}
# endif /* B43_DEBUG */
}
2010-12-07 09:42:06 +01:00
static void b43_nphy_op_maskset ( struct b43_wldev * dev , u16 reg , u16 mask ,
u16 set )
{
check_phyreg ( dev , reg ) ;
2014-08-07 07:45:37 +02:00
b43_write16f ( dev , B43_MMIO_PHY_CONTROL , reg ) ;
2012-01-02 19:31:21 +01:00
b43_maskset16 ( dev , B43_MMIO_PHY_DATA , mask , set ) ;
2014-07-31 21:59:42 +02:00
dev - > phy . writes_counter = 1 ;
2010-12-07 09:42:06 +01:00
}
2008-08-27 18:53:02 +02:00
static u16 b43_nphy_op_radio_read ( struct b43_wldev * dev , u16 reg )
{
/* Register 1 is a 32-bit register. */
2014-07-08 15:11:04 +02:00
B43_WARN_ON ( dev - > phy . rev < 7 & & reg = = 1 ) ;
2014-04-20 13:05:46 +02:00
if ( dev - > phy . rev > = 7 )
reg | = 0x200 ; /* Radio 0x2057 */
else
reg | = 0x100 ;
2008-08-27 18:53:02 +02:00
2014-08-07 07:45:37 +02:00
b43_write16f ( dev , B43_MMIO_RADIO_CONTROL , reg ) ;
2008-08-27 18:53:02 +02:00
return b43_read16 ( dev , B43_MMIO_RADIO_DATA_LOW ) ;
}
static void b43_nphy_op_radio_write ( struct b43_wldev * dev , u16 reg , u16 value )
{
/* Register 1 is a 32-bit register. */
2014-07-08 15:11:04 +02:00
B43_WARN_ON ( dev - > phy . rev < 7 & & reg = = 1 ) ;
2008-08-27 18:53:02 +02:00
2014-08-07 07:45:37 +02:00
b43_write16f ( dev , B43_MMIO_RADIO_CONTROL , reg ) ;
2008-08-27 18:53:02 +02:00
b43_write16 ( dev , B43_MMIO_RADIO_DATA_LOW , value ) ;
}
2010-02-27 13:03:34 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
2008-08-27 18:53:02 +02:00
static void b43_nphy_op_software_rfkill ( struct b43_wldev * dev ,
2009-06-02 13:01:37 +02:00
bool blocked )
2010-02-27 13:03:34 +01:00
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2010-02-27 13:03:34 +01:00
if ( b43_read32 ( dev , B43_MMIO_MACCTL ) & B43_MACCTL_ENABLED )
b43err ( dev - > wl , " MAC not suspended \n " ) ;
if ( blocked ) {
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
2012-07-26 00:07:39 +02:00
/* TODO */
2014-07-08 15:11:07 +02:00
} else if ( phy - > rev > = 8 ) {
b43_phy_mask ( dev , B43_NPHY_RFCTL_CMD ,
~ B43_NPHY_RFCTL_CMD_CHIP0PU ) ;
2014-07-08 15:11:06 +02:00
} else if ( phy - > rev > = 7 ) {
2014-07-08 15:11:07 +02:00
/* Nothing needed */
2014-07-08 15:11:06 +02:00
} else if ( phy - > rev > = 3 ) {
2014-07-08 15:11:07 +02:00
b43_phy_mask ( dev , B43_NPHY_RFCTL_CMD ,
~ B43_NPHY_RFCTL_CMD_CHIP0PU ) ;
2010-02-27 13:03:34 +01:00
b43_radio_mask ( dev , 0x09 , ~ 0x2 ) ;
b43_radio_write ( dev , 0x204D , 0 ) ;
b43_radio_write ( dev , 0x2053 , 0 ) ;
b43_radio_write ( dev , 0x2058 , 0 ) ;
b43_radio_write ( dev , 0x205E , 0 ) ;
b43_radio_mask ( dev , 0x2062 , ~ 0xF0 ) ;
b43_radio_write ( dev , 0x2064 , 0 ) ;
b43_radio_write ( dev , 0x304D , 0 ) ;
b43_radio_write ( dev , 0x3053 , 0 ) ;
b43_radio_write ( dev , 0x3058 , 0 ) ;
b43_radio_write ( dev , 0x305E , 0 ) ;
b43_radio_mask ( dev , 0x3062 , ~ 0xF0 ) ;
b43_radio_write ( dev , 0x3064 , 0 ) ;
}
} else {
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 7 ) {
2014-05-27 22:07:33 +02:00
if ( ! dev - > phy . radio_on )
b43_radio_2057_init ( dev ) ;
2012-07-26 00:07:39 +02:00
b43_switch_channel ( dev , dev - > phy . channel ) ;
2014-07-08 15:11:06 +02:00
} else if ( phy - > rev > = 3 ) {
2014-05-27 22:07:33 +02:00
if ( ! dev - > phy . radio_on )
b43_radio_init2056 ( dev ) ;
2010-10-06 07:50:08 +02:00
b43_switch_channel ( dev , dev - > phy . channel ) ;
2010-02-27 13:03:34 +01:00
} else {
b43_radio_init2055 ( dev ) ;
}
}
2008-08-27 18:53:02 +02:00
}
2011-03-01 21:40:39 +01:00
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
2008-09-03 12:12:20 +02:00
static void b43_nphy_op_switch_analog ( struct b43_wldev * dev , bool on )
{
2014-07-08 15:11:06 +02:00
struct b43_phy * phy = & dev - > phy ;
2011-06-19 13:30:20 +02:00
u16 override = on ? 0x0 : 0x7FFF ;
u16 core = on ? 0xD : 0x00FD ;
2011-03-01 21:40:39 +01:00
2014-07-08 15:11:06 +02:00
if ( phy - > rev > = 19 ) {
/* TODO */
} else if ( phy - > rev > = 3 ) {
2011-06-19 13:30:20 +02:00
if ( on ) {
b43_phy_write ( dev , B43_NPHY_AFECTL_C1 , core ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER1 , override ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_C2 , core ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , override ) ;
} else {
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER1 , override ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_C1 , core ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , override ) ;
b43_phy_write ( dev , B43_NPHY_AFECTL_C2 , core ) ;
}
} else {
b43_phy_write ( dev , B43_NPHY_AFECTL_OVER , override ) ;
}
2008-09-03 12:12:20 +02:00
}
2008-08-27 18:53:02 +02:00
static int b43_nphy_op_switch_channel ( struct b43_wldev * dev ,
unsigned int new_channel )
{
2013-03-25 16:26:57 +01:00
struct ieee80211_channel * channel = dev - > wl - > hw - > conf . chandef . chan ;
enum nl80211_channel_type channel_type =
cfg80211_get_chandef_type ( & dev - > wl - > hw - > conf . chandef ) ;
2010-10-06 07:50:06 +02:00
2008-08-27 18:53:02 +02:00
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ ) {
if ( ( new_channel < 1 ) | | ( new_channel > 14 ) )
return - EINVAL ;
} else {
if ( new_channel > 200 )
return - EINVAL ;
}
2010-10-11 03:11:01 +02:00
return b43_nphy_set_channel ( dev , channel , channel_type ) ;
2008-08-27 18:53:02 +02:00
}
static unsigned int b43_nphy_op_get_default_chan ( struct b43_wldev * dev )
{
if ( b43_current_band ( dev - > wl ) = = IEEE80211_BAND_2GHZ )
return 1 ;
return 36 ;
}
const struct b43_phy_operations b43_phyops_n = {
. allocate = b43_nphy_op_allocate ,
2008-09-02 13:00:34 +02:00
. free = b43_nphy_op_free ,
. prepare_structs = b43_nphy_op_prepare_structs ,
2008-08-27 18:53:02 +02:00
. init = b43_nphy_op_init ,
2010-12-07 09:42:06 +01:00
. phy_maskset = b43_nphy_op_maskset ,
2008-08-27 18:53:02 +02:00
. radio_read = b43_nphy_op_radio_read ,
. radio_write = b43_nphy_op_radio_write ,
. software_rfkill = b43_nphy_op_software_rfkill ,
2008-09-03 12:12:20 +02:00
. switch_analog = b43_nphy_op_switch_analog ,
2008-08-27 18:53:02 +02:00
. switch_channel = b43_nphy_op_switch_channel ,
. get_default_chan = b43_nphy_op_get_default_chan ,
2008-08-28 19:33:40 +02:00
. recalc_txpower = b43_nphy_op_recalc_txpower ,
2008-08-27 18:53:02 +02:00
} ;