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