1// SPDX-License-Identifier: GPL-2.0-or-later
2/* ZD1211 USB-WLAN driver for Linux
3 *
4 * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
5 * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
6 */
7
8#include <linux/kernel.h>
9
10#include "zd_rf.h"
11#include "zd_usb.h"
12#include "zd_chip.h"
13
14#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF)
15
16static const u32 zd1211_al2230_table[][3] = {
17 RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
18 RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
19 RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, },
20 RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, },
21 RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, },
22 RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, },
23 RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, },
24 RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, },
25 RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, },
26 RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, },
27 RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, },
28 RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, },
29 RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, },
30 RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, },
31};
32
33static const u32 zd1211b_al2230_table[][3] = {
34 RF_CHANNEL( 1) = { 0x09efc0, 0x8cccc0, 0xb00000, },
35 RF_CHANNEL( 2) = { 0x09efc0, 0x8cccd0, 0xb00000, },
36 RF_CHANNEL( 3) = { 0x09e7c0, 0x8cccc0, 0xb00000, },
37 RF_CHANNEL( 4) = { 0x09e7c0, 0x8cccd0, 0xb00000, },
38 RF_CHANNEL( 5) = { 0x05efc0, 0x8cccc0, 0xb00000, },
39 RF_CHANNEL( 6) = { 0x05efc0, 0x8cccd0, 0xb00000, },
40 RF_CHANNEL( 7) = { 0x05e7c0, 0x8cccc0, 0xb00000, },
41 RF_CHANNEL( 8) = { 0x05e7c0, 0x8cccd0, 0xb00000, },
42 RF_CHANNEL( 9) = { 0x0defc0, 0x8cccc0, 0xb00000, },
43 RF_CHANNEL(10) = { 0x0defc0, 0x8cccd0, 0xb00000, },
44 RF_CHANNEL(11) = { 0x0de7c0, 0x8cccc0, 0xb00000, },
45 RF_CHANNEL(12) = { 0x0de7c0, 0x8cccd0, 0xb00000, },
46 RF_CHANNEL(13) = { 0x03efc0, 0x8cccc0, 0xb00000, },
47 RF_CHANNEL(14) = { 0x03e7c0, 0x866660, 0xb00000, },
48};
49
50static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = {
51 { ZD_CR240, 0x57 }, { ZD_CR9, 0xe0 },
52};
53
54static const struct zd_ioreq16 ioreqs_init_al2230s[] = {
55 { ZD_CR47, 0x1e }, /* MARK_002 */
56 { ZD_CR106, 0x22 },
57 { ZD_CR107, 0x2a }, /* MARK_002 */
58 { ZD_CR109, 0x13 }, /* MARK_002 */
59 { ZD_CR118, 0xf8 }, /* MARK_002 */
60 { ZD_CR119, 0x12 }, { ZD_CR122, 0xe0 },
61 { ZD_CR128, 0x10 }, /* MARK_001 from 0xe->0x10 */
62 { ZD_CR129, 0x0e }, /* MARK_001 from 0xd->0x0e */
63 { ZD_CR130, 0x10 }, /* MARK_001 from 0xb->0x0d */
64};
65
66static int zd1211b_al2230_finalize_rf(struct zd_chip *chip)
67{
68 int r;
69 static const struct zd_ioreq16 ioreqs[] = {
70 { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 }, { ZD_CR79, 0x58 },
71 { ZD_CR12, 0xf0 }, { ZD_CR77, 0x1b }, { ZD_CR78, 0x58 },
72 { ZD_CR203, 0x06 },
73 { },
74
75 { ZD_CR240, 0x80 },
76 };
77
78 r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
79 if (r)
80 return r;
81
82 /* related to antenna selection? */
83 if (chip->new_phy_layout) {
84 r = zd_iowrite16_locked(chip, value: 0xe1, ZD_CR9);
85 if (r)
86 return r;
87 }
88
89 return zd_iowrite16_locked(chip, value: 0x06, ZD_CR203);
90}
91
92static int zd1211_al2230_init_hw(struct zd_rf *rf)
93{
94 int r;
95 struct zd_chip *chip = zd_rf_to_chip(rf);
96
97 static const struct zd_ioreq16 ioreqs_init[] = {
98 { ZD_CR15, 0x20 }, { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 },
99 { ZD_CR26, 0x11 }, { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 },
100 { ZD_CR44, 0x33 }, { ZD_CR106, 0x2a }, { ZD_CR107, 0x1a },
101 { ZD_CR109, 0x09 }, { ZD_CR110, 0x27 }, { ZD_CR111, 0x2b },
102 { ZD_CR112, 0x2b }, { ZD_CR119, 0x0a }, { ZD_CR10, 0x89 },
103 /* for newest (3rd cut) AL2300 */
104 { ZD_CR17, 0x28 },
105 { ZD_CR26, 0x93 }, { ZD_CR34, 0x30 },
106 /* for newest (3rd cut) AL2300 */
107 { ZD_CR35, 0x3e },
108 { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 },
109 /* for newest (3rd cut) AL2300 */
110 { ZD_CR46, 0x96 },
111 { ZD_CR47, 0x1e }, { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 },
112 { ZD_CR81, 0x30 }, { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 },
113 { ZD_CR92, 0x0a }, { ZD_CR99, 0x28 }, { ZD_CR100, 0x00 },
114 { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, { ZD_CR106, 0x24 },
115 { ZD_CR107, 0x2a }, { ZD_CR109, 0x09 }, { ZD_CR110, 0x13 },
116 { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 },
117 { ZD_CR114, 0x27 },
118 /* for newest (3rd cut) AL2300 */
119 { ZD_CR115, 0x24 },
120 { ZD_CR116, 0x24 }, { ZD_CR117, 0xf4 }, { ZD_CR118, 0xfc },
121 { ZD_CR119, 0x10 }, { ZD_CR120, 0x4f }, { ZD_CR121, 0x77 },
122 { ZD_CR122, 0xe0 }, { ZD_CR137, 0x88 }, { ZD_CR252, 0xff },
123 { ZD_CR253, 0xff },
124 };
125
126 static const struct zd_ioreq16 ioreqs_pll[] = {
127 /* shdnb(PLL_ON)=0 */
128 { ZD_CR251, 0x2f },
129 /* shdnb(PLL_ON)=1 */
130 { ZD_CR251, 0x3f },
131 { ZD_CR138, 0x28 }, { ZD_CR203, 0x06 },
132 };
133
134 static const u32 rv1[] = {
135 /* Channel 1 */
136 0x03f790,
137 0x033331,
138 0x00000d,
139
140 0x0b3331,
141 0x03b812,
142 0x00fff3,
143 };
144
145 static const u32 rv2[] = {
146 0x000da4,
147 0x0f4dc5, /* fix freq shift, 0x04edc5 */
148 0x0805b6,
149 0x011687,
150 0x000688,
151 0x0403b9, /* external control TX power (ZD_CR31) */
152 0x00dbba,
153 0x00099b,
154 0x0bdffc,
155 0x00000d,
156 0x00500f,
157 };
158
159 static const u32 rv3[] = {
160 0x00d00f,
161 0x004c0f,
162 0x00540f,
163 0x00700f,
164 0x00500f,
165 };
166
167 r = zd_iowrite16a_locked(chip, ioreqs: ioreqs_init, ARRAY_SIZE(ioreqs_init));
168 if (r)
169 return r;
170
171 if (IS_AL2230S(chip)) {
172 r = zd_iowrite16a_locked(chip, ioreqs: ioreqs_init_al2230s,
173 ARRAY_SIZE(ioreqs_init_al2230s));
174 if (r)
175 return r;
176 }
177
178 r = zd_rfwritev_locked(chip, values: rv1, ARRAY_SIZE(rv1), bits: RF_RV_BITS);
179 if (r)
180 return r;
181
182 /* improve band edge for AL2230S */
183 if (IS_AL2230S(chip))
184 r = zd_rfwrite_locked(chip, value: 0x000824, bits: RF_RV_BITS);
185 else
186 r = zd_rfwrite_locked(chip, value: 0x0005a4, bits: RF_RV_BITS);
187 if (r)
188 return r;
189
190 r = zd_rfwritev_locked(chip, values: rv2, ARRAY_SIZE(rv2), bits: RF_RV_BITS);
191 if (r)
192 return r;
193
194 r = zd_iowrite16a_locked(chip, ioreqs: ioreqs_pll, ARRAY_SIZE(ioreqs_pll));
195 if (r)
196 return r;
197
198 r = zd_rfwritev_locked(chip, values: rv3, ARRAY_SIZE(rv3), bits: RF_RV_BITS);
199 if (r)
200 return r;
201
202 return 0;
203}
204
205static int zd1211b_al2230_init_hw(struct zd_rf *rf)
206{
207 int r;
208 struct zd_chip *chip = zd_rf_to_chip(rf);
209
210 static const struct zd_ioreq16 ioreqs1[] = {
211 { ZD_CR10, 0x89 }, { ZD_CR15, 0x20 },
212 { ZD_CR17, 0x2B }, /* for newest(3rd cut) AL2230 */
213 { ZD_CR23, 0x40 }, { ZD_CR24, 0x20 }, { ZD_CR26, 0x93 },
214 { ZD_CR28, 0x3e }, { ZD_CR29, 0x00 },
215 { ZD_CR33, 0x28 }, /* 5621 */
216 { ZD_CR34, 0x30 },
217 { ZD_CR35, 0x3e }, /* for newest(3rd cut) AL2230 */
218 { ZD_CR41, 0x24 }, { ZD_CR44, 0x32 },
219 { ZD_CR46, 0x99 }, /* for newest(3rd cut) AL2230 */
220 { ZD_CR47, 0x1e },
221
222 /* ZD1211B 05.06.10 */
223 { ZD_CR48, 0x06 }, { ZD_CR49, 0xf9 }, { ZD_CR51, 0x01 },
224 { ZD_CR52, 0x80 }, { ZD_CR53, 0x7e }, { ZD_CR65, 0x00 },
225 { ZD_CR66, 0x00 }, { ZD_CR67, 0x00 }, { ZD_CR68, 0x00 },
226 { ZD_CR69, 0x28 },
227
228 { ZD_CR79, 0x58 }, { ZD_CR80, 0x30 }, { ZD_CR81, 0x30 },
229 { ZD_CR87, 0x0a }, { ZD_CR89, 0x04 },
230 { ZD_CR91, 0x00 }, /* 5621 */
231 { ZD_CR92, 0x0a },
232 { ZD_CR98, 0x8d }, /* 4804, for 1212 new algorithm */
233 { ZD_CR99, 0x00 }, /* 5621 */
234 { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 },
235 { ZD_CR106, 0x24 }, /* for newest(3rd cut) AL2230 */
236 { ZD_CR107, 0x2a },
237 { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */
238 { ZD_CR110, 0x1f }, /* 4804, for 1212 new algorithm */
239 { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 },
240 { ZD_CR114, 0x27 },
241 { ZD_CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut)
242 * AL2230
243 */
244 { ZD_CR116, 0x24 },
245 { ZD_CR117, 0xfa }, /* for 1211b */
246 { ZD_CR118, 0xfa }, /* for 1211b */
247 { ZD_CR119, 0x10 },
248 { ZD_CR120, 0x4f },
249 { ZD_CR121, 0x6c }, /* for 1211b */
250 { ZD_CR122, 0xfc }, /* E0->FC at 4902 */
251 { ZD_CR123, 0x57 }, /* 5623 */
252 { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */
253 { ZD_CR126, 0x6c }, /* 5614 */
254 { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */
255 { ZD_CR137, 0x50 }, /* 5614 */
256 { ZD_CR138, 0xa8 },
257 { ZD_CR144, 0xac }, /* 5621 */
258 { ZD_CR150, 0x0d }, { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 },
259 };
260
261 static const u32 rv1[] = {
262 0x8cccd0,
263 0x481dc0,
264 0xcfff00,
265 0x25a000,
266 };
267
268 static const u32 rv2[] = {
269 /* To improve AL2230 yield, improve phase noise, 4713 */
270 0x25a000,
271 0xa3b2f0,
272
273 0x6da010, /* Reg6 update for MP versio */
274 0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */
275 0x116000,
276 0x9dc020, /* External control TX power (ZD_CR31) */
277 0x5ddb00, /* RegA update for MP version */
278 0xd99000, /* RegB update for MP version */
279 0x3ffbd0, /* RegC update for MP version */
280 0xb00000, /* RegD update for MP version */
281
282 /* improve phase noise and remove phase calibration,4713 */
283 0xf01a00,
284 };
285
286 static const struct zd_ioreq16 ioreqs2[] = {
287 { ZD_CR251, 0x2f }, /* shdnb(PLL_ON)=0 */
288 { ZD_CR251, 0x7f }, /* shdnb(PLL_ON)=1 */
289 };
290
291 static const u32 rv3[] = {
292 /* To improve AL2230 yield, 4713 */
293 0xf01b00,
294 0xf01e00,
295 0xf01a00,
296 };
297
298 static const struct zd_ioreq16 ioreqs3[] = {
299 /* related to 6M band edge patching, happens unconditionally */
300 { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
301 };
302
303 r = zd_iowrite16a_locked(chip, ioreqs: zd1211b_ioreqs_shared_1,
304 ARRAY_SIZE(zd1211b_ioreqs_shared_1));
305 if (r)
306 return r;
307 r = zd_iowrite16a_locked(chip, ioreqs: ioreqs1, ARRAY_SIZE(ioreqs1));
308 if (r)
309 return r;
310
311 if (IS_AL2230S(chip)) {
312 r = zd_iowrite16a_locked(chip, ioreqs: ioreqs_init_al2230s,
313 ARRAY_SIZE(ioreqs_init_al2230s));
314 if (r)
315 return r;
316 }
317
318 r = zd_rfwritev_cr_locked(chip, values: zd1211b_al2230_table[0], count: 3);
319 if (r)
320 return r;
321 r = zd_rfwritev_cr_locked(chip, values: rv1, ARRAY_SIZE(rv1));
322 if (r)
323 return r;
324
325 if (IS_AL2230S(chip))
326 r = zd_rfwrite_locked(chip, value: 0x241000, bits: RF_RV_BITS);
327 else
328 r = zd_rfwrite_locked(chip, value: 0x25a000, bits: RF_RV_BITS);
329 if (r)
330 return r;
331
332 r = zd_rfwritev_cr_locked(chip, values: rv2, ARRAY_SIZE(rv2));
333 if (r)
334 return r;
335 r = zd_iowrite16a_locked(chip, ioreqs: ioreqs2, ARRAY_SIZE(ioreqs2));
336 if (r)
337 return r;
338 r = zd_rfwritev_cr_locked(chip, values: rv3, ARRAY_SIZE(rv3));
339 if (r)
340 return r;
341 r = zd_iowrite16a_locked(chip, ioreqs: ioreqs3, ARRAY_SIZE(ioreqs3));
342 if (r)
343 return r;
344 return zd1211b_al2230_finalize_rf(chip);
345}
346
347static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel)
348{
349 int r;
350 const u32 *rv = zd1211_al2230_table[channel-1];
351 struct zd_chip *chip = zd_rf_to_chip(rf);
352 static const struct zd_ioreq16 ioreqs[] = {
353 { ZD_CR138, 0x28 },
354 { ZD_CR203, 0x06 },
355 };
356
357 r = zd_rfwritev_locked(chip, values: rv, count: 3, bits: RF_RV_BITS);
358 if (r)
359 return r;
360 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
361}
362
363static int zd1211b_al2230_set_channel(struct zd_rf *rf, u8 channel)
364{
365 int r;
366 const u32 *rv = zd1211b_al2230_table[channel-1];
367 struct zd_chip *chip = zd_rf_to_chip(rf);
368
369 r = zd_iowrite16a_locked(chip, ioreqs: zd1211b_ioreqs_shared_1,
370 ARRAY_SIZE(zd1211b_ioreqs_shared_1));
371 if (r)
372 return r;
373
374 r = zd_rfwritev_cr_locked(chip, values: rv, count: 3);
375 if (r)
376 return r;
377
378 return zd1211b_al2230_finalize_rf(chip);
379}
380
381static int zd1211_al2230_switch_radio_on(struct zd_rf *rf)
382{
383 struct zd_chip *chip = zd_rf_to_chip(rf);
384 static const struct zd_ioreq16 ioreqs[] = {
385 { ZD_CR11, 0x00 },
386 { ZD_CR251, 0x3f },
387 };
388
389 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
390}
391
392static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf)
393{
394 struct zd_chip *chip = zd_rf_to_chip(rf);
395 static const struct zd_ioreq16 ioreqs[] = {
396 { ZD_CR11, 0x00 },
397 { ZD_CR251, 0x7f },
398 };
399
400 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
401}
402
403static int al2230_switch_radio_off(struct zd_rf *rf)
404{
405 struct zd_chip *chip = zd_rf_to_chip(rf);
406 static const struct zd_ioreq16 ioreqs[] = {
407 { ZD_CR11, 0x04 },
408 { ZD_CR251, 0x2f },
409 };
410
411 return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
412}
413
414int zd_rf_init_al2230(struct zd_rf *rf)
415{
416 struct zd_chip *chip = zd_rf_to_chip(rf);
417
418 rf->switch_radio_off = al2230_switch_radio_off;
419 if (zd_chip_is_zd1211b(chip)) {
420 rf->init_hw = zd1211b_al2230_init_hw;
421 rf->set_channel = zd1211b_al2230_set_channel;
422 rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
423 } else {
424 rf->init_hw = zd1211_al2230_init_hw;
425 rf->set_channel = zd1211_al2230_set_channel;
426 rf->switch_radio_on = zd1211_al2230_switch_radio_on;
427 }
428 rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
429 rf->patch_cck_gain = 1;
430 return 0;
431}
432

source code of linux/drivers/net/wireless/zydas/zd1211rw/zd_rf_al2230.c