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