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