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