]>
Commit | Line | Data |
---|---|---|
f6532111 MW |
1 | /* |
2 | * Radio tuning for Maxim max2820 on RTL8180 | |
3 | * | |
93ba2a85 | 4 | * Copyright 2007 Andrea Merello <andrea.merello@gmail.com> |
f6532111 MW |
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" | |
3cfeb0c3 | 27 | #include "max2820.h" |
f6532111 MW |
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 | ||
8b73fb8e JL |
77 | static u8 max2820_rf_calc_rssi(u8 agc, u8 sq) |
78 | { | |
79 | bool odd; | |
80 | ||
81 | odd = !!(agc & 1); | |
82 | ||
83 | agc >>= 1; | |
84 | if (odd) | |
85 | agc += 76; | |
86 | else | |
87 | agc += 66; | |
88 | ||
89 | /* TODO: change addends above to avoid mult / div below */ | |
90 | return 65 * agc / 100; | |
91 | } | |
92 | ||
f6532111 MW |
93 | static void max2820_rf_set_channel(struct ieee80211_hw *dev, |
94 | struct ieee80211_conf *conf) | |
95 | { | |
96 | struct rtl8180_priv *priv = dev->priv; | |
6f6c218f | 97 | int channel = conf ? |
675a0b04 | 98 | ieee80211_frequency_to_channel(conf->chandef.chan->center_freq) : 1; |
8318d78a JB |
99 | unsigned int chan_idx = channel - 1; |
100 | u32 txpw = priv->channels[chan_idx].hw_value & 0xFF; | |
f6532111 MW |
101 | u32 chan = max2820_chan[chan_idx]; |
102 | ||
103 | /* While philips SA2400 drive the PA bias from | |
104 | * sa2400, for MAXIM we do this directly from BB */ | |
105 | rtl8180_write_phy(dev, 3, txpw); | |
106 | ||
0a0ab41e | 107 | max2820_write_phy_antenna(dev, channel); |
f6532111 MW |
108 | write_max2820(dev, 3, chan); |
109 | } | |
110 | ||
111 | static void max2820_rf_stop(struct ieee80211_hw *dev) | |
112 | { | |
113 | rtl8180_write_phy(dev, 3, 0x8); | |
114 | write_max2820(dev, 1, 0); | |
115 | } | |
116 | ||
117 | ||
118 | static void max2820_rf_init(struct ieee80211_hw *dev) | |
119 | { | |
120 | struct rtl8180_priv *priv = dev->priv; | |
121 | ||
122 | /* MAXIM from netbsd driver */ | |
123 | write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */ | |
124 | write_max2820(dev, 1, 0x01e); /* enable register */ | |
125 | write_max2820(dev, 2, 0x001); /* synt register */ | |
126 | ||
127 | max2820_rf_set_channel(dev, NULL); | |
128 | ||
129 | write_max2820(dev, 4, 0x313); /* rx register */ | |
130 | ||
131 | /* PA is driven directly by the BB, we keep the MAXIM bias | |
132 | * at the highest value in case that setting it to lower | |
133 | * values may introduce some further attenuation somewhere.. | |
134 | */ | |
135 | write_max2820(dev, 5, 0x00f); | |
136 | ||
137 | /* baseband configuration */ | |
138 | rtl8180_write_phy(dev, 0, 0x88); /* sys1 */ | |
139 | rtl8180_write_phy(dev, 3, 0x08); /* txagc */ | |
140 | rtl8180_write_phy(dev, 4, 0xf8); /* lnadet */ | |
141 | rtl8180_write_phy(dev, 5, 0x90); /* ifagcinit */ | |
142 | rtl8180_write_phy(dev, 6, 0x1a); /* ifagclimit */ | |
143 | rtl8180_write_phy(dev, 7, 0x64); /* ifagcdet */ | |
144 | ||
145 | max2820_write_phy_antenna(dev, 1); | |
146 | ||
147 | rtl8180_write_phy(dev, 0x11, 0x88); /* trl */ | |
148 | ||
149 | if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & | |
150 | RTL818X_CONFIG2_ANTENNA_DIV) | |
151 | rtl8180_write_phy(dev, 0x12, 0xc7); | |
152 | else | |
153 | rtl8180_write_phy(dev, 0x12, 0x47); | |
154 | ||
155 | rtl8180_write_phy(dev, 0x13, 0x9b); | |
156 | ||
157 | rtl8180_write_phy(dev, 0x19, 0x0); /* CHESTLIM */ | |
158 | rtl8180_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM */ | |
159 | ||
160 | max2820_rf_set_channel(dev, NULL); | |
161 | } | |
162 | ||
163 | const struct rtl818x_rf_ops max2820_rf_ops = { | |
164 | .name = "Maxim", | |
165 | .init = max2820_rf_init, | |
166 | .stop = max2820_rf_stop, | |
8b73fb8e JL |
167 | .set_chan = max2820_rf_set_channel, |
168 | .calc_rssi = max2820_rf_calc_rssi, | |
f6532111 | 169 | }; |