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 "mcu.h"
20134b2d0dSStanislaw Gruszka #include "initvals.h"
21134b2d0dSStanislaw Gruszka 
221bee323aSLorenzo Bianconi static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband)
231bee323aSLorenzo Bianconi {
241bee323aSLorenzo Bianconi 	struct ieee80211_sta_vht_cap *vht_cap = &sband->vht_cap;
251bee323aSLorenzo Bianconi 	u16 mcs_map = 0;
261bee323aSLorenzo Bianconi 	int i;
271bee323aSLorenzo Bianconi 
281bee323aSLorenzo Bianconi 	vht_cap->cap &= ~IEEE80211_VHT_CAP_RXLDPC;
291bee323aSLorenzo Bianconi 	for (i = 0; i < 8; i++) {
301bee323aSLorenzo Bianconi 		if (!i)
311bee323aSLorenzo Bianconi 			mcs_map |= (IEEE80211_VHT_MCS_SUPPORT_0_7 << (i * 2));
321bee323aSLorenzo Bianconi 		else
331bee323aSLorenzo Bianconi 			mcs_map |=
341bee323aSLorenzo Bianconi 				(IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2));
351bee323aSLorenzo Bianconi 	}
361bee323aSLorenzo Bianconi 	vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
371bee323aSLorenzo Bianconi 	vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
381bee323aSLorenzo Bianconi }
391bee323aSLorenzo Bianconi 
40134b2d0dSStanislaw Gruszka static void
41b2d871c0SLorenzo Bianconi mt76x0_set_wlan_state(struct mt76x02_dev *dev, u32 val, bool enable)
42134b2d0dSStanislaw Gruszka {
435b394355SLorenzo Bianconi 	u32 mask = MT_CMB_CTRL_XTAL_RDY | MT_CMB_CTRL_PLL_LD;
44134b2d0dSStanislaw Gruszka 
45134b2d0dSStanislaw Gruszka 	/* Note: we don't turn off WLAN_CLK because that makes the device
46134b2d0dSStanislaw Gruszka 	 *	 not respond properly on the probe path.
47134b2d0dSStanislaw Gruszka 	 *	 In case anyone (PSM?) wants to use this function we can
48134b2d0dSStanislaw Gruszka 	 *	 bring the clock stuff back and fixup the probe path.
49134b2d0dSStanislaw Gruszka 	 */
50134b2d0dSStanislaw Gruszka 
51134b2d0dSStanislaw Gruszka 	if (enable)
52134b2d0dSStanislaw Gruszka 		val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
53134b2d0dSStanislaw Gruszka 			MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
54134b2d0dSStanislaw Gruszka 	else
55134b2d0dSStanislaw Gruszka 		val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN);
56134b2d0dSStanislaw Gruszka 
57134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
58134b2d0dSStanislaw Gruszka 	udelay(20);
59134b2d0dSStanislaw Gruszka 
60134b2d0dSStanislaw Gruszka 	/* Note: vendor driver tries to disable/enable wlan here and retry
61134b2d0dSStanislaw Gruszka 	 *       but the code which does it is so buggy it must have never
62134b2d0dSStanislaw Gruszka 	 *       triggered, so don't bother.
63134b2d0dSStanislaw Gruszka 	 */
645b394355SLorenzo Bianconi 	if (enable && !mt76_poll(dev, MT_CMB_CTRL, mask, mask, 2000))
655b394355SLorenzo Bianconi 		dev_err(dev->mt76.dev, "PLL and XTAL check failed\n");
66134b2d0dSStanislaw Gruszka }
67134b2d0dSStanislaw Gruszka 
68b2d871c0SLorenzo Bianconi void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset)
69134b2d0dSStanislaw Gruszka {
70134b2d0dSStanislaw Gruszka 	u32 val;
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 }
94c2a4d9fbSStanislaw Gruszka EXPORT_SYMBOL_GPL(mt76x0_chip_onoff);
95134b2d0dSStanislaw Gruszka 
96b2d871c0SLorenzo Bianconi static void mt76x0_reset_csr_bbp(struct mt76x02_dev *dev)
97134b2d0dSStanislaw Gruszka {
98512bd4b1SLorenzo Bianconi 	mt76_wr(dev, MT_MAC_SYS_CTRL,
99512bd4b1SLorenzo Bianconi 		MT_MAC_SYS_CTRL_RESET_CSR |
100134b2d0dSStanislaw Gruszka 		MT_MAC_SYS_CTRL_RESET_BBP);
101134b2d0dSStanislaw Gruszka 	msleep(200);
1022b2cb40bSLorenzo Bianconi 	mt76_clear(dev, MT_MAC_SYS_CTRL,
1032b2cb40bSLorenzo Bianconi 		   MT_MAC_SYS_CTRL_RESET_CSR |
1042b2cb40bSLorenzo Bianconi 		   MT_MAC_SYS_CTRL_RESET_BBP);
105134b2d0dSStanislaw Gruszka }
106134b2d0dSStanislaw Gruszka 
107134b2d0dSStanislaw Gruszka #define RANDOM_WRITE(dev, tab)			\
10817507157SLorenzo Bianconi 	mt76_wr_rp(dev, MT_MCU_MEMMAP_WLAN,	\
109f1638c7cSStanislaw Gruszka 		   tab, ARRAY_SIZE(tab))
110134b2d0dSStanislaw Gruszka 
111b2d871c0SLorenzo Bianconi static int mt76x0_init_bbp(struct mt76x02_dev *dev)
112134b2d0dSStanislaw Gruszka {
113134b2d0dSStanislaw Gruszka 	int ret, i;
114134b2d0dSStanislaw Gruszka 
1159c410782SLorenzo Bianconi 	ret = mt76x0_phy_wait_bbp_ready(dev);
116134b2d0dSStanislaw Gruszka 	if (ret)
117134b2d0dSStanislaw Gruszka 		return ret;
118134b2d0dSStanislaw Gruszka 
119134b2d0dSStanislaw Gruszka 	RANDOM_WRITE(dev, mt76x0_bbp_init_tab);
120134b2d0dSStanislaw Gruszka 
121134b2d0dSStanislaw Gruszka 	for (i = 0; i < ARRAY_SIZE(mt76x0_bbp_switch_tab); i++) {
122134b2d0dSStanislaw Gruszka 		const struct mt76x0_bbp_switch_item *item = &mt76x0_bbp_switch_tab[i];
123134b2d0dSStanislaw Gruszka 		const struct mt76_reg_pair *pair = &item->reg_pair;
124134b2d0dSStanislaw Gruszka 
125134b2d0dSStanislaw Gruszka 		if (((RF_G_BAND | RF_BW_20) & item->bw_band) == (RF_G_BAND | RF_BW_20))
126134b2d0dSStanislaw Gruszka 			mt76_wr(dev, pair->reg, pair->value);
127134b2d0dSStanislaw Gruszka 	}
128134b2d0dSStanislaw Gruszka 
129134b2d0dSStanislaw Gruszka 	RANDOM_WRITE(dev, mt76x0_dcoc_tab);
130134b2d0dSStanislaw Gruszka 
131134b2d0dSStanislaw Gruszka 	return 0;
132134b2d0dSStanislaw Gruszka }
133134b2d0dSStanislaw Gruszka 
134b2d871c0SLorenzo Bianconi static void mt76x0_init_mac_registers(struct mt76x02_dev *dev)
135134b2d0dSStanislaw Gruszka {
136134b2d0dSStanislaw Gruszka 	RANDOM_WRITE(dev, common_mac_reg_table);
137134b2d0dSStanislaw Gruszka 
138134b2d0dSStanislaw Gruszka 	/* Enable PBF and MAC clock SYS_CTRL[11:10] = 0x3 */
139134b2d0dSStanislaw Gruszka 	RANDOM_WRITE(dev, mt76x0_mac_reg_table);
140134b2d0dSStanislaw Gruszka 
141134b2d0dSStanislaw Gruszka 	/* Release BBP and MAC reset MAC_SYS_CTRL[1:0] = 0x0 */
14200eccdd6SLorenzo Bianconi 	mt76_clear(dev, MT_MAC_SYS_CTRL, 0x3);
143134b2d0dSStanislaw Gruszka 
144134b2d0dSStanislaw Gruszka 	/* Set 0x141C[15:12]=0xF */
14500eccdd6SLorenzo Bianconi 	mt76_set(dev, MT_EXT_CCA_CFG, 0xf000);
146134b2d0dSStanislaw Gruszka 
147134b2d0dSStanislaw Gruszka 	mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
148134b2d0dSStanislaw Gruszka 
149134b2d0dSStanislaw Gruszka 	/*
15000eccdd6SLorenzo Bianconi 	 * tx_ring 9 is for mgmt frame
15100eccdd6SLorenzo Bianconi 	 * tx_ring 8 is for in-band command frame.
15200eccdd6SLorenzo Bianconi 	 * WMM_RG0_TXQMA: this register setting is for FCE to
15300eccdd6SLorenzo Bianconi 	 *		  define the rule of tx_ring 9
15400eccdd6SLorenzo Bianconi 	 * WMM_RG1_TXQMA: this register setting is for FCE to
15500eccdd6SLorenzo Bianconi 	 *		  define the rule of tx_ring 8
156134b2d0dSStanislaw Gruszka 	 */
15700eccdd6SLorenzo Bianconi 	mt76_rmw(dev, MT_WMM_CTRL, 0x3ff, 0x201);
158134b2d0dSStanislaw Gruszka }
159134b2d0dSStanislaw Gruszka 
160b2d871c0SLorenzo Bianconi static void mt76x0_reset_counters(struct mt76x02_dev *dev)
161134b2d0dSStanislaw Gruszka {
162797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_RX_STAT_0);
163797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_RX_STAT_1);
164797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_RX_STAT_2);
165797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_TX_STA_0);
166797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_TX_STA_1);
167797ea240SStanislaw Gruszka 	mt76_rr(dev, MT_TX_STA_2);
168134b2d0dSStanislaw Gruszka }
169134b2d0dSStanislaw Gruszka 
170b2d871c0SLorenzo Bianconi int mt76x0_mac_start(struct mt76x02_dev *dev)
171134b2d0dSStanislaw Gruszka {
172134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
173134b2d0dSStanislaw Gruszka 
1743b11db26SLorenzo Bianconi 	if (!mt76x02_wait_for_wpdma(&dev->mt76, 200000))
175134b2d0dSStanislaw Gruszka 		return -ETIMEDOUT;
176134b2d0dSStanislaw Gruszka 
177108a4861SStanislaw Gruszka 	mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
178134b2d0dSStanislaw Gruszka 	mt76_wr(dev, MT_MAC_SYS_CTRL,
179134b2d0dSStanislaw Gruszka 		MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
180134b2d0dSStanislaw Gruszka 
1813b11db26SLorenzo Bianconi 	return !mt76x02_wait_for_wpdma(&dev->mt76, 50) ? -ETIMEDOUT : 0;
182134b2d0dSStanislaw Gruszka }
183b11e1969SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x0_mac_start);
184134b2d0dSStanislaw Gruszka 
185b2d871c0SLorenzo Bianconi void mt76x0_mac_stop(struct mt76x02_dev *dev)
186134b2d0dSStanislaw Gruszka {
187b11e1969SLorenzo Bianconi 	int i = 200, ok = 0;
188134b2d0dSStanislaw Gruszka 
189134b2d0dSStanislaw Gruszka 	/* Page count on TxQ */
190134b2d0dSStanislaw Gruszka 	while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
191134b2d0dSStanislaw Gruszka 		       (mt76_rr(dev, 0x0a30) & 0x000000ff) ||
192134b2d0dSStanislaw Gruszka 		       (mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
193134b2d0dSStanislaw Gruszka 		msleep(10);
194134b2d0dSStanislaw Gruszka 
195134b2d0dSStanislaw Gruszka 	if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX, 0, 1000))
196134b2d0dSStanislaw Gruszka 		dev_warn(dev->mt76.dev, "Warning: MAC TX did not stop!\n");
197134b2d0dSStanislaw Gruszka 
198134b2d0dSStanislaw Gruszka 	mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX |
199134b2d0dSStanislaw Gruszka 					 MT_MAC_SYS_CTRL_ENABLE_TX);
200134b2d0dSStanislaw Gruszka 
201134b2d0dSStanislaw Gruszka 	/* Page count on RxQ */
202b11e1969SLorenzo Bianconi 	for (i = 0; i < 200; i++) {
203134b2d0dSStanislaw Gruszka 		if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
204134b2d0dSStanislaw Gruszka 		    !mt76_rr(dev, 0x0a30) &&
205134b2d0dSStanislaw Gruszka 		    !mt76_rr(dev, 0x0a34)) {
206134b2d0dSStanislaw Gruszka 			if (ok++ > 5)
207134b2d0dSStanislaw Gruszka 				break;
208134b2d0dSStanislaw Gruszka 			continue;
209134b2d0dSStanislaw Gruszka 		}
210134b2d0dSStanislaw Gruszka 		msleep(1);
211134b2d0dSStanislaw Gruszka 	}
212134b2d0dSStanislaw Gruszka 
213134b2d0dSStanislaw Gruszka 	if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000))
214134b2d0dSStanislaw Gruszka 		dev_warn(dev->mt76.dev, "Warning: MAC RX did not stop!\n");
215134b2d0dSStanislaw Gruszka }
216c2a4d9fbSStanislaw Gruszka EXPORT_SYMBOL_GPL(mt76x0_mac_stop);
217134b2d0dSStanislaw Gruszka 
218b2d871c0SLorenzo Bianconi int mt76x0_init_hardware(struct mt76x02_dev *dev)
219134b2d0dSStanislaw Gruszka {
22048c76588SLorenzo Bianconi 	int ret, i, k;
221134b2d0dSStanislaw Gruszka 
2223b11db26SLorenzo Bianconi 	if (!mt76x02_wait_for_wpdma(&dev->mt76, 1000))
223e30a655eSLorenzo Bianconi 		return -EIO;
224134b2d0dSStanislaw Gruszka 
225134b2d0dSStanislaw Gruszka 	/* Wait for ASIC ready after FW load. */
226e30a655eSLorenzo Bianconi 	if (!mt76x02_wait_for_mac(&dev->mt76))
227e30a655eSLorenzo Bianconi 		return -ETIMEDOUT;
228134b2d0dSStanislaw Gruszka 
229134b2d0dSStanislaw Gruszka 	mt76x0_reset_csr_bbp(dev);
2303d2d61b5SStanislaw Gruszka 	ret = mt76x02_mcu_function_select(dev, Q_SELECT, 1);
231134b2d0dSStanislaw Gruszka 	if (ret)
232e30a655eSLorenzo Bianconi 		return ret;
23330ec9152SLorenzo Bianconi 
234134b2d0dSStanislaw Gruszka 	mt76x0_init_mac_registers(dev);
235134b2d0dSStanislaw Gruszka 
2363b11db26SLorenzo Bianconi 	if (!mt76x02_wait_for_txrx_idle(&dev->mt76))
237e30a655eSLorenzo Bianconi 		return -EIO;
238134b2d0dSStanislaw Gruszka 
239134b2d0dSStanislaw Gruszka 	ret = mt76x0_init_bbp(dev);
240134b2d0dSStanislaw Gruszka 	if (ret)
241e30a655eSLorenzo Bianconi 		return ret;
242134b2d0dSStanislaw Gruszka 
243a31821abSLorenzo Bianconi 	dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
244a31821abSLorenzo Bianconi 
24548c76588SLorenzo Bianconi 	for (i = 0; i < 16; i++)
24648c76588SLorenzo Bianconi 		for (k = 0; k < 4; k++)
24748c76588SLorenzo Bianconi 			mt76x02_mac_shared_key_setup(dev, i, k, NULL);
248e30a655eSLorenzo Bianconi 
24924702cdbSLorenzo Bianconi 	for (i = 0; i < 256; i++)
25024702cdbSLorenzo Bianconi 		mt76x02_mac_wcid_setup(dev, i, 0, NULL);
251134b2d0dSStanislaw Gruszka 
252134b2d0dSStanislaw Gruszka 	mt76x0_reset_counters(dev);
253134b2d0dSStanislaw Gruszka 
254134b2d0dSStanislaw Gruszka 	ret = mt76x0_eeprom_init(dev);
255134b2d0dSStanislaw Gruszka 	if (ret)
256e30a655eSLorenzo Bianconi 		return ret;
257134b2d0dSStanislaw Gruszka 
258134b2d0dSStanislaw Gruszka 	mt76x0_phy_init(dev);
259fc245983SLorenzo Bianconi 	mt76x02_init_beacon_config(dev);
260134b2d0dSStanislaw Gruszka 
261e30a655eSLorenzo Bianconi 	return 0;
262134b2d0dSStanislaw Gruszka }
263c2a4d9fbSStanislaw Gruszka EXPORT_SYMBOL_GPL(mt76x0_init_hardware);
264134b2d0dSStanislaw Gruszka 
265b2d871c0SLorenzo Bianconi struct mt76x02_dev *
266b11e1969SLorenzo Bianconi mt76x0_alloc_device(struct device *pdev,
267b11e1969SLorenzo Bianconi 		    const struct mt76_driver_ops *drv_ops,
268b11e1969SLorenzo Bianconi 		    const struct ieee80211_ops *ops)
269134b2d0dSStanislaw Gruszka {
270b2d871c0SLorenzo Bianconi 	struct mt76x02_dev *dev;
27195e507d2SLorenzo Bianconi 	struct mt76_dev *mdev;
272134b2d0dSStanislaw Gruszka 
273b11e1969SLorenzo Bianconi 	mdev = mt76_alloc_device(sizeof(*dev), ops);
27495e507d2SLorenzo Bianconi 	if (!mdev)
275134b2d0dSStanislaw Gruszka 		return NULL;
276134b2d0dSStanislaw Gruszka 
27795e507d2SLorenzo Bianconi 	mdev->dev = pdev;
278835123b7SStanislaw Gruszka 	mdev->drv = drv_ops;
27995e507d2SLorenzo Bianconi 
280b2d871c0SLorenzo Bianconi 	dev = container_of(mdev, struct mt76x02_dev, mt76);
281b2d871c0SLorenzo Bianconi 	mutex_init(&dev->phy_mutex);
282134b2d0dSStanislaw Gruszka 
283134b2d0dSStanislaw Gruszka 	return dev;
284134b2d0dSStanislaw Gruszka }
285c2a4d9fbSStanislaw Gruszka EXPORT_SYMBOL_GPL(mt76x0_alloc_device);
286134b2d0dSStanislaw Gruszka 
287b2d871c0SLorenzo Bianconi int mt76x0_register_device(struct mt76x02_dev *dev)
288134b2d0dSStanislaw Gruszka {
289134b2d0dSStanislaw Gruszka 	int ret;
290134b2d0dSStanislaw Gruszka 
2915cbace02SLorenzo Bianconi 	mt76x02_init_device(dev);
2925cbace02SLorenzo Bianconi 	ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,
2931bee323aSLorenzo Bianconi 				   ARRAY_SIZE(mt76x02_rates));
294134b2d0dSStanislaw Gruszka 	if (ret)
295134b2d0dSStanislaw Gruszka 		return ret;
296134b2d0dSStanislaw Gruszka 
2971bee323aSLorenzo Bianconi 	/* overwrite unsupported features */
2985cbace02SLorenzo Bianconi 	if (dev->mt76.cap.has_5ghz)
2991bee323aSLorenzo Bianconi 		mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband);
3001bee323aSLorenzo Bianconi 
30163f15d94SLorenzo Bianconi 	mt76x02_init_debugfs(dev);
302134b2d0dSStanislaw Gruszka 
303134b2d0dSStanislaw Gruszka 	return 0;
304134b2d0dSStanislaw Gruszka }
305c2a4d9fbSStanislaw Gruszka EXPORT_SYMBOL_GPL(mt76x0_register_device);
306