diff options
Diffstat (limited to 'drivers/net/wireless/rtl8180_max2820.c')
-rw-r--r-- | drivers/net/wireless/rtl8180_max2820.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c new file mode 100644 index 000000000000..98fe9fd64968 --- /dev/null +++ b/drivers/net/wireless/rtl8180_max2820.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * Radio tuning for Maxim max2820 on RTL8180 | ||
3 | * | ||
4 | * Copyright 2007 Andrea Merello <andreamrl@tiscali.it> | ||
5 | * | ||
6 | * Code from the BSD driver and the rtl8181 project have been | ||
7 | * very useful to understand certain things | ||
8 | * | ||
9 | * I want to thanks the Authors of such projects and the Ndiswrapper | ||
10 | * project Authors. | ||
11 | * | ||
12 | * A special Big Thanks also is for all people who donated me cards, | ||
13 | * making possible the creation of the original rtl8180 driver | ||
14 | * from which this code is derived! | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License version 2 as | ||
18 | * published by the Free Software Foundation. | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <net/mac80211.h> | ||
25 | |||
26 | #include "rtl8180.h" | ||
27 | #include "rtl8180_max2820.h" | ||
28 | |||
29 | static const u32 max2820_chan[] = { | ||
30 | 12, /* CH 1 */ | ||
31 | 17, | ||
32 | 22, | ||
33 | 27, | ||
34 | 32, | ||
35 | 37, | ||
36 | 42, | ||
37 | 47, | ||
38 | 52, | ||
39 | 57, | ||
40 | 62, | ||
41 | 67, | ||
42 | 72, | ||
43 | 84, /* CH 14 */ | ||
44 | }; | ||
45 | |||
46 | static void write_max2820(struct ieee80211_hw *dev, u8 addr, u32 data) | ||
47 | { | ||
48 | struct rtl8180_priv *priv = dev->priv; | ||
49 | u32 phy_config; | ||
50 | |||
51 | phy_config = 0x90 + (data & 0xf); | ||
52 | phy_config <<= 16; | ||
53 | phy_config += addr; | ||
54 | phy_config <<= 8; | ||
55 | phy_config += (data >> 4) & 0xff; | ||
56 | |||
57 | rtl818x_iowrite32(priv, | ||
58 | (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); | ||
59 | |||
60 | msleep(1); | ||
61 | } | ||
62 | |||
63 | static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan) | ||
64 | { | ||
65 | struct rtl8180_priv *priv = dev->priv; | ||
66 | u8 ant; | ||
67 | |||
68 | ant = MAXIM_ANTENNA; | ||
69 | if (priv->rfparam & RF_PARAM_ANTBDEFAULT) | ||
70 | ant |= BB_ANTENNA_B; | ||
71 | if (chan == 14) | ||
72 | ant |= BB_ANTATTEN_CHAN14; | ||
73 | |||
74 | rtl8180_write_phy(dev, 0x10, ant); | ||
75 | } | ||
76 | |||
77 | static void max2820_rf_set_channel(struct ieee80211_hw *dev, | ||
78 | struct ieee80211_conf *conf) | ||
79 | { | ||
80 | struct rtl8180_priv *priv = dev->priv; | ||
81 | unsigned int chan_idx = conf ? conf->channel - 1 : 0; | ||
82 | u32 txpw = priv->channels[chan_idx].val & 0xFF; | ||
83 | u32 chan = max2820_chan[chan_idx]; | ||
84 | |||
85 | /* While philips SA2400 drive the PA bias from | ||
86 | * sa2400, for MAXIM we do this directly from BB */ | ||
87 | rtl8180_write_phy(dev, 3, txpw); | ||
88 | |||
89 | max2820_write_phy_antenna(dev, chan); | ||
90 | write_max2820(dev, 3, chan); | ||
91 | } | ||
92 | |||
93 | static void max2820_rf_stop(struct ieee80211_hw *dev) | ||
94 | { | ||
95 | rtl8180_write_phy(dev, 3, 0x8); | ||
96 | write_max2820(dev, 1, 0); | ||
97 | } | ||
98 | |||
99 | |||
100 | static void max2820_rf_init(struct ieee80211_hw *dev) | ||
101 | { | ||
102 | struct rtl8180_priv *priv = dev->priv; | ||
103 | |||
104 | /* MAXIM from netbsd driver */ | ||
105 | write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */ | ||
106 | write_max2820(dev, 1, 0x01e); /* enable register */ | ||
107 | write_max2820(dev, 2, 0x001); /* synt register */ | ||
108 | |||
109 | max2820_rf_set_channel(dev, NULL); | ||
110 | |||
111 | write_max2820(dev, 4, 0x313); /* rx register */ | ||
112 | |||
113 | /* PA is driven directly by the BB, we keep the MAXIM bias | ||
114 | * at the highest value in case that setting it to lower | ||
115 | * values may introduce some further attenuation somewhere.. | ||
116 | */ | ||
117 | write_max2820(dev, 5, 0x00f); | ||
118 | |||
119 | /* baseband configuration */ | ||
120 | rtl8180_write_phy(dev, 0, 0x88); /* sys1 */ | ||
121 | rtl8180_write_phy(dev, 3, 0x08); /* txagc */ | ||
122 | rtl8180_write_phy(dev, 4, 0xf8); /* lnadet */ | ||
123 | rtl8180_write_phy(dev, 5, 0x90); /* ifagcinit */ | ||
124 | rtl8180_write_phy(dev, 6, 0x1a); /* ifagclimit */ | ||
125 | rtl8180_write_phy(dev, 7, 0x64); /* ifagcdet */ | ||
126 | |||
127 | max2820_write_phy_antenna(dev, 1); | ||
128 | |||
129 | rtl8180_write_phy(dev, 0x11, 0x88); /* trl */ | ||
130 | |||
131 | if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & | ||
132 | RTL818X_CONFIG2_ANTENNA_DIV) | ||
133 | rtl8180_write_phy(dev, 0x12, 0xc7); | ||
134 | else | ||
135 | rtl8180_write_phy(dev, 0x12, 0x47); | ||
136 | |||
137 | rtl8180_write_phy(dev, 0x13, 0x9b); | ||
138 | |||
139 | rtl8180_write_phy(dev, 0x19, 0x0); /* CHESTLIM */ | ||
140 | rtl8180_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM */ | ||
141 | |||
142 | max2820_rf_set_channel(dev, NULL); | ||
143 | } | ||
144 | |||
145 | const struct rtl818x_rf_ops max2820_rf_ops = { | ||
146 | .name = "Maxim", | ||
147 | .init = max2820_rf_init, | ||
148 | .stop = max2820_rf_stop, | ||
149 | .set_chan = max2820_rf_set_channel | ||
150 | }; | ||