Home | History | Annotate | Download | only in rtl818x
      1 /*
      2  * Radio tuning for Maxim max2820 on RTL8180
      3  *
      4  * Copyright 2007 Andrea Merello <andreamrl (at) tiscali.it>
      5  *
      6  * Modified slightly for gPXE, June 2009 by Joshua Oreman.
      7  *
      8  * Code from the BSD driver and the rtl8181 project have been
      9  * very useful to understand certain things
     10  *
     11  * I want to thanks the Authors of such projects and the Ndiswrapper
     12  * project Authors.
     13  *
     14  * A special Big Thanks also is for all people who donated me cards,
     15  * making possible the creation of the original rtl8180 driver
     16  * from which this code is derived!
     17  *
     18  * This program is free software; you can redistribute it and/or modify
     19  * it under the terms of the GNU General Public License version 2 as
     20  * published by the Free Software Foundation.
     21  */
     22 
     23 #include <unistd.h>
     24 #include <gpxe/pci.h>
     25 #include <gpxe/net80211.h>
     26 
     27 #include "rtl818x.h"
     28 
     29 FILE_LICENCE(GPL2_ONLY);
     30 
     31 #define MAXIM_ANTENNA 0xb3
     32 
     33 static const u32 max2820_chan[] = {
     34 	12, /* CH 1 */
     35 	17,
     36 	22,
     37 	27,
     38 	32,
     39 	37,
     40 	42,
     41 	47,
     42 	52,
     43 	57,
     44 	62,
     45 	67,
     46 	72,
     47 	84, /* CH 14 */
     48 };
     49 
     50 static void write_max2820(struct net80211_device *dev, u8 addr, u32 data)
     51 {
     52 	struct rtl818x_priv *priv = dev->priv;
     53 	u32 phy_config;
     54 
     55 	phy_config = 0x90 + (data & 0xf);
     56 	phy_config <<= 16;
     57 	phy_config += addr;
     58 	phy_config <<= 8;
     59 	phy_config += (data >> 4) & 0xff;
     60 
     61 	/* This was originally a 32-bit write to a typecast
     62 	   RFPinsOutput, but gcc complained about aliasing rules. -JBO */
     63 	rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, phy_config & 0xffff);
     64 	rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, phy_config >> 16);
     65 
     66 	mdelay(1);
     67 }
     68 
     69 static void max2820_write_phy_antenna(struct net80211_device *dev, short chan)
     70 {
     71 	struct rtl818x_priv *priv = dev->priv;
     72 	u8 ant;
     73 
     74 	ant = MAXIM_ANTENNA;
     75 	if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
     76 		ant |= BB_ANTENNA_B;
     77 	if (chan == 14)
     78 		ant |= BB_ANTATTEN_CHAN14;
     79 
     80 	rtl818x_write_phy(dev, 0x10, ant);
     81 }
     82 
     83 static void max2820_rf_set_channel(struct net80211_device *dev,
     84 				   struct net80211_channel *channelp)
     85 {
     86 	struct rtl818x_priv *priv = dev->priv;
     87 	int channel = channelp->channel_nr;
     88 	unsigned int chan_idx = channel - 1;
     89 	u32 txpw = priv->txpower[chan_idx] & 0xFF;
     90 	u32 chan = max2820_chan[chan_idx];
     91 
     92 	/* While philips SA2400 drive the PA bias from
     93 	 * sa2400, for MAXIM we do this directly from BB */
     94 	rtl818x_write_phy(dev, 3, txpw);
     95 
     96 	max2820_write_phy_antenna(dev, channel);
     97 	write_max2820(dev, 3, chan);
     98 }
     99 
    100 static void max2820_rf_stop(struct net80211_device *dev)
    101 {
    102 	rtl818x_write_phy(dev, 3, 0x8);
    103 	write_max2820(dev, 1, 0);
    104 }
    105 
    106 
    107 static void max2820_rf_init(struct net80211_device *dev)
    108 {
    109 	struct rtl818x_priv *priv = dev->priv;
    110 
    111 	/* MAXIM from netbsd driver */
    112 	write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */
    113 	write_max2820(dev, 1, 0x01e); /* enable register */
    114 	write_max2820(dev, 2, 0x001); /* synt register */
    115 
    116 	max2820_rf_set_channel(dev, NULL);
    117 
    118 	write_max2820(dev, 4, 0x313); /* rx register */
    119 
    120 	/* PA is driven directly by the BB, we keep the MAXIM bias
    121 	 * at the highest value in case that setting it to lower
    122 	 * values may introduce some further attenuation somewhere..
    123 	 */
    124 	write_max2820(dev, 5, 0x00f);
    125 
    126 	/* baseband configuration */
    127 	rtl818x_write_phy(dev, 0, 0x88); /* sys1       */
    128 	rtl818x_write_phy(dev, 3, 0x08); /* txagc      */
    129 	rtl818x_write_phy(dev, 4, 0xf8); /* lnadet     */
    130 	rtl818x_write_phy(dev, 5, 0x90); /* ifagcinit  */
    131 	rtl818x_write_phy(dev, 6, 0x1a); /* ifagclimit */
    132 	rtl818x_write_phy(dev, 7, 0x64); /* ifagcdet   */
    133 
    134 	max2820_write_phy_antenna(dev, 1);
    135 
    136 	rtl818x_write_phy(dev, 0x11, 0x88); /* trl */
    137 
    138 	if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
    139 	    RTL818X_CONFIG2_ANTENNA_DIV)
    140 		rtl818x_write_phy(dev, 0x12, 0xc7);
    141 	else
    142 		rtl818x_write_phy(dev, 0x12, 0x47);
    143 
    144 	rtl818x_write_phy(dev, 0x13, 0x9b);
    145 
    146 	rtl818x_write_phy(dev, 0x19, 0x0);  /* CHESTLIM */
    147 	rtl818x_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM  */
    148 
    149 	max2820_rf_set_channel(dev, NULL);
    150 }
    151 
    152 struct rtl818x_rf_ops max2820_rf_ops __rtl818x_rf_driver = {
    153 	.name		= "Maxim max2820",
    154 	.id		= 4,
    155 	.init		= max2820_rf_init,
    156 	.stop		= max2820_rf_stop,
    157 	.set_chan	= max2820_rf_set_channel
    158 };
    159