1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/delay.h>
20#include <linux/pci.h>
21#include <linux/sched.h>
22#include <linux/slab.h>
23#include <linux/types.h>
24
25#include "b43legacy.h"
26#include "phy.h"
27#include "main.h"
28#include "radio.h"
29#include "ilt.h"
30
31
32static const s8 b43legacy_tssi2dbm_b_table[] = {
33 0x4D, 0x4C, 0x4B, 0x4A,
34 0x4A, 0x49, 0x48, 0x47,
35 0x47, 0x46, 0x45, 0x45,
36 0x44, 0x43, 0x42, 0x42,
37 0x41, 0x40, 0x3F, 0x3E,
38 0x3D, 0x3C, 0x3B, 0x3A,
39 0x39, 0x38, 0x37, 0x36,
40 0x35, 0x34, 0x32, 0x31,
41 0x30, 0x2F, 0x2D, 0x2C,
42 0x2B, 0x29, 0x28, 0x26,
43 0x25, 0x23, 0x21, 0x1F,
44 0x1D, 0x1A, 0x17, 0x14,
45 0x10, 0x0C, 0x06, 0x00,
46 -7, -7, -7, -7,
47 -7, -7, -7, -7,
48 -7, -7, -7, -7,
49};
50
51static const s8 b43legacy_tssi2dbm_g_table[] = {
52 77, 77, 77, 76,
53 76, 76, 75, 75,
54 74, 74, 73, 73,
55 73, 72, 72, 71,
56 71, 70, 70, 69,
57 68, 68, 67, 67,
58 66, 65, 65, 64,
59 63, 63, 62, 61,
60 60, 59, 58, 57,
61 56, 55, 54, 53,
62 52, 50, 49, 47,
63 45, 43, 40, 37,
64 33, 28, 22, 14,
65 5, -7, -20, -20,
66 -20, -20, -20, -20,
67 -20, -20, -20, -20,
68};
69
70static void b43legacy_phy_initg(struct b43legacy_wldev *dev);
71
72
73static inline
74void b43legacy_voluntary_preempt(void)
75{
76 B43legacy_BUG_ON(!(!in_atomic() && !in_irq() &&
77 !in_interrupt() && !irqs_disabled()));
78#ifndef CONFIG_PREEMPT
79 cond_resched();
80#endif
81}
82
83
84
85void b43legacy_phy_lock(struct b43legacy_wldev *dev)
86{
87#if B43legacy_DEBUG
88 B43legacy_WARN_ON(dev->phy.phy_locked);
89 dev->phy.phy_locked = 1;
90#endif
91
92 if (dev->dev->id.revision < 3) {
93 b43legacy_mac_suspend(dev);
94 } else {
95 if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
96 b43legacy_power_saving_ctl_bits(dev, -1, 1);
97 }
98}
99
100void b43legacy_phy_unlock(struct b43legacy_wldev *dev)
101{
102#if B43legacy_DEBUG
103 B43legacy_WARN_ON(!dev->phy.phy_locked);
104 dev->phy.phy_locked = 0;
105#endif
106
107 if (dev->dev->id.revision < 3) {
108 b43legacy_mac_enable(dev);
109 } else {
110 if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
111 b43legacy_power_saving_ctl_bits(dev, -1, -1);
112 }
113}
114
115u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset)
116{
117 b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset);
118 return b43legacy_read16(dev, B43legacy_MMIO_PHY_DATA);
119}
120
121void b43legacy_phy_write(struct b43legacy_wldev *dev, u16 offset, u16 val)
122{
123 b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset);
124 b43legacy_write16(dev, B43legacy_MMIO_PHY_DATA, val);
125}
126
127void b43legacy_phy_calibrate(struct b43legacy_wldev *dev)
128{
129 struct b43legacy_phy *phy = &dev->phy;
130
131 b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
132 if (phy->calibrated)
133 return;
134 if (phy->type == B43legacy_PHYTYPE_G && phy->rev == 1) {
135 b43legacy_wireless_core_reset(dev, 0);
136 b43legacy_phy_initg(dev);
137 b43legacy_wireless_core_reset(dev, B43legacy_TMSLOW_GMODE);
138 }
139 phy->calibrated = 1;
140}
141
142
143
144
145static void b43legacy_phy_init_pctl(struct b43legacy_wldev *dev)
146{
147 struct b43legacy_phy *phy = &dev->phy;
148 u16 saved_batt = 0;
149 u16 saved_ratt = 0;
150 u16 saved_txctl1 = 0;
151 int must_reset_txpower = 0;
152
153 B43legacy_BUG_ON(!(phy->type == B43legacy_PHYTYPE_B ||
154 phy->type == B43legacy_PHYTYPE_G));
155 if (is_bcm_board_vendor(dev) &&
156 (dev->dev->bus->boardinfo.type == 0x0416))
157 return;
158
159 b43legacy_phy_write(dev, 0x0028, 0x8018);
160 b43legacy_write16(dev, 0x03E6, b43legacy_read16(dev, 0x03E6) & 0xFFDF);
161
162 if (phy->type == B43legacy_PHYTYPE_G) {
163 if (!phy->gmode)
164 return;
165 b43legacy_phy_write(dev, 0x047A, 0xC111);
166 }
167 if (phy->savedpctlreg != 0xFFFF)
168 return;
169#ifdef CONFIG_B43LEGACY_DEBUG
170 if (phy->manual_txpower_control)
171 return;
172#endif
173
174 if (phy->type == B43legacy_PHYTYPE_B &&
175 phy->rev >= 2 &&
176 phy->radio_ver == 0x2050)
177 b43legacy_radio_write16(dev, 0x0076,
178 b43legacy_radio_read16(dev, 0x0076)
179 | 0x0084);
180 else {
181 saved_batt = phy->bbatt;
182 saved_ratt = phy->rfatt;
183 saved_txctl1 = phy->txctl1;
184 if ((phy->radio_rev >= 6) && (phy->radio_rev <= 8)
185 && 0)
186 b43legacy_radio_set_txpower_bg(dev, 0xB, 0x1F, 0);
187 else
188 b43legacy_radio_set_txpower_bg(dev, 0xB, 9, 0);
189 must_reset_txpower = 1;
190 }
191 b43legacy_dummy_transmission(dev);
192
193 phy->savedpctlreg = b43legacy_phy_read(dev, B43legacy_PHY_G_PCTL);
194
195 if (must_reset_txpower)
196 b43legacy_radio_set_txpower_bg(dev, saved_batt, saved_ratt,
197 saved_txctl1);
198 else
199 b43legacy_radio_write16(dev, 0x0076, b43legacy_radio_read16(dev,
200 0x0076) & 0xFF7B);
201 b43legacy_radio_clear_tssi(dev);
202}
203
204static void b43legacy_phy_agcsetup(struct b43legacy_wldev *dev)
205{
206 struct b43legacy_phy *phy = &dev->phy;
207 u16 offset = 0x0000;
208
209 if (phy->rev == 1)
210 offset = 0x4C00;
211
212 b43legacy_ilt_write(dev, offset, 0x00FE);
213 b43legacy_ilt_write(dev, offset + 1, 0x000D);
214 b43legacy_ilt_write(dev, offset + 2, 0x0013);
215 b43legacy_ilt_write(dev, offset + 3, 0x0019);
216
217 if (phy->rev == 1) {
218 b43legacy_ilt_write(dev, 0x1800, 0x2710);
219 b43legacy_ilt_write(dev, 0x1801, 0x9B83);
220 b43legacy_ilt_write(dev, 0x1802, 0x9B83);
221 b43legacy_ilt_write(dev, 0x1803, 0x0F8D);
222 b43legacy_phy_write(dev, 0x0455, 0x0004);
223 }
224
225 b43legacy_phy_write(dev, 0x04A5, (b43legacy_phy_read(dev, 0x04A5)
226 & 0x00FF) | 0x5700);
227 b43legacy_phy_write(dev, 0x041A, (b43legacy_phy_read(dev, 0x041A)
228 & 0xFF80) | 0x000F);
229 b43legacy_phy_write(dev, 0x041A, (b43legacy_phy_read(dev, 0x041A)
230 & 0xC07F) | 0x2B80);
231 b43legacy_phy_write(dev, 0x048C, (b43legacy_phy_read(dev, 0x048C)
232 & 0xF0FF) | 0x0300);
233
234 b43legacy_radio_write16(dev, 0x007A,
235 b43legacy_radio_read16(dev, 0x007A)
236 | 0x0008);
237
238 b43legacy_phy_write(dev, 0x04A0, (b43legacy_phy_read(dev, 0x04A0)
239 & 0xFFF0) | 0x0008);
240 b43legacy_phy_write(dev, 0x04A1, (b43legacy_phy_read(dev, 0x04A1)
241 & 0xF0FF) | 0x0600);
242 b43legacy_phy_write(dev, 0x04A2, (b43legacy_phy_read(dev, 0x04A2)
243 & 0xF0FF) | 0x0700);
244 b43legacy_phy_write(dev, 0x04A0, (b43legacy_phy_read(dev, 0x04A0)
245 & 0xF0FF) | 0x0100);
246
247 if (phy->rev == 1)
248 b43legacy_phy_write(dev, 0x04A2,
249 (b43legacy_phy_read(dev, 0x04A2)
250 & 0xFFF0) | 0x0007);
251
252 b43legacy_phy_write(dev, 0x0488, (b43legacy_phy_read(dev, 0x0488)
253 & 0xFF00) | 0x001C);
254 b43legacy_phy_write(dev, 0x0488, (b43legacy_phy_read(dev, 0x0488)
255 & 0xC0FF) | 0x0200);
256 b43legacy_phy_write(dev, 0x0496, (b43legacy_phy_read(dev, 0x0496)
257 & 0xFF00) | 0x001C);
258 b43legacy_phy_write(dev, 0x0489, (b43legacy_phy_read(dev, 0x0489)
259 & 0xFF00) | 0x0020);
260 b43legacy_phy_write(dev, 0x0489, (b43legacy_phy_read(dev, 0x0489)
261 & 0xC0FF) | 0x0200);
262 b43legacy_phy_write(dev, 0x0482, (b43legacy_phy_read(dev, 0x0482)
263 & 0xFF00) | 0x002E);
264 b43legacy_phy_write(dev, 0x0496, (b43legacy_phy_read(dev, 0x0496)
265 & 0x00FF) | 0x1A00);
266 b43legacy_phy_write(dev, 0x0481, (b43legacy_phy_read(dev, 0x0481)
267 & 0xFF00) | 0x0028);
268 b43legacy_phy_write(dev, 0x0481, (b43legacy_phy_read(dev, 0x0481)
269 & 0x00FF) | 0x2C00);
270
271 if (phy->rev == 1) {
272 b43legacy_phy_write(dev, 0x0430, 0x092B);
273 b43legacy_phy_write(dev, 0x041B,
274 (b43legacy_phy_read(dev, 0x041B)
275 & 0xFFE1) | 0x0002);
276 } else {
277 b43legacy_phy_write(dev, 0x041B,
278 b43legacy_phy_read(dev, 0x041B) & 0xFFE1);
279 b43legacy_phy_write(dev, 0x041F, 0x287A);
280 b43legacy_phy_write(dev, 0x0420,
281 (b43legacy_phy_read(dev, 0x0420)
282 & 0xFFF0) | 0x0004);
283 }
284
285 if (phy->rev > 2) {
286 b43legacy_phy_write(dev, 0x0422, 0x287A);
287 b43legacy_phy_write(dev, 0x0420,
288 (b43legacy_phy_read(dev, 0x0420)
289 & 0x0FFF) | 0x3000);
290 }
291
292 b43legacy_phy_write(dev, 0x04A8, (b43legacy_phy_read(dev, 0x04A8)
293 & 0x8080) | 0x7874);
294 b43legacy_phy_write(dev, 0x048E, 0x1C00);
295
296 if (phy->rev == 1) {
297 b43legacy_phy_write(dev, 0x04AB,
298 (b43legacy_phy_read(dev, 0x04AB)
299 & 0xF0FF) | 0x0600);
300 b43legacy_phy_write(dev, 0x048B, 0x005E);
301 b43legacy_phy_write(dev, 0x048C,
302 (b43legacy_phy_read(dev, 0x048C) & 0xFF00)
303 | 0x001E);
304 b43legacy_phy_write(dev, 0x048D, 0x0002);
305 }
306
307 b43legacy_ilt_write(dev, offset + 0x0800, 0);
308 b43legacy_ilt_write(dev, offset + 0x0801, 7);
309 b43legacy_ilt_write(dev, offset + 0x0802, 16);
310 b43legacy_ilt_write(dev, offset + 0x0803, 28);
311
312 if (phy->rev >= 6) {
313 b43legacy_phy_write(dev, 0x0426,
314 (b43legacy_phy_read(dev, 0x0426) & 0xFFFC));
315 b43legacy_phy_write(dev, 0x0426,
316 (b43legacy_phy_read(dev, 0x0426) & 0xEFFF));
317 }
318}
319
320static void b43legacy_phy_setupg(struct b43legacy_wldev *dev)
321{
322 struct b43legacy_phy *phy = &dev->phy;
323 u16 i;
324
325 B43legacy_BUG_ON(phy->type != B43legacy_PHYTYPE_G);
326 if (phy->rev == 1) {
327 b43legacy_phy_write(dev, 0x0406, 0x4F19);
328 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
329 (b43legacy_phy_read(dev,
330 B43legacy_PHY_G_CRS) & 0xFC3F) | 0x0340);
331 b43legacy_phy_write(dev, 0x042C, 0x005A);
332 b43legacy_phy_write(dev, 0x0427, 0x001A);
333
334 for (i = 0; i < B43legacy_ILT_FINEFREQG_SIZE; i++)
335 b43legacy_ilt_write(dev, 0x5800 + i,
336 b43legacy_ilt_finefreqg[i]);
337 for (i = 0; i < B43legacy_ILT_NOISEG1_SIZE; i++)
338 b43legacy_ilt_write(dev, 0x1800 + i,
339 b43legacy_ilt_noiseg1[i]);
340 for (i = 0; i < B43legacy_ILT_ROTOR_SIZE; i++)
341 b43legacy_ilt_write32(dev, 0x2000 + i,
342 b43legacy_ilt_rotor[i]);
343 } else {
344
345 b43legacy_nrssi_hw_write(dev, 0xBA98, (s16)0x7654);
346
347 if (phy->rev == 2) {
348 b43legacy_phy_write(dev, 0x04C0, 0x1861);
349 b43legacy_phy_write(dev, 0x04C1, 0x0271);
350 } else if (phy->rev > 2) {
351 b43legacy_phy_write(dev, 0x04C0, 0x0098);
352 b43legacy_phy_write(dev, 0x04C1, 0x0070);
353 b43legacy_phy_write(dev, 0x04C9, 0x0080);
354 }
355 b43legacy_phy_write(dev, 0x042B, b43legacy_phy_read(dev,
356 0x042B) | 0x800);
357
358 for (i = 0; i < 64; i++)
359 b43legacy_ilt_write(dev, 0x4000 + i, i);
360 for (i = 0; i < B43legacy_ILT_NOISEG2_SIZE; i++)
361 b43legacy_ilt_write(dev, 0x1800 + i,
362 b43legacy_ilt_noiseg2[i]);
363 }
364
365 if (phy->rev <= 2)
366 for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++)
367 b43legacy_ilt_write(dev, 0x1400 + i,
368 b43legacy_ilt_noisescaleg1[i]);
369 else if ((phy->rev >= 7) && (b43legacy_phy_read(dev, 0x0449) & 0x0200))
370 for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++)
371 b43legacy_ilt_write(dev, 0x1400 + i,
372 b43legacy_ilt_noisescaleg3[i]);
373 else
374 for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++)
375 b43legacy_ilt_write(dev, 0x1400 + i,
376 b43legacy_ilt_noisescaleg2[i]);
377
378 if (phy->rev == 2)
379 for (i = 0; i < B43legacy_ILT_SIGMASQR_SIZE; i++)
380 b43legacy_ilt_write(dev, 0x5000 + i,
381 b43legacy_ilt_sigmasqr1[i]);
382 else if ((phy->rev > 2) && (phy->rev <= 8))
383 for (i = 0; i < B43legacy_ILT_SIGMASQR_SIZE; i++)
384 b43legacy_ilt_write(dev, 0x5000 + i,
385 b43legacy_ilt_sigmasqr2[i]);
386
387 if (phy->rev == 1) {
388 for (i = 0; i < B43legacy_ILT_RETARD_SIZE; i++)
389 b43legacy_ilt_write32(dev, 0x2400 + i,
390 b43legacy_ilt_retard[i]);
391 for (i = 4; i < 20; i++)
392 b43legacy_ilt_write(dev, 0x5400 + i, 0x0020);
393 b43legacy_phy_agcsetup(dev);
394
395 if (is_bcm_board_vendor(dev) &&
396 (dev->dev->bus->boardinfo.type == 0x0416) &&
397 (dev->dev->bus->sprom.board_rev == 0x0017))
398 return;
399
400 b43legacy_ilt_write(dev, 0x5001, 0x0002);
401 b43legacy_ilt_write(dev, 0x5002, 0x0001);
402 } else {
403 for (i = 0; i <= 0x20; i++)
404 b43legacy_ilt_write(dev, 0x1000 + i, 0x0820);
405 b43legacy_phy_agcsetup(dev);
406 b43legacy_phy_read(dev, 0x0400);
407 b43legacy_phy_write(dev, 0x0403, 0x1000);
408 b43legacy_ilt_write(dev, 0x3C02, 0x000F);
409 b43legacy_ilt_write(dev, 0x3C03, 0x0014);
410
411 if (is_bcm_board_vendor(dev) &&
412 (dev->dev->bus->boardinfo.type == 0x0416) &&
413 (dev->dev->bus->sprom.board_rev == 0x0017))
414 return;
415
416 b43legacy_ilt_write(dev, 0x0401, 0x0002);
417 b43legacy_ilt_write(dev, 0x0402, 0x0001);
418 }
419}
420
421
422static void b43legacy_phy_inita(struct b43legacy_wldev *dev)
423{
424
425 might_sleep();
426
427 b43legacy_phy_setupg(dev);
428 if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL)
429 b43legacy_phy_write(dev, 0x046E, 0x03CF);
430}
431
432static void b43legacy_phy_initb2(struct b43legacy_wldev *dev)
433{
434 struct b43legacy_phy *phy = &dev->phy;
435 u16 offset;
436 int val;
437
438 b43legacy_write16(dev, 0x03EC, 0x3F22);
439 b43legacy_phy_write(dev, 0x0020, 0x301C);
440 b43legacy_phy_write(dev, 0x0026, 0x0000);
441 b43legacy_phy_write(dev, 0x0030, 0x00C6);
442 b43legacy_phy_write(dev, 0x0088, 0x3E00);
443 val = 0x3C3D;
444 for (offset = 0x0089; offset < 0x00A7; offset++) {
445 b43legacy_phy_write(dev, offset, val);
446 val -= 0x0202;
447 }
448 b43legacy_phy_write(dev, 0x03E4, 0x3000);
449 b43legacy_radio_selectchannel(dev, phy->channel, 0);
450 if (phy->radio_ver != 0x2050) {
451 b43legacy_radio_write16(dev, 0x0075, 0x0080);
452 b43legacy_radio_write16(dev, 0x0079, 0x0081);
453 }
454 b43legacy_radio_write16(dev, 0x0050, 0x0020);
455 b43legacy_radio_write16(dev, 0x0050, 0x0023);
456 if (phy->radio_ver == 0x2050) {
457 b43legacy_radio_write16(dev, 0x0050, 0x0020);
458 b43legacy_radio_write16(dev, 0x005A, 0x0070);
459 b43legacy_radio_write16(dev, 0x005B, 0x007B);
460 b43legacy_radio_write16(dev, 0x005C, 0x00B0);
461 b43legacy_radio_write16(dev, 0x007A, 0x000F);
462 b43legacy_phy_write(dev, 0x0038, 0x0677);
463 b43legacy_radio_init2050(dev);
464 }
465 b43legacy_phy_write(dev, 0x0014, 0x0080);
466 b43legacy_phy_write(dev, 0x0032, 0x00CA);
467 b43legacy_phy_write(dev, 0x0032, 0x00CC);
468 b43legacy_phy_write(dev, 0x0035, 0x07C2);
469 b43legacy_phy_lo_b_measure(dev);
470 b43legacy_phy_write(dev, 0x0026, 0xCC00);
471 if (phy->radio_ver != 0x2050)
472 b43legacy_phy_write(dev, 0x0026, 0xCE00);
473 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x1000);
474 b43legacy_phy_write(dev, 0x002A, 0x88A3);
475 if (phy->radio_ver != 0x2050)
476 b43legacy_phy_write(dev, 0x002A, 0x88C2);
477 b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
478 b43legacy_phy_init_pctl(dev);
479}
480
481static void b43legacy_phy_initb4(struct b43legacy_wldev *dev)
482{
483 struct b43legacy_phy *phy = &dev->phy;
484 u16 offset;
485 u16 val;
486
487 b43legacy_write16(dev, 0x03EC, 0x3F22);
488 b43legacy_phy_write(dev, 0x0020, 0x301C);
489 b43legacy_phy_write(dev, 0x0026, 0x0000);
490 b43legacy_phy_write(dev, 0x0030, 0x00C6);
491 b43legacy_phy_write(dev, 0x0088, 0x3E00);
492 val = 0x3C3D;
493 for (offset = 0x0089; offset < 0x00A7; offset++) {
494 b43legacy_phy_write(dev, offset, val);
495 val -= 0x0202;
496 }
497 b43legacy_phy_write(dev, 0x03E4, 0x3000);
498 b43legacy_radio_selectchannel(dev, phy->channel, 0);
499 if (phy->radio_ver != 0x2050) {
500 b43legacy_radio_write16(dev, 0x0075, 0x0080);
501 b43legacy_radio_write16(dev, 0x0079, 0x0081);
502 }
503 b43legacy_radio_write16(dev, 0x0050, 0x0020);
504 b43legacy_radio_write16(dev, 0x0050, 0x0023);
505 if (phy->radio_ver == 0x2050) {
506 b43legacy_radio_write16(dev, 0x0050, 0x0020);
507 b43legacy_radio_write16(dev, 0x005A, 0x0070);
508 b43legacy_radio_write16(dev, 0x005B, 0x007B);
509 b43legacy_radio_write16(dev, 0x005C, 0x00B0);
510 b43legacy_radio_write16(dev, 0x007A, 0x000F);
511 b43legacy_phy_write(dev, 0x0038, 0x0677);
512 b43legacy_radio_init2050(dev);
513 }
514 b43legacy_phy_write(dev, 0x0014, 0x0080);
515 b43legacy_phy_write(dev, 0x0032, 0x00CA);
516 if (phy->radio_ver == 0x2050)
517 b43legacy_phy_write(dev, 0x0032, 0x00E0);
518 b43legacy_phy_write(dev, 0x0035, 0x07C2);
519
520 b43legacy_phy_lo_b_measure(dev);
521
522 b43legacy_phy_write(dev, 0x0026, 0xCC00);
523 if (phy->radio_ver == 0x2050)
524 b43legacy_phy_write(dev, 0x0026, 0xCE00);
525 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x1100);
526 b43legacy_phy_write(dev, 0x002A, 0x88A3);
527 if (phy->radio_ver == 0x2050)
528 b43legacy_phy_write(dev, 0x002A, 0x88C2);
529 b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
530 if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
531 b43legacy_calc_nrssi_slope(dev);
532 b43legacy_calc_nrssi_threshold(dev);
533 }
534 b43legacy_phy_init_pctl(dev);
535}
536
537static void b43legacy_phy_initb5(struct b43legacy_wldev *dev)
538{
539 struct b43legacy_phy *phy = &dev->phy;
540 u16 offset;
541 u16 value;
542 u8 old_channel;
543
544 if (phy->analog == 1)
545 b43legacy_radio_write16(dev, 0x007A,
546 b43legacy_radio_read16(dev, 0x007A)
547 | 0x0050);
548 if (!is_bcm_board_vendor(dev) &&
549 (dev->dev->bus->boardinfo.type != 0x0416)) {
550 value = 0x2120;
551 for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
552 b43legacy_phy_write(dev, offset, value);
553 value += 0x0202;
554 }
555 }
556 b43legacy_phy_write(dev, 0x0035,
557 (b43legacy_phy_read(dev, 0x0035) & 0xF0FF)
558 | 0x0700);
559 if (phy->radio_ver == 0x2050)
560 b43legacy_phy_write(dev, 0x0038, 0x0667);
561
562 if (phy->gmode) {
563 if (phy->radio_ver == 0x2050) {
564 b43legacy_radio_write16(dev, 0x007A,
565 b43legacy_radio_read16(dev, 0x007A)
566 | 0x0020);
567 b43legacy_radio_write16(dev, 0x0051,
568 b43legacy_radio_read16(dev, 0x0051)
569 | 0x0004);
570 }
571 b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO, 0x0000);
572
573 b43legacy_phy_write(dev, 0x0802, b43legacy_phy_read(dev, 0x0802)
574 | 0x0100);
575 b43legacy_phy_write(dev, 0x042B, b43legacy_phy_read(dev, 0x042B)
576 | 0x2000);
577
578 b43legacy_phy_write(dev, 0x001C, 0x186A);
579
580 b43legacy_phy_write(dev, 0x0013, (b43legacy_phy_read(dev,
581 0x0013) & 0x00FF) | 0x1900);
582 b43legacy_phy_write(dev, 0x0035, (b43legacy_phy_read(dev,
583 0x0035) & 0xFFC0) | 0x0064);
584 b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev,
585 0x005D) & 0xFF80) | 0x000A);
586 b43legacy_phy_write(dev, 0x5B, 0x0000);
587 b43legacy_phy_write(dev, 0x5C, 0x0000);
588 }
589
590 if (dev->bad_frames_preempt)
591 b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
592 b43legacy_phy_read(dev,
593 B43legacy_PHY_RADIO_BITFIELD) | (1 << 12));
594
595 if (phy->analog == 1) {
596 b43legacy_phy_write(dev, 0x0026, 0xCE00);
597 b43legacy_phy_write(dev, 0x0021, 0x3763);
598 b43legacy_phy_write(dev, 0x0022, 0x1BC3);
599 b43legacy_phy_write(dev, 0x0023, 0x06F9);
600 b43legacy_phy_write(dev, 0x0024, 0x037E);
601 } else
602 b43legacy_phy_write(dev, 0x0026, 0xCC00);
603 b43legacy_phy_write(dev, 0x0030, 0x00C6);
604 b43legacy_write16(dev, 0x03EC, 0x3F22);
605
606 if (phy->analog == 1)
607 b43legacy_phy_write(dev, 0x0020, 0x3E1C);
608 else
609 b43legacy_phy_write(dev, 0x0020, 0x301C);
610
611 if (phy->analog == 0)
612 b43legacy_write16(dev, 0x03E4, 0x3000);
613
614 old_channel = (phy->channel == 0xFF) ? 1 : phy->channel;
615
616 b43legacy_radio_selectchannel(dev, 7, 0);
617
618 if (phy->radio_ver != 0x2050) {
619 b43legacy_radio_write16(dev, 0x0075, 0x0080);
620 b43legacy_radio_write16(dev, 0x0079, 0x0081);
621 }
622
623 b43legacy_radio_write16(dev, 0x0050, 0x0020);
624 b43legacy_radio_write16(dev, 0x0050, 0x0023);
625
626 if (phy->radio_ver == 0x2050) {
627 b43legacy_radio_write16(dev, 0x0050, 0x0020);
628 b43legacy_radio_write16(dev, 0x005A, 0x0070);
629 }
630
631 b43legacy_radio_write16(dev, 0x005B, 0x007B);
632 b43legacy_radio_write16(dev, 0x005C, 0x00B0);
633
634 b43legacy_radio_write16(dev, 0x007A, b43legacy_radio_read16(dev,
635 0x007A) | 0x0007);
636
637 b43legacy_radio_selectchannel(dev, old_channel, 0);
638
639 b43legacy_phy_write(dev, 0x0014, 0x0080);
640 b43legacy_phy_write(dev, 0x0032, 0x00CA);
641 b43legacy_phy_write(dev, 0x002A, 0x88A3);
642
643 b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
644
645 if (phy->radio_ver == 0x2050)
646 b43legacy_radio_write16(dev, 0x005D, 0x000D);
647
648 b43legacy_write16(dev, 0x03E4, (b43legacy_read16(dev, 0x03E4) &
649 0xFFC0) | 0x0004);
650}
651
652static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
653{
654 struct b43legacy_phy *phy = &dev->phy;
655 u16 offset;
656 u16 val;
657 u8 old_channel;
658
659 b43legacy_phy_write(dev, 0x003E, 0x817A);
660 b43legacy_radio_write16(dev, 0x007A,
661 (b43legacy_radio_read16(dev, 0x007A) | 0x0058));
662 if (phy->radio_rev == 4 ||
663 phy->radio_rev == 5) {
664 b43legacy_radio_write16(dev, 0x0051, 0x0037);
665 b43legacy_radio_write16(dev, 0x0052, 0x0070);
666 b43legacy_radio_write16(dev, 0x0053, 0x00B3);
667 b43legacy_radio_write16(dev, 0x0054, 0x009B);
668 b43legacy_radio_write16(dev, 0x005A, 0x0088);
669 b43legacy_radio_write16(dev, 0x005B, 0x0088);
670 b43legacy_radio_write16(dev, 0x005D, 0x0088);
671 b43legacy_radio_write16(dev, 0x005E, 0x0088);
672 b43legacy_radio_write16(dev, 0x007D, 0x0088);
673 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
674 B43legacy_UCODEFLAGS_OFFSET,
675 (b43legacy_shm_read32(dev,
676 B43legacy_SHM_SHARED,
677 B43legacy_UCODEFLAGS_OFFSET)
678 | 0x00000200));
679 }
680 if (phy->radio_rev == 8) {
681 b43legacy_radio_write16(dev, 0x0051, 0x0000);
682 b43legacy_radio_write16(dev, 0x0052, 0x0040);
683 b43legacy_radio_write16(dev, 0x0053, 0x00B7);
684 b43legacy_radio_write16(dev, 0x0054, 0x0098);
685 b43legacy_radio_write16(dev, 0x005A, 0x0088);
686 b43legacy_radio_write16(dev, 0x005B, 0x006B);
687 b43legacy_radio_write16(dev, 0x005C, 0x000F);
688 if (dev->dev->bus->sprom.boardflags_lo & 0x8000) {
689 b43legacy_radio_write16(dev, 0x005D, 0x00FA);
690 b43legacy_radio_write16(dev, 0x005E, 0x00D8);
691 } else {
692 b43legacy_radio_write16(dev, 0x005D, 0x00F5);
693 b43legacy_radio_write16(dev, 0x005E, 0x00B8);
694 }
695 b43legacy_radio_write16(dev, 0x0073, 0x0003);
696 b43legacy_radio_write16(dev, 0x007D, 0x00A8);
697 b43legacy_radio_write16(dev, 0x007C, 0x0001);
698 b43legacy_radio_write16(dev, 0x007E, 0x0008);
699 }
700 val = 0x1E1F;
701 for (offset = 0x0088; offset < 0x0098; offset++) {
702 b43legacy_phy_write(dev, offset, val);
703 val -= 0x0202;
704 }
705 val = 0x3E3F;
706 for (offset = 0x0098; offset < 0x00A8; offset++) {
707 b43legacy_phy_write(dev, offset, val);
708 val -= 0x0202;
709 }
710 val = 0x2120;
711 for (offset = 0x00A8; offset < 0x00C8; offset++) {
712 b43legacy_phy_write(dev, offset, (val & 0x3F3F));
713 val += 0x0202;
714 }
715 if (phy->type == B43legacy_PHYTYPE_G) {
716 b43legacy_radio_write16(dev, 0x007A,
717 b43legacy_radio_read16(dev, 0x007A) |
718 0x0020);
719 b43legacy_radio_write16(dev, 0x0051,
720 b43legacy_radio_read16(dev, 0x0051) |
721 0x0004);
722 b43legacy_phy_write(dev, 0x0802,
723 b43legacy_phy_read(dev, 0x0802) | 0x0100);
724 b43legacy_phy_write(dev, 0x042B,
725 b43legacy_phy_read(dev, 0x042B) | 0x2000);
726 b43legacy_phy_write(dev, 0x5B, 0x0000);
727 b43legacy_phy_write(dev, 0x5C, 0x0000);
728 }
729
730 old_channel = phy->channel;
731 if (old_channel >= 8)
732 b43legacy_radio_selectchannel(dev, 1, 0);
733 else
734 b43legacy_radio_selectchannel(dev, 13, 0);
735
736 b43legacy_radio_write16(dev, 0x0050, 0x0020);
737 b43legacy_radio_write16(dev, 0x0050, 0x0023);
738 udelay(40);
739 if (phy->radio_rev < 6 || phy->radio_rev == 8) {
740 b43legacy_radio_write16(dev, 0x007C,
741 (b43legacy_radio_read16(dev, 0x007C)
742 | 0x0002));
743 b43legacy_radio_write16(dev, 0x0050, 0x0020);
744 }
745 if (phy->radio_rev <= 2) {
746 b43legacy_radio_write16(dev, 0x0050, 0x0020);
747 b43legacy_radio_write16(dev, 0x005A, 0x0070);
748 b43legacy_radio_write16(dev, 0x005B, 0x007B);
749 b43legacy_radio_write16(dev, 0x005C, 0x00B0);
750 }
751 b43legacy_radio_write16(dev, 0x007A,
752 (b43legacy_radio_read16(dev,
753 0x007A) & 0x00F8) | 0x0007);
754
755 b43legacy_radio_selectchannel(dev, old_channel, 0);
756
757 b43legacy_phy_write(dev, 0x0014, 0x0200);
758 if (phy->radio_rev >= 6)
759 b43legacy_phy_write(dev, 0x002A, 0x88C2);
760 else
761 b43legacy_phy_write(dev, 0x002A, 0x8AC0);
762 b43legacy_phy_write(dev, 0x0038, 0x0668);
763 b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
764 if (phy->radio_rev == 4 || phy->radio_rev == 5)
765 b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev,
766 0x005D) & 0xFF80) | 0x0003);
767 if (phy->radio_rev <= 2)
768 b43legacy_radio_write16(dev, 0x005D, 0x000D);
769
770 if (phy->analog == 4) {
771 b43legacy_write16(dev, 0x03E4, 0x0009);
772 b43legacy_phy_write(dev, 0x61, b43legacy_phy_read(dev, 0x61)
773 & 0xFFF);
774 } else
775 b43legacy_phy_write(dev, 0x0002, (b43legacy_phy_read(dev,
776 0x0002) & 0xFFC0) | 0x0004);
777 if (phy->type == B43legacy_PHYTYPE_G)
778 b43legacy_write16(dev, 0x03E6, 0x0);
779 if (phy->type == B43legacy_PHYTYPE_B) {
780 b43legacy_write16(dev, 0x03E6, 0x8140);
781 b43legacy_phy_write(dev, 0x0016, 0x0410);
782 b43legacy_phy_write(dev, 0x0017, 0x0820);
783 b43legacy_phy_write(dev, 0x0062, 0x0007);
784 b43legacy_radio_init2050(dev);
785 b43legacy_phy_lo_g_measure(dev);
786 if (dev->dev->bus->sprom.boardflags_lo &
787 B43legacy_BFL_RSSI) {
788 b43legacy_calc_nrssi_slope(dev);
789 b43legacy_calc_nrssi_threshold(dev);
790 }
791 b43legacy_phy_init_pctl(dev);
792 }
793}
794
795static void b43legacy_calc_loopback_gain(struct b43legacy_wldev *dev)
796{
797 struct b43legacy_phy *phy = &dev->phy;
798 u16 backup_phy[15] = {0};
799 u16 backup_radio[3];
800 u16 backup_bband;
801 u16 i;
802 u16 loop1_cnt;
803 u16 loop1_done;
804 u16 loop1_omitted;
805 u16 loop2_done;
806
807 backup_phy[0] = b43legacy_phy_read(dev, 0x0429);
808 backup_phy[1] = b43legacy_phy_read(dev, 0x0001);
809 backup_phy[2] = b43legacy_phy_read(dev, 0x0811);
810 backup_phy[3] = b43legacy_phy_read(dev, 0x0812);
811 if (phy->rev != 1) {
812 backup_phy[4] = b43legacy_phy_read(dev, 0x0814);
813 backup_phy[5] = b43legacy_phy_read(dev, 0x0815);
814 }
815 backup_phy[6] = b43legacy_phy_read(dev, 0x005A);
816 backup_phy[7] = b43legacy_phy_read(dev, 0x0059);
817 backup_phy[8] = b43legacy_phy_read(dev, 0x0058);
818 backup_phy[9] = b43legacy_phy_read(dev, 0x000A);
819 backup_phy[10] = b43legacy_phy_read(dev, 0x0003);
820 backup_phy[11] = b43legacy_phy_read(dev, 0x080F);
821 backup_phy[12] = b43legacy_phy_read(dev, 0x0810);
822 backup_phy[13] = b43legacy_phy_read(dev, 0x002B);
823 backup_phy[14] = b43legacy_phy_read(dev, 0x0015);
824 b43legacy_phy_read(dev, 0x002D);
825 backup_bband = phy->bbatt;
826 backup_radio[0] = b43legacy_radio_read16(dev, 0x0052);
827 backup_radio[1] = b43legacy_radio_read16(dev, 0x0043);
828 backup_radio[2] = b43legacy_radio_read16(dev, 0x007A);
829
830 b43legacy_phy_write(dev, 0x0429,
831 b43legacy_phy_read(dev, 0x0429) & 0x3FFF);
832 b43legacy_phy_write(dev, 0x0001,
833 b43legacy_phy_read(dev, 0x0001) & 0x8000);
834 b43legacy_phy_write(dev, 0x0811,
835 b43legacy_phy_read(dev, 0x0811) | 0x0002);
836 b43legacy_phy_write(dev, 0x0812,
837 b43legacy_phy_read(dev, 0x0812) & 0xFFFD);
838 b43legacy_phy_write(dev, 0x0811,
839 b43legacy_phy_read(dev, 0x0811) | 0x0001);
840 b43legacy_phy_write(dev, 0x0812,
841 b43legacy_phy_read(dev, 0x0812) & 0xFFFE);
842 if (phy->rev != 1) {
843 b43legacy_phy_write(dev, 0x0814,
844 b43legacy_phy_read(dev, 0x0814) | 0x0001);
845 b43legacy_phy_write(dev, 0x0815,
846 b43legacy_phy_read(dev, 0x0815) & 0xFFFE);
847 b43legacy_phy_write(dev, 0x0814,
848 b43legacy_phy_read(dev, 0x0814) | 0x0002);
849 b43legacy_phy_write(dev, 0x0815,
850 b43legacy_phy_read(dev, 0x0815) & 0xFFFD);
851 }
852 b43legacy_phy_write(dev, 0x0811, b43legacy_phy_read(dev, 0x0811) |
853 0x000C);
854 b43legacy_phy_write(dev, 0x0812, b43legacy_phy_read(dev, 0x0812) |
855 0x000C);
856
857 b43legacy_phy_write(dev, 0x0811, (b43legacy_phy_read(dev, 0x0811)
858 & 0xFFCF) | 0x0030);
859 b43legacy_phy_write(dev, 0x0812, (b43legacy_phy_read(dev, 0x0812)
860 & 0xFFCF) | 0x0010);
861
862 b43legacy_phy_write(dev, 0x005A, 0x0780);
863 b43legacy_phy_write(dev, 0x0059, 0xC810);
864 b43legacy_phy_write(dev, 0x0058, 0x000D);
865 if (phy->analog == 0)
866 b43legacy_phy_write(dev, 0x0003, 0x0122);
867 else
868 b43legacy_phy_write(dev, 0x000A,
869 b43legacy_phy_read(dev, 0x000A)
870 | 0x2000);
871 if (phy->rev != 1) {
872 b43legacy_phy_write(dev, 0x0814,
873 b43legacy_phy_read(dev, 0x0814) | 0x0004);
874 b43legacy_phy_write(dev, 0x0815,
875 b43legacy_phy_read(dev, 0x0815) & 0xFFFB);
876 }
877 b43legacy_phy_write(dev, 0x0003,
878 (b43legacy_phy_read(dev, 0x0003)
879 & 0xFF9F) | 0x0040);
880 if (phy->radio_ver == 0x2050 && phy->radio_rev == 2) {
881 b43legacy_radio_write16(dev, 0x0052, 0x0000);
882 b43legacy_radio_write16(dev, 0x0043,
883 (b43legacy_radio_read16(dev, 0x0043)
884 & 0xFFF0) | 0x0009);
885 loop1_cnt = 9;
886 } else if (phy->radio_rev == 8) {
887 b43legacy_radio_write16(dev, 0x0043, 0x000F);
888 loop1_cnt = 15;
889 } else
890 loop1_cnt = 0;
891
892 b43legacy_phy_set_baseband_attenuation(dev, 11);
893
894 if (phy->rev >= 3)
895 b43legacy_phy_write(dev, 0x080F, 0xC020);
896 else
897 b43legacy_phy_write(dev, 0x080F, 0x8020);
898 b43legacy_phy_write(dev, 0x0810, 0x0000);
899
900 b43legacy_phy_write(dev, 0x002B,
901 (b43legacy_phy_read(dev, 0x002B)
902 & 0xFFC0) | 0x0001);
903 b43legacy_phy_write(dev, 0x002B,
904 (b43legacy_phy_read(dev, 0x002B)
905 & 0xC0FF) | 0x0800);
906 b43legacy_phy_write(dev, 0x0811,
907 b43legacy_phy_read(dev, 0x0811) | 0x0100);
908 b43legacy_phy_write(dev, 0x0812,
909 b43legacy_phy_read(dev, 0x0812) & 0xCFFF);
910 if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_EXTLNA) {
911 if (phy->rev >= 7) {
912 b43legacy_phy_write(dev, 0x0811,
913 b43legacy_phy_read(dev, 0x0811)
914 | 0x0800);
915 b43legacy_phy_write(dev, 0x0812,
916 b43legacy_phy_read(dev, 0x0812)
917 | 0x8000);
918 }
919 }
920 b43legacy_radio_write16(dev, 0x007A,
921 b43legacy_radio_read16(dev, 0x007A)
922 & 0x00F7);
923
924 for (i = 0; i < loop1_cnt; i++) {
925 b43legacy_radio_write16(dev, 0x0043, loop1_cnt);
926 b43legacy_phy_write(dev, 0x0812,
927 (b43legacy_phy_read(dev, 0x0812)
928 & 0xF0FF) | (i << 8));
929 b43legacy_phy_write(dev, 0x0015,
930 (b43legacy_phy_read(dev, 0x0015)
931 & 0x0FFF) | 0xA000);
932 b43legacy_phy_write(dev, 0x0015,
933 (b43legacy_phy_read(dev, 0x0015)
934 & 0x0FFF) | 0xF000);
935 udelay(20);
936 if (b43legacy_phy_read(dev, 0x002D) >= 0x0DFC)
937 break;
938 }
939 loop1_done = i;
940 loop1_omitted = loop1_cnt - loop1_done;
941
942 loop2_done = 0;
943 if (loop1_done >= 8) {
944 b43legacy_phy_write(dev, 0x0812,
945 b43legacy_phy_read(dev, 0x0812)
946 | 0x0030);
947 for (i = loop1_done - 8; i < 16; i++) {
948 b43legacy_phy_write(dev, 0x0812,
949 (b43legacy_phy_read(dev, 0x0812)
950 & 0xF0FF) | (i << 8));
951 b43legacy_phy_write(dev, 0x0015,
952 (b43legacy_phy_read(dev, 0x0015)
953 & 0x0FFF) | 0xA000);
954 b43legacy_phy_write(dev, 0x0015,
955 (b43legacy_phy_read(dev, 0x0015)
956 & 0x0FFF) | 0xF000);
957 udelay(20);
958 if (b43legacy_phy_read(dev, 0x002D) >= 0x0DFC)
959 break;
960 }
961 }
962
963 if (phy->rev != 1) {
964 b43legacy_phy_write(dev, 0x0814, backup_phy[4]);
965 b43legacy_phy_write(dev, 0x0815, backup_phy[5]);
966 }
967 b43legacy_phy_write(dev, 0x005A, backup_phy[6]);
968 b43legacy_phy_write(dev, 0x0059, backup_phy[7]);
969 b43legacy_phy_write(dev, 0x0058, backup_phy[8]);
970 b43legacy_phy_write(dev, 0x000A, backup_phy[9]);
971 b43legacy_phy_write(dev, 0x0003, backup_phy[10]);
972 b43legacy_phy_write(dev, 0x080F, backup_phy[11]);
973 b43legacy_phy_write(dev, 0x0810, backup_phy[12]);
974 b43legacy_phy_write(dev, 0x002B, backup_phy[13]);
975 b43legacy_phy_write(dev, 0x0015, backup_phy[14]);
976
977 b43legacy_phy_set_baseband_attenuation(dev, backup_bband);
978
979 b43legacy_radio_write16(dev, 0x0052, backup_radio[0]);
980 b43legacy_radio_write16(dev, 0x0043, backup_radio[1]);
981 b43legacy_radio_write16(dev, 0x007A, backup_radio[2]);
982
983 b43legacy_phy_write(dev, 0x0811, backup_phy[2] | 0x0003);
984 udelay(10);
985 b43legacy_phy_write(dev, 0x0811, backup_phy[2]);
986 b43legacy_phy_write(dev, 0x0812, backup_phy[3]);
987 b43legacy_phy_write(dev, 0x0429, backup_phy[0]);
988 b43legacy_phy_write(dev, 0x0001, backup_phy[1]);
989
990 phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11;
991 phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2;
992}
993
994static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
995{
996 struct b43legacy_phy *phy = &dev->phy;
997 u16 tmp;
998
999 if (phy->rev == 1)
1000 b43legacy_phy_initb5(dev);
1001 else
1002 b43legacy_phy_initb6(dev);
1003 if (phy->rev >= 2 && phy->gmode)
1004 b43legacy_phy_inita(dev);
1005
1006 if (phy->rev >= 2) {
1007 b43legacy_phy_write(dev, 0x0814, 0x0000);
1008 b43legacy_phy_write(dev, 0x0815, 0x0000);
1009 }
1010 if (phy->rev == 2) {
1011 b43legacy_phy_write(dev, 0x0811, 0x0000);
1012 b43legacy_phy_write(dev, 0x0015, 0x00C0);
1013 }
1014 if (phy->rev > 5) {
1015 b43legacy_phy_write(dev, 0x0811, 0x0400);
1016 b43legacy_phy_write(dev, 0x0015, 0x00C0);
1017 }
1018 if (phy->gmode) {
1019 tmp = b43legacy_phy_read(dev, 0x0400) & 0xFF;
1020 if (tmp == 3) {
1021 b43legacy_phy_write(dev, 0x04C2, 0x1816);
1022 b43legacy_phy_write(dev, 0x04C3, 0x8606);
1023 }
1024 if (tmp == 4 || tmp == 5) {
1025 b43legacy_phy_write(dev, 0x04C2, 0x1816);
1026 b43legacy_phy_write(dev, 0x04C3, 0x8006);
1027 b43legacy_phy_write(dev, 0x04CC,
1028 (b43legacy_phy_read(dev,
1029 0x04CC) & 0x00FF) |
1030 0x1F00);
1031 }
1032 if (phy->rev >= 2)
1033 b43legacy_phy_write(dev, 0x047E, 0x0078);
1034 }
1035 if (phy->radio_rev == 8) {
1036 b43legacy_phy_write(dev, 0x0801, b43legacy_phy_read(dev, 0x0801)
1037 | 0x0080);
1038 b43legacy_phy_write(dev, 0x043E, b43legacy_phy_read(dev, 0x043E)
1039 | 0x0004);
1040 }
1041 if (phy->rev >= 2 && phy->gmode)
1042 b43legacy_calc_loopback_gain(dev);
1043 if (phy->radio_rev != 8) {
1044 if (phy->initval == 0xFFFF)
1045 phy->initval = b43legacy_radio_init2050(dev);
1046 else
1047 b43legacy_radio_write16(dev, 0x0078, phy->initval);
1048 }
1049 if (phy->txctl2 == 0xFFFF)
1050 b43legacy_phy_lo_g_measure(dev);
1051 else {
1052 if (phy->radio_ver == 0x2050 && phy->radio_rev == 8)
1053 b43legacy_radio_write16(dev, 0x0052,
1054 (phy->txctl1 << 4) |
1055 phy->txctl2);
1056 else
1057 b43legacy_radio_write16(dev, 0x0052,
1058 (b43legacy_radio_read16(dev,
1059 0x0052) & 0xFFF0) |
1060 phy->txctl1);
1061 if (phy->rev >= 6)
1062 b43legacy_phy_write(dev, 0x0036,
1063 (b43legacy_phy_read(dev, 0x0036)
1064 & 0x0FFF) | (phy->txctl2 << 12));
1065 if (dev->dev->bus->sprom.boardflags_lo &
1066 B43legacy_BFL_PACTRL)
1067 b43legacy_phy_write(dev, 0x002E, 0x8075);
1068 else
1069 b43legacy_phy_write(dev, 0x002E, 0x807F);
1070 if (phy->rev < 2)
1071 b43legacy_phy_write(dev, 0x002F, 0x0101);
1072 else
1073 b43legacy_phy_write(dev, 0x002F, 0x0202);
1074 }
1075 if (phy->gmode) {
1076 b43legacy_phy_lo_adjust(dev, 0);
1077 b43legacy_phy_write(dev, 0x080F, 0x8078);
1078 }
1079
1080 if (!(dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI)) {
1081
1082
1083
1084
1085
1086
1087 b43legacy_nrssi_hw_update(dev, 0xFFFF);
1088 b43legacy_calc_nrssi_threshold(dev);
1089 } else if (phy->gmode || phy->rev >= 2) {
1090 if (phy->nrssi[0] == -1000) {
1091 B43legacy_WARN_ON(phy->nrssi[1] != -1000);
1092 b43legacy_calc_nrssi_slope(dev);
1093 } else {
1094 B43legacy_WARN_ON(phy->nrssi[1] == -1000);
1095 b43legacy_calc_nrssi_threshold(dev);
1096 }
1097 }
1098 if (phy->radio_rev == 8)
1099 b43legacy_phy_write(dev, 0x0805, 0x3230);
1100 b43legacy_phy_init_pctl(dev);
1101 if (dev->dev->bus->chip_id == 0x4306
1102 && dev->dev->bus->chip_package == 2) {
1103 b43legacy_phy_write(dev, 0x0429,
1104 b43legacy_phy_read(dev, 0x0429) & 0xBFFF);
1105 b43legacy_phy_write(dev, 0x04C3,
1106 b43legacy_phy_read(dev, 0x04C3) & 0x7FFF);
1107 }
1108}
1109
1110static u16 b43legacy_phy_lo_b_r15_loop(struct b43legacy_wldev *dev)
1111{
1112 int i;
1113 u16 ret = 0;
1114 unsigned long flags;
1115
1116 local_irq_save(flags);
1117 for (i = 0; i < 10; i++) {
1118 b43legacy_phy_write(dev, 0x0015, 0xAFA0);
1119 udelay(1);
1120 b43legacy_phy_write(dev, 0x0015, 0xEFA0);
1121 udelay(10);
1122 b43legacy_phy_write(dev, 0x0015, 0xFFA0);
1123 udelay(40);
1124 ret += b43legacy_phy_read(dev, 0x002C);
1125 }
1126 local_irq_restore(flags);
1127 b43legacy_voluntary_preempt();
1128
1129 return ret;
1130}
1131
1132void b43legacy_phy_lo_b_measure(struct b43legacy_wldev *dev)
1133{
1134 struct b43legacy_phy *phy = &dev->phy;
1135 u16 regstack[12] = { 0 };
1136 u16 mls;
1137 u16 fval;
1138 int i;
1139 int j;
1140
1141 regstack[0] = b43legacy_phy_read(dev, 0x0015);
1142 regstack[1] = b43legacy_radio_read16(dev, 0x0052) & 0xFFF0;
1143
1144 if (phy->radio_ver == 0x2053) {
1145 regstack[2] = b43legacy_phy_read(dev, 0x000A);
1146 regstack[3] = b43legacy_phy_read(dev, 0x002A);
1147 regstack[4] = b43legacy_phy_read(dev, 0x0035);
1148 regstack[5] = b43legacy_phy_read(dev, 0x0003);
1149 regstack[6] = b43legacy_phy_read(dev, 0x0001);
1150 regstack[7] = b43legacy_phy_read(dev, 0x0030);
1151
1152 regstack[8] = b43legacy_radio_read16(dev, 0x0043);
1153 regstack[9] = b43legacy_radio_read16(dev, 0x007A);
1154 regstack[10] = b43legacy_read16(dev, 0x03EC);
1155 regstack[11] = b43legacy_radio_read16(dev, 0x0052) & 0x00F0;
1156
1157 b43legacy_phy_write(dev, 0x0030, 0x00FF);
1158 b43legacy_write16(dev, 0x03EC, 0x3F3F);
1159 b43legacy_phy_write(dev, 0x0035, regstack[4] & 0xFF7F);
1160 b43legacy_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0);
1161 }
1162 b43legacy_phy_write(dev, 0x0015, 0xB000);
1163 b43legacy_phy_write(dev, 0x002B, 0x0004);
1164
1165 if (phy->radio_ver == 0x2053) {
1166 b43legacy_phy_write(dev, 0x002B, 0x0203);
1167 b43legacy_phy_write(dev, 0x002A, 0x08A3);
1168 }
1169
1170 phy->minlowsig[0] = 0xFFFF;
1171
1172 for (i = 0; i < 4; i++) {
1173 b43legacy_radio_write16(dev, 0x0052, regstack[1] | i);
1174 b43legacy_phy_lo_b_r15_loop(dev);
1175 }
1176 for (i = 0; i < 10; i++) {
1177 b43legacy_radio_write16(dev, 0x0052, regstack[1] | i);
1178 mls = b43legacy_phy_lo_b_r15_loop(dev) / 10;
1179 if (mls < phy->minlowsig[0]) {
1180 phy->minlowsig[0] = mls;
1181 phy->minlowsigpos[0] = i;
1182 }
1183 }
1184 b43legacy_radio_write16(dev, 0x0052, regstack[1]
1185 | phy->minlowsigpos[0]);
1186
1187 phy->minlowsig[1] = 0xFFFF;
1188
1189 for (i = -4; i < 5; i += 2) {
1190 for (j = -4; j < 5; j += 2) {
1191 if (j < 0)
1192 fval = (0x0100 * i) + j + 0x0100;
1193 else
1194 fval = (0x0100 * i) + j;
1195 b43legacy_phy_write(dev, 0x002F, fval);
1196 mls = b43legacy_phy_lo_b_r15_loop(dev) / 10;
1197 if (mls < phy->minlowsig[1]) {
1198 phy->minlowsig[1] = mls;
1199 phy->minlowsigpos[1] = fval;
1200 }
1201 }
1202 }
1203 phy->minlowsigpos[1] += 0x0101;
1204
1205 b43legacy_phy_write(dev, 0x002F, phy->minlowsigpos[1]);
1206 if (phy->radio_ver == 0x2053) {
1207 b43legacy_phy_write(dev, 0x000A, regstack[2]);
1208 b43legacy_phy_write(dev, 0x002A, regstack[3]);
1209 b43legacy_phy_write(dev, 0x0035, regstack[4]);
1210 b43legacy_phy_write(dev, 0x0003, regstack[5]);
1211 b43legacy_phy_write(dev, 0x0001, regstack[6]);
1212 b43legacy_phy_write(dev, 0x0030, regstack[7]);
1213
1214 b43legacy_radio_write16(dev, 0x0043, regstack[8]);
1215 b43legacy_radio_write16(dev, 0x007A, regstack[9]);
1216
1217 b43legacy_radio_write16(dev, 0x0052,
1218 (b43legacy_radio_read16(dev, 0x0052)
1219 & 0x000F) | regstack[11]);
1220
1221 b43legacy_write16(dev, 0x03EC, regstack[10]);
1222 }
1223 b43legacy_phy_write(dev, 0x0015, regstack[0]);
1224}
1225
1226static inline
1227u16 b43legacy_phy_lo_g_deviation_subval(struct b43legacy_wldev *dev,
1228 u16 control)
1229{
1230 struct b43legacy_phy *phy = &dev->phy;
1231 u16 ret;
1232 unsigned long flags;
1233
1234 local_irq_save(flags);
1235 if (phy->gmode) {
1236 b43legacy_phy_write(dev, 0x15, 0xE300);
1237 control <<= 8;
1238 b43legacy_phy_write(dev, 0x0812, control | 0x00B0);
1239 udelay(5);
1240 b43legacy_phy_write(dev, 0x0812, control | 0x00B2);
1241 udelay(2);
1242 b43legacy_phy_write(dev, 0x0812, control | 0x00B3);
1243 udelay(4);
1244 b43legacy_phy_write(dev, 0x0015, 0xF300);
1245 udelay(8);
1246 } else {
1247 b43legacy_phy_write(dev, 0x0015, control | 0xEFA0);
1248 udelay(2);
1249 b43legacy_phy_write(dev, 0x0015, control | 0xEFE0);
1250 udelay(4);
1251 b43legacy_phy_write(dev, 0x0015, control | 0xFFE0);
1252 udelay(8);
1253 }
1254 ret = b43legacy_phy_read(dev, 0x002D);
1255 local_irq_restore(flags);
1256 b43legacy_voluntary_preempt();
1257
1258 return ret;
1259}
1260
1261static u32 b43legacy_phy_lo_g_singledeviation(struct b43legacy_wldev *dev,
1262 u16 control)
1263{
1264 int i;
1265 u32 ret = 0;
1266
1267 for (i = 0; i < 8; i++)
1268 ret += b43legacy_phy_lo_g_deviation_subval(dev, control);
1269
1270 return ret;
1271}
1272
1273
1274static inline
1275void b43legacy_lo_write(struct b43legacy_wldev *dev,
1276 struct b43legacy_lopair *pair)
1277{
1278 u16 value;
1279
1280 value = (u8)(pair->low);
1281 value |= ((u8)(pair->high)) << 8;
1282
1283#ifdef CONFIG_B43LEGACY_DEBUG
1284
1285 if (pair->low < -8 || pair->low > 8 ||
1286 pair->high < -8 || pair->high > 8) {
1287 b43legacydbg(dev->wl,
1288 "WARNING: Writing invalid LOpair "
1289 "(low: %d, high: %d)\n",
1290 pair->low, pair->high);
1291 dump_stack();
1292 }
1293#endif
1294
1295 b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, value);
1296}
1297
1298static inline
1299struct b43legacy_lopair *b43legacy_find_lopair(struct b43legacy_wldev *dev,
1300 u16 bbatt,
1301 u16 rfatt,
1302 u16 tx)
1303{
1304 static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
1305 struct b43legacy_phy *phy = &dev->phy;
1306
1307 if (bbatt > 6)
1308 bbatt = 6;
1309 B43legacy_WARN_ON(rfatt >= 10);
1310
1311 if (tx == 3)
1312 return b43legacy_get_lopair(phy, rfatt, bbatt);
1313 return b43legacy_get_lopair(phy, dict[rfatt], bbatt);
1314}
1315
1316static inline
1317struct b43legacy_lopair *b43legacy_current_lopair(struct b43legacy_wldev *dev)
1318{
1319 struct b43legacy_phy *phy = &dev->phy;
1320
1321 return b43legacy_find_lopair(dev, phy->bbatt,
1322 phy->rfatt, phy->txctl1);
1323}
1324
1325
1326void b43legacy_phy_lo_adjust(struct b43legacy_wldev *dev, int fixed)
1327{
1328 struct b43legacy_lopair *pair;
1329
1330 if (fixed) {
1331
1332 pair = b43legacy_find_lopair(dev, 2, 3, 0);
1333 } else
1334 pair = b43legacy_current_lopair(dev);
1335 b43legacy_lo_write(dev, pair);
1336}
1337
1338static void b43legacy_phy_lo_g_measure_txctl2(struct b43legacy_wldev *dev)
1339{
1340 struct b43legacy_phy *phy = &dev->phy;
1341 u16 txctl2 = 0;
1342 u16 i;
1343 u32 smallest;
1344 u32 tmp;
1345
1346 b43legacy_radio_write16(dev, 0x0052, 0x0000);
1347 udelay(10);
1348 smallest = b43legacy_phy_lo_g_singledeviation(dev, 0);
1349 for (i = 0; i < 16; i++) {
1350 b43legacy_radio_write16(dev, 0x0052, i);
1351 udelay(10);
1352 tmp = b43legacy_phy_lo_g_singledeviation(dev, 0);
1353 if (tmp < smallest) {
1354 smallest = tmp;
1355 txctl2 = i;
1356 }
1357 }
1358 phy->txctl2 = txctl2;
1359}
1360
1361static
1362void b43legacy_phy_lo_g_state(struct b43legacy_wldev *dev,
1363 const struct b43legacy_lopair *in_pair,
1364 struct b43legacy_lopair *out_pair,
1365 u16 r27)
1366{
1367 static const struct b43legacy_lopair transitions[8] = {
1368 { .high = 1, .low = 1, },
1369 { .high = 1, .low = 0, },
1370 { .high = 1, .low = -1, },
1371 { .high = 0, .low = -1, },
1372 { .high = -1, .low = -1, },
1373 { .high = -1, .low = 0, },
1374 { .high = -1, .low = 1, },
1375 { .high = 0, .low = 1, },
1376 };
1377 struct b43legacy_lopair lowest_transition = {
1378 .high = in_pair->high,
1379 .low = in_pair->low,
1380 };
1381 struct b43legacy_lopair tmp_pair;
1382 struct b43legacy_lopair transition;
1383 int i = 12;
1384 int state = 0;
1385 int found_lower;
1386 int j;
1387 int begin;
1388 int end;
1389 u32 lowest_deviation;
1390 u32 tmp;
1391
1392
1393
1394
1395 b43legacy_lo_write(dev, &lowest_transition);
1396 lowest_deviation = b43legacy_phy_lo_g_singledeviation(dev, r27);
1397 do {
1398 found_lower = 0;
1399 B43legacy_WARN_ON(!(state >= 0 && state <= 8));
1400 if (state == 0) {
1401 begin = 1;
1402 end = 8;
1403 } else if (state % 2 == 0) {
1404 begin = state - 1;
1405 end = state + 1;
1406 } else {
1407 begin = state - 2;
1408 end = state + 2;
1409 }
1410 if (begin < 1)
1411 begin += 8;
1412 if (end > 8)
1413 end -= 8;
1414
1415 j = begin;
1416 tmp_pair.high = lowest_transition.high;
1417 tmp_pair.low = lowest_transition.low;
1418 while (1) {
1419 B43legacy_WARN_ON(!(j >= 1 && j <= 8));
1420 transition.high = tmp_pair.high +
1421 transitions[j - 1].high;
1422 transition.low = tmp_pair.low + transitions[j - 1].low;
1423 if ((abs(transition.low) < 9)
1424 && (abs(transition.high) < 9)) {
1425 b43legacy_lo_write(dev, &transition);
1426 tmp = b43legacy_phy_lo_g_singledeviation(dev,
1427 r27);
1428 if (tmp < lowest_deviation) {
1429 lowest_deviation = tmp;
1430 state = j;
1431 found_lower = 1;
1432
1433 lowest_transition.high =
1434 transition.high;
1435 lowest_transition.low = transition.low;
1436 }
1437 }
1438 if (j == end)
1439 break;
1440 if (j == 8)
1441 j = 1;
1442 else
1443 j++;
1444 }
1445 } while (i-- && found_lower);
1446
1447 out_pair->high = lowest_transition.high;
1448 out_pair->low = lowest_transition.low;
1449}
1450
1451
1452void b43legacy_phy_set_baseband_attenuation(struct b43legacy_wldev *dev,
1453 u16 bbatt)
1454{
1455 struct b43legacy_phy *phy = &dev->phy;
1456 u16 value;
1457
1458 if (phy->analog == 0) {
1459 value = (b43legacy_read16(dev, 0x03E6) & 0xFFF0);
1460 value |= (bbatt & 0x000F);
1461 b43legacy_write16(dev, 0x03E6, value);
1462 return;
1463 }
1464
1465 if (phy->analog > 1) {
1466 value = b43legacy_phy_read(dev, 0x0060) & 0xFFC3;
1467 value |= (bbatt << 2) & 0x003C;
1468 } else {
1469 value = b43legacy_phy_read(dev, 0x0060) & 0xFF87;
1470 value |= (bbatt << 3) & 0x0078;
1471 }
1472 b43legacy_phy_write(dev, 0x0060, value);
1473}
1474
1475
1476void b43legacy_phy_lo_g_measure(struct b43legacy_wldev *dev)
1477{
1478 static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
1479 const int is_initializing = (b43legacy_status(dev)
1480 < B43legacy_STAT_STARTED);
1481 struct b43legacy_phy *phy = &dev->phy;
1482 u16 h;
1483 u16 i;
1484 u16 oldi = 0;
1485 u16 j;
1486 struct b43legacy_lopair control;
1487 struct b43legacy_lopair *tmp_control;
1488 u16 tmp;
1489 u16 regstack[16] = { 0 };
1490 u8 oldchannel;
1491
1492
1493 u8 r27 = 0;
1494 u16 r31;
1495
1496 oldchannel = phy->channel;
1497
1498 if (phy->gmode) {
1499 regstack[0] = b43legacy_phy_read(dev, B43legacy_PHY_G_CRS);
1500 regstack[1] = b43legacy_phy_read(dev, 0x0802);
1501 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0]
1502 & 0x7FFF);
1503 b43legacy_phy_write(dev, 0x0802, regstack[1] & 0xFFFC);
1504 }
1505 regstack[3] = b43legacy_read16(dev, 0x03E2);
1506 b43legacy_write16(dev, 0x03E2, regstack[3] | 0x8000);
1507 regstack[4] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT);
1508 regstack[5] = b43legacy_phy_read(dev, 0x15);
1509 regstack[6] = b43legacy_phy_read(dev, 0x2A);
1510 regstack[7] = b43legacy_phy_read(dev, 0x35);
1511 regstack[8] = b43legacy_phy_read(dev, 0x60);
1512 regstack[9] = b43legacy_radio_read16(dev, 0x43);
1513 regstack[10] = b43legacy_radio_read16(dev, 0x7A);
1514 regstack[11] = b43legacy_radio_read16(dev, 0x52);
1515 if (phy->gmode) {
1516 regstack[12] = b43legacy_phy_read(dev, 0x0811);
1517 regstack[13] = b43legacy_phy_read(dev, 0x0812);
1518 regstack[14] = b43legacy_phy_read(dev, 0x0814);
1519 regstack[15] = b43legacy_phy_read(dev, 0x0815);
1520 }
1521 b43legacy_radio_selectchannel(dev, 6, 0);
1522 if (phy->gmode) {
1523 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0]
1524 & 0x7FFF);
1525 b43legacy_phy_write(dev, 0x0802, regstack[1] & 0xFFFC);
1526 b43legacy_dummy_transmission(dev);
1527 }
1528 b43legacy_radio_write16(dev, 0x0043, 0x0006);
1529
1530 b43legacy_phy_set_baseband_attenuation(dev, 2);
1531
1532 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x0000);
1533 b43legacy_phy_write(dev, 0x002E, 0x007F);
1534 b43legacy_phy_write(dev, 0x080F, 0x0078);
1535 b43legacy_phy_write(dev, 0x0035, regstack[7] & ~(1 << 7));
1536 b43legacy_radio_write16(dev, 0x007A, regstack[10] & 0xFFF0);
1537 b43legacy_phy_write(dev, 0x002B, 0x0203);
1538 b43legacy_phy_write(dev, 0x002A, 0x08A3);
1539 if (phy->gmode) {
1540 b43legacy_phy_write(dev, 0x0814, regstack[14] | 0x0003);
1541 b43legacy_phy_write(dev, 0x0815, regstack[15] & 0xFFFC);
1542 b43legacy_phy_write(dev, 0x0811, 0x01B3);
1543 b43legacy_phy_write(dev, 0x0812, 0x00B2);
1544 }
1545 if (is_initializing)
1546 b43legacy_phy_lo_g_measure_txctl2(dev);
1547 b43legacy_phy_write(dev, 0x080F, 0x8078);
1548
1549
1550 control.low = 0;
1551 control.high = 0;
1552 for (h = 0; h < 10; h++) {
1553
1554 i = pairorder[h];
1555 if (is_initializing) {
1556 if (i == 3) {
1557 control.low = 0;
1558 control.high = 0;
1559 } else if (((i % 2 == 1) && (oldi % 2 == 1)) ||
1560 ((i % 2 == 0) && (oldi % 2 == 0))) {
1561 tmp_control = b43legacy_get_lopair(phy, oldi,
1562 0);
1563 memcpy(&control, tmp_control, sizeof(control));
1564 } else {
1565 tmp_control = b43legacy_get_lopair(phy, 3, 0);
1566 memcpy(&control, tmp_control, sizeof(control));
1567 }
1568 }
1569
1570 for (j = 0; j < 4; j++) {
1571 if (is_initializing) {
1572 tmp = i * 2 + j;
1573 r27 = 0;
1574 r31 = 0;
1575 if (tmp > 14) {
1576 r31 = 1;
1577 if (tmp > 17)
1578 r27 = 1;
1579 if (tmp > 19)
1580 r27 = 2;
1581 }
1582 } else {
1583 tmp_control = b43legacy_get_lopair(phy, i,
1584 j * 2);
1585 if (!tmp_control->used)
1586 continue;
1587 memcpy(&control, tmp_control, sizeof(control));
1588 r27 = 3;
1589 r31 = 0;
1590 }
1591 b43legacy_radio_write16(dev, 0x43, i);
1592 b43legacy_radio_write16(dev, 0x52, phy->txctl2);
1593 udelay(10);
1594 b43legacy_voluntary_preempt();
1595
1596 b43legacy_phy_set_baseband_attenuation(dev, j * 2);
1597
1598 tmp = (regstack[10] & 0xFFF0);
1599 if (r31)
1600 tmp |= 0x0008;
1601 b43legacy_radio_write16(dev, 0x007A, tmp);
1602
1603 tmp_control = b43legacy_get_lopair(phy, i, j * 2);
1604 b43legacy_phy_lo_g_state(dev, &control, tmp_control,
1605 r27);
1606 }
1607 oldi = i;
1608 }
1609
1610 for (i = 10; i < 14; i++) {
1611
1612 for (j = 0; j < 4; j++) {
1613 if (is_initializing) {
1614 tmp_control = b43legacy_get_lopair(phy, i - 9,
1615 j * 2);
1616 memcpy(&control, tmp_control, sizeof(control));
1617
1618
1619 tmp = (i - 9) * 2 + j - 5;
1620 r27 = 0;
1621 r31 = 0;
1622 if (tmp > 14) {
1623 r31 = 1;
1624 if (tmp > 17)
1625 r27 = 1;
1626 if (tmp > 19)
1627 r27 = 2;
1628 }
1629 } else {
1630 tmp_control = b43legacy_get_lopair(phy, i - 9,
1631 j * 2);
1632 if (!tmp_control->used)
1633 continue;
1634 memcpy(&control, tmp_control, sizeof(control));
1635 r27 = 3;
1636 r31 = 0;
1637 }
1638 b43legacy_radio_write16(dev, 0x43, i - 9);
1639
1640
1641 b43legacy_radio_write16(dev, 0x52,
1642 phy->txctl2
1643 | (3 << 4));
1644 udelay(10);
1645 b43legacy_voluntary_preempt();
1646
1647 b43legacy_phy_set_baseband_attenuation(dev, j * 2);
1648
1649 tmp = (regstack[10] & 0xFFF0);
1650 if (r31)
1651 tmp |= 0x0008;
1652 b43legacy_radio_write16(dev, 0x7A, tmp);
1653
1654 tmp_control = b43legacy_get_lopair(phy, i, j * 2);
1655 b43legacy_phy_lo_g_state(dev, &control, tmp_control,
1656 r27);
1657 }
1658 }
1659
1660
1661 if (phy->gmode) {
1662 b43legacy_phy_write(dev, 0x0015, 0xE300);
1663 b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA0);
1664 udelay(5);
1665 b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA2);
1666 udelay(2);
1667 b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA3);
1668 b43legacy_voluntary_preempt();
1669 } else
1670 b43legacy_phy_write(dev, 0x0015, r27 | 0xEFA0);
1671 b43legacy_phy_lo_adjust(dev, is_initializing);
1672 b43legacy_phy_write(dev, 0x002E, 0x807F);
1673 if (phy->gmode)
1674 b43legacy_phy_write(dev, 0x002F, 0x0202);
1675 else
1676 b43legacy_phy_write(dev, 0x002F, 0x0101);
1677 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, regstack[4]);
1678 b43legacy_phy_write(dev, 0x0015, regstack[5]);
1679 b43legacy_phy_write(dev, 0x002A, regstack[6]);
1680 b43legacy_phy_write(dev, 0x0035, regstack[7]);
1681 b43legacy_phy_write(dev, 0x0060, regstack[8]);
1682 b43legacy_radio_write16(dev, 0x0043, regstack[9]);
1683 b43legacy_radio_write16(dev, 0x007A, regstack[10]);
1684 regstack[11] &= 0x00F0;
1685 regstack[11] |= (b43legacy_radio_read16(dev, 0x52) & 0x000F);
1686 b43legacy_radio_write16(dev, 0x52, regstack[11]);
1687 b43legacy_write16(dev, 0x03E2, regstack[3]);
1688 if (phy->gmode) {
1689 b43legacy_phy_write(dev, 0x0811, regstack[12]);
1690 b43legacy_phy_write(dev, 0x0812, regstack[13]);
1691 b43legacy_phy_write(dev, 0x0814, regstack[14]);
1692 b43legacy_phy_write(dev, 0x0815, regstack[15]);
1693 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0]);
1694 b43legacy_phy_write(dev, 0x0802, regstack[1]);
1695 }
1696 b43legacy_radio_selectchannel(dev, oldchannel, 1);
1697
1698#ifdef CONFIG_B43LEGACY_DEBUG
1699 {
1700
1701 for (i = 0; i < B43legacy_LO_COUNT; i++) {
1702 tmp_control = phy->_lo_pairs + i;
1703 if (tmp_control->low < -8 || tmp_control->low > 8 ||
1704 tmp_control->high < -8 || tmp_control->high > 8)
1705 b43legacywarn(dev->wl,
1706 "WARNING: Invalid LOpair (low: %d, high:"
1707 " %d, index: %d)\n",
1708 tmp_control->low, tmp_control->high, i);
1709 }
1710 }
1711#endif
1712}
1713
1714static
1715void b43legacy_phy_lo_mark_current_used(struct b43legacy_wldev *dev)
1716{
1717 struct b43legacy_lopair *pair;
1718
1719 pair = b43legacy_current_lopair(dev);
1720 pair->used = 1;
1721}
1722
1723void b43legacy_phy_lo_mark_all_unused(struct b43legacy_wldev *dev)
1724{
1725 struct b43legacy_phy *phy = &dev->phy;
1726 struct b43legacy_lopair *pair;
1727 int i;
1728
1729 for (i = 0; i < B43legacy_LO_COUNT; i++) {
1730 pair = phy->_lo_pairs + i;
1731 pair->used = 0;
1732 }
1733}
1734
1735
1736
1737
1738static s8 b43legacy_phy_estimate_power_out(struct b43legacy_wldev *dev, s8 tssi)
1739{
1740 struct b43legacy_phy *phy = &dev->phy;
1741 s8 dbm = 0;
1742 s32 tmp;
1743
1744 tmp = phy->idle_tssi;
1745 tmp += tssi;
1746 tmp -= phy->savedpctlreg;
1747
1748 switch (phy->type) {
1749 case B43legacy_PHYTYPE_B:
1750 case B43legacy_PHYTYPE_G:
1751 tmp = clamp_val(tmp, 0x00, 0x3F);
1752 dbm = phy->tssi2dbm[tmp];
1753 break;
1754 default:
1755 B43legacy_BUG_ON(1);
1756 }
1757
1758 return dbm;
1759}
1760
1761
1762void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
1763{
1764 struct b43legacy_phy *phy = &dev->phy;
1765 u16 tmp;
1766 u16 txpower;
1767 s8 v0;
1768 s8 v1;
1769 s8 v2;
1770 s8 v3;
1771 s8 average;
1772 int max_pwr;
1773 s16 desired_pwr;
1774 s16 estimated_pwr;
1775 s16 pwr_adjust;
1776 s16 radio_att_delta;
1777 s16 baseband_att_delta;
1778 s16 radio_attenuation;
1779 s16 baseband_attenuation;
1780
1781 if (phy->savedpctlreg == 0xFFFF)
1782 return;
1783 if ((dev->dev->bus->boardinfo.type == 0x0416) &&
1784 is_bcm_board_vendor(dev))
1785 return;
1786#ifdef CONFIG_B43LEGACY_DEBUG
1787 if (phy->manual_txpower_control)
1788 return;
1789#endif
1790
1791 B43legacy_BUG_ON(!(phy->type == B43legacy_PHYTYPE_B ||
1792 phy->type == B43legacy_PHYTYPE_G));
1793 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0058);
1794 v0 = (s8)(tmp & 0x00FF);
1795 v1 = (s8)((tmp & 0xFF00) >> 8);
1796 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x005A);
1797 v2 = (s8)(tmp & 0x00FF);
1798 v3 = (s8)((tmp & 0xFF00) >> 8);
1799 tmp = 0;
1800
1801 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
1802 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
1803 0x0070);
1804 v0 = (s8)(tmp & 0x00FF);
1805 v1 = (s8)((tmp & 0xFF00) >> 8);
1806 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
1807 0x0072);
1808 v2 = (s8)(tmp & 0x00FF);
1809 v3 = (s8)((tmp & 0xFF00) >> 8);
1810 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
1811 return;
1812 v0 = (v0 + 0x20) & 0x3F;
1813 v1 = (v1 + 0x20) & 0x3F;
1814 v2 = (v2 + 0x20) & 0x3F;
1815 v3 = (v3 + 0x20) & 0x3F;
1816 tmp = 1;
1817 }
1818 b43legacy_radio_clear_tssi(dev);
1819
1820 average = (v0 + v1 + v2 + v3 + 2) / 4;
1821
1822 if (tmp && (b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x005E)
1823 & 0x8))
1824 average -= 13;
1825
1826 estimated_pwr = b43legacy_phy_estimate_power_out(dev, average);
1827
1828 max_pwr = dev->dev->bus->sprom.maxpwr_bg;
1829
1830 if ((dev->dev->bus->sprom.boardflags_lo
1831 & B43legacy_BFL_PACTRL) &&
1832 (phy->type == B43legacy_PHYTYPE_G))
1833 max_pwr -= 0x3;
1834 if (unlikely(max_pwr <= 0)) {
1835 b43legacywarn(dev->wl, "Invalid max-TX-power value in SPROM."
1836 "\n");
1837 max_pwr = 74;
1838 dev->dev->bus->sprom.maxpwr_bg = max_pwr;
1839 }
1840
1841
1842
1843
1844
1845
1846
1847#define REG_MAX_PWR 20
1848 max_pwr = min(REG_MAX_PWR * 4
1849 - dev->dev->bus->sprom.antenna_gain.a0
1850 - 0x6, max_pwr);
1851
1852
1853
1854 desired_pwr = clamp_val(phy->power_level << 2, 0, max_pwr);
1855 if (b43legacy_debug(dev, B43legacy_DBG_XMITPOWER))
1856 b43legacydbg(dev->wl, "Current TX power output: " Q52_FMT
1857 " dBm, Desired TX power output: " Q52_FMT
1858 " dBm\n", Q52_ARG(estimated_pwr),
1859 Q52_ARG(desired_pwr));
1860
1861
1862 pwr_adjust = (desired_pwr - estimated_pwr) / 2;
1863
1864
1865 radio_att_delta = -(pwr_adjust + 7) >> 3;
1866
1867 baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta);
1868
1869 if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
1870 b43legacy_phy_lo_mark_current_used(dev);
1871 return;
1872 }
1873
1874
1875 baseband_attenuation = phy->bbatt;
1876 baseband_attenuation += baseband_att_delta;
1877 radio_attenuation = phy->rfatt;
1878 radio_attenuation += radio_att_delta;
1879
1880
1881
1882
1883
1884 if (radio_attenuation < 0) {
1885 baseband_attenuation -= (4 * -radio_attenuation);
1886 radio_attenuation = 0;
1887 } else if (radio_attenuation > 9) {
1888 baseband_attenuation += (4 * (radio_attenuation - 9));
1889 radio_attenuation = 9;
1890 } else {
1891 while (baseband_attenuation < 0 && radio_attenuation > 0) {
1892 baseband_attenuation += 4;
1893 radio_attenuation--;
1894 }
1895 while (baseband_attenuation > 11 && radio_attenuation < 9) {
1896 baseband_attenuation -= 4;
1897 radio_attenuation++;
1898 }
1899 }
1900 baseband_attenuation = clamp_val(baseband_attenuation, 0, 11);
1901
1902 txpower = phy->txctl1;
1903 if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {
1904 if (radio_attenuation <= 1) {
1905 if (txpower == 0) {
1906 txpower = 3;
1907 radio_attenuation += 2;
1908 baseband_attenuation += 2;
1909 } else if (dev->dev->bus->sprom.boardflags_lo
1910 & B43legacy_BFL_PACTRL) {
1911 baseband_attenuation += 4 *
1912 (radio_attenuation - 2);
1913 radio_attenuation = 2;
1914 }
1915 } else if (radio_attenuation > 4 && txpower != 0) {
1916 txpower = 0;
1917 if (baseband_attenuation < 3) {
1918 radio_attenuation -= 3;
1919 baseband_attenuation += 2;
1920 } else {
1921 radio_attenuation -= 2;
1922 baseband_attenuation -= 2;
1923 }
1924 }
1925 }
1926
1927 phy->txctl1 = txpower;
1928 baseband_attenuation = clamp_val(baseband_attenuation, 0, 11);
1929 radio_attenuation = clamp_val(radio_attenuation, 0, 9);
1930 phy->rfatt = radio_attenuation;
1931 phy->bbatt = baseband_attenuation;
1932
1933
1934 b43legacy_phy_lock(dev);
1935 b43legacy_radio_lock(dev);
1936 b43legacy_radio_set_txpower_bg(dev, baseband_attenuation,
1937 radio_attenuation, txpower);
1938 b43legacy_phy_lo_mark_current_used(dev);
1939 b43legacy_radio_unlock(dev);
1940 b43legacy_phy_unlock(dev);
1941}
1942
1943static inline
1944s32 b43legacy_tssi2dbm_ad(s32 num, s32 den)
1945{
1946 if (num < 0)
1947 return num/den;
1948 else
1949 return (num+den/2)/den;
1950}
1951
1952static inline
1953s8 b43legacy_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
1954{
1955 s32 m1;
1956 s32 m2;
1957 s32 f = 256;
1958 s32 q;
1959 s32 delta;
1960 s8 i = 0;
1961
1962 m1 = b43legacy_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
1963 m2 = max(b43legacy_tssi2dbm_ad(32768 + index * pab2, 256), 1);
1964 do {
1965 if (i > 15)
1966 return -EINVAL;
1967 q = b43legacy_tssi2dbm_ad(f * 4096 -
1968 b43legacy_tssi2dbm_ad(m2 * f, 16) *
1969 f, 2048);
1970 delta = abs(q - f);
1971 f = q;
1972 i++;
1973 } while (delta >= 2);
1974 entry[index] = clamp_val(b43legacy_tssi2dbm_ad(m1 * f, 8192),
1975 -127, 128);
1976 return 0;
1977}
1978
1979
1980int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev)
1981{
1982 struct b43legacy_phy *phy = &dev->phy;
1983 s16 pab0;
1984 s16 pab1;
1985 s16 pab2;
1986 u8 idx;
1987 s8 *dyn_tssi2dbm;
1988
1989 B43legacy_WARN_ON(!(phy->type == B43legacy_PHYTYPE_B ||
1990 phy->type == B43legacy_PHYTYPE_G));
1991 pab0 = (s16)(dev->dev->bus->sprom.pa0b0);
1992 pab1 = (s16)(dev->dev->bus->sprom.pa0b1);
1993 pab2 = (s16)(dev->dev->bus->sprom.pa0b2);
1994
1995 if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
1996 phy->idle_tssi = 0x34;
1997 phy->tssi2dbm = b43legacy_tssi2dbm_b_table;
1998 return 0;
1999 }
2000
2001 if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
2002 pab0 != -1 && pab1 != -1 && pab2 != -1) {
2003
2004 if ((s8)dev->dev->bus->sprom.itssi_bg != 0 &&
2005 (s8)dev->dev->bus->sprom.itssi_bg != -1)
2006 phy->idle_tssi = (s8)(dev->dev->bus->sprom.
2007 itssi_bg);
2008 else
2009 phy->idle_tssi = 62;
2010 dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
2011 if (dyn_tssi2dbm == NULL) {
2012 b43legacyerr(dev->wl, "Could not allocate memory "
2013 "for tssi2dbm table\n");
2014 return -ENOMEM;
2015 }
2016 for (idx = 0; idx < 64; idx++)
2017 if (b43legacy_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0,
2018 pab1, pab2)) {
2019 phy->tssi2dbm = NULL;
2020 b43legacyerr(dev->wl, "Could not generate "
2021 "tssi2dBm table\n");
2022 kfree(dyn_tssi2dbm);
2023 return -ENODEV;
2024 }
2025 phy->tssi2dbm = dyn_tssi2dbm;
2026 phy->dyn_tssi_tbl = 1;
2027 } else {
2028
2029 switch (phy->type) {
2030 case B43legacy_PHYTYPE_B:
2031 phy->idle_tssi = 0x34;
2032 phy->tssi2dbm = b43legacy_tssi2dbm_b_table;
2033 break;
2034 case B43legacy_PHYTYPE_G:
2035 phy->idle_tssi = 0x34;
2036 phy->tssi2dbm = b43legacy_tssi2dbm_g_table;
2037 break;
2038 }
2039 }
2040
2041 return 0;
2042}
2043
2044int b43legacy_phy_init(struct b43legacy_wldev *dev)
2045{
2046 struct b43legacy_phy *phy = &dev->phy;
2047 int err = -ENODEV;
2048
2049 switch (phy->type) {
2050 case B43legacy_PHYTYPE_B:
2051 switch (phy->rev) {
2052 case 2:
2053 b43legacy_phy_initb2(dev);
2054 err = 0;
2055 break;
2056 case 4:
2057 b43legacy_phy_initb4(dev);
2058 err = 0;
2059 break;
2060 case 5:
2061 b43legacy_phy_initb5(dev);
2062 err = 0;
2063 break;
2064 case 6:
2065 b43legacy_phy_initb6(dev);
2066 err = 0;
2067 break;
2068 }
2069 break;
2070 case B43legacy_PHYTYPE_G:
2071 b43legacy_phy_initg(dev);
2072 err = 0;
2073 break;
2074 }
2075 if (err)
2076 b43legacyerr(dev->wl, "Unknown PHYTYPE found\n");
2077
2078 return err;
2079}
2080
2081void b43legacy_phy_set_antenna_diversity(struct b43legacy_wldev *dev)
2082{
2083 struct b43legacy_phy *phy = &dev->phy;
2084 u16 antennadiv;
2085 u16 offset;
2086 u16 value;
2087 u32 ucodeflags;
2088
2089 antennadiv = phy->antenna_diversity;
2090
2091 if (antennadiv == 0xFFFF)
2092 antennadiv = 3;
2093 B43legacy_WARN_ON(antennadiv > 3);
2094
2095 ucodeflags = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
2096 B43legacy_UCODEFLAGS_OFFSET);
2097 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
2098 B43legacy_UCODEFLAGS_OFFSET,
2099 ucodeflags & ~B43legacy_UCODEFLAG_AUTODIV);
2100
2101 switch (phy->type) {
2102 case B43legacy_PHYTYPE_G:
2103 offset = 0x0400;
2104
2105 if (antennadiv == 2)
2106 value = (3 << 7);
2107 else
2108 value = (antennadiv << 7);
2109 b43legacy_phy_write(dev, offset + 1,
2110 (b43legacy_phy_read(dev, offset + 1)
2111 & 0x7E7F) | value);
2112
2113 if (antennadiv >= 2) {
2114 if (antennadiv == 2)
2115 value = (antennadiv << 7);
2116 else
2117 value = (0 << 7);
2118 b43legacy_phy_write(dev, offset + 0x2B,
2119 (b43legacy_phy_read(dev,
2120 offset + 0x2B)
2121 & 0xFEFF) | value);
2122 }
2123
2124 if (phy->type == B43legacy_PHYTYPE_G) {
2125 if (antennadiv >= 2)
2126 b43legacy_phy_write(dev, 0x048C,
2127 b43legacy_phy_read(dev,
2128 0x048C) | 0x2000);
2129 else
2130 b43legacy_phy_write(dev, 0x048C,
2131 b43legacy_phy_read(dev,
2132 0x048C) & ~0x2000);
2133 if (phy->rev >= 2) {
2134 b43legacy_phy_write(dev, 0x0461,
2135 b43legacy_phy_read(dev,
2136 0x0461) | 0x0010);
2137 b43legacy_phy_write(dev, 0x04AD,
2138 (b43legacy_phy_read(dev,
2139 0x04AD)
2140 & 0x00FF) | 0x0015);
2141 if (phy->rev == 2)
2142 b43legacy_phy_write(dev, 0x0427,
2143 0x0008);
2144 else
2145 b43legacy_phy_write(dev, 0x0427,
2146 (b43legacy_phy_read(dev, 0x0427)
2147 & 0x00FF) | 0x0008);
2148 } else if (phy->rev >= 6)
2149 b43legacy_phy_write(dev, 0x049B, 0x00DC);
2150 } else {
2151 if (phy->rev < 3)
2152 b43legacy_phy_write(dev, 0x002B,
2153 (b43legacy_phy_read(dev,
2154 0x002B) & 0x00FF)
2155 | 0x0024);
2156 else {
2157 b43legacy_phy_write(dev, 0x0061,
2158 b43legacy_phy_read(dev,
2159 0x0061) | 0x0010);
2160 if (phy->rev == 3) {
2161 b43legacy_phy_write(dev, 0x0093,
2162 0x001D);
2163 b43legacy_phy_write(dev, 0x0027,
2164 0x0008);
2165 } else {
2166 b43legacy_phy_write(dev, 0x0093,
2167 0x003A);
2168 b43legacy_phy_write(dev, 0x0027,
2169 (b43legacy_phy_read(dev, 0x0027)
2170 & 0x00FF) | 0x0008);
2171 }
2172 }
2173 }
2174 break;
2175 case B43legacy_PHYTYPE_B:
2176 if (dev->dev->id.revision == 2)
2177 value = (3 << 7);
2178 else
2179 value = (antennadiv << 7);
2180 b43legacy_phy_write(dev, 0x03E2,
2181 (b43legacy_phy_read(dev, 0x03E2)
2182 & 0xFE7F) | value);
2183 break;
2184 default:
2185 B43legacy_WARN_ON(1);
2186 }
2187
2188 if (antennadiv >= 2) {
2189 ucodeflags = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
2190 B43legacy_UCODEFLAGS_OFFSET);
2191 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
2192 B43legacy_UCODEFLAGS_OFFSET,
2193 ucodeflags | B43legacy_UCODEFLAG_AUTODIV);
2194 }
2195
2196 phy->antenna_diversity = antennadiv;
2197}
2198
2199
2200
2201
2202
2203
2204
2205void b43legacy_power_saving_ctl_bits(struct b43legacy_wldev *dev,
2206 int bit25, int bit26)
2207{
2208 int i;
2209 u32 status;
2210
2211
2212bit25 = 0;
2213bit26 = 1;
2214
2215 if (bit25 == -1) {
2216
2217
2218
2219 }
2220 if (bit26 == -1) {
2221
2222
2223
2224
2225 }
2226 status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
2227 if (bit25)
2228 status |= B43legacy_MACCTL_HWPS;
2229 else
2230 status &= ~B43legacy_MACCTL_HWPS;
2231 if (bit26)
2232 status |= B43legacy_MACCTL_AWAKE;
2233 else
2234 status &= ~B43legacy_MACCTL_AWAKE;
2235 b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
2236 if (bit26 && dev->dev->id.revision >= 5) {
2237 for (i = 0; i < 100; i++) {
2238 if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
2239 0x0040) != 4)
2240 break;
2241 udelay(10);
2242 }
2243 }
2244}
2245