]>
Commit | Line | Data |
---|---|---|
7bc04215 FF |
1 | /* |
2 | * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | ||
17 | #include <linux/delay.h> | |
18 | #include "mt76x2.h" | |
19 | #include "mt76x2_eeprom.h" | |
20 | #include "mt76x2_mcu.h" | |
21 | ||
22 | struct mt76x2_reg_pair { | |
23 | u32 reg; | |
24 | u32 value; | |
25 | }; | |
26 | ||
27 | static bool | |
28 | mt76x2_wait_for_mac(struct mt76x2_dev *dev) | |
29 | { | |
30 | int i; | |
31 | ||
32 | for (i = 0; i < 500; i++) { | |
33 | switch (mt76_rr(dev, MT_MAC_CSR0)) { | |
34 | case 0: | |
35 | case ~0: | |
36 | break; | |
37 | default: | |
38 | return true; | |
39 | } | |
40 | usleep_range(5000, 10000); | |
41 | } | |
42 | ||
43 | return false; | |
44 | } | |
45 | ||
46 | static bool | |
47 | wait_for_wpdma(struct mt76x2_dev *dev) | |
48 | { | |
49 | return mt76_poll(dev, MT_WPDMA_GLO_CFG, | |
50 | MT_WPDMA_GLO_CFG_TX_DMA_BUSY | | |
51 | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, | |
52 | 0, 1000); | |
53 | } | |
54 | ||
55 | static void | |
56 | mt76x2_mac_pbf_init(struct mt76x2_dev *dev) | |
57 | { | |
58 | u32 val; | |
59 | ||
60 | val = MT_PBF_SYS_CTRL_MCU_RESET | | |
61 | MT_PBF_SYS_CTRL_DMA_RESET | | |
62 | MT_PBF_SYS_CTRL_MAC_RESET | | |
63 | MT_PBF_SYS_CTRL_PBF_RESET | | |
64 | MT_PBF_SYS_CTRL_ASY_RESET; | |
65 | ||
66 | mt76_set(dev, MT_PBF_SYS_CTRL, val); | |
67 | mt76_clear(dev, MT_PBF_SYS_CTRL, val); | |
68 | ||
69 | mt76_wr(dev, MT_PBF_TX_MAX_PCNT, 0xefef3f1f); | |
70 | mt76_wr(dev, MT_PBF_RX_MAX_PCNT, 0xfebf); | |
71 | } | |
72 | ||
73 | static void | |
74 | mt76x2_write_reg_pairs(struct mt76x2_dev *dev, | |
75 | const struct mt76x2_reg_pair *data, int len) | |
76 | { | |
77 | while (len > 0) { | |
78 | mt76_wr(dev, data->reg, data->value); | |
79 | len--; | |
80 | data++; | |
81 | } | |
82 | } | |
83 | ||
84 | static void | |
85 | mt76_write_mac_initvals(struct mt76x2_dev *dev) | |
86 | { | |
87 | #define DEFAULT_PROT_CFG \ | |
88 | (FIELD_PREP(MT_PROT_CFG_RATE, 0x2004) | \ | |
89 | FIELD_PREP(MT_PROT_CFG_NAV, 1) | \ | |
90 | FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x3f) | \ | |
91 | MT_PROT_CFG_RTS_THRESH) | |
92 | ||
93 | #define DEFAULT_PROT_CFG_20 \ | |
94 | (FIELD_PREP(MT_PROT_CFG_RATE, 0x2004) | \ | |
95 | FIELD_PREP(MT_PROT_CFG_CTRL, 1) | \ | |
96 | FIELD_PREP(MT_PROT_CFG_NAV, 1) | \ | |
97 | FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x17)) | |
98 | ||
99 | #define DEFAULT_PROT_CFG_40 \ | |
100 | (FIELD_PREP(MT_PROT_CFG_RATE, 0x2084) | \ | |
101 | FIELD_PREP(MT_PROT_CFG_CTRL, 1) | \ | |
102 | FIELD_PREP(MT_PROT_CFG_NAV, 1) | \ | |
103 | FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x3f)) | |
104 | ||
105 | static const struct mt76x2_reg_pair vals[] = { | |
106 | /* Copied from MediaTek reference source */ | |
107 | { MT_PBF_SYS_CTRL, 0x00080c00 }, | |
108 | { MT_PBF_CFG, 0x1efebcff }, | |
109 | { MT_FCE_PSE_CTRL, 0x00000001 }, | |
110 | { MT_MAC_SYS_CTRL, 0x0000000c }, | |
111 | { MT_MAX_LEN_CFG, 0x003e3f00 }, | |
112 | { MT_AMPDU_MAX_LEN_20M1S, 0xaaa99887 }, | |
113 | { MT_AMPDU_MAX_LEN_20M2S, 0x000000aa }, | |
114 | { MT_XIFS_TIME_CFG, 0x33a40d0a }, | |
115 | { MT_BKOFF_SLOT_CFG, 0x00000209 }, | |
116 | { MT_TBTT_SYNC_CFG, 0x00422010 }, | |
117 | { MT_PWR_PIN_CFG, 0x00000000 }, | |
118 | { 0x1238, 0x001700c8 }, | |
119 | { MT_TX_SW_CFG0, 0x00101001 }, | |
120 | { MT_TX_SW_CFG1, 0x00010000 }, | |
121 | { MT_TX_SW_CFG2, 0x00000000 }, | |
122 | { MT_TXOP_CTRL_CFG, 0x0400583f }, | |
123 | { MT_TX_RTS_CFG, 0x00100020 }, | |
124 | { MT_TX_TIMEOUT_CFG, 0x000a2290 }, | |
125 | { MT_TX_RETRY_CFG, 0x47f01f0f }, | |
126 | { MT_EXP_ACK_TIME, 0x002c00dc }, | |
127 | { MT_TX_PROT_CFG6, 0xe3f42004 }, | |
128 | { MT_TX_PROT_CFG7, 0xe3f42084 }, | |
129 | { MT_TX_PROT_CFG8, 0xe3f42104 }, | |
130 | { MT_PIFS_TX_CFG, 0x00060fff }, | |
131 | { MT_RX_FILTR_CFG, 0x00015f97 }, | |
132 | { MT_LEGACY_BASIC_RATE, 0x0000017f }, | |
133 | { MT_HT_BASIC_RATE, 0x00004003 }, | |
30ce7f44 | 134 | { MT_PN_PAD_MODE, 0x00000003 }, |
7bc04215 FF |
135 | { MT_TXOP_HLDR_ET, 0x00000002 }, |
136 | { 0xa44, 0x00000000 }, | |
137 | { MT_HEADER_TRANS_CTRL_REG, 0x00000000 }, | |
138 | { MT_TSO_CTRL, 0x00000000 }, | |
139 | { MT_AUX_CLK_CFG, 0x00000000 }, | |
140 | { MT_DACCLK_EN_DLY_CFG, 0x00000000 }, | |
141 | { MT_TX_ALC_CFG_4, 0x00000000 }, | |
142 | { MT_TX_ALC_VGA3, 0x00000000 }, | |
143 | { MT_TX_PWR_CFG_0, 0x3a3a3a3a }, | |
144 | { MT_TX_PWR_CFG_1, 0x3a3a3a3a }, | |
145 | { MT_TX_PWR_CFG_2, 0x3a3a3a3a }, | |
146 | { MT_TX_PWR_CFG_3, 0x3a3a3a3a }, | |
147 | { MT_TX_PWR_CFG_4, 0x3a3a3a3a }, | |
148 | { MT_TX_PWR_CFG_7, 0x3a3a3a3a }, | |
149 | { MT_TX_PWR_CFG_8, 0x0000003a }, | |
150 | { MT_TX_PWR_CFG_9, 0x0000003a }, | |
151 | { MT_EFUSE_CTRL, 0x0000d000 }, | |
152 | { MT_PAUSE_ENABLE_CONTROL1, 0x0000000a }, | |
153 | { MT_FCE_WLAN_FLOW_CONTROL1, 0x60401c18 }, | |
154 | { MT_WPDMA_DELAY_INT_CFG, 0x94ff0000 }, | |
155 | { MT_TX_SW_CFG3, 0x00000004 }, | |
156 | { MT_HT_FBK_TO_LEGACY, 0x00001818 }, | |
157 | { MT_VHT_HT_FBK_CFG1, 0xedcba980 }, | |
158 | { MT_PROT_AUTO_TX_CFG, 0x00830083 }, | |
159 | { MT_HT_CTRL_CFG, 0x000001ff }, | |
160 | }; | |
161 | struct mt76x2_reg_pair prot_vals[] = { | |
162 | { MT_CCK_PROT_CFG, DEFAULT_PROT_CFG }, | |
163 | { MT_OFDM_PROT_CFG, DEFAULT_PROT_CFG }, | |
164 | { MT_MM20_PROT_CFG, DEFAULT_PROT_CFG_20 }, | |
165 | { MT_MM40_PROT_CFG, DEFAULT_PROT_CFG_40 }, | |
166 | { MT_GF20_PROT_CFG, DEFAULT_PROT_CFG_20 }, | |
167 | { MT_GF40_PROT_CFG, DEFAULT_PROT_CFG_40 }, | |
168 | }; | |
169 | ||
170 | mt76x2_write_reg_pairs(dev, vals, ARRAY_SIZE(vals)); | |
171 | mt76x2_write_reg_pairs(dev, prot_vals, ARRAY_SIZE(prot_vals)); | |
172 | } | |
173 | ||
174 | static void | |
175 | mt76x2_fixup_xtal(struct mt76x2_dev *dev) | |
176 | { | |
177 | u16 eep_val; | |
178 | s8 offset = 0; | |
179 | ||
180 | eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_2); | |
181 | ||
182 | offset = eep_val & 0x7f; | |
183 | if ((eep_val & 0xff) == 0xff) | |
184 | offset = 0; | |
185 | else if (eep_val & 0x80) | |
186 | offset = 0 - offset; | |
187 | ||
188 | eep_val >>= 8; | |
189 | if (eep_val == 0x00 || eep_val == 0xff) { | |
190 | eep_val = mt76x2_eeprom_get(dev, MT_EE_XTAL_TRIM_1); | |
191 | eep_val &= 0xff; | |
192 | ||
193 | if (eep_val == 0x00 || eep_val == 0xff) | |
194 | eep_val = 0x14; | |
195 | } | |
196 | ||
197 | eep_val &= 0x7f; | |
198 | mt76_rmw_field(dev, MT_XO_CTRL5, MT_XO_CTRL5_C2_VAL, eep_val + offset); | |
199 | mt76_set(dev, MT_XO_CTRL6, MT_XO_CTRL6_C2_CTRL); | |
200 | ||
201 | eep_val = mt76x2_eeprom_get(dev, MT_EE_NIC_CONF_2); | |
202 | switch (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, eep_val)) { | |
203 | case 0: | |
204 | mt76_wr(dev, MT_XO_CTRL7, 0x5c1fee80); | |
205 | break; | |
206 | case 1: | |
207 | mt76_wr(dev, MT_XO_CTRL7, 0x5c1feed0); | |
208 | break; | |
209 | default: | |
210 | break; | |
211 | } | |
212 | } | |
213 | ||
214 | static void | |
215 | mt76x2_init_beacon_offsets(struct mt76x2_dev *dev) | |
216 | { | |
217 | u16 base = MT_BEACON_BASE; | |
218 | u32 regs[4] = {}; | |
219 | int i; | |
220 | ||
221 | for (i = 0; i < 16; i++) { | |
222 | u16 addr = dev->beacon_offsets[i]; | |
223 | ||
224 | regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4)); | |
225 | } | |
226 | ||
227 | for (i = 0; i < 4; i++) | |
228 | mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]); | |
229 | } | |
230 | ||
231 | int mt76x2_mac_reset(struct mt76x2_dev *dev, bool hard) | |
232 | { | |
233 | static const u8 null_addr[ETH_ALEN] = {}; | |
234 | const u8 *macaddr = dev->mt76.macaddr; | |
235 | u32 val; | |
236 | int i, k; | |
237 | ||
238 | if (!mt76x2_wait_for_mac(dev)) | |
239 | return -ETIMEDOUT; | |
240 | ||
241 | val = mt76_rr(dev, MT_WPDMA_GLO_CFG); | |
242 | ||
243 | val &= ~(MT_WPDMA_GLO_CFG_TX_DMA_EN | | |
244 | MT_WPDMA_GLO_CFG_TX_DMA_BUSY | | |
245 | MT_WPDMA_GLO_CFG_RX_DMA_EN | | |
246 | MT_WPDMA_GLO_CFG_RX_DMA_BUSY | | |
247 | MT_WPDMA_GLO_CFG_DMA_BURST_SIZE); | |
248 | val |= FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3); | |
249 | ||
250 | mt76_wr(dev, MT_WPDMA_GLO_CFG, val); | |
251 | ||
252 | mt76x2_mac_pbf_init(dev); | |
253 | mt76_write_mac_initvals(dev); | |
254 | mt76x2_fixup_xtal(dev); | |
255 | ||
256 | mt76_clear(dev, MT_MAC_SYS_CTRL, | |
257 | MT_MAC_SYS_CTRL_RESET_CSR | | |
258 | MT_MAC_SYS_CTRL_RESET_BBP); | |
259 | ||
260 | if (is_mt7612(dev)) | |
261 | mt76_clear(dev, MT_COEXCFG0, MT_COEXCFG0_COEX_EN); | |
262 | ||
263 | mt76_set(dev, MT_EXT_CCA_CFG, 0x0000f000); | |
264 | mt76_clear(dev, MT_TX_ALC_CFG_4, BIT(31)); | |
265 | ||
266 | mt76_wr(dev, MT_RF_BYPASS_0, 0x06000000); | |
267 | mt76_wr(dev, MT_RF_SETTING_0, 0x08800000); | |
268 | usleep_range(5000, 10000); | |
269 | mt76_wr(dev, MT_RF_BYPASS_0, 0x00000000); | |
270 | ||
271 | mt76_wr(dev, MT_MCU_CLOCK_CTL, 0x1401); | |
272 | mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN); | |
273 | ||
274 | mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(macaddr)); | |
275 | mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(macaddr + 4)); | |
276 | ||
277 | mt76_wr(dev, MT_MAC_BSSID_DW0, get_unaligned_le32(macaddr)); | |
278 | mt76_wr(dev, MT_MAC_BSSID_DW1, get_unaligned_le16(macaddr + 4) | | |
279 | FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 beacons */ | |
280 | MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT); | |
281 | ||
282 | /* Fire a pre-TBTT interrupt 8 ms before TBTT */ | |
283 | mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, | |
284 | 8 << 4); | |
285 | mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER, | |
286 | MT_DFS_GP_INTERVAL); | |
287 | mt76_wr(dev, MT_INT_TIMER_EN, 0); | |
288 | ||
289 | mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); | |
290 | if (!hard) | |
291 | return 0; | |
292 | ||
293 | for (i = 0; i < 256 / 32; i++) | |
294 | mt76_wr(dev, MT_WCID_DROP_BASE + i * 4, 0); | |
295 | ||
296 | for (i = 0; i < 256; i++) | |
297 | mt76x2_mac_wcid_setup(dev, i, 0, NULL); | |
298 | ||
299 | for (i = 0; i < 16; i++) | |
300 | for (k = 0; k < 4; k++) | |
301 | mt76x2_mac_shared_key_setup(dev, i, k, NULL); | |
302 | ||
303 | for (i = 0; i < 8; i++) { | |
304 | mt76x2_mac_set_bssid(dev, i, null_addr); | |
305 | mt76x2_mac_set_beacon(dev, i, NULL); | |
306 | } | |
307 | ||
308 | for (i = 0; i < 16; i++) | |
309 | mt76_rr(dev, MT_TX_STAT_FIFO); | |
310 | ||
7bc04215 FF |
311 | mt76_wr(dev, MT_CH_TIME_CFG, |
312 | MT_CH_TIME_CFG_TIMER_EN | | |
313 | MT_CH_TIME_CFG_TX_AS_BUSY | | |
314 | MT_CH_TIME_CFG_RX_AS_BUSY | | |
315 | MT_CH_TIME_CFG_NAV_AS_BUSY | | |
316 | MT_CH_TIME_CFG_EIFS_AS_BUSY | | |
317 | FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1)); | |
318 | ||
319 | mt76x2_init_beacon_offsets(dev); | |
320 | ||
321 | mt76x2_set_tx_ackto(dev); | |
322 | ||
323 | return 0; | |
324 | } | |
325 | ||
326 | int mt76x2_mac_start(struct mt76x2_dev *dev) | |
327 | { | |
328 | int i; | |
329 | ||
330 | for (i = 0; i < 16; i++) | |
331 | mt76_rr(dev, MT_TX_AGG_CNT(i)); | |
332 | ||
333 | for (i = 0; i < 16; i++) | |
334 | mt76_rr(dev, MT_TX_STAT_FIFO); | |
335 | ||
336 | memset(dev->aggr_stats, 0, sizeof(dev->aggr_stats)); | |
337 | ||
338 | mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX); | |
339 | wait_for_wpdma(dev); | |
340 | usleep_range(50, 100); | |
341 | ||
342 | mt76_set(dev, MT_WPDMA_GLO_CFG, | |
343 | MT_WPDMA_GLO_CFG_TX_DMA_EN | | |
344 | MT_WPDMA_GLO_CFG_RX_DMA_EN); | |
345 | ||
346 | mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); | |
347 | ||
348 | mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter); | |
349 | ||
350 | mt76_wr(dev, MT_MAC_SYS_CTRL, | |
351 | MT_MAC_SYS_CTRL_ENABLE_TX | | |
352 | MT_MAC_SYS_CTRL_ENABLE_RX); | |
353 | ||
354 | mt76x2_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | | |
355 | MT_INT_TX_STAT); | |
356 | ||
357 | return 0; | |
358 | } | |
359 | ||
360 | void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force) | |
361 | { | |
362 | bool stopped = false; | |
363 | u32 rts_cfg; | |
364 | int i; | |
365 | ||
366 | mt76_wr(dev, MT_MAC_SYS_CTRL, 0); | |
367 | ||
368 | rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); | |
369 | mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); | |
370 | ||
371 | /* Wait for MAC to become idle */ | |
372 | for (i = 0; i < 300; i++) { | |
373 | if (mt76_rr(dev, MT_MAC_STATUS) & | |
374 | (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) | |
375 | continue; | |
376 | ||
377 | if (mt76_rr(dev, MT_BBP(IBI, 12))) | |
378 | continue; | |
379 | ||
380 | stopped = true; | |
381 | break; | |
382 | } | |
383 | ||
384 | if (force && !stopped) { | |
385 | mt76_set(dev, MT_BBP(CORE, 4), BIT(1)); | |
386 | mt76_clear(dev, MT_BBP(CORE, 4), BIT(1)); | |
387 | ||
388 | mt76_set(dev, MT_BBP(CORE, 4), BIT(0)); | |
389 | mt76_clear(dev, MT_BBP(CORE, 4), BIT(0)); | |
390 | } | |
391 | ||
392 | mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg); | |
393 | } | |
394 | ||
395 | void mt76x2_mac_resume(struct mt76x2_dev *dev) | |
396 | { | |
397 | mt76_wr(dev, MT_MAC_SYS_CTRL, | |
398 | MT_MAC_SYS_CTRL_ENABLE_TX | | |
399 | MT_MAC_SYS_CTRL_ENABLE_RX); | |
400 | } | |
401 | ||
402 | static void | |
403 | mt76x2_power_on_rf_patch(struct mt76x2_dev *dev) | |
404 | { | |
405 | mt76_set(dev, 0x10130, BIT(0) | BIT(16)); | |
406 | udelay(1); | |
407 | ||
408 | mt76_clear(dev, 0x1001c, 0xff); | |
409 | mt76_set(dev, 0x1001c, 0x30); | |
410 | ||
411 | mt76_wr(dev, 0x10014, 0x484f); | |
412 | udelay(1); | |
413 | ||
414 | mt76_set(dev, 0x10130, BIT(17)); | |
415 | udelay(125); | |
416 | ||
417 | mt76_clear(dev, 0x10130, BIT(16)); | |
418 | udelay(50); | |
419 | ||
420 | mt76_set(dev, 0x1014c, BIT(19) | BIT(20)); | |
421 | } | |
422 | ||
423 | static void | |
424 | mt76x2_power_on_rf(struct mt76x2_dev *dev, int unit) | |
425 | { | |
426 | int shift = unit ? 8 : 0; | |
427 | ||
428 | /* Enable RF BG */ | |
429 | mt76_set(dev, 0x10130, BIT(0) << shift); | |
430 | udelay(10); | |
431 | ||
432 | /* Enable RFDIG LDO/AFE/ABB/ADDA */ | |
433 | mt76_set(dev, 0x10130, (BIT(1) | BIT(3) | BIT(4) | BIT(5)) << shift); | |
434 | udelay(10); | |
435 | ||
436 | /* Switch RFDIG power to internal LDO */ | |
437 | mt76_clear(dev, 0x10130, BIT(2) << shift); | |
438 | udelay(10); | |
439 | ||
440 | mt76x2_power_on_rf_patch(dev); | |
441 | ||
442 | mt76_set(dev, 0x530, 0xf); | |
443 | } | |
444 | ||
445 | static void | |
446 | mt76x2_power_on(struct mt76x2_dev *dev) | |
447 | { | |
448 | u32 val; | |
449 | ||
450 | /* Turn on WL MTCMOS */ | |
451 | mt76_set(dev, MT_WLAN_MTC_CTRL, MT_WLAN_MTC_CTRL_MTCMOS_PWR_UP); | |
452 | ||
453 | val = MT_WLAN_MTC_CTRL_STATE_UP | | |
454 | MT_WLAN_MTC_CTRL_PWR_ACK | | |
455 | MT_WLAN_MTC_CTRL_PWR_ACK_S; | |
456 | ||
457 | mt76_poll(dev, MT_WLAN_MTC_CTRL, val, val, 1000); | |
458 | ||
459 | mt76_clear(dev, MT_WLAN_MTC_CTRL, 0x7f << 16); | |
460 | udelay(10); | |
461 | ||
462 | mt76_clear(dev, MT_WLAN_MTC_CTRL, 0xf << 24); | |
463 | udelay(10); | |
464 | ||
465 | mt76_set(dev, MT_WLAN_MTC_CTRL, 0xf << 24); | |
466 | mt76_clear(dev, MT_WLAN_MTC_CTRL, 0xfff); | |
467 | ||
468 | /* Turn on AD/DA power down */ | |
469 | mt76_clear(dev, 0x11204, BIT(3)); | |
470 | ||
471 | /* WLAN function enable */ | |
472 | mt76_set(dev, 0x10080, BIT(0)); | |
473 | ||
474 | /* Release BBP software reset */ | |
475 | mt76_clear(dev, 0x10064, BIT(18)); | |
476 | ||
477 | mt76x2_power_on_rf(dev, 0); | |
478 | mt76x2_power_on_rf(dev, 1); | |
479 | } | |
480 | ||
481 | void mt76x2_set_tx_ackto(struct mt76x2_dev *dev) | |
482 | { | |
483 | u8 ackto, sifs, slottime = dev->slottime; | |
484 | ||
485 | slottime += 3 * dev->coverage_class; | |
486 | ||
487 | sifs = mt76_get_field(dev, MT_XIFS_TIME_CFG, | |
488 | MT_XIFS_TIME_CFG_OFDM_SIFS); | |
489 | ||
490 | ackto = slottime + sifs; | |
491 | mt76_rmw_field(dev, MT_TX_TIMEOUT_CFG, | |
492 | MT_TX_TIMEOUT_CFG_ACKTO, ackto); | |
493 | } | |
494 | ||
495 | static void | |
496 | mt76x2_set_wlan_state(struct mt76x2_dev *dev, bool enable) | |
497 | { | |
498 | u32 val = mt76_rr(dev, MT_WLAN_FUN_CTRL); | |
499 | ||
500 | if (enable) | |
501 | val |= (MT_WLAN_FUN_CTRL_WLAN_EN | | |
502 | MT_WLAN_FUN_CTRL_WLAN_CLK_EN); | |
503 | else | |
504 | val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN | | |
505 | MT_WLAN_FUN_CTRL_WLAN_CLK_EN); | |
506 | ||
507 | mt76_wr(dev, MT_WLAN_FUN_CTRL, val); | |
508 | udelay(20); | |
509 | } | |
510 | ||
511 | static void | |
512 | mt76x2_reset_wlan(struct mt76x2_dev *dev, bool enable) | |
513 | { | |
514 | u32 val; | |
515 | ||
516 | val = mt76_rr(dev, MT_WLAN_FUN_CTRL); | |
517 | ||
518 | val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL; | |
519 | ||
520 | if (val & MT_WLAN_FUN_CTRL_WLAN_EN) { | |
521 | val |= MT_WLAN_FUN_CTRL_WLAN_RESET_RF; | |
522 | mt76_wr(dev, MT_WLAN_FUN_CTRL, val); | |
523 | udelay(20); | |
524 | ||
525 | val &= ~MT_WLAN_FUN_CTRL_WLAN_RESET_RF; | |
526 | } | |
527 | ||
528 | mt76_wr(dev, MT_WLAN_FUN_CTRL, val); | |
529 | udelay(20); | |
530 | ||
531 | mt76x2_set_wlan_state(dev, enable); | |
532 | } | |
533 | ||
534 | int mt76x2_init_hardware(struct mt76x2_dev *dev) | |
535 | { | |
536 | static const u16 beacon_offsets[16] = { | |
537 | /* 1024 byte per beacon */ | |
538 | 0xc000, | |
539 | 0xc400, | |
540 | 0xc800, | |
541 | 0xcc00, | |
542 | 0xd000, | |
543 | 0xd400, | |
544 | 0xd800, | |
545 | 0xdc00, | |
546 | ||
547 | /* BSS idx 8-15 not used for beacons */ | |
548 | 0xc000, | |
549 | 0xc000, | |
550 | 0xc000, | |
551 | 0xc000, | |
552 | 0xc000, | |
553 | 0xc000, | |
554 | 0xc000, | |
555 | 0xc000, | |
556 | }; | |
557 | u32 val; | |
558 | int ret; | |
559 | ||
560 | dev->beacon_offsets = beacon_offsets; | |
561 | tasklet_init(&dev->pre_tbtt_tasklet, mt76x2_pre_tbtt_tasklet, | |
562 | (unsigned long) dev); | |
563 | ||
564 | dev->chainmask = 0x202; | |
565 | dev->global_wcid.idx = 255; | |
566 | dev->global_wcid.hw_key_idx = -1; | |
567 | dev->slottime = 9; | |
568 | ||
569 | val = mt76_rr(dev, MT_WPDMA_GLO_CFG); | |
570 | val &= MT_WPDMA_GLO_CFG_DMA_BURST_SIZE | | |
571 | MT_WPDMA_GLO_CFG_BIG_ENDIAN | | |
572 | MT_WPDMA_GLO_CFG_HDR_SEG_LEN; | |
573 | val |= MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE; | |
574 | mt76_wr(dev, MT_WPDMA_GLO_CFG, val); | |
575 | ||
576 | mt76x2_reset_wlan(dev, true); | |
577 | mt76x2_power_on(dev); | |
578 | ||
579 | ret = mt76x2_eeprom_init(dev); | |
580 | if (ret) | |
581 | return ret; | |
582 | ||
583 | ret = mt76x2_mac_reset(dev, true); | |
584 | if (ret) | |
585 | return ret; | |
586 | ||
a86af66f LB |
587 | dev->rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG); |
588 | ||
7bc04215 FF |
589 | ret = mt76x2_dma_init(dev); |
590 | if (ret) | |
591 | return ret; | |
592 | ||
593 | set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); | |
594 | ret = mt76x2_mac_start(dev); | |
595 | if (ret) | |
596 | return ret; | |
597 | ||
598 | ret = mt76x2_mcu_init(dev); | |
599 | if (ret) | |
600 | return ret; | |
601 | ||
602 | mt76x2_mac_stop(dev, false); | |
7bc04215 FF |
603 | |
604 | return 0; | |
605 | } | |
606 | ||
607 | void mt76x2_stop_hardware(struct mt76x2_dev *dev) | |
608 | { | |
609 | cancel_delayed_work_sync(&dev->cal_work); | |
610 | cancel_delayed_work_sync(&dev->mac_work); | |
611 | mt76x2_mcu_set_radio_state(dev, false); | |
612 | mt76x2_mac_stop(dev, false); | |
613 | } | |
614 | ||
615 | void mt76x2_cleanup(struct mt76x2_dev *dev) | |
616 | { | |
ba9797b2 LB |
617 | tasklet_disable(&dev->dfs_pd.dfs_tasklet); |
618 | tasklet_disable(&dev->pre_tbtt_tasklet); | |
7bc04215 FF |
619 | mt76x2_stop_hardware(dev); |
620 | mt76x2_dma_cleanup(dev); | |
621 | mt76x2_mcu_cleanup(dev); | |
622 | } | |
623 | ||
624 | struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev) | |
625 | { | |
626 | static const struct mt76_driver_ops drv_ops = { | |
627 | .txwi_size = sizeof(struct mt76x2_txwi), | |
628 | .update_survey = mt76x2_update_channel, | |
629 | .tx_prepare_skb = mt76x2_tx_prepare_skb, | |
630 | .tx_complete_skb = mt76x2_tx_complete_skb, | |
631 | .rx_skb = mt76x2_queue_rx_skb, | |
632 | .rx_poll_complete = mt76x2_rx_poll_complete, | |
d71ef286 | 633 | .sta_ps = mt76x2_sta_ps, |
7bc04215 FF |
634 | }; |
635 | struct ieee80211_hw *hw; | |
636 | struct mt76x2_dev *dev; | |
637 | ||
638 | hw = ieee80211_alloc_hw(sizeof(*dev), &mt76x2_ops); | |
639 | if (!hw) | |
640 | return NULL; | |
641 | ||
642 | dev = hw->priv; | |
643 | dev->mt76.dev = pdev; | |
644 | dev->mt76.hw = hw; | |
645 | dev->mt76.drv = &drv_ops; | |
646 | mutex_init(&dev->mutex); | |
647 | spin_lock_init(&dev->irq_lock); | |
648 | ||
649 | return dev; | |
650 | } | |
651 | ||
652 | static void mt76x2_regd_notifier(struct wiphy *wiphy, | |
653 | struct regulatory_request *request) | |
654 | { | |
655 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | |
656 | struct mt76x2_dev *dev = hw->priv; | |
657 | ||
2070f3cc | 658 | mt76x2_dfs_set_domain(dev, request->dfs_region); |
7bc04215 FF |
659 | } |
660 | ||
661 | #define CCK_RATE(_idx, _rate) { \ | |
662 | .bitrate = _rate, \ | |
663 | .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ | |
664 | .hw_value = (MT_PHY_TYPE_CCK << 8) | _idx, \ | |
665 | .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + _idx), \ | |
666 | } | |
667 | ||
668 | #define OFDM_RATE(_idx, _rate) { \ | |
669 | .bitrate = _rate, \ | |
670 | .hw_value = (MT_PHY_TYPE_OFDM << 8) | _idx, \ | |
671 | .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | _idx, \ | |
672 | } | |
673 | ||
674 | static struct ieee80211_rate mt76x2_rates[] = { | |
675 | CCK_RATE(0, 10), | |
676 | CCK_RATE(1, 20), | |
677 | CCK_RATE(2, 55), | |
678 | CCK_RATE(3, 110), | |
679 | OFDM_RATE(0, 60), | |
680 | OFDM_RATE(1, 90), | |
681 | OFDM_RATE(2, 120), | |
682 | OFDM_RATE(3, 180), | |
683 | OFDM_RATE(4, 240), | |
684 | OFDM_RATE(5, 360), | |
685 | OFDM_RATE(6, 480), | |
686 | OFDM_RATE(7, 540), | |
687 | }; | |
688 | ||
689 | static const struct ieee80211_iface_limit if_limits[] = { | |
690 | { | |
691 | .max = 1, | |
692 | .types = BIT(NL80211_IFTYPE_ADHOC) | |
693 | }, { | |
694 | .max = 8, | |
695 | .types = BIT(NL80211_IFTYPE_STATION) | | |
696 | #ifdef CONFIG_MAC80211_MESH | |
697 | BIT(NL80211_IFTYPE_MESH_POINT) | | |
698 | #endif | |
699 | BIT(NL80211_IFTYPE_AP) | |
700 | }, | |
701 | }; | |
702 | ||
703 | static const struct ieee80211_iface_combination if_comb[] = { | |
704 | { | |
705 | .limits = if_limits, | |
706 | .n_limits = ARRAY_SIZE(if_limits), | |
707 | .max_interfaces = 8, | |
708 | .num_different_channels = 1, | |
709 | .beacon_int_infra_match = true, | |
710 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | | |
711 | BIT(NL80211_CHAN_WIDTH_20) | | |
712 | BIT(NL80211_CHAN_WIDTH_40) | | |
713 | BIT(NL80211_CHAN_WIDTH_80), | |
714 | } | |
715 | }; | |
716 | ||
717 | static void mt76x2_led_set_config(struct mt76_dev *mt76, u8 delay_on, | |
718 | u8 delay_off) | |
719 | { | |
720 | struct mt76x2_dev *dev = container_of(mt76, struct mt76x2_dev, | |
721 | mt76); | |
722 | u32 val; | |
723 | ||
724 | val = MT_LED_STATUS_DURATION(0xff) | | |
725 | MT_LED_STATUS_OFF(delay_off) | | |
726 | MT_LED_STATUS_ON(delay_on); | |
727 | ||
728 | mt76_wr(dev, MT_LED_S0(mt76->led_pin), val); | |
729 | mt76_wr(dev, MT_LED_S1(mt76->led_pin), val); | |
730 | ||
731 | val = MT_LED_CTRL_REPLAY(mt76->led_pin) | | |
732 | MT_LED_CTRL_KICK(mt76->led_pin); | |
733 | if (mt76->led_al) | |
734 | val |= MT_LED_CTRL_POLARITY(mt76->led_pin); | |
735 | mt76_wr(dev, MT_LED_CTRL, val); | |
736 | } | |
737 | ||
738 | static int mt76x2_led_set_blink(struct led_classdev *led_cdev, | |
739 | unsigned long *delay_on, | |
740 | unsigned long *delay_off) | |
741 | { | |
742 | struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, | |
743 | led_cdev); | |
744 | u8 delta_on, delta_off; | |
745 | ||
746 | delta_off = max_t(u8, *delay_off / 10, 1); | |
747 | delta_on = max_t(u8, *delay_on / 10, 1); | |
748 | ||
749 | mt76x2_led_set_config(mt76, delta_on, delta_off); | |
750 | return 0; | |
751 | } | |
752 | ||
753 | static void mt76x2_led_set_brightness(struct led_classdev *led_cdev, | |
754 | enum led_brightness brightness) | |
755 | { | |
756 | struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, | |
757 | led_cdev); | |
758 | ||
759 | if (!brightness) | |
760 | mt76x2_led_set_config(mt76, 0, 0xff); | |
761 | else | |
762 | mt76x2_led_set_config(mt76, 0xff, 0); | |
763 | } | |
764 | ||
984ea503 FF |
765 | static void |
766 | mt76x2_init_txpower(struct mt76x2_dev *dev, | |
767 | struct ieee80211_supported_band *sband) | |
768 | { | |
769 | struct ieee80211_channel *chan; | |
770 | struct mt76x2_tx_power_info txp; | |
771 | struct mt76_rate_power t = {}; | |
772 | int target_power; | |
773 | int i; | |
774 | ||
775 | for (i = 0; i < sband->n_channels; i++) { | |
776 | chan = &sband->channels[i]; | |
777 | ||
778 | mt76x2_get_power_info(dev, &txp, chan); | |
779 | ||
780 | target_power = max_t(int, (txp.chain[0].target_power + | |
781 | txp.chain[0].delta), | |
782 | (txp.chain[1].target_power + | |
783 | txp.chain[1].delta)); | |
784 | ||
785 | mt76x2_get_rate_power(dev, &t, chan); | |
786 | ||
787 | chan->max_power = mt76x2_get_max_rate_power(&t) + | |
788 | target_power; | |
789 | chan->max_power /= 2; | |
53aa29b2 FF |
790 | |
791 | /* convert to combined output power on 2x2 devices */ | |
792 | chan->max_power += 3; | |
984ea503 FF |
793 | } |
794 | } | |
795 | ||
7bc04215 FF |
796 | int mt76x2_register_device(struct mt76x2_dev *dev) |
797 | { | |
798 | struct ieee80211_hw *hw = mt76_hw(dev); | |
799 | struct wiphy *wiphy = hw->wiphy; | |
800 | void *status_fifo; | |
801 | int fifo_size; | |
802 | int i, ret; | |
803 | ||
804 | fifo_size = roundup_pow_of_two(32 * sizeof(struct mt76x2_tx_status)); | |
805 | status_fifo = devm_kzalloc(dev->mt76.dev, fifo_size, GFP_KERNEL); | |
806 | if (!status_fifo) | |
807 | return -ENOMEM; | |
808 | ||
809 | kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size); | |
810 | ||
811 | ret = mt76x2_init_hardware(dev); | |
812 | if (ret) | |
813 | return ret; | |
814 | ||
815 | hw->queues = 4; | |
816 | hw->max_rates = 1; | |
817 | hw->max_report_rates = 7; | |
818 | hw->max_rate_tries = 1; | |
819 | hw->extra_tx_headroom = 2; | |
820 | ||
821 | hw->sta_data_size = sizeof(struct mt76x2_sta); | |
822 | hw->vif_data_size = sizeof(struct mt76x2_vif); | |
823 | ||
824 | for (i = 0; i < ARRAY_SIZE(dev->macaddr_list); i++) { | |
825 | u8 *addr = dev->macaddr_list[i].addr; | |
826 | ||
827 | memcpy(addr, dev->mt76.macaddr, ETH_ALEN); | |
828 | ||
829 | if (!i) | |
830 | continue; | |
831 | ||
832 | addr[0] |= BIT(1); | |
833 | addr[0] ^= ((i - 1) << 2); | |
834 | } | |
835 | wiphy->addresses = dev->macaddr_list; | |
836 | wiphy->n_addresses = ARRAY_SIZE(dev->macaddr_list); | |
837 | ||
838 | wiphy->iface_combinations = if_comb; | |
839 | wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); | |
840 | ||
841 | wiphy->reg_notifier = mt76x2_regd_notifier; | |
842 | ||
843 | wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); | |
844 | ||
845 | ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); | |
aee5b8cf FF |
846 | ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); |
847 | ||
7bc04215 FF |
848 | INIT_DELAYED_WORK(&dev->cal_work, mt76x2_phy_calibrate); |
849 | INIT_DELAYED_WORK(&dev->mac_work, mt76x2_mac_work); | |
850 | ||
851 | dev->mt76.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; | |
852 | dev->mt76.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; | |
853 | ||
854 | mt76x2_dfs_init_detector(dev); | |
855 | ||
856 | /* init led callbacks */ | |
857 | dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness; | |
858 | dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink; | |
859 | ||
24114a5f LB |
860 | /* init antenna configuration */ |
861 | dev->mt76.antenna_mask = 3; | |
862 | ||
7bc04215 FF |
863 | ret = mt76_register_device(&dev->mt76, true, mt76x2_rates, |
864 | ARRAY_SIZE(mt76x2_rates)); | |
865 | if (ret) | |
866 | goto fail; | |
867 | ||
868 | mt76x2_init_debugfs(dev); | |
984ea503 FF |
869 | mt76x2_init_txpower(dev, &dev->mt76.sband_2g.sband); |
870 | mt76x2_init_txpower(dev, &dev->mt76.sband_5g.sband); | |
7bc04215 FF |
871 | |
872 | return 0; | |
873 | ||
874 | fail: | |
875 | mt76x2_stop_hardware(dev); | |
876 | return ret; | |
877 | } | |
878 | ||
879 |