16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /*
36c92544dSBjoern A. Zeeb  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
46c92544dSBjoern A. Zeeb  */
56c92544dSBjoern A. Zeeb 
66c92544dSBjoern A. Zeeb #include <linux/delay.h>
76c92544dSBjoern A. Zeeb #include "mt76x2.h"
86c92544dSBjoern A. Zeeb #include "eeprom.h"
96c92544dSBjoern A. Zeeb #include "mcu.h"
106c92544dSBjoern A. Zeeb #include "../mt76x02_mac.h"
116c92544dSBjoern A. Zeeb 
126c92544dSBjoern A. Zeeb static void
mt76x2_mac_pbf_init(struct mt76x02_dev * dev)136c92544dSBjoern A. Zeeb mt76x2_mac_pbf_init(struct mt76x02_dev *dev)
146c92544dSBjoern A. Zeeb {
156c92544dSBjoern A. Zeeb 	u32 val;
166c92544dSBjoern A. Zeeb 
176c92544dSBjoern A. Zeeb 	val = MT_PBF_SYS_CTRL_MCU_RESET |
186c92544dSBjoern A. Zeeb 	      MT_PBF_SYS_CTRL_DMA_RESET |
196c92544dSBjoern A. Zeeb 	      MT_PBF_SYS_CTRL_MAC_RESET |
206c92544dSBjoern A. Zeeb 	      MT_PBF_SYS_CTRL_PBF_RESET |
216c92544dSBjoern A. Zeeb 	      MT_PBF_SYS_CTRL_ASY_RESET;
226c92544dSBjoern A. Zeeb 
236c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_PBF_SYS_CTRL, val);
246c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_PBF_SYS_CTRL, val);
256c92544dSBjoern A. Zeeb 
266c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_PBF_TX_MAX_PCNT, 0xefef3f1f);
276c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_PBF_RX_MAX_PCNT, 0xfebf);
286c92544dSBjoern A. Zeeb }
296c92544dSBjoern A. Zeeb 
306c92544dSBjoern A. Zeeb static void
mt76x2_fixup_xtal(struct mt76x02_dev * dev)316c92544dSBjoern A. Zeeb mt76x2_fixup_xtal(struct mt76x02_dev *dev)
326c92544dSBjoern A. Zeeb {
336c92544dSBjoern A. Zeeb 	u16 eep_val;
346c92544dSBjoern A. Zeeb 	s8 offset = 0;
356c92544dSBjoern A. Zeeb 
366c92544dSBjoern A. Zeeb 	eep_val = mt76x02_eeprom_get(dev, MT_EE_XTAL_TRIM_2);
376c92544dSBjoern A. Zeeb 
386c92544dSBjoern A. Zeeb 	offset = eep_val & 0x7f;
396c92544dSBjoern A. Zeeb 	if ((eep_val & 0xff) == 0xff)
406c92544dSBjoern A. Zeeb 		offset = 0;
416c92544dSBjoern A. Zeeb 	else if (eep_val & 0x80)
426c92544dSBjoern A. Zeeb 		offset = 0 - offset;
436c92544dSBjoern A. Zeeb 
446c92544dSBjoern A. Zeeb 	eep_val >>= 8;
456c92544dSBjoern A. Zeeb 	if (eep_val == 0x00 || eep_val == 0xff) {
466c92544dSBjoern A. Zeeb 		eep_val = mt76x02_eeprom_get(dev, MT_EE_XTAL_TRIM_1);
476c92544dSBjoern A. Zeeb 		eep_val &= 0xff;
486c92544dSBjoern A. Zeeb 
496c92544dSBjoern A. Zeeb 		if (eep_val == 0x00 || eep_val == 0xff)
506c92544dSBjoern A. Zeeb 			eep_val = 0x14;
516c92544dSBjoern A. Zeeb 	}
526c92544dSBjoern A. Zeeb 
536c92544dSBjoern A. Zeeb 	eep_val &= 0x7f;
546c92544dSBjoern A. Zeeb 	mt76_rmw_field(dev, MT_XO_CTRL5, MT_XO_CTRL5_C2_VAL, eep_val + offset);
556c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_XO_CTRL6, MT_XO_CTRL6_C2_CTRL);
566c92544dSBjoern A. Zeeb 
576c92544dSBjoern A. Zeeb 	eep_val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2);
586c92544dSBjoern A. Zeeb 	switch (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, eep_val)) {
596c92544dSBjoern A. Zeeb 	case 0:
606c92544dSBjoern A. Zeeb 		mt76_wr(dev, MT_XO_CTRL7, 0x5c1fee80);
616c92544dSBjoern A. Zeeb 		break;
626c92544dSBjoern A. Zeeb 	case 1:
636c92544dSBjoern A. Zeeb 		mt76_wr(dev, MT_XO_CTRL7, 0x5c1feed0);
646c92544dSBjoern A. Zeeb 		break;
656c92544dSBjoern A. Zeeb 	default:
666c92544dSBjoern A. Zeeb 		break;
676c92544dSBjoern A. Zeeb 	}
686c92544dSBjoern A. Zeeb }
696c92544dSBjoern A. Zeeb 
mt76x2_mac_reset(struct mt76x02_dev * dev,bool hard)706c92544dSBjoern A. Zeeb int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
716c92544dSBjoern A. Zeeb {
726c92544dSBjoern A. Zeeb 	const u8 *macaddr = dev->mphy.macaddr;
736c92544dSBjoern A. Zeeb 	u32 val;
746c92544dSBjoern A. Zeeb 	int i, k;
756c92544dSBjoern A. Zeeb 
766c92544dSBjoern A. Zeeb 	if (!mt76x02_wait_for_mac(&dev->mt76))
776c92544dSBjoern A. Zeeb 		return -ETIMEDOUT;
786c92544dSBjoern A. Zeeb 
796c92544dSBjoern A. Zeeb 	val = mt76_rr(dev, MT_WPDMA_GLO_CFG);
806c92544dSBjoern A. Zeeb 
816c92544dSBjoern A. Zeeb 	val &= ~(MT_WPDMA_GLO_CFG_TX_DMA_EN |
826c92544dSBjoern A. Zeeb 		 MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
836c92544dSBjoern A. Zeeb 		 MT_WPDMA_GLO_CFG_RX_DMA_EN |
846c92544dSBjoern A. Zeeb 		 MT_WPDMA_GLO_CFG_RX_DMA_BUSY |
856c92544dSBjoern A. Zeeb 		 MT_WPDMA_GLO_CFG_DMA_BURST_SIZE);
866c92544dSBjoern A. Zeeb 	val |= FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3);
876c92544dSBjoern A. Zeeb 
886c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_WPDMA_GLO_CFG, val);
896c92544dSBjoern A. Zeeb 
906c92544dSBjoern A. Zeeb 	mt76x2_mac_pbf_init(dev);
916c92544dSBjoern A. Zeeb 	mt76_write_mac_initvals(dev);
926c92544dSBjoern A. Zeeb 	mt76x2_fixup_xtal(dev);
936c92544dSBjoern A. Zeeb 
946c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_MAC_SYS_CTRL,
956c92544dSBjoern A. Zeeb 		   MT_MAC_SYS_CTRL_RESET_CSR |
966c92544dSBjoern A. Zeeb 		   MT_MAC_SYS_CTRL_RESET_BBP);
976c92544dSBjoern A. Zeeb 
986c92544dSBjoern A. Zeeb 	if (is_mt7612(dev))
996c92544dSBjoern A. Zeeb 		mt76_clear(dev, MT_COEXCFG0, MT_COEXCFG0_COEX_EN);
1006c92544dSBjoern A. Zeeb 
1016c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_EXT_CCA_CFG, 0x0000f000);
1026c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_TX_ALC_CFG_4, BIT(31));
1036c92544dSBjoern A. Zeeb 
1046c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_RF_BYPASS_0, 0x06000000);
1056c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_RF_SETTING_0, 0x08800000);
1066c92544dSBjoern A. Zeeb 	usleep_range(5000, 10000);
1076c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_RF_BYPASS_0, 0x00000000);
1086c92544dSBjoern A. Zeeb 
1096c92544dSBjoern A. Zeeb 	mt76_wr(dev, MT_MCU_CLOCK_CTL, 0x1401);
1106c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
1116c92544dSBjoern A. Zeeb 
1126c92544dSBjoern A. Zeeb 	mt76x02_mac_setaddr(dev, macaddr);
1136c92544dSBjoern A. Zeeb 	mt76x02e_init_beacon_config(dev);
1146c92544dSBjoern A. Zeeb 	if (!hard)
1156c92544dSBjoern A. Zeeb 		return 0;
1166c92544dSBjoern A. Zeeb 
1176c92544dSBjoern A. Zeeb 	for (i = 0; i < 256 / 32; i++)
1186c92544dSBjoern A. Zeeb 		mt76_wr(dev, MT_WCID_DROP_BASE + i * 4, 0);
1196c92544dSBjoern A. Zeeb 
1206c92544dSBjoern A. Zeeb 	for (i = 0; i < 256; i++) {
1216c92544dSBjoern A. Zeeb 		mt76x02_mac_wcid_setup(dev, i, 0, NULL);
1226c92544dSBjoern A. Zeeb 		mt76_wr(dev, MT_WCID_TX_RATE(i), 0);
1236c92544dSBjoern A. Zeeb 		mt76_wr(dev, MT_WCID_TX_RATE(i) + 4, 0);
1246c92544dSBjoern A. Zeeb 	}
1256c92544dSBjoern A. Zeeb 
1266c92544dSBjoern A. Zeeb 	for (i = 0; i < MT_MAX_VIFS; i++)
1276c92544dSBjoern A. Zeeb 		mt76x02_mac_wcid_setup(dev, MT_VIF_WCID(i), i, NULL);
1286c92544dSBjoern A. Zeeb 
1296c92544dSBjoern A. Zeeb 	for (i = 0; i < 16; i++)
1306c92544dSBjoern A. Zeeb 		for (k = 0; k < 4; k++)
1316c92544dSBjoern A. Zeeb 			mt76x02_mac_shared_key_setup(dev, i, k, NULL);
1326c92544dSBjoern A. Zeeb 
1336c92544dSBjoern A. Zeeb 	for (i = 0; i < 16; i++)
1346c92544dSBjoern A. Zeeb 		mt76_rr(dev, MT_TX_STAT_FIFO);
1356c92544dSBjoern A. Zeeb 
1366c92544dSBjoern A. Zeeb 	mt76x02_set_tx_ackto(dev);
1376c92544dSBjoern A. Zeeb 
1386c92544dSBjoern A. Zeeb 	return 0;
1396c92544dSBjoern A. Zeeb }
1406c92544dSBjoern A. Zeeb 
1416c92544dSBjoern A. Zeeb static void
mt76x2_power_on_rf_patch(struct mt76x02_dev * dev)1426c92544dSBjoern A. Zeeb mt76x2_power_on_rf_patch(struct mt76x02_dev *dev)
1436c92544dSBjoern A. Zeeb {
1446c92544dSBjoern A. Zeeb 	mt76_set(dev, 0x10130, BIT(0) | BIT(16));
1456c92544dSBjoern A. Zeeb 	udelay(1);
1466c92544dSBjoern A. Zeeb 
1476c92544dSBjoern A. Zeeb 	mt76_clear(dev, 0x1001c, 0xff);
1486c92544dSBjoern A. Zeeb 	mt76_set(dev, 0x1001c, 0x30);
1496c92544dSBjoern A. Zeeb 
1506c92544dSBjoern A. Zeeb 	mt76_wr(dev, 0x10014, 0x484f);
1516c92544dSBjoern A. Zeeb 	udelay(1);
1526c92544dSBjoern A. Zeeb 
1536c92544dSBjoern A. Zeeb 	mt76_set(dev, 0x10130, BIT(17));
1546c92544dSBjoern A. Zeeb 	udelay(125);
1556c92544dSBjoern A. Zeeb 
1566c92544dSBjoern A. Zeeb 	mt76_clear(dev, 0x10130, BIT(16));
1576c92544dSBjoern A. Zeeb 	udelay(50);
1586c92544dSBjoern A. Zeeb 
1596c92544dSBjoern A. Zeeb 	mt76_set(dev, 0x1014c, BIT(19) | BIT(20));
1606c92544dSBjoern A. Zeeb }
1616c92544dSBjoern A. Zeeb 
1626c92544dSBjoern A. Zeeb static void
mt76x2_power_on_rf(struct mt76x02_dev * dev,int unit)1636c92544dSBjoern A. Zeeb mt76x2_power_on_rf(struct mt76x02_dev *dev, int unit)
1646c92544dSBjoern A. Zeeb {
1656c92544dSBjoern A. Zeeb 	int shift = unit ? 8 : 0;
1666c92544dSBjoern A. Zeeb 
1676c92544dSBjoern A. Zeeb 	/* Enable RF BG */
1686c92544dSBjoern A. Zeeb 	mt76_set(dev, 0x10130, BIT(0) << shift);
1696c92544dSBjoern A. Zeeb 	udelay(10);
1706c92544dSBjoern A. Zeeb 
1716c92544dSBjoern A. Zeeb 	/* Enable RFDIG LDO/AFE/ABB/ADDA */
1726c92544dSBjoern A. Zeeb 	mt76_set(dev, 0x10130, (BIT(1) | BIT(3) | BIT(4) | BIT(5)) << shift);
1736c92544dSBjoern A. Zeeb 	udelay(10);
1746c92544dSBjoern A. Zeeb 
1756c92544dSBjoern A. Zeeb 	/* Switch RFDIG power to internal LDO */
1766c92544dSBjoern A. Zeeb 	mt76_clear(dev, 0x10130, BIT(2) << shift);
1776c92544dSBjoern A. Zeeb 	udelay(10);
1786c92544dSBjoern A. Zeeb 
1796c92544dSBjoern A. Zeeb 	mt76x2_power_on_rf_patch(dev);
1806c92544dSBjoern A. Zeeb 
1816c92544dSBjoern A. Zeeb 	mt76_set(dev, 0x530, 0xf);
1826c92544dSBjoern A. Zeeb }
1836c92544dSBjoern A. Zeeb 
1846c92544dSBjoern A. Zeeb static void
mt76x2_power_on(struct mt76x02_dev * dev)1856c92544dSBjoern A. Zeeb mt76x2_power_on(struct mt76x02_dev *dev)
1866c92544dSBjoern A. Zeeb {
1876c92544dSBjoern A. Zeeb 	u32 val;
1886c92544dSBjoern A. Zeeb 
1896c92544dSBjoern A. Zeeb 	/* Turn on WL MTCMOS */
1906c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_WLAN_MTC_CTRL, MT_WLAN_MTC_CTRL_MTCMOS_PWR_UP);
1916c92544dSBjoern A. Zeeb 
1926c92544dSBjoern A. Zeeb 	val = MT_WLAN_MTC_CTRL_STATE_UP |
1936c92544dSBjoern A. Zeeb 	      MT_WLAN_MTC_CTRL_PWR_ACK |
1946c92544dSBjoern A. Zeeb 	      MT_WLAN_MTC_CTRL_PWR_ACK_S;
1956c92544dSBjoern A. Zeeb 
1966c92544dSBjoern A. Zeeb 	mt76_poll(dev, MT_WLAN_MTC_CTRL, val, val, 1000);
1976c92544dSBjoern A. Zeeb 
1986c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_WLAN_MTC_CTRL, 0x7f << 16);
1996c92544dSBjoern A. Zeeb 	udelay(10);
2006c92544dSBjoern A. Zeeb 
2016c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_WLAN_MTC_CTRL, 0xf << 24);
2026c92544dSBjoern A. Zeeb 	udelay(10);
2036c92544dSBjoern A. Zeeb 
2046c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_WLAN_MTC_CTRL, 0xf << 24);
2056c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_WLAN_MTC_CTRL, 0xfff);
2066c92544dSBjoern A. Zeeb 
2076c92544dSBjoern A. Zeeb 	/* Turn on AD/DA power down */
2086c92544dSBjoern A. Zeeb 	mt76_clear(dev, 0x11204, BIT(3));
2096c92544dSBjoern A. Zeeb 
2106c92544dSBjoern A. Zeeb 	/* WLAN function enable */
2116c92544dSBjoern A. Zeeb 	mt76_set(dev, 0x10080, BIT(0));
2126c92544dSBjoern A. Zeeb 
2136c92544dSBjoern A. Zeeb 	/* Release BBP software reset */
2146c92544dSBjoern A. Zeeb 	mt76_clear(dev, 0x10064, BIT(18));
2156c92544dSBjoern A. Zeeb 
2166c92544dSBjoern A. Zeeb 	mt76x2_power_on_rf(dev, 0);
2176c92544dSBjoern A. Zeeb 	mt76x2_power_on_rf(dev, 1);
2186c92544dSBjoern A. Zeeb }
2196c92544dSBjoern A. Zeeb 
mt76x2_resume_device(struct mt76x02_dev * dev)2206c92544dSBjoern A. Zeeb int mt76x2_resume_device(struct mt76x02_dev *dev)
2216c92544dSBjoern A. Zeeb {
2226c92544dSBjoern A. Zeeb 	int err;
2236c92544dSBjoern A. Zeeb 
2246c92544dSBjoern A. Zeeb 	mt76x02_dma_disable(dev);
2256c92544dSBjoern A. Zeeb 	mt76x2_reset_wlan(dev, true);
2266c92544dSBjoern A. Zeeb 	mt76x2_power_on(dev);
2276c92544dSBjoern A. Zeeb 
2286c92544dSBjoern A. Zeeb 	err = mt76x2_mac_reset(dev, true);
2296c92544dSBjoern A. Zeeb 	if (err)
2306c92544dSBjoern A. Zeeb 		return err;
2316c92544dSBjoern A. Zeeb 
2326c92544dSBjoern A. Zeeb 	mt76x02_mac_start(dev);
2336c92544dSBjoern A. Zeeb 
2346c92544dSBjoern A. Zeeb 	return mt76x2_mcu_init(dev);
2356c92544dSBjoern A. Zeeb }
2366c92544dSBjoern A. Zeeb 
mt76x2_init_hardware(struct mt76x02_dev * dev)2376c92544dSBjoern A. Zeeb static int mt76x2_init_hardware(struct mt76x02_dev *dev)
2386c92544dSBjoern A. Zeeb {
2396c92544dSBjoern A. Zeeb 	int ret;
2406c92544dSBjoern A. Zeeb 
2416c92544dSBjoern A. Zeeb 	mt76x02_dma_disable(dev);
2426c92544dSBjoern A. Zeeb 	mt76x2_reset_wlan(dev, true);
2436c92544dSBjoern A. Zeeb 	mt76x2_power_on(dev);
2446c92544dSBjoern A. Zeeb 
2456c92544dSBjoern A. Zeeb 	ret = mt76x2_eeprom_init(dev);
2466c92544dSBjoern A. Zeeb 	if (ret)
2476c92544dSBjoern A. Zeeb 		return ret;
2486c92544dSBjoern A. Zeeb 
2496c92544dSBjoern A. Zeeb 	ret = mt76x2_mac_reset(dev, true);
2506c92544dSBjoern A. Zeeb 	if (ret)
2516c92544dSBjoern A. Zeeb 		return ret;
2526c92544dSBjoern A. Zeeb 
2536c92544dSBjoern A. Zeeb 	dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG);
2546c92544dSBjoern A. Zeeb 
2556c92544dSBjoern A. Zeeb 	ret = mt76x02_dma_init(dev);
2566c92544dSBjoern A. Zeeb 	if (ret)
2576c92544dSBjoern A. Zeeb 		return ret;
2586c92544dSBjoern A. Zeeb 
2596c92544dSBjoern A. Zeeb 	set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
2606c92544dSBjoern A. Zeeb 	mt76x02_mac_start(dev);
2616c92544dSBjoern A. Zeeb 
2626c92544dSBjoern A. Zeeb 	ret = mt76x2_mcu_init(dev);
2636c92544dSBjoern A. Zeeb 	if (ret)
2646c92544dSBjoern A. Zeeb 		return ret;
2656c92544dSBjoern A. Zeeb 
2666c92544dSBjoern A. Zeeb 	mt76x2_mac_stop(dev, false);
2676c92544dSBjoern A. Zeeb 
2686c92544dSBjoern A. Zeeb 	return 0;
2696c92544dSBjoern A. Zeeb }
2706c92544dSBjoern A. Zeeb 
mt76x2_stop_hardware(struct mt76x02_dev * dev)2716c92544dSBjoern A. Zeeb void mt76x2_stop_hardware(struct mt76x02_dev *dev)
2726c92544dSBjoern A. Zeeb {
2736c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&dev->cal_work);
2746c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&dev->mphy.mac_work);
2756c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&dev->wdt_work);
2766c92544dSBjoern A. Zeeb 	clear_bit(MT76_RESTART, &dev->mphy.state);
2776c92544dSBjoern A. Zeeb 	mt76x02_mcu_set_radio_state(dev, false);
2786c92544dSBjoern A. Zeeb 	mt76x2_mac_stop(dev, false);
2796c92544dSBjoern A. Zeeb }
2806c92544dSBjoern A. Zeeb 
mt76x2_cleanup(struct mt76x02_dev * dev)2816c92544dSBjoern A. Zeeb void mt76x2_cleanup(struct mt76x02_dev *dev)
2826c92544dSBjoern A. Zeeb {
2836c92544dSBjoern A. Zeeb 	tasklet_disable(&dev->dfs_pd.dfs_tasklet);
2846c92544dSBjoern A. Zeeb 	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
2856c92544dSBjoern A. Zeeb 	mt76x2_stop_hardware(dev);
2866c92544dSBjoern A. Zeeb 	mt76_dma_cleanup(&dev->mt76);
2876c92544dSBjoern A. Zeeb 	mt76x02_mcu_cleanup(dev);
2886c92544dSBjoern A. Zeeb }
2896c92544dSBjoern A. Zeeb 
mt76x2_register_device(struct mt76x02_dev * dev)2906c92544dSBjoern A. Zeeb int mt76x2_register_device(struct mt76x02_dev *dev)
2916c92544dSBjoern A. Zeeb {
2926c92544dSBjoern A. Zeeb 	int ret;
2936c92544dSBjoern A. Zeeb 
2946c92544dSBjoern A. Zeeb 	INIT_DELAYED_WORK(&dev->cal_work, mt76x2_phy_calibrate);
2956c92544dSBjoern A. Zeeb 	ret = mt76x02_init_device(dev);
2966c92544dSBjoern A. Zeeb 	if (ret)
2976c92544dSBjoern A. Zeeb 		return ret;
2986c92544dSBjoern A. Zeeb 
2996c92544dSBjoern A. Zeeb 	ret = mt76x2_init_hardware(dev);
3006c92544dSBjoern A. Zeeb 	if (ret)
3016c92544dSBjoern A. Zeeb 		return ret;
3026c92544dSBjoern A. Zeeb 
3036c92544dSBjoern A. Zeeb 	mt76x02_config_mac_addr_list(dev);
3046c92544dSBjoern A. Zeeb 
3056c92544dSBjoern A. Zeeb 	ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,
3066c92544dSBjoern A. Zeeb 				   ARRAY_SIZE(mt76x02_rates));
3076c92544dSBjoern A. Zeeb 	if (ret)
3086c92544dSBjoern A. Zeeb 		goto fail;
3096c92544dSBjoern A. Zeeb 
3106c92544dSBjoern A. Zeeb 	mt76x02_init_debugfs(dev);
3116c92544dSBjoern A. Zeeb 	mt76x2_init_txpower(dev, &dev->mphy.sband_2g.sband);
3126c92544dSBjoern A. Zeeb 	mt76x2_init_txpower(dev, &dev->mphy.sband_5g.sband);
3136c92544dSBjoern A. Zeeb 
3146c92544dSBjoern A. Zeeb 	return 0;
3156c92544dSBjoern A. Zeeb 
3166c92544dSBjoern A. Zeeb fail:
3176c92544dSBjoern A. Zeeb 	mt76x2_stop_hardware(dev);
3186c92544dSBjoern A. Zeeb 	return ret;
3196c92544dSBjoern A. Zeeb }
3206c92544dSBjoern A. Zeeb 
321