]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bwn/if_bwn_phy_g.c
Merge one true awk from 2024-01-22 for the Awk Second Edition support
[FreeBSD/FreeBSD.git] / sys / dev / bwn / if_bwn_phy_g.c
1 /*-
2  * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29
30 #include <sys/cdefs.h>
31 #include "opt_bwn.h"
32 #include "opt_wlan.h"
33
34 /*
35  * The Broadcom Wireless LAN controller driver.
36  */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/module.h>
43 #include <sys/endian.h>
44 #include <sys/errno.h>
45 #include <sys/firmware.h>
46 #include <sys/lock.h>
47 #include <sys/mutex.h>
48 #include <machine/bus.h>
49 #include <machine/resource.h>
50 #include <sys/bus.h>
51 #include <sys/rman.h>
52 #include <sys/socket.h>
53 #include <sys/sockio.h>
54
55 #include <net/ethernet.h>
56 #include <net/if.h>
57 #include <net/if_var.h>
58 #include <net/if_arp.h>
59 #include <net/if_dl.h>
60 #include <net/if_llc.h>
61 #include <net/if_media.h>
62 #include <net/if_types.h>
63
64 #include <dev/pci/pcivar.h>
65 #include <dev/pci/pcireg.h>
66
67 #include <net80211/ieee80211_var.h>
68 #include <net80211/ieee80211_radiotap.h>
69 #include <net80211/ieee80211_regdomain.h>
70 #include <net80211/ieee80211_phy.h>
71 #include <net80211/ieee80211_ratectl.h>
72
73 #include <dev/bwn/if_bwnreg.h>
74 #include <dev/bwn/if_bwnvar.h>
75
76 #include <dev/bwn/if_bwn_debug.h>
77 #include <dev/bwn/if_bwn_misc.h>
78 #include <dev/bwn/if_bwn_phy_g.h>
79
80 #include "bhnd_nvram_map.h"
81
82 static void     bwn_phy_g_init_sub(struct bwn_mac *);
83 static uint8_t  bwn_has_hwpctl(struct bwn_mac *);
84 static void     bwn_phy_init_b5(struct bwn_mac *);
85 static void     bwn_phy_init_b6(struct bwn_mac *);
86 static void     bwn_phy_init_a(struct bwn_mac *);
87 static void     bwn_loopback_calcgain(struct bwn_mac *);
88 static uint16_t bwn_rf_init_bcm2050(struct bwn_mac *);
89 static void     bwn_lo_g_init(struct bwn_mac *);
90 static void     bwn_lo_g_adjust(struct bwn_mac *);
91 static void     bwn_lo_get_powervector(struct bwn_mac *);
92 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
93                     const struct bwn_bbatt *, const struct bwn_rfatt *);
94 static void     bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
95 static void     bwn_phy_hwpctl_init(struct bwn_mac *);
96 static void     bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
97 static void     bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
98                     const struct bwn_bbatt *, const struct bwn_rfatt *,
99                     uint8_t);
100 static void     bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
101 static uint16_t bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
102 static void     bwn_spu_workaround(struct bwn_mac *, uint8_t);
103 static void     bwn_wa_init(struct bwn_mac *);
104 static void     bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
105                     uint16_t);
106 static void     bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
107                     uint32_t);
108 static void     bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
109                     uint16_t);
110 static int16_t  bwn_nrssi_read(struct bwn_mac *, uint16_t);
111 static void     bwn_nrssi_offset(struct bwn_mac *);
112 static void     bwn_nrssi_threshold(struct bwn_mac *);
113 static void     bwn_nrssi_slope_11g(struct bwn_mac *);
114 static void     bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
115                     int16_t);
116 static void     bwn_set_original_gains(struct bwn_mac *);
117 static void     bwn_hwpctl_early_init(struct bwn_mac *);
118 static void     bwn_hwpctl_init_gphy(struct bwn_mac *);
119 static uint16_t bwn_phy_g_chan2freq(uint8_t);
120 static void     bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
121
122 /* Stuff we need */
123
124 static uint16_t bwn_phy_g_txctl(struct bwn_mac *mac);
125 static int      bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset);
126 static void     bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp);
127 static void     bwn_phy_lock(struct bwn_mac *mac);
128 static void     bwn_phy_unlock(struct bwn_mac *mac);
129 static void     bwn_rf_lock(struct bwn_mac *mac);
130 static void     bwn_rf_unlock(struct bwn_mac *mac);
131
132 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
133 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
134 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
135 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
136 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
137 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
138
139 static uint8_t
140 bwn_has_hwpctl(struct bwn_mac *mac)
141 {
142
143         if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
144                 return (0);
145         return (mac->mac_phy.use_hwpctl(mac));
146 }
147
148 int
149 bwn_phy_g_attach(struct bwn_mac *mac)
150 {
151         struct bwn_softc *sc = mac->mac_sc;
152         struct bwn_phy *phy = &mac->mac_phy;
153         struct bwn_phy_g *pg = &phy->phy_g;
154         unsigned int i;
155         int16_t pab0, pab1, pab2;
156         static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
157         int8_t bg;
158         int error;
159
160         /* Fetch SPROM configuration */
161 #define BWN_PHY_G_READVAR(_dev, _type, _name, _result)          \
162 do {                                                                    \
163         error = bhnd_nvram_getvar_ ##_type((_dev), (_name), (_result)); \
164         if (error) {                                                    \
165                 device_printf((_dev), "NVRAM variable %s unreadable: "  \
166                     "%d\n", (_name), error);                            \
167                 return (error);                                         \
168         }                                                               \
169 } while(0)
170
171         BWN_PHY_G_READVAR(sc->sc_dev, int8, BHND_NVAR_PA0ITSSIT, &bg);
172         BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0B0, &pab0);
173         BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0B1, &pab1);
174         BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0B2, &pab2);
175         BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0MAXPWR,
176             &pg->pg_pa0maxpwr);
177
178 #undef  BWN_PHY_G_READVAR
179
180         pg->pg_flags = 0;
181         if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
182             pab2 == -1) {
183                 pg->pg_idletssi = 52;
184                 pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
185                 return (0);
186         }
187
188         pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
189         pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
190         if (pg->pg_tssi2dbm == NULL) {
191                 device_printf(sc->sc_dev, "failed to allocate buffer\n");
192                 return (ENOMEM);
193         }
194         for (i = 0; i < 64; i++) {
195                 int32_t m1, m2, f, q, delta;
196                 int8_t j = 0;
197
198                 m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
199                 m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
200                 f = 256;
201
202                 do {
203                         if (j > 15) {
204                                 device_printf(sc->sc_dev,
205                                     "failed to generate tssi2dBm\n");
206                                 free(pg->pg_tssi2dbm, M_DEVBUF);
207                                 return (ENOMEM);
208                         }
209                         q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
210                             f, 2048);
211                         delta = abs(q - f);
212                         f = q;
213                         j++;
214                 } while (delta >= 2);
215
216                 pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
217                     127);
218         }
219
220         pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
221         return (0);
222 }
223
224 void
225 bwn_phy_g_detach(struct bwn_mac *mac)
226 {
227         struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
228
229         if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
230                 free(pg->pg_tssi2dbm, M_DEVBUF);
231                 pg->pg_tssi2dbm = NULL;
232         }
233         pg->pg_flags = 0;
234 }
235
236 void
237 bwn_phy_g_init_pre(struct bwn_mac *mac)
238 {
239         struct bwn_phy *phy = &mac->mac_phy;
240         struct bwn_phy_g *pg = &phy->phy_g;
241         void *tssi2dbm;
242         int idletssi;
243         unsigned int i;
244
245         tssi2dbm = pg->pg_tssi2dbm;
246         idletssi = pg->pg_idletssi;
247
248         memset(pg, 0, sizeof(*pg));
249
250         pg->pg_tssi2dbm = tssi2dbm;
251         pg->pg_idletssi = idletssi;
252
253         memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
254
255         for (i = 0; i < N(pg->pg_nrssi); i++)
256                 pg->pg_nrssi[i] = -1000;
257         for (i = 0; i < N(pg->pg_nrssi_lt); i++)
258                 pg->pg_nrssi_lt[i] = i;
259         pg->pg_lofcal = 0xffff;
260         pg->pg_initval = 0xffff;
261         pg->pg_immode = BWN_IMMODE_NONE;
262         pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
263         pg->pg_avgtssi = 0xff;
264
265         pg->pg_loctl.tx_bias = 0xff;
266         TAILQ_INIT(&pg->pg_loctl.calib_list);
267 }
268
269 int
270 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
271 {
272         struct bwn_phy *phy = &mac->mac_phy;
273         struct bwn_phy_g *pg = &phy->phy_g;
274         struct bwn_softc *sc = mac->mac_sc;
275         struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
276         static const struct bwn_rfatt rfatt0[] = {
277                 { 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 }, { 9, 0 }, { 2, 0 },
278                 { 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
279                 { 3, 1 }, { 4, 1 }
280         };
281         static const struct bwn_rfatt rfatt1[] = {
282                 { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
283                 { 14, 1 }
284         };
285         static const struct bwn_rfatt rfatt2[] = {
286                 { 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
287                 { 9, 1 }
288         };
289         static const struct bwn_bbatt bbatt_0[] = {
290                 { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
291         };
292
293         KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
294
295         if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
296                 pg->pg_bbatt.att = 0;
297         else
298                 pg->pg_bbatt.att = 2;
299
300         /* prepare Radio Attenuation */
301         pg->pg_rfatt.padmix = 0;
302
303         if (sc->sc_board_info.board_vendor == PCI_VENDOR_BROADCOM &&
304             sc->sc_board_info.board_type == BHND_BOARD_BCM94309G) {
305                 if (sc->sc_board_info.board_rev < 0x43) {
306                         pg->pg_rfatt.att = 2;
307                         goto done;
308                 } else if (sc->sc_board_info.board_rev < 0x51) {
309                         pg->pg_rfatt.att = 3;
310                         goto done;
311                 }
312         }
313
314         if (phy->type == BWN_PHYTYPE_A) {
315                 pg->pg_rfatt.att = 0x60;
316                 goto done;
317         }
318
319         switch (phy->rf_ver) {
320         case 0x2050:
321                 switch (phy->rf_rev) {
322                 case 0:
323                         pg->pg_rfatt.att = 5;
324                         goto done;
325                 case 1:
326                         if (phy->type == BWN_PHYTYPE_G) {
327                                 if (sc->sc_board_info.board_vendor ==
328                                     PCI_VENDOR_BROADCOM &&
329                                     sc->sc_board_info.board_type ==
330                                     BHND_BOARD_BCM94309G &&
331                                     sc->sc_board_info.board_rev >= 30)
332                                         pg->pg_rfatt.att = 3;
333                                 else if (sc->sc_board_info.board_vendor ==
334                                     PCI_VENDOR_BROADCOM &&
335                                     sc->sc_board_info.board_type ==
336                                     BHND_BOARD_BU4306)
337                                         pg->pg_rfatt.att = 3;
338                                 else
339                                         pg->pg_rfatt.att = 1;
340                         } else {
341                                 if (sc->sc_board_info.board_vendor ==
342                                     PCI_VENDOR_BROADCOM &&
343                                     sc->sc_board_info.board_type ==
344                                     BHND_BOARD_BCM94309G &&
345                                     sc->sc_board_info.board_rev >= 30)
346                                         pg->pg_rfatt.att = 7;
347                                 else
348                                         pg->pg_rfatt.att = 6;
349                         }
350                         goto done;
351                 case 2:
352                         if (phy->type == BWN_PHYTYPE_G) {
353                                 if (sc->sc_board_info.board_vendor ==
354                                     PCI_VENDOR_BROADCOM &&
355                                     sc->sc_board_info.board_type ==
356                                     BHND_BOARD_BCM94309G &&
357                                     sc->sc_board_info.board_rev >= 30)
358                                         pg->pg_rfatt.att = 3;
359                                 else if (sc->sc_board_info.board_vendor ==
360                                     PCI_VENDOR_BROADCOM &&
361                                     sc->sc_board_info.board_type ==
362                                     BHND_BOARD_BU4306)
363                                         pg->pg_rfatt.att = 5;
364                                 else if (sc->sc_cid.chip_id ==
365                                     BHND_CHIPID_BCM4320)
366                                         pg->pg_rfatt.att = 4;
367                                 else
368                                         pg->pg_rfatt.att = 3;
369                         } else
370                                 pg->pg_rfatt.att = 6;
371                         goto done;
372                 case 3:
373                         pg->pg_rfatt.att = 5;
374                         goto done;
375                 case 4:
376                 case 5:
377                         pg->pg_rfatt.att = 1;
378                         goto done;
379                 case 6:
380                 case 7:
381                         pg->pg_rfatt.att = 5;
382                         goto done;
383                 case 8:
384                         pg->pg_rfatt.att = 0xa;
385                         pg->pg_rfatt.padmix = 1;
386                         goto done;
387                 case 9:
388                 default:
389                         pg->pg_rfatt.att = 5;
390                         goto done;
391                 }
392                 break;
393         case 0x2053:
394                 switch (phy->rf_rev) {
395                 case 1:
396                         pg->pg_rfatt.att = 6;
397                         goto done;
398                 }
399                 break;
400         }
401         pg->pg_rfatt.att = 5;
402 done:
403         pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
404
405         if (!bwn_has_hwpctl(mac)) {
406                 lo->rfatt.array = rfatt0;
407                 lo->rfatt.len = N(rfatt0);
408                 lo->rfatt.min = 0;
409                 lo->rfatt.max = 9;
410                 goto genbbatt;
411         }
412         if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
413                 lo->rfatt.array = rfatt1;
414                 lo->rfatt.len = N(rfatt1);
415                 lo->rfatt.min = 0;
416                 lo->rfatt.max = 14;
417                 goto genbbatt;
418         }
419         lo->rfatt.array = rfatt2;
420         lo->rfatt.len = N(rfatt2);
421         lo->rfatt.min = 0;
422         lo->rfatt.max = 9;
423 genbbatt:
424         lo->bbatt.array = bbatt_0;
425         lo->bbatt.len = N(bbatt_0);
426         lo->bbatt.min = 0;
427         lo->bbatt.max = 8;
428
429         BWN_READ_4(mac, BWN_MACCTL);
430         if (phy->rev == 1) {
431                 phy->gmode = 0;
432                 bwn_reset_core(mac, 0);
433                 bwn_phy_g_init_sub(mac);
434                 phy->gmode = 1;
435                 bwn_reset_core(mac, 1);
436         }
437         return (0);
438 }
439
440 static uint16_t
441 bwn_phy_g_txctl(struct bwn_mac *mac)
442 {
443         struct bwn_phy *phy = &mac->mac_phy;
444
445         if (phy->rf_ver != 0x2050)
446                 return (0);
447         if (phy->rf_rev == 1)
448                 return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
449         if (phy->rf_rev < 6)
450                 return (BWN_TXCTL_PA2DB);
451         if (phy->rf_rev == 8)
452                 return (BWN_TXCTL_TXMIX);
453         return (0);
454 }
455
456 int
457 bwn_phy_g_init(struct bwn_mac *mac)
458 {
459
460         bwn_phy_g_init_sub(mac);
461         return (0);
462 }
463
464 void
465 bwn_phy_g_exit(struct bwn_mac *mac)
466 {
467         struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
468         struct bwn_lo_calib *cal, *tmp;
469
470         if (lo == NULL)
471                 return;
472         TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
473                 TAILQ_REMOVE(&lo->calib_list, cal, list);
474                 free(cal, M_DEVBUF);
475         }
476 }
477
478 uint16_t
479 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
480 {
481
482         BWN_WRITE_2(mac, BWN_PHYCTL, reg);
483         return (BWN_READ_2(mac, BWN_PHYDATA));
484 }
485
486 void
487 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
488 {
489
490         BWN_WRITE_2(mac, BWN_PHYCTL, reg);
491         BWN_WRITE_2(mac, BWN_PHYDATA, value);
492 }
493
494 uint16_t
495 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
496 {
497
498         KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
499         BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
500         return (BWN_READ_2(mac, BWN_RFDATALO));
501 }
502
503 void
504 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
505 {
506
507         KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
508         BWN_WRITE_2(mac, BWN_RFCTL, reg);
509         BWN_WRITE_2(mac, BWN_RFDATALO, value);
510 }
511
512 int
513 bwn_phy_g_hwpctl(struct bwn_mac *mac)
514 {
515
516         return (mac->mac_phy.rev >= 6);
517 }
518
519 void
520 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
521 {
522         struct bwn_phy *phy = &mac->mac_phy;
523         struct bwn_phy_g *pg = &phy->phy_g;
524         unsigned int channel;
525         uint16_t rfover, rfoverval;
526
527         if (on) {
528                 if (phy->rf_on)
529                         return;
530
531                 BWN_PHY_WRITE(mac, 0x15, 0x8000);
532                 BWN_PHY_WRITE(mac, 0x15, 0xcc00);
533                 BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
534                 if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
535                         BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
536                             pg->pg_radioctx_over);
537                         BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
538                             pg->pg_radioctx_overval);
539                         pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
540                 }
541                 channel = phy->chan;
542                 bwn_phy_g_switch_chan(mac, 6, 1);
543                 bwn_phy_g_switch_chan(mac, channel, 0);
544                 return;
545         }
546
547         rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
548         rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
549         pg->pg_radioctx_over = rfover;
550         pg->pg_radioctx_overval = rfoverval;
551         pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
552         BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
553         BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
554 }
555
556 int
557 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
558 {
559
560         if ((newchan < 1) || (newchan > 14))
561                 return (EINVAL);
562         bwn_phy_g_switch_chan(mac, newchan, 0);
563
564         return (0);
565 }
566
567 uint32_t
568 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
569 {
570
571         return (1);
572 }
573
574 void
575 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
576 {
577         struct bwn_phy *phy = &mac->mac_phy;
578         uint64_t hf;
579         int autodiv = 0;
580         uint16_t tmp;
581
582         if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
583                 autodiv = 1;
584
585         hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
586         bwn_hf_write(mac, hf);
587
588         BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
589             (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
590             ((autodiv ? BWN_ANTAUTO1 : antenna)
591                 << BWN_PHY_BBANDCFG_RXANT_SHIFT));
592
593         if (autodiv) {
594                 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
595                 if (antenna == BWN_ANTAUTO1)
596                         tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
597                 else
598                         tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
599                 BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
600         }
601         tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
602         if (autodiv)
603                 tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
604         else
605                 tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
606         BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
607         if (phy->rev >= 2) {
608                 BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
609                     BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
610                 BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
611                     (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
612                     0x15);
613                 if (phy->rev == 2)
614                         BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
615                 else
616                         BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
617                             (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
618                             8);
619         }
620         if (phy->rev >= 6)
621                 BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
622
623         hf |= BWN_HF_UCODE_ANTDIV_HELPER;
624         bwn_hf_write(mac, hf);
625 }
626
627 int
628 bwn_phy_g_im(struct bwn_mac *mac, int mode)
629 {
630         struct bwn_phy *phy = &mac->mac_phy;
631         struct bwn_phy_g *pg = &phy->phy_g;
632
633         KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
634         KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
635
636         if (phy->rev == 0 || !phy->gmode)
637                 return (ENODEV);
638
639         pg->pg_aci_wlan_automatic = 0;
640         return (0);
641 }
642
643 bwn_txpwr_result_t
644 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
645 {
646         struct bwn_phy *phy = &mac->mac_phy;
647         struct bwn_phy_g *pg = &phy->phy_g;
648         struct bwn_softc *sc = mac->mac_sc;
649         unsigned int tssi;
650         int cck, ofdm;
651         int power;
652         int rfatt, bbatt;
653         unsigned int max;
654
655         KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
656
657         cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
658         ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
659         if (cck < 0 && ofdm < 0) {
660                 if (ignore_tssi == 0)
661                         return (BWN_TXPWR_RES_DONE);
662                 cck = 0;
663                 ofdm = 0;
664         }
665         tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
666         if (pg->pg_avgtssi != 0xff)
667                 tssi = (tssi + pg->pg_avgtssi) / 2;
668         pg->pg_avgtssi = tssi;
669         KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
670
671         max = pg->pg_pa0maxpwr;
672         if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL)
673                 max -= 3;
674         if (max >= 120) {
675                 device_printf(sc->sc_dev, "invalid max TX-power value\n");
676                 max = 80;
677                 pg->pg_pa0maxpwr = max;
678         }
679
680         power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
681             (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
682              tssi, 0x00), 0x3f)]);
683         if (power == 0)
684                 return (BWN_TXPWR_RES_DONE);
685
686         rfatt = -((power + 7) / 8);
687         bbatt = (-(power / 2)) - (4 * rfatt);
688         if ((rfatt == 0) && (bbatt == 0))
689                 return (BWN_TXPWR_RES_DONE);
690         pg->pg_bbatt_delta = bbatt;
691         pg->pg_rfatt_delta = rfatt;
692         return (BWN_TXPWR_RES_NEED_ADJUST);
693 }
694
695 void
696 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
697 {
698         struct bwn_phy *phy = &mac->mac_phy;
699         struct bwn_phy_g *pg = &phy->phy_g;
700         struct bwn_softc *sc = mac->mac_sc;
701         int rfatt, bbatt;
702         uint8_t txctl;
703
704         bwn_mac_suspend(mac);
705
706         BWN_ASSERT_LOCKED(sc);
707
708         bbatt = pg->pg_bbatt.att;
709         bbatt += pg->pg_bbatt_delta;
710         rfatt = pg->pg_rfatt.att;
711         rfatt += pg->pg_rfatt_delta;
712
713         bwn_phy_g_setatt(mac, &bbatt, &rfatt);
714         txctl = pg->pg_txctl;
715         if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
716                 if (rfatt <= 1) {
717                         if (txctl == 0) {
718                                 txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
719                                 rfatt += 2;
720                                 bbatt += 2;
721                         } else if (sc->sc_board_info.board_flags &
722                             BHND_BFL_PACTRL) {
723                                 bbatt += 4 * (rfatt - 2);
724                                 rfatt = 2;
725                         }
726                 } else if (rfatt > 4 && txctl) {
727                         txctl = 0;
728                         if (bbatt < 3) {
729                                 rfatt -= 3;
730                                 bbatt += 2;
731                         } else {
732                                 rfatt -= 2;
733                                 bbatt -= 2;
734                         }
735                 }
736         }
737         pg->pg_txctl = txctl;
738         bwn_phy_g_setatt(mac, &bbatt, &rfatt);
739         pg->pg_rfatt.att = rfatt;
740         pg->pg_bbatt.att = bbatt;
741
742         DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
743
744         bwn_phy_lock(mac);
745         bwn_rf_lock(mac);
746         bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
747             pg->pg_txctl);
748         bwn_rf_unlock(mac);
749         bwn_phy_unlock(mac);
750
751         bwn_mac_enable(mac);
752 }
753
754 void
755 bwn_phy_g_task_15s(struct bwn_mac *mac)
756 {
757         struct bwn_phy *phy = &mac->mac_phy;
758         struct bwn_phy_g *pg = &phy->phy_g;
759         struct bwn_softc *sc = mac->mac_sc;
760         struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
761         unsigned long expire, now;
762         struct bwn_lo_calib *cal, *tmp;
763         uint8_t expired = 0;
764
765         bwn_mac_suspend(mac);
766
767         if (lo == NULL)
768                 goto fail;
769
770         BWN_GETTIME(now);
771         if (bwn_has_hwpctl(mac)) {
772                 expire = now - BWN_LO_PWRVEC_EXPIRE;
773                 if (ieee80211_time_before(lo->pwr_vec_read_time, expire)) {
774                         bwn_lo_get_powervector(mac);
775                         bwn_phy_g_dc_lookup_init(mac, 0);
776                 }
777                 goto fail;
778         }
779
780         expire = now - BWN_LO_CALIB_EXPIRE;
781         TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
782                 if (!ieee80211_time_before(cal->calib_time, expire))
783                         continue;
784                 if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
785                     BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
786                         KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
787                         expired = 1;
788                 }
789
790                 DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
791                     cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
792                     cal->ctl.i, cal->ctl.q);
793
794                 TAILQ_REMOVE(&lo->calib_list, cal, list);
795                 free(cal, M_DEVBUF);
796         }
797         if (expired || TAILQ_EMPTY(&lo->calib_list)) {
798                 cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
799                     &pg->pg_rfatt);
800                 if (cal == NULL) {
801                         device_printf(sc->sc_dev,
802                             "failed to recalibrate LO\n");
803                         goto fail;
804                 }
805                 TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
806                 bwn_lo_write(mac, &cal->ctl);
807         }
808
809 fail:
810         bwn_mac_enable(mac);
811 }
812
813 void
814 bwn_phy_g_task_60s(struct bwn_mac *mac)
815 {
816         struct bwn_phy *phy = &mac->mac_phy;
817         struct bwn_softc *sc = mac->mac_sc;
818         uint8_t old = phy->chan;
819
820         if (!(sc->sc_board_info.board_flags & BHND_BFL_ADCDIV))
821                 return;
822
823         bwn_mac_suspend(mac);
824         bwn_nrssi_slope_11g(mac);
825         if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
826                 bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
827                 bwn_switch_channel(mac, old);
828         }
829         bwn_mac_enable(mac);
830 }
831
832 void
833 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
834 {
835
836         BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
837 }
838
839 static void
840 bwn_phy_g_init_sub(struct bwn_mac *mac)
841 {
842         struct bwn_phy *phy = &mac->mac_phy;
843         struct bwn_phy_g *pg = &phy->phy_g;
844         struct bwn_softc *sc = mac->mac_sc;
845         uint16_t i, tmp;
846
847         if (phy->rev == 1)
848                 bwn_phy_init_b5(mac);
849         else
850                 bwn_phy_init_b6(mac);
851
852         if (phy->rev >= 2 || phy->gmode)
853                 bwn_phy_init_a(mac);
854
855         if (phy->rev >= 2) {
856                 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
857                 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
858         }
859         if (phy->rev == 2) {
860                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
861                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
862         }
863         if (phy->rev > 5) {
864                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
865                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
866         }
867         if (phy->gmode || phy->rev >= 2) {
868                 tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
869                 tmp &= BWN_PHYVER_VERSION;
870                 if (tmp == 3 || tmp == 5) {
871                         BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
872                         BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
873                 }
874                 if (tmp == 5) {
875                         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
876                             0x1f00);
877                 }
878         }
879         if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
880                 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
881         if (phy->rf_rev == 8) {
882                 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
883                 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
884         }
885         if (BWN_HAS_LOOPBACK(phy))
886                 bwn_loopback_calcgain(mac);
887
888         if (phy->rf_rev != 8) {
889                 if (pg->pg_initval == 0xffff)
890                         pg->pg_initval = bwn_rf_init_bcm2050(mac);
891                 else
892                         BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
893         }
894         bwn_lo_g_init(mac);
895         if (BWN_HAS_TXMAG(phy)) {
896                 BWN_RF_WRITE(mac, 0x52,
897                     (BWN_RF_READ(mac, 0x52) & 0xff00)
898                     | pg->pg_loctl.tx_bias |
899                     pg->pg_loctl.tx_magn);
900         } else {
901                 BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
902         }
903         if (phy->rev >= 6) {
904                 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
905                     (pg->pg_loctl.tx_bias << 12));
906         }
907         if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL)
908                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
909         else
910                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
911         if (phy->rev < 2)
912                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
913         else
914                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
915         if (phy->gmode || phy->rev >= 2) {
916                 bwn_lo_g_adjust(mac);
917                 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
918         }
919
920         if (!(sc->sc_board_info.board_flags & BHND_BFL_ADCDIV)) {
921                 for (i = 0; i < 64; i++) {
922                         BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
923                         BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
924                             (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
925                             -32), 31));
926                 }
927                 bwn_nrssi_threshold(mac);
928         } else if (phy->gmode || phy->rev >= 2) {
929                 if (pg->pg_nrssi[0] == -1000) {
930                         KASSERT(pg->pg_nrssi[1] == -1000,
931                             ("%s:%d: fail", __func__, __LINE__));
932                         bwn_nrssi_slope_11g(mac);
933                 } else
934                         bwn_nrssi_threshold(mac);
935         }
936         if (phy->rf_rev == 8)
937                 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
938         bwn_phy_hwpctl_init(mac);
939         if ((sc->sc_cid.chip_id == BHND_CHIPID_BCM4306
940              && sc->sc_cid.chip_pkg == 2) || 0) {
941                 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
942                 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
943         }
944 }
945
946 static void
947 bwn_phy_init_b5(struct bwn_mac *mac)
948 {
949         struct bwn_phy *phy = &mac->mac_phy;
950         struct bwn_phy_g *pg = &phy->phy_g;
951         struct bwn_softc *sc = mac->mac_sc;
952         uint16_t offset, value;
953         uint8_t old_channel;
954
955         if (phy->analog == 1)
956                 BWN_RF_SET(mac, 0x007a, 0x0050);
957         if ((sc->sc_board_info.board_vendor != PCI_VENDOR_BROADCOM) &&
958             (sc->sc_board_info.board_type != BHND_BOARD_BU4306)) {
959                 value = 0x2120;
960                 for (offset = 0x00a8; offset < 0x00c7; offset++) {
961                         BWN_PHY_WRITE(mac, offset, value);
962                         value += 0x202;
963                 }
964         }
965         BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
966         if (phy->rf_ver == 0x2050)
967                 BWN_PHY_WRITE(mac, 0x0038, 0x0667);
968
969         if (phy->gmode || phy->rev >= 2) {
970                 if (phy->rf_ver == 0x2050) {
971                         BWN_RF_SET(mac, 0x007a, 0x0020);
972                         BWN_RF_SET(mac, 0x0051, 0x0004);
973                 }
974                 BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
975
976                 BWN_PHY_SET(mac, 0x0802, 0x0100);
977                 BWN_PHY_SET(mac, 0x042b, 0x2000);
978
979                 BWN_PHY_WRITE(mac, 0x001c, 0x186a);
980
981                 BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
982                 BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
983                 BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
984         }
985
986         if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
987                 BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
988
989         if (phy->analog == 1) {
990                 BWN_PHY_WRITE(mac, 0x0026, 0xce00);
991                 BWN_PHY_WRITE(mac, 0x0021, 0x3763);
992                 BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
993                 BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
994                 BWN_PHY_WRITE(mac, 0x0024, 0x037e);
995         } else
996                 BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
997         BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
998         BWN_WRITE_2(mac, 0x03ec, 0x3f22);
999
1000         if (phy->analog == 1)
1001                 BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
1002         else
1003                 BWN_PHY_WRITE(mac, 0x0020, 0x301c);
1004
1005         if (phy->analog == 0)
1006                 BWN_WRITE_2(mac, 0x03e4, 0x3000);
1007
1008         old_channel = phy->chan;
1009         bwn_phy_g_switch_chan(mac, 7, 0);
1010
1011         if (phy->rf_ver != 0x2050) {
1012                 BWN_RF_WRITE(mac, 0x0075, 0x0080);
1013                 BWN_RF_WRITE(mac, 0x0079, 0x0081);
1014         }
1015
1016         BWN_RF_WRITE(mac, 0x0050, 0x0020);
1017         BWN_RF_WRITE(mac, 0x0050, 0x0023);
1018
1019         if (phy->rf_ver == 0x2050) {
1020                 BWN_RF_WRITE(mac, 0x0050, 0x0020);
1021                 BWN_RF_WRITE(mac, 0x005a, 0x0070);
1022         }
1023
1024         BWN_RF_WRITE(mac, 0x005b, 0x007b);
1025         BWN_RF_WRITE(mac, 0x005c, 0x00b0);
1026         BWN_RF_SET(mac, 0x007a, 0x0007);
1027
1028         bwn_phy_g_switch_chan(mac, old_channel, 0);
1029         BWN_PHY_WRITE(mac, 0x0014, 0x0080);
1030         BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
1031         BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
1032
1033         bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
1034             pg->pg_txctl);
1035
1036         if (phy->rf_ver == 0x2050)
1037                 BWN_RF_WRITE(mac, 0x005d, 0x000d);
1038
1039         BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
1040 }
1041
1042 static void
1043 bwn_loopback_calcgain(struct bwn_mac *mac)
1044 {
1045         struct bwn_phy *phy = &mac->mac_phy;
1046         struct bwn_phy_g *pg = &phy->phy_g;
1047         struct bwn_softc *sc = mac->mac_sc;
1048         uint16_t backup_phy[16] = { 0 };
1049         uint16_t backup_radio[3];
1050         uint16_t backup_bband;
1051         uint16_t i, j, loop_i_max;
1052         uint16_t trsw_rx;
1053         uint16_t loop1_outer_done, loop1_inner_done;
1054
1055         backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
1056         backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
1057         backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
1058         backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
1059         if (phy->rev != 1) {
1060                 backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
1061                 backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
1062         }
1063         backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
1064         backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
1065         backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
1066         backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
1067         backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
1068         backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
1069         backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
1070         backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
1071         backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
1072         backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1073         backup_bband = pg->pg_bbatt.att;
1074         backup_radio[0] = BWN_RF_READ(mac, 0x52);
1075         backup_radio[1] = BWN_RF_READ(mac, 0x43);
1076         backup_radio[2] = BWN_RF_READ(mac, 0x7a);
1077
1078         BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
1079         BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
1080         BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
1081         BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
1082         BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
1083         BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
1084         if (phy->rev != 1) {
1085                 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
1086                 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
1087                 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
1088                 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
1089         }
1090         BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
1091         BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
1092         BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
1093         BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
1094
1095         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
1096         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
1097         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
1098
1099         BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
1100         if (phy->rev != 1) {
1101                 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
1102                 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
1103         }
1104         BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
1105
1106         if (phy->rf_rev == 8)
1107                 BWN_RF_WRITE(mac, 0x43, 0x000f);
1108         else {
1109                 BWN_RF_WRITE(mac, 0x52, 0);
1110                 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
1111         }
1112         bwn_phy_g_set_bbatt(mac, 11);
1113
1114         if (phy->rev >= 3)
1115                 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
1116         else
1117                 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
1118         BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
1119
1120         BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
1121         BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
1122
1123         BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
1124         BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
1125
1126         if (sc->sc_board_info.board_flags & BHND_BFL_EXTLNA) {
1127                 if (phy->rev >= 7) {
1128                         BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
1129                         BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
1130                 }
1131         }
1132         BWN_RF_MASK(mac, 0x7a, 0x00f7);
1133
1134         j = 0;
1135         loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
1136         for (i = 0; i < loop_i_max; i++) {
1137                 for (j = 0; j < 16; j++) {
1138                         BWN_RF_WRITE(mac, 0x43, i);
1139                         BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
1140                             (j << 8));
1141                         BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
1142                         BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
1143                         DELAY(20);
1144                         if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
1145                                 goto done0;
1146                 }
1147         }
1148 done0:
1149         loop1_outer_done = i;
1150         loop1_inner_done = j;
1151         if (j >= 8) {
1152                 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
1153                 trsw_rx = 0x1b;
1154                 for (j = j - 8; j < 16; j++) {
1155                         BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
1156                         BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
1157                         BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
1158                         DELAY(20);
1159                         trsw_rx -= 3;
1160                         if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
1161                                 goto done1;
1162                 }
1163         } else
1164                 trsw_rx = 0x18;
1165 done1:
1166
1167         if (phy->rev != 1) {
1168                 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
1169                 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
1170         }
1171         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
1172         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
1173         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
1174         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
1175         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
1176         BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
1177         BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
1178         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
1179         BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
1180
1181         bwn_phy_g_set_bbatt(mac, backup_bband);
1182
1183         BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
1184         BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
1185         BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
1186
1187         BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
1188         DELAY(10);
1189         BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
1190         BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
1191         BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
1192         BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
1193
1194         pg->pg_max_lb_gain =
1195             ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
1196         pg->pg_trsw_rx_gain = trsw_rx * 2;
1197 }
1198
1199 static uint16_t
1200 bwn_rf_init_bcm2050(struct bwn_mac *mac)
1201 {
1202         struct bwn_phy *phy = &mac->mac_phy;
1203         uint32_t tmp1 = 0, tmp2 = 0;
1204         uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
1205             analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
1206             radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
1207         static const uint8_t rcc_table[] = {
1208                 0x02, 0x03, 0x01, 0x0f,
1209                 0x06, 0x07, 0x05, 0x0f,
1210                 0x0a, 0x0b, 0x09, 0x0f,
1211                 0x0e, 0x0f, 0x0d, 0x0f,
1212         };
1213
1214         loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
1215             rfoverval = rfover = cck3 = 0;
1216         radio0 = BWN_RF_READ(mac, 0x43);
1217         radio1 = BWN_RF_READ(mac, 0x51);
1218         radio2 = BWN_RF_READ(mac, 0x52);
1219         pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
1220         cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
1221         cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
1222         cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
1223
1224         if (phy->type == BWN_PHYTYPE_B) {
1225                 cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
1226                 reg0 = BWN_READ_2(mac, 0x3ec);
1227
1228                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
1229                 BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
1230         } else if (phy->gmode || phy->rev >= 2) {
1231                 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
1232                 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
1233                 analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
1234                 analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
1235                 crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
1236                 classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
1237
1238                 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
1239                 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
1240                 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
1241                 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
1242                 if (BWN_HAS_LOOPBACK(phy)) {
1243                         lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
1244                         loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
1245                         if (phy->rev >= 3)
1246                                 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
1247                         else
1248                                 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
1249                         BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
1250                 }
1251
1252                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1253                     bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
1254                         BWN_LPD(0, 1, 1)));
1255                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
1256                     bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
1257         }
1258         BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
1259
1260         syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
1261         BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
1262         reg1 = BWN_READ_2(mac, 0x3e6);
1263         reg2 = BWN_READ_2(mac, 0x3f4);
1264
1265         if (phy->analog == 0)
1266                 BWN_WRITE_2(mac, 0x03e6, 0x0122);
1267         else {
1268                 if (phy->analog >= 2)
1269                         BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
1270                 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
1271                     (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
1272         }
1273
1274         reg = BWN_RF_READ(mac, 0x60);
1275         index = (reg & 0x001e) >> 1;
1276         rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
1277
1278         if (phy->type == BWN_PHYTYPE_B)
1279                 BWN_RF_WRITE(mac, 0x78, 0x26);
1280         if (phy->gmode || phy->rev >= 2) {
1281                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1282                     bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
1283                         BWN_LPD(0, 1, 1)));
1284         }
1285         BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
1286         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
1287         if (phy->gmode || phy->rev >= 2) {
1288                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1289                     bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
1290                         BWN_LPD(0, 0, 1)));
1291         }
1292         BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
1293         BWN_RF_SET(mac, 0x51, 0x0004);
1294         if (phy->rf_rev == 8)
1295                 BWN_RF_WRITE(mac, 0x43, 0x1f);
1296         else {
1297                 BWN_RF_WRITE(mac, 0x52, 0);
1298                 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
1299         }
1300         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1301
1302         for (i = 0; i < 16; i++) {
1303                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
1304                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
1305                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
1306                 if (phy->gmode || phy->rev >= 2) {
1307                         BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1308                             bwn_rf_2050_rfoverval(mac,
1309                                 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1310                 }
1311                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1312                 DELAY(10);
1313                 if (phy->gmode || phy->rev >= 2) {
1314                         BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1315                             bwn_rf_2050_rfoverval(mac,
1316                                 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1317                 }
1318                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
1319                 DELAY(10);
1320                 if (phy->gmode || phy->rev >= 2) {
1321                         BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1322                             bwn_rf_2050_rfoverval(mac,
1323                                 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
1324                 }
1325                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
1326                 DELAY(20);
1327                 tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1328                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1329                 if (phy->gmode || phy->rev >= 2) {
1330                         BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1331                             bwn_rf_2050_rfoverval(mac,
1332                                 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1333                 }
1334                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1335         }
1336         DELAY(10);
1337
1338         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1339         tmp1++;
1340         tmp1 >>= 9;
1341
1342         for (i = 0; i < 16; i++) {
1343                 radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
1344                 BWN_RF_WRITE(mac, 0x78, radio78);
1345                 DELAY(10);
1346                 for (j = 0; j < 16; j++) {
1347                         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
1348                         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
1349                         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
1350                         if (phy->gmode || phy->rev >= 2) {
1351                                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1352                                     bwn_rf_2050_rfoverval(mac,
1353                                         BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1354                         }
1355                         BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1356                         DELAY(10);
1357                         if (phy->gmode || phy->rev >= 2) {
1358                                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1359                                     bwn_rf_2050_rfoverval(mac,
1360                                         BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1361                         }
1362                         BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
1363                         DELAY(10);
1364                         if (phy->gmode || phy->rev >= 2) {
1365                                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1366                                     bwn_rf_2050_rfoverval(mac,
1367                                         BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
1368                         }
1369                         BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
1370                         DELAY(10);
1371                         tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1372                         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1373                         if (phy->gmode || phy->rev >= 2) {
1374                                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1375                                     bwn_rf_2050_rfoverval(mac,
1376                                         BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1377                         }
1378                         BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1379                 }
1380                 tmp2++;
1381                 tmp2 >>= 8;
1382                 if (tmp1 < tmp2)
1383                         break;
1384         }
1385
1386         BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
1387         BWN_RF_WRITE(mac, 0x51, radio1);
1388         BWN_RF_WRITE(mac, 0x52, radio2);
1389         BWN_RF_WRITE(mac, 0x43, radio0);
1390         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
1391         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
1392         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
1393         BWN_WRITE_2(mac, 0x3e6, reg1);
1394         if (phy->analog != 0)
1395                 BWN_WRITE_2(mac, 0x3f4, reg2);
1396         BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
1397         bwn_spu_workaround(mac, phy->chan);
1398         if (phy->type == BWN_PHYTYPE_B) {
1399                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
1400                 BWN_WRITE_2(mac, 0x3ec, reg0);
1401         } else if (phy->gmode) {
1402                 BWN_WRITE_2(mac, BWN_PHY_RADIO,
1403                             BWN_READ_2(mac, BWN_PHY_RADIO)
1404                             & 0x7fff);
1405                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
1406                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
1407                 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
1408                 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
1409                               analogoverval);
1410                 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
1411                 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
1412                 if (BWN_HAS_LOOPBACK(phy)) {
1413                         BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
1414                         BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
1415                 }
1416         }
1417
1418         return ((i > 15) ? radio78 : rcc);
1419 }
1420
1421 static void
1422 bwn_phy_init_b6(struct bwn_mac *mac)
1423 {
1424         struct bwn_phy *phy = &mac->mac_phy;
1425         struct bwn_phy_g *pg = &phy->phy_g;
1426         struct bwn_softc *sc = mac->mac_sc;
1427         uint16_t offset, val;
1428         uint8_t old_channel;
1429
1430         KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
1431             ("%s:%d: fail", __func__, __LINE__));
1432
1433         BWN_PHY_WRITE(mac, 0x003e, 0x817a);
1434         BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
1435         if (phy->rf_rev == 4 || phy->rf_rev == 5) {
1436                 BWN_RF_WRITE(mac, 0x51, 0x37);
1437                 BWN_RF_WRITE(mac, 0x52, 0x70);
1438                 BWN_RF_WRITE(mac, 0x53, 0xb3);
1439                 BWN_RF_WRITE(mac, 0x54, 0x9b);
1440                 BWN_RF_WRITE(mac, 0x5a, 0x88);
1441                 BWN_RF_WRITE(mac, 0x5b, 0x88);
1442                 BWN_RF_WRITE(mac, 0x5d, 0x88);
1443                 BWN_RF_WRITE(mac, 0x5e, 0x88);
1444                 BWN_RF_WRITE(mac, 0x7d, 0x88);
1445                 bwn_hf_write(mac,
1446                     bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
1447         }
1448         if (phy->rf_rev == 8) {
1449                 BWN_RF_WRITE(mac, 0x51, 0);
1450                 BWN_RF_WRITE(mac, 0x52, 0x40);
1451                 BWN_RF_WRITE(mac, 0x53, 0xb7);
1452                 BWN_RF_WRITE(mac, 0x54, 0x98);
1453                 BWN_RF_WRITE(mac, 0x5a, 0x88);
1454                 BWN_RF_WRITE(mac, 0x5b, 0x6b);
1455                 BWN_RF_WRITE(mac, 0x5c, 0x0f);
1456                 if (sc->sc_board_info.board_flags & BHND_BFL_ALTIQ) {
1457                         BWN_RF_WRITE(mac, 0x5d, 0xfa);
1458                         BWN_RF_WRITE(mac, 0x5e, 0xd8);
1459                 } else {
1460                         BWN_RF_WRITE(mac, 0x5d, 0xf5);
1461                         BWN_RF_WRITE(mac, 0x5e, 0xb8);
1462                 }
1463                 BWN_RF_WRITE(mac, 0x0073, 0x0003);
1464                 BWN_RF_WRITE(mac, 0x007d, 0x00a8);
1465                 BWN_RF_WRITE(mac, 0x007c, 0x0001);
1466                 BWN_RF_WRITE(mac, 0x007e, 0x0008);
1467         }
1468         for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
1469                 BWN_PHY_WRITE(mac, offset, val);
1470                 val -= 0x0202;
1471         }
1472         for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
1473                 BWN_PHY_WRITE(mac, offset, val);
1474                 val -= 0x0202;
1475         }
1476         for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
1477                 BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
1478                 val += 0x0202;
1479         }
1480         if (phy->type == BWN_PHYTYPE_G) {
1481                 BWN_RF_SET(mac, 0x007a, 0x0020);
1482                 BWN_RF_SET(mac, 0x0051, 0x0004);
1483                 BWN_PHY_SET(mac, 0x0802, 0x0100);
1484                 BWN_PHY_SET(mac, 0x042b, 0x2000);
1485                 BWN_PHY_WRITE(mac, 0x5b, 0);
1486                 BWN_PHY_WRITE(mac, 0x5c, 0);
1487         }
1488
1489         old_channel = phy->chan;
1490         bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
1491
1492         BWN_RF_WRITE(mac, 0x0050, 0x0020);
1493         BWN_RF_WRITE(mac, 0x0050, 0x0023);
1494         DELAY(40);
1495         if (phy->rf_rev < 6 || phy->rf_rev == 8) {
1496                 BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
1497                 BWN_RF_WRITE(mac, 0x50, 0x20);
1498         }
1499         if (phy->rf_rev <= 2) {
1500                 BWN_RF_WRITE(mac, 0x7c, 0x20);
1501                 BWN_RF_WRITE(mac, 0x5a, 0x70);
1502                 BWN_RF_WRITE(mac, 0x5b, 0x7b);
1503                 BWN_RF_WRITE(mac, 0x5c, 0xb0);
1504         }
1505         BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
1506
1507         bwn_phy_g_switch_chan(mac, old_channel, 0);
1508
1509         BWN_PHY_WRITE(mac, 0x0014, 0x0200);
1510         if (phy->rf_rev >= 6)
1511                 BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
1512         else
1513                 BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
1514         BWN_PHY_WRITE(mac, 0x0038, 0x0668);
1515         bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
1516             pg->pg_txctl);
1517         if (phy->rf_rev <= 5)
1518                 BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
1519         if (phy->rf_rev <= 2)
1520                 BWN_RF_WRITE(mac, 0x005d, 0x000d);
1521
1522         if (phy->analog == 4) {
1523                 BWN_WRITE_2(mac, 0x3e4, 9);
1524                 BWN_PHY_MASK(mac, 0x61, 0x0fff);
1525         } else
1526                 BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
1527         if (phy->type == BWN_PHYTYPE_B)
1528                 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1529         else if (phy->type == BWN_PHYTYPE_G)
1530                 BWN_WRITE_2(mac, 0x03e6, 0x0);
1531 }
1532
1533 static void
1534 bwn_phy_init_a(struct bwn_mac *mac)
1535 {
1536         struct bwn_phy *phy = &mac->mac_phy;
1537         struct bwn_softc *sc = mac->mac_sc;
1538
1539         KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
1540             ("%s:%d: fail", __func__, __LINE__));
1541
1542         if (phy->rev >= 6) {
1543                 if (phy->type == BWN_PHYTYPE_A)
1544                         BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
1545                 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
1546                         BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
1547                 else
1548                         BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
1549         }
1550
1551         bwn_wa_init(mac);
1552
1553         if (phy->type == BWN_PHYTYPE_G &&
1554             (sc->sc_board_info.board_flags & BHND_BFL_PACTRL))
1555                 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
1556 }
1557
1558 static void
1559 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
1560 {
1561         int i;
1562
1563         for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
1564                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
1565 }
1566
1567 static void
1568 bwn_wa_agc(struct bwn_mac *mac)
1569 {
1570         struct bwn_phy *phy = &mac->mac_phy;
1571
1572         if (phy->rev == 1) {
1573                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
1574                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
1575                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
1576                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
1577                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
1578                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
1579                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
1580                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
1581                 BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
1582         } else {
1583                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
1584                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
1585                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
1586                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
1587         }
1588
1589         BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
1590             0x5700);
1591         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
1592         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
1593         BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
1594         BWN_RF_SET(mac, 0x7a, 0x0008);
1595         BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
1596         BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
1597         BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
1598         BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
1599         if (phy->rev == 1)
1600                 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
1601         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
1602         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
1603         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
1604         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
1605         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
1606         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
1607         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
1608         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
1609         BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
1610         if (phy->rev == 1) {
1611                 BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
1612                 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
1613         } else {
1614                 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
1615                 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
1616                 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
1617                 if (phy->rev >= 6) {
1618                         BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
1619                         BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
1620                             (uint16_t)~0xf000, 0x3000);
1621                 }
1622         }
1623         BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
1624         BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
1625         if (phy->rev == 1) {
1626                 BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
1627                 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
1628                 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
1629                 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
1630                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
1631                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
1632                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
1633                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
1634         } else {
1635                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
1636                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
1637                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
1638                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
1639         }
1640         if (phy->rev >= 6) {
1641                 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
1642                 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
1643         }
1644         BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
1645 }
1646
1647 static void
1648 bwn_wa_grev1(struct bwn_mac *mac)
1649 {
1650         struct bwn_phy *phy = &mac->mac_phy;
1651         int i;
1652         static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
1653         static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
1654         static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
1655
1656         KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
1657
1658         /* init CRSTHRES and ANTDWELL */
1659         if (phy->rev == 1) {
1660                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
1661         } else if (phy->rev == 2) {
1662                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
1663                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
1664                 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1665         } else {
1666                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
1667                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
1668                 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
1669                 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1670         }
1671         BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
1672         BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
1673         BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
1674
1675         /* XXX support PHY-A??? */
1676         for (i = 0; i < N(bwn_tab_finefreqg); i++)
1677                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
1678                     bwn_tab_finefreqg[i]);
1679
1680         /* XXX support PHY-A??? */
1681         if (phy->rev == 1)
1682                 for (i = 0; i < N(bwn_tab_noise_g1); i++)
1683                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1684                             bwn_tab_noise_g1[i]);
1685         else
1686                 for (i = 0; i < N(bwn_tab_noise_g2); i++)
1687                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1688                             bwn_tab_noise_g2[i]);
1689
1690         for (i = 0; i < N(bwn_tab_rotor); i++)
1691                 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
1692                     bwn_tab_rotor[i]);
1693
1694         /* XXX support PHY-A??? */
1695         if (phy->rev >= 6) {
1696                 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
1697                     BWN_PHY_ENCORE_EN)
1698                         bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
1699                 else
1700                         bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
1701         } else
1702                 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
1703
1704         for (i = 0; i < N(bwn_tab_retard); i++)
1705                 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
1706                     bwn_tab_retard[i]);
1707
1708         if (phy->rev == 1) {
1709                 for (i = 0; i < 16; i++)
1710                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
1711                             i, 0x0020);
1712         } else {
1713                 for (i = 0; i < 32; i++)
1714                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
1715         }
1716
1717         bwn_wa_agc(mac);
1718 }
1719
1720 static void
1721 bwn_wa_grev26789(struct bwn_mac *mac)
1722 {
1723         struct bwn_phy *phy = &mac->mac_phy;
1724         int i;
1725         static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
1726         uint16_t ofdmrev;
1727
1728         KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
1729
1730         bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
1731
1732         /* init CRSTHRES and ANTDWELL */
1733         if (phy->rev == 1)
1734                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
1735         else if (phy->rev == 2) {
1736                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
1737                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
1738                 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1739         } else {
1740                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
1741                 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
1742                 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
1743                 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1744         }
1745
1746         for (i = 0; i < 64; i++)
1747                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
1748
1749         /* XXX support PHY-A??? */
1750         if (phy->rev == 1)
1751                 for (i = 0; i < N(bwn_tab_noise_g1); i++)
1752                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1753                             bwn_tab_noise_g1[i]);
1754         else
1755                 for (i = 0; i < N(bwn_tab_noise_g2); i++)
1756                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1757                             bwn_tab_noise_g2[i]);
1758
1759         /* XXX support PHY-A??? */
1760         if (phy->rev >= 6) {
1761                 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
1762                     BWN_PHY_ENCORE_EN)
1763                         bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
1764                 else
1765                         bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
1766         } else
1767                 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
1768
1769         for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
1770                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
1771                     bwn_tab_sigmasqr2[i]);
1772
1773         if (phy->rev == 1) {
1774                 for (i = 0; i < 16; i++)
1775                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
1776                             0x0020);
1777         } else {
1778                 for (i = 0; i < 32; i++)
1779                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
1780         }
1781
1782         bwn_wa_agc(mac);
1783
1784         ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
1785         if (ofdmrev > 2) {
1786                 if (phy->type == BWN_PHYTYPE_A)
1787                         BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
1788                 else
1789                         BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
1790         } else {
1791                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
1792                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
1793                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
1794         }
1795
1796         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
1797         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
1798 }
1799
1800 static void
1801 bwn_wa_init(struct bwn_mac *mac)
1802 {
1803         struct bwn_phy *phy = &mac->mac_phy;
1804         struct bwn_softc *sc = mac->mac_sc;
1805
1806         KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
1807
1808         switch (phy->rev) {
1809         case 1:
1810                 bwn_wa_grev1(mac);
1811                 break;
1812         case 2:
1813         case 6:
1814         case 7:
1815         case 8:
1816         case 9:
1817                 bwn_wa_grev26789(mac);
1818                 break;
1819         default:
1820                 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1821         }
1822
1823         if (sc->sc_board_info.board_vendor != PCI_VENDOR_BROADCOM ||
1824             sc->sc_board_info.board_type != BHND_BOARD_BU4306 ||
1825             sc->sc_board_info.board_rev != 0x17) {
1826                 if (phy->rev < 2) {
1827                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
1828                             0x0002);
1829                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
1830                             0x0001);
1831                 } else {
1832                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
1833                         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
1834                         if ((sc->sc_board_info.board_flags &
1835                              BHND_BFL_EXTLNA) &&
1836                             (phy->rev >= 7)) {
1837                                 BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
1838                                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1839                                     0x0020, 0x0001);
1840                                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1841                                     0x0021, 0x0001);
1842                                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1843                                     0x0022, 0x0001);
1844                                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1845                                     0x0023, 0x0000);
1846                                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1847                                     0x0000, 0x0000);
1848                                 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1849                                     0x0003, 0x0002);
1850                         }
1851                 }
1852         }
1853         if (sc->sc_board_info.board_flags & BHND_BFL_FEM) {
1854                 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
1855                 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
1856         }
1857
1858         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
1859         bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
1860 }
1861
1862 static void
1863 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
1864     uint16_t value)
1865 {
1866         struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
1867         uint16_t addr;
1868
1869         addr = table + offset;
1870         if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
1871             (addr - 1 != pg->pg_ofdmtab_addr)) {
1872                 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
1873                 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
1874         }
1875         pg->pg_ofdmtab_addr = addr;
1876         BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
1877 }
1878
1879 static void
1880 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
1881     uint32_t value)
1882 {
1883         struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
1884         uint16_t addr;
1885
1886         addr = table + offset;
1887         if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
1888             (addr - 1 != pg->pg_ofdmtab_addr)) {
1889                 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
1890                 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
1891         }
1892         pg->pg_ofdmtab_addr = addr;
1893
1894         BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
1895         BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
1896 }
1897
1898 static void
1899 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
1900     uint16_t value)
1901 {
1902
1903         BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
1904         BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
1905 }
1906
1907 static void
1908 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
1909 {
1910         uint16_t value;
1911
1912         KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
1913             ("%s:%d: fail", __func__, __LINE__));
1914
1915         value = (uint8_t) (ctl->q);
1916         value |= ((uint8_t) (ctl->i)) << 8;
1917         BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
1918 }
1919
1920 static uint16_t
1921 bwn_lo_calcfeed(struct bwn_mac *mac,
1922     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
1923 {
1924         struct bwn_phy *phy = &mac->mac_phy;
1925         struct bwn_softc *sc = mac->mac_sc;
1926         uint16_t rfover;
1927         uint16_t feedthrough;
1928
1929         if (phy->gmode) {
1930                 lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
1931                 pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
1932
1933                 KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
1934                     ("%s:%d: fail", __func__, __LINE__));
1935                 KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
1936                     ("%s:%d: fail", __func__, __LINE__));
1937
1938                 trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
1939
1940                 rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
1941                 if ((sc->sc_board_info.board_flags & BHND_BFL_EXTLNA) &&
1942                     phy->rev > 6)
1943                         rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
1944
1945                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
1946                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
1947                 DELAY(10);
1948                 rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
1949                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
1950                 DELAY(10);
1951                 rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
1952                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
1953                 DELAY(10);
1954                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
1955         } else {
1956                 pga |= BWN_PHY_PGACTL_UNKNOWN;
1957                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
1958                 DELAY(10);
1959                 pga |= BWN_PHY_PGACTL_LOWBANDW;
1960                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
1961                 DELAY(10);
1962                 pga |= BWN_PHY_PGACTL_LPF;
1963                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
1964         }
1965         DELAY(21);
1966         feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1967
1968         return (feedthrough);
1969 }
1970
1971 static uint16_t
1972 bwn_lo_txctl_regtable(struct bwn_mac *mac,
1973     uint16_t *value, uint16_t *pad_mix_gain)
1974 {
1975         struct bwn_phy *phy = &mac->mac_phy;
1976         uint16_t reg, v, padmix;
1977
1978         if (phy->type == BWN_PHYTYPE_B) {
1979                 v = 0x30;
1980                 if (phy->rf_rev <= 5) {
1981                         reg = 0x43;
1982                         padmix = 0;
1983                 } else {
1984                         reg = 0x52;
1985                         padmix = 5;
1986                 }
1987         } else {
1988                 if (phy->rev >= 2 && phy->rf_rev == 8) {
1989                         reg = 0x43;
1990                         v = 0x10;
1991                         padmix = 2;
1992                 } else {
1993                         reg = 0x52;
1994                         v = 0x30;
1995                         padmix = 5;
1996                 }
1997         }
1998         if (value)
1999                 *value = v;
2000         if (pad_mix_gain)
2001                 *pad_mix_gain = padmix;
2002
2003         return (reg);
2004 }
2005
2006 static void
2007 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
2008 {
2009         struct bwn_phy *phy = &mac->mac_phy;
2010         struct bwn_phy_g *pg = &phy->phy_g;
2011         struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2012         uint16_t reg, mask;
2013         uint16_t trsw_rx, pga;
2014         uint16_t rf_pctl_reg;
2015
2016         static const uint8_t tx_bias_values[] = {
2017                 0x09, 0x08, 0x0a, 0x01, 0x00,
2018                 0x02, 0x05, 0x04, 0x06,
2019         };
2020         static const uint8_t tx_magn_values[] = {
2021                 0x70, 0x40,
2022         };
2023
2024         if (!BWN_HAS_LOOPBACK(phy)) {
2025                 rf_pctl_reg = 6;
2026                 trsw_rx = 2;
2027                 pga = 0;
2028         } else {
2029                 int lb_gain;
2030
2031                 trsw_rx = 0;
2032                 lb_gain = pg->pg_max_lb_gain / 2;
2033                 if (lb_gain > 10) {
2034                         rf_pctl_reg = 0;
2035                         pga = abs(10 - lb_gain) / 6;
2036                         pga = MIN(MAX(pga, 0), 15);
2037                 } else {
2038                         int cmp_val;
2039                         int tmp;
2040
2041                         pga = 0;
2042                         cmp_val = 0x24;
2043                         if ((phy->rev >= 2) &&
2044                             (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
2045                                 cmp_val = 0x3c;
2046                         tmp = lb_gain;
2047                         if ((10 - lb_gain) < cmp_val)
2048                                 tmp = (10 - lb_gain);
2049                         if (tmp < 0)
2050                                 tmp += 6;
2051                         else
2052                                 tmp += 3;
2053                         cmp_val /= 4;
2054                         tmp /= 4;
2055                         if (tmp >= cmp_val)
2056                                 rf_pctl_reg = cmp_val;
2057                         else
2058                                 rf_pctl_reg = tmp;
2059                 }
2060         }
2061         BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
2062         bwn_phy_g_set_bbatt(mac, 2);
2063
2064         reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
2065         mask = ~mask;
2066         BWN_RF_MASK(mac, reg, mask);
2067
2068         if (BWN_HAS_TXMAG(phy)) {
2069                 int i, j;
2070                 int feedthrough;
2071                 int min_feedth = 0xffff;
2072                 uint8_t tx_magn, tx_bias;
2073
2074                 for (i = 0; i < N(tx_magn_values); i++) {
2075                         tx_magn = tx_magn_values[i];
2076                         BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
2077                         for (j = 0; j < N(tx_bias_values); j++) {
2078                                 tx_bias = tx_bias_values[j];
2079                                 BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
2080                                 feedthrough = bwn_lo_calcfeed(mac, 0, pga,
2081                                     trsw_rx);
2082                                 if (feedthrough < min_feedth) {
2083                                         lo->tx_bias = tx_bias;
2084                                         lo->tx_magn = tx_magn;
2085                                         min_feedth = feedthrough;
2086                                 }
2087                                 if (lo->tx_bias == 0)
2088                                         break;
2089                         }
2090                         BWN_RF_WRITE(mac, 0x52,
2091                                           (BWN_RF_READ(mac, 0x52)
2092                                            & 0xff00) | lo->tx_bias | lo->
2093                                           tx_magn);
2094                 }
2095         } else {
2096                 lo->tx_magn = 0;
2097                 lo->tx_bias = 0;
2098                 BWN_RF_MASK(mac, 0x52, 0xfff0);
2099         }
2100
2101         BWN_GETTIME(lo->txctl_measured_time);
2102 }
2103
2104 static void
2105 bwn_lo_get_powervector(struct bwn_mac *mac)
2106 {
2107         struct bwn_phy *phy = &mac->mac_phy;
2108         struct bwn_phy_g *pg = &phy->phy_g;
2109         struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2110         int i;
2111         uint64_t tmp;
2112         uint64_t power_vector = 0;
2113
2114         for (i = 0; i < 8; i += 2) {
2115                 tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
2116                 power_vector |= (tmp << (i * 8));
2117                 bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
2118         }
2119         if (power_vector)
2120                 lo->power_vector = power_vector;
2121
2122         BWN_GETTIME(lo->pwr_vec_read_time);
2123 }
2124
2125 static void
2126 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
2127     int use_trsw_rx)
2128 {
2129         struct bwn_phy *phy = &mac->mac_phy;
2130         struct bwn_phy_g *pg = &phy->phy_g;
2131         uint16_t tmp;
2132
2133         if (max_rx_gain < 0)
2134                 max_rx_gain = 0;
2135
2136         if (BWN_HAS_LOOPBACK(phy)) {
2137                 int trsw_rx_gain;
2138
2139                 if (use_trsw_rx) {
2140                         trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
2141                         if (max_rx_gain >= trsw_rx_gain) {
2142                                 trsw_rx_gain = max_rx_gain - trsw_rx_gain;
2143                         }
2144                 } else
2145                         trsw_rx_gain = max_rx_gain;
2146                 if (trsw_rx_gain < 9) {
2147                         pg->pg_lna_lod_gain = 0;
2148                 } else {
2149                         pg->pg_lna_lod_gain = 1;
2150                         trsw_rx_gain -= 8;
2151                 }
2152                 trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
2153                 pg->pg_pga_gain = trsw_rx_gain / 3;
2154                 if (pg->pg_pga_gain >= 5) {
2155                         pg->pg_pga_gain -= 5;
2156                         pg->pg_lna_gain = 2;
2157                 } else
2158                         pg->pg_lna_gain = 0;
2159         } else {
2160                 pg->pg_lna_gain = 0;
2161                 pg->pg_trsw_rx_gain = 0x20;
2162                 if (max_rx_gain >= 0x14) {
2163                         pg->pg_lna_lod_gain = 1;
2164                         pg->pg_pga_gain = 2;
2165                 } else if (max_rx_gain >= 0x12) {
2166                         pg->pg_lna_lod_gain = 1;
2167                         pg->pg_pga_gain = 1;
2168                 } else if (max_rx_gain >= 0xf) {
2169                         pg->pg_lna_lod_gain = 1;
2170                         pg->pg_pga_gain = 0;
2171                 } else {
2172                         pg->pg_lna_lod_gain = 0;
2173                         pg->pg_pga_gain = 0;
2174                 }
2175         }
2176
2177         tmp = BWN_RF_READ(mac, 0x7a);
2178         if (pg->pg_lna_lod_gain == 0)
2179                 tmp &= ~0x0008;
2180         else
2181                 tmp |= 0x0008;
2182         BWN_RF_WRITE(mac, 0x7a, tmp);
2183 }
2184
2185 static void
2186 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
2187 {
2188         struct bwn_phy *phy = &mac->mac_phy;
2189         struct bwn_phy_g *pg = &phy->phy_g;
2190         struct bwn_softc *sc = mac->mac_sc;
2191         struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2192         struct timespec ts;
2193         uint16_t tmp;
2194
2195         if (bwn_has_hwpctl(mac)) {
2196                 sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
2197                 sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
2198                 sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
2199                 sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
2200                 sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
2201
2202                 BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
2203                 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
2204                 BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
2205                 BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
2206         }
2207         if (phy->type == BWN_PHYTYPE_B &&
2208             phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
2209                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
2210                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
2211         }
2212         if (phy->rev >= 2) {
2213                 sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
2214                 sav->phy_analogoverval =
2215                     BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
2216                 sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2217                 sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2218                 sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
2219                 sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
2220                 sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
2221
2222                 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
2223                 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
2224                 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
2225                 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
2226                 if (phy->type == BWN_PHYTYPE_G) {
2227                         if ((phy->rev >= 7) &&
2228                             (sc->sc_board_info.board_flags &
2229                              BHND_BFL_EXTLNA)) {
2230                                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
2231                         } else {
2232                                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
2233                         }
2234                 } else {
2235                         BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
2236                 }
2237                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
2238         }
2239         sav->reg0 = BWN_READ_2(mac, 0x3f4);
2240         sav->reg1 = BWN_READ_2(mac, 0x3e2);
2241         sav->rf0 = BWN_RF_READ(mac, 0x43);
2242         sav->rf1 = BWN_RF_READ(mac, 0x7a);
2243         sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
2244         sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
2245         sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
2246         sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
2247
2248         if (!BWN_HAS_TXMAG(phy)) {
2249                 sav->rf2 = BWN_RF_READ(mac, 0x52);
2250                 sav->rf2 &= 0x00f0;
2251         }
2252         if (phy->type == BWN_PHYTYPE_B) {
2253                 sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
2254                 sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
2255                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
2256                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
2257         } else {
2258                 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
2259                             | 0x8000);
2260         }
2261         BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
2262                     & 0xf000);
2263
2264         tmp =
2265             (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
2266         BWN_PHY_WRITE(mac, tmp, 0x007f);
2267
2268         tmp = sav->phy_syncctl;
2269         BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
2270         tmp = sav->rf1;
2271         BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
2272
2273         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
2274         if (phy->type == BWN_PHYTYPE_G ||
2275             (phy->type == BWN_PHYTYPE_B &&
2276              phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
2277                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
2278         } else
2279                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
2280         if (phy->rev >= 2)
2281                 bwn_dummy_transmission(mac, 0, 1);
2282         bwn_phy_g_switch_chan(mac, 6, 0);
2283         BWN_RF_READ(mac, 0x51);
2284         if (phy->type == BWN_PHYTYPE_G)
2285                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
2286
2287         nanouptime(&ts);
2288         if (ieee80211_time_before(lo->txctl_measured_time,
2289             (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
2290                 bwn_lo_measure_txctl_values(mac);
2291
2292         if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
2293                 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
2294         else {
2295                 if (phy->type == BWN_PHYTYPE_B)
2296                         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
2297                 else
2298                         BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
2299         }
2300 }
2301
2302 static void
2303 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
2304 {
2305         struct bwn_phy *phy = &mac->mac_phy;
2306         struct bwn_phy_g *pg = &phy->phy_g;
2307         uint16_t tmp;
2308
2309         if (phy->rev >= 2) {
2310                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
2311                 tmp = (pg->pg_pga_gain << 8);
2312                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
2313                 DELAY(5);
2314                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
2315                 DELAY(2);
2316                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
2317         } else {
2318                 tmp = (pg->pg_pga_gain | 0xefa0);
2319                 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
2320         }
2321         if (phy->type == BWN_PHYTYPE_G) {
2322                 if (phy->rev >= 3)
2323                         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
2324                 else
2325                         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
2326                 if (phy->rev >= 2)
2327                         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
2328                 else
2329                         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
2330         }
2331         BWN_WRITE_2(mac, 0x3f4, sav->reg0);
2332         BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
2333         BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
2334         BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
2335         BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
2336         BWN_RF_WRITE(mac, 0x43, sav->rf0);
2337         BWN_RF_WRITE(mac, 0x7a, sav->rf1);
2338         if (!BWN_HAS_TXMAG(phy)) {
2339                 tmp = sav->rf2;
2340                 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
2341         }
2342         BWN_WRITE_2(mac, 0x3e2, sav->reg1);
2343         if (phy->type == BWN_PHYTYPE_B &&
2344             phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
2345                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
2346                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
2347         }
2348         if (phy->rev >= 2) {
2349                 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
2350                 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
2351                               sav->phy_analogoverval);
2352                 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
2353                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
2354                 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
2355                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
2356                 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
2357         }
2358         if (bwn_has_hwpctl(mac)) {
2359                 tmp = (sav->phy_lomask & 0xbfff);
2360                 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
2361                 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
2362                 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
2363                 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
2364                 BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
2365         }
2366         bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
2367 }
2368
2369 static int
2370 bwn_lo_probe_loctl(struct bwn_mac *mac,
2371     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
2372 {
2373         struct bwn_phy *phy = &mac->mac_phy;
2374         struct bwn_phy_g *pg = &phy->phy_g;
2375         struct bwn_loctl orig, test;
2376         struct bwn_loctl prev = { -100, -100 };
2377         static const struct bwn_loctl modifiers[] = {
2378                 {  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
2379                 { -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
2380         };
2381         int begin, end, lower = 0, i;
2382         uint16_t feedth;
2383
2384         if (d->curstate == 0) {
2385                 begin = 1;
2386                 end = 8;
2387         } else if (d->curstate % 2 == 0) {
2388                 begin = d->curstate - 1;
2389                 end = d->curstate + 1;
2390         } else {
2391                 begin = d->curstate - 2;
2392                 end = d->curstate + 2;
2393         }
2394         if (begin < 1)
2395                 begin += 8;
2396         if (end > 8)
2397                 end -= 8;
2398
2399         memcpy(&orig, probe, sizeof(struct bwn_loctl));
2400         i = begin;
2401         d->curstate = i;
2402         while (1) {
2403                 KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
2404                 memcpy(&test, &orig, sizeof(struct bwn_loctl));
2405                 test.i += modifiers[i - 1].i * d->multipler;
2406                 test.q += modifiers[i - 1].q * d->multipler;
2407                 if ((test.i != prev.i || test.q != prev.q) &&
2408                     (abs(test.i) <= 16 && abs(test.q) <= 16)) {
2409                         bwn_lo_write(mac, &test);
2410                         feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
2411                             pg->pg_pga_gain, pg->pg_trsw_rx_gain);
2412                         if (feedth < d->feedth) {
2413                                 memcpy(probe, &test,
2414                                     sizeof(struct bwn_loctl));
2415                                 lower = 1;
2416                                 d->feedth = feedth;
2417                                 if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
2418                                         break;
2419                         }
2420                 }
2421                 memcpy(&prev, &test, sizeof(prev));
2422                 if (i == end)
2423                         break;
2424                 if (i == 8)
2425                         i = 1;
2426                 else
2427                         i++;
2428                 d->curstate = i;
2429         }
2430
2431         return (lower);
2432 }
2433
2434 static void
2435 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
2436 {
2437         struct bwn_phy *phy = &mac->mac_phy;
2438         struct bwn_phy_g *pg = &phy->phy_g;
2439         struct bwn_lo_g_sm d;
2440         struct bwn_loctl probe;
2441         int lower, repeat, cnt = 0;
2442         uint16_t feedth;
2443
2444         d.nmeasure = 0;
2445         d.multipler = 1;
2446         if (BWN_HAS_LOOPBACK(phy))
2447                 d.multipler = 3;
2448
2449         memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
2450         repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
2451
2452         do {
2453                 bwn_lo_write(mac, &d.loctl);
2454                 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
2455                     pg->pg_pga_gain, pg->pg_trsw_rx_gain);
2456                 if (feedth < 0x258) {
2457                         if (feedth >= 0x12c)
2458                                 *rxgain += 6;
2459                         else
2460                                 *rxgain += 3;
2461                         feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
2462                             pg->pg_pga_gain, pg->pg_trsw_rx_gain);
2463                 }
2464                 d.feedth = feedth;
2465                 d.curstate = 0;
2466                 do {
2467                         KASSERT(d.curstate >= 0 && d.curstate <= 8,
2468                             ("%s:%d: fail", __func__, __LINE__));
2469                         memcpy(&probe, &d.loctl,
2470                                sizeof(struct bwn_loctl));
2471                         lower = bwn_lo_probe_loctl(mac, &probe, &d);
2472                         if (!lower)
2473                                 break;
2474                         if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
2475                                 break;
2476                         memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
2477                         d.nmeasure++;
2478                 } while (d.nmeasure < 24);
2479                 memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
2480
2481                 if (BWN_HAS_LOOPBACK(phy)) {
2482                         if (d.feedth > 0x1194)
2483                                 *rxgain -= 6;
2484                         else if (d.feedth < 0x5dc)
2485                                 *rxgain += 3;
2486                         if (cnt == 0) {
2487                                 if (d.feedth <= 0x5dc) {
2488                                         d.multipler = 1;
2489                                         cnt++;
2490                                 } else
2491                                         d.multipler = 2;
2492                         } else if (cnt == 2)
2493                                 d.multipler = 1;
2494                 }
2495                 bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
2496         } while (++cnt < repeat);
2497 }
2498
2499 static struct bwn_lo_calib *
2500 bwn_lo_calibset(struct bwn_mac *mac,
2501     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
2502 {
2503         struct bwn_phy *phy = &mac->mac_phy;
2504         struct bwn_phy_g *pg = &phy->phy_g;
2505         struct bwn_loctl loctl = { 0, 0 };
2506         struct bwn_lo_calib *cal;
2507         struct bwn_lo_g_value sval = { 0 };
2508         int rxgain;
2509         uint16_t pad, reg, value;
2510
2511         sval.old_channel = phy->chan;
2512         bwn_mac_suspend(mac);
2513         bwn_lo_save(mac, &sval);
2514
2515         reg = bwn_lo_txctl_regtable(mac, &value, &pad);
2516         BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
2517         BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
2518
2519         rxgain = (rfatt->att * 2) + (bbatt->att / 2);
2520         if (rfatt->padmix)
2521                 rxgain -= pad;
2522         if (BWN_HAS_LOOPBACK(phy))
2523                 rxgain += pg->pg_max_lb_gain;
2524         bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
2525         bwn_phy_g_set_bbatt(mac, bbatt->att);
2526         bwn_lo_probe_sm(mac, &loctl, &rxgain);
2527
2528         bwn_lo_restore(mac, &sval);
2529         bwn_mac_enable(mac);
2530
2531         cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
2532         if (!cal) {
2533                 device_printf(mac->mac_sc->sc_dev, "out of memory\n");
2534                 return (NULL);
2535         }
2536         memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
2537         memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
2538         memcpy(&cal->ctl, &loctl, sizeof(loctl));
2539
2540         BWN_GETTIME(cal->calib_time);
2541
2542         return (cal);
2543 }
2544
2545 static struct bwn_lo_calib *
2546 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
2547     const struct bwn_rfatt *rfatt)
2548 {
2549         struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2550         struct bwn_lo_calib *c;
2551
2552         TAILQ_FOREACH(c, &lo->calib_list, list) {
2553                 if (!BWN_BBATTCMP(&c->bbatt, bbatt))
2554                         continue;
2555                 if (!BWN_RFATTCMP(&c->rfatt, rfatt))
2556                         continue;
2557                 return (c);
2558         }
2559
2560         c = bwn_lo_calibset(mac, bbatt, rfatt);
2561         if (!c)
2562                 return (NULL);
2563         TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
2564
2565         return (c);
2566 }
2567
2568 static void
2569 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
2570 {
2571         struct bwn_phy *phy = &mac->mac_phy;
2572         struct bwn_phy_g *pg = &phy->phy_g;
2573         struct bwn_softc *sc = mac->mac_sc;
2574         struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2575         const struct bwn_rfatt *rfatt;
2576         const struct bwn_bbatt *bbatt;
2577         uint64_t pvector;
2578         int i;
2579         int rf_offset, bb_offset;
2580         uint8_t changed = 0;
2581
2582         KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
2583         KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
2584             ("%s:%d: fail", __func__, __LINE__));
2585
2586         pvector = lo->power_vector;
2587         if (!update && !pvector)
2588                 return;
2589
2590         bwn_mac_suspend(mac);
2591
2592         for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
2593                 struct bwn_lo_calib *cal;
2594                 int idx;
2595                 uint16_t val;
2596
2597                 if (!update && !(pvector & (((uint64_t)1ULL) << i)))
2598                         continue;
2599                 bb_offset = i / lo->rfatt.len;
2600                 rf_offset = i % lo->rfatt.len;
2601                 bbatt = &(lo->bbatt.array[bb_offset]);
2602                 rfatt = &(lo->rfatt.array[rf_offset]);
2603
2604                 cal = bwn_lo_calibset(mac, bbatt, rfatt);
2605                 if (!cal) {
2606                         device_printf(sc->sc_dev, "LO: Could not "
2607                             "calibrate DC table entry\n");
2608                         continue;
2609                 }
2610                 val = (uint8_t)(cal->ctl.q);
2611                 val |= ((uint8_t)(cal->ctl.i)) << 4;
2612                 free(cal, M_DEVBUF);
2613
2614                 idx = i / 2;
2615                 if (i % 2)
2616                         lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
2617                             | ((val & 0x00ff) << 8);
2618                 else
2619                         lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
2620                             | (val & 0x00ff);
2621                 changed = 1;
2622         }
2623         if (changed) {
2624                 for (i = 0; i < BWN_DC_LT_SIZE; i++)
2625                         BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
2626         }
2627         bwn_mac_enable(mac);
2628 }
2629
2630 static void
2631 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
2632 {
2633
2634         if (!rf->padmix)
2635                 return;
2636         if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
2637                 rf->att = 4;
2638 }
2639
2640 static void
2641 bwn_lo_g_adjust(struct bwn_mac *mac)
2642 {
2643         struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2644         struct bwn_lo_calib *cal;
2645         struct bwn_rfatt rf;
2646
2647         memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
2648         bwn_lo_fixup_rfatt(&rf);
2649
2650         cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
2651         if (!cal)
2652                 return;
2653         bwn_lo_write(mac, &cal->ctl);
2654 }
2655
2656 static void
2657 bwn_lo_g_init(struct bwn_mac *mac)
2658 {
2659
2660         if (!bwn_has_hwpctl(mac))
2661                 return;
2662
2663         bwn_lo_get_powervector(mac);
2664         bwn_phy_g_dc_lookup_init(mac, 1);
2665 }
2666
2667 static int16_t
2668 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
2669 {
2670
2671         BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
2672         return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
2673 }
2674
2675 static void
2676 bwn_nrssi_threshold(struct bwn_mac *mac)
2677 {
2678         struct bwn_phy *phy = &mac->mac_phy;
2679         struct bwn_phy_g *pg = &phy->phy_g;
2680         struct bwn_softc *sc = mac->mac_sc;
2681         int32_t a, b;
2682         int16_t tmp16;
2683         uint16_t tmpu16;
2684
2685         KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2686
2687         if (phy->gmode && (sc->sc_board_info.board_flags & BHND_BFL_ADCDIV)) {
2688                 if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
2689                         a = 0x13;
2690                         b = 0x12;
2691                 } else {
2692                         a = 0xe;
2693                         b = 0x11;
2694                 }
2695
2696                 a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
2697                 a += (pg->pg_nrssi[0] << 6);
2698                 a += (a < 32) ? 31 : 32;
2699                 a = a >> 6;
2700                 a = MIN(MAX(a, -31), 31);
2701
2702                 b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
2703                 b += (pg->pg_nrssi[0] << 6);
2704                 if (b < 32)
2705                         b += 31;
2706                 else
2707                         b += 32;
2708                 b = b >> 6;
2709                 b = MIN(MAX(b, -31), 31);
2710
2711                 tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
2712                 tmpu16 |= ((uint32_t)b & 0x0000003f);
2713                 tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
2714                 BWN_PHY_WRITE(mac, 0x048a, tmpu16);
2715                 return;
2716         }
2717
2718         tmp16 = bwn_nrssi_read(mac, 0x20);
2719         if (tmp16 >= 0x20)
2720                 tmp16 -= 0x40;
2721         BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
2722 }
2723
2724 static void
2725 bwn_nrssi_slope_11g(struct bwn_mac *mac)
2726 {
2727 #define SAVE_RF_MAX             3
2728 #define SAVE_PHY_COMM_MAX       4
2729 #define SAVE_PHY3_MAX           8
2730         static const uint16_t save_rf_regs[SAVE_RF_MAX] =
2731                 { 0x7a, 0x52, 0x43 };
2732         static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
2733                 { 0x15, 0x5a, 0x59, 0x58 };
2734         static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
2735                 0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
2736                 0x0801, 0x0060, 0x0014, 0x0478
2737         };
2738         struct bwn_phy *phy = &mac->mac_phy;
2739         struct bwn_phy_g *pg = &phy->phy_g;
2740         int32_t i, tmp32, phy3_idx = 0;
2741         uint16_t delta, tmp;
2742         uint16_t save_rf[SAVE_RF_MAX];
2743         uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
2744         uint16_t save_phy3[SAVE_PHY3_MAX];
2745         uint16_t ant_div, phy0, chan_ex;
2746         int16_t nrssi0, nrssi1;
2747
2748         KASSERT(phy->type == BWN_PHYTYPE_G,
2749             ("%s:%d: fail", __func__, __LINE__));
2750
2751         if (phy->rf_rev >= 9)
2752                 return;
2753         if (phy->rf_rev == 8)
2754                 bwn_nrssi_offset(mac);
2755
2756         BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
2757         BWN_PHY_MASK(mac, 0x0802, 0xfffc);
2758
2759         /*
2760          * Save RF/PHY registers for later restoration
2761          */
2762         ant_div = BWN_READ_2(mac, 0x03e2);
2763         BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
2764         for (i = 0; i < SAVE_RF_MAX; ++i)
2765                 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
2766         for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
2767                 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
2768
2769         phy0 = BWN_READ_2(mac, BWN_PHY0);
2770         chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
2771         if (phy->rev >= 3) {
2772                 for (i = 0; i < SAVE_PHY3_MAX; ++i)
2773                         save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
2774                 BWN_PHY_WRITE(mac, 0x002e, 0);
2775                 BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
2776                 switch (phy->rev) {
2777                 case 4:
2778                 case 6:
2779                 case 7:
2780                         BWN_PHY_SET(mac, 0x0478, 0x0100);
2781                         BWN_PHY_SET(mac, 0x0801, 0x0040);
2782                         break;
2783                 case 3:
2784                 case 5:
2785                         BWN_PHY_MASK(mac, 0x0801, 0xffbf);
2786                         break;
2787                 }
2788                 BWN_PHY_SET(mac, 0x0060, 0x0040);
2789                 BWN_PHY_SET(mac, 0x0014, 0x0200);
2790         }
2791         /*
2792          * Calculate nrssi0
2793          */
2794         BWN_RF_SET(mac, 0x007a, 0x0070);
2795         bwn_set_all_gains(mac, 0, 8, 0);
2796         BWN_RF_MASK(mac, 0x007a, 0x00f7);
2797         if (phy->rev >= 2) {
2798                 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
2799                 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
2800         }
2801         BWN_RF_SET(mac, 0x007a, 0x0080);
2802         DELAY(20);
2803
2804         nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2805         if (nrssi0 >= 0x0020)
2806                 nrssi0 -= 0x0040;
2807
2808         /*
2809          * Calculate nrssi1
2810          */
2811         BWN_RF_MASK(mac, 0x007a, 0x007f);
2812         if (phy->rev >= 2)
2813                 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
2814
2815         BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
2816             BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
2817         BWN_RF_SET(mac, 0x007a, 0x000f);
2818         BWN_PHY_WRITE(mac, 0x0015, 0xf330);
2819         if (phy->rev >= 2) {
2820                 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
2821                 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
2822         }
2823
2824         bwn_set_all_gains(mac, 3, 0, 1);
2825         if (phy->rf_rev == 8) {
2826                 BWN_RF_WRITE(mac, 0x0043, 0x001f);
2827         } else {
2828                 tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
2829                 BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
2830                 tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
2831                 BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
2832         }
2833         BWN_PHY_WRITE(mac, 0x005a, 0x0480);
2834         BWN_PHY_WRITE(mac, 0x0059, 0x0810);
2835         BWN_PHY_WRITE(mac, 0x0058, 0x000d);
2836         DELAY(20);
2837         nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2838
2839         /*
2840          * Install calculated narrow RSSI values
2841          */
2842         if (nrssi1 >= 0x0020)
2843                 nrssi1 -= 0x0040;
2844         if (nrssi0 == nrssi1)
2845                 pg->pg_nrssi_slope = 0x00010000;
2846         else
2847                 pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
2848         if (nrssi0 >= -4) {
2849                 pg->pg_nrssi[0] = nrssi1;
2850                 pg->pg_nrssi[1] = nrssi0;
2851         }
2852
2853         /*
2854          * Restore saved RF/PHY registers
2855          */
2856         if (phy->rev >= 3) {
2857                 for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
2858                         BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
2859                             save_phy3[phy3_idx]);
2860                 }
2861         }
2862         if (phy->rev >= 2) {
2863                 BWN_PHY_MASK(mac, 0x0812, 0xffcf);
2864                 BWN_PHY_MASK(mac, 0x0811, 0xffcf);
2865         }
2866
2867         for (i = 0; i < SAVE_RF_MAX; ++i)
2868                 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
2869
2870         BWN_WRITE_2(mac, 0x03e2, ant_div);
2871         BWN_WRITE_2(mac, 0x03e6, phy0);
2872         BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
2873
2874         for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
2875                 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
2876
2877         bwn_spu_workaround(mac, phy->chan);
2878         BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
2879         bwn_set_original_gains(mac);
2880         BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
2881         if (phy->rev >= 3) {
2882                 for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
2883                         BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
2884                             save_phy3[phy3_idx]);
2885                 }
2886         }
2887
2888         delta = 0x1f - pg->pg_nrssi[0];
2889         for (i = 0; i < 64; i++) {
2890                 tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
2891                 tmp32 = MIN(MAX(tmp32, 0), 0x3f);
2892                 pg->pg_nrssi_lt[i] = tmp32;
2893         }
2894
2895         bwn_nrssi_threshold(mac);
2896 #undef SAVE_RF_MAX
2897 #undef SAVE_PHY_COMM_MAX
2898 #undef SAVE_PHY3_MAX
2899 }
2900
2901 static void
2902 bwn_nrssi_offset(struct bwn_mac *mac)
2903 {
2904 #define SAVE_RF_MAX             2
2905 #define SAVE_PHY_COMM_MAX       10
2906 #define SAVE_PHY6_MAX           8
2907         static const uint16_t save_rf_regs[SAVE_RF_MAX] =
2908                 { 0x7a, 0x43 };
2909         static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
2910                 0x0001, 0x0811, 0x0812, 0x0814,
2911                 0x0815, 0x005a, 0x0059, 0x0058,
2912                 0x000a, 0x0003
2913         };
2914         static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
2915                 0x002e, 0x002f, 0x080f, 0x0810,
2916                 0x0801, 0x0060, 0x0014, 0x0478
2917         };
2918         struct bwn_phy *phy = &mac->mac_phy;
2919         int i, phy6_idx = 0;
2920         uint16_t save_rf[SAVE_RF_MAX];
2921         uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
2922         uint16_t save_phy6[SAVE_PHY6_MAX];
2923         int16_t nrssi;
2924         uint16_t saved = 0xffff;
2925
2926         for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
2927                 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
2928         for (i = 0; i < SAVE_RF_MAX; ++i)
2929                 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
2930
2931         BWN_PHY_MASK(mac, 0x0429, 0x7fff);
2932         BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
2933         BWN_PHY_SET(mac, 0x0811, 0x000c);
2934         BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
2935         BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
2936         if (phy->rev >= 6) {
2937                 for (i = 0; i < SAVE_PHY6_MAX; ++i)
2938                         save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
2939
2940                 BWN_PHY_WRITE(mac, 0x002e, 0);
2941                 BWN_PHY_WRITE(mac, 0x002f, 0);
2942                 BWN_PHY_WRITE(mac, 0x080f, 0);
2943                 BWN_PHY_WRITE(mac, 0x0810, 0);
2944                 BWN_PHY_SET(mac, 0x0478, 0x0100);
2945                 BWN_PHY_SET(mac, 0x0801, 0x0040);
2946                 BWN_PHY_SET(mac, 0x0060, 0x0040);
2947                 BWN_PHY_SET(mac, 0x0014, 0x0200);
2948         }
2949         BWN_RF_SET(mac, 0x007a, 0x0070);
2950         BWN_RF_SET(mac, 0x007a, 0x0080);
2951         DELAY(30);
2952
2953         nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2954         if (nrssi >= 0x20)
2955                 nrssi -= 0x40;
2956         if (nrssi == 31) {
2957                 for (i = 7; i >= 4; i--) {
2958                         BWN_RF_WRITE(mac, 0x007b, i);
2959                         DELAY(20);
2960                         nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
2961                             0x003f);
2962                         if (nrssi >= 0x20)
2963                                 nrssi -= 0x40;
2964                         if (nrssi < 31 && saved == 0xffff)
2965                                 saved = i;
2966                 }
2967                 if (saved == 0xffff)
2968                         saved = 4;
2969         } else {
2970                 BWN_RF_MASK(mac, 0x007a, 0x007f);
2971                 if (phy->rev != 1) {
2972                         BWN_PHY_SET(mac, 0x0814, 0x0001);
2973                         BWN_PHY_MASK(mac, 0x0815, 0xfffe);
2974                 }
2975                 BWN_PHY_SET(mac, 0x0811, 0x000c);
2976                 BWN_PHY_SET(mac, 0x0812, 0x000c);
2977                 BWN_PHY_SET(mac, 0x0811, 0x0030);
2978                 BWN_PHY_SET(mac, 0x0812, 0x0030);
2979                 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
2980                 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
2981                 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
2982                 if (phy->rev == 0)
2983                         BWN_PHY_WRITE(mac, 0x0003, 0x0122);
2984                 else
2985                         BWN_PHY_SET(mac, 0x000a, 0x2000);
2986                 if (phy->rev != 1) {
2987                         BWN_PHY_SET(mac, 0x0814, 0x0004);
2988                         BWN_PHY_MASK(mac, 0x0815, 0xfffb);
2989                 }
2990                 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
2991                 BWN_RF_SET(mac, 0x007a, 0x000f);
2992                 bwn_set_all_gains(mac, 3, 0, 1);
2993                 BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
2994                 DELAY(30);
2995                 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2996                 if (nrssi >= 0x20)
2997                         nrssi -= 0x40;
2998                 if (nrssi == -32) {
2999                         for (i = 0; i < 4; i++) {
3000                                 BWN_RF_WRITE(mac, 0x007b, i);
3001                                 DELAY(20);
3002                                 nrssi = (int16_t)((BWN_PHY_READ(mac,
3003                                     0x047f) >> 8) & 0x003f);
3004                                 if (nrssi >= 0x20)
3005                                         nrssi -= 0x40;
3006                                 if (nrssi > -31 && saved == 0xffff)
3007                                         saved = i;
3008                         }
3009                         if (saved == 0xffff)
3010                                 saved = 3;
3011                 } else
3012                         saved = 0;
3013         }
3014         BWN_RF_WRITE(mac, 0x007b, saved);
3015
3016         /*
3017          * Restore saved RF/PHY registers
3018          */
3019         if (phy->rev >= 6) {
3020                 for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
3021                         BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
3022                             save_phy6[phy6_idx]);
3023                 }
3024         }
3025         if (phy->rev != 1) {
3026                 for (i = 3; i < 5; i++)
3027                         BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
3028                             save_phy_comm[i]);
3029         }
3030         for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
3031                 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
3032
3033         for (i = SAVE_RF_MAX - 1; i >= 0; --i)
3034                 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
3035
3036         BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
3037         BWN_PHY_SET(mac, 0x0429, 0x8000);
3038         bwn_set_original_gains(mac);
3039         if (phy->rev >= 6) {
3040                 for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
3041                         BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
3042                             save_phy6[phy6_idx]);
3043                 }
3044         }
3045
3046         BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
3047         BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
3048         BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
3049 }
3050
3051 static void
3052 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
3053     int16_t third)
3054 {
3055         struct bwn_phy *phy = &mac->mac_phy;
3056         uint16_t i;
3057         uint16_t start = 0x08, end = 0x18;
3058         uint16_t tmp;
3059         uint16_t table;
3060
3061         if (phy->rev <= 1) {
3062                 start = 0x10;
3063                 end = 0x20;
3064         }
3065
3066         table = BWN_OFDMTAB_GAINX;
3067         if (phy->rev <= 1)
3068                 table = BWN_OFDMTAB_GAINX_R1;
3069         for (i = 0; i < 4; i++)
3070                 bwn_ofdmtab_write_2(mac, table, i, first);
3071
3072         for (i = start; i < end; i++)
3073                 bwn_ofdmtab_write_2(mac, table, i, second);
3074
3075         if (third != -1) {
3076                 tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
3077                 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
3078                 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
3079                 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
3080         }
3081         bwn_dummy_transmission(mac, 0, 1);
3082 }
3083
3084 static void
3085 bwn_set_original_gains(struct bwn_mac *mac)
3086 {
3087         struct bwn_phy *phy = &mac->mac_phy;
3088         uint16_t i, tmp;
3089         uint16_t table;
3090         uint16_t start = 0x0008, end = 0x0018;
3091
3092         if (phy->rev <= 1) {
3093                 start = 0x0010;
3094                 end = 0x0020;
3095         }
3096
3097         table = BWN_OFDMTAB_GAINX;
3098         if (phy->rev <= 1)
3099                 table = BWN_OFDMTAB_GAINX_R1;
3100         for (i = 0; i < 4; i++) {
3101                 tmp = (i & 0xfffc);
3102                 tmp |= (i & 0x0001) << 1;
3103                 tmp |= (i & 0x0002) >> 1;
3104
3105                 bwn_ofdmtab_write_2(mac, table, i, tmp);
3106         }
3107
3108         for (i = start; i < end; i++)
3109                 bwn_ofdmtab_write_2(mac, table, i, i - start);
3110
3111         BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
3112         BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
3113         BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
3114         bwn_dummy_transmission(mac, 0, 1);
3115 }
3116
3117 static void
3118 bwn_phy_hwpctl_init(struct bwn_mac *mac)
3119 {
3120         struct bwn_phy *phy = &mac->mac_phy;
3121         struct bwn_phy_g *pg = &phy->phy_g;
3122         struct bwn_rfatt old_rfatt, rfatt;
3123         struct bwn_bbatt old_bbatt, bbatt;
3124         struct bwn_softc *sc = mac->mac_sc;
3125         uint8_t old_txctl = 0;
3126
3127         KASSERT(phy->type == BWN_PHYTYPE_G,
3128             ("%s:%d: fail", __func__, __LINE__));
3129
3130         if ((sc->sc_board_info.board_vendor == PCI_VENDOR_BROADCOM) &&
3131             (sc->sc_board_info.board_type == BHND_BOARD_BU4306))
3132                 return;
3133
3134         BWN_PHY_WRITE(mac, 0x0028, 0x8018);
3135
3136         BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
3137
3138         if (!phy->gmode)
3139                 return;
3140         bwn_hwpctl_early_init(mac);
3141         if (pg->pg_curtssi == 0) {
3142                 if (phy->rf_ver == 0x2050 && phy->analog == 0) {
3143                         BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
3144                 } else {
3145                         memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
3146                         memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
3147                         old_txctl = pg->pg_txctl;
3148
3149                         bbatt.att = 11;
3150                         if (phy->rf_rev == 8) {
3151                                 rfatt.att = 15;
3152                                 rfatt.padmix = 1;
3153                         } else {
3154                                 rfatt.att = 9;
3155                                 rfatt.padmix = 0;
3156                         }
3157                         bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
3158                 }
3159                 bwn_dummy_transmission(mac, 0, 1);
3160                 pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
3161                 if (phy->rf_ver == 0x2050 && phy->analog == 0)
3162                         BWN_RF_MASK(mac, 0x0076, 0xff7b);
3163                 else
3164                         bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
3165                             &old_rfatt, old_txctl);
3166         }
3167         bwn_hwpctl_init_gphy(mac);
3168
3169         /* clear TSSI */
3170         bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
3171         bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
3172         bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
3173         bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
3174 }
3175
3176 static void
3177 bwn_hwpctl_early_init(struct bwn_mac *mac)
3178 {
3179         struct bwn_phy *phy = &mac->mac_phy;
3180
3181         if (!bwn_has_hwpctl(mac)) {
3182                 BWN_PHY_WRITE(mac, 0x047a, 0xc111);
3183                 return;
3184         }
3185
3186         BWN_PHY_MASK(mac, 0x0036, 0xfeff);
3187         BWN_PHY_WRITE(mac, 0x002f, 0x0202);
3188         BWN_PHY_SET(mac, 0x047c, 0x0002);
3189         BWN_PHY_SET(mac, 0x047a, 0xf000);
3190         if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
3191                 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
3192                 BWN_PHY_SET(mac, 0x005d, 0x8000);
3193                 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
3194                 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
3195                 BWN_PHY_SET(mac, 0x0036, 0x0400);
3196         } else {
3197                 BWN_PHY_SET(mac, 0x0036, 0x0200);
3198                 BWN_PHY_SET(mac, 0x0036, 0x0400);
3199                 BWN_PHY_MASK(mac, 0x005d, 0x7fff);
3200                 BWN_PHY_MASK(mac, 0x004f, 0xfffe);
3201                 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
3202                 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
3203                 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
3204         }
3205 }
3206
3207 static void
3208 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
3209 {
3210         struct bwn_phy *phy = &mac->mac_phy;
3211         struct bwn_phy_g *pg = &phy->phy_g;
3212         struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
3213         int i;
3214         uint16_t nr_written = 0, tmp, value;
3215         uint8_t rf, bb;
3216
3217         if (!bwn_has_hwpctl(mac)) {
3218                 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
3219                 return;
3220         }
3221
3222         BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
3223             (pg->pg_idletssi - pg->pg_curtssi));
3224         BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
3225             (pg->pg_idletssi - pg->pg_curtssi));
3226
3227         for (i = 0; i < 32; i++)
3228                 bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
3229         for (i = 32; i < 64; i++)
3230                 bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
3231         for (i = 0; i < 64; i += 2) {
3232                 value = (uint16_t) pg->pg_tssi2dbm[i];
3233                 value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
3234                 BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
3235         }
3236
3237         for (rf = 0; rf < lo->rfatt.len; rf++) {
3238                 for (bb = 0; bb < lo->bbatt.len; bb++) {
3239                         if (nr_written >= 0x40)
3240                                 return;
3241                         tmp = lo->bbatt.array[bb].att;
3242                         tmp <<= 8;
3243                         if (phy->rf_rev == 8)
3244                                 tmp |= 0x50;
3245                         else
3246                                 tmp |= 0x40;
3247                         tmp |= lo->rfatt.array[rf].att;
3248                         BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
3249                         nr_written++;
3250                 }
3251         }
3252
3253         BWN_PHY_MASK(mac, 0x0060, 0xffbf);
3254         BWN_PHY_WRITE(mac, 0x0014, 0x0000);
3255
3256         KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
3257         BWN_PHY_SET(mac, 0x0478, 0x0800);
3258         BWN_PHY_MASK(mac, 0x0478, 0xfeff);
3259         BWN_PHY_MASK(mac, 0x0801, 0xffbf);
3260
3261         bwn_phy_g_dc_lookup_init(mac, 1);
3262         bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
3263 }
3264
3265 static void
3266 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
3267 {
3268         struct bwn_softc        *sc = mac->mac_sc;
3269         int                      error;
3270
3271         if (spu != 0)
3272                 bwn_spu_workaround(mac, channel);
3273
3274         BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
3275
3276         if (channel == 14) {
3277                 uint8_t cc;
3278
3279                 error = bhnd_nvram_getvar_uint8(sc->sc_dev, BHND_NVAR_CC, &cc);
3280                 if (error) {
3281                         device_printf(sc->sc_dev, "error reading country code "
3282                             "from NVRAM, assuming channel 14 unavailable: %d\n",
3283                             error);
3284                         cc = BWN_SPROM1_CC_WORLDWIDE;
3285                 }
3286
3287                 if (cc == BWN_SPROM1_CC_JP)
3288                         bwn_hf_write(mac,
3289                             bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
3290                 else
3291                         bwn_hf_write(mac,
3292                             bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
3293                 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
3294                     BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
3295                 return;
3296         }
3297
3298         BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
3299             BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
3300 }
3301
3302 static uint16_t
3303 bwn_phy_g_chan2freq(uint8_t channel)
3304 {
3305         static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
3306
3307         KASSERT(channel >= 1 && channel <= 14,
3308             ("%s:%d: fail", __func__, __LINE__));
3309
3310         return (bwn_phy_g_rf_channels[channel - 1]);
3311 }
3312
3313 static void
3314 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
3315     const struct bwn_rfatt *rfatt, uint8_t txctl)
3316 {
3317         struct bwn_phy *phy = &mac->mac_phy;
3318         struct bwn_phy_g *pg = &phy->phy_g;
3319         struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
3320         uint16_t bb, rf;
3321         uint16_t tx_bias, tx_magn;
3322
3323         bb = bbatt->att;
3324         rf = rfatt->att;
3325         tx_bias = lo->tx_bias;
3326         tx_magn = lo->tx_magn;
3327         if (tx_bias == 0xff)
3328                 tx_bias = 0;
3329
3330         pg->pg_txctl = txctl;
3331         memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
3332         pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
3333         memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
3334         bwn_phy_g_set_bbatt(mac, bb);
3335         bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
3336         if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
3337                 BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
3338         else {
3339                 BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
3340                 BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
3341         }
3342         if (BWN_HAS_TXMAG(phy))
3343                 BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
3344         else
3345                 BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
3346         bwn_lo_g_adjust(mac);
3347 }
3348
3349 static void
3350 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
3351     uint16_t bbatt)
3352 {
3353         struct bwn_phy *phy = &mac->mac_phy;
3354
3355         if (phy->analog == 0) {
3356                 BWN_WRITE_2(mac, BWN_PHY0,
3357                     (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
3358                 return;
3359         }
3360         if (phy->analog > 1) {
3361                 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
3362                 return;
3363         }
3364         BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
3365 }
3366
3367 static uint16_t
3368 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
3369 {
3370         struct bwn_phy *phy = &mac->mac_phy;
3371         struct bwn_phy_g *pg = &phy->phy_g;
3372         struct bwn_softc *sc = mac->mac_sc;
3373         int max_lb_gain;
3374         uint16_t extlna;
3375         uint16_t i;
3376
3377         if (phy->gmode == 0)
3378                 return (0);
3379
3380         if (BWN_HAS_LOOPBACK(phy)) {
3381                 max_lb_gain = pg->pg_max_lb_gain;
3382                 max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
3383                 if (max_lb_gain >= 0x46) {
3384                         extlna = 0x3000;
3385                         max_lb_gain -= 0x46;
3386                 } else if (max_lb_gain >= 0x3a) {
3387                         extlna = 0x1000;
3388                         max_lb_gain -= 0x3a;
3389                 } else if (max_lb_gain >= 0x2e) {
3390                         extlna = 0x2000;
3391                         max_lb_gain -= 0x2e;
3392                 } else {
3393                         extlna = 0;
3394                         max_lb_gain -= 0x10;
3395                 }
3396
3397                 for (i = 0; i < 16; i++) {
3398                         max_lb_gain -= (i * 6);
3399                         if (max_lb_gain < 6)
3400                                 break;
3401                 }
3402
3403                 if ((phy->rev < 7) ||
3404                     !(sc->sc_board_info.board_flags & BHND_BFL_EXTLNA)) {
3405                         if (reg == BWN_PHY_RFOVER) {
3406                                 return (0x1b3);
3407                         } else if (reg == BWN_PHY_RFOVERVAL) {
3408                                 extlna |= (i << 8);
3409                                 switch (lpd) {
3410                                 case BWN_LPD(0, 1, 1):
3411                                         return (0x0f92);
3412                                 case BWN_LPD(0, 0, 1):
3413                                 case BWN_LPD(1, 0, 1):
3414                                         return (0x0092 | extlna);
3415                                 case BWN_LPD(1, 0, 0):
3416                                         return (0x0093 | extlna);
3417                                 }
3418                                 KASSERT(0 == 1,
3419                                     ("%s:%d: fail", __func__, __LINE__));
3420                         }
3421                         KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3422                 } else {
3423                         if (reg == BWN_PHY_RFOVER)
3424                                 return (0x9b3);
3425                         if (reg == BWN_PHY_RFOVERVAL) {
3426                                 if (extlna)
3427                                         extlna |= 0x8000;
3428                                 extlna |= (i << 8);
3429                                 switch (lpd) {
3430                                 case BWN_LPD(0, 1, 1):
3431                                         return (0x8f92);
3432                                 case BWN_LPD(0, 0, 1):
3433                                         return (0x8092 | extlna);
3434                                 case BWN_LPD(1, 0, 1):
3435                                         return (0x2092 | extlna);
3436                                 case BWN_LPD(1, 0, 0):
3437                                         return (0x2093 | extlna);
3438                                 }
3439                                 KASSERT(0 == 1,
3440                                     ("%s:%d: fail", __func__, __LINE__));
3441                         }
3442                         KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3443                 }
3444                 return (0);
3445         }
3446
3447         if ((phy->rev < 7) ||
3448             !(sc->sc_board_info.board_flags & BHND_BFL_EXTLNA)) {
3449                 if (reg == BWN_PHY_RFOVER) {
3450                         return (0x1b3);
3451                 } else if (reg == BWN_PHY_RFOVERVAL) {
3452                         switch (lpd) {
3453                         case BWN_LPD(0, 1, 1):
3454                                 return (0x0fb2);
3455                         case BWN_LPD(0, 0, 1):
3456                                 return (0x00b2);
3457                         case BWN_LPD(1, 0, 1):
3458                                 return (0x30b2);
3459                         case BWN_LPD(1, 0, 0):
3460                                 return (0x30b3);
3461                         }
3462                         KASSERT(0 == 1,
3463                             ("%s:%d: fail", __func__, __LINE__));
3464                 }
3465                 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3466         } else {
3467                 if (reg == BWN_PHY_RFOVER) {
3468                         return (0x9b3);
3469                 } else if (reg == BWN_PHY_RFOVERVAL) {
3470                         switch (lpd) {
3471                         case BWN_LPD(0, 1, 1):
3472                                 return (0x8fb2);
3473                         case BWN_LPD(0, 0, 1):
3474                                 return (0x80b2);
3475                         case BWN_LPD(1, 0, 1):
3476                                 return (0x20b2);
3477                         case BWN_LPD(1, 0, 0):
3478                                 return (0x20b3);
3479                         }
3480                         KASSERT(0 == 1,
3481                             ("%s:%d: fail", __func__, __LINE__));
3482                 }
3483                 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3484         }
3485         return (0);
3486 }
3487
3488 static void
3489 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
3490 {
3491
3492         if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
3493                 return;
3494         BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
3495             bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
3496         DELAY(1000);
3497         BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
3498 }
3499
3500 static int
3501 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
3502 {
3503         const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
3504         unsigned int a, b, c, d;
3505         unsigned int avg;
3506         uint32_t tmp;
3507
3508         tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
3509         a = tmp & 0xff;
3510         b = (tmp >> 8) & 0xff;
3511         c = (tmp >> 16) & 0xff;
3512         d = (tmp >> 24) & 0xff;
3513         if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
3514             c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
3515                 return (ENOENT);
3516         bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
3517             BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
3518             (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
3519
3520         if (ofdm) {
3521                 a = (a + 32) & 0x3f;
3522                 b = (b + 32) & 0x3f;
3523                 c = (c + 32) & 0x3f;
3524                 d = (d + 32) & 0x3f;
3525         }
3526
3527         avg = (a + b + c + d + 2) / 4;
3528         if (ofdm) {
3529                 if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
3530                     & BWN_HF_4DB_CCK_POWERBOOST)
3531                         avg = (avg >= 13) ? (avg - 13) : 0;
3532         }
3533         return (avg);
3534 }
3535
3536 static void
3537 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
3538 {
3539         struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
3540         int rfatt = *rfattp;
3541         int bbatt = *bbattp;
3542
3543         while (1) {
3544                 if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
3545                         break;
3546                 if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
3547                         break;
3548                 if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
3549                         break;
3550                 if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
3551                         break;
3552                 if (bbatt > lo->bbatt.max) {
3553                         bbatt -= 4;
3554                         rfatt += 1;
3555                         continue;
3556                 }
3557                 if (bbatt < lo->bbatt.min) {
3558                         bbatt += 4;
3559                         rfatt -= 1;
3560                         continue;
3561                 }
3562                 if (rfatt > lo->rfatt.max) {
3563                         rfatt -= 1;
3564                         bbatt += 4;
3565                         continue;
3566                 }
3567                 if (rfatt < lo->rfatt.min) {
3568                         rfatt += 1;
3569                         bbatt -= 4;
3570                         continue;
3571                 }
3572                 break;
3573         }
3574
3575         *rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
3576         *bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
3577 }
3578
3579 static void
3580 bwn_phy_lock(struct bwn_mac *mac)
3581 {
3582         struct bwn_softc *sc = mac->mac_sc;
3583         struct ieee80211com *ic = &sc->sc_ic;
3584
3585         KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 3,
3586             ("%s: unsupported rev %d", __func__, bhnd_get_hwrev(sc->sc_dev)));
3587
3588         if (ic->ic_opmode != IEEE80211_M_HOSTAP)
3589                 bwn_psctl(mac, BWN_PS_AWAKE);
3590 }
3591
3592 static void
3593 bwn_phy_unlock(struct bwn_mac *mac)
3594 {
3595         struct bwn_softc *sc = mac->mac_sc;
3596         struct ieee80211com *ic = &sc->sc_ic;
3597
3598         KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 3,
3599             ("%s: unsupported rev %d", __func__, bhnd_get_hwrev(sc->sc_dev)));
3600
3601         if (ic->ic_opmode != IEEE80211_M_HOSTAP)
3602                 bwn_psctl(mac, 0);
3603 }
3604
3605 static void
3606 bwn_rf_lock(struct bwn_mac *mac)
3607 {
3608
3609         BWN_WRITE_4(mac, BWN_MACCTL,
3610             BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
3611         BWN_READ_4(mac, BWN_MACCTL);
3612         DELAY(10);
3613 }
3614
3615 static void
3616 bwn_rf_unlock(struct bwn_mac *mac)
3617 {
3618
3619         BWN_READ_2(mac, BWN_PHYVER);
3620         BWN_WRITE_4(mac, BWN_MACCTL,
3621             BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
3622 }