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