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