xref: /linux/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
10e3d6777SRyder Lee // SPDX-License-Identifier: ISC
21613c621SLorenzo Bianconi /*
31613c621SLorenzo Bianconi  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
41613c621SLorenzo Bianconi  */
51613c621SLorenzo Bianconi 
61613c621SLorenzo Bianconi #include <linux/delay.h>
71613c621SLorenzo Bianconi #include "mt76x2.h"
81613c621SLorenzo Bianconi #include "eeprom.h"
91613c621SLorenzo Bianconi #include "mcu.h"
10ad571c93SLorenzo Bianconi #include "../mt76x02_mac.h"
111613c621SLorenzo Bianconi 
121613c621SLorenzo Bianconi static void
mt76x2_mac_pbf_init(struct mt76x02_dev * dev)13e40803f2SLorenzo Bianconi mt76x2_mac_pbf_init(struct mt76x02_dev *dev)
141613c621SLorenzo Bianconi {
151613c621SLorenzo Bianconi 	u32 val;
161613c621SLorenzo Bianconi 
171613c621SLorenzo Bianconi 	val = MT_PBF_SYS_CTRL_MCU_RESET |
181613c621SLorenzo Bianconi 	      MT_PBF_SYS_CTRL_DMA_RESET |
191613c621SLorenzo Bianconi 	      MT_PBF_SYS_CTRL_MAC_RESET |
201613c621SLorenzo Bianconi 	      MT_PBF_SYS_CTRL_PBF_RESET |
211613c621SLorenzo Bianconi 	      MT_PBF_SYS_CTRL_ASY_RESET;
221613c621SLorenzo Bianconi 
231613c621SLorenzo Bianconi 	mt76_set(dev, MT_PBF_SYS_CTRL, val);
241613c621SLorenzo Bianconi 	mt76_clear(dev, MT_PBF_SYS_CTRL, val);
251613c621SLorenzo Bianconi 
261613c621SLorenzo Bianconi 	mt76_wr(dev, MT_PBF_TX_MAX_PCNT, 0xefef3f1f);
271613c621SLorenzo Bianconi 	mt76_wr(dev, MT_PBF_RX_MAX_PCNT, 0xfebf);
281613c621SLorenzo Bianconi }
291613c621SLorenzo Bianconi 
301613c621SLorenzo Bianconi static void
mt76x2_fixup_xtal(struct mt76x02_dev * dev)31e40803f2SLorenzo Bianconi mt76x2_fixup_xtal(struct mt76x02_dev *dev)
321613c621SLorenzo Bianconi {
331613c621SLorenzo Bianconi 	u16 eep_val;
341613c621SLorenzo Bianconi 	s8 offset = 0;
351613c621SLorenzo Bianconi 
3626a9daa6SLorenzo Bianconi 	eep_val = mt76x02_eeprom_get(dev, MT_EE_XTAL_TRIM_2);
371613c621SLorenzo Bianconi 
381613c621SLorenzo Bianconi 	offset = eep_val & 0x7f;
391613c621SLorenzo Bianconi 	if ((eep_val & 0xff) == 0xff)
401613c621SLorenzo Bianconi 		offset = 0;
411613c621SLorenzo Bianconi 	else if (eep_val & 0x80)
421613c621SLorenzo Bianconi 		offset = 0 - offset;
431613c621SLorenzo Bianconi 
441613c621SLorenzo Bianconi 	eep_val >>= 8;
451613c621SLorenzo Bianconi 	if (eep_val == 0x00 || eep_val == 0xff) {
4626a9daa6SLorenzo Bianconi 		eep_val = mt76x02_eeprom_get(dev, MT_EE_XTAL_TRIM_1);
471613c621SLorenzo Bianconi 		eep_val &= 0xff;
481613c621SLorenzo Bianconi 
491613c621SLorenzo Bianconi 		if (eep_val == 0x00 || eep_val == 0xff)
501613c621SLorenzo Bianconi 			eep_val = 0x14;
511613c621SLorenzo Bianconi 	}
521613c621SLorenzo Bianconi 
531613c621SLorenzo Bianconi 	eep_val &= 0x7f;
541613c621SLorenzo Bianconi 	mt76_rmw_field(dev, MT_XO_CTRL5, MT_XO_CTRL5_C2_VAL, eep_val + offset);
551613c621SLorenzo Bianconi 	mt76_set(dev, MT_XO_CTRL6, MT_XO_CTRL6_C2_CTRL);
561613c621SLorenzo Bianconi 
5726a9daa6SLorenzo Bianconi 	eep_val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2);
581613c621SLorenzo Bianconi 	switch (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, eep_val)) {
591613c621SLorenzo Bianconi 	case 0:
601613c621SLorenzo Bianconi 		mt76_wr(dev, MT_XO_CTRL7, 0x5c1fee80);
611613c621SLorenzo Bianconi 		break;
621613c621SLorenzo Bianconi 	case 1:
631613c621SLorenzo Bianconi 		mt76_wr(dev, MT_XO_CTRL7, 0x5c1feed0);
641613c621SLorenzo Bianconi 		break;
651613c621SLorenzo Bianconi 	default:
661613c621SLorenzo Bianconi 		break;
671613c621SLorenzo Bianconi 	}
681613c621SLorenzo Bianconi }
691613c621SLorenzo Bianconi 
mt76x2_mac_reset(struct mt76x02_dev * dev,bool hard)7000496042SFelix Fietkau int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
711613c621SLorenzo Bianconi {
7298df2baeSLorenzo Bianconi 	const u8 *macaddr = dev->mphy.macaddr;
731613c621SLorenzo Bianconi 	u32 val;
741613c621SLorenzo Bianconi 	int i, k;
751613c621SLorenzo Bianconi 
761613c621SLorenzo Bianconi 	if (!mt76x02_wait_for_mac(&dev->mt76))
771613c621SLorenzo Bianconi 		return -ETIMEDOUT;
781613c621SLorenzo Bianconi 
791613c621SLorenzo Bianconi 	val = mt76_rr(dev, MT_WPDMA_GLO_CFG);
801613c621SLorenzo Bianconi 
811613c621SLorenzo Bianconi 	val &= ~(MT_WPDMA_GLO_CFG_TX_DMA_EN |
821613c621SLorenzo Bianconi 		 MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
831613c621SLorenzo Bianconi 		 MT_WPDMA_GLO_CFG_RX_DMA_EN |
841613c621SLorenzo Bianconi 		 MT_WPDMA_GLO_CFG_RX_DMA_BUSY |
851613c621SLorenzo Bianconi 		 MT_WPDMA_GLO_CFG_DMA_BURST_SIZE);
861613c621SLorenzo Bianconi 	val |= FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3);
871613c621SLorenzo Bianconi 
881613c621SLorenzo Bianconi 	mt76_wr(dev, MT_WPDMA_GLO_CFG, val);
891613c621SLorenzo Bianconi 
901613c621SLorenzo Bianconi 	mt76x2_mac_pbf_init(dev);
911613c621SLorenzo Bianconi 	mt76_write_mac_initvals(dev);
921613c621SLorenzo Bianconi 	mt76x2_fixup_xtal(dev);
931613c621SLorenzo Bianconi 
941613c621SLorenzo Bianconi 	mt76_clear(dev, MT_MAC_SYS_CTRL,
951613c621SLorenzo Bianconi 		   MT_MAC_SYS_CTRL_RESET_CSR |
961613c621SLorenzo Bianconi 		   MT_MAC_SYS_CTRL_RESET_BBP);
971613c621SLorenzo Bianconi 
981613c621SLorenzo Bianconi 	if (is_mt7612(dev))
991613c621SLorenzo Bianconi 		mt76_clear(dev, MT_COEXCFG0, MT_COEXCFG0_COEX_EN);
1001613c621SLorenzo Bianconi 
1011613c621SLorenzo Bianconi 	mt76_set(dev, MT_EXT_CCA_CFG, 0x0000f000);
1021613c621SLorenzo Bianconi 	mt76_clear(dev, MT_TX_ALC_CFG_4, BIT(31));
1031613c621SLorenzo Bianconi 
1041613c621SLorenzo Bianconi 	mt76_wr(dev, MT_RF_BYPASS_0, 0x06000000);
1051613c621SLorenzo Bianconi 	mt76_wr(dev, MT_RF_SETTING_0, 0x08800000);
1061613c621SLorenzo Bianconi 	usleep_range(5000, 10000);
1071613c621SLorenzo Bianconi 	mt76_wr(dev, MT_RF_BYPASS_0, 0x00000000);
1081613c621SLorenzo Bianconi 
1091613c621SLorenzo Bianconi 	mt76_wr(dev, MT_MCU_CLOCK_CTL, 0x1401);
1101613c621SLorenzo Bianconi 	mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
1111613c621SLorenzo Bianconi 
1120b2d27e5SStanislaw Gruszka 	mt76x02_mac_setaddr(dev, macaddr);
1138d71aef9SStanislaw Gruszka 	mt76x02e_init_beacon_config(dev);
1141613c621SLorenzo Bianconi 	if (!hard)
1151613c621SLorenzo Bianconi 		return 0;
1161613c621SLorenzo Bianconi 
1171613c621SLorenzo Bianconi 	for (i = 0; i < 256 / 32; i++)
1181613c621SLorenzo Bianconi 		mt76_wr(dev, MT_WCID_DROP_BASE + i * 4, 0);
1191613c621SLorenzo Bianconi 
120544f9a53SLorenzo Bianconi 	for (i = 0; i < 256; i++) {
1218d66af49SLorenzo Bianconi 		mt76x02_mac_wcid_setup(dev, i, 0, NULL);
122544f9a53SLorenzo Bianconi 		mt76_wr(dev, MT_WCID_TX_RATE(i), 0);
123544f9a53SLorenzo Bianconi 		mt76_wr(dev, MT_WCID_TX_RATE(i) + 4, 0);
124544f9a53SLorenzo Bianconi 	}
1251613c621SLorenzo Bianconi 
1261613c621SLorenzo Bianconi 	for (i = 0; i < MT_MAX_VIFS; i++)
1278d66af49SLorenzo Bianconi 		mt76x02_mac_wcid_setup(dev, MT_VIF_WCID(i), i, NULL);
1281613c621SLorenzo Bianconi 
1291613c621SLorenzo Bianconi 	for (i = 0; i < 16; i++)
1301613c621SLorenzo Bianconi 		for (k = 0; k < 4; k++)
1318d66af49SLorenzo Bianconi 			mt76x02_mac_shared_key_setup(dev, i, k, NULL);
1321613c621SLorenzo Bianconi 
1331613c621SLorenzo Bianconi 	for (i = 0; i < 16; i++)
1341613c621SLorenzo Bianconi 		mt76_rr(dev, MT_TX_STAT_FIFO);
1351613c621SLorenzo Bianconi 
13636704051SLorenzo Bianconi 	mt76x02_set_tx_ackto(dev);
1371613c621SLorenzo Bianconi 
1381613c621SLorenzo Bianconi 	return 0;
1391613c621SLorenzo Bianconi }
1401613c621SLorenzo Bianconi 
1411613c621SLorenzo Bianconi static void
mt76x2_power_on_rf_patch(struct mt76x02_dev * dev)142e40803f2SLorenzo Bianconi mt76x2_power_on_rf_patch(struct mt76x02_dev *dev)
1431613c621SLorenzo Bianconi {
1441613c621SLorenzo Bianconi 	mt76_set(dev, 0x10130, BIT(0) | BIT(16));
1451613c621SLorenzo Bianconi 	udelay(1);
1461613c621SLorenzo Bianconi 
1471613c621SLorenzo Bianconi 	mt76_clear(dev, 0x1001c, 0xff);
1481613c621SLorenzo Bianconi 	mt76_set(dev, 0x1001c, 0x30);
1491613c621SLorenzo Bianconi 
1501613c621SLorenzo Bianconi 	mt76_wr(dev, 0x10014, 0x484f);
1511613c621SLorenzo Bianconi 	udelay(1);
1521613c621SLorenzo Bianconi 
1531613c621SLorenzo Bianconi 	mt76_set(dev, 0x10130, BIT(17));
1541613c621SLorenzo Bianconi 	udelay(125);
1551613c621SLorenzo Bianconi 
1561613c621SLorenzo Bianconi 	mt76_clear(dev, 0x10130, BIT(16));
1571613c621SLorenzo Bianconi 	udelay(50);
1581613c621SLorenzo Bianconi 
1591613c621SLorenzo Bianconi 	mt76_set(dev, 0x1014c, BIT(19) | BIT(20));
1601613c621SLorenzo Bianconi }
1611613c621SLorenzo Bianconi 
1621613c621SLorenzo Bianconi static void
mt76x2_power_on_rf(struct mt76x02_dev * dev,int unit)163e40803f2SLorenzo Bianconi mt76x2_power_on_rf(struct mt76x02_dev *dev, int unit)
1641613c621SLorenzo Bianconi {
1651613c621SLorenzo Bianconi 	int shift = unit ? 8 : 0;
1661613c621SLorenzo Bianconi 
1671613c621SLorenzo Bianconi 	/* Enable RF BG */
1681613c621SLorenzo Bianconi 	mt76_set(dev, 0x10130, BIT(0) << shift);
1691613c621SLorenzo Bianconi 	udelay(10);
1701613c621SLorenzo Bianconi 
1711613c621SLorenzo Bianconi 	/* Enable RFDIG LDO/AFE/ABB/ADDA */
1721613c621SLorenzo Bianconi 	mt76_set(dev, 0x10130, (BIT(1) | BIT(3) | BIT(4) | BIT(5)) << shift);
1731613c621SLorenzo Bianconi 	udelay(10);
1741613c621SLorenzo Bianconi 
1751613c621SLorenzo Bianconi 	/* Switch RFDIG power to internal LDO */
1761613c621SLorenzo Bianconi 	mt76_clear(dev, 0x10130, BIT(2) << shift);
1771613c621SLorenzo Bianconi 	udelay(10);
1781613c621SLorenzo Bianconi 
1791613c621SLorenzo Bianconi 	mt76x2_power_on_rf_patch(dev);
1801613c621SLorenzo Bianconi 
1811613c621SLorenzo Bianconi 	mt76_set(dev, 0x530, 0xf);
1821613c621SLorenzo Bianconi }
1831613c621SLorenzo Bianconi 
1841613c621SLorenzo Bianconi static void
mt76x2_power_on(struct mt76x02_dev * dev)185e40803f2SLorenzo Bianconi mt76x2_power_on(struct mt76x02_dev *dev)
1861613c621SLorenzo Bianconi {
1871613c621SLorenzo Bianconi 	u32 val;
1881613c621SLorenzo Bianconi 
1891613c621SLorenzo Bianconi 	/* Turn on WL MTCMOS */
1901613c621SLorenzo Bianconi 	mt76_set(dev, MT_WLAN_MTC_CTRL, MT_WLAN_MTC_CTRL_MTCMOS_PWR_UP);
1911613c621SLorenzo Bianconi 
1921613c621SLorenzo Bianconi 	val = MT_WLAN_MTC_CTRL_STATE_UP |
1931613c621SLorenzo Bianconi 	      MT_WLAN_MTC_CTRL_PWR_ACK |
1941613c621SLorenzo Bianconi 	      MT_WLAN_MTC_CTRL_PWR_ACK_S;
1951613c621SLorenzo Bianconi 
1961613c621SLorenzo Bianconi 	mt76_poll(dev, MT_WLAN_MTC_CTRL, val, val, 1000);
1971613c621SLorenzo Bianconi 
1981613c621SLorenzo Bianconi 	mt76_clear(dev, MT_WLAN_MTC_CTRL, 0x7f << 16);
1991613c621SLorenzo Bianconi 	udelay(10);
2001613c621SLorenzo Bianconi 
2011613c621SLorenzo Bianconi 	mt76_clear(dev, MT_WLAN_MTC_CTRL, 0xf << 24);
2021613c621SLorenzo Bianconi 	udelay(10);
2031613c621SLorenzo Bianconi 
2041613c621SLorenzo Bianconi 	mt76_set(dev, MT_WLAN_MTC_CTRL, 0xf << 24);
2051613c621SLorenzo Bianconi 	mt76_clear(dev, MT_WLAN_MTC_CTRL, 0xfff);
2061613c621SLorenzo Bianconi 
2071613c621SLorenzo Bianconi 	/* Turn on AD/DA power down */
2081613c621SLorenzo Bianconi 	mt76_clear(dev, 0x11204, BIT(3));
2091613c621SLorenzo Bianconi 
2101613c621SLorenzo Bianconi 	/* WLAN function enable */
2111613c621SLorenzo Bianconi 	mt76_set(dev, 0x10080, BIT(0));
2121613c621SLorenzo Bianconi 
2131613c621SLorenzo Bianconi 	/* Release BBP software reset */
2141613c621SLorenzo Bianconi 	mt76_clear(dev, 0x10064, BIT(18));
2151613c621SLorenzo Bianconi 
2161613c621SLorenzo Bianconi 	mt76x2_power_on_rf(dev, 0);
2171613c621SLorenzo Bianconi 	mt76x2_power_on_rf(dev, 1);
2181613c621SLorenzo Bianconi }
2191613c621SLorenzo Bianconi 
mt76x2_resume_device(struct mt76x02_dev * dev)22040ba9a93SLorenzo Bianconi int mt76x2_resume_device(struct mt76x02_dev *dev)
22140ba9a93SLorenzo Bianconi {
22240ba9a93SLorenzo Bianconi 	int err;
22340ba9a93SLorenzo Bianconi 
22440ba9a93SLorenzo Bianconi 	mt76x02_dma_disable(dev);
22540ba9a93SLorenzo Bianconi 	mt76x2_reset_wlan(dev, true);
22640ba9a93SLorenzo Bianconi 	mt76x2_power_on(dev);
22740ba9a93SLorenzo Bianconi 
22840ba9a93SLorenzo Bianconi 	err = mt76x2_mac_reset(dev, true);
22940ba9a93SLorenzo Bianconi 	if (err)
23040ba9a93SLorenzo Bianconi 		return err;
23140ba9a93SLorenzo Bianconi 
23240ba9a93SLorenzo Bianconi 	mt76x02_mac_start(dev);
23340ba9a93SLorenzo Bianconi 
23440ba9a93SLorenzo Bianconi 	return mt76x2_mcu_init(dev);
23540ba9a93SLorenzo Bianconi }
23640ba9a93SLorenzo Bianconi 
mt76x2_init_hardware(struct mt76x02_dev * dev)237bf349ce1SLorenzo Bianconi static int mt76x2_init_hardware(struct mt76x02_dev *dev)
2381613c621SLorenzo Bianconi {
2391613c621SLorenzo Bianconi 	int ret;
2401613c621SLorenzo Bianconi 
241a23fde09SLorenzo Bianconi 	mt76x02_dma_disable(dev);
2421613c621SLorenzo Bianconi 	mt76x2_reset_wlan(dev, true);
2431613c621SLorenzo Bianconi 	mt76x2_power_on(dev);
2441613c621SLorenzo Bianconi 
2451613c621SLorenzo Bianconi 	ret = mt76x2_eeprom_init(dev);
2461613c621SLorenzo Bianconi 	if (ret)
2471613c621SLorenzo Bianconi 		return ret;
2481613c621SLorenzo Bianconi 
2491613c621SLorenzo Bianconi 	ret = mt76x2_mac_reset(dev, true);
2501613c621SLorenzo Bianconi 	if (ret)
2511613c621SLorenzo Bianconi 		return ret;
2521613c621SLorenzo Bianconi 
2531613c621SLorenzo Bianconi 	dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
2541613c621SLorenzo Bianconi 
255a23fde09SLorenzo Bianconi 	ret = mt76x02_dma_init(dev);
2561613c621SLorenzo Bianconi 	if (ret)
2571613c621SLorenzo Bianconi 		return ret;
2581613c621SLorenzo Bianconi 
259011849e0SFelix Fietkau 	set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
260ad571c93SLorenzo Bianconi 	mt76x02_mac_start(dev);
2611613c621SLorenzo Bianconi 
2621613c621SLorenzo Bianconi 	ret = mt76x2_mcu_init(dev);
2631613c621SLorenzo Bianconi 	if (ret)
2641613c621SLorenzo Bianconi 		return ret;
2651613c621SLorenzo Bianconi 
2661613c621SLorenzo Bianconi 	mt76x2_mac_stop(dev, false);
2671613c621SLorenzo Bianconi 
2681613c621SLorenzo Bianconi 	return 0;
2691613c621SLorenzo Bianconi }
2701613c621SLorenzo Bianconi 
mt76x2_stop_hardware(struct mt76x02_dev * dev)271e40803f2SLorenzo Bianconi void mt76x2_stop_hardware(struct mt76x02_dev *dev)
2721613c621SLorenzo Bianconi {
2731613c621SLorenzo Bianconi 	cancel_delayed_work_sync(&dev->cal_work);
274a782f8bfSLorenzo Bianconi 	cancel_delayed_work_sync(&dev->mphy.mac_work);
275c1e0d2beSLorenzo Bianconi 	cancel_delayed_work_sync(&dev->wdt_work);
276fd6c2dfaSFelix Fietkau 	clear_bit(MT76_RESTART, &dev->mphy.state);
277c6950536SStanislaw Gruszka 	mt76x02_mcu_set_radio_state(dev, false);
2781613c621SLorenzo Bianconi 	mt76x2_mac_stop(dev, false);
2791613c621SLorenzo Bianconi }
2801613c621SLorenzo Bianconi 
mt76x2_cleanup(struct mt76x02_dev * dev)281e40803f2SLorenzo Bianconi void mt76x2_cleanup(struct mt76x02_dev *dev)
2821613c621SLorenzo Bianconi {
2831613c621SLorenzo Bianconi 	tasklet_disable(&dev->dfs_pd.dfs_tasklet);
284dc6057f4SLorenzo Bianconi 	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
2851613c621SLorenzo Bianconi 	mt76x2_stop_hardware(dev);
286781eef5bSFelix Fietkau 	mt76_dma_cleanup(&dev->mt76);
287499cd0aaSLorenzo Bianconi 	mt76x02_mcu_cleanup(dev);
2881613c621SLorenzo Bianconi }
2891613c621SLorenzo Bianconi 
mt76x2_register_device(struct mt76x02_dev * dev)290e40803f2SLorenzo Bianconi int mt76x2_register_device(struct mt76x02_dev *dev)
2911613c621SLorenzo Bianconi {
292269906acSLorenzo Bianconi 	int ret;
2931613c621SLorenzo Bianconi 
2941613c621SLorenzo Bianconi 	INIT_DELAYED_WORK(&dev->cal_work, mt76x2_phy_calibrate);
295*633f77b5SLorenzo Bianconi 	ret = mt76x02_init_device(dev);
296*633f77b5SLorenzo Bianconi 	if (ret)
297*633f77b5SLorenzo Bianconi 		return ret;
2981613c621SLorenzo Bianconi 
2991613c621SLorenzo Bianconi 	ret = mt76x2_init_hardware(dev);
3001613c621SLorenzo Bianconi 	if (ret)
3011613c621SLorenzo Bianconi 		return ret;
3021613c621SLorenzo Bianconi 
303269906acSLorenzo Bianconi 	mt76x02_config_mac_addr_list(dev);
3041613c621SLorenzo Bianconi 
3051613c621SLorenzo Bianconi 	ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,
3061613c621SLorenzo Bianconi 				   ARRAY_SIZE(mt76x02_rates));
3071613c621SLorenzo Bianconi 	if (ret)
3081613c621SLorenzo Bianconi 		goto fail;
3091613c621SLorenzo Bianconi 
31076055413SLorenzo Bianconi 	mt76x02_init_debugfs(dev);
31196747a51SFelix Fietkau 	mt76x2_init_txpower(dev, &dev->mphy.sband_2g.sband);
31296747a51SFelix Fietkau 	mt76x2_init_txpower(dev, &dev->mphy.sband_5g.sband);
3131613c621SLorenzo Bianconi 
3141613c621SLorenzo Bianconi 	return 0;
3151613c621SLorenzo Bianconi 
3161613c621SLorenzo Bianconi fail:
3171613c621SLorenzo Bianconi 	mt76x2_stop_hardware(dev);
3181613c621SLorenzo Bianconi 	return ret;
3191613c621SLorenzo Bianconi }
3201613c621SLorenzo Bianconi 
321