2007-09-26 03:46:54 +04:00
/*
Broadcom B43legacy wireless driver
Copyright ( c ) 2005 Martin Langer < martin - langer @ gmx . de > ,
2007-11-07 00:49:20 +03:00
Stefano Brivio < stefano . brivio @ polimi . it >
2011-07-04 22:50:05 +04:00
Michael Buesch < m @ bues . ch >
2007-09-26 03:46:54 +04:00
Danny van Dyk < kugelfang @ gentoo . org >
Andreas Jaggi < andreas . jaggi @ waterwave . ch >
Copyright ( c ) 2007 Larry Finger < Larry . Finger @ lwfinger . net >
Some parts of the code in this file are derived from the ipw2200
driver Copyright ( c ) 2003 - 2004 Intel Corporation .
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 .
*/
# include <linux/delay.h>
# include "b43legacy.h"
# include "main.h"
# include "phy.h"
# include "radio.h"
# include "ilt.h"
/* Table for b43legacy_radio_calibrationvalue() */
static const u16 rcc_table [ 16 ] = {
0x0002 , 0x0003 , 0x0001 , 0x000F ,
0x0006 , 0x0007 , 0x0005 , 0x000F ,
0x000A , 0x000B , 0x0009 , 0x000F ,
0x000E , 0x000F , 0x000D , 0x000F ,
} ;
/* Reverse the bits of a 4bit value.
* Example : 1101 is flipped 1011
*/
static u16 flip_4bit ( u16 value )
{
u16 flipped = 0x0000 ;
B43legacy_BUG_ON ( ! ( ( value & ~ 0x000F ) = = 0x0000 ) ) ;
flipped | = ( value & 0x0001 ) < < 3 ;
flipped | = ( value & 0x0002 ) < < 1 ;
flipped | = ( value & 0x0004 ) > > 1 ;
flipped | = ( value & 0x0008 ) > > 3 ;
return flipped ;
}
/* Get the freq, as it has to be written to the device. */
static inline
u16 channel2freq_bg ( u8 channel )
{
/* Frequencies are given as frequencies_bg[index] + 2.4GHz
* Starting with channel 1
*/
static const u16 frequencies_bg [ 14 ] = {
12 , 17 , 22 , 27 ,
32 , 37 , 42 , 47 ,
52 , 57 , 62 , 67 ,
72 , 84 ,
} ;
if ( unlikely ( channel < 1 | | channel > 14 ) ) {
printk ( KERN_INFO " b43legacy: Channel %d is out of range \n " ,
channel ) ;
dump_stack ( ) ;
return 2412 ;
}
return frequencies_bg [ channel - 1 ] ;
}
void b43legacy_radio_lock ( struct b43legacy_wldev * dev )
{
u32 status ;
2008-01-23 16:48:50 +03:00
status = b43legacy_read32 ( dev , B43legacy_MMIO_MACCTL ) ;
B43legacy_WARN_ON ( status & B43legacy_MACCTL_RADIOLOCK ) ;
status | = B43legacy_MACCTL_RADIOLOCK ;
b43legacy_write32 ( dev , B43legacy_MMIO_MACCTL , status ) ;
2007-09-26 03:46:54 +04:00
mmiowb ( ) ;
udelay ( 10 ) ;
}
void b43legacy_radio_unlock ( struct b43legacy_wldev * dev )
{
u32 status ;
b43legacy_read16 ( dev , B43legacy_MMIO_PHY_VER ) ; /* dummy read */
2008-01-23 16:48:50 +03:00
status = b43legacy_read32 ( dev , B43legacy_MMIO_MACCTL ) ;
B43legacy_WARN_ON ( ! ( status & B43legacy_MACCTL_RADIOLOCK ) ) ;
status & = ~ B43legacy_MACCTL_RADIOLOCK ;
b43legacy_write32 ( dev , B43legacy_MMIO_MACCTL , status ) ;
2007-09-26 03:46:54 +04:00
mmiowb ( ) ;
}
u16 b43legacy_radio_read16 ( struct b43legacy_wldev * dev , u16 offset )
{
struct b43legacy_phy * phy = & dev - > phy ;
switch ( phy - > type ) {
case B43legacy_PHYTYPE_B :
if ( phy - > radio_ver = = 0x2053 ) {
if ( offset < 0x70 )
offset + = 0x80 ;
else if ( offset < 0x80 )
offset + = 0x70 ;
} else if ( phy - > radio_ver = = 0x2050 )
offset | = 0x80 ;
else
B43legacy_WARN_ON ( 1 ) ;
break ;
case B43legacy_PHYTYPE_G :
offset | = 0x80 ;
break ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
b43legacy_write16 ( dev , B43legacy_MMIO_RADIO_CONTROL , offset ) ;
return b43legacy_read16 ( dev , B43legacy_MMIO_RADIO_DATA_LOW ) ;
}
void b43legacy_radio_write16 ( struct b43legacy_wldev * dev , u16 offset , u16 val )
{
b43legacy_write16 ( dev , B43legacy_MMIO_RADIO_CONTROL , offset ) ;
mmiowb ( ) ;
b43legacy_write16 ( dev , B43legacy_MMIO_RADIO_DATA_LOW , val ) ;
}
static void b43legacy_set_all_gains ( struct b43legacy_wldev * dev ,
s16 first , s16 second , s16 third )
{
struct b43legacy_phy * phy = & dev - > phy ;
u16 i ;
u16 start = 0x08 ;
u16 end = 0x18 ;
u16 offset = 0x0400 ;
u16 tmp ;
if ( phy - > rev < = 1 ) {
offset = 0x5000 ;
start = 0x10 ;
end = 0x20 ;
}
for ( i = 0 ; i < 4 ; i + + )
b43legacy_ilt_write ( dev , offset + i , first ) ;
for ( i = start ; i < end ; i + + )
b43legacy_ilt_write ( dev , offset + i , second ) ;
if ( third ! = - 1 ) {
tmp = ( ( u16 ) third < < 14 ) | ( ( u16 ) third < < 6 ) ;
b43legacy_phy_write ( dev , 0x04A0 ,
( b43legacy_phy_read ( dev , 0x04A0 ) & 0xBFBF )
| tmp ) ;
b43legacy_phy_write ( dev , 0x04A1 ,
( b43legacy_phy_read ( dev , 0x04A1 ) & 0xBFBF )
| tmp ) ;
b43legacy_phy_write ( dev , 0x04A2 ,
( b43legacy_phy_read ( dev , 0x04A2 ) & 0xBFBF )
| tmp ) ;
}
b43legacy_dummy_transmission ( dev ) ;
}
static void b43legacy_set_original_gains ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
u16 i ;
u16 tmp ;
u16 offset = 0x0400 ;
u16 start = 0x0008 ;
u16 end = 0x0018 ;
if ( phy - > rev < = 1 ) {
offset = 0x5000 ;
start = 0x0010 ;
end = 0x0020 ;
}
for ( i = 0 ; i < 4 ; i + + ) {
tmp = ( i & 0xFFFC ) ;
tmp | = ( i & 0x0001 ) < < 1 ;
tmp | = ( i & 0x0002 ) > > 1 ;
b43legacy_ilt_write ( dev , offset + i , tmp ) ;
}
for ( i = start ; i < end ; i + + )
b43legacy_ilt_write ( dev , offset + i , i - start ) ;
b43legacy_phy_write ( dev , 0x04A0 ,
( b43legacy_phy_read ( dev , 0x04A0 ) & 0xBFBF )
| 0x4040 ) ;
b43legacy_phy_write ( dev , 0x04A1 ,
( b43legacy_phy_read ( dev , 0x04A1 ) & 0xBFBF )
| 0x4040 ) ;
b43legacy_phy_write ( dev , 0x04A2 ,
( b43legacy_phy_read ( dev , 0x04A2 ) & 0xBFBF )
| 0x4000 ) ;
b43legacy_dummy_transmission ( dev ) ;
}
/* Synthetic PU workaround */
static void b43legacy_synth_pu_workaround ( struct b43legacy_wldev * dev ,
u8 channel )
{
struct b43legacy_phy * phy = & dev - > phy ;
might_sleep ( ) ;
if ( phy - > radio_ver ! = 0x2050 | | phy - > radio_rev > = 6 )
/* We do not need the workaround. */
return ;
if ( channel < = 10 )
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL ,
channel2freq_bg ( channel + 4 ) ) ;
else
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL ,
channel2freq_bg ( channel ) ) ;
msleep ( 1 ) ;
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL ,
channel2freq_bg ( channel ) ) ;
}
u8 b43legacy_radio_aci_detect ( struct b43legacy_wldev * dev , u8 channel )
{
struct b43legacy_phy * phy = & dev - > phy ;
u8 ret = 0 ;
u16 saved ;
u16 rssi ;
u16 temp ;
int i ;
int j = 0 ;
saved = b43legacy_phy_read ( dev , 0x0403 ) ;
b43legacy_radio_selectchannel ( dev , channel , 0 ) ;
b43legacy_phy_write ( dev , 0x0403 , ( saved & 0xFFF8 ) | 5 ) ;
if ( phy - > aci_hw_rssi )
rssi = b43legacy_phy_read ( dev , 0x048A ) & 0x3F ;
else
rssi = saved & 0x3F ;
/* clamp temp to signed 5bit */
if ( rssi > 32 )
rssi - = 64 ;
for ( i = 0 ; i < 100 ; i + + ) {
temp = ( b43legacy_phy_read ( dev , 0x047F ) > > 8 ) & 0x3F ;
if ( temp > 32 )
temp - = 64 ;
if ( temp < rssi )
j + + ;
if ( j > = 20 )
ret = 1 ;
}
b43legacy_phy_write ( dev , 0x0403 , saved ) ;
return ret ;
}
u8 b43legacy_radio_aci_scan ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
u8 ret [ 13 ] ;
unsigned int channel = phy - > channel ;
unsigned int i ;
unsigned int j ;
unsigned int start ;
unsigned int end ;
if ( ! ( ( phy - > type = = B43legacy_PHYTYPE_G ) & & ( phy - > rev > 0 ) ) )
return 0 ;
2008-01-09 22:15:31 +03:00
b43legacy_phy_lock ( dev ) ;
2007-09-26 03:46:54 +04:00
b43legacy_radio_lock ( dev ) ;
b43legacy_phy_write ( dev , 0x0802 ,
b43legacy_phy_read ( dev , 0x0802 ) & 0xFFFC ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
b43legacy_phy_read ( dev , B43legacy_PHY_G_CRS )
& 0x7FFF ) ;
b43legacy_set_all_gains ( dev , 3 , 8 , 1 ) ;
start = ( channel - 5 > 0 ) ? channel - 5 : 1 ;
end = ( channel + 5 < 14 ) ? channel + 5 : 13 ;
for ( i = start ; i < = end ; i + + ) {
if ( abs ( channel - i ) > 2 )
ret [ i - 1 ] = b43legacy_radio_aci_detect ( dev , i ) ;
}
b43legacy_radio_selectchannel ( dev , channel , 0 ) ;
b43legacy_phy_write ( dev , 0x0802 ,
( b43legacy_phy_read ( dev , 0x0802 ) & 0xFFFC )
| 0x0003 ) ;
b43legacy_phy_write ( dev , 0x0403 ,
b43legacy_phy_read ( dev , 0x0403 ) & 0xFFF8 ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
b43legacy_phy_read ( dev , B43legacy_PHY_G_CRS )
| 0x8000 ) ;
b43legacy_set_original_gains ( dev ) ;
for ( i = 0 ; i < 13 ; i + + ) {
if ( ! ret [ i ] )
continue ;
end = ( i + 5 < 13 ) ? i + 5 : 13 ;
for ( j = i ; j < end ; j + + )
ret [ j ] = 1 ;
}
b43legacy_radio_unlock ( dev ) ;
2008-01-09 22:15:31 +03:00
b43legacy_phy_unlock ( dev ) ;
2007-09-26 03:46:54 +04:00
return ret [ channel - 1 ] ;
}
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
void b43legacy_nrssi_hw_write ( struct b43legacy_wldev * dev , u16 offset , s16 val )
{
b43legacy_phy_write ( dev , B43legacy_PHY_NRSSILT_CTRL , offset ) ;
mmiowb ( ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_NRSSILT_DATA , ( u16 ) val ) ;
}
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
s16 b43legacy_nrssi_hw_read ( struct b43legacy_wldev * dev , u16 offset )
{
u16 val ;
b43legacy_phy_write ( dev , B43legacy_PHY_NRSSILT_CTRL , offset ) ;
val = b43legacy_phy_read ( dev , B43legacy_PHY_NRSSILT_DATA ) ;
return ( s16 ) val ;
}
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
void b43legacy_nrssi_hw_update ( struct b43legacy_wldev * dev , u16 val )
{
u16 i ;
s16 tmp ;
for ( i = 0 ; i < 64 ; i + + ) {
tmp = b43legacy_nrssi_hw_read ( dev , i ) ;
tmp - = val ;
2008-05-03 00:47:49 +04:00
tmp = clamp_val ( tmp , - 32 , 31 ) ;
2007-09-26 03:46:54 +04:00
b43legacy_nrssi_hw_write ( dev , i , tmp ) ;
}
}
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
void b43legacy_nrssi_mem_update ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
s16 i ;
s16 delta ;
s32 tmp ;
delta = 0x1F - phy - > nrssi [ 0 ] ;
for ( i = 0 ; i < 64 ; i + + ) {
tmp = ( i - delta ) * phy - > nrssislope ;
tmp / = 0x10000 ;
tmp + = 0x3A ;
2008-05-03 00:47:49 +04:00
tmp = clamp_val ( tmp , 0 , 0x3F ) ;
2007-09-26 03:46:54 +04:00
phy - > nrssi_lt [ i ] = tmp ;
}
}
static void b43legacy_calc_nrssi_offset ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
u16 backup [ 20 ] = { 0 } ;
s16 v47F ;
u16 i ;
u16 saved = 0xFFFF ;
backup [ 0 ] = b43legacy_phy_read ( dev , 0x0001 ) ;
backup [ 1 ] = b43legacy_phy_read ( dev , 0x0811 ) ;
backup [ 2 ] = b43legacy_phy_read ( dev , 0x0812 ) ;
backup [ 3 ] = b43legacy_phy_read ( dev , 0x0814 ) ;
backup [ 4 ] = b43legacy_phy_read ( dev , 0x0815 ) ;
backup [ 5 ] = b43legacy_phy_read ( dev , 0x005A ) ;
backup [ 6 ] = b43legacy_phy_read ( dev , 0x0059 ) ;
backup [ 7 ] = b43legacy_phy_read ( dev , 0x0058 ) ;
backup [ 8 ] = b43legacy_phy_read ( dev , 0x000A ) ;
backup [ 9 ] = b43legacy_phy_read ( dev , 0x0003 ) ;
backup [ 10 ] = b43legacy_radio_read16 ( dev , 0x007A ) ;
backup [ 11 ] = b43legacy_radio_read16 ( dev , 0x0043 ) ;
b43legacy_phy_write ( dev , 0x0429 ,
b43legacy_phy_read ( dev , 0x0429 ) & 0x7FFF ) ;
b43legacy_phy_write ( dev , 0x0001 ,
( b43legacy_phy_read ( dev , 0x0001 ) & 0x3FFF )
| 0x4000 ) ;
b43legacy_phy_write ( dev , 0x0811 ,
b43legacy_phy_read ( dev , 0x0811 ) | 0x000C ) ;
b43legacy_phy_write ( dev , 0x0812 ,
( b43legacy_phy_read ( dev , 0x0812 ) & 0xFFF3 )
| 0x0004 ) ;
b43legacy_phy_write ( dev , 0x0802 ,
b43legacy_phy_read ( dev , 0x0802 ) & ~ ( 0x1 | 0x2 ) ) ;
if ( phy - > rev > = 6 ) {
backup [ 12 ] = b43legacy_phy_read ( dev , 0x002E ) ;
backup [ 13 ] = b43legacy_phy_read ( dev , 0x002F ) ;
backup [ 14 ] = b43legacy_phy_read ( dev , 0x080F ) ;
backup [ 15 ] = b43legacy_phy_read ( dev , 0x0810 ) ;
backup [ 16 ] = b43legacy_phy_read ( dev , 0x0801 ) ;
backup [ 17 ] = b43legacy_phy_read ( dev , 0x0060 ) ;
backup [ 18 ] = b43legacy_phy_read ( dev , 0x0014 ) ;
backup [ 19 ] = b43legacy_phy_read ( dev , 0x0478 ) ;
b43legacy_phy_write ( dev , 0x002E , 0 ) ;
b43legacy_phy_write ( dev , 0x002F , 0 ) ;
b43legacy_phy_write ( dev , 0x080F , 0 ) ;
b43legacy_phy_write ( dev , 0x0810 , 0 ) ;
b43legacy_phy_write ( dev , 0x0478 ,
b43legacy_phy_read ( dev , 0x0478 ) | 0x0100 ) ;
b43legacy_phy_write ( dev , 0x0801 ,
b43legacy_phy_read ( dev , 0x0801 ) | 0x0040 ) ;
b43legacy_phy_write ( dev , 0x0060 ,
b43legacy_phy_read ( dev , 0x0060 ) | 0x0040 ) ;
b43legacy_phy_write ( dev , 0x0014 ,
b43legacy_phy_read ( dev , 0x0014 ) | 0x0200 ) ;
}
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A ) | 0x0070 ) ;
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A ) | 0x0080 ) ;
udelay ( 30 ) ;
v47F = ( s16 ) ( ( b43legacy_phy_read ( dev , 0x047F ) > > 8 ) & 0x003F ) ;
if ( v47F > = 0x20 )
v47F - = 0x40 ;
if ( v47F = = 31 ) {
for ( i = 7 ; i > = 4 ; i - - ) {
b43legacy_radio_write16 ( dev , 0x007B , i ) ;
udelay ( 20 ) ;
v47F = ( s16 ) ( ( b43legacy_phy_read ( dev , 0x047F ) > > 8 )
& 0x003F ) ;
if ( v47F > = 0x20 )
v47F - = 0x40 ;
if ( v47F < 31 & & saved = = 0xFFFF )
saved = i ;
}
if ( saved = = 0xFFFF )
saved = 4 ;
} else {
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A )
& 0x007F ) ;
b43legacy_phy_write ( dev , 0x0814 ,
b43legacy_phy_read ( dev , 0x0814 ) | 0x0001 ) ;
b43legacy_phy_write ( dev , 0x0815 ,
b43legacy_phy_read ( dev , 0x0815 ) & 0xFFFE ) ;
b43legacy_phy_write ( dev , 0x0811 ,
b43legacy_phy_read ( dev , 0x0811 ) | 0x000C ) ;
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_phy_read ( dev , 0x0812 ) | 0x000C ) ;
b43legacy_phy_write ( dev , 0x0811 ,
b43legacy_phy_read ( dev , 0x0811 ) | 0x0030 ) ;
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_phy_read ( dev , 0x0812 ) | 0x0030 ) ;
b43legacy_phy_write ( dev , 0x005A , 0x0480 ) ;
b43legacy_phy_write ( dev , 0x0059 , 0x0810 ) ;
b43legacy_phy_write ( dev , 0x0058 , 0x000D ) ;
if ( phy - > analog = = 0 )
b43legacy_phy_write ( dev , 0x0003 , 0x0122 ) ;
else
b43legacy_phy_write ( dev , 0x000A ,
b43legacy_phy_read ( dev , 0x000A )
| 0x2000 ) ;
b43legacy_phy_write ( dev , 0x0814 ,
b43legacy_phy_read ( dev , 0x0814 ) | 0x0004 ) ;
b43legacy_phy_write ( dev , 0x0815 ,
b43legacy_phy_read ( dev , 0x0815 ) & 0xFFFB ) ;
b43legacy_phy_write ( dev , 0x0003 ,
( b43legacy_phy_read ( dev , 0x0003 ) & 0xFF9F )
| 0x0040 ) ;
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A )
| 0x000F ) ;
b43legacy_set_all_gains ( dev , 3 , 0 , 1 ) ;
b43legacy_radio_write16 ( dev , 0x0043 ,
( b43legacy_radio_read16 ( dev , 0x0043 )
& 0x00F0 ) | 0x000F ) ;
udelay ( 30 ) ;
v47F = ( s16 ) ( ( b43legacy_phy_read ( dev , 0x047F ) > > 8 ) & 0x003F ) ;
if ( v47F > = 0x20 )
v47F - = 0x40 ;
if ( v47F = = - 32 ) {
for ( i = 0 ; i < 4 ; i + + ) {
b43legacy_radio_write16 ( dev , 0x007B , i ) ;
udelay ( 20 ) ;
v47F = ( s16 ) ( ( b43legacy_phy_read ( dev , 0x047F ) > >
8 ) & 0x003F ) ;
if ( v47F > = 0x20 )
v47F - = 0x40 ;
if ( v47F > - 31 & & saved = = 0xFFFF )
saved = i ;
}
if ( saved = = 0xFFFF )
saved = 3 ;
} else
saved = 0 ;
}
b43legacy_radio_write16 ( dev , 0x007B , saved ) ;
if ( phy - > rev > = 6 ) {
b43legacy_phy_write ( dev , 0x002E , backup [ 12 ] ) ;
b43legacy_phy_write ( dev , 0x002F , backup [ 13 ] ) ;
b43legacy_phy_write ( dev , 0x080F , backup [ 14 ] ) ;
b43legacy_phy_write ( dev , 0x0810 , backup [ 15 ] ) ;
}
b43legacy_phy_write ( dev , 0x0814 , backup [ 3 ] ) ;
b43legacy_phy_write ( dev , 0x0815 , backup [ 4 ] ) ;
b43legacy_phy_write ( dev , 0x005A , backup [ 5 ] ) ;
b43legacy_phy_write ( dev , 0x0059 , backup [ 6 ] ) ;
b43legacy_phy_write ( dev , 0x0058 , backup [ 7 ] ) ;
b43legacy_phy_write ( dev , 0x000A , backup [ 8 ] ) ;
b43legacy_phy_write ( dev , 0x0003 , backup [ 9 ] ) ;
b43legacy_radio_write16 ( dev , 0x0043 , backup [ 11 ] ) ;
b43legacy_radio_write16 ( dev , 0x007A , backup [ 10 ] ) ;
b43legacy_phy_write ( dev , 0x0802 ,
b43legacy_phy_read ( dev , 0x0802 ) | 0x1 | 0x2 ) ;
b43legacy_phy_write ( dev , 0x0429 ,
b43legacy_phy_read ( dev , 0x0429 ) | 0x8000 ) ;
b43legacy_set_original_gains ( dev ) ;
if ( phy - > rev > = 6 ) {
b43legacy_phy_write ( dev , 0x0801 , backup [ 16 ] ) ;
b43legacy_phy_write ( dev , 0x0060 , backup [ 17 ] ) ;
b43legacy_phy_write ( dev , 0x0014 , backup [ 18 ] ) ;
b43legacy_phy_write ( dev , 0x0478 , backup [ 19 ] ) ;
}
b43legacy_phy_write ( dev , 0x0001 , backup [ 0 ] ) ;
b43legacy_phy_write ( dev , 0x0812 , backup [ 2 ] ) ;
b43legacy_phy_write ( dev , 0x0811 , backup [ 1 ] ) ;
}
void b43legacy_calc_nrssi_slope ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
u16 backup [ 18 ] = { 0 } ;
u16 tmp ;
s16 nrssi0 ;
s16 nrssi1 ;
switch ( phy - > type ) {
case B43legacy_PHYTYPE_B :
backup [ 0 ] = b43legacy_radio_read16 ( dev , 0x007A ) ;
backup [ 1 ] = b43legacy_radio_read16 ( dev , 0x0052 ) ;
backup [ 2 ] = b43legacy_radio_read16 ( dev , 0x0043 ) ;
backup [ 3 ] = b43legacy_phy_read ( dev , 0x0030 ) ;
backup [ 4 ] = b43legacy_phy_read ( dev , 0x0026 ) ;
backup [ 5 ] = b43legacy_phy_read ( dev , 0x0015 ) ;
backup [ 6 ] = b43legacy_phy_read ( dev , 0x002A ) ;
backup [ 7 ] = b43legacy_phy_read ( dev , 0x0020 ) ;
backup [ 8 ] = b43legacy_phy_read ( dev , 0x005A ) ;
backup [ 9 ] = b43legacy_phy_read ( dev , 0x0059 ) ;
backup [ 10 ] = b43legacy_phy_read ( dev , 0x0058 ) ;
backup [ 11 ] = b43legacy_read16 ( dev , 0x03E2 ) ;
backup [ 12 ] = b43legacy_read16 ( dev , 0x03E6 ) ;
backup [ 13 ] = b43legacy_read16 ( dev , B43legacy_MMIO_CHANNEL_EXT ) ;
tmp = b43legacy_radio_read16 ( dev , 0x007A ) ;
tmp & = ( phy - > rev > = 5 ) ? 0x007F : 0x000F ;
b43legacy_radio_write16 ( dev , 0x007A , tmp ) ;
b43legacy_phy_write ( dev , 0x0030 , 0x00FF ) ;
b43legacy_write16 ( dev , 0x03EC , 0x7F7F ) ;
b43legacy_phy_write ( dev , 0x0026 , 0x0000 ) ;
b43legacy_phy_write ( dev , 0x0015 ,
b43legacy_phy_read ( dev , 0x0015 ) | 0x0020 ) ;
b43legacy_phy_write ( dev , 0x002A , 0x08A3 ) ;
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A )
| 0x0080 ) ;
nrssi0 = ( s16 ) b43legacy_phy_read ( dev , 0x0027 ) ;
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A )
& 0x007F ) ;
if ( phy - > analog > = 2 )
b43legacy_write16 ( dev , 0x03E6 , 0x0040 ) ;
else if ( phy - > analog = = 0 )
b43legacy_write16 ( dev , 0x03E6 , 0x0122 ) ;
else
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL_EXT ,
b43legacy_read16 ( dev ,
B43legacy_MMIO_CHANNEL_EXT ) & 0x2000 ) ;
b43legacy_phy_write ( dev , 0x0020 , 0x3F3F ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xF330 ) ;
b43legacy_radio_write16 ( dev , 0x005A , 0x0060 ) ;
b43legacy_radio_write16 ( dev , 0x0043 ,
b43legacy_radio_read16 ( dev , 0x0043 )
& 0x00F0 ) ;
b43legacy_phy_write ( dev , 0x005A , 0x0480 ) ;
b43legacy_phy_write ( dev , 0x0059 , 0x0810 ) ;
b43legacy_phy_write ( dev , 0x0058 , 0x000D ) ;
udelay ( 20 ) ;
nrssi1 = ( s16 ) b43legacy_phy_read ( dev , 0x0027 ) ;
b43legacy_phy_write ( dev , 0x0030 , backup [ 3 ] ) ;
b43legacy_radio_write16 ( dev , 0x007A , backup [ 0 ] ) ;
b43legacy_write16 ( dev , 0x03E2 , backup [ 11 ] ) ;
b43legacy_phy_write ( dev , 0x0026 , backup [ 4 ] ) ;
b43legacy_phy_write ( dev , 0x0015 , backup [ 5 ] ) ;
b43legacy_phy_write ( dev , 0x002A , backup [ 6 ] ) ;
b43legacy_synth_pu_workaround ( dev , phy - > channel ) ;
if ( phy - > analog ! = 0 )
b43legacy_write16 ( dev , 0x03F4 , backup [ 13 ] ) ;
b43legacy_phy_write ( dev , 0x0020 , backup [ 7 ] ) ;
b43legacy_phy_write ( dev , 0x005A , backup [ 8 ] ) ;
b43legacy_phy_write ( dev , 0x0059 , backup [ 9 ] ) ;
b43legacy_phy_write ( dev , 0x0058 , backup [ 10 ] ) ;
b43legacy_radio_write16 ( dev , 0x0052 , backup [ 1 ] ) ;
b43legacy_radio_write16 ( dev , 0x0043 , backup [ 2 ] ) ;
if ( nrssi0 = = nrssi1 )
phy - > nrssislope = 0x00010000 ;
else
phy - > nrssislope = 0x00400000 / ( nrssi0 - nrssi1 ) ;
if ( nrssi0 < = - 4 ) {
phy - > nrssi [ 0 ] = nrssi0 ;
phy - > nrssi [ 1 ] = nrssi1 ;
}
break ;
case B43legacy_PHYTYPE_G :
if ( phy - > radio_rev > = 9 )
return ;
if ( phy - > radio_rev = = 8 )
b43legacy_calc_nrssi_offset ( dev ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
b43legacy_phy_read ( dev , B43legacy_PHY_G_CRS )
& 0x7FFF ) ;
b43legacy_phy_write ( dev , 0x0802 ,
b43legacy_phy_read ( dev , 0x0802 ) & 0xFFFC ) ;
backup [ 7 ] = b43legacy_read16 ( dev , 0x03E2 ) ;
b43legacy_write16 ( dev , 0x03E2 ,
b43legacy_read16 ( dev , 0x03E2 ) | 0x8000 ) ;
backup [ 0 ] = b43legacy_radio_read16 ( dev , 0x007A ) ;
backup [ 1 ] = b43legacy_radio_read16 ( dev , 0x0052 ) ;
backup [ 2 ] = b43legacy_radio_read16 ( dev , 0x0043 ) ;
backup [ 3 ] = b43legacy_phy_read ( dev , 0x0015 ) ;
backup [ 4 ] = b43legacy_phy_read ( dev , 0x005A ) ;
backup [ 5 ] = b43legacy_phy_read ( dev , 0x0059 ) ;
backup [ 6 ] = b43legacy_phy_read ( dev , 0x0058 ) ;
backup [ 8 ] = b43legacy_read16 ( dev , 0x03E6 ) ;
backup [ 9 ] = b43legacy_read16 ( dev , B43legacy_MMIO_CHANNEL_EXT ) ;
if ( phy - > rev > = 3 ) {
backup [ 10 ] = b43legacy_phy_read ( dev , 0x002E ) ;
backup [ 11 ] = b43legacy_phy_read ( dev , 0x002F ) ;
backup [ 12 ] = b43legacy_phy_read ( dev , 0x080F ) ;
backup [ 13 ] = b43legacy_phy_read ( dev ,
B43legacy_PHY_G_LO_CONTROL ) ;
backup [ 14 ] = b43legacy_phy_read ( dev , 0x0801 ) ;
backup [ 15 ] = b43legacy_phy_read ( dev , 0x0060 ) ;
backup [ 16 ] = b43legacy_phy_read ( dev , 0x0014 ) ;
backup [ 17 ] = b43legacy_phy_read ( dev , 0x0478 ) ;
b43legacy_phy_write ( dev , 0x002E , 0 ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_LO_CONTROL , 0 ) ;
switch ( phy - > rev ) {
case 4 : case 6 : case 7 :
b43legacy_phy_write ( dev , 0x0478 ,
b43legacy_phy_read ( dev ,
0x0478 ) | 0x0100 ) ;
b43legacy_phy_write ( dev , 0x0801 ,
b43legacy_phy_read ( dev ,
0x0801 ) | 0x0040 ) ;
break ;
case 3 : case 5 :
b43legacy_phy_write ( dev , 0x0801 ,
b43legacy_phy_read ( dev ,
0x0801 ) & 0xFFBF ) ;
break ;
}
b43legacy_phy_write ( dev , 0x0060 ,
b43legacy_phy_read ( dev , 0x0060 )
| 0x0040 ) ;
b43legacy_phy_write ( dev , 0x0014 ,
b43legacy_phy_read ( dev , 0x0014 )
| 0x0200 ) ;
}
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A )
| 0x0070 ) ;
b43legacy_set_all_gains ( dev , 0 , 8 , 0 ) ;
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A )
& 0x00F7 ) ;
if ( phy - > rev > = 2 ) {
b43legacy_phy_write ( dev , 0x0811 ,
( b43legacy_phy_read ( dev , 0x0811 )
& 0xFFCF ) | 0x0030 ) ;
b43legacy_phy_write ( dev , 0x0812 ,
( b43legacy_phy_read ( dev , 0x0812 )
& 0xFFCF ) | 0x0010 ) ;
}
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A )
| 0x0080 ) ;
udelay ( 20 ) ;
nrssi0 = ( s16 ) ( ( b43legacy_phy_read ( dev , 0x047F ) > > 8 ) & 0x003F ) ;
if ( nrssi0 > = 0x0020 )
nrssi0 - = 0x0040 ;
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A )
& 0x007F ) ;
if ( phy - > analog > = 2 )
b43legacy_phy_write ( dev , 0x0003 ,
( b43legacy_phy_read ( dev , 0x0003 )
& 0xFF9F ) | 0x0040 ) ;
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL_EXT ,
b43legacy_read16 ( dev ,
B43legacy_MMIO_CHANNEL_EXT ) | 0x2000 ) ;
b43legacy_radio_write16 ( dev , 0x007A ,
b43legacy_radio_read16 ( dev , 0x007A )
| 0x000F ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xF330 ) ;
if ( phy - > rev > = 2 ) {
b43legacy_phy_write ( dev , 0x0812 ,
( b43legacy_phy_read ( dev , 0x0812 )
& 0xFFCF ) | 0x0020 ) ;
b43legacy_phy_write ( dev , 0x0811 ,
( b43legacy_phy_read ( dev , 0x0811 )
& 0xFFCF ) | 0x0020 ) ;
}
b43legacy_set_all_gains ( dev , 3 , 0 , 1 ) ;
if ( phy - > radio_rev = = 8 )
b43legacy_radio_write16 ( dev , 0x0043 , 0x001F ) ;
else {
tmp = b43legacy_radio_read16 ( dev , 0x0052 ) & 0xFF0F ;
b43legacy_radio_write16 ( dev , 0x0052 , tmp | 0x0060 ) ;
tmp = b43legacy_radio_read16 ( dev , 0x0043 ) & 0xFFF0 ;
b43legacy_radio_write16 ( dev , 0x0043 , tmp | 0x0009 ) ;
}
b43legacy_phy_write ( dev , 0x005A , 0x0480 ) ;
b43legacy_phy_write ( dev , 0x0059 , 0x0810 ) ;
b43legacy_phy_write ( dev , 0x0058 , 0x000D ) ;
udelay ( 20 ) ;
nrssi1 = ( s16 ) ( ( b43legacy_phy_read ( dev , 0x047F ) > > 8 ) & 0x003F ) ;
if ( nrssi1 > = 0x0020 )
nrssi1 - = 0x0040 ;
if ( nrssi0 = = nrssi1 )
phy - > nrssislope = 0x00010000 ;
else
phy - > nrssislope = 0x00400000 / ( nrssi0 - nrssi1 ) ;
if ( nrssi0 > = - 4 ) {
phy - > nrssi [ 0 ] = nrssi1 ;
phy - > nrssi [ 1 ] = nrssi0 ;
}
if ( phy - > rev > = 3 ) {
b43legacy_phy_write ( dev , 0x002E , backup [ 10 ] ) ;
b43legacy_phy_write ( dev , 0x002F , backup [ 11 ] ) ;
b43legacy_phy_write ( dev , 0x080F , backup [ 12 ] ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_LO_CONTROL ,
backup [ 13 ] ) ;
}
if ( phy - > rev > = 2 ) {
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_phy_read ( dev , 0x0812 )
& 0xFFCF ) ;
b43legacy_phy_write ( dev , 0x0811 ,
b43legacy_phy_read ( dev , 0x0811 )
& 0xFFCF ) ;
}
b43legacy_radio_write16 ( dev , 0x007A , backup [ 0 ] ) ;
b43legacy_radio_write16 ( dev , 0x0052 , backup [ 1 ] ) ;
b43legacy_radio_write16 ( dev , 0x0043 , backup [ 2 ] ) ;
b43legacy_write16 ( dev , 0x03E2 , backup [ 7 ] ) ;
b43legacy_write16 ( dev , 0x03E6 , backup [ 8 ] ) ;
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL_EXT , backup [ 9 ] ) ;
b43legacy_phy_write ( dev , 0x0015 , backup [ 3 ] ) ;
b43legacy_phy_write ( dev , 0x005A , backup [ 4 ] ) ;
b43legacy_phy_write ( dev , 0x0059 , backup [ 5 ] ) ;
b43legacy_phy_write ( dev , 0x0058 , backup [ 6 ] ) ;
b43legacy_synth_pu_workaround ( dev , phy - > channel ) ;
b43legacy_phy_write ( dev , 0x0802 ,
b43legacy_phy_read ( dev , 0x0802 ) | 0x0003 ) ;
b43legacy_set_original_gains ( dev ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
b43legacy_phy_read ( dev , B43legacy_PHY_G_CRS )
| 0x8000 ) ;
if ( phy - > rev > = 3 ) {
b43legacy_phy_write ( dev , 0x0801 , backup [ 14 ] ) ;
b43legacy_phy_write ( dev , 0x0060 , backup [ 15 ] ) ;
b43legacy_phy_write ( dev , 0x0014 , backup [ 16 ] ) ;
b43legacy_phy_write ( dev , 0x0478 , backup [ 17 ] ) ;
}
b43legacy_nrssi_mem_update ( dev ) ;
b43legacy_calc_nrssi_threshold ( dev ) ;
break ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
}
void b43legacy_calc_nrssi_threshold ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
s32 threshold ;
s32 a ;
s32 b ;
s16 tmp16 ;
u16 tmp_u16 ;
switch ( phy - > type ) {
case B43legacy_PHYTYPE_B : {
if ( phy - > radio_ver ! = 0x2050 )
return ;
2007-11-10 01:57:34 +03:00
if ( ! ( dev - > dev - > bus - > sprom . boardflags_lo &
2007-09-26 03:46:54 +04:00
B43legacy_BFL_RSSI ) )
return ;
if ( phy - > radio_rev > = 6 ) {
threshold = ( phy - > nrssi [ 1 ] - phy - > nrssi [ 0 ] ) * 32 ;
threshold + = 20 * ( phy - > nrssi [ 0 ] + 1 ) ;
threshold / = 40 ;
} else
threshold = phy - > nrssi [ 1 ] - 5 ;
2008-05-03 00:47:49 +04:00
threshold = clamp_val ( threshold , 0 , 0x3E ) ;
2007-09-26 03:46:54 +04:00
b43legacy_phy_read ( dev , 0x0020 ) ; /* dummy read */
b43legacy_phy_write ( dev , 0x0020 , ( ( ( u16 ) threshold ) < < 8 )
| 0x001C ) ;
if ( phy - > radio_rev > = 6 ) {
b43legacy_phy_write ( dev , 0x0087 , 0x0E0D ) ;
b43legacy_phy_write ( dev , 0x0086 , 0x0C0B ) ;
b43legacy_phy_write ( dev , 0x0085 , 0x0A09 ) ;
b43legacy_phy_write ( dev , 0x0084 , 0x0808 ) ;
b43legacy_phy_write ( dev , 0x0083 , 0x0808 ) ;
b43legacy_phy_write ( dev , 0x0082 , 0x0604 ) ;
b43legacy_phy_write ( dev , 0x0081 , 0x0302 ) ;
b43legacy_phy_write ( dev , 0x0080 , 0x0100 ) ;
}
break ;
}
case B43legacy_PHYTYPE_G :
if ( ! phy - > gmode | |
2007-11-10 01:57:34 +03:00
! ( dev - > dev - > bus - > sprom . boardflags_lo &
2007-09-26 03:46:54 +04:00
B43legacy_BFL_RSSI ) ) {
tmp16 = b43legacy_nrssi_hw_read ( dev , 0x20 ) ;
if ( tmp16 > = 0x20 )
tmp16 - = 0x40 ;
if ( tmp16 < 3 )
b43legacy_phy_write ( dev , 0x048A ,
( b43legacy_phy_read ( dev ,
0x048A ) & 0xF000 ) | 0x09EB ) ;
else
b43legacy_phy_write ( dev , 0x048A ,
( b43legacy_phy_read ( dev ,
0x048A ) & 0xF000 ) | 0x0AED ) ;
} else {
if ( phy - > interfmode = =
B43legacy_RADIO_INTERFMODE_NONWLAN ) {
a = 0xE ;
b = 0xA ;
} else if ( ! phy - > aci_wlan_automatic & &
phy - > aci_enable ) {
a = 0x13 ;
b = 0x12 ;
} else {
a = 0xE ;
b = 0x11 ;
}
a = a * ( phy - > nrssi [ 1 ] - phy - > nrssi [ 0 ] ) ;
a + = ( phy - > nrssi [ 0 ] < < 6 ) ;
if ( a < 32 )
a + = 31 ;
else
a + = 32 ;
a = a > > 6 ;
2008-05-03 00:47:49 +04:00
a = clamp_val ( a , - 31 , 31 ) ;
2007-09-26 03:46:54 +04:00
b = b * ( phy - > nrssi [ 1 ] - phy - > nrssi [ 0 ] ) ;
b + = ( phy - > nrssi [ 0 ] < < 6 ) ;
if ( b < 32 )
b + = 31 ;
else
b + = 32 ;
b = b > > 6 ;
2008-05-03 00:47:49 +04:00
b = clamp_val ( b , - 31 , 31 ) ;
2007-09-26 03:46:54 +04:00
tmp_u16 = b43legacy_phy_read ( dev , 0x048A ) & 0xF000 ;
tmp_u16 | = ( ( u32 ) b & 0x0000003F ) ;
tmp_u16 | = ( ( ( u32 ) a & 0x0000003F ) < < 6 ) ;
b43legacy_phy_write ( dev , 0x048A , tmp_u16 ) ;
}
break ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
}
/* Stack implementation to save/restore values from the
* interference mitigation code .
* It is save to restore values in random order .
*/
static void _stack_save ( u32 * _stackptr , size_t * stackidx ,
u8 id , u16 offset , u16 value )
{
u32 * stackptr = & ( _stackptr [ * stackidx ] ) ;
B43legacy_WARN_ON ( ! ( ( offset & 0xE000 ) = = 0x0000 ) ) ;
B43legacy_WARN_ON ( ! ( ( id & 0xF8 ) = = 0x00 ) ) ;
* stackptr = offset ;
* stackptr | = ( ( u32 ) id ) < < 13 ;
* stackptr | = ( ( u32 ) value ) < < 16 ;
( * stackidx ) + + ;
B43legacy_WARN_ON ( ! ( * stackidx < B43legacy_INTERFSTACK_SIZE ) ) ;
}
static u16 _stack_restore ( u32 * stackptr ,
u8 id , u16 offset )
{
size_t i ;
B43legacy_WARN_ON ( ! ( ( offset & 0xE000 ) = = 0x0000 ) ) ;
B43legacy_WARN_ON ( ! ( ( id & 0xF8 ) = = 0x00 ) ) ;
for ( i = 0 ; i < B43legacy_INTERFSTACK_SIZE ; i + + , stackptr + + ) {
if ( ( * stackptr & 0x00001FFF ) ! = offset )
continue ;
if ( ( ( * stackptr & 0x00007000 ) > > 13 ) ! = id )
continue ;
return ( ( * stackptr & 0xFFFF0000 ) > > 16 ) ;
}
B43legacy_BUG_ON ( 1 ) ;
return 0 ;
}
# define phy_stacksave(offset) \
do { \
_stack_save ( stack , & stackidx , 0x1 , ( offset ) , \
b43legacy_phy_read ( dev , ( offset ) ) ) ; \
} while ( 0 )
# define phy_stackrestore(offset) \
do { \
b43legacy_phy_write ( dev , ( offset ) , \
_stack_restore ( stack , 0x1 , \
( offset ) ) ) ; \
} while ( 0 )
# define radio_stacksave(offset) \
do { \
_stack_save ( stack , & stackidx , 0x2 , ( offset ) , \
b43legacy_radio_read16 ( dev , ( offset ) ) ) ; \
} while ( 0 )
# define radio_stackrestore(offset) \
do { \
b43legacy_radio_write16 ( dev , ( offset ) , \
_stack_restore ( stack , 0x2 , \
( offset ) ) ) ; \
} while ( 0 )
# define ilt_stacksave(offset) \
do { \
_stack_save ( stack , & stackidx , 0x3 , ( offset ) , \
b43legacy_ilt_read ( dev , ( offset ) ) ) ; \
} while ( 0 )
# define ilt_stackrestore(offset) \
do { \
b43legacy_ilt_write ( dev , ( offset ) , \
_stack_restore ( stack , 0x3 , \
( offset ) ) ) ; \
} while ( 0 )
static void
b43legacy_radio_interference_mitigation_enable ( struct b43legacy_wldev * dev ,
int mode )
{
struct b43legacy_phy * phy = & dev - > phy ;
u16 tmp ;
u16 flipped ;
u32 tmp32 ;
size_t stackidx = 0 ;
u32 * stack = phy - > interfstack ;
switch ( mode ) {
case B43legacy_RADIO_INTERFMODE_NONWLAN :
if ( phy - > rev ! = 1 ) {
b43legacy_phy_write ( dev , 0x042B ,
b43legacy_phy_read ( dev , 0x042B )
| 0x0800 ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
b43legacy_phy_read ( dev ,
B43legacy_PHY_G_CRS ) & ~ 0x4000 ) ;
break ;
}
radio_stacksave ( 0x0078 ) ;
tmp = ( b43legacy_radio_read16 ( dev , 0x0078 ) & 0x001E ) ;
flipped = flip_4bit ( tmp ) ;
if ( flipped < 10 & & flipped > = 8 )
flipped = 7 ;
else if ( flipped > = 10 )
flipped - = 3 ;
flipped = flip_4bit ( flipped ) ;
flipped = ( flipped < < 1 ) | 0x0020 ;
b43legacy_radio_write16 ( dev , 0x0078 , flipped ) ;
b43legacy_calc_nrssi_threshold ( dev ) ;
phy_stacksave ( 0x0406 ) ;
b43legacy_phy_write ( dev , 0x0406 , 0x7E28 ) ;
b43legacy_phy_write ( dev , 0x042B ,
b43legacy_phy_read ( dev , 0x042B ) | 0x0800 ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_RADIO_BITFIELD ,
b43legacy_phy_read ( dev ,
B43legacy_PHY_RADIO_BITFIELD ) | 0x1000 ) ;
phy_stacksave ( 0x04A0 ) ;
b43legacy_phy_write ( dev , 0x04A0 ,
( b43legacy_phy_read ( dev , 0x04A0 ) & 0xC0C0 )
| 0x0008 ) ;
phy_stacksave ( 0x04A1 ) ;
b43legacy_phy_write ( dev , 0x04A1 ,
( b43legacy_phy_read ( dev , 0x04A1 ) & 0xC0C0 )
| 0x0605 ) ;
phy_stacksave ( 0x04A2 ) ;
b43legacy_phy_write ( dev , 0x04A2 ,
( b43legacy_phy_read ( dev , 0x04A2 ) & 0xC0C0 )
| 0x0204 ) ;
phy_stacksave ( 0x04A8 ) ;
b43legacy_phy_write ( dev , 0x04A8 ,
( b43legacy_phy_read ( dev , 0x04A8 ) & 0xC0C0 )
| 0x0803 ) ;
phy_stacksave ( 0x04AB ) ;
b43legacy_phy_write ( dev , 0x04AB ,
( b43legacy_phy_read ( dev , 0x04AB ) & 0xC0C0 )
| 0x0605 ) ;
phy_stacksave ( 0x04A7 ) ;
b43legacy_phy_write ( dev , 0x04A7 , 0x0002 ) ;
phy_stacksave ( 0x04A3 ) ;
b43legacy_phy_write ( dev , 0x04A3 , 0x287A ) ;
phy_stacksave ( 0x04A9 ) ;
b43legacy_phy_write ( dev , 0x04A9 , 0x2027 ) ;
phy_stacksave ( 0x0493 ) ;
b43legacy_phy_write ( dev , 0x0493 , 0x32F5 ) ;
phy_stacksave ( 0x04AA ) ;
b43legacy_phy_write ( dev , 0x04AA , 0x2027 ) ;
phy_stacksave ( 0x04AC ) ;
b43legacy_phy_write ( dev , 0x04AC , 0x32F5 ) ;
break ;
case B43legacy_RADIO_INTERFMODE_MANUALWLAN :
if ( b43legacy_phy_read ( dev , 0x0033 ) & 0x0800 )
break ;
2011-12-19 17:56:45 +04:00
phy - > aci_enable = true ;
2007-09-26 03:46:54 +04:00
phy_stacksave ( B43legacy_PHY_RADIO_BITFIELD ) ;
phy_stacksave ( B43legacy_PHY_G_CRS ) ;
if ( phy - > rev < 2 )
phy_stacksave ( 0x0406 ) ;
else {
phy_stacksave ( 0x04C0 ) ;
phy_stacksave ( 0x04C1 ) ;
}
phy_stacksave ( 0x0033 ) ;
phy_stacksave ( 0x04A7 ) ;
phy_stacksave ( 0x04A3 ) ;
phy_stacksave ( 0x04A9 ) ;
phy_stacksave ( 0x04AA ) ;
phy_stacksave ( 0x04AC ) ;
phy_stacksave ( 0x0493 ) ;
phy_stacksave ( 0x04A1 ) ;
phy_stacksave ( 0x04A0 ) ;
phy_stacksave ( 0x04A2 ) ;
phy_stacksave ( 0x048A ) ;
phy_stacksave ( 0x04A8 ) ;
phy_stacksave ( 0x04AB ) ;
if ( phy - > rev = = 2 ) {
phy_stacksave ( 0x04AD ) ;
phy_stacksave ( 0x04AE ) ;
} else if ( phy - > rev > = 3 ) {
phy_stacksave ( 0x04AD ) ;
phy_stacksave ( 0x0415 ) ;
phy_stacksave ( 0x0416 ) ;
phy_stacksave ( 0x0417 ) ;
ilt_stacksave ( 0x1A00 + 0x2 ) ;
ilt_stacksave ( 0x1A00 + 0x3 ) ;
}
phy_stacksave ( 0x042B ) ;
phy_stacksave ( 0x048C ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_RADIO_BITFIELD ,
b43legacy_phy_read ( dev ,
B43legacy_PHY_RADIO_BITFIELD ) & ~ 0x1000 ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
( b43legacy_phy_read ( dev ,
B43legacy_PHY_G_CRS )
& 0xFFFC ) | 0x0002 ) ;
b43legacy_phy_write ( dev , 0x0033 , 0x0800 ) ;
b43legacy_phy_write ( dev , 0x04A3 , 0x2027 ) ;
b43legacy_phy_write ( dev , 0x04A9 , 0x1CA8 ) ;
b43legacy_phy_write ( dev , 0x0493 , 0x287A ) ;
b43legacy_phy_write ( dev , 0x04AA , 0x1CA8 ) ;
b43legacy_phy_write ( dev , 0x04AC , 0x287A ) ;
b43legacy_phy_write ( dev , 0x04A0 ,
( b43legacy_phy_read ( dev , 0x04A0 )
& 0xFFC0 ) | 0x001A ) ;
b43legacy_phy_write ( dev , 0x04A7 , 0x000D ) ;
if ( phy - > rev < 2 )
b43legacy_phy_write ( dev , 0x0406 , 0xFF0D ) ;
else if ( phy - > rev = = 2 ) {
b43legacy_phy_write ( dev , 0x04C0 , 0xFFFF ) ;
b43legacy_phy_write ( dev , 0x04C1 , 0x00A9 ) ;
} else {
b43legacy_phy_write ( dev , 0x04C0 , 0x00C1 ) ;
b43legacy_phy_write ( dev , 0x04C1 , 0x0059 ) ;
}
b43legacy_phy_write ( dev , 0x04A1 ,
( b43legacy_phy_read ( dev , 0x04A1 )
& 0xC0FF ) | 0x1800 ) ;
b43legacy_phy_write ( dev , 0x04A1 ,
( b43legacy_phy_read ( dev , 0x04A1 )
& 0xFFC0 ) | 0x0015 ) ;
b43legacy_phy_write ( dev , 0x04A8 ,
( b43legacy_phy_read ( dev , 0x04A8 )
& 0xCFFF ) | 0x1000 ) ;
b43legacy_phy_write ( dev , 0x04A8 ,
( b43legacy_phy_read ( dev , 0x04A8 )
& 0xF0FF ) | 0x0A00 ) ;
b43legacy_phy_write ( dev , 0x04AB ,
( b43legacy_phy_read ( dev , 0x04AB )
& 0xCFFF ) | 0x1000 ) ;
b43legacy_phy_write ( dev , 0x04AB ,
( b43legacy_phy_read ( dev , 0x04AB )
& 0xF0FF ) | 0x0800 ) ;
b43legacy_phy_write ( dev , 0x04AB ,
( b43legacy_phy_read ( dev , 0x04AB )
& 0xFFCF ) | 0x0010 ) ;
b43legacy_phy_write ( dev , 0x04AB ,
( b43legacy_phy_read ( dev , 0x04AB )
& 0xFFF0 ) | 0x0005 ) ;
b43legacy_phy_write ( dev , 0x04A8 ,
( b43legacy_phy_read ( dev , 0x04A8 )
& 0xFFCF ) | 0x0010 ) ;
b43legacy_phy_write ( dev , 0x04A8 ,
( b43legacy_phy_read ( dev , 0x04A8 )
& 0xFFF0 ) | 0x0006 ) ;
b43legacy_phy_write ( dev , 0x04A2 ,
( b43legacy_phy_read ( dev , 0x04A2 )
& 0xF0FF ) | 0x0800 ) ;
b43legacy_phy_write ( dev , 0x04A0 ,
( b43legacy_phy_read ( dev , 0x04A0 )
& 0xF0FF ) | 0x0500 ) ;
b43legacy_phy_write ( dev , 0x04A2 ,
( b43legacy_phy_read ( dev , 0x04A2 )
& 0xFFF0 ) | 0x000B ) ;
if ( phy - > rev > = 3 ) {
b43legacy_phy_write ( dev , 0x048A ,
b43legacy_phy_read ( dev , 0x048A )
& ~ 0x8000 ) ;
b43legacy_phy_write ( dev , 0x0415 ,
( b43legacy_phy_read ( dev , 0x0415 )
& 0x8000 ) | 0x36D8 ) ;
b43legacy_phy_write ( dev , 0x0416 ,
( b43legacy_phy_read ( dev , 0x0416 )
& 0x8000 ) | 0x36D8 ) ;
b43legacy_phy_write ( dev , 0x0417 ,
( b43legacy_phy_read ( dev , 0x0417 )
& 0xFE00 ) | 0x016D ) ;
} else {
b43legacy_phy_write ( dev , 0x048A ,
b43legacy_phy_read ( dev , 0x048A )
| 0x1000 ) ;
b43legacy_phy_write ( dev , 0x048A ,
( b43legacy_phy_read ( dev , 0x048A )
& 0x9FFF ) | 0x2000 ) ;
tmp32 = b43legacy_shm_read32 ( dev , B43legacy_SHM_SHARED ,
B43legacy_UCODEFLAGS_OFFSET ) ;
if ( ! ( tmp32 & 0x800 ) ) {
tmp32 | = 0x800 ;
b43legacy_shm_write32 ( dev , B43legacy_SHM_SHARED ,
B43legacy_UCODEFLAGS_OFFSET ,
tmp32 ) ;
}
}
if ( phy - > rev > = 2 )
b43legacy_phy_write ( dev , 0x042B ,
b43legacy_phy_read ( dev , 0x042B )
| 0x0800 ) ;
b43legacy_phy_write ( dev , 0x048C ,
( b43legacy_phy_read ( dev , 0x048C )
& 0xF0FF ) | 0x0200 ) ;
if ( phy - > rev = = 2 ) {
b43legacy_phy_write ( dev , 0x04AE ,
( b43legacy_phy_read ( dev , 0x04AE )
& 0xFF00 ) | 0x007F ) ;
b43legacy_phy_write ( dev , 0x04AD ,
( b43legacy_phy_read ( dev , 0x04AD )
& 0x00FF ) | 0x1300 ) ;
} else if ( phy - > rev > = 6 ) {
b43legacy_ilt_write ( dev , 0x1A00 + 0x3 , 0x007F ) ;
b43legacy_ilt_write ( dev , 0x1A00 + 0x2 , 0x007F ) ;
b43legacy_phy_write ( dev , 0x04AD ,
b43legacy_phy_read ( dev , 0x04AD )
& 0x00FF ) ;
}
b43legacy_calc_nrssi_slope ( dev ) ;
break ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
}
static void
b43legacy_radio_interference_mitigation_disable ( struct b43legacy_wldev * dev ,
int mode )
{
struct b43legacy_phy * phy = & dev - > phy ;
u32 tmp32 ;
u32 * stack = phy - > interfstack ;
switch ( mode ) {
case B43legacy_RADIO_INTERFMODE_NONWLAN :
if ( phy - > rev ! = 1 ) {
b43legacy_phy_write ( dev , 0x042B ,
b43legacy_phy_read ( dev , 0x042B )
& ~ 0x0800 ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
b43legacy_phy_read ( dev ,
B43legacy_PHY_G_CRS ) | 0x4000 ) ;
break ;
}
phy_stackrestore ( 0x0078 ) ;
b43legacy_calc_nrssi_threshold ( dev ) ;
phy_stackrestore ( 0x0406 ) ;
b43legacy_phy_write ( dev , 0x042B ,
b43legacy_phy_read ( dev , 0x042B ) & ~ 0x0800 ) ;
if ( ! dev - > bad_frames_preempt )
b43legacy_phy_write ( dev , B43legacy_PHY_RADIO_BITFIELD ,
b43legacy_phy_read ( dev ,
B43legacy_PHY_RADIO_BITFIELD )
& ~ ( 1 < < 11 ) ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
b43legacy_phy_read ( dev , B43legacy_PHY_G_CRS )
| 0x4000 ) ;
phy_stackrestore ( 0x04A0 ) ;
phy_stackrestore ( 0x04A1 ) ;
phy_stackrestore ( 0x04A2 ) ;
phy_stackrestore ( 0x04A8 ) ;
phy_stackrestore ( 0x04AB ) ;
phy_stackrestore ( 0x04A7 ) ;
phy_stackrestore ( 0x04A3 ) ;
phy_stackrestore ( 0x04A9 ) ;
phy_stackrestore ( 0x0493 ) ;
phy_stackrestore ( 0x04AA ) ;
phy_stackrestore ( 0x04AC ) ;
break ;
case B43legacy_RADIO_INTERFMODE_MANUALWLAN :
if ( ! ( b43legacy_phy_read ( dev , 0x0033 ) & 0x0800 ) )
break ;
2011-12-19 17:56:45 +04:00
phy - > aci_enable = false ;
2007-09-26 03:46:54 +04:00
phy_stackrestore ( B43legacy_PHY_RADIO_BITFIELD ) ;
phy_stackrestore ( B43legacy_PHY_G_CRS ) ;
phy_stackrestore ( 0x0033 ) ;
phy_stackrestore ( 0x04A3 ) ;
phy_stackrestore ( 0x04A9 ) ;
phy_stackrestore ( 0x0493 ) ;
phy_stackrestore ( 0x04AA ) ;
phy_stackrestore ( 0x04AC ) ;
phy_stackrestore ( 0x04A0 ) ;
phy_stackrestore ( 0x04A7 ) ;
if ( phy - > rev > = 2 ) {
phy_stackrestore ( 0x04C0 ) ;
phy_stackrestore ( 0x04C1 ) ;
} else
phy_stackrestore ( 0x0406 ) ;
phy_stackrestore ( 0x04A1 ) ;
phy_stackrestore ( 0x04AB ) ;
phy_stackrestore ( 0x04A8 ) ;
if ( phy - > rev = = 2 ) {
phy_stackrestore ( 0x04AD ) ;
phy_stackrestore ( 0x04AE ) ;
} else if ( phy - > rev > = 3 ) {
phy_stackrestore ( 0x04AD ) ;
phy_stackrestore ( 0x0415 ) ;
phy_stackrestore ( 0x0416 ) ;
phy_stackrestore ( 0x0417 ) ;
ilt_stackrestore ( 0x1A00 + 0x2 ) ;
ilt_stackrestore ( 0x1A00 + 0x3 ) ;
}
phy_stackrestore ( 0x04A2 ) ;
phy_stackrestore ( 0x04A8 ) ;
phy_stackrestore ( 0x042B ) ;
phy_stackrestore ( 0x048C ) ;
tmp32 = b43legacy_shm_read32 ( dev , B43legacy_SHM_SHARED ,
B43legacy_UCODEFLAGS_OFFSET ) ;
if ( tmp32 & 0x800 ) {
tmp32 & = ~ 0x800 ;
b43legacy_shm_write32 ( dev , B43legacy_SHM_SHARED ,
B43legacy_UCODEFLAGS_OFFSET ,
tmp32 ) ;
}
b43legacy_calc_nrssi_slope ( dev ) ;
break ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
}
# undef phy_stacksave
# undef phy_stackrestore
# undef radio_stacksave
# undef radio_stackrestore
# undef ilt_stacksave
# undef ilt_stackrestore
int b43legacy_radio_set_interference_mitigation ( struct b43legacy_wldev * dev ,
int mode )
{
struct b43legacy_phy * phy = & dev - > phy ;
int currentmode ;
if ( ( phy - > type ! = B43legacy_PHYTYPE_G ) | |
( phy - > rev = = 0 ) | | ( ! phy - > gmode ) )
return - ENODEV ;
2011-12-19 17:56:45 +04:00
phy - > aci_wlan_automatic = false ;
2007-09-26 03:46:54 +04:00
switch ( mode ) {
case B43legacy_RADIO_INTERFMODE_AUTOWLAN :
2011-12-19 17:56:45 +04:00
phy - > aci_wlan_automatic = true ;
2007-09-26 03:46:54 +04:00
if ( phy - > aci_enable )
mode = B43legacy_RADIO_INTERFMODE_MANUALWLAN ;
else
mode = B43legacy_RADIO_INTERFMODE_NONE ;
break ;
case B43legacy_RADIO_INTERFMODE_NONE :
case B43legacy_RADIO_INTERFMODE_NONWLAN :
case B43legacy_RADIO_INTERFMODE_MANUALWLAN :
break ;
default :
return - EINVAL ;
}
currentmode = phy - > interfmode ;
if ( currentmode = = mode )
return 0 ;
if ( currentmode ! = B43legacy_RADIO_INTERFMODE_NONE )
b43legacy_radio_interference_mitigation_disable ( dev ,
currentmode ) ;
if ( mode = = B43legacy_RADIO_INTERFMODE_NONE ) {
2011-12-19 17:56:45 +04:00
phy - > aci_enable = false ;
phy - > aci_hw_rssi = false ;
2007-09-26 03:46:54 +04:00
} else
b43legacy_radio_interference_mitigation_enable ( dev , mode ) ;
phy - > interfmode = mode ;
return 0 ;
}
u16 b43legacy_radio_calibrationvalue ( struct b43legacy_wldev * dev )
{
u16 reg ;
u16 index ;
u16 ret ;
reg = b43legacy_radio_read16 ( dev , 0x0060 ) ;
index = ( reg & 0x001E ) > > 1 ;
ret = rcc_table [ index ] < < 1 ;
ret | = ( reg & 0x0001 ) ;
ret | = 0x0020 ;
return ret ;
}
# define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0))
static u16 b43legacy_get_812_value ( struct b43legacy_wldev * dev , u8 lpd )
{
struct b43legacy_phy * phy = & dev - > phy ;
u16 loop_or = 0 ;
u16 adj_loopback_gain = phy - > loopback_gain [ 0 ] ;
u8 loop ;
u16 extern_lna_control ;
if ( ! phy - > gmode )
return 0 ;
if ( ! has_loopback_gain ( phy ) ) {
2007-11-10 01:57:34 +03:00
if ( phy - > rev < 7 | | ! ( dev - > dev - > bus - > sprom . boardflags_lo
2007-09-26 03:46:54 +04:00
& B43legacy_BFL_EXTLNA ) ) {
switch ( lpd ) {
case LPD ( 0 , 1 , 1 ) :
return 0x0FB2 ;
case LPD ( 0 , 0 , 1 ) :
return 0x00B2 ;
case LPD ( 1 , 0 , 1 ) :
return 0x30B2 ;
case LPD ( 1 , 0 , 0 ) :
return 0x30B3 ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
} else {
switch ( lpd ) {
case LPD ( 0 , 1 , 1 ) :
return 0x8FB2 ;
case LPD ( 0 , 0 , 1 ) :
return 0x80B2 ;
case LPD ( 1 , 0 , 1 ) :
return 0x20B2 ;
case LPD ( 1 , 0 , 0 ) :
return 0x20B3 ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
}
} else {
if ( phy - > radio_rev = = 8 )
adj_loopback_gain + = 0x003E ;
else
adj_loopback_gain + = 0x0026 ;
if ( adj_loopback_gain > = 0x46 ) {
adj_loopback_gain - = 0x46 ;
extern_lna_control = 0x3000 ;
} else if ( adj_loopback_gain > = 0x3A ) {
adj_loopback_gain - = 0x3A ;
extern_lna_control = 0x2000 ;
} else if ( adj_loopback_gain > = 0x2E ) {
adj_loopback_gain - = 0x2E ;
extern_lna_control = 0x1000 ;
} else {
adj_loopback_gain - = 0x10 ;
extern_lna_control = 0x0000 ;
}
for ( loop = 0 ; loop < 16 ; loop + + ) {
u16 tmp = adj_loopback_gain - 6 * loop ;
if ( tmp < 6 )
break ;
}
loop_or = ( loop < < 8 ) | extern_lna_control ;
2007-11-10 01:57:34 +03:00
if ( phy - > rev > = 7 & & dev - > dev - > bus - > sprom . boardflags_lo
2007-09-26 03:46:54 +04:00
& B43legacy_BFL_EXTLNA ) {
if ( extern_lna_control )
loop_or | = 0x8000 ;
switch ( lpd ) {
case LPD ( 0 , 1 , 1 ) :
return 0x8F92 ;
case LPD ( 0 , 0 , 1 ) :
return ( 0x8092 | loop_or ) ;
case LPD ( 1 , 0 , 1 ) :
return ( 0x2092 | loop_or ) ;
case LPD ( 1 , 0 , 0 ) :
return ( 0x2093 | loop_or ) ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
} else {
switch ( lpd ) {
case LPD ( 0 , 1 , 1 ) :
return 0x0F92 ;
case LPD ( 0 , 0 , 1 ) :
case LPD ( 1 , 0 , 1 ) :
return ( 0x0092 | loop_or ) ;
case LPD ( 1 , 0 , 0 ) :
return ( 0x0093 | loop_or ) ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
}
}
return 0 ;
}
u16 b43legacy_radio_init2050 ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
u16 backup [ 21 ] = { 0 } ;
u16 ret ;
u16 i ;
u16 j ;
u32 tmp1 = 0 ;
u32 tmp2 = 0 ;
backup [ 0 ] = b43legacy_radio_read16 ( dev , 0x0043 ) ;
backup [ 14 ] = b43legacy_radio_read16 ( dev , 0x0051 ) ;
backup [ 15 ] = b43legacy_radio_read16 ( dev , 0x0052 ) ;
backup [ 1 ] = b43legacy_phy_read ( dev , 0x0015 ) ;
backup [ 16 ] = b43legacy_phy_read ( dev , 0x005A ) ;
backup [ 17 ] = b43legacy_phy_read ( dev , 0x0059 ) ;
backup [ 18 ] = b43legacy_phy_read ( dev , 0x0058 ) ;
if ( phy - > type = = B43legacy_PHYTYPE_B ) {
backup [ 2 ] = b43legacy_phy_read ( dev , 0x0030 ) ;
backup [ 3 ] = b43legacy_read16 ( dev , 0x03EC ) ;
b43legacy_phy_write ( dev , 0x0030 , 0x00FF ) ;
b43legacy_write16 ( dev , 0x03EC , 0x3F3F ) ;
} else {
if ( phy - > gmode ) {
backup [ 4 ] = b43legacy_phy_read ( dev , 0x0811 ) ;
backup [ 5 ] = b43legacy_phy_read ( dev , 0x0812 ) ;
backup [ 6 ] = b43legacy_phy_read ( dev , 0x0814 ) ;
backup [ 7 ] = b43legacy_phy_read ( dev , 0x0815 ) ;
backup [ 8 ] = b43legacy_phy_read ( dev ,
B43legacy_PHY_G_CRS ) ;
backup [ 9 ] = b43legacy_phy_read ( dev , 0x0802 ) ;
b43legacy_phy_write ( dev , 0x0814 ,
( b43legacy_phy_read ( dev , 0x0814 )
| 0x0003 ) ) ;
b43legacy_phy_write ( dev , 0x0815 ,
( b43legacy_phy_read ( dev , 0x0815 )
& 0xFFFC ) ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
( b43legacy_phy_read ( dev ,
B43legacy_PHY_G_CRS ) & 0x7FFF ) ) ;
b43legacy_phy_write ( dev , 0x0802 ,
( b43legacy_phy_read ( dev , 0x0802 )
& 0xFFFC ) ) ;
if ( phy - > rev > 1 ) { /* loopback gain enabled */
backup [ 19 ] = b43legacy_phy_read ( dev , 0x080F ) ;
backup [ 20 ] = b43legacy_phy_read ( dev , 0x0810 ) ;
if ( phy - > rev > = 3 )
b43legacy_phy_write ( dev , 0x080F ,
0xC020 ) ;
else
b43legacy_phy_write ( dev , 0x080F ,
0x8020 ) ;
b43legacy_phy_write ( dev , 0x0810 , 0x0000 ) ;
}
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 0 , 1 , 1 ) ) ) ;
if ( phy - > rev < 7 | |
2007-11-10 01:57:34 +03:00
! ( dev - > dev - > bus - > sprom . boardflags_lo
2007-09-26 03:46:54 +04:00
& B43legacy_BFL_EXTLNA ) )
b43legacy_phy_write ( dev , 0x0811 , 0x01B3 ) ;
else
b43legacy_phy_write ( dev , 0x0811 , 0x09B3 ) ;
}
}
b43legacy_write16 ( dev , B43legacy_MMIO_PHY_RADIO ,
( b43legacy_read16 ( dev , B43legacy_MMIO_PHY_RADIO )
| 0x8000 ) ) ;
backup [ 10 ] = b43legacy_phy_read ( dev , 0x0035 ) ;
b43legacy_phy_write ( dev , 0x0035 ,
( b43legacy_phy_read ( dev , 0x0035 ) & 0xFF7F ) ) ;
backup [ 11 ] = b43legacy_read16 ( dev , 0x03E6 ) ;
backup [ 12 ] = b43legacy_read16 ( dev , B43legacy_MMIO_CHANNEL_EXT ) ;
/* Initialization */
if ( phy - > analog = = 0 )
b43legacy_write16 ( dev , 0x03E6 , 0x0122 ) ;
else {
if ( phy - > analog > = 2 )
b43legacy_phy_write ( dev , 0x0003 ,
( b43legacy_phy_read ( dev , 0x0003 )
& 0xFFBF ) | 0x0040 ) ;
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL_EXT ,
( b43legacy_read16 ( dev ,
B43legacy_MMIO_CHANNEL_EXT ) | 0x2000 ) ) ;
}
ret = b43legacy_radio_calibrationvalue ( dev ) ;
if ( phy - > type = = B43legacy_PHYTYPE_B )
b43legacy_radio_write16 ( dev , 0x0078 , 0x0026 ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 0 , 1 , 1 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xBFAF ) ;
b43legacy_phy_write ( dev , 0x002B , 0x1403 ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 0 , 0 , 1 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xBFA0 ) ;
b43legacy_radio_write16 ( dev , 0x0051 ,
( b43legacy_radio_read16 ( dev , 0x0051 )
| 0x0004 ) ) ;
if ( phy - > radio_rev = = 8 )
b43legacy_radio_write16 ( dev , 0x0043 , 0x001F ) ;
else {
b43legacy_radio_write16 ( dev , 0x0052 , 0x0000 ) ;
b43legacy_radio_write16 ( dev , 0x0043 ,
( b43legacy_radio_read16 ( dev , 0x0043 )
& 0xFFF0 ) | 0x0009 ) ;
}
b43legacy_phy_write ( dev , 0x0058 , 0x0000 ) ;
for ( i = 0 ; i < 16 ; i + + ) {
b43legacy_phy_write ( dev , 0x005A , 0x0480 ) ;
b43legacy_phy_write ( dev , 0x0059 , 0xC810 ) ;
b43legacy_phy_write ( dev , 0x0058 , 0x000D ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 1 , 0 , 1 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xAFB0 ) ;
udelay ( 10 ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 1 , 0 , 1 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xEFB0 ) ;
udelay ( 10 ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 1 , 0 , 0 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xFFF0 ) ;
udelay ( 20 ) ;
tmp1 + = b43legacy_phy_read ( dev , 0x002D ) ;
b43legacy_phy_write ( dev , 0x0058 , 0x0000 ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 1 , 0 , 1 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xAFB0 ) ;
}
tmp1 + + ;
tmp1 > > = 9 ;
udelay ( 10 ) ;
b43legacy_phy_write ( dev , 0x0058 , 0x0000 ) ;
for ( i = 0 ; i < 16 ; i + + ) {
b43legacy_radio_write16 ( dev , 0x0078 , ( flip_4bit ( i ) < < 1 )
| 0x0020 ) ;
backup [ 13 ] = b43legacy_radio_read16 ( dev , 0x0078 ) ;
udelay ( 10 ) ;
for ( j = 0 ; j < 16 ; j + + ) {
b43legacy_phy_write ( dev , 0x005A , 0x0D80 ) ;
b43legacy_phy_write ( dev , 0x0059 , 0xC810 ) ;
b43legacy_phy_write ( dev , 0x0058 , 0x000D ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 1 , 0 , 1 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xAFB0 ) ;
udelay ( 10 ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 1 , 0 , 1 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xEFB0 ) ;
udelay ( 10 ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 1 , 0 , 0 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xFFF0 ) ;
udelay ( 10 ) ;
tmp2 + = b43legacy_phy_read ( dev , 0x002D ) ;
b43legacy_phy_write ( dev , 0x0058 , 0x0000 ) ;
if ( phy - > gmode )
b43legacy_phy_write ( dev , 0x0812 ,
b43legacy_get_812_value ( dev ,
LPD ( 1 , 0 , 1 ) ) ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xAFB0 ) ;
}
tmp2 + + ;
tmp2 > > = 8 ;
if ( tmp1 < tmp2 )
break ;
}
/* Restore the registers */
b43legacy_phy_write ( dev , 0x0015 , backup [ 1 ] ) ;
b43legacy_radio_write16 ( dev , 0x0051 , backup [ 14 ] ) ;
b43legacy_radio_write16 ( dev , 0x0052 , backup [ 15 ] ) ;
b43legacy_radio_write16 ( dev , 0x0043 , backup [ 0 ] ) ;
b43legacy_phy_write ( dev , 0x005A , backup [ 16 ] ) ;
b43legacy_phy_write ( dev , 0x0059 , backup [ 17 ] ) ;
b43legacy_phy_write ( dev , 0x0058 , backup [ 18 ] ) ;
b43legacy_write16 ( dev , 0x03E6 , backup [ 11 ] ) ;
if ( phy - > analog ! = 0 )
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL_EXT , backup [ 12 ] ) ;
b43legacy_phy_write ( dev , 0x0035 , backup [ 10 ] ) ;
b43legacy_radio_selectchannel ( dev , phy - > channel , 1 ) ;
if ( phy - > type = = B43legacy_PHYTYPE_B ) {
b43legacy_phy_write ( dev , 0x0030 , backup [ 2 ] ) ;
b43legacy_write16 ( dev , 0x03EC , backup [ 3 ] ) ;
} else {
if ( phy - > gmode ) {
b43legacy_write16 ( dev , B43legacy_MMIO_PHY_RADIO ,
( b43legacy_read16 ( dev ,
B43legacy_MMIO_PHY_RADIO ) & 0x7FFF ) ) ;
b43legacy_phy_write ( dev , 0x0811 , backup [ 4 ] ) ;
b43legacy_phy_write ( dev , 0x0812 , backup [ 5 ] ) ;
b43legacy_phy_write ( dev , 0x0814 , backup [ 6 ] ) ;
b43legacy_phy_write ( dev , 0x0815 , backup [ 7 ] ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_G_CRS ,
backup [ 8 ] ) ;
b43legacy_phy_write ( dev , 0x0802 , backup [ 9 ] ) ;
if ( phy - > rev > 1 ) {
b43legacy_phy_write ( dev , 0x080F , backup [ 19 ] ) ;
b43legacy_phy_write ( dev , 0x0810 , backup [ 20 ] ) ;
}
}
}
if ( i > = 15 )
ret = backup [ 13 ] ;
return ret ;
}
static inline
u16 freq_r3A_value ( u16 frequency )
{
u16 value ;
if ( frequency < 5091 )
value = 0x0040 ;
else if ( frequency < 5321 )
value = 0x0000 ;
else if ( frequency < 5806 )
value = 0x0080 ;
else
value = 0x0040 ;
return value ;
}
void b43legacy_radio_set_tx_iq ( struct b43legacy_wldev * dev )
{
static const u8 data_high [ 5 ] = { 0x00 , 0x40 , 0x80 , 0x90 , 0xD0 } ;
static const u8 data_low [ 5 ] = { 0x00 , 0x01 , 0x05 , 0x06 , 0x0A } ;
u16 tmp = b43legacy_radio_read16 ( dev , 0x001E ) ;
int i ;
int j ;
for ( i = 0 ; i < 5 ; i + + ) {
for ( j = 0 ; j < 5 ; j + + ) {
if ( tmp = = ( data_high [ i ] | data_low [ j ] ) ) {
b43legacy_phy_write ( dev , 0x0069 , ( i - j ) < < 8 |
0x00C0 ) ;
return ;
}
}
}
}
int b43legacy_radio_selectchannel ( struct b43legacy_wldev * dev ,
u8 channel ,
int synthetic_pu_workaround )
{
struct b43legacy_phy * phy = & dev - > phy ;
2007-09-21 06:11:02 +04:00
if ( channel = = 0xFF ) {
switch ( phy - > type ) {
case B43legacy_PHYTYPE_B :
case B43legacy_PHYTYPE_G :
channel = B43legacy_RADIO_DEFAULT_CHANNEL_BG ;
break ;
default :
B43legacy_WARN_ON ( 1 ) ;
}
}
2007-09-26 03:46:54 +04:00
/* TODO: Check if channel is valid - return -EINVAL if not */
if ( synthetic_pu_workaround )
b43legacy_synth_pu_workaround ( dev , channel ) ;
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL ,
channel2freq_bg ( channel ) ) ;
if ( channel = = 14 ) {
2007-11-10 01:57:34 +03:00
if ( dev - > dev - > bus - > sprom . country_code = = 5 ) /* JAPAN) */
2007-09-26 03:46:54 +04:00
b43legacy_shm_write32 ( dev , B43legacy_SHM_SHARED ,
B43legacy_UCODEFLAGS_OFFSET ,
b43legacy_shm_read32 ( dev ,
B43legacy_SHM_SHARED ,
B43legacy_UCODEFLAGS_OFFSET )
& ~ ( 1 < < 7 ) ) ;
else
b43legacy_shm_write32 ( dev , B43legacy_SHM_SHARED ,
B43legacy_UCODEFLAGS_OFFSET ,
b43legacy_shm_read32 ( dev ,
B43legacy_SHM_SHARED ,
B43legacy_UCODEFLAGS_OFFSET )
| ( 1 < < 7 ) ) ;
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL_EXT ,
b43legacy_read16 ( dev ,
B43legacy_MMIO_CHANNEL_EXT ) | ( 1 < < 11 ) ) ;
} else
b43legacy_write16 ( dev , B43legacy_MMIO_CHANNEL_EXT ,
b43legacy_read16 ( dev ,
B43legacy_MMIO_CHANNEL_EXT ) & 0xF7BF ) ;
phy - > channel = channel ;
/*XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
* that 2000 usecs might suffice . */
msleep ( 8 ) ;
return 0 ;
}
void b43legacy_radio_set_txantenna ( struct b43legacy_wldev * dev , u32 val )
{
u16 tmp ;
val < < = 8 ;
tmp = b43legacy_shm_read16 ( dev , B43legacy_SHM_SHARED , 0x0022 ) & 0xFCFF ;
b43legacy_shm_write16 ( dev , B43legacy_SHM_SHARED , 0x0022 , tmp | val ) ;
tmp = b43legacy_shm_read16 ( dev , B43legacy_SHM_SHARED , 0x03A8 ) & 0xFCFF ;
b43legacy_shm_write16 ( dev , B43legacy_SHM_SHARED , 0x03A8 , tmp | val ) ;
tmp = b43legacy_shm_read16 ( dev , B43legacy_SHM_SHARED , 0x0054 ) & 0xFCFF ;
b43legacy_shm_write16 ( dev , B43legacy_SHM_SHARED , 0x0054 , tmp | val ) ;
}
/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
static u16 b43legacy_get_txgain_base_band ( u16 txpower )
{
u16 ret ;
B43legacy_WARN_ON ( txpower > 63 ) ;
if ( txpower > = 54 )
ret = 2 ;
else if ( txpower > = 49 )
ret = 4 ;
else if ( txpower > = 44 )
ret = 5 ;
else
ret = 6 ;
return ret ;
}
/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
static u16 b43legacy_get_txgain_freq_power_amp ( u16 txpower )
{
u16 ret ;
B43legacy_WARN_ON ( txpower > 63 ) ;
if ( txpower > = 32 )
ret = 0 ;
else if ( txpower > = 25 )
ret = 1 ;
else if ( txpower > = 20 )
ret = 2 ;
else if ( txpower > = 12 )
ret = 3 ;
else
ret = 4 ;
return ret ;
}
/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
static u16 b43legacy_get_txgain_dac ( u16 txpower )
{
u16 ret ;
B43legacy_WARN_ON ( txpower > 63 ) ;
if ( txpower > = 54 )
ret = txpower - 53 ;
else if ( txpower > = 49 )
ret = txpower - 42 ;
else if ( txpower > = 44 )
ret = txpower - 37 ;
else if ( txpower > = 32 )
ret = txpower - 32 ;
else if ( txpower > = 25 )
ret = txpower - 20 ;
else if ( txpower > = 20 )
ret = txpower - 13 ;
else if ( txpower > = 12 )
ret = txpower - 8 ;
else
ret = txpower ;
return ret ;
}
void b43legacy_radio_set_txpower_a ( struct b43legacy_wldev * dev , u16 txpower )
{
struct b43legacy_phy * phy = & dev - > phy ;
u16 pamp ;
u16 base ;
u16 dac ;
u16 ilt ;
2008-05-03 00:47:49 +04:00
txpower = clamp_val ( txpower , 0 , 63 ) ;
2007-09-26 03:46:54 +04:00
pamp = b43legacy_get_txgain_freq_power_amp ( txpower ) ;
pamp < < = 5 ;
pamp & = 0x00E0 ;
b43legacy_phy_write ( dev , 0x0019 , pamp ) ;
base = b43legacy_get_txgain_base_band ( txpower ) ;
base & = 0x000F ;
b43legacy_phy_write ( dev , 0x0017 , base | 0x0020 ) ;
ilt = b43legacy_ilt_read ( dev , 0x3001 ) ;
ilt & = 0x0007 ;
dac = b43legacy_get_txgain_dac ( txpower ) ;
dac < < = 3 ;
dac | = ilt ;
b43legacy_ilt_write ( dev , 0x3001 , dac ) ;
phy - > txpwr_offset = txpower ;
/* TODO: FuncPlaceholder (Adjust BB loft cancel) */
}
void b43legacy_radio_set_txpower_bg ( struct b43legacy_wldev * dev ,
u16 baseband_attenuation ,
u16 radio_attenuation ,
u16 txpower )
{
struct b43legacy_phy * phy = & dev - > phy ;
if ( baseband_attenuation = = 0xFFFF )
baseband_attenuation = phy - > bbatt ;
if ( radio_attenuation = = 0xFFFF )
radio_attenuation = phy - > rfatt ;
if ( txpower = = 0xFFFF )
txpower = phy - > txctl1 ;
phy - > bbatt = baseband_attenuation ;
phy - > rfatt = radio_attenuation ;
phy - > txctl1 = txpower ;
B43legacy_WARN_ON ( baseband_attenuation > 11 ) ;
if ( phy - > radio_rev < 6 )
B43legacy_WARN_ON ( radio_attenuation > 9 ) ;
else
B43legacy_WARN_ON ( radio_attenuation > 31 ) ;
B43legacy_WARN_ON ( txpower > 7 ) ;
b43legacy_phy_set_baseband_attenuation ( dev , baseband_attenuation ) ;
b43legacy_radio_write16 ( dev , 0x0043 , radio_attenuation ) ;
b43legacy_shm_write16 ( dev , B43legacy_SHM_SHARED , 0x0064 ,
radio_attenuation ) ;
if ( phy - > radio_ver = = 0x2050 )
b43legacy_radio_write16 ( dev , 0x0052 ,
( b43legacy_radio_read16 ( dev , 0x0052 )
& ~ 0x0070 ) | ( ( txpower < < 4 ) & 0x0070 ) ) ;
/* FIXME: The spec is very weird and unclear here. */
if ( phy - > type = = B43legacy_PHYTYPE_G )
b43legacy_phy_lo_adjust ( dev , 0 ) ;
}
u16 b43legacy_default_baseband_attenuation ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
if ( phy - > radio_ver = = 0x2050 & & phy - > radio_rev < 6 )
return 0 ;
return 2 ;
}
u16 b43legacy_default_radio_attenuation ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
u16 att = 0xFFFF ;
switch ( phy - > radio_ver ) {
case 0x2053 :
switch ( phy - > radio_rev ) {
case 1 :
att = 6 ;
break ;
}
break ;
case 0x2050 :
switch ( phy - > radio_rev ) {
case 0 :
att = 5 ;
break ;
case 1 :
if ( phy - > type = = B43legacy_PHYTYPE_G ) {
if ( is_bcm_board_vendor ( dev ) & &
dev - > dev - > bus - > boardinfo . type = = 0x421 & &
2012-04-29 04:04:06 +04:00
dev - > dev - > bus - > sprom . board_rev > = 30 )
2007-09-26 03:46:54 +04:00
att = 3 ;
else if ( is_bcm_board_vendor ( dev ) & &
dev - > dev - > bus - > boardinfo . type = = 0x416 )
att = 3 ;
else
att = 1 ;
} else {
if ( is_bcm_board_vendor ( dev ) & &
dev - > dev - > bus - > boardinfo . type = = 0x421 & &
2012-04-29 04:04:06 +04:00
dev - > dev - > bus - > sprom . board_rev > = 30 )
2007-09-26 03:46:54 +04:00
att = 7 ;
else
att = 6 ;
}
break ;
case 2 :
if ( phy - > type = = B43legacy_PHYTYPE_G ) {
if ( is_bcm_board_vendor ( dev ) & &
dev - > dev - > bus - > boardinfo . type = = 0x421 & &
2012-04-29 04:04:06 +04:00
dev - > dev - > bus - > sprom . board_rev > = 30 )
2007-09-26 03:46:54 +04:00
att = 3 ;
else if ( is_bcm_board_vendor ( dev ) & &
dev - > dev - > bus - > boardinfo . type = =
0x416 )
att = 5 ;
else if ( dev - > dev - > bus - > chip_id = = 0x4320 )
att = 4 ;
else
att = 3 ;
} else
att = 6 ;
break ;
case 3 :
att = 5 ;
break ;
case 4 :
case 5 :
att = 1 ;
break ;
case 6 :
case 7 :
att = 5 ;
break ;
case 8 :
att = 0x1A ;
break ;
case 9 :
default :
att = 5 ;
}
}
if ( is_bcm_board_vendor ( dev ) & &
dev - > dev - > bus - > boardinfo . type = = 0x421 ) {
2012-04-29 04:04:06 +04:00
if ( dev - > dev - > bus - > sprom . board_rev < 0x43 )
2007-09-26 03:46:54 +04:00
att = 2 ;
2012-04-29 04:04:06 +04:00
else if ( dev - > dev - > bus - > sprom . board_rev < 0x51 )
2007-09-26 03:46:54 +04:00
att = 3 ;
}
if ( att = = 0xFFFF )
att = 5 ;
return att ;
}
u16 b43legacy_default_txctl1 ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
if ( phy - > radio_ver ! = 0x2050 )
return 0 ;
if ( phy - > radio_rev = = 1 )
return 3 ;
if ( phy - > radio_rev < 6 )
return 2 ;
if ( phy - > radio_rev = = 8 )
return 1 ;
return 0 ;
}
void b43legacy_radio_turn_on ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
int err ;
2007-09-21 06:11:02 +04:00
u8 channel ;
2007-09-26 03:46:54 +04:00
might_sleep ( ) ;
if ( phy - > radio_on )
return ;
switch ( phy - > type ) {
case B43legacy_PHYTYPE_B :
case B43legacy_PHYTYPE_G :
b43legacy_phy_write ( dev , 0x0015 , 0x8000 ) ;
b43legacy_phy_write ( dev , 0x0015 , 0xCC00 ) ;
b43legacy_phy_write ( dev , 0x0015 ,
( phy - > gmode ? 0x00C0 : 0x0000 ) ) ;
2007-09-21 06:11:02 +04:00
if ( phy - > radio_off_context . valid ) {
/* Restore the RFover values. */
b43legacy_phy_write ( dev , B43legacy_PHY_RFOVER ,
phy - > radio_off_context . rfover ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_RFOVERVAL ,
phy - > radio_off_context . rfoverval ) ;
2011-12-19 17:56:45 +04:00
phy - > radio_off_context . valid = false ;
2007-09-21 06:11:02 +04:00
}
channel = phy - > channel ;
2007-09-26 03:46:54 +04:00
err = b43legacy_radio_selectchannel ( dev ,
B43legacy_RADIO_DEFAULT_CHANNEL_BG , 1 ) ;
2007-09-21 06:11:02 +04:00
err | = b43legacy_radio_selectchannel ( dev , channel , 0 ) ;
B43legacy_WARN_ON ( err ) ;
2007-09-26 03:46:54 +04:00
break ;
default :
B43legacy_BUG_ON ( 1 ) ;
}
2011-12-19 17:56:45 +04:00
phy - > radio_on = true ;
2007-09-26 03:46:54 +04:00
}
2007-10-11 07:44:22 +04:00
void b43legacy_radio_turn_off ( struct b43legacy_wldev * dev , bool force )
2007-09-26 03:46:54 +04:00
{
struct b43legacy_phy * phy = & dev - > phy ;
2007-10-11 07:44:22 +04:00
if ( ! phy - > radio_on & & ! force )
return ;
2007-09-26 03:46:54 +04:00
if ( phy - > type = = B43legacy_PHYTYPE_G & & dev - > dev - > id . revision > = 5 ) {
2007-09-21 06:11:02 +04:00
u16 rfover , rfoverval ;
rfover = b43legacy_phy_read ( dev , B43legacy_PHY_RFOVER ) ;
rfoverval = b43legacy_phy_read ( dev , B43legacy_PHY_RFOVERVAL ) ;
2007-10-11 07:44:22 +04:00
if ( ! force ) {
phy - > radio_off_context . rfover = rfover ;
phy - > radio_off_context . rfoverval = rfoverval ;
2011-12-19 17:56:45 +04:00
phy - > radio_off_context . valid = true ;
2007-10-11 07:44:22 +04:00
}
2007-09-21 06:11:02 +04:00
b43legacy_phy_write ( dev , B43legacy_PHY_RFOVER , rfover | 0x008C ) ;
b43legacy_phy_write ( dev , B43legacy_PHY_RFOVERVAL ,
rfoverval & 0xFF73 ) ;
2007-09-26 03:46:54 +04:00
} else
b43legacy_phy_write ( dev , 0x0015 , 0xAA00 ) ;
2011-12-19 17:56:45 +04:00
phy - > radio_on = false ;
2007-09-21 05:10:07 +04:00
b43legacydbg ( dev - > wl , " Radio initialized \n " ) ;
2007-09-26 03:46:54 +04:00
}
void b43legacy_radio_clear_tssi ( struct b43legacy_wldev * dev )
{
struct b43legacy_phy * phy = & dev - > phy ;
switch ( phy - > type ) {
case B43legacy_PHYTYPE_B :
case B43legacy_PHYTYPE_G :
b43legacy_shm_write16 ( dev , B43legacy_SHM_SHARED , 0x0058 ,
0x7F7F ) ;
b43legacy_shm_write16 ( dev , B43legacy_SHM_SHARED , 0x005a ,
0x7F7F ) ;
b43legacy_shm_write16 ( dev , B43legacy_SHM_SHARED , 0x0070 ,
0x7F7F ) ;
b43legacy_shm_write16 ( dev , B43legacy_SHM_SHARED , 0x0072 ,
0x7F7F ) ;
break ;
}
}