aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/rtl8187se/r8180_max2820.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rtl8187se/r8180_max2820.c')
-rw-r--r--drivers/staging/rtl8187se/r8180_max2820.c240
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 000000000000..cea08463d5ee
--- /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);
+}