iPXE
rtl8180_max2820.c
Go to the documentation of this file.
00001 /*
00002  * Radio tuning for Maxim max2820 on RTL8180
00003  *
00004  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
00005  *
00006  * Modified slightly for iPXE, June 2009 by Joshua Oreman.
00007  *
00008  * Code from the BSD driver and the rtl8181 project have been
00009  * very useful to understand certain things
00010  *
00011  * I want to thanks the Authors of such projects and the Ndiswrapper
00012  * project Authors.
00013  *
00014  * A special Big Thanks also is for all people who donated me cards,
00015  * making possible the creation of the original rtl8180 driver
00016  * from which this code is derived!
00017  *
00018  * This program is free software; you can redistribute it and/or modify
00019  * it under the terms of the GNU General Public License version 2 as
00020  * published by the Free Software Foundation.
00021  */
00022 
00023 #include <unistd.h>
00024 #include <ipxe/pci.h>
00025 #include <ipxe/net80211.h>
00026 
00027 #include "rtl818x.h"
00028 
00029 FILE_LICENCE(GPL2_ONLY);
00030 
00031 #define MAXIM_ANTENNA 0xb3
00032 
00033 static const u32 max2820_chan[] = {
00034         12, /* CH 1 */
00035         17,
00036         22,
00037         27,
00038         32,
00039         37,
00040         42,
00041         47,
00042         52,
00043         57,
00044         62,
00045         67,
00046         72,
00047         84, /* CH 14 */
00048 };
00049 
00050 static void write_max2820(struct net80211_device *dev, u8 addr, u32 data)
00051 {
00052         struct rtl818x_priv *priv = dev->priv;
00053         u32 phy_config;
00054 
00055         phy_config = 0x90 + (data & 0xf);
00056         phy_config <<= 16;
00057         phy_config += addr;
00058         phy_config <<= 8;
00059         phy_config += (data >> 4) & 0xff;
00060 
00061         /* This was originally a 32-bit write to a typecast
00062            RFPinsOutput, but gcc complained about aliasing rules. -JBO */
00063         rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, phy_config & 0xffff);
00064         rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, phy_config >> 16);
00065 
00066         mdelay(1);
00067 }
00068 
00069 static void max2820_write_phy_antenna(struct net80211_device *dev, short chan)
00070 {
00071         struct rtl818x_priv *priv = dev->priv;
00072         u8 ant;
00073 
00074         ant = MAXIM_ANTENNA;
00075         if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
00076                 ant |= BB_ANTENNA_B;
00077         if (chan == 14)
00078                 ant |= BB_ANTATTEN_CHAN14;
00079 
00080         rtl818x_write_phy(dev, 0x10, ant);
00081 }
00082 
00083 static void max2820_rf_set_channel(struct net80211_device *dev,
00084                                    struct net80211_channel *channelp)
00085 {
00086         struct rtl818x_priv *priv = dev->priv;
00087         int channel = channelp->channel_nr;
00088         unsigned int chan_idx = channel - 1;
00089         u32 txpw = priv->txpower[chan_idx] & 0xFF;
00090         u32 chan = max2820_chan[chan_idx];
00091 
00092         /* While philips SA2400 drive the PA bias from
00093          * sa2400, for MAXIM we do this directly from BB */
00094         rtl818x_write_phy(dev, 3, txpw);
00095 
00096         max2820_write_phy_antenna(dev, channel);
00097         write_max2820(dev, 3, chan);
00098 }
00099 
00100 static void max2820_rf_stop(struct net80211_device *dev)
00101 {
00102         rtl818x_write_phy(dev, 3, 0x8);
00103         write_max2820(dev, 1, 0);
00104 }
00105 
00106 
00107 static void max2820_rf_init(struct net80211_device *dev)
00108 {
00109         struct rtl818x_priv *priv = dev->priv;
00110 
00111         /* MAXIM from netbsd driver */
00112         write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */
00113         write_max2820(dev, 1, 0x01e); /* enable register */
00114         write_max2820(dev, 2, 0x001); /* synt register */
00115 
00116         max2820_rf_set_channel(dev, NULL);
00117 
00118         write_max2820(dev, 4, 0x313); /* rx register */
00119 
00120         /* PA is driven directly by the BB, we keep the MAXIM bias
00121          * at the highest value in case that setting it to lower
00122          * values may introduce some further attenuation somewhere..
00123          */
00124         write_max2820(dev, 5, 0x00f);
00125 
00126         /* baseband configuration */
00127         rtl818x_write_phy(dev, 0, 0x88); /* sys1       */
00128         rtl818x_write_phy(dev, 3, 0x08); /* txagc      */
00129         rtl818x_write_phy(dev, 4, 0xf8); /* lnadet     */
00130         rtl818x_write_phy(dev, 5, 0x90); /* ifagcinit  */
00131         rtl818x_write_phy(dev, 6, 0x1a); /* ifagclimit */
00132         rtl818x_write_phy(dev, 7, 0x64); /* ifagcdet   */
00133 
00134         max2820_write_phy_antenna(dev, 1);
00135 
00136         rtl818x_write_phy(dev, 0x11, 0x88); /* trl */
00137 
00138         if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
00139             RTL818X_CONFIG2_ANTENNA_DIV)
00140                 rtl818x_write_phy(dev, 0x12, 0xc7);
00141         else
00142                 rtl818x_write_phy(dev, 0x12, 0x47);
00143 
00144         rtl818x_write_phy(dev, 0x13, 0x9b);
00145 
00146         rtl818x_write_phy(dev, 0x19, 0x0);  /* CHESTLIM */
00147         rtl818x_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM  */
00148 
00149         max2820_rf_set_channel(dev, NULL);
00150 }
00151 
00152 struct rtl818x_rf_ops max2820_rf_ops __rtl818x_rf_driver = {
00153         .name           = "Maxim max2820",
00154         .id             = 4,
00155         .init           = max2820_rf_init,
00156         .stop           = max2820_rf_stop,
00157         .set_chan       = max2820_rf_set_channel
00158 };