diff options
Diffstat (limited to 'drivers/staging/rtl8187se/r8180_max2820.c')
-rw-r--r-- | drivers/staging/rtl8187se/r8180_max2820.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/drivers/staging/rtl8187se/r8180_max2820.c b/drivers/staging/rtl8187se/r8180_max2820.c new file mode 100644 index 00000000000..cea08463d5e --- /dev/null +++ b/drivers/staging/rtl8187se/r8180_max2820.c @@ -0,0 +1,240 @@ +/* + This files contains MAXIM MAX2820 radio frontend programming routines. + + This is part of rtl8180 OpenSource driver + Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it> + Released under the terms of GPL (General Public Licence) + + Parts of this driver are based on the GPL part of the + official realtek driver + + Parts of this driver are based on the rtl8180 driver skeleton + from Patric Schenke & Andres Salomon + + Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. + + NetBSD rtl8180 driver from Dave Young has been really useful to + understand how to program the MAXIM radio. Thanks a lot!!! + + 'The Deuce' tested this and fixed some bugs. + + Code from rtl8181 project has been useful to me to understand some things. + + We want to tanks the Authors of such projects and the Ndiswrapper + project Authors. +*/ + + +#include "r8180.h" +#include "r8180_hw.h" +#include "r8180_max2820.h" + + +//#define DEBUG_MAXIM + +u32 maxim_chan[] = { + 0, //dummy channel 0 + 12, //1 + 17, //2 + 22, //3 + 27, //4 + 32, //5 + 37, //6 + 42, //7 + 47, //8 + 52, //9 + 57, //10 + 62, //11 + 67, //12 + 72, //13 + 84, //14 +}; + +#if 0 +/* maxim expects 4 bit address MSF, then 12 bit data MSF*/ +void write_maxim(struct net_device *dev,u8 adr, u32 data) +{ + + int shift; + short bit; + u16 word; + + adr = adr &0xf; + word = (u16)data & 0xfff; + word |= (adr<<12); + /*write_nic_dword(dev,PHY_CONFIG,BB_HOST_BANG | BB_HOST_BANG_EN); + read_nic_dword(dev,PHY_CONFIG); + mdelay(1); + + write_nic_dword(dev,PHY_CONFIG,BB_HOST_BANG | BB_HOST_BANG_EN | BB_HOST_BANG_CLK); + read_nic_dword(dev,PHY_CONFIG); + mdelay(1); + */ + + /* MAX2820 will sample data on rising edge of clock */ + for(shift = 15;shift >=0; shift--){ + bit = word>>shift & 1; + + write_nic_dword(dev,PHY_CONFIG,BB_HOST_BANG | (bit<<BB_HOST_BANG_DATA)); + + read_nic_dword(dev,PHY_CONFIG); + mdelay(2); + + write_nic_dword(dev,PHY_CONFIG,BB_HOST_BANG | + (bit<<BB_HOST_BANG_DATA) | BB_HOST_BANG_CLK); /* sample data */ + + read_nic_dword(dev,PHY_CONFIG); + mdelay(1); + + write_nic_dword(dev,PHY_CONFIG,BB_HOST_BANG | + (bit<<BB_HOST_BANG_DATA)); + + read_nic_dword(dev,PHY_CONFIG); + mdelay(2); + + } + write_nic_dword(dev,PHY_CONFIG,BB_HOST_BANG | (bit<<BB_HOST_BANG_DATA)| + BB_HOST_BANG_EN); + read_nic_dword(dev,PHY_CONFIG); + mdelay(2); + + /* The shift register fill flush to the requested register the + * last 12 bits data shifted in + */ + write_nic_dword(dev,PHY_CONFIG,BB_HOST_BANG | (bit<<BB_HOST_BANG_DATA)| + BB_HOST_BANG_EN | BB_HOST_BANG_CLK); + read_nic_dword(dev,PHY_CONFIG); + mdelay(2); + + write_nic_dword(dev,PHY_CONFIG,BB_HOST_BANG | (bit<<BB_HOST_BANG_DATA)| + BB_HOST_BANG_EN); + read_nic_dword(dev,PHY_CONFIG); + mdelay(2); + + +#ifdef DEBUG_MAXIM + DMESG("Writing maxim: %x (adr %x)",phy_config,adr); +#endif + +} +#endif + +void write_maxim(struct net_device *dev,u8 adr, u32 data) { + u32 temp; + temp = 0x90 + (data & 0xf); + temp <<= 16; + temp += adr; + temp <<= 8; + temp += (data >> 4) & 0xff; +#ifdef DEBUG_MAXIM + DMESG("write_maxim: %08x", temp); +#endif + write_nic_dword(dev, PHY_CONFIG, temp); + force_pci_posting(dev); + mdelay(1); +} + + +void maxim_write_phy_antenna(struct net_device *dev,short ch) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + u8 ant; + + ant = MAXIM_ANTENNA; + if(priv->antb) /*default antenna is antenna B */ + ant |= BB_ANTENNA_B; + if(ch == 14) + ant |= BB_ANTATTEN_CHAN14; + write_phy(dev,0x10,ant); + //DMESG("BB antenna %x ",ant); +} + + +void maxim_rf_set_chan(struct net_device *dev, short ch) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + u32 txpw = 0xff & priv->chtxpwr[ch]; + u32 chan = maxim_chan[ch]; + + /*While philips SA2400 drive the PA bias + *seems that for MAXIM we delegate this + *to the BB + */ + + //write_maxim(dev,5,txpw); + write_phy(dev,3,txpw); + + maxim_write_phy_antenna(dev,ch); + write_maxim(dev,3,chan); +} + + +void maxim_rf_close(struct net_device *dev) +{ + write_phy(dev, 3, 0x8); + write_maxim(dev, 1, 0); +} + + +void maxim_rf_init(struct net_device *dev) +{ + struct r8180_priv *priv = ieee80211_priv(dev); + u32 anaparam; + + write_nic_byte(dev,PHY_DELAY,0x6); //this is general + write_nic_byte(dev,CARRIER_SENSE_COUNTER,0x4c); //this is general + + /*these are maxim specific*/ + anaparam = read_nic_dword(dev,ANAPARAM); + anaparam = anaparam &~ (ANAPARAM_TXDACOFF_SHIFT); + anaparam = anaparam &~ANAPARAM_PWR1_MASK; + anaparam = anaparam &~ANAPARAM_PWR0_MASK; + anaparam |= (MAXIM_ANAPARAM_PWR1_ON<<ANAPARAM_PWR1_SHIFT); + anaparam |= (MAXIM_ANAPARAM_PWR0_ON<<ANAPARAM_PWR0_SHIFT); + + //rtl8180_set_anaparam(dev,anaparam); + + /* MAXIM from netbsd driver */ + + write_maxim(dev,0, 7); /* test mode as indicated in datasheet*/ + write_maxim(dev,1, 0x1e); /* enable register*/ + write_maxim(dev,2, 1); /* synt register */ + + + maxim_rf_set_chan(dev,priv->chan); + + write_maxim(dev,4, 0x313); /* rx register*/ + + /* PA is driven directly by the BB, we keep the MAXIM bias + * at the highest value in the boubt tha pleacing it to lower + * values may introduce some further attenuation somewhere.. + */ + + write_maxim(dev,5, 0xf); + + + /*baseband configuration*/ + write_phy(dev,0,0x88); //sys1 + write_phy(dev,3,0x8); //txagc + write_phy(dev,4,0xf8); // lnadet + write_phy(dev,5,0x90); // ifagcinit + write_phy(dev,6,0x1a); // ifagclimit + write_phy(dev,7,0x64); // ifagcdet + + /*Should be done something more here??*/ + + maxim_write_phy_antenna(dev,priv->chan); + + write_phy(dev,0x11,0x88); //trl + if(priv->diversity) + write_phy(dev,0x12,0xc7); + else + write_phy(dev,0x12,0x47); + + write_phy(dev,0x13,0x9b); + + write_phy(dev,0x19,0x0); //CHESTLIM + write_phy(dev,0x1a,0x9f); //CHSQLIM + + maxim_rf_set_chan(dev,priv->chan); +} |