18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * (c) Copyright 2002-2010, Ralink Technology, Inc.
48c2ecf20Sopenharmony_ci * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "mt7601u.h"
98c2ecf20Sopenharmony_ci#include "eeprom.h"
108c2ecf20Sopenharmony_ci#include "trace.h"
118c2ecf20Sopenharmony_ci#include "mcu.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "initvals.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic void
168c2ecf20Sopenharmony_cimt7601u_set_wlan_state(struct mt7601u_dev *dev, u32 val, bool enable)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	int i;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	/* Note: we don't turn off WLAN_CLK because that makes the device
218c2ecf20Sopenharmony_ci	 *	 not respond properly on the probe path.
228c2ecf20Sopenharmony_ci	 *	 In case anyone (PSM?) wants to use this function we can
238c2ecf20Sopenharmony_ci	 *	 bring the clock stuff back and fixup the probe path.
248c2ecf20Sopenharmony_ci	 */
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	if (enable)
278c2ecf20Sopenharmony_ci		val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
288c2ecf20Sopenharmony_ci			MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
298c2ecf20Sopenharmony_ci	else
308c2ecf20Sopenharmony_ci		val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_WLAN_FUN_CTRL, val);
338c2ecf20Sopenharmony_ci	udelay(20);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	if (enable) {
368c2ecf20Sopenharmony_ci		set_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state);
378c2ecf20Sopenharmony_ci	} else {
388c2ecf20Sopenharmony_ci		clear_bit(MT7601U_STATE_WLAN_RUNNING, &dev->state);
398c2ecf20Sopenharmony_ci		return;
408c2ecf20Sopenharmony_ci	}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	for (i = 200; i; i--) {
438c2ecf20Sopenharmony_ci		val = mt7601u_rr(dev, MT_CMB_CTRL);
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci		if (val & MT_CMB_CTRL_XTAL_RDY && val & MT_CMB_CTRL_PLL_LD)
468c2ecf20Sopenharmony_ci			break;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci		udelay(20);
498c2ecf20Sopenharmony_ci	}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	/* Note: vendor driver tries to disable/enable wlan here and retry
528c2ecf20Sopenharmony_ci	 *       but the code which does it is so buggy it must have never
538c2ecf20Sopenharmony_ci	 *       triggered, so don't bother.
548c2ecf20Sopenharmony_ci	 */
558c2ecf20Sopenharmony_ci	if (!i)
568c2ecf20Sopenharmony_ci		dev_err(dev->dev, "Error: PLL and XTAL check failed!\n");
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic void mt7601u_chip_onoff(struct mt7601u_dev *dev, bool enable, bool reset)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	u32 val;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	mutex_lock(&dev->hw_atomic_mutex);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	val = mt7601u_rr(dev, MT_WLAN_FUN_CTRL);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	if (reset) {
688c2ecf20Sopenharmony_ci		val |= MT_WLAN_FUN_CTRL_GPIO_OUT_EN;
698c2ecf20Sopenharmony_ci		val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci		if (val & MT_WLAN_FUN_CTRL_WLAN_EN) {
728c2ecf20Sopenharmony_ci			val |= (MT_WLAN_FUN_CTRL_WLAN_RESET |
738c2ecf20Sopenharmony_ci				MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
748c2ecf20Sopenharmony_ci			mt7601u_wr(dev, MT_WLAN_FUN_CTRL, val);
758c2ecf20Sopenharmony_ci			udelay(20);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci			val &= ~(MT_WLAN_FUN_CTRL_WLAN_RESET |
788c2ecf20Sopenharmony_ci				 MT_WLAN_FUN_CTRL_WLAN_RESET_RF);
798c2ecf20Sopenharmony_ci		}
808c2ecf20Sopenharmony_ci	}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_WLAN_FUN_CTRL, val);
838c2ecf20Sopenharmony_ci	udelay(20);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	mt7601u_set_wlan_state(dev, val, enable);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	mutex_unlock(&dev->hw_atomic_mutex);
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistatic void mt7601u_reset_csr_bbp(struct mt7601u_dev *dev)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_MAC_SYS_CTRL, (MT_MAC_SYS_CTRL_RESET_CSR |
938c2ecf20Sopenharmony_ci					  MT_MAC_SYS_CTRL_RESET_BBP));
948c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_USB_DMA_CFG, 0);
958c2ecf20Sopenharmony_ci	msleep(1);
968c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_MAC_SYS_CTRL, 0);
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic void mt7601u_init_usb_dma(struct mt7601u_dev *dev)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	u32 val;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	val = FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, MT_USB_AGGR_TIMEOUT) |
1048c2ecf20Sopenharmony_ci	      FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_LMT,
1058c2ecf20Sopenharmony_ci			 MT_USB_AGGR_SIZE_LIMIT) |
1068c2ecf20Sopenharmony_ci	      MT_USB_DMA_CFG_RX_BULK_EN |
1078c2ecf20Sopenharmony_ci	      MT_USB_DMA_CFG_TX_BULK_EN;
1088c2ecf20Sopenharmony_ci	if (dev->in_max_packet == 512)
1098c2ecf20Sopenharmony_ci		val |= MT_USB_DMA_CFG_RX_BULK_AGG_EN;
1108c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_USB_DMA_CFG, val);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	val |= MT_USB_DMA_CFG_UDMA_RX_WL_DROP;
1138c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_USB_DMA_CFG, val);
1148c2ecf20Sopenharmony_ci	val &= ~MT_USB_DMA_CFG_UDMA_RX_WL_DROP;
1158c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_USB_DMA_CFG, val);
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic int mt7601u_init_bbp(struct mt7601u_dev *dev)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	int ret;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	ret = mt7601u_wait_bbp_ready(dev);
1238c2ecf20Sopenharmony_ci	if (ret)
1248c2ecf20Sopenharmony_ci		return ret;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP, bbp_common_vals,
1278c2ecf20Sopenharmony_ci				      ARRAY_SIZE(bbp_common_vals));
1288c2ecf20Sopenharmony_ci	if (ret)
1298c2ecf20Sopenharmony_ci		return ret;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	return mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_BBP, bbp_chip_vals,
1328c2ecf20Sopenharmony_ci				       ARRAY_SIZE(bbp_chip_vals));
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic void
1368c2ecf20Sopenharmony_cimt76_init_beacon_offsets(struct mt7601u_dev *dev)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	u16 base = MT_BEACON_BASE;
1398c2ecf20Sopenharmony_ci	u32 regs[4] = {};
1408c2ecf20Sopenharmony_ci	int i;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	for (i = 0; i < 16; i++) {
1438c2ecf20Sopenharmony_ci		u16 addr = dev->beacon_offsets[i];
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci		regs[i / 4] |= ((addr - base) / 64) << (8 * (i % 4));
1468c2ecf20Sopenharmony_ci	}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++)
1498c2ecf20Sopenharmony_ci		mt7601u_wr(dev, MT_BCN_OFFSET(i), regs[i]);
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic int mt7601u_write_mac_initvals(struct mt7601u_dev *dev)
1538c2ecf20Sopenharmony_ci{
1548c2ecf20Sopenharmony_ci	int ret;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_WLAN, mac_common_vals,
1578c2ecf20Sopenharmony_ci				      ARRAY_SIZE(mac_common_vals));
1588c2ecf20Sopenharmony_ci	if (ret)
1598c2ecf20Sopenharmony_ci		return ret;
1608c2ecf20Sopenharmony_ci	ret = mt7601u_write_reg_pairs(dev, MT_MCU_MEMMAP_WLAN,
1618c2ecf20Sopenharmony_ci				      mac_chip_vals, ARRAY_SIZE(mac_chip_vals));
1628c2ecf20Sopenharmony_ci	if (ret)
1638c2ecf20Sopenharmony_ci		return ret;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	mt76_init_beacon_offsets(dev);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_AUX_CLK_CFG, 0);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	return 0;
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic int mt7601u_init_wcid_mem(struct mt7601u_dev *dev)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	u32 *vals;
1758c2ecf20Sopenharmony_ci	int i, ret;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	vals = kmalloc(sizeof(*vals) * N_WCIDS * 2, GFP_KERNEL);
1788c2ecf20Sopenharmony_ci	if (!vals)
1798c2ecf20Sopenharmony_ci		return -ENOMEM;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	for (i = 0; i < N_WCIDS; i++)  {
1828c2ecf20Sopenharmony_ci		vals[i * 2] = 0xffffffff;
1838c2ecf20Sopenharmony_ci		vals[i * 2 + 1] = 0x00ffffff;
1848c2ecf20Sopenharmony_ci	}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	ret = mt7601u_burst_write_regs(dev, MT_WCID_ADDR_BASE,
1878c2ecf20Sopenharmony_ci				       vals, N_WCIDS * 2);
1888c2ecf20Sopenharmony_ci	kfree(vals);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	return ret;
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic int mt7601u_init_key_mem(struct mt7601u_dev *dev)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	u32 vals[4] = {};
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	return mt7601u_burst_write_regs(dev, MT_SKEY_MODE_BASE_0,
1988c2ecf20Sopenharmony_ci					vals, ARRAY_SIZE(vals));
1998c2ecf20Sopenharmony_ci}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_cistatic int mt7601u_init_wcid_attr_mem(struct mt7601u_dev *dev)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	u32 *vals;
2048c2ecf20Sopenharmony_ci	int i, ret;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	vals = kmalloc(sizeof(*vals) * N_WCIDS * 2, GFP_KERNEL);
2078c2ecf20Sopenharmony_ci	if (!vals)
2088c2ecf20Sopenharmony_ci		return -ENOMEM;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	for (i = 0; i < N_WCIDS * 2; i++)
2118c2ecf20Sopenharmony_ci		vals[i] = 1;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	ret = mt7601u_burst_write_regs(dev, MT_WCID_ATTR_BASE,
2148c2ecf20Sopenharmony_ci				       vals, N_WCIDS * 2);
2158c2ecf20Sopenharmony_ci	kfree(vals);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	return ret;
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic void mt7601u_reset_counters(struct mt7601u_dev *dev)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	mt7601u_rr(dev, MT_RX_STA_CNT0);
2238c2ecf20Sopenharmony_ci	mt7601u_rr(dev, MT_RX_STA_CNT1);
2248c2ecf20Sopenharmony_ci	mt7601u_rr(dev, MT_RX_STA_CNT2);
2258c2ecf20Sopenharmony_ci	mt7601u_rr(dev, MT_TX_STA_CNT0);
2268c2ecf20Sopenharmony_ci	mt7601u_rr(dev, MT_TX_STA_CNT1);
2278c2ecf20Sopenharmony_ci	mt7601u_rr(dev, MT_TX_STA_CNT2);
2288c2ecf20Sopenharmony_ci}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ciint mt7601u_mac_start(struct mt7601u_dev *dev)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
2358c2ecf20Sopenharmony_ci		       MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 200000))
2368c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	dev->rxfilter = MT_RX_FILTR_CFG_CRC_ERR |
2398c2ecf20Sopenharmony_ci		MT_RX_FILTR_CFG_PHY_ERR | MT_RX_FILTR_CFG_PROMISC |
2408c2ecf20Sopenharmony_ci		MT_RX_FILTR_CFG_VER_ERR | MT_RX_FILTR_CFG_DUP |
2418c2ecf20Sopenharmony_ci		MT_RX_FILTR_CFG_CFACK | MT_RX_FILTR_CFG_CFEND |
2428c2ecf20Sopenharmony_ci		MT_RX_FILTR_CFG_ACK | MT_RX_FILTR_CFG_CTS |
2438c2ecf20Sopenharmony_ci		MT_RX_FILTR_CFG_RTS | MT_RX_FILTR_CFG_PSPOLL |
2448c2ecf20Sopenharmony_ci		MT_RX_FILTR_CFG_BA | MT_RX_FILTR_CFG_CTRL_RSV;
2458c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_MAC_SYS_CTRL,
2488c2ecf20Sopenharmony_ci		   MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
2518c2ecf20Sopenharmony_ci		       MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 50))
2528c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	return 0;
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic void mt7601u_mac_stop_hw(struct mt7601u_dev *dev)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	int i, ok;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	if (test_bit(MT7601U_STATE_REMOVED, &dev->state))
2628c2ecf20Sopenharmony_ci		return;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
2658c2ecf20Sopenharmony_ci		   MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
2668c2ecf20Sopenharmony_ci		   MT_BEACON_TIME_CFG_BEACON_TX);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
2698c2ecf20Sopenharmony_ci		dev_warn(dev->dev, "Warning: TX DMA did not stop!\n");
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	/* Page count on TxQ */
2728c2ecf20Sopenharmony_ci	i = 200;
2738c2ecf20Sopenharmony_ci	while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) ||
2748c2ecf20Sopenharmony_ci		       (mt76_rr(dev, 0x0a30) & 0x000000ff) ||
2758c2ecf20Sopenharmony_ci		       (mt76_rr(dev, 0x0a34) & 0x00ff00ff)))
2768c2ecf20Sopenharmony_ci		msleep(10);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX, 0, 1000))
2798c2ecf20Sopenharmony_ci		dev_warn(dev->dev, "Warning: MAC TX did not stop!\n");
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX |
2828c2ecf20Sopenharmony_ci					 MT_MAC_SYS_CTRL_ENABLE_TX);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	/* Page count on RxQ */
2858c2ecf20Sopenharmony_ci	ok = 0;
2868c2ecf20Sopenharmony_ci	i = 200;
2878c2ecf20Sopenharmony_ci	while (i--) {
2888c2ecf20Sopenharmony_ci		if (!(mt76_rr(dev, MT_RXQ_STA) & 0x00ff0000) &&
2898c2ecf20Sopenharmony_ci		    !mt76_rr(dev, 0x0a30) &&
2908c2ecf20Sopenharmony_ci		    !mt76_rr(dev, 0x0a34)) {
2918c2ecf20Sopenharmony_ci			if (ok++ > 5)
2928c2ecf20Sopenharmony_ci				break;
2938c2ecf20Sopenharmony_ci			continue;
2948c2ecf20Sopenharmony_ci		}
2958c2ecf20Sopenharmony_ci		msleep(1);
2968c2ecf20Sopenharmony_ci	}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000))
2998c2ecf20Sopenharmony_ci		dev_warn(dev->dev, "Warning: MAC RX did not stop!\n");
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000))
3028c2ecf20Sopenharmony_ci		dev_warn(dev->dev, "Warning: RX DMA did not stop!\n");
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_civoid mt7601u_mac_stop(struct mt7601u_dev *dev)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	mt7601u_mac_stop_hw(dev);
3088c2ecf20Sopenharmony_ci	flush_delayed_work(&dev->stat_work);
3098c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&dev->stat_work);
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic void mt7601u_stop_hardware(struct mt7601u_dev *dev)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	mt7601u_chip_onoff(dev, false, false);
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ciint mt7601u_init_hardware(struct mt7601u_dev *dev)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	static const u16 beacon_offsets[16] = {
3208c2ecf20Sopenharmony_ci		/* 512 byte per beacon */
3218c2ecf20Sopenharmony_ci		0xc000,	0xc200,	0xc400,	0xc600,
3228c2ecf20Sopenharmony_ci		0xc800,	0xca00,	0xcc00,	0xce00,
3238c2ecf20Sopenharmony_ci		0xd000,	0xd200,	0xd400,	0xd600,
3248c2ecf20Sopenharmony_ci		0xd800,	0xda00,	0xdc00,	0xde00
3258c2ecf20Sopenharmony_ci	};
3268c2ecf20Sopenharmony_ci	int ret;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	dev->beacon_offsets = beacon_offsets;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	mt7601u_chip_onoff(dev, true, false);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	ret = mt7601u_wait_asic_ready(dev);
3338c2ecf20Sopenharmony_ci	if (ret)
3348c2ecf20Sopenharmony_ci		goto err;
3358c2ecf20Sopenharmony_ci	ret = mt7601u_mcu_init(dev);
3368c2ecf20Sopenharmony_ci	if (ret)
3378c2ecf20Sopenharmony_ci		goto err;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG,
3408c2ecf20Sopenharmony_ci			    MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
3418c2ecf20Sopenharmony_ci			    MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100)) {
3428c2ecf20Sopenharmony_ci		ret = -EIO;
3438c2ecf20Sopenharmony_ci		goto err;
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	/* Wait for ASIC ready after FW load. */
3478c2ecf20Sopenharmony_ci	ret = mt7601u_wait_asic_ready(dev);
3488c2ecf20Sopenharmony_ci	if (ret)
3498c2ecf20Sopenharmony_ci		goto err;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	mt7601u_reset_csr_bbp(dev);
3528c2ecf20Sopenharmony_ci	mt7601u_init_usb_dma(dev);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	ret = mt7601u_mcu_cmd_init(dev);
3558c2ecf20Sopenharmony_ci	if (ret)
3568c2ecf20Sopenharmony_ci		goto err;
3578c2ecf20Sopenharmony_ci	ret = mt7601u_dma_init(dev);
3588c2ecf20Sopenharmony_ci	if (ret)
3598c2ecf20Sopenharmony_ci		goto err_mcu;
3608c2ecf20Sopenharmony_ci	ret = mt7601u_write_mac_initvals(dev);
3618c2ecf20Sopenharmony_ci	if (ret)
3628c2ecf20Sopenharmony_ci		goto err_rx;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	if (!mt76_poll_msec(dev, MT_MAC_STATUS,
3658c2ecf20Sopenharmony_ci			    MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 100)) {
3668c2ecf20Sopenharmony_ci		ret = -EIO;
3678c2ecf20Sopenharmony_ci		goto err_rx;
3688c2ecf20Sopenharmony_ci	}
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	ret = mt7601u_init_bbp(dev);
3718c2ecf20Sopenharmony_ci	if (ret)
3728c2ecf20Sopenharmony_ci		goto err_rx;
3738c2ecf20Sopenharmony_ci	ret = mt7601u_init_wcid_mem(dev);
3748c2ecf20Sopenharmony_ci	if (ret)
3758c2ecf20Sopenharmony_ci		goto err_rx;
3768c2ecf20Sopenharmony_ci	ret = mt7601u_init_key_mem(dev);
3778c2ecf20Sopenharmony_ci	if (ret)
3788c2ecf20Sopenharmony_ci		goto err_rx;
3798c2ecf20Sopenharmony_ci	ret = mt7601u_init_wcid_attr_mem(dev);
3808c2ecf20Sopenharmony_ci	if (ret)
3818c2ecf20Sopenharmony_ci		goto err_rx;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
3848c2ecf20Sopenharmony_ci					     MT_BEACON_TIME_CFG_SYNC_MODE |
3858c2ecf20Sopenharmony_ci					     MT_BEACON_TIME_CFG_TBTT_EN |
3868c2ecf20Sopenharmony_ci					     MT_BEACON_TIME_CFG_BEACON_TX));
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	mt7601u_reset_counters(dev);
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	mt7601u_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	mt7601u_wr(dev, MT_TXOP_CTRL_CFG,
3938c2ecf20Sopenharmony_ci		   FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
3948c2ecf20Sopenharmony_ci		   FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	ret = mt7601u_eeprom_init(dev);
3978c2ecf20Sopenharmony_ci	if (ret)
3988c2ecf20Sopenharmony_ci		goto err_rx;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	ret = mt7601u_phy_init(dev);
4018c2ecf20Sopenharmony_ci	if (ret)
4028c2ecf20Sopenharmony_ci		goto err_rx;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	mt7601u_set_rx_path(dev, 0);
4058c2ecf20Sopenharmony_ci	mt7601u_set_tx_dac(dev, 0);
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	mt7601u_mac_set_ctrlch(dev, false);
4088c2ecf20Sopenharmony_ci	mt7601u_bbp_set_ctrlch(dev, false);
4098c2ecf20Sopenharmony_ci	mt7601u_bbp_set_bw(dev, MT_BW_20);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	return 0;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cierr_rx:
4148c2ecf20Sopenharmony_ci	mt7601u_dma_cleanup(dev);
4158c2ecf20Sopenharmony_cierr_mcu:
4168c2ecf20Sopenharmony_ci	mt7601u_mcu_cmd_deinit(dev);
4178c2ecf20Sopenharmony_cierr:
4188c2ecf20Sopenharmony_ci	mt7601u_chip_onoff(dev, false, false);
4198c2ecf20Sopenharmony_ci	return ret;
4208c2ecf20Sopenharmony_ci}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_civoid mt7601u_cleanup(struct mt7601u_dev *dev)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	if (!test_and_clear_bit(MT7601U_STATE_INITIALIZED, &dev->state))
4258c2ecf20Sopenharmony_ci		return;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	mt7601u_stop_hardware(dev);
4288c2ecf20Sopenharmony_ci	mt7601u_dma_cleanup(dev);
4298c2ecf20Sopenharmony_ci	mt7601u_mcu_cmd_deinit(dev);
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistruct mt7601u_dev *mt7601u_alloc_device(struct device *pdev)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	struct ieee80211_hw *hw;
4358c2ecf20Sopenharmony_ci	struct mt7601u_dev *dev;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	hw = ieee80211_alloc_hw(sizeof(*dev), &mt7601u_ops);
4388c2ecf20Sopenharmony_ci	if (!hw)
4398c2ecf20Sopenharmony_ci		return NULL;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	dev = hw->priv;
4428c2ecf20Sopenharmony_ci	dev->dev = pdev;
4438c2ecf20Sopenharmony_ci	dev->hw = hw;
4448c2ecf20Sopenharmony_ci	mutex_init(&dev->vendor_req_mutex);
4458c2ecf20Sopenharmony_ci	mutex_init(&dev->reg_atomic_mutex);
4468c2ecf20Sopenharmony_ci	mutex_init(&dev->hw_atomic_mutex);
4478c2ecf20Sopenharmony_ci	mutex_init(&dev->mutex);
4488c2ecf20Sopenharmony_ci	spin_lock_init(&dev->tx_lock);
4498c2ecf20Sopenharmony_ci	spin_lock_init(&dev->rx_lock);
4508c2ecf20Sopenharmony_ci	spin_lock_init(&dev->lock);
4518c2ecf20Sopenharmony_ci	spin_lock_init(&dev->mac_lock);
4528c2ecf20Sopenharmony_ci	spin_lock_init(&dev->con_mon_lock);
4538c2ecf20Sopenharmony_ci	atomic_set(&dev->avg_ampdu_len, 1);
4548c2ecf20Sopenharmony_ci	skb_queue_head_init(&dev->tx_skb_done);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	dev->stat_wq = alloc_workqueue("mt7601u", WQ_UNBOUND, 0);
4578c2ecf20Sopenharmony_ci	if (!dev->stat_wq) {
4588c2ecf20Sopenharmony_ci		ieee80211_free_hw(hw);
4598c2ecf20Sopenharmony_ci		return NULL;
4608c2ecf20Sopenharmony_ci	}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	return dev;
4638c2ecf20Sopenharmony_ci}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci#define CHAN2G(_idx, _freq) {			\
4668c2ecf20Sopenharmony_ci	.band = NL80211_BAND_2GHZ,		\
4678c2ecf20Sopenharmony_ci	.center_freq = (_freq),			\
4688c2ecf20Sopenharmony_ci	.hw_value = (_idx),			\
4698c2ecf20Sopenharmony_ci	.max_power = 30,			\
4708c2ecf20Sopenharmony_ci}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_cistatic const struct ieee80211_channel mt76_channels_2ghz[] = {
4738c2ecf20Sopenharmony_ci	CHAN2G(1, 2412),
4748c2ecf20Sopenharmony_ci	CHAN2G(2, 2417),
4758c2ecf20Sopenharmony_ci	CHAN2G(3, 2422),
4768c2ecf20Sopenharmony_ci	CHAN2G(4, 2427),
4778c2ecf20Sopenharmony_ci	CHAN2G(5, 2432),
4788c2ecf20Sopenharmony_ci	CHAN2G(6, 2437),
4798c2ecf20Sopenharmony_ci	CHAN2G(7, 2442),
4808c2ecf20Sopenharmony_ci	CHAN2G(8, 2447),
4818c2ecf20Sopenharmony_ci	CHAN2G(9, 2452),
4828c2ecf20Sopenharmony_ci	CHAN2G(10, 2457),
4838c2ecf20Sopenharmony_ci	CHAN2G(11, 2462),
4848c2ecf20Sopenharmony_ci	CHAN2G(12, 2467),
4858c2ecf20Sopenharmony_ci	CHAN2G(13, 2472),
4868c2ecf20Sopenharmony_ci	CHAN2G(14, 2484),
4878c2ecf20Sopenharmony_ci};
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci#define CCK_RATE(_idx, _rate) {					\
4908c2ecf20Sopenharmony_ci	.bitrate = _rate,					\
4918c2ecf20Sopenharmony_ci	.flags = IEEE80211_RATE_SHORT_PREAMBLE,			\
4928c2ecf20Sopenharmony_ci	.hw_value = (MT_PHY_TYPE_CCK << 8) | _idx,		\
4938c2ecf20Sopenharmony_ci	.hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + _idx),	\
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci#define OFDM_RATE(_idx, _rate) {				\
4978c2ecf20Sopenharmony_ci	.bitrate = _rate,					\
4988c2ecf20Sopenharmony_ci	.hw_value = (MT_PHY_TYPE_OFDM << 8) | _idx,		\
4998c2ecf20Sopenharmony_ci	.hw_value_short = (MT_PHY_TYPE_OFDM << 8) | _idx,	\
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_cistatic struct ieee80211_rate mt76_rates[] = {
5038c2ecf20Sopenharmony_ci	CCK_RATE(0, 10),
5048c2ecf20Sopenharmony_ci	CCK_RATE(1, 20),
5058c2ecf20Sopenharmony_ci	CCK_RATE(2, 55),
5068c2ecf20Sopenharmony_ci	CCK_RATE(3, 110),
5078c2ecf20Sopenharmony_ci	OFDM_RATE(0, 60),
5088c2ecf20Sopenharmony_ci	OFDM_RATE(1, 90),
5098c2ecf20Sopenharmony_ci	OFDM_RATE(2, 120),
5108c2ecf20Sopenharmony_ci	OFDM_RATE(3, 180),
5118c2ecf20Sopenharmony_ci	OFDM_RATE(4, 240),
5128c2ecf20Sopenharmony_ci	OFDM_RATE(5, 360),
5138c2ecf20Sopenharmony_ci	OFDM_RATE(6, 480),
5148c2ecf20Sopenharmony_ci	OFDM_RATE(7, 540),
5158c2ecf20Sopenharmony_ci};
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_cistatic int
5188c2ecf20Sopenharmony_cimt76_init_sband(struct mt7601u_dev *dev, struct ieee80211_supported_band *sband,
5198c2ecf20Sopenharmony_ci		const struct ieee80211_channel *chan, int n_chan,
5208c2ecf20Sopenharmony_ci		struct ieee80211_rate *rates, int n_rates)
5218c2ecf20Sopenharmony_ci{
5228c2ecf20Sopenharmony_ci	struct ieee80211_sta_ht_cap *ht_cap;
5238c2ecf20Sopenharmony_ci	void *chanlist;
5248c2ecf20Sopenharmony_ci	int size;
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	size = n_chan * sizeof(*chan);
5278c2ecf20Sopenharmony_ci	chanlist = devm_kmemdup(dev->dev, chan, size, GFP_KERNEL);
5288c2ecf20Sopenharmony_ci	if (!chanlist)
5298c2ecf20Sopenharmony_ci		return -ENOMEM;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	sband->channels = chanlist;
5328c2ecf20Sopenharmony_ci	sband->n_channels = n_chan;
5338c2ecf20Sopenharmony_ci	sband->bitrates = rates;
5348c2ecf20Sopenharmony_ci	sband->n_bitrates = n_rates;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	ht_cap = &sband->ht_cap;
5378c2ecf20Sopenharmony_ci	ht_cap->ht_supported = true;
5388c2ecf20Sopenharmony_ci	ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
5398c2ecf20Sopenharmony_ci		      IEEE80211_HT_CAP_GRN_FLD |
5408c2ecf20Sopenharmony_ci		      IEEE80211_HT_CAP_SGI_20 |
5418c2ecf20Sopenharmony_ci		      IEEE80211_HT_CAP_SGI_40 |
5428c2ecf20Sopenharmony_ci		      (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	ht_cap->mcs.rx_mask[0] = 0xff;
5458c2ecf20Sopenharmony_ci	ht_cap->mcs.rx_mask[4] = 0x1;
5468c2ecf20Sopenharmony_ci	ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
5478c2ecf20Sopenharmony_ci	ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
5488c2ecf20Sopenharmony_ci	ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_2;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	dev->chandef.chan = &sband->channels[0];
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	return 0;
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_cistatic int
5568c2ecf20Sopenharmony_cimt76_init_sband_2g(struct mt7601u_dev *dev)
5578c2ecf20Sopenharmony_ci{
5588c2ecf20Sopenharmony_ci	dev->sband_2g = devm_kzalloc(dev->dev, sizeof(*dev->sband_2g),
5598c2ecf20Sopenharmony_ci				     GFP_KERNEL);
5608c2ecf20Sopenharmony_ci	if (!dev->sband_2g)
5618c2ecf20Sopenharmony_ci		return -ENOMEM;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = dev->sband_2g;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	WARN_ON(dev->ee->reg.start - 1 + dev->ee->reg.num >
5668c2ecf20Sopenharmony_ci		ARRAY_SIZE(mt76_channels_2ghz));
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	return mt76_init_sband(dev, dev->sband_2g,
5698c2ecf20Sopenharmony_ci			       &mt76_channels_2ghz[dev->ee->reg.start - 1],
5708c2ecf20Sopenharmony_ci			       dev->ee->reg.num,
5718c2ecf20Sopenharmony_ci			       mt76_rates, ARRAY_SIZE(mt76_rates));
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ciint mt7601u_register_device(struct mt7601u_dev *dev)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	struct ieee80211_hw *hw = dev->hw;
5778c2ecf20Sopenharmony_ci	struct wiphy *wiphy = hw->wiphy;
5788c2ecf20Sopenharmony_ci	int ret;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	/* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
5818c2ecf20Sopenharmony_ci	 * entry no. 1 like it does in the vendor driver.
5828c2ecf20Sopenharmony_ci	 */
5838c2ecf20Sopenharmony_ci	dev->wcid_mask[0] |= 1;
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	/* init fake wcid for monitor interfaces */
5868c2ecf20Sopenharmony_ci	dev->mon_wcid = devm_kmalloc(dev->dev, sizeof(*dev->mon_wcid),
5878c2ecf20Sopenharmony_ci				     GFP_KERNEL);
5888c2ecf20Sopenharmony_ci	if (!dev->mon_wcid)
5898c2ecf20Sopenharmony_ci		return -ENOMEM;
5908c2ecf20Sopenharmony_ci	dev->mon_wcid->idx = 0xff;
5918c2ecf20Sopenharmony_ci	dev->mon_wcid->hw_key_idx = -1;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	SET_IEEE80211_DEV(hw, dev->dev);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	hw->queues = 4;
5968c2ecf20Sopenharmony_ci	ieee80211_hw_set(hw, SIGNAL_DBM);
5978c2ecf20Sopenharmony_ci	ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
5988c2ecf20Sopenharmony_ci	ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES);
5998c2ecf20Sopenharmony_ci	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
6008c2ecf20Sopenharmony_ci	ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
6018c2ecf20Sopenharmony_ci	ieee80211_hw_set(hw, MFP_CAPABLE);
6028c2ecf20Sopenharmony_ci	hw->max_rates = 1;
6038c2ecf20Sopenharmony_ci	hw->max_report_rates = 7;
6048c2ecf20Sopenharmony_ci	hw->max_rate_tries = 1;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	hw->sta_data_size = sizeof(struct mt76_sta);
6078c2ecf20Sopenharmony_ci	hw->vif_data_size = sizeof(struct mt76_vif);
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	SET_IEEE80211_PERM_ADDR(hw, dev->macaddr);
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
6128c2ecf20Sopenharmony_ci	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	ret = mt76_init_sband_2g(dev);
6178c2ecf20Sopenharmony_ci	if (ret)
6188c2ecf20Sopenharmony_ci		return ret;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&dev->mac_work, mt7601u_mac_work);
6218c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&dev->stat_work, mt7601u_tx_stat);
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	ret = ieee80211_register_hw(hw);
6248c2ecf20Sopenharmony_ci	if (ret)
6258c2ecf20Sopenharmony_ci		return ret;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	mt7601u_init_debugfs(dev);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	return 0;
6308c2ecf20Sopenharmony_ci}
631