1
2/*
3
4  Broadcom B43 wireless driver
5  IEEE 802.11n PHY data tables
6
7  Copyright (c) 2008 Michael Buesch <m@bues.ch>
8  Copyright (c) 2010 Rafa�� Mi��ecki <zajec5@gmail.com>
9
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License
21  along with this program; see the file COPYING.  If not, write to
22  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
23  Boston, MA 02110-1301, USA.
24
25*/
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
30/*
31 * The Broadcom Wireless LAN controller driver.
32 */
33
34#include "opt_wlan.h"
35#include "opt_bwn.h"
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/malloc.h>
41#include <sys/module.h>
42#include <sys/endian.h>
43#include <sys/errno.h>
44#include <sys/firmware.h>
45#include <sys/lock.h>
46#include <sys/mutex.h>
47#include <machine/bus.h>
48#include <machine/resource.h>
49#include <sys/bus.h>
50#include <sys/rman.h>
51#include <sys/socket.h>
52#include <sys/sockio.h>
53
54#include <net/ethernet.h>
55#include <net/if.h>
56#include <net/if_var.h>
57#include <net/if_arp.h>
58#include <net/if_dl.h>
59#include <net/if_llc.h>
60#include <net/if_media.h>
61#include <net/if_types.h>
62
63#include <dev/pci/pcivar.h>
64#include <dev/pci/pcireg.h>
65
66#include <net80211/ieee80211_var.h>
67#include <net80211/ieee80211_radiotap.h>
68#include <net80211/ieee80211_regdomain.h>
69#include <net80211/ieee80211_phy.h>
70#include <net80211/ieee80211_ratectl.h>
71
72#include <dev/bwn/if_bwnreg.h>
73#include <dev/bwn/if_bwnvar.h>
74#include <dev/bwn/if_bwn_debug.h>
75
76#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_regs.h>
77#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_ppr.h>
78#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_tables.h>
79#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_core.h>
80#include <gnu/dev/bwn/phy_n/if_bwn_radio_2057.h>
81
82static uint16_t r2057_rev4_init[][2] = {
83	{ 0x0E, 0x20 }, { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 },
84	{ 0x35, 0x26 }, { 0x3C, 0xff }, { 0x3D, 0xff }, { 0x3E, 0xff },
85	{ 0x3F, 0xff }, { 0x62, 0x33 }, { 0x8A, 0xf0 }, { 0x8B, 0x10 },
86	{ 0x8C, 0xf0 }, { 0x91, 0x3f }, { 0x92, 0x36 }, { 0xA4, 0x8c },
87	{ 0xA8, 0x55 }, { 0xAF, 0x01 }, { 0x10F, 0xf0 }, { 0x110, 0x10 },
88	{ 0x111, 0xf0 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x129, 0x8c },
89	{ 0x12D, 0x55 }, { 0x134, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
90	{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
91	{ 0x169, 0x02 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
92	{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
93	{ 0x1AB, 0x00 }, { 0x1AC, 0x00 },
94};
95
96static uint16_t r2057_rev5_init[][2] = {
97	{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
98	{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
99	{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
100	{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
101	{ 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
102	{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
103	{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
104	{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
105	{ 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 },
106	{ 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 },
107	{ 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 }, { 0x1C2, 0x80 },
108};
109
110static uint16_t r2057_rev5a_init[][2] = {
111	{ 0x00, 0x15 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
112	{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
113	{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
114	{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
115	{ 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
116	{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
117	{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x14E, 0x01 }, { 0x15E, 0x00 },
118	{ 0x15F, 0x00 }, { 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 },
119	{ 0x163, 0x00 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
120	{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
121	{ 0x1AB, 0x00 }, { 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 },
122	{ 0x1C2, 0x80 },
123};
124
125static uint16_t r2057_rev7_init[][2] = {
126	{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
127	{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
128	{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x13 },
129	{ 0x66, 0xee }, { 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 },
130	{ 0x7C, 0x14 }, { 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f },
131	{ 0x92, 0x36 }, { 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
132	{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x13 }, { 0xEB, 0xee },
133	{ 0xF3, 0x58 }, { 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x14 },
134	{ 0x102, 0xee }, { 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 },
135	{ 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
136	{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
137	{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
138	{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
139	{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
140};
141
142/* TODO: Which devices should use it?
143static uint16_t r2057_rev8_init[][2] = {
144	{ 0x00, 0x08 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
145	{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
146	{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x0f },
147	{ 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 }, { 0x7C, 0x0f },
148	{ 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
149	{ 0xA1, 0x20 }, { 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
150	{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0xF3, 0x58 },
151	{ 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x0f }, { 0x102, 0xee },
152	{ 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x126, 0x20 },
153	{ 0x14E, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
154	{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
155	{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
156	{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
157	{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
158};
159*/
160
161/* Extracted from MMIO dump of 6.30.223.141 */
162static uint16_t r2057_rev9_init[][2] = {
163	{ 0x27, 0x1f }, { 0x28, 0x0a }, { 0x29, 0x2f }, { 0x42, 0x1f },
164	{ 0x48, 0x3f }, { 0x5c, 0x41 }, { 0x63, 0x14 }, { 0x64, 0x12 },
165	{ 0x66, 0xff }, { 0x74, 0xa3 }, { 0x7b, 0x14 }, { 0x7c, 0x14 },
166	{ 0x7d, 0xee }, { 0x86, 0xc0 }, { 0xc4, 0x10 }, { 0xc9, 0x01 },
167	{ 0xe1, 0x41 }, { 0xe8, 0x14 }, { 0xe9, 0x12 }, { 0xeb, 0xff },
168	{ 0xf5, 0x0a }, { 0xf8, 0x09 }, { 0xf9, 0xa3 }, { 0x100, 0x14 },
169	{ 0x101, 0x10 }, { 0x102, 0xee }, { 0x10b, 0xc0 }, { 0x149, 0x10 },
170	{ 0x14e, 0x01 }, { 0x1b7, 0x05 }, { 0x1c2, 0xa0 },
171};
172
173/* Extracted from MMIO dump of 6.30.223.248 */
174static uint16_t r2057_rev14_init[][2] = {
175	{ 0x011, 0xfc }, { 0x030, 0x24 }, { 0x040, 0x1c }, { 0x082, 0x08 },
176	{ 0x0b4, 0x44 }, { 0x0c8, 0x01 }, { 0x0c9, 0x01 }, { 0x107, 0x08 },
177	{ 0x14d, 0x01 }, { 0x14e, 0x01 }, { 0x1af, 0x40 }, { 0x1b0, 0x40 },
178	{ 0x1cc, 0x01 }, { 0x1cf, 0x10 }, { 0x1d0, 0x0f }, { 0x1d3, 0x10 },
179	{ 0x1d4, 0x0f },
180};
181
182#define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
183		   r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
184		   r20, r21, r22, r23, r24, r25, r26, r27) \
185	.radio_vcocal_countval0			= r00,	\
186	.radio_vcocal_countval1			= r01,	\
187	.radio_rfpll_refmaster_sparextalsize	= r02,	\
188	.radio_rfpll_loopfilter_r1		= r03,	\
189	.radio_rfpll_loopfilter_c2		= r04,	\
190	.radio_rfpll_loopfilter_c1		= r05,	\
191	.radio_cp_kpd_idac			= r06,	\
192	.radio_rfpll_mmd0			= r07,	\
193	.radio_rfpll_mmd1			= r08,	\
194	.radio_vcobuf_tune			= r09,	\
195	.radio_logen_mx2g_tune			= r10,	\
196	.radio_logen_mx5g_tune			= r11,	\
197	.radio_logen_indbuf2g_tune		= r12,	\
198	.radio_logen_indbuf5g_tune		= r13,	\
199	.radio_txmix2g_tune_boost_pu_core0	= r14,	\
200	.radio_pad2g_tune_pus_core0		= r15,	\
201	.radio_pga_boost_tune_core0		= r16,	\
202	.radio_txmix5g_boost_tune_core0		= r17,	\
203	.radio_pad5g_tune_misc_pus_core0	= r18,	\
204	.radio_lna2g_tune_core0			= r19,	\
205	.radio_lna5g_tune_core0			= r20,	\
206	.radio_txmix2g_tune_boost_pu_core1	= r21,	\
207	.radio_pad2g_tune_pus_core1		= r22,	\
208	.radio_pga_boost_tune_core1		= r23,	\
209	.radio_txmix5g_boost_tune_core1		= r24,	\
210	.radio_pad5g_tune_misc_pus_core1	= r25,	\
211	.radio_lna2g_tune_core1			= r26,	\
212	.radio_lna5g_tune_core1			= r27
213
214#define RADIOREGS7_2G(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
215		      r10, r11, r12, r13, r14, r15, r16, r17) \
216	.radio_vcocal_countval0			= r00,	\
217	.radio_vcocal_countval1			= r01,	\
218	.radio_rfpll_refmaster_sparextalsize	= r02,	\
219	.radio_rfpll_loopfilter_r1		= r03,	\
220	.radio_rfpll_loopfilter_c2		= r04,	\
221	.radio_rfpll_loopfilter_c1		= r05,	\
222	.radio_cp_kpd_idac			= r06,	\
223	.radio_rfpll_mmd0			= r07,	\
224	.radio_rfpll_mmd1			= r08,	\
225	.radio_vcobuf_tune			= r09,	\
226	.radio_logen_mx2g_tune			= r10,	\
227	.radio_logen_indbuf2g_tune		= r11,	\
228	.radio_txmix2g_tune_boost_pu_core0	= r12,	\
229	.radio_pad2g_tune_pus_core0		= r13,	\
230	.radio_lna2g_tune_core0			= r14,	\
231	.radio_txmix2g_tune_boost_pu_core1	= r15,	\
232	.radio_pad2g_tune_pus_core1		= r16,	\
233	.radio_lna2g_tune_core1			= r17
234
235#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
236	.phy_regs.phy_bw1a	= r0,	\
237	.phy_regs.phy_bw2	= r1,	\
238	.phy_regs.phy_bw3	= r2,	\
239	.phy_regs.phy_bw4	= r3,	\
240	.phy_regs.phy_bw5	= r4,	\
241	.phy_regs.phy_bw6	= r5
242
243/* Copied from brcmsmac (5.75.11): chan_info_nphyrev8_2057_rev5 */
244static const struct bwn_nphy_chantabent_rev7_2g bwn_nphy_chantab_phy_rev8_radio_rev5[] = {
245	{
246		.freq			= 2412,
247		RADIOREGS7_2G(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
248			      0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
249			      0x03, 0xff),
250		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
251	},
252	{
253		.freq			= 2417,
254		RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
255			      0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
256			      0x03, 0xff),
257		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
258	},
259	{
260		.freq			= 2422,
261		RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
262			      0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61,
263			      0x03, 0xef),
264		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
265	},
266	{
267		.freq			= 2427,
268		RADIOREGS7_2G(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
269			      0x09, 0x0c, 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61,
270			      0x03, 0xdf),
271		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
272	},
273	{
274		.freq			= 2432,
275		RADIOREGS7_2G(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
276			      0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61,
277			      0x03, 0xcf),
278		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
279	},
280	{
281		.freq			= 2437,
282		RADIOREGS7_2G(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
283			      0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61,
284			      0x03, 0xbf),
285		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
286	},
287	{
288		.freq			= 2442,
289		RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
290			      0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61,
291			      0x03, 0xaf),
292		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
293	},
294	{
295		.freq			= 2447,
296		RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
297			      0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61,
298			      0x03, 0x9f),
299		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
300	},
301	{
302		.freq			= 2452,
303		RADIOREGS7_2G(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
304			      0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61,
305			      0x03, 0x8f),
306		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
307	},
308	{
309		.freq			= 2457,
310		RADIOREGS7_2G(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
311			      0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61,
312			      0x03, 0x7f),
313		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
314	},
315	{
316		.freq			= 2462,
317		RADIOREGS7_2G(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
318			      0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61,
319			      0x03, 0x6f),
320		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
321	},
322	{
323		.freq			= 2467,
324		RADIOREGS7_2G(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
325			      0x09, 0x0b, 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61,
326			      0x03, 0x5f),
327		PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
328	},
329	{
330		.freq			= 2472,
331		RADIOREGS7_2G(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
332			      0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61,
333			      0x03, 0x4f),
334		PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
335	},
336	{
337		.freq			= 2484,
338		RADIOREGS7_2G(0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4,
339			      0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61,
340			      0x03, 0x3f),
341		PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
342	}
343};
344
345/* Extracted from MMIO dump of 6.30.223.248 */
346static const struct bwn_nphy_chantabent_rev7_2g bwn_nphy_chantab_phy_rev17_radio_rev14[] = {
347	{
348		.freq			= 2412,
349		RADIOREGS7_2G(0x48, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x6c,
350			      0x09, 0x0d, 0x09, 0x03, 0x21, 0x53, 0xff, 0x21,
351			      0x53, 0xff),
352		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
353	},
354	{
355		.freq			= 2417,
356		RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x71,
357			      0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
358			      0x53, 0xff),
359		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
360	},
361	{
362		.freq			= 2422,
363		RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x76,
364			      0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
365			      0x53, 0xff),
366		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
367	},
368	{
369		.freq			= 2427,
370		RADIOREGS7_2G(0x52, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x7b,
371			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
372			      0x53, 0xff),
373		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
374	},
375	{
376		.freq			= 2432,
377		RADIOREGS7_2G(0x55, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x80,
378			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
379			      0x53, 0xff),
380		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
381	},
382	{
383		.freq			= 2437,
384		RADIOREGS7_2G(0x58, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x85,
385			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
386			      0x53, 0xff),
387		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
388	},
389	{
390		.freq			= 2442,
391		RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8a,
392			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
393			      0x43, 0xff),
394		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
395	},
396	{
397		.freq			= 2447,
398		RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8f,
399			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
400			      0x43, 0xff),
401		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
402	},
403	{
404		.freq			= 2452,
405		RADIOREGS7_2G(0x62, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x94,
406			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
407			      0x43, 0xff),
408		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
409	},
410	{
411		.freq			= 2457,
412		RADIOREGS7_2G(0x66, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x99,
413			      0x09, 0x0b, 0x07, 0x03, 0x21, 0x43, 0xff, 0x21,
414			      0x43, 0xff),
415		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
416	},
417	{
418		.freq			= 2462,
419		RADIOREGS7_2G(0x69, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x9e,
420			      0x09, 0x0b, 0x07, 0x03, 0x01, 0x43, 0xff, 0x01,
421			      0x43, 0xff),
422		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
423	},
424};
425
426/* Extracted from MMIO dump of 6.30.223.141 */
427static const struct bwn_nphy_chantabent_rev7 bwn_nphy_chantab_phy_rev16_radio_rev9[] = {
428	{
429		.freq			= 2412,
430		RADIOREGS7(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
431			   0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
432			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
433			   0x00, 0x00, 0xf0, 0x00),
434		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
435	},
436	{
437		.freq			= 2417,
438		RADIOREGS7(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
439			   0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
440			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
441			   0x00, 0x00, 0xf0, 0x00),
442		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
443	},
444	{
445		.freq			= 2422,
446		RADIOREGS7(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
447			   0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
448			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
449			   0x00, 0x00, 0xf0, 0x00),
450		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
451	},
452	{
453		.freq			= 2427,
454		RADIOREGS7(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
455			   0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
456			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
457			   0x00, 0x00, 0xf0, 0x00),
458		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
459	},
460	{
461		.freq			= 2432,
462		RADIOREGS7(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
463			   0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
464			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
465			   0x00, 0x00, 0xf0, 0x00),
466		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
467	},
468	{
469		.freq			= 2437,
470		RADIOREGS7(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
471			   0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
472			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
473			   0x00, 0x00, 0xf0, 0x00),
474		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
475	},
476	{
477		.freq			= 2442,
478		RADIOREGS7(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
479			   0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
480			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
481			   0x00, 0x00, 0xf0, 0x00),
482		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
483	},
484	{
485		.freq			= 2447,
486		RADIOREGS7(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
487			   0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
488			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
489			   0x00, 0x00, 0xf0, 0x00),
490		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
491	},
492	{
493		.freq			= 2452,
494		RADIOREGS7(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
495			   0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
496			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
497			   0x00, 0x00, 0xf0, 0x00),
498		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
499	},
500	{
501		.freq			= 2457,
502		RADIOREGS7(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
503			   0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
504			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
505			   0x00, 0x00, 0xf0, 0x00),
506		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
507	},
508	{
509		.freq			= 2462,
510		RADIOREGS7(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
511			   0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
512			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
513			   0x00, 0x00, 0xf0, 0x00),
514		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
515	},
516	{
517		.freq			= 5180,
518		RADIOREGS7(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06,
519			   0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
520			   0x9f, 0x2f, 0xa3, 0x00, 0xfc, 0x00, 0x00, 0x4f,
521			   0x3a, 0x83, 0x00, 0xfc),
522		PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
523	},
524	{
525		.freq			= 5200,
526		RADIOREGS7(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08,
527			   0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
528			   0x7f, 0x2f, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x4c,
529			   0x4a, 0x83, 0x00, 0xf8),
530		PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
531	},
532	{
533		.freq			= 5220,
534		RADIOREGS7(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a,
535			   0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
536			   0x6d, 0x3d, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x2d,
537			   0x2a, 0x73, 0x00, 0xf8),
538		PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
539	},
540	{
541		.freq			= 5240,
542		RADIOREGS7(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c,
543			   0x02, 0x0d, 0x00, 0x0d, 0x00, 0x8d, 0x00, 0x00,
544			   0x4d, 0x1c, 0x73, 0x00, 0xf8, 0x00, 0x00, 0x4d,
545			   0x2b, 0x73, 0x00, 0xf8),
546		PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
547	},
548	{
549		.freq			= 5745,
550		RADIOREGS7(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d,
551			   0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
552			   0x08, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x06,
553			   0x02, 0x03, 0x00, 0x30),
554		PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
555	},
556	{
557		.freq			= 5765,
558		RADIOREGS7(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81,
559			   0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
560			   0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
561			   0x02, 0x03, 0x00, 0x00),
562		PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
563	},
564	{
565		.freq			= 5785,
566		RADIOREGS7(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85,
567			   0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
568			   0x08, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
569			   0x21, 0x03, 0x00, 0x00),
570		PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
571	},
572	{
573		.freq			= 5805,
574		RADIOREGS7(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89,
575			   0x04, 0x07, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00,
576			   0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
577			   0x00, 0x03, 0x00, 0x00),
578		PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
579	},
580	{
581		.freq			= 5825,
582		RADIOREGS7(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d,
583			   0x04, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00,
584			   0x05, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
585			   0x00, 0x03, 0x00, 0x00),
586		PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
587	},
588};
589
590void r2057_upload_inittabs(struct bwn_mac *mac)
591{
592	struct bwn_phy *phy = &mac->mac_phy;
593	uint16_t *table = NULL;
594	uint16_t size, i;
595
596	switch (phy->rev) {
597	case 7:
598		table = r2057_rev4_init[0];
599		size = nitems(r2057_rev4_init);
600		break;
601	case 8:
602		if (phy->rf_rev == 5) {
603			table = r2057_rev5_init[0];
604			size = nitems(r2057_rev5_init);
605		} else if (phy->rf_rev == 7) {
606			table = r2057_rev7_init[0];
607			size = nitems(r2057_rev7_init);
608		}
609		break;
610	case 9:
611		if (phy->rf_rev == 5) {
612			table = r2057_rev5a_init[0];
613			size = nitems(r2057_rev5a_init);
614		}
615		break;
616	case 16:
617		if (phy->rf_rev == 9) {
618			table = r2057_rev9_init[0];
619			size = nitems(r2057_rev9_init);
620		}
621		break;
622	case 17:
623		if (phy->rf_rev == 14) {
624			table = r2057_rev14_init[0];
625			size = nitems(r2057_rev14_init);
626		}
627		break;
628	}
629
630	if (! table) {
631		device_printf(mac->mac_sc->sc_dev,
632		    "%s: couldn't find a suitable table (phy ref=%d, rf_ref=%d)\n",
633		    __func__,
634		    phy->rev,
635		    phy->rf_rev);
636	}
637
638	if (table) {
639		for (i = 0; i < size; i++, table += 2)
640			BWN_RF_WRITE(mac, table[0], table[1]);
641	}
642}
643
644void r2057_get_chantabent_rev7(struct bwn_mac *mac, uint16_t freq,
645			       const struct bwn_nphy_chantabent_rev7 **tabent_r7,
646			       const struct bwn_nphy_chantabent_rev7_2g **tabent_r7_2g)
647{
648	struct bwn_phy *phy = &mac->mac_phy;
649	const struct bwn_nphy_chantabent_rev7 *e_r7 = NULL;
650	const struct bwn_nphy_chantabent_rev7_2g *e_r7_2g = NULL;
651	unsigned int len, i;
652
653	*tabent_r7 = NULL;
654	*tabent_r7_2g = NULL;
655
656	switch (phy->rev) {
657	case 8:
658		if (phy->rf_rev == 5) {
659			e_r7_2g = bwn_nphy_chantab_phy_rev8_radio_rev5;
660			len = nitems(bwn_nphy_chantab_phy_rev8_radio_rev5);
661		}
662		break;
663	case 16:
664		if (phy->rf_rev == 9) {
665			e_r7 = bwn_nphy_chantab_phy_rev16_radio_rev9;
666			len = nitems(bwn_nphy_chantab_phy_rev16_radio_rev9);
667		}
668		break;
669	case 17:
670		if (phy->rf_rev == 14) {
671			e_r7_2g = bwn_nphy_chantab_phy_rev17_radio_rev14;
672			len = nitems(bwn_nphy_chantab_phy_rev17_radio_rev14);
673		}
674		break;
675	default:
676		break;
677	}
678
679	if (e_r7) {
680		for (i = 0; i < len; i++, e_r7++) {
681			if (e_r7->freq == freq) {
682				*tabent_r7 = e_r7;
683				return;
684			}
685		}
686	} else if (e_r7_2g) {
687		for (i = 0; i < len; i++, e_r7_2g++) {
688			if (e_r7_2g->freq == freq) {
689				*tabent_r7_2g = e_r7_2g;
690				return;
691			}
692		}
693	} else {
694		device_printf(mac->mac_sc->sc_dev,
695		    "%s: couldn't find a suitable chantab\n",
696		    __func__);
697	}
698}
699