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 
82 static 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 
96 static 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 
110 static 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 
125 static 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?
143 static 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 */
162 static 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 */
174 static 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 */
244 static 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 */
346 static 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 */
427 static 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 
590 void 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 
644 void 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