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