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