1134b2d0dSStanislaw Gruszka /*
2134b2d0dSStanislaw Gruszka  * (c) Copyright 2002-2010, Ralink Technology, Inc.
3134b2d0dSStanislaw Gruszka  * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
4134b2d0dSStanislaw Gruszka  * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
5134b2d0dSStanislaw Gruszka  * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
6134b2d0dSStanislaw Gruszka  *
7134b2d0dSStanislaw Gruszka  * This program is free software; you can redistribute it and/or modify
8134b2d0dSStanislaw Gruszka  * it under the terms of the GNU General Public License version 2
9134b2d0dSStanislaw Gruszka  * as published by the Free Software Foundation
10134b2d0dSStanislaw Gruszka  *
11134b2d0dSStanislaw Gruszka  * This program is distributed in the hope that it will be useful,
12134b2d0dSStanislaw Gruszka  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13134b2d0dSStanislaw Gruszka  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14134b2d0dSStanislaw Gruszka  * GNU General Public License for more details.
15134b2d0dSStanislaw Gruszka  */
16134b2d0dSStanislaw Gruszka 
17134b2d0dSStanislaw Gruszka #include "mt76x0.h"
18134b2d0dSStanislaw Gruszka #include "eeprom.h"
19134b2d0dSStanislaw Gruszka #include "trace.h"
20134b2d0dSStanislaw Gruszka #include "mcu.h"
21134b2d0dSStanislaw Gruszka #include "usb.h"
22f2653a4eSLorenzo Bianconi #include "../mt76x02_util.h"
23134b2d0dSStanislaw Gruszka 
24134b2d0dSStanislaw Gruszka #include "initvals.h"
25134b2d0dSStanislaw Gruszka 
26134b2d0dSStanislaw Gruszka static void
27134b2d0dSStanislaw Gruszka mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable)
28134b2d0dSStanislaw Gruszka {
29134b2d0dSStanislaw Gruszka 	int i;
30134b2d0dSStanislaw Gruszka 
31134b2d0dSStanislaw Gruszka 	/* Note: we don't turn off WLAN_CLK because that makes the device
32134b2d0dSStanislaw Gruszka 	 *	 not respond properly on the probe path.
33134b2d0dSStanislaw Gruszka 	 *	 In case anyone (PSM?) wants to use this function we can
34134b2d0dSStanislaw Gruszka 	 *	 bring the clock stuff back and fixup the probe path.
35134b2d0dSStanislaw Gruszka 	 */
36134b2d0dSStanislaw Gruszka 
37134b2d0dSStanislaw Gruszka 	if (enable)
38134b2d0dSStanislaw Gruszka 		val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
39134b2d0dSStanislaw Gruszka 			MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
40134b2d0dSStanislaw Gruszka 	else
41134b2d0dSStanislaw Gruszka 		val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN);
42134b2d0dSStanislaw Gruszka 
43134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
44134b2d0dSStanislaw Gruszka 	udelay(20);
45134b2d0dSStanislaw Gruszka 
46134b2d0dSStanislaw Gruszka 	if (!enable)
47134b2d0dSStanislaw Gruszka 		return;
48134b2d0dSStanislaw Gruszka 
49134b2d0dSStanislaw Gruszka 	for (i = 200; i; i--) {
50134b2d0dSStanislaw Gruszka 		val = mt76_rr(dev, MT_CMB_CTRL);
51134b2d0dSStanislaw Gruszka 
52134b2d0dSStanislaw Gruszka 		if (val & MT_CMB_CTRL_XTAL_RDY && val & MT_CMB_CTRL_PLL_LD)
53134b2d0dSStanislaw Gruszka 			break;
54134b2d0dSStanislaw Gruszka 
55134b2d0dSStanislaw Gruszka 		udelay(20);
56134b2d0dSStanislaw Gruszka 	}
57134b2d0dSStanislaw Gruszka 
58134b2d0dSStanislaw Gruszka 	/* Note: vendor driver tries to disable/enable wlan here and retry
59134b2d0dSStanislaw Gruszka 	 *       but the code which does it is so buggy it must have never
60134b2d0dSStanislaw Gruszka 	 *       triggered, so don't bother.
61134b2d0dSStanislaw Gruszka 	 */
62134b2d0dSStanislaw Gruszka 	if (!i)
63134b2d0dSStanislaw Gruszka 		dev_err(dev->mt76.dev, "Error: PLL and XTAL check failed!\n");
64134b2d0dSStanislaw Gruszka }
65134b2d0dSStanislaw Gruszka 
66369bbecdSStanislaw Gruszka void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, bool reset)
67134b2d0dSStanislaw Gruszka {
68134b2d0dSStanislaw Gruszka 	u32 val;
69134b2d0dSStanislaw Gruszka 
70134b2d0dSStanislaw Gruszka 	mutex_lock(&dev->hw_atomic_mutex);
71134b2d0dSStanislaw Gruszka 
72134b2d0dSStanislaw Gruszka 	val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
73134b2d0dSStanislaw Gruszka 
74134b2d0dSStanislaw Gruszka 	if (reset) {
75134b2d0dSStanislaw Gruszka 		val |= MT_WLAN_FUN_CTRL_GPIO_OUT_EN;
76134b2d0dSStanislaw Gruszka 		val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;
77134b2d0dSStanislaw Gruszka 
78134b2d0dSStanislaw Gruszka 		if (val & MT_WLAN_FUN_CTRL_WLAN_EN) {
79134b2d0dSStanislaw Gruszka 			val |= (MT_WLAN_FUN_CTRL_WLAN_RESET |
80134b2d0dSStanislaw Gruszka 				MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
81134b2d0dSStanislaw Gruszka 			mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
82134b2d0dSStanislaw Gruszka 			udelay(20);
83134b2d0dSStanislaw Gruszka 
84134b2d0dSStanislaw Gruszka 			val &= ~(MT_WLAN_FUN_CTRL_WLAN_RESET |
85134b2d0dSStanislaw Gruszka 				 MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
86134b2d0dSStanislaw Gruszka 		}
87134b2d0dSStanislaw Gruszka 	}
88134b2d0dSStanislaw Gruszka 
89134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
90134b2d0dSStanislaw Gruszka 	udelay(20);
91134b2d0dSStanislaw Gruszka 
92134b2d0dSStanislaw Gruszka 	mt76x0_set_wlan_state(dev, val, enable);
93134b2d0dSStanislaw Gruszka 
94134b2d0dSStanislaw Gruszka 	mutex_unlock(&dev->hw_atomic_mutex);
95134b2d0dSStanislaw Gruszka }
96134b2d0dSStanislaw Gruszka 
97134b2d0dSStanislaw Gruszka static void mt76x0_reset_csr_bbp(struct mt76x0_dev *dev)
98134b2d0dSStanislaw Gruszka {
99134b2d0dSStanislaw Gruszka 	u32 val;
100134b2d0dSStanislaw Gruszka 
101134b2d0dSStanislaw Gruszka 	val = mt76_rr(dev, MT_PBF_SYS_CTRL);
102134b2d0dSStanislaw Gruszka 	val &= ~0x2000;
103134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_PBF_SYS_CTRL, val);
104134b2d0dSStanislaw Gruszka 
105134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR |
106134b2d0dSStanislaw Gruszka 					 MT_MAC_SYS_CTRL_RESET_BBP);
107134b2d0dSStanislaw Gruszka 
108134b2d0dSStanislaw Gruszka 	msleep(200);
109134b2d0dSStanislaw Gruszka }
110134b2d0dSStanislaw Gruszka 
111134b2d0dSStanislaw Gruszka static void mt76x0_init_usb_dma(struct mt76x0_dev *dev)
112134b2d0dSStanislaw Gruszka {
113134b2d0dSStanislaw Gruszka 	u32 val;
114134b2d0dSStanislaw Gruszka 
115134b2d0dSStanislaw Gruszka 	val = mt76_rr(dev, MT_USB_DMA_CFG);
116134b2d0dSStanislaw Gruszka 
1177fd3c60cSLorenzo Bianconi 	val |= MT_USB_DMA_CFG_RX_BULK_EN |
118134b2d0dSStanislaw Gruszka 	       MT_USB_DMA_CFG_TX_BULK_EN;
1197fd3c60cSLorenzo Bianconi 
1207fd3c60cSLorenzo Bianconi 	/* disable AGGR_BULK_RX in order to receive one
1217fd3c60cSLorenzo Bianconi 	 * frame in each rx urb and avoid copies
1227fd3c60cSLorenzo Bianconi 	 */
1237fd3c60cSLorenzo Bianconi 	val &= ~MT_USB_DMA_CFG_RX_BULK_AGG_EN;
124134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_USB_DMA_CFG, val);
125134b2d0dSStanislaw Gruszka 
126134b2d0dSStanislaw Gruszka 	val = mt76_rr(dev, MT_COM_REG0);
127134b2d0dSStanislaw Gruszka 	if (val & 1)
128134b2d0dSStanislaw Gruszka 		dev_dbg(dev->mt76.dev, "MCU not ready\n");
129134b2d0dSStanislaw Gruszka 
130134b2d0dSStanislaw Gruszka 	val = mt76_rr(dev, MT_USB_DMA_CFG);
131134b2d0dSStanislaw Gruszka 
132797ea240SStanislaw Gruszka 	val |= MT_USB_DMA_CFG_RX_DROP_OR_PAD;
133134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_USB_DMA_CFG, val);
134797ea240SStanislaw Gruszka 	val &= ~MT_USB_DMA_CFG_RX_DROP_OR_PAD;
135134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_USB_DMA_CFG, val);
136134b2d0dSStanislaw Gruszka }
137134b2d0dSStanislaw Gruszka 
138134b2d0dSStanislaw Gruszka #define RANDOM_WRITE(dev, tab) \
139134b2d0dSStanislaw Gruszka 	mt76x0_write_reg_pairs(dev, MT_MCU_MEMMAP_WLAN, tab, ARRAY_SIZE(tab));
140134b2d0dSStanislaw Gruszka 
141134b2d0dSStanislaw Gruszka static int mt76x0_init_bbp(struct mt76x0_dev *dev)
142134b2d0dSStanislaw Gruszka {
143134b2d0dSStanislaw Gruszka 	int ret, i;
144134b2d0dSStanislaw Gruszka 
145134b2d0dSStanislaw Gruszka 	ret = mt76x0_wait_bbp_ready(dev);
146134b2d0dSStanislaw Gruszka 	if (ret)
147134b2d0dSStanislaw Gruszka 		return ret;
148134b2d0dSStanislaw Gruszka 
149134b2d0dSStanislaw Gruszka 	RANDOM_WRITE(dev, mt76x0_bbp_init_tab);
150134b2d0dSStanislaw Gruszka 
151134b2d0dSStanislaw Gruszka 	for (i = 0; i < ARRAY_SIZE(mt76x0_bbp_switch_tab); i++) {
152134b2d0dSStanislaw Gruszka 		const struct mt76x0_bbp_switch_item *item = &mt76x0_bbp_switch_tab[i];
153134b2d0dSStanislaw Gruszka 		const struct mt76_reg_pair *pair = &item->reg_pair;
154134b2d0dSStanislaw Gruszka 
155134b2d0dSStanislaw Gruszka 		if (((RF_G_BAND | RF_BW_20) & item->bw_band) == (RF_G_BAND | RF_BW_20))
156134b2d0dSStanislaw Gruszka 			mt76_wr(dev, pair->reg, pair->value);
157134b2d0dSStanislaw Gruszka 	}
158134b2d0dSStanislaw Gruszka 
159134b2d0dSStanislaw Gruszka 	RANDOM_WRITE(dev, mt76x0_dcoc_tab);
160134b2d0dSStanislaw Gruszka 
161134b2d0dSStanislaw Gruszka 	return 0;
162134b2d0dSStanislaw Gruszka }
163134b2d0dSStanislaw Gruszka 
164134b2d0dSStanislaw Gruszka static void
165134b2d0dSStanislaw Gruszka mt76_init_beacon_offsets(struct mt76x0_dev *dev)
166134b2d0dSStanislaw Gruszka {
167134b2d0dSStanislaw Gruszka 	u16 base = MT_BEACON_BASE;
168134b2d0dSStanislaw Gruszka 	u32 regs[4] = {};
169134b2d0dSStanislaw Gruszka 	int i;
170134b2d0dSStanislaw Gruszka 
171134b2d0dSStanislaw Gruszka 	for (i = 0; i < 16; i++) {
172134b2d0dSStanislaw Gruszka 		u16 addr = dev->beacon_offsets[i];
173134b2d0dSStanislaw Gruszka 
174134b2d0dSStanislaw Gruszka 		regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4));
175134b2d0dSStanislaw Gruszka 	}
176134b2d0dSStanislaw Gruszka 
177134b2d0dSStanislaw Gruszka 	for (i = 0; i < 4; i++)
178134b2d0dSStanislaw Gruszka 		mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]);
179134b2d0dSStanislaw Gruszka }
180134b2d0dSStanislaw Gruszka 
181134b2d0dSStanislaw Gruszka static void mt76x0_init_mac_registers(struct mt76x0_dev *dev)
182134b2d0dSStanislaw Gruszka {
183134b2d0dSStanislaw Gruszka 	u32 reg;
184134b2d0dSStanislaw Gruszka 
185134b2d0dSStanislaw Gruszka 	RANDOM_WRITE(dev, common_mac_reg_table);
186134b2d0dSStanislaw Gruszka 
187134b2d0dSStanislaw Gruszka 	mt76_init_beacon_offsets(dev);
188134b2d0dSStanislaw Gruszka 
189134b2d0dSStanislaw Gruszka 	/* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */
190134b2d0dSStanislaw Gruszka 	RANDOM_WRITE(dev, mt76x0_mac_reg_table);
191134b2d0dSStanislaw Gruszka 
192134b2d0dSStanislaw Gruszka 	/* Release BBP and MAC reset MAC_SYS_CTRL[1:0] = 0x0 */
193134b2d0dSStanislaw Gruszka 	reg = mt76_rr(dev, MT_MAC_SYS_CTRL);
194134b2d0dSStanislaw Gruszka 	reg &= ~0x3;
195134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_MAC_SYS_CTRL, reg);
196134b2d0dSStanislaw Gruszka 
197134b2d0dSStanislaw Gruszka 	if (is_mt7610e(dev)) {
198134b2d0dSStanislaw Gruszka 		/* Disable COEX_EN */
199134b2d0dSStanislaw Gruszka 		reg = mt76_rr(dev, MT_COEXCFG0);
200134b2d0dSStanislaw Gruszka 		reg &= 0xFFFFFFFE;
201134b2d0dSStanislaw Gruszka 		mt76_wr(dev, MT_COEXCFG0, reg);
202134b2d0dSStanislaw Gruszka 	}
203134b2d0dSStanislaw Gruszka 
204134b2d0dSStanislaw Gruszka 	/* Set 0x141C[15:12]=0xF */
205134b2d0dSStanislaw Gruszka 	reg = mt76_rr(dev, MT_EXT_CCA_CFG);
206134b2d0dSStanislaw Gruszka 	reg |= 0x0000F000;
207134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_EXT_CCA_CFG, reg);
208134b2d0dSStanislaw Gruszka 
209134b2d0dSStanislaw Gruszka 	mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
210134b2d0dSStanislaw Gruszka 
211134b2d0dSStanislaw Gruszka 	/*
212134b2d0dSStanislaw Gruszka 		TxRing 9 is for Mgmt frame.
213134b2d0dSStanislaw Gruszka 		TxRing 8 is for In-band command frame.
214134b2d0dSStanislaw Gruszka 		WMM_RG0_TXQMA: This register setting is for FCE to define the rule of TxRing 9.
215134b2d0dSStanislaw Gruszka 		WMM_RG1_TXQMA: This register setting is for FCE to define the rule of TxRing 8.
216134b2d0dSStanislaw Gruszka 	*/
217134b2d0dSStanislaw Gruszka 	reg = mt76_rr(dev, MT_WMM_CTRL);
218134b2d0dSStanislaw Gruszka 	reg &= ~0x000003FF;
219134b2d0dSStanislaw Gruszka 	reg |= 0x00000201;
220134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_WMM_CTRL, reg);
221134b2d0dSStanislaw Gruszka 
222134b2d0dSStanislaw Gruszka 	/* TODO: Probably not needed */
223134b2d0dSStanislaw Gruszka 	mt76_wr(dev, 0x7028, 0);
224134b2d0dSStanislaw Gruszka 	mt76_wr(dev, 0x7010, 0);
225134b2d0dSStanislaw Gruszka 	mt76_wr(dev, 0x7024, 0);
226134b2d0dSStanislaw Gruszka 	msleep(10);
227134b2d0dSStanislaw Gruszka }
228134b2d0dSStanislaw Gruszka 
229134b2d0dSStanislaw Gruszka static int mt76x0_init_wcid_mem(struct mt76x0_dev *dev)
230134b2d0dSStanislaw Gruszka {
231134b2d0dSStanislaw Gruszka 	u32 *vals;
232134b2d0dSStanislaw Gruszka 	int i, ret;
233134b2d0dSStanislaw Gruszka 
23436404c06SStanislaw Gruszka 	vals = kmalloc(sizeof(*vals) * MT76_N_WCIDS * 2, GFP_KERNEL);
235134b2d0dSStanislaw Gruszka 	if (!vals)
236134b2d0dSStanislaw Gruszka 		return -ENOMEM;
237134b2d0dSStanislaw Gruszka 
23836404c06SStanislaw Gruszka 	for (i = 0; i < MT76_N_WCIDS; i++)  {
239134b2d0dSStanislaw Gruszka 		vals[i * 2] = 0xffffffff;
240134b2d0dSStanislaw Gruszka 		vals[i * 2 + 1] = 0x00ffffff;
241134b2d0dSStanislaw Gruszka 	}
242134b2d0dSStanislaw Gruszka 
243134b2d0dSStanislaw Gruszka 	ret = mt76x0_burst_write_regs(dev, MT_WCID_ADDR_BASE,
24436404c06SStanislaw Gruszka 				      vals, MT76_N_WCIDS * 2);
245134b2d0dSStanislaw Gruszka 	kfree(vals);
246134b2d0dSStanislaw Gruszka 
247134b2d0dSStanislaw Gruszka 	return ret;
248134b2d0dSStanislaw Gruszka }
249134b2d0dSStanislaw Gruszka 
250134b2d0dSStanislaw Gruszka static int mt76x0_init_key_mem(struct mt76x0_dev *dev)
251134b2d0dSStanislaw Gruszka {
252134b2d0dSStanislaw Gruszka 	u32 vals[4] = {};
253134b2d0dSStanislaw Gruszka 
254134b2d0dSStanislaw Gruszka 	return mt76x0_burst_write_regs(dev, MT_SKEY_MODE_BASE_0,
255134b2d0dSStanislaw Gruszka 					vals, ARRAY_SIZE(vals));
256134b2d0dSStanislaw Gruszka }
257134b2d0dSStanislaw Gruszka 
258134b2d0dSStanislaw Gruszka static int mt76x0_init_wcid_attr_mem(struct mt76x0_dev *dev)
259134b2d0dSStanislaw Gruszka {
260134b2d0dSStanislaw Gruszka 	u32 *vals;
261134b2d0dSStanislaw Gruszka 	int i, ret;
262134b2d0dSStanislaw Gruszka 
26336404c06SStanislaw Gruszka 	vals = kmalloc(sizeof(*vals) * MT76_N_WCIDS * 2, GFP_KERNEL);
264134b2d0dSStanislaw Gruszka 	if (!vals)
265134b2d0dSStanislaw Gruszka 		return -ENOMEM;
266134b2d0dSStanislaw Gruszka 
26736404c06SStanislaw Gruszka 	for (i = 0; i < MT76_N_WCIDS * 2; i++)
268134b2d0dSStanislaw Gruszka 		vals[i] = 1;
269134b2d0dSStanislaw Gruszka 
270134b2d0dSStanislaw Gruszka 	ret = mt76x0_burst_write_regs(dev, MT_WCID_ATTR_BASE,
27136404c06SStanislaw Gruszka 				      vals, MT76_N_WCIDS * 2);
272134b2d0dSStanislaw Gruszka 	kfree(vals);
273134b2d0dSStanislaw Gruszka 
274134b2d0dSStanislaw Gruszka 	return ret;
275134b2d0dSStanislaw Gruszka }
276134b2d0dSStanislaw Gruszka 
277134b2d0dSStanislaw Gruszka static void mt76x0_reset_counters(struct mt76x0_dev *dev)
278134b2d0dSStanislaw Gruszka {
279797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_RX_STAT_0);
280797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_RX_STAT_1);
281797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_RX_STAT_2);
282797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_TX_STA_0);
283797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_TX_STA_1);
284797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_TX_STA_2);
285134b2d0dSStanislaw Gruszka }
286134b2d0dSStanislaw Gruszka 
287134b2d0dSStanislaw Gruszka int mt76x0_mac_start(struct mt76x0_dev *dev)
288134b2d0dSStanislaw Gruszka {
289134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
290134b2d0dSStanislaw Gruszka 
291134b2d0dSStanislaw Gruszka 	if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
292134b2d0dSStanislaw Gruszka 		       MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 200000))
293134b2d0dSStanislaw Gruszka 		return -ETIMEDOUT;
294134b2d0dSStanislaw Gruszka 
295108a4861SStanislaw Gruszka 	dev->mt76.rxfilter = MT_RX_FILTR_CFG_CRC_ERR |
296134b2d0dSStanislaw Gruszka 		MT_RX_FILTR_CFG_PHY_ERR | MT_RX_FILTR_CFG_PROMISC |
297134b2d0dSStanislaw Gruszka 		MT_RX_FILTR_CFG_VER_ERR | MT_RX_FILTR_CFG_DUP |
298134b2d0dSStanislaw Gruszka 		MT_RX_FILTR_CFG_CFACK | MT_RX_FILTR_CFG_CFEND |
299134b2d0dSStanislaw Gruszka 		MT_RX_FILTR_CFG_ACK | MT_RX_FILTR_CFG_CTS |
300134b2d0dSStanislaw Gruszka 		MT_RX_FILTR_CFG_RTS | MT_RX_FILTR_CFG_PSPOLL |
301134b2d0dSStanislaw Gruszka 		MT_RX_FILTR_CFG_BA | MT_RX_FILTR_CFG_CTRL_RSV;
302108a4861SStanislaw Gruszka 	mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
303134b2d0dSStanislaw Gruszka 
304134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_MAC_SYS_CTRL,
305134b2d0dSStanislaw Gruszka 		   MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
306134b2d0dSStanislaw Gruszka 
307134b2d0dSStanislaw Gruszka 	if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
308134b2d0dSStanislaw Gruszka 		       MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 50))
309134b2d0dSStanislaw Gruszka 		return -ETIMEDOUT;
310134b2d0dSStanislaw Gruszka 
311134b2d0dSStanislaw Gruszka 	return 0;
312134b2d0dSStanislaw Gruszka }
313134b2d0dSStanislaw Gruszka 
314134b2d0dSStanislaw Gruszka static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
315134b2d0dSStanislaw Gruszka {
316134b2d0dSStanislaw Gruszka 	int i, ok;
317134b2d0dSStanislaw Gruszka 
318134b2d0dSStanislaw Gruszka 	if (test_bit(MT76_REMOVED, &dev->mt76.state))
319134b2d0dSStanislaw Gruszka 		return;
320134b2d0dSStanislaw Gruszka 
321134b2d0dSStanislaw Gruszka 	mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
322134b2d0dSStanislaw Gruszka 		   MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
323134b2d0dSStanislaw Gruszka 		   MT_BEACON_TIME_CFG_BEACON_TX);
324134b2d0dSStanislaw Gruszka 
325134b2d0dSStanislaw Gruszka 	if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
326134b2d0dSStanislaw Gruszka 		dev_warn(dev->mt76.dev, "Warning: TX DMA did not stop!\n");
327134b2d0dSStanislaw Gruszka 
328134b2d0dSStanislaw Gruszka 	/* Page count on TxQ */
329134b2d0dSStanislaw Gruszka 	i = 200;
330134b2d0dSStanislaw Gruszka 	while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
331134b2d0dSStanislaw Gruszka 		       (mt76_rr(dev, 0x0a30) & 0x000000ff) ||
332134b2d0dSStanislaw Gruszka 		       (mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
333134b2d0dSStanislaw Gruszka 		msleep(10);
334134b2d0dSStanislaw Gruszka 
335134b2d0dSStanislaw Gruszka 	if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX, 0, 1000))
336134b2d0dSStanislaw Gruszka 		dev_warn(dev->mt76.dev, "Warning: MAC TX did not stop!\n");
337134b2d0dSStanislaw Gruszka 
338134b2d0dSStanislaw Gruszka 	mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX |
339134b2d0dSStanislaw Gruszka 					 MT_MAC_SYS_CTRL_ENABLE_TX);
340134b2d0dSStanislaw Gruszka 
341134b2d0dSStanislaw Gruszka 	/* Page count on RxQ */
342134b2d0dSStanislaw Gruszka 	ok = 0;
343134b2d0dSStanislaw Gruszka 	i = 200;
344134b2d0dSStanislaw Gruszka 	while (i--) {
345134b2d0dSStanislaw Gruszka 		if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
346134b2d0dSStanislaw Gruszka 		    !mt76_rr(dev, 0x0a30) &&
347134b2d0dSStanislaw Gruszka 		    !mt76_rr(dev, 0x0a34)) {
348134b2d0dSStanislaw Gruszka 			if (ok++ > 5)
349134b2d0dSStanislaw Gruszka 				break;
350134b2d0dSStanislaw Gruszka 			continue;
351134b2d0dSStanislaw Gruszka 		}
352134b2d0dSStanislaw Gruszka 		msleep(1);
353134b2d0dSStanislaw Gruszka 	}
354134b2d0dSStanislaw Gruszka 
355134b2d0dSStanislaw Gruszka 	if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000))
356134b2d0dSStanislaw Gruszka 		dev_warn(dev->mt76.dev, "Warning: MAC RX did not stop!\n");
357134b2d0dSStanislaw Gruszka 
358134b2d0dSStanislaw Gruszka 	if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
359134b2d0dSStanislaw Gruszka 		dev_warn(dev->mt76.dev, "Warning: RX DMA did not stop!\n");
360134b2d0dSStanislaw Gruszka }
361134b2d0dSStanislaw Gruszka 
362134b2d0dSStanislaw Gruszka void mt76x0_mac_stop(struct mt76x0_dev *dev)
363134b2d0dSStanislaw Gruszka {
364134b2d0dSStanislaw Gruszka 	mt76x0_mac_stop_hw(dev);
365134b2d0dSStanislaw Gruszka 	flush_delayed_work(&dev->stat_work);
366134b2d0dSStanislaw Gruszka 	cancel_delayed_work_sync(&dev->stat_work);
367134b2d0dSStanislaw Gruszka }
368134b2d0dSStanislaw Gruszka 
369134b2d0dSStanislaw Gruszka static void mt76x0_stop_hardware(struct mt76x0_dev *dev)
370134b2d0dSStanislaw Gruszka {
371134b2d0dSStanislaw Gruszka 	mt76x0_chip_onoff(dev, false, false);
372134b2d0dSStanislaw Gruszka }
373134b2d0dSStanislaw Gruszka 
374134b2d0dSStanislaw Gruszka int mt76x0_init_hardware(struct mt76x0_dev *dev)
375134b2d0dSStanislaw Gruszka {
376134b2d0dSStanislaw Gruszka 	static const u16 beacon_offsets[16] = {
377134b2d0dSStanislaw Gruszka 		/* 512 byte per beacon */
378134b2d0dSStanislaw Gruszka 		0xc000,	0xc200,	0xc400,	0xc600,
379134b2d0dSStanislaw Gruszka 		0xc800,	0xca00,	0xcc00,	0xce00,
380134b2d0dSStanislaw Gruszka 		0xd000,	0xd200,	0xd400,	0xd600,
381134b2d0dSStanislaw Gruszka 		0xd800,	0xda00,	0xdc00,	0xde00
382134b2d0dSStanislaw Gruszka 	};
383134b2d0dSStanislaw Gruszka 	int ret;
384134b2d0dSStanislaw Gruszka 
385134b2d0dSStanislaw Gruszka 	dev->beacon_offsets = beacon_offsets;
386134b2d0dSStanislaw Gruszka 
387134b2d0dSStanislaw Gruszka 	mt76x0_chip_onoff(dev, true, true);
388134b2d0dSStanislaw Gruszka 
3892735a6ddSStanislaw Gruszka 	if (!mt76x02_wait_for_mac(&dev->mt76)) {
3902735a6ddSStanislaw Gruszka 		ret = -ETIMEDOUT;
391134b2d0dSStanislaw Gruszka 		goto err;
3922735a6ddSStanislaw Gruszka 	}
3932735a6ddSStanislaw Gruszka 
394134b2d0dSStanislaw Gruszka 	ret = mt76x0_mcu_init(dev);
395134b2d0dSStanislaw Gruszka 	if (ret)
396134b2d0dSStanislaw Gruszka 		goto err;
397134b2d0dSStanislaw Gruszka 
398134b2d0dSStanislaw Gruszka 	if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG,
399134b2d0dSStanislaw Gruszka 			    MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
400134b2d0dSStanislaw Gruszka 			    MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100)) {
401134b2d0dSStanislaw Gruszka 		ret = -EIO;
402134b2d0dSStanislaw Gruszka 		goto err;
403134b2d0dSStanislaw Gruszka 	}
404134b2d0dSStanislaw Gruszka 
405134b2d0dSStanislaw Gruszka 	/* Wait for ASIC ready after FW load. */
4062735a6ddSStanislaw Gruszka 	if (!mt76x02_wait_for_mac(&dev->mt76)) {
4072735a6ddSStanislaw Gruszka 		ret = -ETIMEDOUT;
408134b2d0dSStanislaw Gruszka 		goto err;
4092735a6ddSStanislaw Gruszka 	}
410134b2d0dSStanislaw Gruszka 
411134b2d0dSStanislaw Gruszka 	mt76x0_reset_csr_bbp(dev);
412134b2d0dSStanislaw Gruszka 	mt76x0_init_usb_dma(dev);
413134b2d0dSStanislaw Gruszka 
414134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_HEADER_TRANS_CTRL_REG, 0x0);
415134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_TSO_CTRL, 0x0);
416134b2d0dSStanislaw Gruszka 
417134b2d0dSStanislaw Gruszka 	ret = mt76x0_mcu_cmd_init(dev);
418134b2d0dSStanislaw Gruszka 	if (ret)
419134b2d0dSStanislaw Gruszka 		goto err;
42030ec9152SLorenzo Bianconi 
42130ec9152SLorenzo Bianconi 	ret = mt76u_alloc_queues(&dev->mt76);
42230ec9152SLorenzo Bianconi 	if (ret < 0)
423134b2d0dSStanislaw Gruszka 		goto err_mcu;
424134b2d0dSStanislaw Gruszka 
425134b2d0dSStanislaw Gruszka 	mt76x0_init_mac_registers(dev);
426134b2d0dSStanislaw Gruszka 
427134b2d0dSStanislaw Gruszka 	if (!mt76_poll_msec(dev, MT_MAC_STATUS,
428134b2d0dSStanislaw Gruszka 			    MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 1000)) {
429134b2d0dSStanislaw Gruszka 		ret = -EIO;
430134b2d0dSStanislaw Gruszka 		goto err_rx;
431134b2d0dSStanislaw Gruszka 	}
432134b2d0dSStanislaw Gruszka 
433134b2d0dSStanislaw Gruszka 	ret = mt76x0_init_bbp(dev);
434134b2d0dSStanislaw Gruszka 	if (ret)
435134b2d0dSStanislaw Gruszka 		goto err_rx;
436134b2d0dSStanislaw Gruszka 
437134b2d0dSStanislaw Gruszka 	ret = mt76x0_init_wcid_mem(dev);
438134b2d0dSStanislaw Gruszka 	if (ret)
439134b2d0dSStanislaw Gruszka 		goto err_rx;
440134b2d0dSStanislaw Gruszka 	ret = mt76x0_init_key_mem(dev);
441134b2d0dSStanislaw Gruszka 	if (ret)
442134b2d0dSStanislaw Gruszka 		goto err_rx;
443134b2d0dSStanislaw Gruszka 	ret = mt76x0_init_wcid_attr_mem(dev);
444134b2d0dSStanislaw Gruszka 	if (ret)
445134b2d0dSStanislaw Gruszka 		goto err_rx;
446134b2d0dSStanislaw Gruszka 
447134b2d0dSStanislaw Gruszka 	mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
448134b2d0dSStanislaw Gruszka 					     MT_BEACON_TIME_CFG_SYNC_MODE |
449134b2d0dSStanislaw Gruszka 					     MT_BEACON_TIME_CFG_TBTT_EN |
450134b2d0dSStanislaw Gruszka 					     MT_BEACON_TIME_CFG_BEACON_TX));
451134b2d0dSStanislaw Gruszka 
452134b2d0dSStanislaw Gruszka 	mt76x0_reset_counters(dev);
453134b2d0dSStanislaw Gruszka 
454134b2d0dSStanislaw Gruszka 	mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
455134b2d0dSStanislaw Gruszka 
456134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_TXOP_CTRL_CFG,
457134b2d0dSStanislaw Gruszka 		   FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
458134b2d0dSStanislaw Gruszka 		   FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));
459134b2d0dSStanislaw Gruszka 
460134b2d0dSStanislaw Gruszka 	ret = mt76x0_eeprom_init(dev);
461134b2d0dSStanislaw Gruszka 	if (ret)
462134b2d0dSStanislaw Gruszka 		goto err_rx;
463134b2d0dSStanislaw Gruszka 
464134b2d0dSStanislaw Gruszka 	mt76x0_phy_init(dev);
465134b2d0dSStanislaw Gruszka 	return 0;
466134b2d0dSStanislaw Gruszka 
467134b2d0dSStanislaw Gruszka err_rx:
46830ec9152SLorenzo Bianconi 	mt76u_queues_deinit(&dev->mt76);
469134b2d0dSStanislaw Gruszka err_mcu:
4706f4796b7SLorenzo Bianconi 	mt76u_mcu_deinit(&dev->mt76);
471134b2d0dSStanislaw Gruszka err:
472134b2d0dSStanislaw Gruszka 	mt76x0_chip_onoff(dev, false, false);
473134b2d0dSStanislaw Gruszka 	return ret;
474134b2d0dSStanislaw Gruszka }
475134b2d0dSStanislaw Gruszka 
476134b2d0dSStanislaw Gruszka void mt76x0_cleanup(struct mt76x0_dev *dev)
477134b2d0dSStanislaw Gruszka {
478134b2d0dSStanislaw Gruszka 	if (!test_and_clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state))
479134b2d0dSStanislaw Gruszka 		return;
480134b2d0dSStanislaw Gruszka 
481134b2d0dSStanislaw Gruszka 	mt76x0_stop_hardware(dev);
48230ec9152SLorenzo Bianconi 	mt76u_queues_deinit(&dev->mt76);
4836f4796b7SLorenzo Bianconi 	mt76u_mcu_deinit(&dev->mt76);
484134b2d0dSStanislaw Gruszka }
485134b2d0dSStanislaw Gruszka 
486134b2d0dSStanislaw Gruszka struct mt76x0_dev *mt76x0_alloc_device(struct device *pdev)
487134b2d0dSStanislaw Gruszka {
488f2653a4eSLorenzo Bianconi 	static const struct mt76_driver_ops drv_ops = {
489f2653a4eSLorenzo Bianconi 		.tx_prepare_skb = mt76x0_tx_prepare_skb,
490f2653a4eSLorenzo Bianconi 		.tx_complete_skb = mt76x02_tx_complete_skb,
491f2653a4eSLorenzo Bianconi 		.tx_status_data = mt76x02_tx_status_data,
492f2653a4eSLorenzo Bianconi 		.rx_skb = mt76x0_queue_rx_skb,
493f2653a4eSLorenzo Bianconi 	};
494134b2d0dSStanislaw Gruszka 	struct mt76x0_dev *dev;
49595e507d2SLorenzo Bianconi 	struct mt76_dev *mdev;
496134b2d0dSStanislaw Gruszka 
49795e507d2SLorenzo Bianconi 	mdev = mt76_alloc_device(sizeof(*dev), &mt76x0_ops);
49895e507d2SLorenzo Bianconi 	if (!mdev)
499134b2d0dSStanislaw Gruszka 		return NULL;
500134b2d0dSStanislaw Gruszka 
50195e507d2SLorenzo Bianconi 	mdev->dev = pdev;
50295e507d2SLorenzo Bianconi 	mdev->drv = &drv_ops;
50395e507d2SLorenzo Bianconi 
50495e507d2SLorenzo Bianconi 	dev = container_of(mdev, struct mt76x0_dev, mt76);
505134b2d0dSStanislaw Gruszka 	mutex_init(&dev->usb_ctrl_mtx);
506134b2d0dSStanislaw Gruszka 	mutex_init(&dev->reg_atomic_mutex);
507134b2d0dSStanislaw Gruszka 	mutex_init(&dev->hw_atomic_mutex);
508134b2d0dSStanislaw Gruszka 	spin_lock_init(&dev->tx_lock);
509134b2d0dSStanislaw Gruszka 	spin_lock_init(&dev->rx_lock);
510134b2d0dSStanislaw Gruszka 	spin_lock_init(&dev->mac_lock);
511134b2d0dSStanislaw Gruszka 	spin_lock_init(&dev->con_mon_lock);
512134b2d0dSStanislaw Gruszka 	atomic_set(&dev->avg_ampdu_len, 1);
513134b2d0dSStanislaw Gruszka 	skb_queue_head_init(&dev->tx_skb_done);
514134b2d0dSStanislaw Gruszka 
515134b2d0dSStanislaw Gruszka 	dev->stat_wq = alloc_workqueue("mt76x0", WQ_UNBOUND, 0);
516134b2d0dSStanislaw Gruszka 	if (!dev->stat_wq) {
51795e507d2SLorenzo Bianconi 		ieee80211_free_hw(mdev->hw);
518134b2d0dSStanislaw Gruszka 		return NULL;
519134b2d0dSStanislaw Gruszka 	}
520134b2d0dSStanislaw Gruszka 
521134b2d0dSStanislaw Gruszka 	return dev;
522134b2d0dSStanislaw Gruszka }
523134b2d0dSStanislaw Gruszka 
524134b2d0dSStanislaw Gruszka #define CHAN2G(_idx, _freq) {			\
525134b2d0dSStanislaw Gruszka 	.band = NL80211_BAND_2GHZ,		\
526134b2d0dSStanislaw Gruszka 	.center_freq = (_freq),			\
527134b2d0dSStanislaw Gruszka 	.hw_value = (_idx),			\
528134b2d0dSStanislaw Gruszka 	.max_power = 30,			\
529134b2d0dSStanislaw Gruszka }
530134b2d0dSStanislaw Gruszka 
531134b2d0dSStanislaw Gruszka static const struct ieee80211_channel mt76_channels_2ghz[] = {
532134b2d0dSStanislaw Gruszka 	CHAN2G(1, 2412),
533134b2d0dSStanislaw Gruszka 	CHAN2G(2, 2417),
534134b2d0dSStanislaw Gruszka 	CHAN2G(3, 2422),
535134b2d0dSStanislaw Gruszka 	CHAN2G(4, 2427),
536134b2d0dSStanislaw Gruszka 	CHAN2G(5, 2432),
537134b2d0dSStanislaw Gruszka 	CHAN2G(6, 2437),
538134b2d0dSStanislaw Gruszka 	CHAN2G(7, 2442),
539134b2d0dSStanislaw Gruszka 	CHAN2G(8, 2447),
540134b2d0dSStanislaw Gruszka 	CHAN2G(9, 2452),
541134b2d0dSStanislaw Gruszka 	CHAN2G(10, 2457),
542134b2d0dSStanislaw Gruszka 	CHAN2G(11, 2462),
543134b2d0dSStanislaw Gruszka 	CHAN2G(12, 2467),
544134b2d0dSStanislaw Gruszka 	CHAN2G(13, 2472),
545134b2d0dSStanislaw Gruszka 	CHAN2G(14, 2484),
546134b2d0dSStanislaw Gruszka };
547134b2d0dSStanislaw Gruszka 
548134b2d0dSStanislaw Gruszka #define CHAN5G(_idx, _freq) {			\
549134b2d0dSStanislaw Gruszka 	.band = NL80211_BAND_5GHZ,		\
550134b2d0dSStanislaw Gruszka 	.center_freq = (_freq),			\
551134b2d0dSStanislaw Gruszka 	.hw_value = (_idx),			\
552134b2d0dSStanislaw Gruszka 	.max_power = 30,			\
553134b2d0dSStanislaw Gruszka }
554134b2d0dSStanislaw Gruszka 
555134b2d0dSStanislaw Gruszka static const struct ieee80211_channel mt76_channels_5ghz[] = {
556134b2d0dSStanislaw Gruszka 	CHAN5G(36, 5180),
557134b2d0dSStanislaw Gruszka 	CHAN5G(40, 5200),
558134b2d0dSStanislaw Gruszka 	CHAN5G(44, 5220),
559134b2d0dSStanislaw Gruszka 	CHAN5G(46, 5230),
560134b2d0dSStanislaw Gruszka 	CHAN5G(48, 5240),
561134b2d0dSStanislaw Gruszka 	CHAN5G(52, 5260),
562134b2d0dSStanislaw Gruszka 	CHAN5G(56, 5280),
563134b2d0dSStanislaw Gruszka 	CHAN5G(60, 5300),
564134b2d0dSStanislaw Gruszka 	CHAN5G(64, 5320),
565134b2d0dSStanislaw Gruszka 
566134b2d0dSStanislaw Gruszka 	CHAN5G(100, 5500),
567134b2d0dSStanislaw Gruszka 	CHAN5G(104, 5520),
568134b2d0dSStanislaw Gruszka 	CHAN5G(108, 5540),
569134b2d0dSStanislaw Gruszka 	CHAN5G(112, 5560),
570134b2d0dSStanislaw Gruszka 	CHAN5G(116, 5580),
571134b2d0dSStanislaw Gruszka 	CHAN5G(120, 5600),
572134b2d0dSStanislaw Gruszka 	CHAN5G(124, 5620),
573134b2d0dSStanislaw Gruszka 	CHAN5G(128, 5640),
574134b2d0dSStanislaw Gruszka 	CHAN5G(132, 5660),
575134b2d0dSStanislaw Gruszka 	CHAN5G(136, 5680),
576134b2d0dSStanislaw Gruszka 	CHAN5G(140, 5700),
577134b2d0dSStanislaw Gruszka };
578134b2d0dSStanislaw Gruszka 
579134b2d0dSStanislaw Gruszka #define CCK_RATE(_idx, _rate) {					\
580134b2d0dSStanislaw Gruszka 	.bitrate = _rate,					\
581134b2d0dSStanislaw Gruszka 	.flags = IEEE80211_RATE_SHORT_PREAMBLE,			\
582134b2d0dSStanislaw Gruszka 	.hw_value = (MT_PHY_TYPE_CCK << 8) | _idx,		\
583134b2d0dSStanislaw Gruszka 	.hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + _idx),	\
584134b2d0dSStanislaw Gruszka }
585134b2d0dSStanislaw Gruszka 
586134b2d0dSStanislaw Gruszka #define OFDM_RATE(_idx, _rate) {				\
587134b2d0dSStanislaw Gruszka 	.bitrate = _rate,					\
588134b2d0dSStanislaw Gruszka 	.hw_value = (MT_PHY_TYPE_OFDM << 8) | _idx,		\
589134b2d0dSStanislaw Gruszka 	.hw_value_short = (MT_PHY_TYPE_OFDM << 8) | _idx,	\
590134b2d0dSStanislaw Gruszka }
591134b2d0dSStanislaw Gruszka 
592134b2d0dSStanislaw Gruszka static struct ieee80211_rate mt76_rates[] = {
593134b2d0dSStanislaw Gruszka 	CCK_RATE(0, 10),
594134b2d0dSStanislaw Gruszka 	CCK_RATE(1, 20),
595134b2d0dSStanislaw Gruszka 	CCK_RATE(2, 55),
596134b2d0dSStanislaw Gruszka 	CCK_RATE(3, 110),
597134b2d0dSStanislaw Gruszka 	OFDM_RATE(0, 60),
598134b2d0dSStanislaw Gruszka 	OFDM_RATE(1, 90),
599134b2d0dSStanislaw Gruszka 	OFDM_RATE(2, 120),
600134b2d0dSStanislaw Gruszka 	OFDM_RATE(3, 180),
601134b2d0dSStanislaw Gruszka 	OFDM_RATE(4, 240),
602134b2d0dSStanislaw Gruszka 	OFDM_RATE(5, 360),
603134b2d0dSStanislaw Gruszka 	OFDM_RATE(6, 480),
604134b2d0dSStanislaw Gruszka 	OFDM_RATE(7, 540),
605134b2d0dSStanislaw Gruszka };
606134b2d0dSStanislaw Gruszka 
607134b2d0dSStanislaw Gruszka static int
608134b2d0dSStanislaw Gruszka mt76_init_sband(struct mt76x0_dev *dev, struct ieee80211_supported_band *sband,
609134b2d0dSStanislaw Gruszka 		const struct ieee80211_channel *chan, int n_chan,
610134b2d0dSStanislaw Gruszka 		struct ieee80211_rate *rates, int n_rates)
611134b2d0dSStanislaw Gruszka {
612134b2d0dSStanislaw Gruszka 	struct ieee80211_sta_ht_cap *ht_cap;
613134b2d0dSStanislaw Gruszka 	void *chanlist;
614134b2d0dSStanislaw Gruszka 	int size;
615134b2d0dSStanislaw Gruszka 
616134b2d0dSStanislaw Gruszka 	size = n_chan * sizeof(*chan);
617134b2d0dSStanislaw Gruszka 	chanlist = devm_kmemdup(dev->mt76.dev, chan, size, GFP_KERNEL);
618134b2d0dSStanislaw Gruszka 	if (!chanlist)
619134b2d0dSStanislaw Gruszka 		return -ENOMEM;
620134b2d0dSStanislaw Gruszka 
621134b2d0dSStanislaw Gruszka 	sband->channels = chanlist;
622134b2d0dSStanislaw Gruszka 	sband->n_channels = n_chan;
623134b2d0dSStanislaw Gruszka 	sband->bitrates = rates;
624134b2d0dSStanislaw Gruszka 	sband->n_bitrates = n_rates;
625134b2d0dSStanislaw Gruszka 
626134b2d0dSStanislaw Gruszka 	ht_cap = &sband->ht_cap;
627134b2d0dSStanislaw Gruszka 	ht_cap->ht_supported = true;
628134b2d0dSStanislaw Gruszka 	ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
629134b2d0dSStanislaw Gruszka 		      IEEE80211_HT_CAP_GRN_FLD |
630134b2d0dSStanislaw Gruszka 		      IEEE80211_HT_CAP_SGI_20 |
631134b2d0dSStanislaw Gruszka 		      IEEE80211_HT_CAP_SGI_40 |
632134b2d0dSStanislaw Gruszka 		      (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
633134b2d0dSStanislaw Gruszka 
634134b2d0dSStanislaw Gruszka 	ht_cap->mcs.rx_mask[0] = 0xff;
635134b2d0dSStanislaw Gruszka 	ht_cap->mcs.rx_mask[4] = 0x1;
636134b2d0dSStanislaw Gruszka 	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
637134b2d0dSStanislaw Gruszka 	ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
638134b2d0dSStanislaw Gruszka 	ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_2;
639134b2d0dSStanislaw Gruszka 
640134b2d0dSStanislaw Gruszka 	return 0;
641134b2d0dSStanislaw Gruszka }
642134b2d0dSStanislaw Gruszka 
643134b2d0dSStanislaw Gruszka static int
644134b2d0dSStanislaw Gruszka mt76_init_sband_2g(struct mt76x0_dev *dev)
645134b2d0dSStanislaw Gruszka {
646134b2d0dSStanislaw Gruszka 	dev->mt76.hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->mt76.sband_2g.sband;
647134b2d0dSStanislaw Gruszka 
648134b2d0dSStanislaw Gruszka 	WARN_ON(dev->ee->reg.start - 1 + dev->ee->reg.num >
649134b2d0dSStanislaw Gruszka 		ARRAY_SIZE(mt76_channels_2ghz));
650134b2d0dSStanislaw Gruszka 
651134b2d0dSStanislaw Gruszka 
652134b2d0dSStanislaw Gruszka 	return mt76_init_sband(dev, &dev->mt76.sband_2g.sband,
653134b2d0dSStanislaw Gruszka 			       mt76_channels_2ghz, ARRAY_SIZE(mt76_channels_2ghz),
654134b2d0dSStanislaw Gruszka 			       mt76_rates, ARRAY_SIZE(mt76_rates));
655134b2d0dSStanislaw Gruszka }
656134b2d0dSStanislaw Gruszka 
657134b2d0dSStanislaw Gruszka static int
658134b2d0dSStanislaw Gruszka mt76_init_sband_5g(struct mt76x0_dev *dev)
659134b2d0dSStanislaw Gruszka {
660134b2d0dSStanislaw Gruszka 	dev->mt76.hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->mt76.sband_5g.sband;
661134b2d0dSStanislaw Gruszka 
662134b2d0dSStanislaw Gruszka 	return mt76_init_sband(dev, &dev->mt76.sband_5g.sband,
663134b2d0dSStanislaw Gruszka 			       mt76_channels_5ghz, ARRAY_SIZE(mt76_channels_5ghz),
664134b2d0dSStanislaw Gruszka 			       mt76_rates + 4, ARRAY_SIZE(mt76_rates) - 4);
665134b2d0dSStanislaw Gruszka }
666134b2d0dSStanislaw Gruszka 
667134b2d0dSStanislaw Gruszka 
668134b2d0dSStanislaw Gruszka int mt76x0_register_device(struct mt76x0_dev *dev)
669134b2d0dSStanislaw Gruszka {
670134b2d0dSStanislaw Gruszka 	struct ieee80211_hw *hw = dev->mt76.hw;
671134b2d0dSStanislaw Gruszka 	struct wiphy *wiphy = hw->wiphy;
672134b2d0dSStanislaw Gruszka 	int ret;
673134b2d0dSStanislaw Gruszka 
674134b2d0dSStanislaw Gruszka 	/* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
675134b2d0dSStanislaw Gruszka 	 * entry no. 1 like it does in the vendor driver.
676134b2d0dSStanislaw Gruszka 	 */
67736404c06SStanislaw Gruszka 	dev->mt76.wcid_mask[0] |= 1;
678134b2d0dSStanislaw Gruszka 
679134b2d0dSStanislaw Gruszka 	/* init fake wcid for monitor interfaces */
68036404c06SStanislaw Gruszka 	dev->mt76.global_wcid.idx = 0xff;
68136404c06SStanislaw Gruszka 	dev->mt76.global_wcid.hw_key_idx = -1;
682134b2d0dSStanislaw Gruszka 
683134b2d0dSStanislaw Gruszka 	SET_IEEE80211_DEV(hw, dev->mt76.dev);
684134b2d0dSStanislaw Gruszka 
685134b2d0dSStanislaw Gruszka 	hw->queues = 4;
686134b2d0dSStanislaw Gruszka 	ieee80211_hw_set(hw, SIGNAL_DBM);
687134b2d0dSStanislaw Gruszka 	ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
688134b2d0dSStanislaw Gruszka 	ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES);
689134b2d0dSStanislaw Gruszka 	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
690134b2d0dSStanislaw Gruszka 	ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
691134b2d0dSStanislaw Gruszka 	hw->max_rates = 1;
692134b2d0dSStanislaw Gruszka 	hw->max_report_rates = 7;
693134b2d0dSStanislaw Gruszka 	hw->max_rate_tries = 1;
694493703aaSStanislaw Gruszka 	hw->extra_tx_headroom = sizeof(struct mt76x02_txwi) + 4 + 2;
695134b2d0dSStanislaw Gruszka 
69616c8a792SStanislaw Gruszka 	hw->sta_data_size = sizeof(struct mt76x02_sta);
69798ff26e5SStanislaw Gruszka 	hw->vif_data_size = sizeof(struct mt76x02_vif);
698134b2d0dSStanislaw Gruszka 
699134b2d0dSStanislaw Gruszka 	SET_IEEE80211_PERM_ADDR(hw, dev->macaddr);
700134b2d0dSStanislaw Gruszka 
701134b2d0dSStanislaw Gruszka 	wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
702134b2d0dSStanislaw Gruszka 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
703134b2d0dSStanislaw Gruszka 
704134b2d0dSStanislaw Gruszka 	if (dev->ee->has_2ghz) {
705134b2d0dSStanislaw Gruszka 		ret = mt76_init_sband_2g(dev);
706134b2d0dSStanislaw Gruszka 		if (ret)
707134b2d0dSStanislaw Gruszka 			return ret;
708134b2d0dSStanislaw Gruszka 	}
709134b2d0dSStanislaw Gruszka 
710134b2d0dSStanislaw Gruszka 	if (dev->ee->has_5ghz) {
711134b2d0dSStanislaw Gruszka 		ret = mt76_init_sband_5g(dev);
712134b2d0dSStanislaw Gruszka 		if (ret)
713134b2d0dSStanislaw Gruszka 			return ret;
714134b2d0dSStanislaw Gruszka 	}
715134b2d0dSStanislaw Gruszka 
716134b2d0dSStanislaw Gruszka 	dev->mt76.chandef.chan = &dev->mt76.sband_2g.sband.channels[0];
717134b2d0dSStanislaw Gruszka 
718134b2d0dSStanislaw Gruszka 	INIT_DELAYED_WORK(&dev->mac_work, mt76x0_mac_work);
719134b2d0dSStanislaw Gruszka 	INIT_DELAYED_WORK(&dev->stat_work, mt76x0_tx_stat);
720134b2d0dSStanislaw Gruszka 
721134b2d0dSStanislaw Gruszka 	ret = ieee80211_register_hw(hw);
722134b2d0dSStanislaw Gruszka 	if (ret)
723134b2d0dSStanislaw Gruszka 		return ret;
724134b2d0dSStanislaw Gruszka 
725c6687464SLorenzo Bianconi 	/* check hw sg support in order to enable AMSDU */
726c6687464SLorenzo Bianconi 	if (mt76u_check_sg(&dev->mt76))
727c6687464SLorenzo Bianconi 		hw->max_tx_fragments = MT_SG_MAX_SIZE;
728c6687464SLorenzo Bianconi 	else
729c6687464SLorenzo Bianconi 		hw->max_tx_fragments = 1;
730c6687464SLorenzo Bianconi 
731134b2d0dSStanislaw Gruszka 	mt76x0_init_debugfs(dev);
732134b2d0dSStanislaw Gruszka 
733134b2d0dSStanislaw Gruszka 	return 0;
734134b2d0dSStanislaw Gruszka }
735