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