bwiphy.c revision 192306
1191762Simp/*
2191762Simp * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
3191762Simp *
4191762Simp * This code is derived from software contributed to The DragonFly Project
5191762Simp * by Sepherosa Ziehau <sepherosa@gmail.com>
6191762Simp *
7191762Simp * Redistribution and use in source and binary forms, with or without
8191762Simp * modification, are permitted provided that the following conditions
9191762Simp * are met:
10191762Simp *
11191762Simp * 1. Redistributions of source code must retain the above copyright
12191762Simp *    notice, this list of conditions and the following disclaimer.
13191762Simp * 2. Redistributions in binary form must reproduce the above copyright
14191762Simp *    notice, this list of conditions and the following disclaimer in
15191762Simp *    the documentation and/or other materials provided with the
16191762Simp *    distribution.
17191762Simp * 3. Neither the name of The DragonFly Project nor the names of its
18191762Simp *    contributors may be used to endorse or promote products derived
19191762Simp *    from this software without specific, prior written permission.
20191762Simp *
21191762Simp * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22191762Simp * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23191762Simp * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24191762Simp * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25191762Simp * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26191762Simp * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27191762Simp * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28191762Simp * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29191762Simp * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30191762Simp * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31191762Simp * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32191762Simp * SUCH DAMAGE.
33191762Simp *
34191762Simp * $DragonFly: src/sys/dev/netif/bwi/bwiphy.c,v 1.5 2008/01/15 09:01:13 sephe Exp $
35191762Simp */
36191762Simp
37191762Simp#include <sys/cdefs.h>
38191762Simp__FBSDID("$FreeBSD: head/sys/dev/bwi/bwiphy.c 192306 2009-05-18 15:31:26Z imp $");
39191762Simp
40191762Simp#include "opt_inet.h"
41191762Simp
42191762Simp#include <sys/param.h>
43191762Simp#include <sys/endian.h>
44191762Simp#include <sys/kernel.h>
45191762Simp#include <sys/bus.h>
46191762Simp#include <sys/malloc.h>
47191762Simp#include <sys/proc.h>
48191762Simp#include <sys/rman.h>
49191762Simp#include <sys/socket.h>
50191762Simp#include <sys/sockio.h>
51191762Simp#include <sys/sysctl.h>
52191762Simp#include <sys/systm.h>
53191762Simp
54191762Simp#include <net/if.h>
55191762Simp#include <net/if_dl.h>
56191762Simp#include <net/if_media.h>
57191762Simp#include <net/if_types.h>
58191762Simp#include <net/if_arp.h>
59191762Simp#include <net/ethernet.h>
60191762Simp#include <net/if_llc.h>
61191762Simp
62191762Simp#include <net80211/ieee80211_var.h>
63191762Simp#include <net80211/ieee80211_radiotap.h>
64191762Simp#include <net80211/ieee80211_amrr.h>
65191762Simp
66191762Simp#include <machine/bus.h>
67191762Simp
68191762Simp#include <dev/bwi/bitops.h>
69191762Simp#include <dev/bwi/if_bwireg.h>
70191762Simp#include <dev/bwi/if_bwivar.h>
71191762Simp#include <dev/bwi/bwimac.h>
72191762Simp#include <dev/bwi/bwirf.h>
73191762Simp#include <dev/bwi/bwiphy.h>
74191762Simp
75191762Simpstatic void	bwi_phy_init_11a(struct bwi_mac *);
76191762Simpstatic void	bwi_phy_init_11g(struct bwi_mac *);
77191762Simpstatic void	bwi_phy_init_11b_rev2(struct bwi_mac *);
78191762Simpstatic void	bwi_phy_init_11b_rev4(struct bwi_mac *);
79191762Simpstatic void	bwi_phy_init_11b_rev5(struct bwi_mac *);
80191762Simpstatic void	bwi_phy_init_11b_rev6(struct bwi_mac *);
81191762Simp
82191762Simpstatic void	bwi_phy_config_11g(struct bwi_mac *);
83191762Simpstatic void	bwi_phy_config_agc(struct bwi_mac *);
84191762Simp
85191762Simpstatic void	bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t);
86191762Simpstatic void	bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t);
87191762Simp
88191762Simp#define SUP_BPHY(num)	{ .rev = num, .init = bwi_phy_init_11b_rev##num }
89191762Simp
90191762Simpstatic const struct {
91191762Simp	uint8_t	rev;
92191762Simp	void	(*init)(struct bwi_mac *);
93191762Simp} bwi_sup_bphy[] = {
94191762Simp	SUP_BPHY(2),
95191762Simp	SUP_BPHY(4),
96191762Simp	SUP_BPHY(5),
97191762Simp	SUP_BPHY(6)
98191762Simp};
99191762Simp
100191762Simp#undef SUP_BPHY
101191762Simp
102191762Simp#define BWI_PHYTBL_WRSSI	0x1000
103191762Simp#define BWI_PHYTBL_NOISE_SCALE	0x1400
104191762Simp#define BWI_PHYTBL_NOISE	0x1800
105191762Simp#define BWI_PHYTBL_ROTOR	0x2000
106191762Simp#define BWI_PHYTBL_DELAY	0x2400
107191762Simp#define BWI_PHYTBL_RSSI		0x4000
108191762Simp#define BWI_PHYTBL_SIGMA_SQ	0x5000
109191762Simp#define BWI_PHYTBL_WRSSI_REV1	0x5400
110191762Simp#define BWI_PHYTBL_FREQ		0x5800
111191762Simp
112191762Simpstatic const uint16_t	bwi_phy_freq_11g_rev1[] =
113191762Simp	{ BWI_PHY_FREQ_11G_REV1 };
114191762Simpstatic const uint16_t	bwi_phy_noise_11g_rev1[] =
115191762Simp	{ BWI_PHY_NOISE_11G_REV1 };
116191762Simpstatic const uint16_t	bwi_phy_noise_11g[] =
117191762Simp	{ BWI_PHY_NOISE_11G };
118191762Simpstatic const uint32_t	bwi_phy_rotor_11g_rev1[] =
119191762Simp	{ BWI_PHY_ROTOR_11G_REV1 };
120191762Simpstatic const uint16_t	bwi_phy_noise_scale_11g_rev2[] =
121191762Simp	{ BWI_PHY_NOISE_SCALE_11G_REV2 };
122191762Simpstatic const uint16_t	bwi_phy_noise_scale_11g_rev7[] =
123191762Simp	{ BWI_PHY_NOISE_SCALE_11G_REV7 };
124191762Simpstatic const uint16_t	bwi_phy_noise_scale_11g[] =
125191762Simp	{ BWI_PHY_NOISE_SCALE_11G };
126191762Simpstatic const uint16_t	bwi_phy_sigma_sq_11g_rev2[] =
127191762Simp	{ BWI_PHY_SIGMA_SQ_11G_REV2 };
128191762Simpstatic const uint16_t	bwi_phy_sigma_sq_11g_rev7[] =
129191762Simp	{ BWI_PHY_SIGMA_SQ_11G_REV7 };
130191762Simpstatic const uint32_t	bwi_phy_delay_11g_rev1[] =
131191762Simp	{ BWI_PHY_DELAY_11G_REV1 };
132191762Simp
133191762Simpvoid
134191762Simpbwi_phy_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data)
135191762Simp{
136191762Simp	struct bwi_softc *sc = mac->mac_sc;
137191762Simp
138191762Simp	/* TODO: 11A */
139191762Simp	CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
140191762Simp	CSR_WRITE_2(sc, BWI_PHY_DATA, data);
141191762Simp}
142191762Simp
143191762Simpuint16_t
144191762Simpbwi_phy_read(struct bwi_mac *mac, uint16_t ctrl)
145191762Simp{
146191762Simp	struct bwi_softc *sc = mac->mac_sc;
147191762Simp
148191762Simp	/* TODO: 11A */
149191762Simp	CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
150191762Simp	return CSR_READ_2(sc, BWI_PHY_DATA);
151191762Simp}
152191762Simp
153191762Simpint
154191762Simpbwi_phy_attach(struct bwi_mac *mac)
155191762Simp{
156191762Simp	struct bwi_softc *sc = mac->mac_sc;
157191762Simp	struct bwi_phy *phy = &mac->mac_phy;
158191762Simp	uint8_t phyrev, phytype, phyver;
159191762Simp	uint16_t val;
160191762Simp	int i;
161191762Simp
162191762Simp	/* Get PHY type/revision/version */
163191762Simp	val = CSR_READ_2(sc, BWI_PHYINFO);
164191762Simp	phyrev = __SHIFTOUT(val, BWI_PHYINFO_REV_MASK);
165191762Simp	phytype = __SHIFTOUT(val, BWI_PHYINFO_TYPE_MASK);
166191762Simp	phyver = __SHIFTOUT(val, BWI_PHYINFO_VER_MASK);
167191762Simp	device_printf(sc->sc_dev, "PHY: type %d, rev %d, ver %d\n",
168191762Simp		      phytype, phyrev, phyver);
169191762Simp
170191762Simp	/*
171191762Simp	 * Verify whether the revision of the PHY type is supported
172191762Simp	 * Convert PHY type to ieee80211_phymode
173191762Simp	 */
174191762Simp	switch (phytype) {
175191762Simp	case BWI_PHYINFO_TYPE_11A:
176191762Simp		if (phyrev >= 4) {
177191762Simp			device_printf(sc->sc_dev, "unsupported 11A PHY, "
178191762Simp				      "rev %u\n", phyrev);
179191762Simp			return ENXIO;
180191762Simp		}
181191762Simp		phy->phy_init = bwi_phy_init_11a;
182191762Simp		phy->phy_mode = IEEE80211_MODE_11A;
183191762Simp		phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11A;
184191762Simp		phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11A;
185191762Simp		phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11A;
186191762Simp		break;
187191762Simp	case BWI_PHYINFO_TYPE_11B:
188191762Simp#define N(arr)	(int)(sizeof(arr) / sizeof(arr[0]))
189191762Simp		for (i = 0; i < N(bwi_sup_bphy); ++i) {
190191762Simp			if (phyrev == bwi_sup_bphy[i].rev) {
191191762Simp				phy->phy_init = bwi_sup_bphy[i].init;
192191762Simp				break;
193191762Simp			}
194191762Simp		}
195191762Simp		if (i == N(bwi_sup_bphy)) {
196191762Simp			device_printf(sc->sc_dev, "unsupported 11B PHY, "
197191762Simp				      "rev %u\n", phyrev);
198191762Simp			return ENXIO;
199191762Simp		}
200191762Simp#undef N
201191762Simp		phy->phy_mode = IEEE80211_MODE_11B;
202191762Simp		break;
203191762Simp	case BWI_PHYINFO_TYPE_11G:
204191762Simp		if (phyrev > 8) {
205191762Simp			device_printf(sc->sc_dev, "unsupported 11G PHY, "
206191762Simp				      "rev %u\n", phyrev);
207191762Simp			return ENXIO;
208191762Simp		}
209191762Simp		phy->phy_init = bwi_phy_init_11g;
210191762Simp		phy->phy_mode = IEEE80211_MODE_11G;
211191762Simp		phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11G;
212191762Simp		phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11G;
213191762Simp		phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11G;
214191762Simp		break;
215191762Simp	default:
216191762Simp		device_printf(sc->sc_dev, "unsupported PHY type %d\n",
217191762Simp			      phytype);
218191762Simp		return ENXIO;
219191762Simp	}
220191762Simp	phy->phy_rev = phyrev;
221191762Simp	phy->phy_version = phyver;
222191762Simp	return 0;
223191762Simp}
224191762Simp
225191762Simpvoid
226191762Simpbwi_phy_set_bbp_atten(struct bwi_mac *mac, uint16_t bbp_atten)
227191762Simp{
228191762Simp	struct bwi_phy *phy = &mac->mac_phy;
229191762Simp	uint16_t mask = __BITS(3, 0);
230191762Simp
231191762Simp	if (phy->phy_version == 0) {
232191762Simp		CSR_FILT_SETBITS_2(mac->mac_sc, BWI_BBP_ATTEN, ~mask,
233191762Simp				   __SHIFTIN(bbp_atten, mask));
234191762Simp	} else {
235191762Simp		if (phy->phy_version > 1)
236191762Simp			mask <<= 2;
237191762Simp		else
238191762Simp			mask <<= 3;
239191762Simp		PHY_FILT_SETBITS(mac, BWI_PHYR_BBP_ATTEN, ~mask,
240191762Simp				 __SHIFTIN(bbp_atten, mask));
241191762Simp	}
242191762Simp}
243191762Simp
244191762Simpint
245191762Simpbwi_phy_calibrate(struct bwi_mac *mac)
246191762Simp{
247191762Simp	struct bwi_phy *phy = &mac->mac_phy;
248191762Simp
249191762Simp	/* Dummy read */
250191762Simp	CSR_READ_4(mac->mac_sc, BWI_MAC_STATUS);
251191762Simp
252191762Simp	/* Don't re-init */
253191762Simp	if (phy->phy_flags & BWI_PHY_F_CALIBRATED)
254191762Simp		return 0;
255191762Simp
256191762Simp	if (phy->phy_mode == IEEE80211_MODE_11G && phy->phy_rev == 1) {
257191762Simp		bwi_mac_reset(mac, 0);
258191762Simp		bwi_phy_init_11g(mac);
259191762Simp		bwi_mac_reset(mac, 1);
260191762Simp	}
261191762Simp
262191762Simp	phy->phy_flags |= BWI_PHY_F_CALIBRATED;
263191762Simp	return 0;
264191762Simp}
265191762Simp
266191762Simpstatic void
267191762Simpbwi_tbl_write_2(struct bwi_mac *mac, uint16_t ofs, uint16_t data)
268191762Simp{
269191762Simp	struct bwi_phy *phy = &mac->mac_phy;
270191762Simp
271191762Simp	KASSERT(phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0,
272191762Simp	   ("phy_tbl_ctrl %d phy_tbl_data_lo %d",
273191762Simp	     phy->phy_tbl_ctrl, phy->phy_tbl_data_lo));
274191762Simp	PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
275191762Simp	PHY_WRITE(mac, phy->phy_tbl_data_lo, data);
276191762Simp}
277191762Simp
278191762Simpstatic void
279191762Simpbwi_tbl_write_4(struct bwi_mac *mac, uint16_t ofs, uint32_t data)
280191762Simp{
281191762Simp	struct bwi_phy *phy = &mac->mac_phy;
282191762Simp
283191762Simp	KASSERT(phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 &&
284191762Simp		 phy->phy_tbl_ctrl != 0,
285191762Simp	    ("phy_tbl_data_lo %d phy_tbl_data_hi %d phy_tbl_ctrl %d",
286191762Simp	      phy->phy_tbl_data_lo, phy->phy_tbl_data_hi, phy->phy_tbl_ctrl));
287191762Simp
288191762Simp	PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
289191762Simp	PHY_WRITE(mac, phy->phy_tbl_data_hi, data >> 16);
290191762Simp	PHY_WRITE(mac, phy->phy_tbl_data_lo, data & 0xffff);
291191762Simp}
292191762Simp
293191762Simpvoid
294191762Simpbwi_nrssi_write(struct bwi_mac *mac, uint16_t ofs, int16_t data)
295191762Simp{
296191762Simp	PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs);
297191762Simp	PHY_WRITE(mac, BWI_PHYR_NRSSI_DATA, (uint16_t)data);
298191762Simp}
299191762Simp
300191762Simpint16_t
301191762Simpbwi_nrssi_read(struct bwi_mac *mac, uint16_t ofs)
302191762Simp{
303191762Simp	PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs);
304191762Simp	return (int16_t)PHY_READ(mac, BWI_PHYR_NRSSI_DATA);
305191762Simp}
306191762Simp
307191762Simpstatic void
308191762Simpbwi_phy_init_11a(struct bwi_mac *mac)
309191762Simp{
310191762Simp	/* TODO:11A */
311191762Simp}
312191762Simp
313191762Simpstatic void
314191762Simpbwi_phy_init_11g(struct bwi_mac *mac)
315191762Simp{
316191762Simp	struct bwi_softc *sc = mac->mac_sc;
317191762Simp	struct bwi_phy *phy = &mac->mac_phy;
318191762Simp	struct bwi_rf *rf = &mac->mac_rf;
319191762Simp	const struct bwi_tpctl *tpctl = &mac->mac_tpctl;
320191762Simp
321191762Simp	if (phy->phy_rev == 1)
322191762Simp		bwi_phy_init_11b_rev5(mac);
323191762Simp	else
324191762Simp		bwi_phy_init_11b_rev6(mac);
325191762Simp
326191762Simp	if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED))
327191762Simp		bwi_phy_config_11g(mac);
328191762Simp
329191762Simp	if (phy->phy_rev >= 2) {
330191762Simp		PHY_WRITE(mac, 0x814, 0);
331191762Simp		PHY_WRITE(mac, 0x815, 0);
332191762Simp
333191762Simp		if (phy->phy_rev == 2) {
334191762Simp			PHY_WRITE(mac, 0x811, 0);
335191762Simp			PHY_WRITE(mac, 0x15, 0xc0);
336191762Simp		} else if (phy->phy_rev > 5) {
337191762Simp			PHY_WRITE(mac, 0x811, 0x400);
338191762Simp			PHY_WRITE(mac, 0x15, 0xc0);
339191762Simp		}
340191762Simp	}
341191762Simp
342191762Simp	if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED)) {
343191762Simp		uint16_t val;
344191762Simp
345191762Simp		val = PHY_READ(mac, 0x400) & 0xff;
346191762Simp		if (val == 3 || val == 5) {
347191762Simp			PHY_WRITE(mac, 0x4c2, 0x1816);
348191762Simp			PHY_WRITE(mac, 0x4c3, 0x8006);
349191762Simp			if (val == 5) {
350191762Simp				PHY_FILT_SETBITS(mac, 0x4cc,
351191762Simp						 0xff, 0x1f00);
352191762Simp			}
353191762Simp		}
354191762Simp	}
355191762Simp
356191762Simp	if ((phy->phy_rev <= 2 && (phy->phy_flags & BWI_PHY_F_LINKED)) ||
357191762Simp	    phy->phy_rev >= 2)
358191762Simp		PHY_WRITE(mac, 0x47e, 0x78);
359191762Simp
360191762Simp	if (rf->rf_rev == 8) {
361191762Simp		PHY_SETBITS(mac, 0x801, 0x80);
362191762Simp		PHY_SETBITS(mac, 0x43e, 0x4);
363191762Simp	}
364191762Simp
365191762Simp	if (phy->phy_rev >= 2 && (phy->phy_flags & BWI_PHY_F_LINKED))
366191762Simp		bwi_rf_get_gains(mac);
367191762Simp
368191762Simp	if (rf->rf_rev != 8)
369191762Simp		bwi_rf_init(mac);
370191762Simp
371191762Simp	if (tpctl->tp_ctrl2 == 0xffff) {
372191762Simp		bwi_rf_lo_update(mac);
373191762Simp	} else {
374191762Simp		if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 8) {
375191762Simp			RF_WRITE(mac, 0x52,
376191762Simp				 (tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2);
377191762Simp		} else {
378192306Simp			RF_FILT_SETBITS(mac, 0x52, 0xfff0, tpctl->tp_ctrl2);
379191762Simp		}
380191762Simp
381191762Simp		if (phy->phy_rev >= 6) {
382191762Simp			PHY_FILT_SETBITS(mac, 0x36, 0xfff,
383191762Simp					 tpctl->tp_ctrl2 << 12);
384191762Simp		}
385191762Simp
386191762Simp		if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
387191762Simp			PHY_WRITE(mac, 0x2e, 0x8075);
388191762Simp		else
389191762Simp			PHY_WRITE(mac, 0x2e, 0x807f);
390191762Simp
391191762Simp		if (phy->phy_rev < 2)
392191762Simp			PHY_WRITE(mac, 0x2f, 0x101);
393191762Simp		else
394191762Simp			PHY_WRITE(mac, 0x2f, 0x202);
395191762Simp	}
396191762Simp
397191762Simp	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
398191762Simp		bwi_rf_lo_adjust(mac, tpctl);
399191762Simp		PHY_WRITE(mac, 0x80f, 0x8078);
400191762Simp	}
401191762Simp
402191762Simp	if ((sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) {
403191762Simp		bwi_rf_init_hw_nrssi_table(mac, 0xffff /* XXX */);
404191762Simp		bwi_rf_set_nrssi_thr(mac);
405191762Simp	} else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
406191762Simp		if (rf->rf_nrssi[0] == BWI_INVALID_NRSSI) {
407191762Simp			KASSERT(rf->rf_nrssi[1] == BWI_INVALID_NRSSI,
408191762Simp			    ("rf_nrssi[1] %d", rf->rf_nrssi[1]));
409191762Simp			bwi_rf_calc_nrssi_slope(mac);
410191762Simp		} else {
411191762Simp			KASSERT(rf->rf_nrssi[1] != BWI_INVALID_NRSSI,
412191762Simp			    ("rf_nrssi[1] %d", rf->rf_nrssi[1]));
413191762Simp			bwi_rf_set_nrssi_thr(mac);
414191762Simp		}
415191762Simp	}
416191762Simp
417191762Simp	if (rf->rf_rev == 8)
418191762Simp		PHY_WRITE(mac, 0x805, 0x3230);
419191762Simp
420191762Simp	bwi_mac_init_tpctl_11bg(mac);
421191762Simp
422191762Simp	if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_pkg == 2) {
423191762Simp		PHY_CLRBITS(mac, 0x429, 0x4000);
424191762Simp		PHY_CLRBITS(mac, 0x4c3, 0x8000);
425191762Simp	}
426191762Simp}
427191762Simp
428191762Simpstatic void
429191762Simpbwi_phy_init_11b_rev2(struct bwi_mac *mac)
430191762Simp{
431191762Simp	/* TODO:11B */
432191762Simp	if_printf(mac->mac_sc->sc_ifp,
433191762Simp		  "%s is not implemented yet\n", __func__);
434191762Simp}
435191762Simp
436191762Simpstatic void
437191762Simpbwi_phy_init_11b_rev4(struct bwi_mac *mac)
438191762Simp{
439191762Simp	struct bwi_softc *sc = mac->mac_sc;
440191762Simp	struct bwi_rf *rf = &mac->mac_rf;
441191762Simp	uint16_t val, ofs;
442191762Simp	u_int chan;
443191762Simp
444191762Simp	CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT);
445191762Simp
446191762Simp	PHY_WRITE(mac, 0x20, 0x301c);
447191762Simp	PHY_WRITE(mac, 0x26, 0);
448191762Simp	PHY_WRITE(mac, 0x30, 0xc6);
449191762Simp	PHY_WRITE(mac, 0x88, 0x3e00);
450191762Simp
451191762Simp	for (ofs = 0, val = 0x3c3d; ofs < 30; ++ofs, val -= 0x202)
452191762Simp		PHY_WRITE(mac, 0x89 + ofs, val);
453191762Simp
454191762Simp	CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1);
455191762Simp
456191762Simp	chan = rf->rf_curchan;
457191762Simp	if (chan == IEEE80211_CHAN_ANY)
458191762Simp		chan = 6;	/* Force to channel 6 */
459191762Simp	bwi_rf_set_chan(mac, chan, 0);
460191762Simp
461191762Simp	if (rf->rf_type != BWI_RF_T_BCM2050) {
462191762Simp		RF_WRITE(mac, 0x75, 0x80);
463191762Simp		RF_WRITE(mac, 0x79, 0x81);
464191762Simp	}
465191762Simp
466191762Simp	RF_WRITE(mac, 0x50, 0x20);
467191762Simp	RF_WRITE(mac, 0x50, 0x23);
468191762Simp
469191762Simp	if (rf->rf_type == BWI_RF_T_BCM2050) {
470191762Simp		RF_WRITE(mac, 0x50, 0x20);
471191762Simp		RF_WRITE(mac, 0x5a, 0x70);
472191762Simp		RF_WRITE(mac, 0x5b, 0x7b);
473191762Simp		RF_WRITE(mac, 0x5c, 0xb0);
474191762Simp		RF_WRITE(mac, 0x7a, 0xf);
475191762Simp		PHY_WRITE(mac, 0x38, 0x677);
476191762Simp		bwi_rf_init_bcm2050(mac);
477191762Simp	}
478191762Simp
479191762Simp	PHY_WRITE(mac, 0x14, 0x80);
480191762Simp	PHY_WRITE(mac, 0x32, 0xca);
481191762Simp	if (rf->rf_type == BWI_RF_T_BCM2050)
482191762Simp		PHY_WRITE(mac, 0x32, 0xe0);
483191762Simp	PHY_WRITE(mac, 0x35, 0x7c2);
484191762Simp
485191762Simp	bwi_rf_lo_update(mac);
486191762Simp
487191762Simp	PHY_WRITE(mac, 0x26, 0xcc00);
488191762Simp	if (rf->rf_type == BWI_RF_T_BCM2050)
489191762Simp		PHY_WRITE(mac, 0x26, 0xce00);
490191762Simp
491191762Simp	CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0x1100);
492191762Simp
493191762Simp	PHY_WRITE(mac, 0x2a, 0x88a3);
494191762Simp	if (rf->rf_type == BWI_RF_T_BCM2050)
495191762Simp		PHY_WRITE(mac, 0x2a, 0x88c2);
496191762Simp
497191762Simp	bwi_mac_set_tpctl_11bg(mac, NULL);
498191762Simp	if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
499191762Simp		bwi_rf_calc_nrssi_slope(mac);
500191762Simp		bwi_rf_set_nrssi_thr(mac);
501191762Simp	}
502191762Simp	bwi_mac_init_tpctl_11bg(mac);
503191762Simp}
504191762Simp
505191762Simpstatic void
506191762Simpbwi_phy_init_11b_rev5(struct bwi_mac *mac)
507191762Simp{
508191762Simp	struct bwi_softc *sc = mac->mac_sc;
509191762Simp	struct bwi_rf *rf = &mac->mac_rf;
510191762Simp	struct bwi_phy *phy = &mac->mac_phy;
511191762Simp	u_int orig_chan;
512191762Simp
513191762Simp	if (phy->phy_version == 1)
514191762Simp		RF_SETBITS(mac, 0x7a, 0x50);
515191762Simp
516191762Simp	if (sc->sc_pci_subvid != PCI_VENDOR_BROADCOM &&
517191762Simp	    sc->sc_pci_subdid != BWI_PCI_SUBDEVICE_BU4306) {
518191762Simp		uint16_t ofs, val;
519191762Simp
520191762Simp		val = 0x2120;
521191762Simp		for (ofs = 0xa8; ofs < 0xc7; ++ofs) {
522191762Simp			PHY_WRITE(mac, ofs, val);
523191762Simp			val += 0x202;
524191762Simp		}
525191762Simp	}
526191762Simp
527191762Simp	PHY_FILT_SETBITS(mac, 0x35, 0xf0ff, 0x700);
528191762Simp
529191762Simp	if (rf->rf_type == BWI_RF_T_BCM2050)
530191762Simp		PHY_WRITE(mac, 0x38, 0x667);
531191762Simp
532191762Simp	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
533191762Simp		if (rf->rf_type == BWI_RF_T_BCM2050) {
534191762Simp			RF_SETBITS(mac, 0x7a, 0x20);
535191762Simp			RF_SETBITS(mac, 0x51, 0x4);
536191762Simp		}
537191762Simp
538191762Simp		CSR_WRITE_2(sc, BWI_RF_ANTDIV, 0);
539191762Simp
540191762Simp		PHY_SETBITS(mac, 0x802, 0x100);
541191762Simp		PHY_SETBITS(mac, 0x42b, 0x2000);
542191762Simp		PHY_WRITE(mac, 0x1c, 0x186a);
543191762Simp
544191762Simp		PHY_FILT_SETBITS(mac, 0x13, 0xff, 0x1900);
545191762Simp		PHY_FILT_SETBITS(mac, 0x35, 0xffc0, 0x64);
546191762Simp		PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0xa);
547191762Simp	}
548191762Simp
549191762Simp	/* TODO: bad_frame_preempt? */
550191762Simp
551191762Simp	if (phy->phy_version == 1) {
552191762Simp	    	PHY_WRITE(mac, 0x26, 0xce00);
553191762Simp		PHY_WRITE(mac, 0x21, 0x3763);
554191762Simp		PHY_WRITE(mac, 0x22, 0x1bc3);
555191762Simp		PHY_WRITE(mac, 0x23, 0x6f9);
556191762Simp		PHY_WRITE(mac, 0x24, 0x37e);
557191762Simp	} else {
558191762Simp		PHY_WRITE(mac, 0x26, 0xcc00);
559191762Simp	}
560191762Simp	PHY_WRITE(mac, 0x30, 0xc6);
561191762Simp
562191762Simp	CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT);
563191762Simp
564191762Simp	if (phy->phy_version == 1)
565191762Simp		PHY_WRITE(mac, 0x20, 0x3e1c);
566191762Simp	else
567191762Simp		PHY_WRITE(mac, 0x20, 0x301c);
568191762Simp
569191762Simp	if (phy->phy_version == 0)
570191762Simp		CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1);
571191762Simp
572191762Simp	/* Force to channel 7 */
573191762Simp	orig_chan = rf->rf_curchan;
574191762Simp	bwi_rf_set_chan(mac, 7, 0);
575191762Simp
576191762Simp	if (rf->rf_type != BWI_RF_T_BCM2050) {
577191762Simp		RF_WRITE(mac, 0x75, 0x80);
578191762Simp		RF_WRITE(mac, 0x79, 0x81);
579191762Simp	}
580191762Simp
581191762Simp	RF_WRITE(mac, 0x50, 0x20);
582191762Simp	RF_WRITE(mac, 0x50, 0x23);
583191762Simp
584191762Simp	if (rf->rf_type == BWI_RF_T_BCM2050) {
585191762Simp		RF_WRITE(mac, 0x50, 0x20);
586191762Simp		RF_WRITE(mac, 0x5a, 0x70);
587191762Simp	}
588191762Simp
589191762Simp	RF_WRITE(mac, 0x5b, 0x7b);
590191762Simp	RF_WRITE(mac, 0x5c, 0xb0);
591191762Simp	RF_SETBITS(mac, 0x7a, 0x7);
592191762Simp
593191762Simp	bwi_rf_set_chan(mac, orig_chan, 0);
594191762Simp
595191762Simp	PHY_WRITE(mac, 0x14, 0x80);
596191762Simp	PHY_WRITE(mac, 0x32, 0xca);
597191762Simp	PHY_WRITE(mac, 0x2a, 0x88a3);
598191762Simp
599191762Simp	bwi_mac_set_tpctl_11bg(mac, NULL);
600191762Simp
601191762Simp	if (rf->rf_type == BWI_RF_T_BCM2050)
602191762Simp		RF_WRITE(mac, 0x5d, 0xd);
603191762Simp
604191762Simp	CSR_FILT_SETBITS_2(sc, BWI_PHY_MAGIC_REG1, 0xffc0, 0x4);
605191762Simp}
606191762Simp
607191762Simpstatic void
608191762Simpbwi_phy_init_11b_rev6(struct bwi_mac *mac)
609191762Simp{
610191762Simp	struct bwi_softc *sc = mac->mac_sc;
611191762Simp	struct bwi_rf *rf = &mac->mac_rf;
612191762Simp	struct bwi_phy *phy = &mac->mac_phy;
613191762Simp	uint16_t val, ofs;
614191762Simp	u_int orig_chan;
615191762Simp
616191762Simp	PHY_WRITE(mac, 0x3e, 0x817a);
617191762Simp	RF_SETBITS(mac, 0x7a, 0x58);
618191762Simp
619191762Simp	if (rf->rf_rev == 4 || rf->rf_rev == 5) {
620191762Simp		RF_WRITE(mac, 0x51, 0x37);
621191762Simp		RF_WRITE(mac, 0x52, 0x70);
622191762Simp		RF_WRITE(mac, 0x53, 0xb3);
623191762Simp		RF_WRITE(mac, 0x54, 0x9b);
624191762Simp		RF_WRITE(mac, 0x5a, 0x88);
625191762Simp		RF_WRITE(mac, 0x5b, 0x88);
626191762Simp		RF_WRITE(mac, 0x5d, 0x88);
627191762Simp		RF_WRITE(mac, 0x5e, 0x88);
628191762Simp		RF_WRITE(mac, 0x7d, 0x88);
629191762Simp		HFLAGS_SETBITS(mac, BWI_HFLAG_MAGIC1);
630191762Simp	} else if (rf->rf_rev == 8) {
631191762Simp		RF_WRITE(mac, 0x51, 0);
632191762Simp		RF_WRITE(mac, 0x52, 0x40);
633191762Simp		RF_WRITE(mac, 0x53, 0xb7);
634191762Simp		RF_WRITE(mac, 0x54, 0x98);
635191762Simp		RF_WRITE(mac, 0x5a, 0x88);
636191762Simp		RF_WRITE(mac, 0x5b, 0x6b);
637191762Simp		RF_WRITE(mac, 0x5c, 0xf);
638191762Simp		if (sc->sc_card_flags & BWI_CARD_F_ALT_IQ) {
639191762Simp			RF_WRITE(mac, 0x5d, 0xfa);
640191762Simp			RF_WRITE(mac, 0x5e, 0xd8);
641191762Simp		} else {
642191762Simp			RF_WRITE(mac, 0x5d, 0xf5);
643191762Simp			RF_WRITE(mac, 0x5e, 0xb8);
644191762Simp		}
645191762Simp		RF_WRITE(mac, 0x73, 0x3);
646191762Simp		RF_WRITE(mac, 0x7d, 0xa8);
647191762Simp		RF_WRITE(mac, 0x7c, 0x1);
648191762Simp		RF_WRITE(mac, 0x7e, 0x8);
649191762Simp	}
650191762Simp
651191762Simp	val = 0x1e1f;
652191762Simp	for (ofs = 0x88; ofs < 0x98; ++ofs) {
653191762Simp		PHY_WRITE(mac, ofs, val);
654191762Simp		val -= 0x202;
655191762Simp	}
656191762Simp
657191762Simp	val = 0x3e3f;
658191762Simp	for (ofs = 0x98; ofs < 0xa8; ++ofs) {
659191762Simp		PHY_WRITE(mac, ofs, val);
660191762Simp		val -= 0x202;
661191762Simp	}
662191762Simp
663191762Simp	val = 0x2120;
664191762Simp	for (ofs = 0xa8; ofs < 0xc8; ++ofs) {
665191762Simp		PHY_WRITE(mac, ofs, (val & 0x3f3f));
666191762Simp		val += 0x202;
667192046Snwhitehorn
668192046Snwhitehorn		/* XXX: delay 10 us to avoid PCI parity errors with BCM4318 */
669192042Snwhitehorn		DELAY(10);
670191762Simp	}
671191762Simp
672191762Simp	if (phy->phy_mode == IEEE80211_MODE_11G) {
673191762Simp		RF_SETBITS(mac, 0x7a, 0x20);
674191762Simp		RF_SETBITS(mac, 0x51, 0x4);
675191762Simp		PHY_SETBITS(mac, 0x802, 0x100);
676191762Simp		PHY_SETBITS(mac, 0x42b, 0x2000);
677191762Simp		PHY_WRITE(mac, 0x5b, 0);
678191762Simp		PHY_WRITE(mac, 0x5c, 0);
679191762Simp	}
680191762Simp
681191762Simp	/* Force to channel 7 */
682191762Simp	orig_chan = rf->rf_curchan;
683191762Simp	if (orig_chan >= 8)
684191762Simp		bwi_rf_set_chan(mac, 1, 0);
685191762Simp	else
686191762Simp		bwi_rf_set_chan(mac, 13, 0);
687191762Simp
688191762Simp	RF_WRITE(mac, 0x50, 0x20);
689191762Simp	RF_WRITE(mac, 0x50, 0x23);
690191762Simp
691191762Simp	DELAY(40);
692191762Simp
693191762Simp	if (rf->rf_rev < 6 || rf->rf_rev == 8) {
694191762Simp		RF_SETBITS(mac, 0x7c, 0x2);
695191762Simp		RF_WRITE(mac, 0x50, 0x20);
696191762Simp	}
697191762Simp	if (rf->rf_rev <= 2) {
698191762Simp		RF_WRITE(mac, 0x7c, 0x20);
699191762Simp		RF_WRITE(mac, 0x5a, 0x70);
700191762Simp		RF_WRITE(mac, 0x5b, 0x7b);
701191762Simp		RF_WRITE(mac, 0x5c, 0xb0);
702191762Simp	}
703191762Simp
704191762Simp	RF_FILT_SETBITS(mac, 0x7a, 0xf8, 0x7);
705191762Simp
706191762Simp	bwi_rf_set_chan(mac, orig_chan, 0);
707191762Simp
708191762Simp	PHY_WRITE(mac, 0x14, 0x200);
709191762Simp	if (rf->rf_rev >= 6)
710191762Simp		PHY_WRITE(mac, 0x2a, 0x88c2);
711191762Simp	else
712191762Simp		PHY_WRITE(mac, 0x2a, 0x8ac0);
713191762Simp	PHY_WRITE(mac, 0x38, 0x668);
714191762Simp
715191762Simp	bwi_mac_set_tpctl_11bg(mac, NULL);
716191762Simp
717191762Simp	if (rf->rf_rev <= 5) {
718191762Simp		PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0x3);
719191762Simp		if (rf->rf_rev <= 2)
720191762Simp			RF_WRITE(mac, 0x5d, 0xd);
721191762Simp	}
722191762Simp
723191762Simp	if (phy->phy_version == 4) {
724191762Simp		CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL2);
725191762Simp		PHY_CLRBITS(mac, 0x61, 0xf000);
726191762Simp	} else {
727191762Simp		PHY_FILT_SETBITS(mac, 0x2, 0xffc0, 0x4);
728191762Simp	}
729191762Simp
730191762Simp	if (phy->phy_mode == IEEE80211_MODE_11B) {
731191762Simp		CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC2);
732191762Simp		PHY_WRITE(mac, 0x16, 0x410);
733191762Simp		PHY_WRITE(mac, 0x17, 0x820);
734191762Simp		PHY_WRITE(mac, 0x62, 0x7);
735191762Simp
736191762Simp		bwi_rf_init_bcm2050(mac);
737191762Simp		bwi_rf_lo_update(mac);
738191762Simp		if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
739191762Simp			bwi_rf_calc_nrssi_slope(mac);
740191762Simp			bwi_rf_set_nrssi_thr(mac);
741191762Simp		}
742191762Simp		bwi_mac_init_tpctl_11bg(mac);
743191762Simp	} else {
744191762Simp		CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
745191762Simp	}
746191762Simp}
747191762Simp
748191762Simp#define N(arr)	(int)(sizeof(arr) / sizeof(arr[0]))
749191762Simp
750191762Simpstatic void
751191762Simpbwi_phy_config_11g(struct bwi_mac *mac)
752191762Simp{
753191762Simp	struct bwi_softc *sc = mac->mac_sc;
754191762Simp	struct bwi_phy *phy = &mac->mac_phy;
755191762Simp	const uint16_t *tbl;
756191762Simp	uint16_t wrd_ofs1, wrd_ofs2;
757191762Simp	int i, n;
758191762Simp
759191762Simp	if (phy->phy_rev == 1) {
760191762Simp		PHY_WRITE(mac, 0x406, 0x4f19);
761191762Simp		PHY_FILT_SETBITS(mac, 0x429, 0xfc3f, 0x340);
762191762Simp		PHY_WRITE(mac, 0x42c, 0x5a);
763191762Simp		PHY_WRITE(mac, 0x427, 0x1a);
764191762Simp
765191762Simp		/* Fill frequency table */
766191762Simp		for (i = 0; i < N(bwi_phy_freq_11g_rev1); ++i) {
767191762Simp			bwi_tbl_write_2(mac, BWI_PHYTBL_FREQ + i,
768191762Simp					bwi_phy_freq_11g_rev1[i]);
769191762Simp		}
770191762Simp
771191762Simp		/* Fill noise table */
772191762Simp		for (i = 0; i < N(bwi_phy_noise_11g_rev1); ++i) {
773191762Simp			bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i,
774191762Simp					bwi_phy_noise_11g_rev1[i]);
775191762Simp		}
776191762Simp
777191762Simp		/* Fill rotor table */
778191762Simp		for (i = 0; i < N(bwi_phy_rotor_11g_rev1); ++i) {
779191762Simp			/* NB: data length is 4 bytes */
780191762Simp			bwi_tbl_write_4(mac, BWI_PHYTBL_ROTOR + i,
781191762Simp					bwi_phy_rotor_11g_rev1[i]);
782191762Simp		}
783191762Simp	} else {
784191762Simp		bwi_nrssi_write(mac, 0xba98, (int16_t)0x7654); /* XXX */
785191762Simp
786191762Simp		if (phy->phy_rev == 2) {
787191762Simp			PHY_WRITE(mac, 0x4c0, 0x1861);
788191762Simp			PHY_WRITE(mac, 0x4c1, 0x271);
789191762Simp		} else if (phy->phy_rev > 2) {
790191762Simp			PHY_WRITE(mac, 0x4c0, 0x98);
791191762Simp			PHY_WRITE(mac, 0x4c1, 0x70);
792191762Simp			PHY_WRITE(mac, 0x4c9, 0x80);
793191762Simp		}
794191762Simp		PHY_SETBITS(mac, 0x42b, 0x800);
795191762Simp
796191762Simp		/* Fill RSSI table */
797191762Simp		for (i = 0; i < 64; ++i)
798191762Simp			bwi_tbl_write_2(mac, BWI_PHYTBL_RSSI + i, i);
799191762Simp
800191762Simp		/* Fill noise table */
801191762Simp		for (i = 0; i < sizeof(bwi_phy_noise_11g); ++i) {
802191762Simp			bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i,
803191762Simp					bwi_phy_noise_11g[i]);
804191762Simp		}
805191762Simp	}
806191762Simp
807191762Simp	/*
808191762Simp	 * Fill noise scale table
809191762Simp	 */
810191762Simp	if (phy->phy_rev <= 2) {
811191762Simp		tbl = bwi_phy_noise_scale_11g_rev2;
812191762Simp		n = N(bwi_phy_noise_scale_11g_rev2);
813191762Simp	} else if (phy->phy_rev >= 7 && (PHY_READ(mac, 0x449) & 0x200)) {
814191762Simp		tbl = bwi_phy_noise_scale_11g_rev7;
815191762Simp		n = N(bwi_phy_noise_scale_11g_rev7);
816191762Simp	} else {
817191762Simp		tbl = bwi_phy_noise_scale_11g;
818191762Simp		n = N(bwi_phy_noise_scale_11g);
819191762Simp	}
820191762Simp	for (i = 0; i < n; ++i)
821191762Simp		bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE_SCALE + i, tbl[i]);
822191762Simp
823191762Simp	/*
824191762Simp	 * Fill sigma square table
825191762Simp	 */
826191762Simp	if (phy->phy_rev == 2) {
827191762Simp		tbl = bwi_phy_sigma_sq_11g_rev2;
828191762Simp		n = N(bwi_phy_sigma_sq_11g_rev2);
829191762Simp	} else if (phy->phy_rev > 2 && phy->phy_rev <= 8) {
830191762Simp		tbl = bwi_phy_sigma_sq_11g_rev7;
831191762Simp		n = N(bwi_phy_sigma_sq_11g_rev7);
832191762Simp	} else {
833191762Simp		tbl = NULL;
834191762Simp		n = 0;
835191762Simp	}
836191762Simp	for (i = 0; i < n; ++i)
837191762Simp		bwi_tbl_write_2(mac, BWI_PHYTBL_SIGMA_SQ + i, tbl[i]);
838191762Simp
839191762Simp	if (phy->phy_rev == 1) {
840191762Simp		/* Fill delay table */
841191762Simp		for (i = 0; i < N(bwi_phy_delay_11g_rev1); ++i) {
842191762Simp			bwi_tbl_write_4(mac, BWI_PHYTBL_DELAY + i,
843191762Simp					bwi_phy_delay_11g_rev1[i]);
844191762Simp		}
845191762Simp
846191762Simp		/* Fill WRSSI (Wide-Band RSSI) table */
847191762Simp		for (i = 4; i < 20; ++i)
848191762Simp			bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI_REV1 + i, 0x20);
849191762Simp
850191762Simp		bwi_phy_config_agc(mac);
851191762Simp
852191762Simp		wrd_ofs1 = 0x5001;
853191762Simp		wrd_ofs2 = 0x5002;
854191762Simp	} else {
855191762Simp		/* Fill WRSSI (Wide-Band RSSI) table */
856191762Simp		for (i = 0; i < 0x20; ++i)
857191762Simp			bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI + i, 0x820);
858191762Simp
859191762Simp		bwi_phy_config_agc(mac);
860191762Simp
861191762Simp		PHY_READ(mac, 0x400);	/* Dummy read */
862191762Simp		PHY_WRITE(mac, 0x403, 0x1000);
863191762Simp		bwi_tbl_write_2(mac, 0x3c02, 0xf);
864191762Simp		bwi_tbl_write_2(mac, 0x3c03, 0x14);
865191762Simp
866191762Simp		wrd_ofs1 = 0x401;
867191762Simp		wrd_ofs2 = 0x402;
868191762Simp	}
869191762Simp
870191762Simp	if (!(BWI_IS_BRCM_BU4306(sc) && sc->sc_pci_revid == 0x17)) {
871191762Simp		bwi_tbl_write_2(mac, wrd_ofs1, 0x2);
872191762Simp		bwi_tbl_write_2(mac, wrd_ofs2, 0x1);
873191762Simp	}
874191762Simp
875191762Simp	/* phy->phy_flags & BWI_PHY_F_LINKED ? */
876191762Simp	if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
877191762Simp		PHY_WRITE(mac, 0x46e, 0x3cf);
878191762Simp}
879191762Simp
880191762Simp#undef N
881191762Simp
882191762Simp/*
883191762Simp * Configure Automatic Gain Controller
884191762Simp */
885191762Simpstatic void
886191762Simpbwi_phy_config_agc(struct bwi_mac *mac)
887191762Simp{
888191762Simp	struct bwi_phy *phy = &mac->mac_phy;
889191762Simp	uint16_t ofs;
890191762Simp
891191762Simp	ofs = phy->phy_rev == 1 ? 0x4c00 : 0;
892191762Simp
893191762Simp	bwi_tbl_write_2(mac, ofs, 0xfe);
894191762Simp	bwi_tbl_write_2(mac, ofs + 1, 0xd);
895191762Simp	bwi_tbl_write_2(mac, ofs + 2, 0x13);
896191762Simp	bwi_tbl_write_2(mac, ofs + 3, 0x19);
897191762Simp
898191762Simp	if (phy->phy_rev == 1) {
899191762Simp		bwi_tbl_write_2(mac, 0x1800, 0x2710);
900191762Simp		bwi_tbl_write_2(mac, 0x1801, 0x9b83);
901191762Simp		bwi_tbl_write_2(mac, 0x1802, 0x9b83);
902191762Simp		bwi_tbl_write_2(mac, 0x1803, 0xf8d);
903191762Simp		PHY_WRITE(mac, 0x455, 0x4);
904191762Simp	}
905191762Simp
906191762Simp	PHY_FILT_SETBITS(mac, 0x4a5, 0xff, 0x5700);
907191762Simp	PHY_FILT_SETBITS(mac, 0x41a, 0xff80, 0xf);
908191762Simp	PHY_FILT_SETBITS(mac, 0x41a, 0xc07f, 0x2b80);
909191762Simp	PHY_FILT_SETBITS(mac, 0x48c, 0xf0ff, 0x300);
910191762Simp
911191762Simp	RF_SETBITS(mac, 0x7a, 0x8);
912191762Simp
913191762Simp	PHY_FILT_SETBITS(mac, 0x4a0, 0xfff0, 0x8);
914191762Simp	PHY_FILT_SETBITS(mac, 0x4a1, 0xf0ff, 0x600);
915191762Simp	PHY_FILT_SETBITS(mac, 0x4a2, 0xf0ff, 0x700);
916191762Simp	PHY_FILT_SETBITS(mac, 0x4a0, 0xf0ff, 0x100);
917191762Simp
918191762Simp	if (phy->phy_rev == 1)
919191762Simp		PHY_FILT_SETBITS(mac, 0x4a2, 0xfff0, 0x7);
920191762Simp
921191762Simp	PHY_FILT_SETBITS(mac, 0x488, 0xff00, 0x1c);
922191762Simp	PHY_FILT_SETBITS(mac, 0x488, 0xc0ff, 0x200);
923191762Simp	PHY_FILT_SETBITS(mac, 0x496, 0xff00, 0x1c);
924191762Simp	PHY_FILT_SETBITS(mac, 0x489, 0xff00, 0x20);
925191762Simp	PHY_FILT_SETBITS(mac, 0x489, 0xc0ff, 0x200);
926191762Simp	PHY_FILT_SETBITS(mac, 0x482, 0xff00, 0x2e);
927191762Simp	PHY_FILT_SETBITS(mac, 0x496, 0xff, 0x1a00);
928191762Simp	PHY_FILT_SETBITS(mac, 0x481, 0xff00, 0x28);
929191762Simp	PHY_FILT_SETBITS(mac, 0x481, 0xff, 0x2c00);
930191762Simp
931191762Simp	if (phy->phy_rev == 1) {
932191762Simp		PHY_WRITE(mac, 0x430, 0x92b);
933191762Simp		PHY_FILT_SETBITS(mac, 0x41b, 0xffe1, 0x2);
934191762Simp	} else {
935191762Simp		PHY_CLRBITS(mac, 0x41b, 0x1e);
936191762Simp		PHY_WRITE(mac, 0x41f, 0x287a);
937191762Simp		PHY_FILT_SETBITS(mac, 0x420, 0xfff0, 0x4);
938191762Simp
939191762Simp		if (phy->phy_rev >= 6) {
940191762Simp			PHY_WRITE(mac, 0x422, 0x287a);
941191762Simp			PHY_FILT_SETBITS(mac, 0x420, 0xfff, 0x3000);
942191762Simp		}
943191762Simp	}
944191762Simp
945191762Simp	PHY_FILT_SETBITS(mac, 0x4a8, 0x8080, 0x7874);
946191762Simp	PHY_WRITE(mac, 0x48e, 0x1c00);
947191762Simp
948191762Simp	if (phy->phy_rev == 1) {
949191762Simp		PHY_FILT_SETBITS(mac, 0x4ab, 0xf0ff, 0x600);
950191762Simp		PHY_WRITE(mac, 0x48b, 0x5e);
951191762Simp		PHY_FILT_SETBITS(mac, 0x48c, 0xff00, 0x1e);
952191762Simp		PHY_WRITE(mac, 0x48d, 0x2);
953191762Simp	}
954191762Simp
955191762Simp	bwi_tbl_write_2(mac, ofs + 0x800, 0);
956191762Simp	bwi_tbl_write_2(mac, ofs + 0x801, 7);
957191762Simp	bwi_tbl_write_2(mac, ofs + 0x802, 16);
958191762Simp	bwi_tbl_write_2(mac, ofs + 0x803, 28);
959191762Simp
960191762Simp	if (phy->phy_rev >= 6) {
961191762Simp		PHY_CLRBITS(mac, 0x426, 0x3);
962191762Simp		PHY_CLRBITS(mac, 0x426, 0x1000);
963191762Simp	}
964191762Simp}
965191762Simp
966191762Simpvoid
967191762Simpbwi_set_gains(struct bwi_mac *mac, const struct bwi_gains *gains)
968191762Simp{
969191762Simp	struct bwi_phy *phy = &mac->mac_phy;
970191762Simp	uint16_t tbl_gain_ofs1, tbl_gain_ofs2, tbl_gain;
971191762Simp	int i;
972191762Simp
973191762Simp	if (phy->phy_rev <= 1) {
974191762Simp		tbl_gain_ofs1 = 0x5000;
975191762Simp		tbl_gain_ofs2 = tbl_gain_ofs1 + 16;
976191762Simp	} else {
977191762Simp		tbl_gain_ofs1 = 0x400;
978191762Simp		tbl_gain_ofs2 = tbl_gain_ofs1 + 8;
979191762Simp	}
980191762Simp
981191762Simp	for (i = 0; i < 4; ++i) {
982191762Simp		if (gains != NULL) {
983191762Simp			tbl_gain = gains->tbl_gain1;
984191762Simp		} else {
985191762Simp			/* Bit swap */
986191762Simp			tbl_gain = (i & 0x1) << 1;
987191762Simp			tbl_gain |= (i & 0x2) >> 1;
988191762Simp		}
989191762Simp		bwi_tbl_write_2(mac, tbl_gain_ofs1 + i, tbl_gain);
990191762Simp	}
991191762Simp
992191762Simp	for (i = 0; i < 16; ++i) {
993191762Simp		if (gains != NULL)
994191762Simp			tbl_gain = gains->tbl_gain2;
995191762Simp		else
996191762Simp			tbl_gain = i;
997191762Simp		bwi_tbl_write_2(mac, tbl_gain_ofs2 + i, tbl_gain);
998191762Simp	}
999191762Simp
1000191762Simp	if (gains == NULL || (gains != NULL && gains->phy_gain != -1)) {
1001191762Simp		uint16_t phy_gain1, phy_gain2;
1002191762Simp
1003191762Simp		if (gains != NULL) {
1004191762Simp			phy_gain1 =
1005191762Simp			((uint16_t)gains->phy_gain << 14) |
1006191762Simp			((uint16_t)gains->phy_gain << 6);
1007191762Simp			phy_gain2 = phy_gain1;
1008191762Simp		} else {
1009191762Simp			phy_gain1 = 0x4040;
1010191762Simp			phy_gain2 = 0x4000;
1011191762Simp		}
1012191762Simp		PHY_FILT_SETBITS(mac, 0x4a0, 0xbfbf, phy_gain1);
1013191762Simp		PHY_FILT_SETBITS(mac, 0x4a1, 0xbfbf, phy_gain1);
1014191762Simp		PHY_FILT_SETBITS(mac, 0x4a2, 0xbfbf, phy_gain2);
1015191762Simp	}
1016191762Simp	bwi_mac_dummy_xmit(mac);
1017191762Simp}
1018191762Simp
1019191762Simpvoid
1020191762Simpbwi_phy_clear_state(struct bwi_phy *phy)
1021191762Simp{
1022191762Simp	phy->phy_flags &= ~BWI_CLEAR_PHY_FLAGS;
1023191762Simp}
1024