aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/zd1211rw
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2007-05-23 20:06:53 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-08 22:16:37 -0400
commit4481d6093e62e168ab06e9bbb4e67a9bebb8c7f7 (patch)
tree49efc53cf2a4c2781f0b644e64c28ce588bf2352 /drivers/net/wireless/zd1211rw
parent9c8fc71ddd1b42c0c632036333790f230cea815d (diff)
[PATCH] zd1211rw: Add UW2453 RF support
This patch adds support for another radio appearing in new devices: the Ubec UW2453. It's more complicated than the other RF's we support, but Ubec publish full tech specs so we're able to understand the vendor code relatively well. Now that we support UW2453, we also support Atheros' new USB chip: the AR5007UG. From the little info we have, this appears to be just a rebranded ZD1211B. This RF code doesn't work very well -- lots more TX/RX errors than the other RFs. However, the vendor driver doesn't do any better, so this is all we can do for now. [kune@deine-taler.de: bug fixes] Signed-off-by: Daniel Drake <dsd@gentoo.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/zd1211rw')
-rw-r--r--drivers/net/wireless/zd1211rw/Makefile2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.c15
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.h1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_uw2453.c534
5 files changed, 547 insertions, 8 deletions
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 6603ad5be63d..4d505903352c 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o
3zd1211rw-objs := zd_chip.o zd_ieee80211.o \ 3zd1211rw-objs := zd_chip.o zd_ieee80211.o \
4 zd_mac.o zd_netdev.o \ 4 zd_mac.o zd_netdev.o \
5 zd_rf_al2230.o zd_rf_rf2959.o \ 5 zd_rf_al2230.o zd_rf_rf2959.o \
6 zd_rf_al7230b.o \ 6 zd_rf_al7230b.o zd_rf_uw2453.o \
7 zd_rf.o zd_usb.o zd_util.o 7 zd_rf.o zd_usb.o zd_util.o
8 8
9ifeq ($(CONFIG_ZD1211RW_DEBUG),y) 9ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ce0a5f6da0d2..79d0288c193a 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -608,6 +608,9 @@ enum {
608#define CR_ZD1211B_TXOP CTL_REG(0x0b20) 608#define CR_ZD1211B_TXOP CTL_REG(0x0b20)
609#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) 609#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28)
610 610
611/* Used to detect PLL lock */
612#define UW2453_INTR_REG ((zd_addr_t)0x85c1)
613
611#define CWIN_SIZE 0x007f043f 614#define CWIN_SIZE 0x007f043f
612 615
613 616
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index c4981ad2f9ea..7407409b60b1 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -67,25 +67,23 @@ void zd_rf_clear(struct zd_rf *rf)
67 67
68int zd_rf_init_hw(struct zd_rf *rf, u8 type) 68int zd_rf_init_hw(struct zd_rf *rf, u8 type)
69{ 69{
70 int r, t; 70 int r = 0;
71 int t;
71 struct zd_chip *chip = zd_rf_to_chip(rf); 72 struct zd_chip *chip = zd_rf_to_chip(rf);
72 73
73 ZD_ASSERT(mutex_is_locked(&chip->mutex)); 74 ZD_ASSERT(mutex_is_locked(&chip->mutex));
74 switch (type) { 75 switch (type) {
75 case RF2959_RF: 76 case RF2959_RF:
76 r = zd_rf_init_rf2959(rf); 77 r = zd_rf_init_rf2959(rf);
77 if (r)
78 return r;
79 break; 78 break;
80 case AL2230_RF: 79 case AL2230_RF:
81 r = zd_rf_init_al2230(rf); 80 r = zd_rf_init_al2230(rf);
82 if (r)
83 return r;
84 break; 81 break;
85 case AL7230B_RF: 82 case AL7230B_RF:
86 r = zd_rf_init_al7230b(rf); 83 r = zd_rf_init_al7230b(rf);
87 if (r) 84 break;
88 return r; 85 case UW2453_RF:
86 r = zd_rf_init_uw2453(rf);
89 break; 87 break;
90 default: 88 default:
91 dev_err(zd_chip_dev(chip), 89 dev_err(zd_chip_dev(chip),
@@ -94,6 +92,9 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
94 return -ENODEV; 92 return -ENODEV;
95 } 93 }
96 94
95 if (r)
96 return r;
97
97 rf->type = type; 98 rf->type = type;
98 99
99 r = zd_chip_lock_phy_regs(chip); 100 r = zd_chip_lock_phy_regs(chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index c204f9ae7128..6dced2ae5a11 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -89,5 +89,6 @@ static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
89int zd_rf_init_rf2959(struct zd_rf *rf); 89int zd_rf_init_rf2959(struct zd_rf *rf);
90int zd_rf_init_al2230(struct zd_rf *rf); 90int zd_rf_init_al2230(struct zd_rf *rf);
91int zd_rf_init_al7230b(struct zd_rf *rf); 91int zd_rf_init_al7230b(struct zd_rf *rf);
92int zd_rf_init_uw2453(struct zd_rf *rf);
92 93
93#endif /* _ZD_RF_H */ 94#endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
new file mode 100644
index 000000000000..414e40d571ab
--- /dev/null
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -0,0 +1,534 @@
1/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18#include <linux/kernel.h>
19
20#include "zd_rf.h"
21#include "zd_usb.h"
22#include "zd_chip.h"
23
24/* This RF programming code is based upon the code found in v2.16.0.0 of the
25 * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
26 * for this RF on their website, so we're able to understand more than
27 * usual as to what is going on. Thumbs up for Ubec for doing that. */
28
29/* The 3-wire serial interface provides access to 8 write-only registers.
30 * The data format is a 4 bit register address followed by a 20 bit value. */
31#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
32
33/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
34 * fractional divide ratio) and 3 (VCO config).
35 *
36 * We configure the RF to produce an interrupt when the PLL is locked onto
37 * the configured frequency. During initialization, we run through a variety
38 * of different VCO configurations on channel 1 until we detect a PLL lock.
39 * When this happens, we remember which VCO configuration produced the lock
40 * and use it later. Actually, we use the configuration *after* the one that
41 * produced the lock, which seems odd, but it works.
42 *
43 * If we do not see a PLL lock on any standard VCO config, we fall back on an
44 * autocal configuration, which has a fixed (as opposed to per-channel) VCO
45 * config and different synth values from the standard set (divide ratio
46 * is still shared with the standard set). */
47
48/* The per-channel synth values for all standard VCO configurations. These get
49 * written to register 1. */
50static const u8 uw2453_std_synth[] = {
51 RF_CHANNEL( 1) = 0x47,
52 RF_CHANNEL( 2) = 0x47,
53 RF_CHANNEL( 3) = 0x67,
54 RF_CHANNEL( 4) = 0x67,
55 RF_CHANNEL( 5) = 0x67,
56 RF_CHANNEL( 6) = 0x67,
57 RF_CHANNEL( 7) = 0x57,
58 RF_CHANNEL( 8) = 0x57,
59 RF_CHANNEL( 9) = 0x57,
60 RF_CHANNEL(10) = 0x57,
61 RF_CHANNEL(11) = 0x77,
62 RF_CHANNEL(12) = 0x77,
63 RF_CHANNEL(13) = 0x77,
64 RF_CHANNEL(14) = 0x4f,
65};
66
67/* This table stores the synthesizer fractional divide ratio for *all* VCO
68 * configurations (both standard and autocal). These get written to register 2.
69 */
70static const u16 uw2453_synth_divide[] = {
71 RF_CHANNEL( 1) = 0x999,
72 RF_CHANNEL( 2) = 0x99b,
73 RF_CHANNEL( 3) = 0x998,
74 RF_CHANNEL( 4) = 0x99a,
75 RF_CHANNEL( 5) = 0x999,
76 RF_CHANNEL( 6) = 0x99b,
77 RF_CHANNEL( 7) = 0x998,
78 RF_CHANNEL( 8) = 0x99a,
79 RF_CHANNEL( 9) = 0x999,
80 RF_CHANNEL(10) = 0x99b,
81 RF_CHANNEL(11) = 0x998,
82 RF_CHANNEL(12) = 0x99a,
83 RF_CHANNEL(13) = 0x999,
84 RF_CHANNEL(14) = 0xccc,
85};
86
87/* Here is the data for all the standard VCO configurations. We shrink our
88 * table a little by observing that both channels in a consecutive pair share
89 * the same value. We also observe that the high 4 bits ([0:3] in the specs)
90 * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
91 * below. */
92#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
93#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
94static const u16 uw2453_std_vco_cfg[][7] = {
95 { /* table 1 */
96 RF_CHANPAIR( 1, 2) = 0x664d,
97 RF_CHANPAIR( 3, 4) = 0x604d,
98 RF_CHANPAIR( 5, 6) = 0x6675,
99 RF_CHANPAIR( 7, 8) = 0x6475,
100 RF_CHANPAIR( 9, 10) = 0x6655,
101 RF_CHANPAIR(11, 12) = 0x6455,
102 RF_CHANPAIR(13, 14) = 0x6665,
103 },
104 { /* table 2 */
105 RF_CHANPAIR( 1, 2) = 0x666d,
106 RF_CHANPAIR( 3, 4) = 0x606d,
107 RF_CHANPAIR( 5, 6) = 0x664d,
108 RF_CHANPAIR( 7, 8) = 0x644d,
109 RF_CHANPAIR( 9, 10) = 0x6675,
110 RF_CHANPAIR(11, 12) = 0x6475,
111 RF_CHANPAIR(13, 14) = 0x6655,
112 },
113 { /* table 3 */
114 RF_CHANPAIR( 1, 2) = 0x665d,
115 RF_CHANPAIR( 3, 4) = 0x605d,
116 RF_CHANPAIR( 5, 6) = 0x666d,
117 RF_CHANPAIR( 7, 8) = 0x646d,
118 RF_CHANPAIR( 9, 10) = 0x664d,
119 RF_CHANPAIR(11, 12) = 0x644d,
120 RF_CHANPAIR(13, 14) = 0x6675,
121 },
122 { /* table 4 */
123 RF_CHANPAIR( 1, 2) = 0x667d,
124 RF_CHANPAIR( 3, 4) = 0x607d,
125 RF_CHANPAIR( 5, 6) = 0x665d,
126 RF_CHANPAIR( 7, 8) = 0x645d,
127 RF_CHANPAIR( 9, 10) = 0x666d,
128 RF_CHANPAIR(11, 12) = 0x646d,
129 RF_CHANPAIR(13, 14) = 0x664d,
130 },
131 { /* table 5 */
132 RF_CHANPAIR( 1, 2) = 0x6643,
133 RF_CHANPAIR( 3, 4) = 0x6043,
134 RF_CHANPAIR( 5, 6) = 0x667d,
135 RF_CHANPAIR( 7, 8) = 0x647d,
136 RF_CHANPAIR( 9, 10) = 0x665d,
137 RF_CHANPAIR(11, 12) = 0x645d,
138 RF_CHANPAIR(13, 14) = 0x666d,
139 },
140 { /* table 6 */
141 RF_CHANPAIR( 1, 2) = 0x6663,
142 RF_CHANPAIR( 3, 4) = 0x6063,
143 RF_CHANPAIR( 5, 6) = 0x6643,
144 RF_CHANPAIR( 7, 8) = 0x6443,
145 RF_CHANPAIR( 9, 10) = 0x667d,
146 RF_CHANPAIR(11, 12) = 0x647d,
147 RF_CHANPAIR(13, 14) = 0x665d,
148 },
149 { /* table 7 */
150 RF_CHANPAIR( 1, 2) = 0x6653,
151 RF_CHANPAIR( 3, 4) = 0x6053,
152 RF_CHANPAIR( 5, 6) = 0x6663,
153 RF_CHANPAIR( 7, 8) = 0x6463,
154 RF_CHANPAIR( 9, 10) = 0x6643,
155 RF_CHANPAIR(11, 12) = 0x6443,
156 RF_CHANPAIR(13, 14) = 0x667d,
157 },
158 { /* table 8 */
159 RF_CHANPAIR( 1, 2) = 0x6673,
160 RF_CHANPAIR( 3, 4) = 0x6073,
161 RF_CHANPAIR( 5, 6) = 0x6653,
162 RF_CHANPAIR( 7, 8) = 0x6453,
163 RF_CHANPAIR( 9, 10) = 0x6663,
164 RF_CHANPAIR(11, 12) = 0x6463,
165 RF_CHANPAIR(13, 14) = 0x6643,
166 },
167 { /* table 9 */
168 RF_CHANPAIR( 1, 2) = 0x664b,
169 RF_CHANPAIR( 3, 4) = 0x604b,
170 RF_CHANPAIR( 5, 6) = 0x6673,
171 RF_CHANPAIR( 7, 8) = 0x6473,
172 RF_CHANPAIR( 9, 10) = 0x6653,
173 RF_CHANPAIR(11, 12) = 0x6453,
174 RF_CHANPAIR(13, 14) = 0x6663,
175 },
176 { /* table 10 */
177 RF_CHANPAIR( 1, 2) = 0x666b,
178 RF_CHANPAIR( 3, 4) = 0x606b,
179 RF_CHANPAIR( 5, 6) = 0x664b,
180 RF_CHANPAIR( 7, 8) = 0x644b,
181 RF_CHANPAIR( 9, 10) = 0x6673,
182 RF_CHANPAIR(11, 12) = 0x6473,
183 RF_CHANPAIR(13, 14) = 0x6653,
184 },
185 { /* table 11 */
186 RF_CHANPAIR( 1, 2) = 0x665b,
187 RF_CHANPAIR( 3, 4) = 0x605b,
188 RF_CHANPAIR( 5, 6) = 0x666b,
189 RF_CHANPAIR( 7, 8) = 0x646b,
190 RF_CHANPAIR( 9, 10) = 0x664b,
191 RF_CHANPAIR(11, 12) = 0x644b,
192 RF_CHANPAIR(13, 14) = 0x6673,
193 },
194
195};
196
197/* The per-channel synth values for autocal. These get written to register 1. */
198static const u16 uw2453_autocal_synth[] = {
199 RF_CHANNEL( 1) = 0x6847,
200 RF_CHANNEL( 2) = 0x6847,
201 RF_CHANNEL( 3) = 0x6867,
202 RF_CHANNEL( 4) = 0x6867,
203 RF_CHANNEL( 5) = 0x6867,
204 RF_CHANNEL( 6) = 0x6867,
205 RF_CHANNEL( 7) = 0x6857,
206 RF_CHANNEL( 8) = 0x6857,
207 RF_CHANNEL( 9) = 0x6857,
208 RF_CHANNEL(10) = 0x6857,
209 RF_CHANNEL(11) = 0x6877,
210 RF_CHANNEL(12) = 0x6877,
211 RF_CHANNEL(13) = 0x6877,
212 RF_CHANNEL(14) = 0x684f,
213};
214
215/* The VCO configuration for autocal (all channels) */
216static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
217
218/* TX gain settings. The array index corresponds to the TX power integration
219 * values found in the EEPROM. The values get written to register 7. */
220static u32 uw2453_txgain[] = {
221 [0x00] = 0x0e313,
222 [0x01] = 0x0fb13,
223 [0x02] = 0x0e093,
224 [0x03] = 0x0f893,
225 [0x04] = 0x0ea93,
226 [0x05] = 0x1f093,
227 [0x06] = 0x1f493,
228 [0x07] = 0x1f693,
229 [0x08] = 0x1f393,
230 [0x09] = 0x1f35b,
231 [0x0a] = 0x1e6db,
232 [0x0b] = 0x1ff3f,
233 [0x0c] = 0x1ffff,
234 [0x0d] = 0x361d7,
235 [0x0e] = 0x37fbf,
236 [0x0f] = 0x3ff8b,
237 [0x10] = 0x3ff33,
238 [0x11] = 0x3fb3f,
239 [0x12] = 0x3ffff,
240};
241
242/* RF-specific structure */
243struct uw2453_priv {
244 /* index into synth/VCO config tables where PLL lock was found
245 * -1 means autocal */
246 int config;
247};
248
249#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
250
251static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
252 bool autocal)
253{
254 int r;
255 int idx = channel - 1;
256 u32 val;
257
258 if (autocal)
259 val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
260 else
261 val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
262
263 r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
264 if (r)
265 return r;
266
267 return zd_rfwrite_locked(chip,
268 UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
269}
270
271static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
272{
273 /* vendor driver always sets these upper bits even though the specs say
274 * they are reserved */
275 u32 val = 0x40000 | value;
276 return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
277}
278
279static int uw2453_init_mode(struct zd_chip *chip)
280{
281 static const u32 rv[] = {
282 UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
283 UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
284 UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
285 UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
286 };
287
288 return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
289}
290
291static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
292{
293 u8 int_value = chip->pwr_int_values[channel - 1];
294
295 if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
296 dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
297 "int value %x on channel %d\n", int_value, channel);
298 return 0;
299 }
300
301 return zd_rfwrite_locked(chip,
302 UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
303}
304
305static int uw2453_init_hw(struct zd_rf *rf)
306{
307 int i, r;
308 int found_config = -1;
309 u16 intr_status;
310 struct zd_chip *chip = zd_rf_to_chip(rf);
311
312 static const struct zd_ioreq16 ioreqs[] = {
313 { CR10, 0x89 }, { CR15, 0x20 },
314 { CR17, 0x28 }, /* 6112 no change */
315 { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 },
316 { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 },
317 { CR33, 0x28 }, { CR34, 0x30 },
318 { CR35, 0x43 }, /* 6112 3e->43 */
319 { CR41, 0x24 }, { CR44, 0x32 },
320 { CR46, 0x92 }, /* 6112 96->92 */
321 { CR47, 0x1e },
322 { CR48, 0x04 }, /* 5602 Roger */
323 { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 },
324 { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 },
325 { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d },
326 { CR99, 0x28 }, { CR100, 0x02 },
327 { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
328 { CR102, 0x27 },
329 { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */
330 { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
331 { CR109, 0x13 },
332 { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
333 { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 },
334 { CR114, 0x23 }, /* 6221 27->23 */
335 { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
336 { CR116, 0x24 }, /* 6220 1c->24 */
337 { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
338 { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
339 { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
340 { CR120, 0x4f },
341 { CR121, 0x1f }, /* 6220 4f->1f */
342 { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad },
343 { CR126, 0x6c }, { CR127, 0x03 },
344 { CR128, 0x14 }, /* 6302 12->11 */
345 { CR129, 0x12 }, /* 6301 10->0f */
346 { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 },
347 { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff },
348 { CR253, 0xff },
349 };
350
351 static const u32 rv[] = {
352 UW2453_REGWRITE(4, 0x2b), /* configure reciever gain */
353 UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
354 UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
355 UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
356
357 /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
358 * RSSI circuit powered down, reduced RSSI range */
359 UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
360
361 /* synthesizer configuration for channel 1 */
362 UW2453_REGWRITE(1, 0x47),
363 UW2453_REGWRITE(2, 0x999),
364
365 /* disable manual VCO band selection */
366 UW2453_REGWRITE(3, 0x7602),
367
368 /* enable manual VCO band selection, configure current level */
369 UW2453_REGWRITE(3, 0x46063),
370 };
371
372 r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
373 if (r)
374 return r;
375
376 r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
377 if (r)
378 return r;
379
380 r = uw2453_init_mode(chip);
381 if (r)
382 return r;
383
384 /* Try all standard VCO configuration settings on channel 1 */
385 for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
386 /* Configure synthesizer for channel 1 */
387 r = uw2453_synth_set_channel(chip, 1, false);
388 if (r)
389 return r;
390
391 /* Write VCO config */
392 r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
393 if (r)
394 return r;
395
396 /* ack interrupt event */
397 r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
398 if (r)
399 return r;
400
401 /* check interrupt status */
402 r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
403 if (r)
404 return r;
405
406 if (!intr_status & 0xf) {
407 dev_dbg_f(zd_chip_dev(chip),
408 "PLL locked on configuration %d\n", i);
409 found_config = i;
410 break;
411 }
412 }
413
414 if (found_config == -1) {
415 /* autocal */
416 dev_dbg_f(zd_chip_dev(chip),
417 "PLL did not lock, using autocal\n");
418
419 r = uw2453_synth_set_channel(chip, 1, true);
420 if (r)
421 return r;
422
423 r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
424 if (r)
425 return r;
426 }
427
428 /* To match the vendor driver behaviour, we use the configuration after
429 * the one that produced a lock. */
430 UW2453_PRIV(rf)->config = found_config + 1;
431
432 return zd_iowrite16_locked(chip, 0x06, CR203);
433}
434
435static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
436{
437 int r;
438 u16 vco_cfg;
439 int config = UW2453_PRIV(rf)->config;
440 bool autocal = (config == -1);
441 struct zd_chip *chip = zd_rf_to_chip(rf);
442
443 static const struct zd_ioreq16 ioreqs[] = {
444 { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 },
445 { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 },
446 };
447
448 r = uw2453_synth_set_channel(chip, channel, autocal);
449 if (r)
450 return r;
451
452 if (autocal)
453 vco_cfg = UW2453_AUTOCAL_VCO_CFG;
454 else
455 vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
456
457 r = uw2453_write_vco_cfg(chip, vco_cfg);
458 if (r)
459 return r;
460
461 r = uw2453_init_mode(chip);
462 if (r)
463 return r;
464
465 r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
466 if (r)
467 return r;
468
469 r = uw2453_set_tx_gain_level(chip, channel);
470 if (r)
471 return r;
472
473 return zd_iowrite16_locked(chip, 0x06, CR203);
474}
475
476static int uw2453_switch_radio_on(struct zd_rf *rf)
477{
478 int r;
479 struct zd_chip *chip = zd_rf_to_chip(rf);
480 struct zd_ioreq16 ioreqs[] = {
481 { CR11, 0x00 }, { CR251, 0x3f },
482 };
483
484 /* enter RXTX mode */
485 r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
486 if (r)
487 return r;
488
489 if (chip->is_zd1211b)
490 ioreqs[1].value = 0x7f;
491
492 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
493}
494
495static int uw2453_switch_radio_off(struct zd_rf *rf)
496{
497 int r;
498 struct zd_chip *chip = zd_rf_to_chip(rf);
499 static const struct zd_ioreq16 ioreqs[] = {
500 { CR11, 0x04 }, { CR251, 0x2f },
501 };
502
503 /* enter IDLE mode */
504 /* FIXME: shouldn't we go to SLEEP? sent email to zydas */
505 r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
506 if (r)
507 return r;
508
509 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
510}
511
512static void uw2453_clear(struct zd_rf *rf)
513{
514 kfree(rf->priv);
515}
516
517int zd_rf_init_uw2453(struct zd_rf *rf)
518{
519 rf->init_hw = uw2453_init_hw;
520 rf->set_channel = uw2453_set_channel;
521 rf->switch_radio_on = uw2453_switch_radio_on;
522 rf->switch_radio_off = uw2453_switch_radio_off;
523 rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
524 rf->clear = uw2453_clear;
525 /* we have our own TX integration code */
526 rf->update_channel_int = 0;
527
528 rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
529 if (rf->priv == NULL)
530 return -ENOMEM;
531
532 return 0;
533}
534