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