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