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
r2057_upload_inittabs(struct bwn_mac * mac)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
r2057_get_chantabent_rev7(struct bwn_mac * mac,uint16_t freq,const struct bwn_nphy_chantabent_rev7 ** tabent_r7,const struct bwn_nphy_chantabent_rev7_2g ** tabent_r7_2g)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