xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt7921/usb.c (revision cbb3ec25)
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 },
246c92544dSBjoern A. Zeeb 	{ },
256c92544dSBjoern A. Zeeb };
266c92544dSBjoern A. Zeeb 
276c92544dSBjoern A. Zeeb static int
mt7921u_mcu_send_message(struct mt76_dev * mdev,struct sk_buff * skb,int cmd,int * seq)286c92544dSBjoern A. Zeeb mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
296c92544dSBjoern A. Zeeb 			 int cmd, int *seq)
306c92544dSBjoern A. Zeeb {
31cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
326c92544dSBjoern A. Zeeb 	u32 pad, ep;
336c92544dSBjoern A. Zeeb 	int ret;
346c92544dSBjoern A. Zeeb 
356c92544dSBjoern A. Zeeb 	ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
366c92544dSBjoern A. Zeeb 	if (ret)
376c92544dSBjoern A. Zeeb 		return ret;
386c92544dSBjoern A. Zeeb 
396c92544dSBjoern A. Zeeb 	mdev->mcu.timeout = 3 * HZ;
406c92544dSBjoern A. Zeeb 
416c92544dSBjoern A. Zeeb 	if (cmd != MCU_CMD(FW_SCATTER))
426c92544dSBjoern A. Zeeb 		ep = MT_EP_OUT_INBAND_CMD;
436c92544dSBjoern A. Zeeb 	else
446c92544dSBjoern A. Zeeb 		ep = MT_EP_OUT_AC_BE;
456c92544dSBjoern A. Zeeb 
466c92544dSBjoern A. Zeeb 	mt7921_skb_add_usb_sdio_hdr(dev, skb, 0);
476c92544dSBjoern A. Zeeb 	pad = round_up(skb->len, 4) + 4 - skb->len;
486c92544dSBjoern A. Zeeb 	__skb_put_zero(skb, pad);
496c92544dSBjoern A. Zeeb 
506c92544dSBjoern A. Zeeb 	ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,
516c92544dSBjoern A. Zeeb 			     1000, ep);
526c92544dSBjoern A. Zeeb 	dev_kfree_skb(skb);
536c92544dSBjoern A. Zeeb 
546c92544dSBjoern A. Zeeb 	return ret;
556c92544dSBjoern A. Zeeb }
566c92544dSBjoern A. Zeeb 
mt7921u_mcu_init(struct mt792x_dev * dev)57cbb3ec25SBjoern A. Zeeb static int mt7921u_mcu_init(struct mt792x_dev *dev)
586c92544dSBjoern A. Zeeb {
596c92544dSBjoern A. Zeeb 	static const struct mt76_mcu_ops mcu_ops = {
606c92544dSBjoern A. Zeeb 		.headroom = MT_SDIO_HDR_SIZE +
616c92544dSBjoern A. Zeeb 			    sizeof(struct mt76_connac2_mcu_txd),
626c92544dSBjoern A. Zeeb 		.tailroom = MT_USB_TAIL_SIZE,
636c92544dSBjoern A. Zeeb 		.mcu_skb_send_msg = mt7921u_mcu_send_message,
646c92544dSBjoern A. Zeeb 		.mcu_parse_response = mt7921_mcu_parse_response,
656c92544dSBjoern A. Zeeb 	};
666c92544dSBjoern A. Zeeb 	int ret;
676c92544dSBjoern A. Zeeb 
686c92544dSBjoern A. Zeeb 	dev->mt76.mcu_ops = &mcu_ops;
696c92544dSBjoern A. Zeeb 
706c92544dSBjoern A. Zeeb 	mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
716c92544dSBjoern A. Zeeb 	ret = mt7921_run_firmware(dev);
726c92544dSBjoern A. Zeeb 	if (ret)
736c92544dSBjoern A. Zeeb 		return ret;
746c92544dSBjoern A. Zeeb 
756c92544dSBjoern A. Zeeb 	set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
766c92544dSBjoern A. Zeeb 	mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
776c92544dSBjoern A. Zeeb 
786c92544dSBjoern A. Zeeb 	return 0;
796c92544dSBjoern A. Zeeb }
806c92544dSBjoern A. Zeeb 
mt7921u_mac_reset(struct mt792x_dev * dev)81cbb3ec25SBjoern A. Zeeb static int mt7921u_mac_reset(struct mt792x_dev *dev)
82cbb3ec25SBjoern A. Zeeb {
83cbb3ec25SBjoern A. Zeeb 	int err;
84cbb3ec25SBjoern A. Zeeb 
85cbb3ec25SBjoern A. Zeeb 	mt76_txq_schedule_all(&dev->mphy);
86cbb3ec25SBjoern A. Zeeb 	mt76_worker_disable(&dev->mt76.tx_worker);
87cbb3ec25SBjoern A. Zeeb 
88cbb3ec25SBjoern A. Zeeb 	set_bit(MT76_RESET, &dev->mphy.state);
89cbb3ec25SBjoern A. Zeeb 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
90cbb3ec25SBjoern A. Zeeb 
91cbb3ec25SBjoern A. Zeeb 	wake_up(&dev->mt76.mcu.wait);
92cbb3ec25SBjoern A. Zeeb 	skb_queue_purge(&dev->mt76.mcu.res_q);
93cbb3ec25SBjoern A. Zeeb 
94cbb3ec25SBjoern A. Zeeb 	mt76u_stop_rx(&dev->mt76);
95cbb3ec25SBjoern A. Zeeb 	mt76u_stop_tx(&dev->mt76);
96cbb3ec25SBjoern A. Zeeb 
97cbb3ec25SBjoern A. Zeeb 	mt792xu_wfsys_reset(dev);
98cbb3ec25SBjoern A. Zeeb 
99cbb3ec25SBjoern A. Zeeb 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
100cbb3ec25SBjoern A. Zeeb 	err = mt76u_resume_rx(&dev->mt76);
101cbb3ec25SBjoern A. Zeeb 	if (err)
102cbb3ec25SBjoern A. Zeeb 		goto out;
103cbb3ec25SBjoern A. Zeeb 
104cbb3ec25SBjoern A. Zeeb 	err = mt792xu_mcu_power_on(dev);
105cbb3ec25SBjoern A. Zeeb 	if (err)
106cbb3ec25SBjoern A. Zeeb 		goto out;
107cbb3ec25SBjoern A. Zeeb 
108cbb3ec25SBjoern A. Zeeb 	err = mt792xu_dma_init(dev, false);
109cbb3ec25SBjoern A. Zeeb 	if (err)
110cbb3ec25SBjoern A. Zeeb 		goto out;
111cbb3ec25SBjoern A. Zeeb 
112cbb3ec25SBjoern A. Zeeb 	mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
113cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
114cbb3ec25SBjoern A. Zeeb 
115cbb3ec25SBjoern A. Zeeb 	err = mt7921_run_firmware(dev);
116cbb3ec25SBjoern A. Zeeb 	if (err)
117cbb3ec25SBjoern A. Zeeb 		goto out;
118cbb3ec25SBjoern A. Zeeb 
119cbb3ec25SBjoern A. Zeeb 	mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
120cbb3ec25SBjoern A. Zeeb 
121cbb3ec25SBjoern A. Zeeb 	err = mt7921_mcu_set_eeprom(dev);
122cbb3ec25SBjoern A. Zeeb 	if (err)
123cbb3ec25SBjoern A. Zeeb 		goto out;
124cbb3ec25SBjoern A. Zeeb 
125cbb3ec25SBjoern A. Zeeb 	err = mt7921_mac_init(dev);
126cbb3ec25SBjoern A. Zeeb 	if (err)
127cbb3ec25SBjoern A. Zeeb 		goto out;
128cbb3ec25SBjoern A. Zeeb 
129cbb3ec25SBjoern A. Zeeb 	err = __mt7921_start(&dev->phy);
130cbb3ec25SBjoern A. Zeeb out:
131cbb3ec25SBjoern A. Zeeb 	clear_bit(MT76_RESET, &dev->mphy.state);
132cbb3ec25SBjoern A. Zeeb 
133cbb3ec25SBjoern A. Zeeb 	mt76_worker_enable(&dev->mt76.tx_worker);
134cbb3ec25SBjoern A. Zeeb 
135cbb3ec25SBjoern A. Zeeb 	return err;
136cbb3ec25SBjoern A. Zeeb }
137cbb3ec25SBjoern A. Zeeb 
mt7921u_stop(struct ieee80211_hw * hw)1386c92544dSBjoern A. Zeeb static void mt7921u_stop(struct ieee80211_hw *hw)
1396c92544dSBjoern A. Zeeb {
140cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = mt792x_hw_dev(hw);
1416c92544dSBjoern A. Zeeb 
1426c92544dSBjoern A. Zeeb 	mt76u_stop_tx(&dev->mt76);
1436c92544dSBjoern A. Zeeb 	mt7921_stop(hw);
1446c92544dSBjoern A. Zeeb }
1456c92544dSBjoern A. Zeeb 
mt7921u_probe(struct usb_interface * usb_intf,const struct usb_device_id * id)1466c92544dSBjoern A. Zeeb static int mt7921u_probe(struct usb_interface *usb_intf,
1476c92544dSBjoern A. Zeeb 			 const struct usb_device_id *id)
1486c92544dSBjoern A. Zeeb {
1496c92544dSBjoern A. Zeeb 	static const struct mt76_driver_ops drv_ops = {
1506c92544dSBjoern A. Zeeb 		.txwi_size = MT_SDIO_TXD_SIZE,
151cbb3ec25SBjoern A. Zeeb 		.drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ |
152cbb3ec25SBjoern A. Zeeb 			     MT_DRV_AMSDU_OFFLOAD,
1536c92544dSBjoern A. Zeeb 		.survey_flags = SURVEY_INFO_TIME_TX |
1546c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_RX |
1556c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_BSS_RX,
1566c92544dSBjoern A. Zeeb 		.tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb,
1576c92544dSBjoern A. Zeeb 		.tx_complete_skb = mt7921_usb_sdio_tx_complete_skb,
1586c92544dSBjoern A. Zeeb 		.tx_status_data = mt7921_usb_sdio_tx_status_data,
1596c92544dSBjoern A. Zeeb 		.rx_skb = mt7921_queue_rx_skb,
1606c92544dSBjoern A. Zeeb 		.rx_check = mt7921_rx_check,
1616c92544dSBjoern A. Zeeb 		.sta_add = mt7921_mac_sta_add,
1626c92544dSBjoern A. Zeeb 		.sta_assoc = mt7921_mac_sta_assoc,
1636c92544dSBjoern A. Zeeb 		.sta_remove = mt7921_mac_sta_remove,
164cbb3ec25SBjoern A. Zeeb 		.update_survey = mt792x_update_channel,
1656c92544dSBjoern A. Zeeb 	};
166cbb3ec25SBjoern A. Zeeb 	static const struct mt792x_hif_ops hif_ops = {
1676c92544dSBjoern A. Zeeb 		.mcu_init = mt7921u_mcu_init,
168cbb3ec25SBjoern A. Zeeb 		.init_reset = mt792xu_init_reset,
1696c92544dSBjoern A. Zeeb 		.reset = mt7921u_mac_reset,
1706c92544dSBjoern A. Zeeb 	};
1716c92544dSBjoern A. Zeeb 	static struct mt76_bus_ops bus_ops = {
172cbb3ec25SBjoern A. Zeeb 		.rr = mt792xu_rr,
173cbb3ec25SBjoern A. Zeeb 		.wr = mt792xu_wr,
174cbb3ec25SBjoern A. Zeeb 		.rmw = mt792xu_rmw,
1756c92544dSBjoern A. Zeeb 		.read_copy = mt76u_read_copy,
176cbb3ec25SBjoern A. Zeeb 		.write_copy = mt792xu_copy,
1776c92544dSBjoern A. Zeeb 		.type = MT76_BUS_USB,
1786c92544dSBjoern A. Zeeb 	};
1796c92544dSBjoern A. Zeeb 	struct usb_device *udev = interface_to_usbdev(usb_intf);
1806c92544dSBjoern A. Zeeb 	struct ieee80211_ops *ops;
1816c92544dSBjoern A. Zeeb 	struct ieee80211_hw *hw;
182cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev;
1836c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev;
184cbb3ec25SBjoern A. Zeeb 	u8 features;
1856c92544dSBjoern A. Zeeb 	int ret;
1866c92544dSBjoern A. Zeeb 
187cbb3ec25SBjoern A. Zeeb 	ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7921_ops,
188cbb3ec25SBjoern A. Zeeb 				      (void *)id->driver_info, &features);
1896c92544dSBjoern A. Zeeb 	if (!ops)
1906c92544dSBjoern A. Zeeb 		return -ENOMEM;
1916c92544dSBjoern A. Zeeb 
1926c92544dSBjoern A. Zeeb 	ops->stop = mt7921u_stop;
1936c92544dSBjoern A. Zeeb 	mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
1946c92544dSBjoern A. Zeeb 	if (!mdev)
1956c92544dSBjoern A. Zeeb 		return -ENOMEM;
1966c92544dSBjoern A. Zeeb 
197cbb3ec25SBjoern A. Zeeb 	dev = container_of(mdev, struct mt792x_dev, mt76);
198cbb3ec25SBjoern A. Zeeb 	dev->fw_features = features;
1996c92544dSBjoern A. Zeeb 	dev->hif_ops = &hif_ops;
2006c92544dSBjoern A. Zeeb 
2016c92544dSBjoern A. Zeeb 	udev = usb_get_dev(udev);
2026c92544dSBjoern A. Zeeb 	usb_reset_device(udev);
2036c92544dSBjoern A. Zeeb 
2046c92544dSBjoern A. Zeeb 	usb_set_intfdata(usb_intf, dev);
2056c92544dSBjoern A. Zeeb 
2066c92544dSBjoern A. Zeeb 	ret = __mt76u_init(mdev, usb_intf, &bus_ops);
2076c92544dSBjoern A. Zeeb 	if (ret < 0)
2086c92544dSBjoern A. Zeeb 		goto error;
2096c92544dSBjoern A. Zeeb 
2106c92544dSBjoern A. Zeeb 	mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
2116c92544dSBjoern A. Zeeb 		    (mt76_rr(dev, MT_HW_REV) & 0xff);
2126c92544dSBjoern A. Zeeb 	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
2136c92544dSBjoern A. Zeeb 
2146c92544dSBjoern A. Zeeb 	if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) {
215cbb3ec25SBjoern A. Zeeb 		ret = mt792xu_wfsys_reset(dev);
2166c92544dSBjoern A. Zeeb 		if (ret)
2176c92544dSBjoern A. Zeeb 			goto error;
2186c92544dSBjoern A. Zeeb 	}
2196c92544dSBjoern A. Zeeb 
220cbb3ec25SBjoern A. Zeeb 	ret = mt792xu_mcu_power_on(dev);
2216c92544dSBjoern A. Zeeb 	if (ret)
2226c92544dSBjoern A. Zeeb 		goto error;
2236c92544dSBjoern A. Zeeb 
2246c92544dSBjoern A. Zeeb 	ret = mt76u_alloc_mcu_queue(&dev->mt76);
2256c92544dSBjoern A. Zeeb 	if (ret)
2266c92544dSBjoern A. Zeeb 		goto error;
2276c92544dSBjoern A. Zeeb 
2286c92544dSBjoern A. Zeeb 	ret = mt76u_alloc_queues(&dev->mt76);
2296c92544dSBjoern A. Zeeb 	if (ret)
2306c92544dSBjoern A. Zeeb 		goto error;
2316c92544dSBjoern A. Zeeb 
232cbb3ec25SBjoern A. Zeeb 	ret = mt792xu_dma_init(dev, false);
2336c92544dSBjoern A. Zeeb 	if (ret)
234cbb3ec25SBjoern A. Zeeb 		goto error;
2356c92544dSBjoern A. Zeeb 
2366c92544dSBjoern A. Zeeb 	hw = mt76_hw(dev);
2376c92544dSBjoern A. Zeeb 	/* check hw sg support in order to enable AMSDU */
2386c92544dSBjoern A. Zeeb 	hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1;
2396c92544dSBjoern A. Zeeb 
2406c92544dSBjoern A. Zeeb 	ret = mt7921_register_device(dev);
2416c92544dSBjoern A. Zeeb 	if (ret)
2426c92544dSBjoern A. Zeeb 		goto error;
2436c92544dSBjoern A. Zeeb 
2446c92544dSBjoern A. Zeeb 	return 0;
2456c92544dSBjoern A. Zeeb 
2466c92544dSBjoern A. Zeeb error:
2476c92544dSBjoern A. Zeeb 	mt76u_queues_deinit(&dev->mt76);
2486c92544dSBjoern A. Zeeb 
2496c92544dSBjoern A. Zeeb 	usb_set_intfdata(usb_intf, NULL);
2506c92544dSBjoern A. Zeeb 	usb_put_dev(interface_to_usbdev(usb_intf));
2516c92544dSBjoern A. Zeeb 
2526c92544dSBjoern A. Zeeb 	mt76_free_device(&dev->mt76);
2536c92544dSBjoern A. Zeeb 
2546c92544dSBjoern A. Zeeb 	return ret;
2556c92544dSBjoern A. Zeeb }
2566c92544dSBjoern A. Zeeb 
2576c92544dSBjoern A. Zeeb #ifdef CONFIG_PM
mt7921u_suspend(struct usb_interface * intf,pm_message_t state)2586c92544dSBjoern A. Zeeb static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
2596c92544dSBjoern A. Zeeb {
260cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = usb_get_intfdata(intf);
2616c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
2626c92544dSBjoern A. Zeeb 	int err;
2636c92544dSBjoern A. Zeeb 
2646c92544dSBjoern A. Zeeb 	pm->suspended = true;
2656c92544dSBjoern A. Zeeb 	flush_work(&dev->reset_work);
2666c92544dSBjoern A. Zeeb 
2676c92544dSBjoern A. Zeeb 	err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
2686c92544dSBjoern A. Zeeb 	if (err)
2696c92544dSBjoern A. Zeeb 		goto failed;
2706c92544dSBjoern A. Zeeb 
2716c92544dSBjoern A. Zeeb 	mt76u_stop_rx(&dev->mt76);
2726c92544dSBjoern A. Zeeb 	mt76u_stop_tx(&dev->mt76);
2736c92544dSBjoern A. Zeeb 
2746c92544dSBjoern A. Zeeb 	return 0;
2756c92544dSBjoern A. Zeeb 
2766c92544dSBjoern A. Zeeb failed:
2776c92544dSBjoern A. Zeeb 	pm->suspended = false;
2786c92544dSBjoern A. Zeeb 
2796c92544dSBjoern A. Zeeb 	if (err < 0)
280cbb3ec25SBjoern A. Zeeb 		mt792x_reset(&dev->mt76);
2816c92544dSBjoern A. Zeeb 
2826c92544dSBjoern A. Zeeb 	return err;
2836c92544dSBjoern A. Zeeb }
2846c92544dSBjoern A. Zeeb 
mt7921u_resume(struct usb_interface * intf)2856c92544dSBjoern A. Zeeb static int mt7921u_resume(struct usb_interface *intf)
2866c92544dSBjoern A. Zeeb {
287cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = usb_get_intfdata(intf);
2886c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
2896c92544dSBjoern A. Zeeb 	bool reinit = true;
2906c92544dSBjoern A. Zeeb 	int err, i;
2916c92544dSBjoern A. Zeeb 
2926c92544dSBjoern A. Zeeb 	for (i = 0; i < 10; i++) {
2936c92544dSBjoern A. Zeeb 		u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT);
2946c92544dSBjoern A. Zeeb 
2956c92544dSBjoern A. Zeeb 		if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) {
2966c92544dSBjoern A. Zeeb 			reinit = false;
2976c92544dSBjoern A. Zeeb 			break;
2986c92544dSBjoern A. Zeeb 		}
2996c92544dSBjoern A. Zeeb 		if (val & MT_WF_SW_SER_DONE_SUSPEND) {
3006c92544dSBjoern A. Zeeb 			mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0);
3016c92544dSBjoern A. Zeeb 			break;
3026c92544dSBjoern A. Zeeb 		}
3036c92544dSBjoern A. Zeeb 
3046c92544dSBjoern A. Zeeb 		msleep(20);
3056c92544dSBjoern A. Zeeb 	}
3066c92544dSBjoern A. Zeeb 
307cbb3ec25SBjoern A. Zeeb 	if (reinit || mt792x_dma_need_reinit(dev)) {
308cbb3ec25SBjoern A. Zeeb 		err = mt792xu_dma_init(dev, true);
3096c92544dSBjoern A. Zeeb 		if (err)
3106c92544dSBjoern A. Zeeb 			goto failed;
3116c92544dSBjoern A. Zeeb 	}
3126c92544dSBjoern A. Zeeb 
3136c92544dSBjoern A. Zeeb 	err = mt76u_resume_rx(&dev->mt76);
3146c92544dSBjoern A. Zeeb 	if (err < 0)
3156c92544dSBjoern A. Zeeb 		goto failed;
3166c92544dSBjoern A. Zeeb 
3176c92544dSBjoern A. Zeeb 	err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
3186c92544dSBjoern A. Zeeb failed:
3196c92544dSBjoern A. Zeeb 	pm->suspended = false;
3206c92544dSBjoern A. Zeeb 
3216c92544dSBjoern A. Zeeb 	if (err < 0)
322cbb3ec25SBjoern A. Zeeb 		mt792x_reset(&dev->mt76);
3236c92544dSBjoern A. Zeeb 
3246c92544dSBjoern A. Zeeb 	return err;
3256c92544dSBjoern A. Zeeb }
3266c92544dSBjoern A. Zeeb #endif /* CONFIG_PM */
3276c92544dSBjoern A. Zeeb 
3286c92544dSBjoern A. Zeeb MODULE_DEVICE_TABLE(usb, mt7921u_device_table);
3296c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
3306c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7921_ROM_PATCH);
3316c92544dSBjoern A. Zeeb 
3326c92544dSBjoern A. Zeeb static struct usb_driver mt7921u_driver = {
3336c92544dSBjoern A. Zeeb 	.name		= KBUILD_MODNAME,
3346c92544dSBjoern A. Zeeb 	.id_table	= mt7921u_device_table,
3356c92544dSBjoern A. Zeeb 	.probe		= mt7921u_probe,
336cbb3ec25SBjoern A. Zeeb 	.disconnect	= mt792xu_disconnect,
3376c92544dSBjoern A. Zeeb #ifdef CONFIG_PM
3386c92544dSBjoern A. Zeeb 	.suspend	= mt7921u_suspend,
3396c92544dSBjoern A. Zeeb 	.resume		= mt7921u_resume,
3406c92544dSBjoern A. Zeeb 	.reset_resume	= mt7921u_resume,
3416c92544dSBjoern A. Zeeb #endif /* CONFIG_PM */
3426c92544dSBjoern A. Zeeb 	.soft_unbind	= 1,
3436c92544dSBjoern A. Zeeb 	.disable_hub_initiated_lpm = 1,
3446c92544dSBjoern A. Zeeb };
3456c92544dSBjoern A. Zeeb module_usb_driver(mt7921u_driver);
3466c92544dSBjoern A. Zeeb 
3476c92544dSBjoern A. Zeeb MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
3486c92544dSBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
349