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