xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt7921/usb.c (revision 8ba4d145d351db26e07695b8e90697398c5dfec2)
16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2022 MediaTek Inc.
36c92544dSBjoern A. Zeeb  *
46c92544dSBjoern A. Zeeb  * Author: Lorenzo Bianconi <lorenzo@kernel.org>
56c92544dSBjoern A. Zeeb  */
66c92544dSBjoern A. Zeeb 
76c92544dSBjoern A. Zeeb #include <linux/kernel.h>
86c92544dSBjoern A. Zeeb #include <linux/module.h>
96c92544dSBjoern A. Zeeb #include <linux/usb.h>
106c92544dSBjoern A. Zeeb 
116c92544dSBjoern A. Zeeb #include "mt7921.h"
126c92544dSBjoern A. Zeeb #include "mcu.h"
13cbb3ec25SBjoern A. Zeeb #include "../mt76_connac2_mac.h"
146c92544dSBjoern A. Zeeb 
156c92544dSBjoern A. Zeeb static const struct usb_device_id mt7921u_device_table[] = {
16cbb3ec25SBjoern A. Zeeb 	{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff),
17cbb3ec25SBjoern A. Zeeb 		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
18cbb3ec25SBjoern A. Zeeb 	/* Comfast CF-952AX */
19cbb3ec25SBjoern A. Zeeb 	{ USB_DEVICE_AND_INTERFACE_INFO(0x3574, 0x6211, 0xff, 0xff, 0xff),
20cbb3ec25SBjoern A. Zeeb 		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
21cbb3ec25SBjoern A. Zeeb 	/* Netgear, Inc. [A8000,AXE3000] */
22cbb3ec25SBjoern A. Zeeb 	{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9060, 0xff, 0xff, 0xff),
23cbb3ec25SBjoern A. Zeeb 		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
24*8ba4d145SBjoern A. Zeeb 	/* TP-Link TXE50UH */
25*8ba4d145SBjoern A. Zeeb 	{ USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0107, 0xff, 0xff, 0xff),
26*8ba4d145SBjoern A. Zeeb 		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
276c92544dSBjoern A. Zeeb 	{ },
286c92544dSBjoern A. Zeeb };
296c92544dSBjoern A. Zeeb 
306c92544dSBjoern A. Zeeb static int
mt7921u_mcu_send_message(struct mt76_dev * mdev,struct sk_buff * skb,int cmd,int * seq)316c92544dSBjoern A. Zeeb mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
326c92544dSBjoern A. Zeeb 			 int cmd, int *seq)
336c92544dSBjoern A. Zeeb {
34cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
356c92544dSBjoern A. Zeeb 	u32 pad, ep;
366c92544dSBjoern A. Zeeb 	int ret;
376c92544dSBjoern A. Zeeb 
386c92544dSBjoern A. Zeeb 	ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
396c92544dSBjoern A. Zeeb 	if (ret)
406c92544dSBjoern A. Zeeb 		return ret;
416c92544dSBjoern A. Zeeb 
426c92544dSBjoern A. Zeeb 	mdev->mcu.timeout = 3 * HZ;
436c92544dSBjoern A. Zeeb 
446c92544dSBjoern A. Zeeb 	if (cmd != MCU_CMD(FW_SCATTER))
456c92544dSBjoern A. Zeeb 		ep = MT_EP_OUT_INBAND_CMD;
466c92544dSBjoern A. Zeeb 	else
476c92544dSBjoern A. Zeeb 		ep = MT_EP_OUT_AC_BE;
486c92544dSBjoern A. Zeeb 
49*8ba4d145SBjoern A. Zeeb 	mt792x_skb_add_usb_sdio_hdr(dev, skb, 0);
506c92544dSBjoern A. Zeeb 	pad = round_up(skb->len, 4) + 4 - skb->len;
516c92544dSBjoern A. Zeeb 	__skb_put_zero(skb, pad);
526c92544dSBjoern A. Zeeb 
536c92544dSBjoern A. Zeeb 	ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,
546c92544dSBjoern A. Zeeb 			     1000, ep);
556c92544dSBjoern A. Zeeb 	dev_kfree_skb(skb);
566c92544dSBjoern A. Zeeb 
576c92544dSBjoern A. Zeeb 	return ret;
586c92544dSBjoern A. Zeeb }
596c92544dSBjoern A. Zeeb 
mt7921u_mcu_init(struct mt792x_dev * dev)60cbb3ec25SBjoern A. Zeeb static int mt7921u_mcu_init(struct mt792x_dev *dev)
616c92544dSBjoern A. Zeeb {
626c92544dSBjoern A. Zeeb 	static const struct mt76_mcu_ops mcu_ops = {
636c92544dSBjoern A. Zeeb 		.headroom = MT_SDIO_HDR_SIZE +
646c92544dSBjoern A. Zeeb 			    sizeof(struct mt76_connac2_mcu_txd),
656c92544dSBjoern A. Zeeb 		.tailroom = MT_USB_TAIL_SIZE,
666c92544dSBjoern A. Zeeb 		.mcu_skb_send_msg = mt7921u_mcu_send_message,
676c92544dSBjoern A. Zeeb 		.mcu_parse_response = mt7921_mcu_parse_response,
686c92544dSBjoern A. Zeeb 	};
696c92544dSBjoern A. Zeeb 	int ret;
706c92544dSBjoern A. Zeeb 
716c92544dSBjoern A. Zeeb 	dev->mt76.mcu_ops = &mcu_ops;
726c92544dSBjoern A. Zeeb 
736c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
746c92544dSBjoern A. Zeeb 	ret = mt7921_run_firmware(dev);
756c92544dSBjoern A. Zeeb 	if (ret)
766c92544dSBjoern A. Zeeb 		return ret;
776c92544dSBjoern A. Zeeb 
786c92544dSBjoern A. Zeeb 	set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
796c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
806c92544dSBjoern A. Zeeb 
816c92544dSBjoern A. Zeeb 	return 0;
826c92544dSBjoern A. Zeeb }
836c92544dSBjoern A. Zeeb 
mt7921u_mac_reset(struct mt792x_dev * dev)84cbb3ec25SBjoern A. Zeeb static int mt7921u_mac_reset(struct mt792x_dev *dev)
85cbb3ec25SBjoern A. Zeeb {
86cbb3ec25SBjoern A. Zeeb 	int err;
87cbb3ec25SBjoern A. Zeeb 
88cbb3ec25SBjoern A. Zeeb 	mt76_txq_schedule_all(&dev->mphy);
89cbb3ec25SBjoern A. Zeeb 	mt76_worker_disable(&dev->mt76.tx_worker);
90cbb3ec25SBjoern A. Zeeb 
91cbb3ec25SBjoern A. Zeeb 	set_bit(MT76_RESET, &dev->mphy.state);
92cbb3ec25SBjoern A. Zeeb 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
93cbb3ec25SBjoern A. Zeeb 
94cbb3ec25SBjoern A. Zeeb 	wake_up(&dev->mt76.mcu.wait);
95cbb3ec25SBjoern A. Zeeb 	skb_queue_purge(&dev->mt76.mcu.res_q);
96cbb3ec25SBjoern A. Zeeb 
97cbb3ec25SBjoern A. Zeeb 	mt76u_stop_rx(&dev->mt76);
98cbb3ec25SBjoern A. Zeeb 	mt76u_stop_tx(&dev->mt76);
99cbb3ec25SBjoern A. Zeeb 
100cbb3ec25SBjoern A. Zeeb 	mt792xu_wfsys_reset(dev);
101cbb3ec25SBjoern A. Zeeb 
102cbb3ec25SBjoern A. Zeeb 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
103cbb3ec25SBjoern A. Zeeb 	err = mt76u_resume_rx(&dev->mt76);
104cbb3ec25SBjoern A. Zeeb 	if (err)
105cbb3ec25SBjoern A. Zeeb 		goto out;
106cbb3ec25SBjoern A. Zeeb 
107cbb3ec25SBjoern A. Zeeb 	err = mt792xu_mcu_power_on(dev);
108cbb3ec25SBjoern A. Zeeb 	if (err)
109cbb3ec25SBjoern A. Zeeb 		goto out;
110cbb3ec25SBjoern A. Zeeb 
111cbb3ec25SBjoern A. Zeeb 	err = mt792xu_dma_init(dev, false);
112cbb3ec25SBjoern A. Zeeb 	if (err)
113cbb3ec25SBjoern A. Zeeb 		goto out;
114cbb3ec25SBjoern A. Zeeb 
115cbb3ec25SBjoern A. Zeeb 	mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
116cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
117cbb3ec25SBjoern A. Zeeb 
118cbb3ec25SBjoern A. Zeeb 	err = mt7921_run_firmware(dev);
119cbb3ec25SBjoern A. Zeeb 	if (err)
120cbb3ec25SBjoern A. Zeeb 		goto out;
121cbb3ec25SBjoern A. Zeeb 
122cbb3ec25SBjoern A. Zeeb 	mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
123cbb3ec25SBjoern A. Zeeb 
124cbb3ec25SBjoern A. Zeeb 	err = mt7921_mcu_set_eeprom(dev);
125cbb3ec25SBjoern A. Zeeb 	if (err)
126cbb3ec25SBjoern A. Zeeb 		goto out;
127cbb3ec25SBjoern A. Zeeb 
128cbb3ec25SBjoern A. Zeeb 	err = mt7921_mac_init(dev);
129cbb3ec25SBjoern A. Zeeb 	if (err)
130cbb3ec25SBjoern A. Zeeb 		goto out;
131cbb3ec25SBjoern A. Zeeb 
132cbb3ec25SBjoern A. Zeeb 	err = __mt7921_start(&dev->phy);
133cbb3ec25SBjoern A. Zeeb out:
134cbb3ec25SBjoern A. Zeeb 	clear_bit(MT76_RESET, &dev->mphy.state);
135cbb3ec25SBjoern A. Zeeb 
136cbb3ec25SBjoern A. Zeeb 	mt76_worker_enable(&dev->mt76.tx_worker);
137cbb3ec25SBjoern A. Zeeb 
138cbb3ec25SBjoern A. Zeeb 	return err;
139cbb3ec25SBjoern A. Zeeb }
140cbb3ec25SBjoern A. Zeeb 
mt7921u_probe(struct usb_interface * usb_intf,const struct usb_device_id * id)1416c92544dSBjoern A. Zeeb static int mt7921u_probe(struct usb_interface *usb_intf,
1426c92544dSBjoern A. Zeeb 			 const struct usb_device_id *id)
1436c92544dSBjoern A. Zeeb {
1446c92544dSBjoern A. Zeeb 	static const struct mt76_driver_ops drv_ops = {
1456c92544dSBjoern A. Zeeb 		.txwi_size = MT_SDIO_TXD_SIZE,
146cbb3ec25SBjoern A. Zeeb 		.drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ |
147cbb3ec25SBjoern A. Zeeb 			     MT_DRV_AMSDU_OFFLOAD,
1486c92544dSBjoern A. Zeeb 		.survey_flags = SURVEY_INFO_TIME_TX |
1496c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_RX |
1506c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_BSS_RX,
1516c92544dSBjoern A. Zeeb 		.tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb,
1526c92544dSBjoern A. Zeeb 		.tx_complete_skb = mt7921_usb_sdio_tx_complete_skb,
1536c92544dSBjoern A. Zeeb 		.tx_status_data = mt7921_usb_sdio_tx_status_data,
1546c92544dSBjoern A. Zeeb 		.rx_skb = mt7921_queue_rx_skb,
1556c92544dSBjoern A. Zeeb 		.rx_check = mt7921_rx_check,
1566c92544dSBjoern A. Zeeb 		.sta_add = mt7921_mac_sta_add,
157*8ba4d145SBjoern A. Zeeb 		.sta_event = mt7921_mac_sta_event,
1586c92544dSBjoern A. Zeeb 		.sta_remove = mt7921_mac_sta_remove,
159cbb3ec25SBjoern A. Zeeb 		.update_survey = mt792x_update_channel,
160*8ba4d145SBjoern A. Zeeb 		.set_channel = mt7921_set_channel,
1616c92544dSBjoern A. Zeeb 	};
162cbb3ec25SBjoern A. Zeeb 	static const struct mt792x_hif_ops hif_ops = {
1636c92544dSBjoern A. Zeeb 		.mcu_init = mt7921u_mcu_init,
164cbb3ec25SBjoern A. Zeeb 		.init_reset = mt792xu_init_reset,
1656c92544dSBjoern A. Zeeb 		.reset = mt7921u_mac_reset,
1666c92544dSBjoern A. Zeeb 	};
1676c92544dSBjoern A. Zeeb 	static struct mt76_bus_ops bus_ops = {
168cbb3ec25SBjoern A. Zeeb 		.rr = mt792xu_rr,
169cbb3ec25SBjoern A. Zeeb 		.wr = mt792xu_wr,
170cbb3ec25SBjoern A. Zeeb 		.rmw = mt792xu_rmw,
1716c92544dSBjoern A. Zeeb 		.read_copy = mt76u_read_copy,
172cbb3ec25SBjoern A. Zeeb 		.write_copy = mt792xu_copy,
1736c92544dSBjoern A. Zeeb 		.type = MT76_BUS_USB,
1746c92544dSBjoern A. Zeeb 	};
1756c92544dSBjoern A. Zeeb 	struct usb_device *udev = interface_to_usbdev(usb_intf);
1766c92544dSBjoern A. Zeeb 	struct ieee80211_ops *ops;
1776c92544dSBjoern A. Zeeb 	struct ieee80211_hw *hw;
178cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev;
1796c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev;
180cbb3ec25SBjoern A. Zeeb 	u8 features;
1816c92544dSBjoern A. Zeeb 	int ret;
1826c92544dSBjoern A. Zeeb 
183cbb3ec25SBjoern A. Zeeb 	ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7921_ops,
184cbb3ec25SBjoern A. Zeeb 				      (void *)id->driver_info, &features);
1856c92544dSBjoern A. Zeeb 	if (!ops)
1866c92544dSBjoern A. Zeeb 		return -ENOMEM;
1876c92544dSBjoern A. Zeeb 
188*8ba4d145SBjoern A. Zeeb 	ops->stop = mt792xu_stop;
1896c92544dSBjoern A. Zeeb 	mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
1906c92544dSBjoern A. Zeeb 	if (!mdev)
1916c92544dSBjoern A. Zeeb 		return -ENOMEM;
1926c92544dSBjoern A. Zeeb 
193cbb3ec25SBjoern A. Zeeb 	dev = container_of(mdev, struct mt792x_dev, mt76);
194cbb3ec25SBjoern A. Zeeb 	dev->fw_features = features;
1956c92544dSBjoern A. Zeeb 	dev->hif_ops = &hif_ops;
1966c92544dSBjoern A. Zeeb 
1976c92544dSBjoern A. Zeeb 	udev = usb_get_dev(udev);
1986c92544dSBjoern A. Zeeb 	usb_reset_device(udev);
1996c92544dSBjoern A. Zeeb 
2006c92544dSBjoern A. Zeeb 	usb_set_intfdata(usb_intf, dev);
2016c92544dSBjoern A. Zeeb 
2026c92544dSBjoern A. Zeeb 	ret = __mt76u_init(mdev, usb_intf, &bus_ops);
2036c92544dSBjoern A. Zeeb 	if (ret < 0)
2046c92544dSBjoern A. Zeeb 		goto error;
2056c92544dSBjoern A. Zeeb 
2066c92544dSBjoern A. Zeeb 	mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
2076c92544dSBjoern A. Zeeb 		    (mt76_rr(dev, MT_HW_REV) & 0xff);
2086c92544dSBjoern A. Zeeb 	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
2096c92544dSBjoern A. Zeeb 
2106c92544dSBjoern A. Zeeb 	if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) {
211cbb3ec25SBjoern A. Zeeb 		ret = mt792xu_wfsys_reset(dev);
2126c92544dSBjoern A. Zeeb 		if (ret)
2136c92544dSBjoern A. Zeeb 			goto error;
2146c92544dSBjoern A. Zeeb 	}
2156c92544dSBjoern A. Zeeb 
216cbb3ec25SBjoern A. Zeeb 	ret = mt792xu_mcu_power_on(dev);
2176c92544dSBjoern A. Zeeb 	if (ret)
2186c92544dSBjoern A. Zeeb 		goto error;
2196c92544dSBjoern A. Zeeb 
2206c92544dSBjoern A. Zeeb 	ret = mt76u_alloc_mcu_queue(&dev->mt76);
2216c92544dSBjoern A. Zeeb 	if (ret)
2226c92544dSBjoern A. Zeeb 		goto error;
2236c92544dSBjoern A. Zeeb 
2246c92544dSBjoern A. Zeeb 	ret = mt76u_alloc_queues(&dev->mt76);
2256c92544dSBjoern A. Zeeb 	if (ret)
2266c92544dSBjoern A. Zeeb 		goto error;
2276c92544dSBjoern A. Zeeb 
228cbb3ec25SBjoern A. Zeeb 	ret = mt792xu_dma_init(dev, false);
2296c92544dSBjoern A. Zeeb 	if (ret)
230cbb3ec25SBjoern A. Zeeb 		goto error;
2316c92544dSBjoern A. Zeeb 
2326c92544dSBjoern A. Zeeb 	hw = mt76_hw(dev);
2336c92544dSBjoern A. Zeeb 	/* check hw sg support in order to enable AMSDU */
2346c92544dSBjoern A. Zeeb 	hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1;
2356c92544dSBjoern A. Zeeb 
2366c92544dSBjoern A. Zeeb 	ret = mt7921_register_device(dev);
2376c92544dSBjoern A. Zeeb 	if (ret)
2386c92544dSBjoern A. Zeeb 		goto error;
2396c92544dSBjoern A. Zeeb 
2406c92544dSBjoern A. Zeeb 	return 0;
2416c92544dSBjoern A. Zeeb 
2426c92544dSBjoern A. Zeeb error:
2436c92544dSBjoern A. Zeeb 	mt76u_queues_deinit(&dev->mt76);
2446c92544dSBjoern A. Zeeb 
2456c92544dSBjoern A. Zeeb 	usb_set_intfdata(usb_intf, NULL);
2466c92544dSBjoern A. Zeeb 	usb_put_dev(interface_to_usbdev(usb_intf));
2476c92544dSBjoern A. Zeeb 
2486c92544dSBjoern A. Zeeb 	mt76_free_device(&dev->mt76);
2496c92544dSBjoern A. Zeeb 
2506c92544dSBjoern A. Zeeb 	return ret;
2516c92544dSBjoern A. Zeeb }
2526c92544dSBjoern A. Zeeb 
2536c92544dSBjoern A. Zeeb #ifdef CONFIG_PM
mt7921u_suspend(struct usb_interface * intf,pm_message_t state)2546c92544dSBjoern A. Zeeb static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
2556c92544dSBjoern A. Zeeb {
256cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = usb_get_intfdata(intf);
2576c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
2586c92544dSBjoern A. Zeeb 	int err;
2596c92544dSBjoern A. Zeeb 
2606c92544dSBjoern A. Zeeb 	pm->suspended = true;
2616c92544dSBjoern A. Zeeb 	flush_work(&dev->reset_work);
2626c92544dSBjoern A. Zeeb 
263*8ba4d145SBjoern A. Zeeb 	err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true, true);
2646c92544dSBjoern A. Zeeb 	if (err)
2656c92544dSBjoern A. Zeeb 		goto failed;
2666c92544dSBjoern A. Zeeb 
2676c92544dSBjoern A. Zeeb 	mt76u_stop_rx(&dev->mt76);
2686c92544dSBjoern A. Zeeb 	mt76u_stop_tx(&dev->mt76);
2696c92544dSBjoern A. Zeeb 
2706c92544dSBjoern A. Zeeb 	return 0;
2716c92544dSBjoern A. Zeeb 
2726c92544dSBjoern A. Zeeb failed:
2736c92544dSBjoern A. Zeeb 	pm->suspended = false;
2746c92544dSBjoern A. Zeeb 
2756c92544dSBjoern A. Zeeb 	if (err < 0)
276cbb3ec25SBjoern A. Zeeb 		mt792x_reset(&dev->mt76);
2776c92544dSBjoern A. Zeeb 
2786c92544dSBjoern A. Zeeb 	return err;
2796c92544dSBjoern A. Zeeb }
2806c92544dSBjoern A. Zeeb 
mt7921u_resume(struct usb_interface * intf)2816c92544dSBjoern A. Zeeb static int mt7921u_resume(struct usb_interface *intf)
2826c92544dSBjoern A. Zeeb {
283cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = usb_get_intfdata(intf);
2846c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
2856c92544dSBjoern A. Zeeb 	bool reinit = true;
2866c92544dSBjoern A. Zeeb 	int err, i;
2876c92544dSBjoern A. Zeeb 
2886c92544dSBjoern A. Zeeb 	for (i = 0; i < 10; i++) {
2896c92544dSBjoern A. Zeeb 		u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT);
2906c92544dSBjoern A. Zeeb 
2916c92544dSBjoern A. Zeeb 		if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) {
2926c92544dSBjoern A. Zeeb 			reinit = false;
2936c92544dSBjoern A. Zeeb 			break;
2946c92544dSBjoern A. Zeeb 		}
2956c92544dSBjoern A. Zeeb 		if (val & MT_WF_SW_SER_DONE_SUSPEND) {
2966c92544dSBjoern A. Zeeb 			mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0);
2976c92544dSBjoern A. Zeeb 			break;
2986c92544dSBjoern A. Zeeb 		}
2996c92544dSBjoern A. Zeeb 
3006c92544dSBjoern A. Zeeb 		msleep(20);
3016c92544dSBjoern A. Zeeb 	}
3026c92544dSBjoern A. Zeeb 
303cbb3ec25SBjoern A. Zeeb 	if (reinit || mt792x_dma_need_reinit(dev)) {
304cbb3ec25SBjoern A. Zeeb 		err = mt792xu_dma_init(dev, true);
3056c92544dSBjoern A. Zeeb 		if (err)
3066c92544dSBjoern A. Zeeb 			goto failed;
3076c92544dSBjoern A. Zeeb 	}
3086c92544dSBjoern A. Zeeb 
3096c92544dSBjoern A. Zeeb 	err = mt76u_resume_rx(&dev->mt76);
3106c92544dSBjoern A. Zeeb 	if (err < 0)
3116c92544dSBjoern A. Zeeb 		goto failed;
3126c92544dSBjoern A. Zeeb 
313*8ba4d145SBjoern A. Zeeb 	err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false, true);
3146c92544dSBjoern A. Zeeb failed:
3156c92544dSBjoern A. Zeeb 	pm->suspended = false;
3166c92544dSBjoern A. Zeeb 
3176c92544dSBjoern A. Zeeb 	if (err < 0)
318cbb3ec25SBjoern A. Zeeb 		mt792x_reset(&dev->mt76);
3196c92544dSBjoern A. Zeeb 
3206c92544dSBjoern A. Zeeb 	return err;
3216c92544dSBjoern A. Zeeb }
3226c92544dSBjoern A. Zeeb #endif /* CONFIG_PM */
3236c92544dSBjoern A. Zeeb 
3246c92544dSBjoern A. Zeeb MODULE_DEVICE_TABLE(usb, mt7921u_device_table);
3256c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
3266c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7921_ROM_PATCH);
3276c92544dSBjoern A. Zeeb 
3286c92544dSBjoern A. Zeeb static struct usb_driver mt7921u_driver = {
3296c92544dSBjoern A. Zeeb 	.name		= KBUILD_MODNAME,
3306c92544dSBjoern A. Zeeb 	.id_table	= mt7921u_device_table,
3316c92544dSBjoern A. Zeeb 	.probe		= mt7921u_probe,
332cbb3ec25SBjoern A. Zeeb 	.disconnect	= mt792xu_disconnect,
3336c92544dSBjoern A. Zeeb #ifdef CONFIG_PM
3346c92544dSBjoern A. Zeeb 	.suspend	= mt7921u_suspend,
3356c92544dSBjoern A. Zeeb 	.resume		= mt7921u_resume,
3366c92544dSBjoern A. Zeeb 	.reset_resume	= mt7921u_resume,
3376c92544dSBjoern A. Zeeb #endif /* CONFIG_PM */
3386c92544dSBjoern A. Zeeb 	.soft_unbind	= 1,
3396c92544dSBjoern A. Zeeb 	.disable_hub_initiated_lpm = 1,
3406c92544dSBjoern A. Zeeb };
3416c92544dSBjoern A. Zeeb module_usb_driver(mt7921u_driver);
3426c92544dSBjoern A. Zeeb 
343*8ba4d145SBjoern A. Zeeb MODULE_DESCRIPTION("MediaTek MT7921U (USB) wireless driver");
3446c92544dSBjoern A. Zeeb MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
3456c92544dSBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
346