xref: /openbmc/linux/drivers/net/wireless/mediatek/mt76/mt7921/usb.c (revision 360823a09426347ea8f232b0b0b5156d0aed0302)
10d2afe09SLorenzo Bianconi // SPDX-License-Identifier: ISC
20d2afe09SLorenzo Bianconi /* Copyright (C) 2022 MediaTek Inc.
30d2afe09SLorenzo Bianconi  *
40d2afe09SLorenzo Bianconi  * Author: Lorenzo Bianconi <lorenzo@kernel.org>
50d2afe09SLorenzo Bianconi  */
60d2afe09SLorenzo Bianconi 
70d2afe09SLorenzo Bianconi #include <linux/kernel.h>
80d2afe09SLorenzo Bianconi #include <linux/module.h>
90d2afe09SLorenzo Bianconi #include <linux/usb.h>
100d2afe09SLorenzo Bianconi 
110d2afe09SLorenzo Bianconi #include "mt7921.h"
120d2afe09SLorenzo Bianconi #include "mcu.h"
13140efef3SLorenzo Bianconi #include "../mt76_connac2_mac.h"
140d2afe09SLorenzo Bianconi 
150d2afe09SLorenzo Bianconi static const struct usb_device_id mt7921u_device_table[] = {
16034ae28bSSean Wang 	{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff),
17034ae28bSSean Wang 		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
18e766b7fdSChuanhong Guo 	/* Comfast CF-952AX */
19e766b7fdSChuanhong Guo 	{ USB_DEVICE_AND_INTERFACE_INFO(0x3574, 0x6211, 0xff, 0xff, 0xff),
20e766b7fdSChuanhong Guo 		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
2103eb52ddSReese Russell 	/* Netgear, Inc. [A8000,AXE3000] */
2203eb52ddSReese Russell 	{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9060, 0xff, 0xff, 0xff),
2303eb52ddSReese Russell 		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
24*7b279f96SNick Morrow 	/* TP-Link TXE50UH */
25*7b279f96SNick Morrow 	{ USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0107, 0xff, 0xff, 0xff),
26*7b279f96SNick Morrow 		.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
270d2afe09SLorenzo Bianconi 	{ },
280d2afe09SLorenzo Bianconi };
290d2afe09SLorenzo Bianconi 
300d2afe09SLorenzo Bianconi static int
mt7921u_mcu_send_message(struct mt76_dev * mdev,struct sk_buff * skb,int cmd,int * seq)310d2afe09SLorenzo Bianconi mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
320d2afe09SLorenzo Bianconi 			 int cmd, int *seq)
330d2afe09SLorenzo Bianconi {
34975e122dSLorenzo Bianconi 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
350d2afe09SLorenzo Bianconi 	u32 pad, ep;
360d2afe09SLorenzo Bianconi 	int ret;
370d2afe09SLorenzo Bianconi 
38d2f5c8edSLorenzo Bianconi 	ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq);
390d2afe09SLorenzo Bianconi 	if (ret)
400d2afe09SLorenzo Bianconi 		return ret;
410d2afe09SLorenzo Bianconi 
42d2f5c8edSLorenzo Bianconi 	mdev->mcu.timeout = 3 * HZ;
43d2f5c8edSLorenzo Bianconi 
440d2afe09SLorenzo Bianconi 	if (cmd != MCU_CMD(FW_SCATTER))
450d2afe09SLorenzo Bianconi 		ep = MT_EP_OUT_INBAND_CMD;
460d2afe09SLorenzo Bianconi 	else
470d2afe09SLorenzo Bianconi 		ep = MT_EP_OUT_AC_BE;
480d2afe09SLorenzo Bianconi 
490d2afe09SLorenzo Bianconi 	mt7921_skb_add_usb_sdio_hdr(dev, skb, 0);
500d2afe09SLorenzo Bianconi 	pad = round_up(skb->len, 4) + 4 - skb->len;
510d2afe09SLorenzo Bianconi 	__skb_put_zero(skb, pad);
520d2afe09SLorenzo Bianconi 
530d2afe09SLorenzo Bianconi 	ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,
540d2afe09SLorenzo Bianconi 			     1000, ep);
550d2afe09SLorenzo Bianconi 	dev_kfree_skb(skb);
560d2afe09SLorenzo Bianconi 
570d2afe09SLorenzo Bianconi 	return ret;
580d2afe09SLorenzo Bianconi }
590d2afe09SLorenzo Bianconi 
mt7921u_mcu_init(struct mt792x_dev * dev)60975e122dSLorenzo Bianconi static int mt7921u_mcu_init(struct mt792x_dev *dev)
610d2afe09SLorenzo Bianconi {
620d2afe09SLorenzo Bianconi 	static const struct mt76_mcu_ops mcu_ops = {
63fc6ee71aSLorenzo Bianconi 		.headroom = MT_SDIO_HDR_SIZE +
64fc6ee71aSLorenzo Bianconi 			    sizeof(struct mt76_connac2_mcu_txd),
650d2afe09SLorenzo Bianconi 		.tailroom = MT_USB_TAIL_SIZE,
660d2afe09SLorenzo Bianconi 		.mcu_skb_send_msg = mt7921u_mcu_send_message,
670d2afe09SLorenzo Bianconi 		.mcu_parse_response = mt7921_mcu_parse_response,
680d2afe09SLorenzo Bianconi 	};
690d2afe09SLorenzo Bianconi 	int ret;
700d2afe09SLorenzo Bianconi 
710d2afe09SLorenzo Bianconi 	dev->mt76.mcu_ops = &mcu_ops;
720d2afe09SLorenzo Bianconi 
730d2afe09SLorenzo Bianconi 	mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
740d2afe09SLorenzo Bianconi 	ret = mt7921_run_firmware(dev);
750d2afe09SLorenzo Bianconi 	if (ret)
760d2afe09SLorenzo Bianconi 		return ret;
770d2afe09SLorenzo Bianconi 
780d2afe09SLorenzo Bianconi 	set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
790d2afe09SLorenzo Bianconi 	mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
800d2afe09SLorenzo Bianconi 
810d2afe09SLorenzo Bianconi 	return 0;
820d2afe09SLorenzo Bianconi }
830d2afe09SLorenzo Bianconi 
mt7921u_mac_reset(struct mt792x_dev * dev)84d28e1a48SLorenzo Bianconi static int mt7921u_mac_reset(struct mt792x_dev *dev)
85d28e1a48SLorenzo Bianconi {
86d28e1a48SLorenzo Bianconi 	int err;
87d28e1a48SLorenzo Bianconi 
88d28e1a48SLorenzo Bianconi 	mt76_txq_schedule_all(&dev->mphy);
89d28e1a48SLorenzo Bianconi 	mt76_worker_disable(&dev->mt76.tx_worker);
90d28e1a48SLorenzo Bianconi 
91d28e1a48SLorenzo Bianconi 	set_bit(MT76_RESET, &dev->mphy.state);
92d28e1a48SLorenzo Bianconi 	set_bit(MT76_MCU_RESET, &dev->mphy.state);
93d28e1a48SLorenzo Bianconi 
94d28e1a48SLorenzo Bianconi 	wake_up(&dev->mt76.mcu.wait);
95d28e1a48SLorenzo Bianconi 	skb_queue_purge(&dev->mt76.mcu.res_q);
96d28e1a48SLorenzo Bianconi 
97d28e1a48SLorenzo Bianconi 	mt76u_stop_rx(&dev->mt76);
98d28e1a48SLorenzo Bianconi 	mt76u_stop_tx(&dev->mt76);
99d28e1a48SLorenzo Bianconi 
100d28e1a48SLorenzo Bianconi 	mt792xu_wfsys_reset(dev);
101d28e1a48SLorenzo Bianconi 
102d28e1a48SLorenzo Bianconi 	clear_bit(MT76_MCU_RESET, &dev->mphy.state);
103d28e1a48SLorenzo Bianconi 	err = mt76u_resume_rx(&dev->mt76);
104d28e1a48SLorenzo Bianconi 	if (err)
105d28e1a48SLorenzo Bianconi 		goto out;
106d28e1a48SLorenzo Bianconi 
107d28e1a48SLorenzo Bianconi 	err = mt792xu_mcu_power_on(dev);
108d28e1a48SLorenzo Bianconi 	if (err)
109d28e1a48SLorenzo Bianconi 		goto out;
110d28e1a48SLorenzo Bianconi 
111d28e1a48SLorenzo Bianconi 	err = mt792xu_dma_init(dev, false);
112d28e1a48SLorenzo Bianconi 	if (err)
113d28e1a48SLorenzo Bianconi 		goto out;
114d28e1a48SLorenzo Bianconi 
115d28e1a48SLorenzo Bianconi 	mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
116d28e1a48SLorenzo Bianconi 	mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
117d28e1a48SLorenzo Bianconi 
118d28e1a48SLorenzo Bianconi 	err = mt7921_run_firmware(dev);
119d28e1a48SLorenzo Bianconi 	if (err)
120d28e1a48SLorenzo Bianconi 		goto out;
121d28e1a48SLorenzo Bianconi 
122d28e1a48SLorenzo Bianconi 	mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
123d28e1a48SLorenzo Bianconi 
124d28e1a48SLorenzo Bianconi 	err = mt7921_mcu_set_eeprom(dev);
125d28e1a48SLorenzo Bianconi 	if (err)
126d28e1a48SLorenzo Bianconi 		goto out;
127d28e1a48SLorenzo Bianconi 
128d28e1a48SLorenzo Bianconi 	err = mt7921_mac_init(dev);
129d28e1a48SLorenzo Bianconi 	if (err)
130d28e1a48SLorenzo Bianconi 		goto out;
131d28e1a48SLorenzo Bianconi 
132d28e1a48SLorenzo Bianconi 	err = __mt7921_start(&dev->phy);
133d28e1a48SLorenzo Bianconi out:
134d28e1a48SLorenzo Bianconi 	clear_bit(MT76_RESET, &dev->mphy.state);
135d28e1a48SLorenzo Bianconi 
136d28e1a48SLorenzo Bianconi 	mt76_worker_enable(&dev->mt76.tx_worker);
137d28e1a48SLorenzo Bianconi 
138d28e1a48SLorenzo Bianconi 	return err;
139d28e1a48SLorenzo Bianconi }
140d28e1a48SLorenzo Bianconi 
mt7921u_stop(struct ieee80211_hw * hw)1410d2afe09SLorenzo Bianconi static void mt7921u_stop(struct ieee80211_hw *hw)
1420d2afe09SLorenzo Bianconi {
14320249e1aSLorenzo Bianconi 	struct mt792x_dev *dev = mt792x_hw_dev(hw);
1440d2afe09SLorenzo Bianconi 
1450d2afe09SLorenzo Bianconi 	mt76u_stop_tx(&dev->mt76);
1460d2afe09SLorenzo Bianconi 	mt7921_stop(hw);
1470d2afe09SLorenzo Bianconi }
1480d2afe09SLorenzo Bianconi 
mt7921u_probe(struct usb_interface * usb_intf,const struct usb_device_id * id)1490d2afe09SLorenzo Bianconi static int mt7921u_probe(struct usb_interface *usb_intf,
1500d2afe09SLorenzo Bianconi 			 const struct usb_device_id *id)
1510d2afe09SLorenzo Bianconi {
1520d2afe09SLorenzo Bianconi 	static const struct mt76_driver_ops drv_ops = {
1530d2afe09SLorenzo Bianconi 		.txwi_size = MT_SDIO_TXD_SIZE,
1545b0fb852SBen Greear 		.drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ |
1555b0fb852SBen Greear 			     MT_DRV_AMSDU_OFFLOAD,
1560d2afe09SLorenzo Bianconi 		.survey_flags = SURVEY_INFO_TIME_TX |
1570d2afe09SLorenzo Bianconi 				SURVEY_INFO_TIME_RX |
1580d2afe09SLorenzo Bianconi 				SURVEY_INFO_TIME_BSS_RX,
1590d2afe09SLorenzo Bianconi 		.tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb,
1600d2afe09SLorenzo Bianconi 		.tx_complete_skb = mt7921_usb_sdio_tx_complete_skb,
1610d2afe09SLorenzo Bianconi 		.tx_status_data = mt7921_usb_sdio_tx_status_data,
1620d2afe09SLorenzo Bianconi 		.rx_skb = mt7921_queue_rx_skb,
16312d7440eSLorenzo Bianconi 		.rx_check = mt7921_rx_check,
1640d2afe09SLorenzo Bianconi 		.sta_add = mt7921_mac_sta_add,
1650d2afe09SLorenzo Bianconi 		.sta_assoc = mt7921_mac_sta_assoc,
1660d2afe09SLorenzo Bianconi 		.sta_remove = mt7921_mac_sta_remove,
167311f121cSLorenzo Bianconi 		.update_survey = mt792x_update_channel,
1680d2afe09SLorenzo Bianconi 	};
169838cc667SLorenzo Bianconi 	static const struct mt792x_hif_ops hif_ops = {
1700d2afe09SLorenzo Bianconi 		.mcu_init = mt7921u_mcu_init,
171d28e1a48SLorenzo Bianconi 		.init_reset = mt792xu_init_reset,
1720d2afe09SLorenzo Bianconi 		.reset = mt7921u_mac_reset,
1730d2afe09SLorenzo Bianconi 	};
1740d2afe09SLorenzo Bianconi 	static struct mt76_bus_ops bus_ops = {
175d28e1a48SLorenzo Bianconi 		.rr = mt792xu_rr,
176d28e1a48SLorenzo Bianconi 		.wr = mt792xu_wr,
177d28e1a48SLorenzo Bianconi 		.rmw = mt792xu_rmw,
1780d2afe09SLorenzo Bianconi 		.read_copy = mt76u_read_copy,
179d28e1a48SLorenzo Bianconi 		.write_copy = mt792xu_copy,
1800d2afe09SLorenzo Bianconi 		.type = MT76_BUS_USB,
1810d2afe09SLorenzo Bianconi 	};
1820d2afe09SLorenzo Bianconi 	struct usb_device *udev = interface_to_usbdev(usb_intf);
1830d2afe09SLorenzo Bianconi 	struct ieee80211_ops *ops;
1840d2afe09SLorenzo Bianconi 	struct ieee80211_hw *hw;
185975e122dSLorenzo Bianconi 	struct mt792x_dev *dev;
1860d2afe09SLorenzo Bianconi 	struct mt76_dev *mdev;
187034ae28bSSean Wang 	u8 features;
1880d2afe09SLorenzo Bianconi 	int ret;
1890d2afe09SLorenzo Bianconi 
190e8a264ccSLorenzo Bianconi 	ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7921_ops,
191e8a264ccSLorenzo Bianconi 				      (void *)id->driver_info, &features);
1920d2afe09SLorenzo Bianconi 	if (!ops)
1930d2afe09SLorenzo Bianconi 		return -ENOMEM;
1940d2afe09SLorenzo Bianconi 
1950d2afe09SLorenzo Bianconi 	ops->stop = mt7921u_stop;
1960d2afe09SLorenzo Bianconi 	mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
1970d2afe09SLorenzo Bianconi 	if (!mdev)
1980d2afe09SLorenzo Bianconi 		return -ENOMEM;
1990d2afe09SLorenzo Bianconi 
200975e122dSLorenzo Bianconi 	dev = container_of(mdev, struct mt792x_dev, mt76);
201034ae28bSSean Wang 	dev->fw_features = features;
2020d2afe09SLorenzo Bianconi 	dev->hif_ops = &hif_ops;
2030d2afe09SLorenzo Bianconi 
2040d2afe09SLorenzo Bianconi 	udev = usb_get_dev(udev);
2050d2afe09SLorenzo Bianconi 	usb_reset_device(udev);
2060d2afe09SLorenzo Bianconi 
2070d2afe09SLorenzo Bianconi 	usb_set_intfdata(usb_intf, dev);
2080d2afe09SLorenzo Bianconi 
2090d2afe09SLorenzo Bianconi 	ret = __mt76u_init(mdev, usb_intf, &bus_ops);
2100d2afe09SLorenzo Bianconi 	if (ret < 0)
2110d2afe09SLorenzo Bianconi 		goto error;
2120d2afe09SLorenzo Bianconi 
2130d2afe09SLorenzo Bianconi 	mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
2140d2afe09SLorenzo Bianconi 		    (mt76_rr(dev, MT_HW_REV) & 0xff);
2150d2afe09SLorenzo Bianconi 	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
2160d2afe09SLorenzo Bianconi 
2170d2afe09SLorenzo Bianconi 	if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) {
218d28e1a48SLorenzo Bianconi 		ret = mt792xu_wfsys_reset(dev);
2190d2afe09SLorenzo Bianconi 		if (ret)
2200d2afe09SLorenzo Bianconi 			goto error;
2210d2afe09SLorenzo Bianconi 	}
2220d2afe09SLorenzo Bianconi 
223d28e1a48SLorenzo Bianconi 	ret = mt792xu_mcu_power_on(dev);
2240d2afe09SLorenzo Bianconi 	if (ret)
2250d2afe09SLorenzo Bianconi 		goto error;
2260d2afe09SLorenzo Bianconi 
2270d2afe09SLorenzo Bianconi 	ret = mt76u_alloc_mcu_queue(&dev->mt76);
2280d2afe09SLorenzo Bianconi 	if (ret)
2290d2afe09SLorenzo Bianconi 		goto error;
2300d2afe09SLorenzo Bianconi 
2310d2afe09SLorenzo Bianconi 	ret = mt76u_alloc_queues(&dev->mt76);
2320d2afe09SLorenzo Bianconi 	if (ret)
2330d2afe09SLorenzo Bianconi 		goto error;
2340d2afe09SLorenzo Bianconi 
235d28e1a48SLorenzo Bianconi 	ret = mt792xu_dma_init(dev, false);
2360d2afe09SLorenzo Bianconi 	if (ret)
2375c47cdebSJiefeng Li 		goto error;
2380d2afe09SLorenzo Bianconi 
2390d2afe09SLorenzo Bianconi 	hw = mt76_hw(dev);
2400d2afe09SLorenzo Bianconi 	/* check hw sg support in order to enable AMSDU */
2410d2afe09SLorenzo Bianconi 	hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1;
2420d2afe09SLorenzo Bianconi 
2430d2afe09SLorenzo Bianconi 	ret = mt7921_register_device(dev);
2440d2afe09SLorenzo Bianconi 	if (ret)
2450d2afe09SLorenzo Bianconi 		goto error;
2460d2afe09SLorenzo Bianconi 
2470d2afe09SLorenzo Bianconi 	return 0;
2480d2afe09SLorenzo Bianconi 
2490d2afe09SLorenzo Bianconi error:
2500d2afe09SLorenzo Bianconi 	mt76u_queues_deinit(&dev->mt76);
2510d2afe09SLorenzo Bianconi 
2520d2afe09SLorenzo Bianconi 	usb_set_intfdata(usb_intf, NULL);
2530d2afe09SLorenzo Bianconi 	usb_put_dev(interface_to_usbdev(usb_intf));
2540d2afe09SLorenzo Bianconi 
2550d2afe09SLorenzo Bianconi 	mt76_free_device(&dev->mt76);
2560d2afe09SLorenzo Bianconi 
2570d2afe09SLorenzo Bianconi 	return ret;
2580d2afe09SLorenzo Bianconi }
2590d2afe09SLorenzo Bianconi 
260df3e4143SLorenzo Bianconi #ifdef CONFIG_PM
mt7921u_suspend(struct usb_interface * intf,pm_message_t state)261df3e4143SLorenzo Bianconi static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
262df3e4143SLorenzo Bianconi {
263975e122dSLorenzo Bianconi 	struct mt792x_dev *dev = usb_get_intfdata(intf);
26486f15d04SSean Wang 	struct mt76_connac_pm *pm = &dev->pm;
265df3e4143SLorenzo Bianconi 	int err;
266df3e4143SLorenzo Bianconi 
26786f15d04SSean Wang 	pm->suspended = true;
26886f15d04SSean Wang 	flush_work(&dev->reset_work);
26986f15d04SSean Wang 
270df3e4143SLorenzo Bianconi 	err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
271df3e4143SLorenzo Bianconi 	if (err)
27286f15d04SSean Wang 		goto failed;
273df3e4143SLorenzo Bianconi 
274df3e4143SLorenzo Bianconi 	mt76u_stop_rx(&dev->mt76);
275df3e4143SLorenzo Bianconi 	mt76u_stop_tx(&dev->mt76);
276df3e4143SLorenzo Bianconi 
277df3e4143SLorenzo Bianconi 	return 0;
27886f15d04SSean Wang 
27986f15d04SSean Wang failed:
28086f15d04SSean Wang 	pm->suspended = false;
28186f15d04SSean Wang 
28286f15d04SSean Wang 	if (err < 0)
283311f121cSLorenzo Bianconi 		mt792x_reset(&dev->mt76);
28486f15d04SSean Wang 
28586f15d04SSean Wang 	return err;
286df3e4143SLorenzo Bianconi }
287df3e4143SLorenzo Bianconi 
mt7921u_resume(struct usb_interface * intf)288df3e4143SLorenzo Bianconi static int mt7921u_resume(struct usb_interface *intf)
289df3e4143SLorenzo Bianconi {
290975e122dSLorenzo Bianconi 	struct mt792x_dev *dev = usb_get_intfdata(intf);
29186f15d04SSean Wang 	struct mt76_connac_pm *pm = &dev->pm;
292df3e4143SLorenzo Bianconi 	bool reinit = true;
293df3e4143SLorenzo Bianconi 	int err, i;
294df3e4143SLorenzo Bianconi 
295df3e4143SLorenzo Bianconi 	for (i = 0; i < 10; i++) {
296df3e4143SLorenzo Bianconi 		u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT);
297df3e4143SLorenzo Bianconi 
298df3e4143SLorenzo Bianconi 		if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) {
299df3e4143SLorenzo Bianconi 			reinit = false;
300df3e4143SLorenzo Bianconi 			break;
301df3e4143SLorenzo Bianconi 		}
302df3e4143SLorenzo Bianconi 		if (val & MT_WF_SW_SER_DONE_SUSPEND) {
303df3e4143SLorenzo Bianconi 			mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0);
304df3e4143SLorenzo Bianconi 			break;
305df3e4143SLorenzo Bianconi 		}
306df3e4143SLorenzo Bianconi 
307df3e4143SLorenzo Bianconi 		msleep(20);
308df3e4143SLorenzo Bianconi 	}
309df3e4143SLorenzo Bianconi 
310c693f2f0SLorenzo Bianconi 	if (reinit || mt792x_dma_need_reinit(dev)) {
311d28e1a48SLorenzo Bianconi 		err = mt792xu_dma_init(dev, true);
312df3e4143SLorenzo Bianconi 		if (err)
31386f15d04SSean Wang 			goto failed;
314df3e4143SLorenzo Bianconi 	}
315df3e4143SLorenzo Bianconi 
316df3e4143SLorenzo Bianconi 	err = mt76u_resume_rx(&dev->mt76);
317df3e4143SLorenzo Bianconi 	if (err < 0)
31886f15d04SSean Wang 		goto failed;
319df3e4143SLorenzo Bianconi 
32086f15d04SSean Wang 	err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
32186f15d04SSean Wang failed:
32286f15d04SSean Wang 	pm->suspended = false;
32386f15d04SSean Wang 
32486f15d04SSean Wang 	if (err < 0)
325311f121cSLorenzo Bianconi 		mt792x_reset(&dev->mt76);
32686f15d04SSean Wang 
32786f15d04SSean Wang 	return err;
328df3e4143SLorenzo Bianconi }
329df3e4143SLorenzo Bianconi #endif /* CONFIG_PM */
330df3e4143SLorenzo Bianconi 
3310d2afe09SLorenzo Bianconi MODULE_DEVICE_TABLE(usb, mt7921u_device_table);
3320d2afe09SLorenzo Bianconi MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
3330d2afe09SLorenzo Bianconi MODULE_FIRMWARE(MT7921_ROM_PATCH);
3340d2afe09SLorenzo Bianconi 
3350d2afe09SLorenzo Bianconi static struct usb_driver mt7921u_driver = {
3360d2afe09SLorenzo Bianconi 	.name		= KBUILD_MODNAME,
3370d2afe09SLorenzo Bianconi 	.id_table	= mt7921u_device_table,
3380d2afe09SLorenzo Bianconi 	.probe		= mt7921u_probe,
339fc80731bSLorenzo Bianconi 	.disconnect	= mt792xu_disconnect,
340df3e4143SLorenzo Bianconi #ifdef CONFIG_PM
341df3e4143SLorenzo Bianconi 	.suspend	= mt7921u_suspend,
342df3e4143SLorenzo Bianconi 	.resume		= mt7921u_resume,
343df3e4143SLorenzo Bianconi 	.reset_resume	= mt7921u_resume,
344df3e4143SLorenzo Bianconi #endif /* CONFIG_PM */
3450d2afe09SLorenzo Bianconi 	.soft_unbind	= 1,
3460d2afe09SLorenzo Bianconi 	.disable_hub_initiated_lpm = 1,
3470d2afe09SLorenzo Bianconi };
3480d2afe09SLorenzo Bianconi module_usb_driver(mt7921u_driver);
3490d2afe09SLorenzo Bianconi 
3500d2afe09SLorenzo Bianconi MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
3510d2afe09SLorenzo Bianconi MODULE_LICENSE("Dual BSD/GPL");
352