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