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