1/*-
2 * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer,
10 *    without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 *    redistribution must be conditioned upon including a substantially
14 *    similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32
33#include "opt_bwn.h"
34#include "opt_wlan.h"
35
36/*
37 * The Broadcom Wireless LAN controller driver.
38 */
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/malloc.h>
44#include <sys/module.h>
45#include <sys/endian.h>
46#include <sys/errno.h>
47#include <sys/firmware.h>
48#include <sys/lock.h>
49#include <sys/mutex.h>
50#include <machine/bus.h>
51#include <machine/resource.h>
52#include <sys/bus.h>
53#include <sys/rman.h>
54#include <sys/socket.h>
55#include <sys/sockio.h>
56
57#include <net/ethernet.h>
58#include <net/if.h>
59#include <net/if_var.h>
60#include <net/if_arp.h>
61#include <net/if_dl.h>
62#include <net/if_llc.h>
63#include <net/if_media.h>
64#include <net/if_types.h>
65
66#include <dev/pci/pcivar.h>
67#include <dev/pci/pcireg.h>
68
69#include <net80211/ieee80211_var.h>
70#include <net80211/ieee80211_radiotap.h>
71#include <net80211/ieee80211_regdomain.h>
72#include <net80211/ieee80211_phy.h>
73#include <net80211/ieee80211_ratectl.h>
74
75#include <dev/bhnd/bhnd.h>
76#include <dev/bhnd/bhnd_ids.h>
77
78#include <dev/bhnd/cores/pmu/bhnd_pmu.h>
79
80#include <dev/bwn/if_bwnreg.h>
81#include <dev/bwn/if_bwnvar.h>
82
83#include <dev/bwn/if_bwn_debug.h>
84#include <dev/bwn/if_bwn_misc.h>
85#include <dev/bwn/if_bwn_util.h>
86#include <dev/bwn/if_bwn_phy_common.h>
87#include <dev/bwn/if_bwn_phy_lp.h>
88
89#include "bhnd_nvram_map.h"
90
91static int	bwn_phy_lp_readsprom(struct bwn_mac *);
92static void	bwn_phy_lp_bbinit(struct bwn_mac *);
93static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
94static void	bwn_phy_lp_calib(struct bwn_mac *);
95static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
96static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
97static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
98static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
99static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
100static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
101static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
102static void	bwn_phy_lp_bugfix(struct bwn_mac *);
103static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
104static void	bwn_phy_lp_tblinit(struct bwn_mac *);
105static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
106static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
107static int	bwn_phy_lp_b2062_init(struct bwn_mac *);
108static int	bwn_phy_lp_b2063_init(struct bwn_mac *);
109static int	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
110static int	bwn_phy_lp_rccal_r12(struct bwn_mac *);
111static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
112static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
113static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
114static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
115static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
116		    const void *);
117static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
118static struct bwn_txgain
119		bwn_phy_lp_get_txgain(struct bwn_mac *);
120static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
121static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
122static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
123static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
124static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
125static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
126static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
127static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
128static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
129static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
130static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
131static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
132static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
133static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
134static int	bwn_phy_lp_loopback(struct bwn_mac *);
135static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
136static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
137		    int);
138static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
139		    struct bwn_phy_lp_iq_est *);
140static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
141static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
142static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
143static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
144static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
145static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
146static uint8_t	bwn_nbits(int32_t);
147static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
148		    struct bwn_txgain_entry *);
149static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
150		    struct bwn_txgain_entry);
151static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
152		    struct bwn_txgain_entry);
153static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
154		    struct bwn_txgain_entry);
155
156static const uint8_t bwn_b2063_chantable_data[33][12] = {
157	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
158	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
159	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
160	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
161	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
162	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
163	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
164	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
165	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
166	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
167	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
168	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
169	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
170	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
171	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
172	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
173	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
174	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
175	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
176	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
177	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
178	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
179	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
180	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
181	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
182	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
183	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
184	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
185	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
186	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
187	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
188	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
189	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
190};
191
192static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
193	{ 1, 2412, bwn_b2063_chantable_data[0] },
194	{ 2, 2417, bwn_b2063_chantable_data[0] },
195	{ 3, 2422, bwn_b2063_chantable_data[0] },
196	{ 4, 2427, bwn_b2063_chantable_data[1] },
197	{ 5, 2432, bwn_b2063_chantable_data[1] },
198	{ 6, 2437, bwn_b2063_chantable_data[1] },
199	{ 7, 2442, bwn_b2063_chantable_data[1] },
200	{ 8, 2447, bwn_b2063_chantable_data[1] },
201	{ 9, 2452, bwn_b2063_chantable_data[2] },
202	{ 10, 2457, bwn_b2063_chantable_data[2] },
203	{ 11, 2462, bwn_b2063_chantable_data[3] },
204	{ 12, 2467, bwn_b2063_chantable_data[3] },
205	{ 13, 2472, bwn_b2063_chantable_data[3] },
206	{ 14, 2484, bwn_b2063_chantable_data[4] },
207	{ 34, 5170, bwn_b2063_chantable_data[5] },
208	{ 36, 5180, bwn_b2063_chantable_data[6] },
209	{ 38, 5190, bwn_b2063_chantable_data[7] },
210	{ 40, 5200, bwn_b2063_chantable_data[8] },
211	{ 42, 5210, bwn_b2063_chantable_data[9] },
212	{ 44, 5220, bwn_b2063_chantable_data[10] },
213	{ 46, 5230, bwn_b2063_chantable_data[11] },
214	{ 48, 5240, bwn_b2063_chantable_data[12] },
215	{ 52, 5260, bwn_b2063_chantable_data[13] },
216	{ 56, 5280, bwn_b2063_chantable_data[14] },
217	{ 60, 5300, bwn_b2063_chantable_data[14] },
218	{ 64, 5320, bwn_b2063_chantable_data[15] },
219	{ 100, 5500, bwn_b2063_chantable_data[16] },
220	{ 104, 5520, bwn_b2063_chantable_data[17] },
221	{ 108, 5540, bwn_b2063_chantable_data[18] },
222	{ 112, 5560, bwn_b2063_chantable_data[19] },
223	{ 116, 5580, bwn_b2063_chantable_data[20] },
224	{ 120, 5600, bwn_b2063_chantable_data[21] },
225	{ 124, 5620, bwn_b2063_chantable_data[21] },
226	{ 128, 5640, bwn_b2063_chantable_data[22] },
227	{ 132, 5660, bwn_b2063_chantable_data[22] },
228	{ 136, 5680, bwn_b2063_chantable_data[22] },
229	{ 140, 5700, bwn_b2063_chantable_data[23] },
230	{ 149, 5745, bwn_b2063_chantable_data[23] },
231	{ 153, 5765, bwn_b2063_chantable_data[23] },
232	{ 157, 5785, bwn_b2063_chantable_data[23] },
233	{ 161, 5805, bwn_b2063_chantable_data[23] },
234	{ 165, 5825, bwn_b2063_chantable_data[23] },
235	{ 184, 4920, bwn_b2063_chantable_data[24] },
236	{ 188, 4940, bwn_b2063_chantable_data[25] },
237	{ 192, 4960, bwn_b2063_chantable_data[26] },
238	{ 196, 4980, bwn_b2063_chantable_data[27] },
239	{ 200, 5000, bwn_b2063_chantable_data[28] },
240	{ 204, 5020, bwn_b2063_chantable_data[29] },
241	{ 208, 5040, bwn_b2063_chantable_data[30] },
242	{ 212, 5060, bwn_b2063_chantable_data[31] },
243	{ 216, 5080, bwn_b2063_chantable_data[32] }
244};
245
246static const uint8_t bwn_b2062_chantable_data[22][12] = {
247	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
248	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
249	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
250	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
251	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
252	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
253	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
254	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
255	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
256	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
257	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
258	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
259	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
260	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
261	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
262	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
263	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
264	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
265	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
266	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
267	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
268	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
269};
270
271static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
272	{ 1, 2412, bwn_b2062_chantable_data[0] },
273	{ 2, 2417, bwn_b2062_chantable_data[0] },
274	{ 3, 2422, bwn_b2062_chantable_data[0] },
275	{ 4, 2427, bwn_b2062_chantable_data[0] },
276	{ 5, 2432, bwn_b2062_chantable_data[0] },
277	{ 6, 2437, bwn_b2062_chantable_data[0] },
278	{ 7, 2442, bwn_b2062_chantable_data[0] },
279	{ 8, 2447, bwn_b2062_chantable_data[0] },
280	{ 9, 2452, bwn_b2062_chantable_data[0] },
281	{ 10, 2457, bwn_b2062_chantable_data[0] },
282	{ 11, 2462, bwn_b2062_chantable_data[0] },
283	{ 12, 2467, bwn_b2062_chantable_data[0] },
284	{ 13, 2472, bwn_b2062_chantable_data[0] },
285	{ 14, 2484, bwn_b2062_chantable_data[0] },
286	{ 34, 5170, bwn_b2062_chantable_data[1] },
287	{ 38, 5190, bwn_b2062_chantable_data[2] },
288	{ 42, 5210, bwn_b2062_chantable_data[2] },
289	{ 46, 5230, bwn_b2062_chantable_data[3] },
290	{ 36, 5180, bwn_b2062_chantable_data[4] },
291	{ 40, 5200, bwn_b2062_chantable_data[5] },
292	{ 44, 5220, bwn_b2062_chantable_data[6] },
293	{ 48, 5240, bwn_b2062_chantable_data[3] },
294	{ 52, 5260, bwn_b2062_chantable_data[3] },
295	{ 56, 5280, bwn_b2062_chantable_data[3] },
296	{ 60, 5300, bwn_b2062_chantable_data[7] },
297	{ 64, 5320, bwn_b2062_chantable_data[8] },
298	{ 100, 5500, bwn_b2062_chantable_data[9] },
299	{ 104, 5520, bwn_b2062_chantable_data[10] },
300	{ 108, 5540, bwn_b2062_chantable_data[10] },
301	{ 112, 5560, bwn_b2062_chantable_data[10] },
302	{ 116, 5580, bwn_b2062_chantable_data[11] },
303	{ 120, 5600, bwn_b2062_chantable_data[12] },
304	{ 124, 5620, bwn_b2062_chantable_data[12] },
305	{ 128, 5640, bwn_b2062_chantable_data[12] },
306	{ 132, 5660, bwn_b2062_chantable_data[12] },
307	{ 136, 5680, bwn_b2062_chantable_data[12] },
308	{ 140, 5700, bwn_b2062_chantable_data[12] },
309	{ 149, 5745, bwn_b2062_chantable_data[12] },
310	{ 153, 5765, bwn_b2062_chantable_data[12] },
311	{ 157, 5785, bwn_b2062_chantable_data[12] },
312	{ 161, 5805, bwn_b2062_chantable_data[12] },
313	{ 165, 5825, bwn_b2062_chantable_data[12] },
314	{ 184, 4920, bwn_b2062_chantable_data[13] },
315	{ 188, 4940, bwn_b2062_chantable_data[14] },
316	{ 192, 4960, bwn_b2062_chantable_data[15] },
317	{ 196, 4980, bwn_b2062_chantable_data[16] },
318	{ 200, 5000, bwn_b2062_chantable_data[17] },
319	{ 204, 5020, bwn_b2062_chantable_data[18] },
320	{ 208, 5040, bwn_b2062_chantable_data[19] },
321	{ 212, 5060, bwn_b2062_chantable_data[20] },
322	{ 216, 5080, bwn_b2062_chantable_data[21] }
323};
324
325/* for LP PHY */
326static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
327	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
328	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
329	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
330	{ 13, -66, 13 }, { 14, -66, 13 },
331};
332
333/* for LP PHY */
334static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
335	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
336	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
337	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
338	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
339	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
340	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
341	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
342	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
343	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
344	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
345	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
346	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
347	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
348};
349
350static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
351
352static const uint8_t bwn_tab_sigsq_tbl[] = {
353	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
354	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
355	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
356	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
357	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
358	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
359};
360
361static const uint8_t bwn_tab_pllfrac_tbl[] = {
362	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
363	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
364};
365
366static const uint16_t bwn_tabl_iqlocal_tbl[] = {
367	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
368	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
369	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
370	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
371	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
372	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
373	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
374	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
375	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
376	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
377	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
378	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
379};
380
381void
382bwn_phy_lp_init_pre(struct bwn_mac *mac)
383{
384	struct bwn_phy *phy = &mac->mac_phy;
385	struct bwn_phy_lp *plp = &phy->phy_lp;
386
387	plp->plp_antenna = BWN_ANT_DEFAULT;
388}
389
390int
391bwn_phy_lp_init(struct bwn_mac *mac)
392{
393	static const struct bwn_stxtable tables[] = {
394		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
395		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
396		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
397		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
398		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
399		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
400		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
401		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
402		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
403		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
404		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
405		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
406		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
407		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
408		{ 2, 11, 0x40, 0, 0x0f }
409	};
410	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
411	struct bwn_softc *sc = mac->mac_sc;
412	const struct bwn_stxtable *st;
413	struct ieee80211com *ic = &sc->sc_ic;
414	int i, error;
415	uint16_t tmp;
416
417	/* All LP-PHY devices have a PMU */
418	if (sc->sc_pmu == NULL) {
419		device_printf(sc->sc_dev, "no PMU; cannot configure PAREF "
420		    "LDO\n");
421		return (ENXIO);
422	}
423
424	if ((error = bwn_phy_lp_readsprom(mac)))
425		return (error);
426
427	bwn_phy_lp_bbinit(mac);
428
429	/* initialize RF */
430	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
431	DELAY(1);
432	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
433	DELAY(1);
434
435	if (mac->mac_phy.rf_ver == 0x2062) {
436		if ((error = bwn_phy_lp_b2062_init(mac)))
437			return (error);
438	} else {
439		if ((error = bwn_phy_lp_b2063_init(mac)))
440			return (error);
441
442		/* synchronize stx table. */
443		for (i = 0; i < N(tables); i++) {
444			st = &tables[i];
445			tmp = BWN_RF_READ(mac, st->st_rfaddr);
446			tmp >>= st->st_rfshift;
447			tmp <<= st->st_physhift;
448			BWN_PHY_SETMASK(mac,
449			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
450			    ~(st->st_mask << st->st_physhift), tmp);
451		}
452
453		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
454		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
455	}
456
457	/* calibrate RC */
458	if (mac->mac_phy.rev >= 2) {
459		if ((error = bwn_phy_lp_rxcal_r2(mac)))
460			return (error);
461	} else if (!plp->plp_rccap) {
462		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
463			if ((error = bwn_phy_lp_rccal_r12(mac)))
464				return (error);
465		}
466	} else
467		bwn_phy_lp_set_rccap(mac);
468
469	error = bwn_phy_lp_switch_channel(mac, 7);
470	if (error)
471		device_printf(sc->sc_dev,
472		    "failed to change channel 7 (%d)\n", error);
473	bwn_phy_lp_txpctl_init(mac);
474	bwn_phy_lp_calib(mac);
475	return (0);
476}
477
478uint16_t
479bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
480{
481
482	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
483	return (BWN_READ_2(mac, BWN_PHYDATA));
484}
485
486void
487bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
488{
489
490	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
491	BWN_WRITE_2(mac, BWN_PHYDATA, value);
492}
493
494void
495bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
496    uint16_t set)
497{
498
499	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
500	BWN_WRITE_2(mac, BWN_PHYDATA,
501	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
502}
503
504uint16_t
505bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
506{
507
508	KASSERT(reg != 1, ("unaccessible register %d", reg));
509	if (mac->mac_phy.rev < 2 && reg != 0x4001)
510		reg |= 0x100;
511	if (mac->mac_phy.rev >= 2)
512		reg |= 0x200;
513	BWN_WRITE_2(mac, BWN_RFCTL, reg);
514	return BWN_READ_2(mac, BWN_RFDATALO);
515}
516
517void
518bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
519{
520
521	KASSERT(reg != 1, ("unaccessible register %d", reg));
522	BWN_WRITE_2(mac, BWN_RFCTL, reg);
523	BWN_WRITE_2(mac, BWN_RFDATALO, value);
524}
525
526void
527bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
528{
529
530	if (on) {
531		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
532		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
533		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
534		return;
535	}
536
537	if (mac->mac_phy.rev >= 2) {
538		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
539		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
540		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
541		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
542		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
543		return;
544	}
545
546	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
547	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
548	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
549	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
550}
551
552int
553bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
554{
555	struct bwn_phy *phy = &mac->mac_phy;
556	struct bwn_phy_lp *plp = &phy->phy_lp;
557	int error;
558
559	if (phy->rf_ver == 0x2063) {
560		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
561		if (error)
562			return (error);
563	} else {
564		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
565		if (error)
566			return (error);
567		bwn_phy_lp_set_anafilter(mac, chan);
568		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
569	}
570
571	plp->plp_chan = chan;
572	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
573	return (0);
574}
575
576uint32_t
577bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
578{
579	struct bwn_softc *sc = mac->mac_sc;
580	struct ieee80211com *ic = &sc->sc_ic;
581
582	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
583}
584
585void
586bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
587{
588	struct bwn_phy *phy = &mac->mac_phy;
589	struct bwn_phy_lp *plp = &phy->phy_lp;
590
591	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
592		return;
593
594	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
595	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
596	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
597	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
598	plp->plp_antenna = antenna;
599}
600
601void
602bwn_phy_lp_task_60s(struct bwn_mac *mac)
603{
604
605	bwn_phy_lp_calib(mac);
606}
607
608static int
609bwn_phy_lp_readsprom(struct bwn_mac *mac)
610{
611	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
612	struct bwn_softc *sc = mac->mac_sc;
613	struct ieee80211com *ic = &sc->sc_ic;
614
615#define	BWN_PHY_LP_READVAR(_dev, _type, _name, _result)		\
616do {									\
617	int error;							\
618									\
619	error = bhnd_nvram_getvar_ ##_type((_dev), (_name), (_result));	\
620	if (error) {							\
621		device_printf((_dev), "NVRAM variable %s unreadable: "	\
622		    "%d\n", (_name), error);				\
623		return (error);						\
624	}								\
625} while(0)
626
627	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
628		BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_TRI2G,
629		    &plp->plp_txisoband_m);
630		BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_BXA2G,
631		    &plp->plp_bxarch);
632		BWN_PHY_LP_READVAR(sc->sc_dev, int8, BHND_NVAR_RXPO2G,
633		    &plp->plp_rxpwroffset);
634		BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISMF2G,
635		    &plp->plp_rssivf);
636		BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISMC2G,
637		    &plp->plp_rssivc);
638		BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISAV2G,
639		    &plp->plp_rssigs);
640
641		return (0);
642	}
643
644	BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_TRI5GL,
645	    &plp->plp_txisoband_l);
646	BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_TRI5G,
647	    &plp->plp_txisoband_m);
648	BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_TRI5GH,
649	    &plp->plp_txisoband_h);
650	BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_BXA5G,
651	    &plp->plp_bxarch);
652	BWN_PHY_LP_READVAR(sc->sc_dev, int8, BHND_NVAR_RXPO5G,
653	    &plp->plp_rxpwroffset);
654	BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISMF5G,
655	    &plp->plp_rssivf);
656	BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISMC5G,
657	    &plp->plp_rssivc);
658	BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISAV5G,
659	    &plp->plp_rssigs);
660
661#undef	BWN_PHY_LP_READVAR
662
663	return (0);
664}
665
666static void
667bwn_phy_lp_bbinit(struct bwn_mac *mac)
668{
669
670	bwn_phy_lp_tblinit(mac);
671	if (mac->mac_phy.rev >= 2)
672		bwn_phy_lp_bbinit_r2(mac);
673	else
674		bwn_phy_lp_bbinit_r01(mac);
675}
676
677static void
678bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
679{
680	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
681	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
682	struct bwn_softc *sc = mac->mac_sc;
683	struct ieee80211com *ic = &sc->sc_ic;
684
685	bwn_phy_lp_set_txgain(mac,
686	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
687	bwn_phy_lp_set_bbmult(mac, 150);
688}
689
690static void
691bwn_phy_lp_calib(struct bwn_mac *mac)
692{
693	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
694	struct bwn_softc *sc = mac->mac_sc;
695	struct ieee80211com *ic = &sc->sc_ic;
696	const struct bwn_rxcompco *rc = NULL;
697	struct bwn_txgain ogain;
698	int i, omode, oafeovr, orf, obbmult;
699	uint8_t mode, fc = 0;
700
701	if (plp->plp_chanfullcal != plp->plp_chan) {
702		plp->plp_chanfullcal = plp->plp_chan;
703		fc = 1;
704	}
705
706	bwn_mac_suspend(mac);
707
708	/* BlueTooth Coexistance Override */
709	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
710	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
711
712	if (mac->mac_phy.rev >= 2)
713		bwn_phy_lp_digflt_save(mac);
714	bwn_phy_lp_get_txpctlmode(mac);
715	mode = plp->plp_txpctlmode;
716	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
717	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
718		bwn_phy_lp_bugfix(mac);
719	if (mac->mac_phy.rev >= 2 && fc == 1) {
720		bwn_phy_lp_get_txpctlmode(mac);
721		omode = plp->plp_txpctlmode;
722		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
723		if (oafeovr)
724			ogain = bwn_phy_lp_get_txgain(mac);
725		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
726		obbmult = bwn_phy_lp_get_bbmult(mac);
727		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
728		if (oafeovr)
729			bwn_phy_lp_set_txgain(mac, &ogain);
730		bwn_phy_lp_set_bbmult(mac, obbmult);
731		bwn_phy_lp_set_txpctlmode(mac, omode);
732		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
733	}
734	bwn_phy_lp_set_txpctlmode(mac, mode);
735	if (mac->mac_phy.rev >= 2)
736		bwn_phy_lp_digflt_restore(mac);
737
738	/* do RX IQ Calculation; assumes that noise is true. */
739	if (sc->sc_cid.chip_id == BHND_CHIPID_BCM5354) {
740		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
741			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
742				rc = &bwn_rxcompco_5354[i];
743		}
744	} else if (mac->mac_phy.rev >= 2)
745		rc = &bwn_rxcompco_r2;
746	else {
747		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
748			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
749				rc = &bwn_rxcompco_r12[i];
750		}
751	}
752	if (rc == NULL)
753		goto fail;
754
755	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
756	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
757
758	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
759
760	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
761		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
762		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
763	} else {
764		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
765		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
766	}
767
768	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
769	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
770	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
771	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
772	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
773	bwn_phy_lp_set_deaf(mac, 0);
774	/* XXX no checking return value? */
775	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
776	bwn_phy_lp_clear_deaf(mac, 0);
777	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
778	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
779	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
780
781	/* disable RX GAIN override. */
782	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
783	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
784	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
785	if (mac->mac_phy.rev >= 2) {
786		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
787		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
788			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
789			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
790		}
791	} else {
792		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
793	}
794
795	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
796	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
797fail:
798	bwn_mac_enable(mac);
799}
800
801void
802bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
803{
804
805	if (on) {
806		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
807		return;
808	}
809
810	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
811	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
812}
813
814static int
815bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
816{
817	static const struct bwn_b206x_chan *bc = NULL;
818	struct bwn_softc *sc = mac->mac_sc;
819	uint32_t count, freqref, freqvco, val[3], timeout, timeoutref,
820	    tmp[6];
821	uint16_t old, scale, tmp16;
822	u_int freqxtal;
823	int error, i, div;
824
825	for (i = 0; i < N(bwn_b2063_chantable); i++) {
826		if (bwn_b2063_chantable[i].bc_chan == chan) {
827			bc = &bwn_b2063_chantable[i];
828			break;
829		}
830	}
831	if (bc == NULL)
832		return (EINVAL);
833
834	error = bhnd_get_clock_freq(sc->sc_dev, BHND_CLOCK_ALP, &freqxtal);
835	if (error) {
836		device_printf(sc->sc_dev, "failed to fetch clock frequency: %d",
837		    error);
838		return (error);
839	}
840
841	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
842	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
843	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
844	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
845	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
846	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
847	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
848	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
849	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
850	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
851	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
852	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
853
854	old = BWN_RF_READ(mac, BWN_B2063_COM15);
855	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
856
857	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
858	freqref = freqxtal * 3;
859	div = (freqxtal <= 26000000 ? 1 : 2);
860	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
861	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
862		999999) / 1000000) + 1;
863
864	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
865	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
866	    0xfff8, timeout >> 2);
867	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
868	    0xff9f,timeout << 5);
869	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
870
871	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
872	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
873	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
874
875	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
876	    (timeoutref + 1)) - 1;
877	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
878	    0xf0, count >> 8);
879	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
880
881	tmp[0] = ((val[2] * 62500) / freqref) << 4;
882	tmp[1] = ((val[2] * 62500) % freqref) << 4;
883	while (tmp[1] >= freqref) {
884		tmp[0]++;
885		tmp[1] -= freqref;
886	}
887	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
888	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
889	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
890	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
891	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
892
893	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
894	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
895	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
896	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
897
898	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
899	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
900
901	if (howmany(tmp[3], tmp[2]) > 60) {
902		scale = 1;
903		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
904	} else {
905		scale = 0;
906		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
907	}
908	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
909	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
910
911	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
912	    (scale + 1);
913	if (tmp[5] > 150)
914		tmp[5] = 0;
915
916	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
917	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
918
919	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
920	if (freqxtal > 26000000)
921		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
922	else
923		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
924
925	if (val[0] == 45)
926		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
927	else
928		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
929
930	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
931	DELAY(1);
932	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
933
934	/* VCO Calibration */
935	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
936	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
937	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
938	DELAY(1);
939	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
940	DELAY(1);
941	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
942	DELAY(1);
943	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
944	DELAY(300);
945	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
946
947	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
948	return (0);
949}
950
951static int
952bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
953{
954	struct bwn_softc *sc = mac->mac_sc;
955	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
956	const struct bwn_b206x_chan *bc = NULL;
957	uint32_t tmp[9];
958	u_int freqxtal;
959	int error, i;
960
961	for (i = 0; i < N(bwn_b2062_chantable); i++) {
962		if (bwn_b2062_chantable[i].bc_chan == chan) {
963			bc = &bwn_b2062_chantable[i];
964			break;
965		}
966	}
967
968	if (bc == NULL)
969		return (EINVAL);
970
971	error = bhnd_get_clock_freq(sc->sc_dev, BHND_CLOCK_ALP, &freqxtal);
972	if (error) {
973		device_printf(sc->sc_dev, "failed to fetch clock frequency: %d",
974		    error);
975		return (error);
976	}
977
978	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
979	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
980	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
981	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
982	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
983	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
984	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
985	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
986	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
987	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
988
989	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
990	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
991	bwn_phy_lp_b2062_reset_pllbias(mac);
992	tmp[0] = freqxtal / 1000;
993	tmp[1] = plp->plp_div * 1000;
994	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
995	if (ieee80211_ieee2mhz(chan, 0) < 4000)
996		tmp[2] *= 2;
997	tmp[3] = 48 * tmp[0];
998	tmp[5] = tmp[2] / tmp[3];
999	tmp[6] = tmp[2] % tmp[3];
1000	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
1001	tmp[4] = tmp[6] * 0x100;
1002	tmp[5] = tmp[4] / tmp[3];
1003	tmp[6] = tmp[4] % tmp[3];
1004	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
1005	tmp[4] = tmp[6] * 0x100;
1006	tmp[5] = tmp[4] / tmp[3];
1007	tmp[6] = tmp[4] % tmp[3];
1008	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
1009	tmp[4] = tmp[6] * 0x100;
1010	tmp[5] = tmp[4] / tmp[3];
1011	tmp[6] = tmp[4] % tmp[3];
1012	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
1013	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
1014	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
1015	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
1016	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
1017	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
1018
1019	bwn_phy_lp_b2062_vco_calib(mac);
1020	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
1021		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
1022		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
1023		bwn_phy_lp_b2062_reset_pllbias(mac);
1024		bwn_phy_lp_b2062_vco_calib(mac);
1025		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
1026			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
1027			return (EIO);
1028		}
1029	}
1030	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
1031	return (0);
1032}
1033
1034static void
1035bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
1036{
1037	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1038	uint16_t tmp = (channel == 14);
1039
1040	if (mac->mac_phy.rev < 2) {
1041		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
1042		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
1043			bwn_phy_lp_set_rccap(mac);
1044		return;
1045	}
1046
1047	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
1048}
1049
1050static void
1051bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
1052{
1053	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1054	struct bwn_softc *sc = mac->mac_sc;
1055	struct ieee80211com *ic = &sc->sc_ic;
1056	uint16_t iso, tmp[3];
1057
1058	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
1059
1060	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
1061		iso = plp->plp_txisoband_m;
1062	else if (freq <= 5320)
1063		iso = plp->plp_txisoband_l;
1064	else if (freq <= 5700)
1065		iso = plp->plp_txisoband_m;
1066	else
1067		iso = plp->plp_txisoband_h;
1068
1069	tmp[0] = ((iso - 26) / 12) << 12;
1070	tmp[1] = tmp[0] + 0x1000;
1071	tmp[2] = tmp[0] + 0x2000;
1072
1073	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
1074	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
1075}
1076
1077static void
1078bwn_phy_lp_digflt_save(struct bwn_mac *mac)
1079{
1080	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1081	int i;
1082	static const uint16_t addr[] = {
1083		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
1084		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
1085		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
1086		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
1087		BWN_PHY_OFDM(0xcf),
1088	};
1089	static const uint16_t val[] = {
1090		0xde5e, 0xe832, 0xe331, 0x4d26,
1091		0x0026, 0x1420, 0x0020, 0xfe08,
1092		0x0008,
1093	};
1094
1095	for (i = 0; i < N(addr); i++) {
1096		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
1097		BWN_PHY_WRITE(mac, addr[i], val[i]);
1098	}
1099}
1100
1101static void
1102bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
1103{
1104	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1105	struct bwn_softc *sc = mac->mac_sc;
1106	uint16_t ctl;
1107
1108	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
1109	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
1110	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
1111		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
1112		break;
1113	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
1114		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
1115		break;
1116	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
1117		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
1118		break;
1119	default:
1120		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
1121		device_printf(sc->sc_dev, "unknown command mode\n");
1122		break;
1123	}
1124}
1125
1126static void
1127bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
1128{
1129	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1130	uint16_t ctl;
1131	uint8_t old;
1132
1133	bwn_phy_lp_get_txpctlmode(mac);
1134	old = plp->plp_txpctlmode;
1135	if (old == mode)
1136		return;
1137	plp->plp_txpctlmode = mode;
1138
1139	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
1140		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
1141		    plp->plp_tssiidx);
1142		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
1143		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
1144
1145		/* disable TX GAIN override */
1146		if (mac->mac_phy.rev < 2)
1147			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
1148		else {
1149			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
1150			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
1151		}
1152		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
1153
1154		plp->plp_txpwridx = -1;
1155	}
1156	if (mac->mac_phy.rev >= 2) {
1157		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
1158			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
1159		else
1160			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
1161	}
1162
1163	/* writes TX Power Control mode */
1164	switch (plp->plp_txpctlmode) {
1165	case BWN_PHYLP_TXPCTL_OFF:
1166		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
1167		break;
1168	case BWN_PHYLP_TXPCTL_ON_HW:
1169		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
1170		break;
1171	case BWN_PHYLP_TXPCTL_ON_SW:
1172		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
1173		break;
1174	default:
1175		ctl = 0;
1176		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1177	}
1178	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
1179	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
1180}
1181
1182static void
1183bwn_phy_lp_bugfix(struct bwn_mac *mac)
1184{
1185	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1186	struct bwn_softc *sc = mac->mac_sc;
1187	const unsigned int size = 256;
1188	struct bwn_txgain tg;
1189	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
1190	uint16_t tssinpt, tssiidx, value[2];
1191	uint8_t mode;
1192	int8_t txpwridx;
1193
1194	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
1195	    M_NOWAIT | M_ZERO);
1196	if (tabs == NULL) {
1197		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
1198		return;
1199	}
1200
1201	bwn_phy_lp_get_txpctlmode(mac);
1202	mode = plp->plp_txpctlmode;
1203	txpwridx = plp->plp_txpwridx;
1204	tssinpt = plp->plp_tssinpt;
1205	tssiidx = plp->plp_tssiidx;
1206
1207	bwn_tab_read_multi(mac,
1208	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
1209	    BWN_TAB_4(7, 0x140), size, tabs);
1210
1211	bwn_phy_lp_tblinit(mac);
1212	bwn_phy_lp_bbinit(mac);
1213	bwn_phy_lp_txpctl_init(mac);
1214	bwn_phy_lp_rf_onoff(mac, 1);
1215	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
1216
1217	bwn_tab_write_multi(mac,
1218	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
1219	    BWN_TAB_4(7, 0x140), size, tabs);
1220
1221	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
1222	plp->plp_tssinpt = tssinpt;
1223	plp->plp_tssiidx = tssiidx;
1224	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
1225	if (txpwridx != -1) {
1226		/* set TX power by index */
1227		plp->plp_txpwridx = txpwridx;
1228		bwn_phy_lp_get_txpctlmode(mac);
1229		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
1230			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
1231		if (mac->mac_phy.rev >= 2) {
1232			rxcomp = bwn_tab_read(mac,
1233			    BWN_TAB_4(7, txpwridx + 320));
1234			txgain = bwn_tab_read(mac,
1235			    BWN_TAB_4(7, txpwridx + 192));
1236			tg.tg_pad = (txgain >> 16) & 0xff;
1237			tg.tg_gm = txgain & 0xff;
1238			tg.tg_pga = (txgain >> 8) & 0xff;
1239			tg.tg_dac = (rxcomp >> 28) & 0xff;
1240			bwn_phy_lp_set_txgain(mac, &tg);
1241		} else {
1242			rxcomp = bwn_tab_read(mac,
1243			    BWN_TAB_4(10, txpwridx + 320));
1244			txgain = bwn_tab_read(mac,
1245			    BWN_TAB_4(10, txpwridx + 192));
1246			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
1247			    0xf800, (txgain >> 4) & 0x7fff);
1248			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
1249			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
1250		}
1251		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
1252
1253		/* set TX IQCC */
1254		value[0] = (rxcomp >> 10) & 0x3ff;
1255		value[1] = rxcomp & 0x3ff;
1256		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
1257
1258		coeff = bwn_tab_read(mac,
1259		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
1260		    BWN_TAB_4(10, txpwridx + 448));
1261		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
1262		if (mac->mac_phy.rev >= 2) {
1263			rfpwr = bwn_tab_read(mac,
1264			    BWN_TAB_4(7, txpwridx + 576));
1265			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
1266			    rfpwr & 0xffff);
1267		}
1268		bwn_phy_lp_set_txgain_override(mac);
1269	}
1270	if (plp->plp_rccap)
1271		bwn_phy_lp_set_rccap(mac);
1272	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
1273	bwn_phy_lp_set_txpctlmode(mac, mode);
1274	free(tabs, M_DEVBUF);
1275}
1276
1277static void
1278bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
1279{
1280	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1281	int i;
1282	static const uint16_t addr[] = {
1283		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
1284		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
1285		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
1286		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
1287		BWN_PHY_OFDM(0xcf),
1288	};
1289
1290	for (i = 0; i < N(addr); i++)
1291		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
1292}
1293
1294static void
1295bwn_phy_lp_tblinit(struct bwn_mac *mac)
1296{
1297	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
1298
1299	if (mac->mac_phy.rev < 2) {
1300		bwn_phy_lp_tblinit_r01(mac);
1301		bwn_phy_lp_tblinit_txgain(mac);
1302		bwn_phy_lp_set_gaintbl(mac, freq);
1303		return;
1304	}
1305
1306	bwn_phy_lp_tblinit_r2(mac);
1307	bwn_phy_lp_tblinit_txgain(mac);
1308}
1309
1310struct bwn_wpair {
1311	uint16_t		reg;
1312	uint16_t		value;
1313};
1314
1315struct bwn_smpair {
1316	uint16_t		offset;
1317	uint16_t		mask;
1318	uint16_t		set;
1319};
1320
1321static void
1322bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
1323{
1324	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1325	struct bwn_softc *sc = mac->mac_sc;
1326	struct ieee80211com *ic = &sc->sc_ic;
1327	static const struct bwn_wpair v1[] = {
1328		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
1329		{ BWN_PHY_AFE_CTL, 0x8800 },
1330		{ BWN_PHY_AFE_CTL_OVR, 0 },
1331		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
1332		{ BWN_PHY_RF_OVERRIDE_0, 0 },
1333		{ BWN_PHY_RF_OVERRIDE_2, 0 },
1334		{ BWN_PHY_OFDM(0xf9), 0 },
1335		{ BWN_PHY_TR_LOOKUP_1, 0 }
1336	};
1337	static const struct bwn_smpair v2[] = {
1338		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
1339		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
1340		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
1341		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
1342		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
1343	};
1344	static const struct bwn_smpair v3[] = {
1345		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
1346		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
1347		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
1348		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
1349		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
1350		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
1351		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
1352		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
1353		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
1354		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
1355
1356	};
1357	int i;
1358
1359	for (i = 0; i < N(v1); i++)
1360		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
1361	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
1362	for (i = 0; i < N(v2); i++)
1363		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
1364
1365	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
1366	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
1367	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
1368	if (sc->sc_board_info.board_rev >= 0x18) {
1369		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
1370		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
1371	} else {
1372		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
1373	}
1374	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
1375	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
1376	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
1377	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
1378	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
1379	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
1380	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
1381	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
1382	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
1383	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
1384	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
1385	if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4325 &&
1386	    sc->sc_cid.chip_pkg == 0) {
1387		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
1388		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
1389	} else {
1390		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
1391		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
1392	}
1393	for (i = 0; i < N(v3); i++)
1394		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
1395	if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4325 &&
1396	    sc->sc_cid.chip_pkg == 0) {
1397		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
1398		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
1399	}
1400
1401	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
1402		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
1403		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
1404		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
1405		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
1406		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
1407		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
1408	} else
1409		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
1410
1411	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
1412	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
1413	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
1414	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
1415	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
1416	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
1417	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
1418	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
1419	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
1420
1421	if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4325 &&
1422	    sc->sc_cid.chip_pkg == 0) {
1423		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
1424		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
1425		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
1426	}
1427
1428	bwn_phy_lp_digflt_save(mac);
1429}
1430
1431static void
1432bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
1433{
1434	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1435	struct bwn_softc *sc = mac->mac_sc;
1436	struct ieee80211com *ic = &sc->sc_ic;
1437	static const struct bwn_smpair v1[] = {
1438		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
1439		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
1440		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
1441		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
1442		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
1443		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
1444		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
1445	};
1446	static const struct bwn_smpair v2[] = {
1447		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
1448		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
1449		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
1450		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
1451		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
1452		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
1453		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
1454		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
1455		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
1456		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
1457		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
1458		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
1459		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
1460		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
1461		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
1462		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
1463	};
1464	static const struct bwn_smpair v3[] = {
1465		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
1466		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
1467		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
1468		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
1469		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
1470		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
1471		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
1472		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
1473	};
1474	static const struct bwn_smpair v4[] = {
1475		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
1476		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
1477		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
1478		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
1479		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
1480		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
1481		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
1482		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
1483	};
1484	static const struct bwn_smpair v5[] = {
1485		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
1486		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
1487		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
1488		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
1489		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
1490		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
1491		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
1492		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
1493	};
1494	int error, i;
1495	uint16_t tmp, tmp2;
1496
1497	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
1498	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
1499	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
1500	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
1501	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
1502	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
1503	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
1504	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
1505	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
1506	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
1507	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
1508	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
1509	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
1510	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
1511	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
1512	for (i = 0; i < N(v1); i++)
1513		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
1514	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
1515	    0xff00, plp->plp_rxpwroffset);
1516	if ((sc->sc_board_info.board_flags & BHND_BFL_FEM) &&
1517	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
1518	   (sc->sc_board_info.board_flags & BHND_BFL_PAREF))) {
1519		error = bhnd_pmu_set_voltage_raw(sc->sc_pmu,
1520		    BHND_REGULATOR_PAREF_LDO, 0x28);
1521		if (error)
1522			device_printf(sc->sc_dev, "failed to set PAREF LDO "
1523			    "voltage: %d\n", error);
1524
1525		error = bhnd_pmu_enable_regulator(sc->sc_pmu,
1526		    BHND_REGULATOR_PAREF_LDO);
1527		if (error)
1528			device_printf(sc->sc_dev, "failed to enable PAREF LDO "
1529			    "regulator: %d\n", error);
1530
1531		if (mac->mac_phy.rev == 0)
1532			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
1533			    0xffcf, 0x0010);
1534		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
1535	} else {
1536		error = bhnd_pmu_disable_regulator(sc->sc_pmu,
1537		    BHND_REGULATOR_PAREF_LDO);
1538		if (error)
1539			device_printf(sc->sc_dev, "failed to disable PAREF LDO "
1540			    "regulator: %d\n", error);
1541
1542		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
1543		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
1544	}
1545	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
1546	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
1547	if (sc->sc_board_info.board_flags & BHND_BFL_RSSIINV)
1548		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
1549	else
1550		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
1551	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
1552	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
1553	    0xfff9, (plp->plp_bxarch << 1));
1554	if (mac->mac_phy.rev == 1 &&
1555	    (sc->sc_board_info.board_flags & BHND_BFL_FEM_BT)) {
1556		for (i = 0; i < N(v2); i++)
1557			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
1558			    v2[i].set);
1559	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
1560	    (sc->sc_board_info.board_type == 0x048a) ||
1561	    ((mac->mac_phy.rev == 0) &&
1562	     (sc->sc_board_info.board_flags & BHND_BFL_FEM))) {
1563		for (i = 0; i < N(v3); i++)
1564			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
1565			    v3[i].set);
1566	} else if (mac->mac_phy.rev == 1 ||
1567		  (sc->sc_board_info.board_flags & BHND_BFL_FEM)) {
1568		for (i = 0; i < N(v4); i++)
1569			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
1570			    v4[i].set);
1571	} else {
1572		for (i = 0; i < N(v5); i++)
1573			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
1574			    v5[i].set);
1575	}
1576	if (mac->mac_phy.rev == 1 &&
1577	    (sc->sc_board_info.board_flags & BHND_BFL_PAREF)) {
1578		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
1579		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
1580		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
1581		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
1582	}
1583	if ((sc->sc_board_info.board_flags & BHND_BFL_FEM_BT) &&
1584	    (sc->sc_cid.chip_id == BHND_CHIPID_BCM5354) &&
1585	    (sc->sc_cid.chip_pkg == BHND_PKGID_BCM4712SMALL)) {
1586		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
1587		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
1588		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
1589		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
1590	}
1591	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
1592		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
1593		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
1594		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
1595		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
1596		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
1597		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
1598		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
1599		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
1600	} else {
1601		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
1602		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
1603	}
1604	if (mac->mac_phy.rev == 1) {
1605		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
1606		tmp2 = (tmp & 0x03e0) >> 5;
1607		tmp2 |= tmp2 << 5;
1608		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
1609		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
1610		tmp2 = (tmp & 0x1f00) >> 8;
1611		tmp2 |= tmp2 << 5;
1612		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
1613		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
1614		tmp2 = tmp & 0x00ff;
1615		tmp2 |= tmp << 8;
1616		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
1617	}
1618}
1619
1620struct bwn_b2062_freq {
1621	uint16_t		freq;
1622	uint8_t			value[6];
1623};
1624
1625static int
1626bwn_phy_lp_b2062_init(struct bwn_mac *mac)
1627{
1628#define	CALC_CTL7(freq, div)						\
1629	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
1630#define	CALC_CTL18(freq, div)						\
1631	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
1632#define	CALC_CTL19(freq, div)						\
1633	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
1634	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1635	struct bwn_softc *sc = mac->mac_sc;
1636	struct ieee80211com *ic = &sc->sc_ic;
1637	static const struct bwn_b2062_freq freqdata_tab[] = {
1638		{ 12000, { 6, 6, 6, 6, 10, 6 } },
1639		{ 13000, { 4, 4, 4, 4, 11, 7 } },
1640		{ 14400, { 3, 3, 3, 3, 12, 7 } },
1641		{ 16200, { 3, 3, 3, 3, 13, 8 } },
1642		{ 18000, { 2, 2, 2, 2, 14, 8 } },
1643		{ 19200, { 1, 1, 1, 1, 14, 9 } }
1644	};
1645	static const struct bwn_wpair v1[] = {
1646		{ BWN_B2062_N_TXCTL3, 0 },
1647		{ BWN_B2062_N_TXCTL4, 0 },
1648		{ BWN_B2062_N_TXCTL5, 0 },
1649		{ BWN_B2062_N_TXCTL6, 0 },
1650		{ BWN_B2062_N_PDNCTL0, 0x40 },
1651		{ BWN_B2062_N_PDNCTL0, 0 },
1652		{ BWN_B2062_N_CALIB_TS, 0x10 },
1653		{ BWN_B2062_N_CALIB_TS, 0 }
1654	};
1655	const struct bwn_b2062_freq *f = NULL;
1656	uint32_t ref;
1657	u_int xtalfreq;
1658	unsigned int i;
1659	int error;
1660
1661	error = bhnd_get_clock_freq(sc->sc_dev, BHND_CLOCK_ALP, &xtalfreq);
1662	if (error) {
1663		device_printf(sc->sc_dev, "failed to fetch clock frequency: %d",
1664		    error);
1665		return (error);
1666	}
1667
1668	bwn_phy_lp_b2062_tblinit(mac);
1669
1670	for (i = 0; i < N(v1); i++)
1671		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
1672	if (mac->mac_phy.rev > 0)
1673		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
1674		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
1675	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
1676		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
1677	else
1678		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
1679
1680	if (xtalfreq <= 30000000) {
1681		plp->plp_div = 1;
1682		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
1683	} else {
1684		plp->plp_div = 2;
1685		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
1686	}
1687
1688	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
1689	    CALC_CTL7(xtalfreq, plp->plp_div));
1690	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
1691	    CALC_CTL18(xtalfreq, plp->plp_div));
1692	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
1693	    CALC_CTL19(xtalfreq, plp->plp_div));
1694
1695	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
1696	ref &= 0xffff;
1697	for (i = 0; i < N(freqdata_tab); i++) {
1698		if (ref < freqdata_tab[i].freq) {
1699			f = &freqdata_tab[i];
1700			break;
1701		}
1702	}
1703	if (f == NULL)
1704		f = &freqdata_tab[N(freqdata_tab) - 1];
1705	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
1706	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
1707	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
1708	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
1709	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
1710	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
1711
1712	return (0);
1713#undef CALC_CTL7
1714#undef CALC_CTL18
1715#undef CALC_CTL19
1716}
1717
1718static int
1719bwn_phy_lp_b2063_init(struct bwn_mac *mac)
1720{
1721
1722	bwn_phy_lp_b2063_tblinit(mac);
1723	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
1724	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
1725	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
1726	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
1727	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
1728	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
1729	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
1730	if (mac->mac_phy.rev == 2) {
1731		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
1732		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
1733		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
1734	} else {
1735		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
1736		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
1737	}
1738
1739	return (0);
1740}
1741
1742static int
1743bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
1744{
1745	struct bwn_softc *sc = mac->mac_sc;
1746	static const struct bwn_wpair v1[] = {
1747		{ BWN_B2063_RX_BB_SP8, 0x0 },
1748		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
1749		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
1750		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
1751		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
1752		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
1753		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
1754		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
1755	};
1756	static const struct bwn_wpair v2[] = {
1757		{ BWN_B2063_TX_BB_SP3, 0x0 },
1758		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
1759		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
1760		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
1761		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
1762	};
1763	u_int freqxtal;
1764	int error, i;
1765	uint8_t tmp;
1766
1767	error = bhnd_get_clock_freq(sc->sc_dev, BHND_CLOCK_ALP, &freqxtal);
1768	if (error) {
1769		device_printf(sc->sc_dev, "failed to fetch clock frequency: %d",
1770		    error);
1771		return (error);
1772	}
1773
1774	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
1775
1776	for (i = 0; i < 2; i++)
1777		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
1778	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
1779	for (i = 2; i < N(v1); i++)
1780		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
1781	for (i = 0; i < 10000; i++) {
1782		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
1783			break;
1784		DELAY(1000);
1785	}
1786
1787	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
1788		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
1789
1790	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
1791
1792	for (i = 0; i < N(v2); i++)
1793		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
1794	if (freqxtal == 24000000) {
1795		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
1796		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
1797	} else {
1798		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
1799		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
1800	}
1801	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
1802	for (i = 0; i < 10000; i++) {
1803		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
1804			break;
1805		DELAY(1000);
1806	}
1807	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
1808		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
1809	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
1810
1811	return (0);
1812}
1813
1814static int
1815bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
1816{
1817	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1818	struct bwn_softc *sc = mac->mac_sc;
1819	struct bwn_phy_lp_iq_est ie;
1820	struct bwn_txgain tx_gains;
1821	static const uint32_t pwrtbl[21] = {
1822		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
1823		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
1824		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
1825		0x0004c, 0x0002c, 0x0001a,
1826	};
1827	uint32_t npwr, ipwr, sqpwr, tmp;
1828	int loopback, i, j, sum, error;
1829	uint16_t save[7];
1830	uint8_t txo, bbmult, txpctlmode;
1831
1832	error = bwn_phy_lp_switch_channel(mac, 7);
1833	if (error)
1834		device_printf(sc->sc_dev,
1835		    "failed to change channel to 7 (%d)\n", error);
1836	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
1837	bbmult = bwn_phy_lp_get_bbmult(mac);
1838	if (txo)
1839		tx_gains = bwn_phy_lp_get_txgain(mac);
1840
1841	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
1842	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
1843	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
1844	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
1845	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
1846	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
1847	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
1848
1849	bwn_phy_lp_get_txpctlmode(mac);
1850	txpctlmode = plp->plp_txpctlmode;
1851	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
1852
1853	/* disable CRS */
1854	bwn_phy_lp_set_deaf(mac, 1);
1855	bwn_phy_lp_set_trsw_over(mac, 0, 1);
1856	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
1857	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
1858	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
1859	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
1860	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
1861	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
1862	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
1863	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
1864	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
1865	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
1866	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
1867	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
1868	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
1869	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
1870	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
1871	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
1872	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
1873	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
1874	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
1875	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
1876	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
1877	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
1878	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
1879
1880	loopback = bwn_phy_lp_loopback(mac);
1881	if (loopback == -1)
1882		goto done;
1883	bwn_phy_lp_set_rxgain_idx(mac, loopback);
1884	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
1885	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
1886	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
1887	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
1888
1889	tmp = 0;
1890	memset(&ie, 0, sizeof(ie));
1891	for (i = 128; i <= 159; i++) {
1892		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
1893		sum = 0;
1894		for (j = 5; j <= 25; j++) {
1895			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
1896			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
1897				goto done;
1898			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
1899			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
1900			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
1901			    12);
1902			sum += ((ipwr - npwr) * (ipwr - npwr));
1903			if ((i == 128) || (sum < tmp)) {
1904				plp->plp_rccap = i;
1905				tmp = sum;
1906			}
1907		}
1908	}
1909	bwn_phy_lp_ddfs_turnoff(mac);
1910done:
1911	/* restore CRS */
1912	bwn_phy_lp_clear_deaf(mac, 1);
1913	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
1914	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
1915
1916	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
1917	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
1918	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
1919	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
1920	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
1921	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
1922	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
1923
1924	bwn_phy_lp_set_bbmult(mac, bbmult);
1925	if (txo)
1926		bwn_phy_lp_set_txgain(mac, &tx_gains);
1927	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
1928	if (plp->plp_rccap)
1929		bwn_phy_lp_set_rccap(mac);
1930
1931	return (0);
1932}
1933
1934static void
1935bwn_phy_lp_set_rccap(struct bwn_mac *mac)
1936{
1937	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
1938	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
1939
1940	if (mac->mac_phy.rev == 1)
1941		rc_cap = MIN(rc_cap + 5, 15);
1942
1943	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
1944	    MAX(plp->plp_rccap - 4, 0x80));
1945	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
1946	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
1947	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
1948}
1949
1950static uint32_t
1951bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
1952{
1953	uint32_t i, q, r;
1954
1955	if (div == 0)
1956		return (0);
1957
1958	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
1959		q <<= 1;
1960		if (r << 1 >= div) {
1961			q++;
1962			r = (r << 1) - div;
1963		}
1964	}
1965	if (r << 1 >= div)
1966		q++;
1967	return (q);
1968}
1969
1970static void
1971bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
1972{
1973	struct bwn_softc *sc = mac->mac_sc;
1974
1975	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
1976	DELAY(20);
1977	if (sc->sc_cid.chip_id == BHND_CHIPID_BCM5354) {
1978		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
1979		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
1980	} else {
1981		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
1982	}
1983	DELAY(5);
1984}
1985
1986static void
1987bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
1988{
1989
1990	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
1991	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
1992	DELAY(200);
1993}
1994
1995static void
1996bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
1997{
1998#define	FLAG_A	0x01
1999#define	FLAG_G	0x02
2000	struct bwn_softc *sc = mac->mac_sc;
2001	struct ieee80211com *ic = &sc->sc_ic;
2002	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
2003		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
2004		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
2005		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
2006		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
2007		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
2008		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
2009		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
2010		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
2011		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
2012		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
2013		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
2014		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
2015		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
2016		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
2017		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
2018		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
2019		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
2020		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
2021		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
2022		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
2023		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
2024		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
2025		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
2026		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
2027		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
2028		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
2029		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
2030		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
2031		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
2032		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
2033		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
2034		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
2035		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
2036		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
2037		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
2038		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
2039		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
2040		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
2041		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
2042		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
2043		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
2044		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
2045		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
2046		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
2047		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
2048		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
2049		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
2050	};
2051	const struct bwn_b206x_rfinit_entry *br;
2052	unsigned int i;
2053
2054	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
2055		br = &bwn_b2062_init_tab[i];
2056		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
2057			if (br->br_flags & FLAG_G)
2058				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
2059		} else {
2060			if (br->br_flags & FLAG_A)
2061				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
2062		}
2063	}
2064#undef FLAG_A
2065#undef FLAG_B
2066}
2067
2068static void
2069bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
2070{
2071#define	FLAG_A	0x01
2072#define	FLAG_G	0x02
2073	struct bwn_softc *sc = mac->mac_sc;
2074	struct ieee80211com *ic = &sc->sc_ic;
2075	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
2076		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
2077		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
2078		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
2079		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
2080		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
2081		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
2082		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
2083		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
2084		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
2085		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
2086		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
2087		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
2088		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
2089		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
2090		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
2091		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
2092		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
2093		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
2094		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
2095		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
2096		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
2097		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
2098		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
2099		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
2100		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
2101		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
2102		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
2103		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
2104		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
2105		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
2106		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
2107		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
2108		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
2109		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
2110		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
2111		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
2112		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
2113		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
2114		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
2115		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
2116		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
2117		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
2118	};
2119	const struct bwn_b206x_rfinit_entry *br;
2120	unsigned int i;
2121
2122	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
2123		br = &bwn_b2063_init_tab[i];
2124		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
2125			if (br->br_flags & FLAG_G)
2126				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
2127		} else {
2128			if (br->br_flags & FLAG_A)
2129				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
2130		}
2131	}
2132#undef FLAG_A
2133#undef FLAG_B
2134}
2135
2136static void
2137bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
2138    int count, void *_data)
2139{
2140	unsigned int i;
2141	uint32_t offset, type;
2142	uint8_t *data = _data;
2143
2144	type = BWN_TAB_GETTYPE(typenoffset);
2145	offset = BWN_TAB_GETOFFSET(typenoffset);
2146	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
2147
2148	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
2149
2150	for (i = 0; i < count; i++) {
2151		switch (type) {
2152		case BWN_TAB_8BIT:
2153			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
2154			data++;
2155			break;
2156		case BWN_TAB_16BIT:
2157			*((uint16_t *)data) = BWN_PHY_READ(mac,
2158			    BWN_PHY_TABLEDATALO);
2159			data += 2;
2160			break;
2161		case BWN_TAB_32BIT:
2162			*((uint32_t *)data) = BWN_PHY_READ(mac,
2163			    BWN_PHY_TABLEDATAHI);
2164			*((uint32_t *)data) <<= 16;
2165			*((uint32_t *)data) |= BWN_PHY_READ(mac,
2166			    BWN_PHY_TABLEDATALO);
2167			data += 4;
2168			break;
2169		default:
2170			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2171		}
2172	}
2173}
2174
2175static void
2176bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
2177    int count, const void *_data)
2178{
2179	uint32_t offset, type, value;
2180	const uint8_t *data = _data;
2181	unsigned int i;
2182
2183	type = BWN_TAB_GETTYPE(typenoffset);
2184	offset = BWN_TAB_GETOFFSET(typenoffset);
2185	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
2186
2187	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
2188
2189	for (i = 0; i < count; i++) {
2190		switch (type) {
2191		case BWN_TAB_8BIT:
2192			value = *data;
2193			data++;
2194			KASSERT(!(value & ~0xff),
2195			    ("%s:%d: fail", __func__, __LINE__));
2196			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
2197			break;
2198		case BWN_TAB_16BIT:
2199			value = *((const uint16_t *)data);
2200			data += 2;
2201			KASSERT(!(value & ~0xffff),
2202			    ("%s:%d: fail", __func__, __LINE__));
2203			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
2204			break;
2205		case BWN_TAB_32BIT:
2206			value = *((const uint32_t *)data);
2207			data += 4;
2208			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
2209			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
2210			break;
2211		default:
2212			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
2213		}
2214	}
2215}
2216
2217static struct bwn_txgain
2218bwn_phy_lp_get_txgain(struct bwn_mac *mac)
2219{
2220	struct bwn_txgain tg;
2221	uint16_t tmp;
2222
2223	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
2224	if (mac->mac_phy.rev < 2) {
2225		tmp = BWN_PHY_READ(mac,
2226		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
2227		tg.tg_gm = tmp & 0x0007;
2228		tg.tg_pga = (tmp & 0x0078) >> 3;
2229		tg.tg_pad = (tmp & 0x780) >> 7;
2230		return (tg);
2231	}
2232
2233	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
2234	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
2235	tg.tg_gm = tmp & 0xff;
2236	tg.tg_pga = (tmp >> 8) & 0xff;
2237	return (tg);
2238}
2239
2240static uint8_t
2241bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
2242{
2243
2244	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
2245}
2246
2247static void
2248bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
2249{
2250	uint16_t pa;
2251
2252	if (mac->mac_phy.rev < 2) {
2253		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
2254		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
2255		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
2256		bwn_phy_lp_set_txgain_override(mac);
2257		return;
2258	}
2259
2260	pa = bwn_phy_lp_get_pa_gain(mac);
2261	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
2262	    (tg->tg_pga << 8) | tg->tg_gm);
2263	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
2264	    tg->tg_pad | (pa << 6));
2265	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
2266	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
2267	    tg->tg_pad | (pa << 8));
2268	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
2269	bwn_phy_lp_set_txgain_override(mac);
2270}
2271
2272static void
2273bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
2274{
2275
2276	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
2277}
2278
2279static void
2280bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
2281{
2282	uint16_t trsw = (tx << 1) | rx;
2283
2284	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
2285	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
2286}
2287
2288static void
2289bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
2290{
2291	struct bwn_softc *sc = mac->mac_sc;
2292	struct ieee80211com *ic = &sc->sc_ic;
2293	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
2294
2295	if (mac->mac_phy.rev < 2) {
2296		trsw = gain & 0x1;
2297		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
2298		ext_lna = (gain & 2) >> 1;
2299
2300		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
2301		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
2302		    0xfbff, ext_lna << 10);
2303		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
2304		    0xf7ff, ext_lna << 11);
2305		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
2306	} else {
2307		low_gain = gain & 0xffff;
2308		high_gain = (gain >> 16) & 0xf;
2309		ext_lna = (gain >> 21) & 0x1;
2310		trsw = ~(gain >> 20) & 0x1;
2311
2312		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
2313		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
2314		    0xfdff, ext_lna << 9);
2315		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
2316		    0xfbff, ext_lna << 10);
2317		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
2318		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
2319		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
2320			tmp = (gain >> 2) & 0x3;
2321			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
2322			    0xe7ff, tmp<<11);
2323			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
2324			    tmp << 3);
2325		}
2326	}
2327
2328	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
2329	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
2330	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
2331	if (mac->mac_phy.rev >= 2) {
2332		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
2333		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
2334			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
2335			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
2336		}
2337		return;
2338	}
2339	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
2340}
2341
2342static void
2343bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
2344{
2345	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
2346
2347	if (user)
2348		plp->plp_crsusr_off = 1;
2349	else
2350		plp->plp_crssys_off = 1;
2351
2352	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
2353}
2354
2355static void
2356bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
2357{
2358	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
2359	struct bwn_softc *sc = mac->mac_sc;
2360	struct ieee80211com *ic = &sc->sc_ic;
2361
2362	if (user)
2363		plp->plp_crsusr_off = 0;
2364	else
2365		plp->plp_crssys_off = 0;
2366
2367	if (plp->plp_crsusr_off || plp->plp_crssys_off)
2368		return;
2369
2370	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
2371		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
2372	else
2373		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
2374}
2375
2376static int
2377bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
2378{
2379#define	CALC_COEFF(_v, _x, _y, _z)	do {				\
2380	int _t;								\
2381	_t = _x - 20;							\
2382	if (_t >= 0) {							\
2383		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
2384	} else {							\
2385		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
2386	}								\
2387} while (0)
2388#define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
2389	int _t;								\
2390	_t = _x - 11;							\
2391	if (_t >= 0)							\
2392		_v = (_y << (31 - _x)) / (_z >> _t);			\
2393	else								\
2394		_v = (_y << (31 - _x)) / (_z << -_t);			\
2395} while (0)
2396	struct bwn_phy_lp_iq_est ie;
2397	uint16_t v0, v1;
2398	int tmp[2], ret;
2399
2400	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
2401	v0 = v1 >> 8;
2402	v1 |= 0xff;
2403
2404	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
2405	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
2406
2407	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
2408	if (ret == 0)
2409		goto done;
2410
2411	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
2412		ret = 0;
2413		goto done;
2414	}
2415
2416	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
2417	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
2418
2419	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
2420	v0 = tmp[0] >> 3;
2421	v1 = tmp[1] >> 4;
2422done:
2423	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
2424	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
2425	return ret;
2426#undef CALC_COEFF
2427#undef CALC_COEFF2
2428}
2429
2430static void
2431bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
2432{
2433	static const uint16_t noisescale[] = {
2434		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
2435		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
2436		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
2437		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2438		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
2439	};
2440	static const uint16_t crsgainnft[] = {
2441		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
2442		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
2443		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
2444		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
2445		0x013d,
2446	};
2447	static const uint16_t filterctl[] = {
2448		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
2449		0xff53, 0x0127,
2450	};
2451	static const uint32_t psctl[] = {
2452		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
2453		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
2454		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
2455		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
2456		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
2457		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
2458		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
2459		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
2460	};
2461	static const uint16_t ofdmcckgain_r0[] = {
2462		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
2463		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
2464		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
2465		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
2466		0x755d,
2467	};
2468	static const uint16_t ofdmcckgain_r1[] = {
2469		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
2470		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
2471		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
2472		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
2473		0x755d,
2474	};
2475	static const uint16_t gaindelta[] = {
2476		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2477		0x0000,
2478	};
2479	static const uint32_t txpwrctl[] = {
2480		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
2481		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
2482		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
2483		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
2484		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
2485		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
2486		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
2487		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
2488		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
2489		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
2490		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
2491		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
2492		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
2493		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2494		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2495		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2496		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2497		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2498		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2499		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2500		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2501		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2502		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2503		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2504		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2505		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2506		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2507		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2508		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2509		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2510		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2511		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2512		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2513		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2514		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2515		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2516		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2517		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2518		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
2519		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
2520		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
2521		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
2522		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
2523		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
2524		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
2525		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
2526		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
2527		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
2528		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
2529		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
2530		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
2531		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
2532		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
2533		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
2534		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
2535		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
2536		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
2537		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
2538		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
2539		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
2540		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
2541		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
2542		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
2543		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
2544		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2545		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2546		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2547		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2548		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2549		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2550		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2551		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2552		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2553		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2554		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2555		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2556		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2557		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2558		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2559		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2560		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2561		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2562		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2563		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2564		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2565		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2566		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2567		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
2568		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
2569		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
2570		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
2571		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
2572		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
2573		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
2574		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
2575		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
2576		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
2577		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
2578		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
2579		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
2580		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
2581		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
2582		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
2583		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
2584		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
2585		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
2586		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
2587		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
2588		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
2589		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
2590		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
2591		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
2592		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
2593		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
2594		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
2595		0x00000702,
2596	};
2597
2598	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
2599
2600	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
2601	    bwn_tab_sigsq_tbl);
2602	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
2603	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
2604	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
2605	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
2606	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
2607	    bwn_tab_pllfrac_tbl);
2608	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
2609	    bwn_tabl_iqlocal_tbl);
2610	if (mac->mac_phy.rev == 0) {
2611		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
2612		    ofdmcckgain_r0);
2613		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
2614		    ofdmcckgain_r0);
2615	} else {
2616		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
2617		    ofdmcckgain_r1);
2618		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
2619		    ofdmcckgain_r1);
2620	}
2621	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
2622	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
2623}
2624
2625static void
2626bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
2627{
2628	struct bwn_softc *sc = mac->mac_sc;
2629	int i;
2630	static const uint16_t noisescale[] = {
2631		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
2632		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
2633		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
2634		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
2635		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
2636		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
2637		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
2638	};
2639	static const uint32_t filterctl[] = {
2640		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
2641		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
2642	};
2643	static const uint32_t psctl[] = {
2644		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
2645		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
2646		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
2647		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
2648	};
2649	static const uint32_t gainidx[] = {
2650		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2651		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2652		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2653		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
2654		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
2655		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
2656		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
2657		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
2658		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
2659		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
2660		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
2661		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
2662		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
2663		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
2664		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
2665		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2666		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2667		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2668		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
2669		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
2670		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
2671		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
2672		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
2673		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
2674		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
2675		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
2676		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
2677		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
2678		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
2679		0x0000001a, 0x64ca55ad, 0x0000001a
2680	};
2681	static const uint16_t auxgainidx[] = {
2682		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2683		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
2684		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
2685		0x0004, 0x0016
2686	};
2687	static const uint16_t swctl[] = {
2688		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
2689		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
2690		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
2691		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
2692		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
2693		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
2694		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
2695		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
2696	};
2697	static const uint8_t hf[] = {
2698		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
2699		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
2700	};
2701	static const uint32_t gainval[] = {
2702		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
2703		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
2704		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
2705		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
2706		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
2707		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
2708		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2709		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2710		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
2711		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
2712		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
2713		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
2714		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
2715		0x000000f1, 0x00000000, 0x00000000
2716	};
2717	static const uint16_t gain[] = {
2718		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
2719		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
2720		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
2721		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
2722		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
2723		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
2724		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2725		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2726		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2727		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2728		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2729		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
2730	};
2731	static const uint32_t papdeps[] = {
2732		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
2733		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
2734		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
2735		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
2736		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
2737		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
2738		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
2739		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
2740		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
2741		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
2742		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
2743		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
2744		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
2745	};
2746	static const uint32_t papdmult[] = {
2747		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
2748		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
2749		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
2750		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
2751		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
2752		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
2753		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
2754		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
2755		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
2756		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
2757		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
2758		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
2759		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
2760	};
2761	static const uint32_t gainidx_a0[] = {
2762		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
2763		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
2764		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
2765		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
2766		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
2767		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
2768		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
2769		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
2770		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
2771		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
2772		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
2773		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
2774		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
2775	};
2776	static const uint16_t auxgainidx_a0[] = {
2777		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2778		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
2779		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2780		0x0002, 0x0014
2781	};
2782	static const uint32_t gainval_a0[] = {
2783		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
2784		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
2785		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
2786		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
2787		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
2788		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
2789		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2790		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2791		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
2792		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
2793		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
2794		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
2795		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
2796		0x000000f7, 0x00000000, 0x00000000
2797	};
2798	static const uint16_t gain_a0[] = {
2799		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
2800		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
2801		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
2802		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
2803		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
2804		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
2805		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2806		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2807		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2808		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2809		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2810		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
2811	};
2812
2813	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
2814
2815	for (i = 0; i < 704; i++)
2816		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
2817
2818	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
2819	    bwn_tab_sigsq_tbl);
2820	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
2821	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
2822	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
2823	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
2824	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
2825	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
2826	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
2827	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
2828	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
2829	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
2830	    bwn_tab_pllfrac_tbl);
2831	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
2832	    bwn_tabl_iqlocal_tbl);
2833	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
2834	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
2835
2836	if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4325 &&
2837	    sc->sc_cid.chip_pkg == 0) {
2838		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
2839		    gainidx_a0);
2840		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
2841		    auxgainidx_a0);
2842		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
2843		    gainval_a0);
2844		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
2845	}
2846}
2847
2848static void
2849bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
2850{
2851	struct bwn_softc *sc = mac->mac_sc;
2852	struct ieee80211com *ic = &sc->sc_ic;
2853	static struct bwn_txgain_entry txgain_r2[] = {
2854		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
2855		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
2856		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
2857		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
2858		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
2859		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
2860		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
2861		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
2862		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
2863		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
2864		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
2865		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
2866		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
2867		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
2868		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
2869		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
2870		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
2871		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
2872		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
2873		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
2874		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
2875		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
2876		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
2877		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
2878		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
2879		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
2880		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
2881		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
2882		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
2883		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
2884		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
2885		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
2886		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
2887		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
2888		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
2889		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
2890		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
2891		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
2892		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
2893		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
2894		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
2895		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
2896		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
2897		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
2898		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
2899		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
2900		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
2901		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
2902		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
2903		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
2904		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
2905		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
2906		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
2907		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
2908		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
2909		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
2910		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
2911		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
2912		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
2913		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
2914		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
2915		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
2916		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
2917		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
2918	};
2919	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
2920		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
2921		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
2922		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
2923		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
2924		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
2925		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
2926		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
2927		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
2928		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
2929		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
2930		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
2931		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
2932		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
2933		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
2934		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
2935		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
2936		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
2937		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
2938		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
2939		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
2940		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
2941		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
2942		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
2943		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
2944		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
2945		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
2946		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
2947		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
2948		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
2949		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
2950		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
2951		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
2952		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
2953		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
2954		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
2955		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
2956		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
2957		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
2958		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
2959		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
2960		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
2961		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
2962		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
2963		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
2964		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
2965		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
2966		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
2967		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
2968		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
2969		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
2970		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
2971		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
2972		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
2973		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
2974		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
2975		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
2976		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
2977		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
2978		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
2979		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
2980		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
2981		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
2982		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
2983		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
2984	};
2985	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
2986		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
2987		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
2988		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
2989		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
2990		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
2991		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
2992		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
2993		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
2994		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
2995		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
2996		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
2997		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
2998		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
2999		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
3000		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
3001		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
3002		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
3003		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
3004		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
3005		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
3006		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
3007		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
3008		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
3009		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
3010		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
3011		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
3012		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
3013		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
3014		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
3015		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
3016		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
3017		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
3018		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
3019		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
3020		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
3021		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
3022		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
3023		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
3024		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
3025		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
3026		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
3027		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
3028		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
3029		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
3030		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
3031		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
3032		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
3033		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
3034		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
3035		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
3036		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
3037		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
3038		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
3039		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
3040		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
3041		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
3042		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
3043		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
3044		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
3045		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
3046		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
3047		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
3048		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
3049		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
3050	};
3051	static struct bwn_txgain_entry txgain_r0[] = {
3052		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
3053		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
3054		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
3055		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
3056		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
3057		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
3058		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
3059		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
3060		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
3061		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
3062		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
3063		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
3064		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
3065		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
3066		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
3067		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
3068		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
3069		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
3070		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
3071		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
3072		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
3073		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
3074		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
3075		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
3076		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
3077		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
3078		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
3079		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
3080		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
3081		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
3082		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
3083		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
3084		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
3085		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
3086		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
3087		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
3088		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
3089		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
3090		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
3091		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
3092		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
3093		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
3094		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
3095		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
3096		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
3097		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
3098		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
3099		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
3100		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
3101		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
3102		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
3103		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
3104		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
3105		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
3106		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
3107		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
3108		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
3109		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
3110		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
3111		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
3112		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
3113		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
3114		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
3115		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
3116	};
3117	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
3118		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
3119		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
3120		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
3121		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
3122		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
3123		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
3124		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
3125		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
3126		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
3127		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
3128		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
3129		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
3130		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
3131		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
3132		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
3133		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
3134		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
3135		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
3136		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
3137		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
3138		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
3139		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
3140		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
3141		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
3142		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
3143		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
3144		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
3145		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
3146		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
3147		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
3148		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
3149		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
3150		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
3151		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
3152		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
3153		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
3154		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
3155		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
3156		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
3157		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
3158		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
3159		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
3160		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
3161		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
3162		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
3163		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
3164		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
3165		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
3166		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
3167		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
3168		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
3169		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
3170		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
3171		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
3172		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
3173		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
3174		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
3175		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
3176		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
3177		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
3178		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
3179		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
3180		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
3181		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
3182	};
3183	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
3184		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
3185		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
3186		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
3187		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
3188		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
3189		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
3190		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
3191		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
3192		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
3193		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
3194		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
3195		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
3196		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
3197		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
3198		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
3199		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
3200		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
3201		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
3202		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
3203		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
3204		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
3205		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
3206		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
3207		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
3208		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
3209		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
3210		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
3211		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
3212		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
3213		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
3214		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
3215		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
3216		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
3217		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
3218		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
3219		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
3220		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
3221		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
3222		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
3223		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
3224		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
3225		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
3226		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
3227		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
3228		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
3229		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
3230		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
3231		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
3232		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
3233		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
3234		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
3235		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
3236		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
3237		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
3238		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
3239		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
3240		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
3241		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
3242		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
3243		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
3244		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
3245		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
3246		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
3247		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
3248	};
3249	static struct bwn_txgain_entry txgain_r1[] = {
3250		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
3251		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
3252		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
3253		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
3254		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
3255		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
3256		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
3257		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
3258		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
3259		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
3260		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
3261		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
3262		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
3263		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
3264		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
3265		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
3266		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
3267		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
3268		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
3269		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
3270		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
3271		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
3272		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
3273		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
3274		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
3275		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
3276		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
3277		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
3278		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
3279		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
3280		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
3281		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
3282		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
3283		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
3284		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
3285		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
3286		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
3287		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
3288		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
3289		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
3290		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
3291		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
3292		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
3293		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
3294		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
3295		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
3296		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
3297		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
3298		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
3299		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
3300		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
3301		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
3302		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
3303		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
3304		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
3305		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
3306		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
3307		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
3308		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
3309		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
3310		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
3311		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
3312		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
3313		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
3314		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
3315		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
3316		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
3317		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
3318		{ 7, 11, 6, 0, 71 }
3319	};
3320	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
3321		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
3322		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
3323		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
3324		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
3325		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
3326		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
3327		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
3328		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
3329		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
3330		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
3331		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
3332		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
3333		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
3334		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
3335		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
3336		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
3337		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
3338		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
3339		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
3340		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
3341		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
3342		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
3343		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
3344		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
3345		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
3346		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
3347		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
3348		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
3349		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
3350		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
3351		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
3352		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
3353		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
3354		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
3355		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
3356		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
3357		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
3358		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
3359		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
3360		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
3361		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
3362		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
3363		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
3364		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
3365		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
3366		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
3367		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
3368		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
3369		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
3370		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
3371		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
3372		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
3373		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
3374		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
3375		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
3376		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
3377		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
3378		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
3379		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
3380		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
3381		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
3382		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
3383		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
3384		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
3385	};
3386	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
3387		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
3388		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
3389		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
3390		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
3391		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
3392		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
3393		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
3394		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
3395		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
3396		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
3397		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
3398		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
3399		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
3400		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
3401		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
3402		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
3403		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
3404		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
3405		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
3406		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
3407		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
3408		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
3409		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
3410		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
3411		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
3412		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
3413		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
3414		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
3415		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
3416		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
3417		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
3418		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
3419		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
3420		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
3421		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
3422		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
3423		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
3424		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
3425		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
3426		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
3427		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
3428		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
3429		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
3430		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
3431		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
3432		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
3433		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
3434		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
3435		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
3436		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
3437		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
3438		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
3439		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
3440		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
3441		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
3442		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
3443		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
3444		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
3445		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
3446		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
3447		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
3448		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
3449		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
3450		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
3451	};
3452
3453	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
3454		if (sc->sc_board_info.board_flags & BHND_BFL_NOPA)
3455			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
3456		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
3457			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
3458			    txgain_2ghz_r2);
3459		else
3460			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
3461			    txgain_5ghz_r2);
3462		return;
3463	}
3464
3465	if (mac->mac_phy.rev == 0) {
3466		if ((sc->sc_board_info.board_flags & BHND_BFL_NOPA) ||
3467		    (sc->sc_board_info.board_flags & BHND_BFL_HGPA))
3468			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
3469		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
3470			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
3471			    txgain_2ghz_r0);
3472		else
3473			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
3474			    txgain_5ghz_r0);
3475		return;
3476	}
3477
3478	if ((sc->sc_board_info.board_flags & BHND_BFL_NOPA) ||
3479	    (sc->sc_board_info.board_flags & BHND_BFL_HGPA))
3480		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
3481	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
3482		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
3483	else
3484		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
3485}
3486
3487static void
3488bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
3489{
3490	uint32_t offset, type;
3491
3492	type = BWN_TAB_GETTYPE(typeoffset);
3493	offset = BWN_TAB_GETOFFSET(typeoffset);
3494	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
3495
3496	switch (type) {
3497	case BWN_TAB_8BIT:
3498		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
3499		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
3500		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
3501		break;
3502	case BWN_TAB_16BIT:
3503		KASSERT(!(value & ~0xffff),
3504		    ("%s:%d: fail", __func__, __LINE__));
3505		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
3506		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
3507		break;
3508	case BWN_TAB_32BIT:
3509		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
3510		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
3511		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
3512		break;
3513	default:
3514		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3515	}
3516}
3517
3518static int
3519bwn_phy_lp_loopback(struct bwn_mac *mac)
3520{
3521	struct bwn_phy_lp_iq_est ie;
3522	int i, index = -1;
3523	uint32_t tmp;
3524
3525	memset(&ie, 0, sizeof(ie));
3526
3527	bwn_phy_lp_set_trsw_over(mac, 1, 1);
3528	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
3529	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
3530	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
3531	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
3532	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
3533	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
3534	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
3535	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
3536	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
3537	for (i = 0; i < 32; i++) {
3538		bwn_phy_lp_set_rxgain_idx(mac, i);
3539		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
3540		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
3541			continue;
3542		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
3543		if ((tmp > 4000) && (tmp < 10000)) {
3544			index = i;
3545			break;
3546		}
3547	}
3548	bwn_phy_lp_ddfs_turnoff(mac);
3549	return (index);
3550}
3551
3552static void
3553bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
3554{
3555
3556	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
3557}
3558
3559static void
3560bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
3561    int incr1, int incr2, int scale_idx)
3562{
3563
3564	bwn_phy_lp_ddfs_turnoff(mac);
3565	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
3566	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
3567	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
3568	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
3569	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
3570	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
3571	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
3572	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
3573	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
3574	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
3575}
3576
3577static uint8_t
3578bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
3579    struct bwn_phy_lp_iq_est *ie)
3580{
3581	int i;
3582
3583	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
3584	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
3585	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
3586	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
3587	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
3588
3589	for (i = 0; i < 500; i++) {
3590		if (!(BWN_PHY_READ(mac,
3591		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
3592			break;
3593		DELAY(1000);
3594	}
3595	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
3596		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
3597		return 0;
3598	}
3599
3600	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
3601	ie->ie_iqprod <<= 16;
3602	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
3603	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
3604	ie->ie_ipwr <<= 16;
3605	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
3606	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
3607	ie->ie_qpwr <<= 16;
3608	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
3609
3610	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
3611	return 1;
3612}
3613
3614static uint32_t
3615bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
3616{
3617	uint32_t offset, type, value;
3618
3619	type = BWN_TAB_GETTYPE(typeoffset);
3620	offset = BWN_TAB_GETOFFSET(typeoffset);
3621	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
3622
3623	switch (type) {
3624	case BWN_TAB_8BIT:
3625		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
3626		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
3627		break;
3628	case BWN_TAB_16BIT:
3629		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
3630		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
3631		break;
3632	case BWN_TAB_32BIT:
3633		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
3634		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
3635		value <<= 16;
3636		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
3637		break;
3638	default:
3639		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3640		value = 0;
3641	}
3642
3643	return (value);
3644}
3645
3646static void
3647bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
3648{
3649
3650	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
3651	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
3652}
3653
3654static void
3655bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
3656{
3657	uint16_t ctl;
3658
3659	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
3660	ctl |= dac << 7;
3661	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
3662}
3663
3664static void
3665bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
3666{
3667
3668	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
3669	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
3670}
3671
3672static void
3673bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
3674{
3675
3676	if (mac->mac_phy.rev < 2)
3677		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
3678	else {
3679		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
3680		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
3681	}
3682	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
3683}
3684
3685static uint16_t
3686bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
3687{
3688
3689	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
3690}
3691
3692static uint8_t
3693bwn_nbits(int32_t val)
3694{
3695	uint32_t tmp;
3696	uint8_t nbits = 0;
3697
3698	for (tmp = abs(val); tmp != 0; tmp >>= 1)
3699		nbits++;
3700	return (nbits);
3701}
3702
3703static void
3704bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
3705    struct bwn_txgain_entry *table)
3706{
3707	int i;
3708
3709	for (i = offset; i < count; i++)
3710		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
3711}
3712
3713static void
3714bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
3715    struct bwn_txgain_entry data)
3716{
3717
3718	if (mac->mac_phy.rev >= 2)
3719		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
3720	else
3721		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
3722}
3723
3724static void
3725bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
3726    struct bwn_txgain_entry te)
3727{
3728	struct bwn_softc *sc = mac->mac_sc;
3729	struct ieee80211com *ic = &sc->sc_ic;
3730	uint32_t tmp;
3731
3732	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
3733
3734	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
3735	if (mac->mac_phy.rev >= 3) {
3736		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
3737		    (0x10 << 24) : (0x70 << 24));
3738	} else {
3739		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
3740		    (0x14 << 24) : (0x7f << 24));
3741	}
3742	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
3743	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
3744	    te.te_bbmult << 20 | te.te_dac << 28);
3745}
3746
3747static void
3748bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
3749    struct bwn_txgain_entry te)
3750{
3751
3752	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
3753
3754	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
3755	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
3756	    te.te_dac);
3757	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
3758}
3759