xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt792x_usb.c (revision 8ba4d145d351db26e07695b8e90697398c5dfec2)
1cbb3ec25SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2cbb3ec25SBjoern A. Zeeb /* Copyright (C) 2023 MediaTek Inc.
3cbb3ec25SBjoern A. Zeeb  *
4cbb3ec25SBjoern A. Zeeb  * Author: Lorenzo Bianconi <lorenzo@kernel.org>
5cbb3ec25SBjoern A. Zeeb  */
6cbb3ec25SBjoern A. Zeeb 
7cbb3ec25SBjoern A. Zeeb #include <linux/kernel.h>
8cbb3ec25SBjoern A. Zeeb #include <linux/module.h>
9cbb3ec25SBjoern A. Zeeb #include <linux/usb.h>
10cbb3ec25SBjoern A. Zeeb 
11cbb3ec25SBjoern A. Zeeb #include "mt792x.h"
12cbb3ec25SBjoern A. Zeeb #include "mt76_connac2_mac.h"
13cbb3ec25SBjoern A. Zeeb 
mt792xu_rr(struct mt76_dev * dev,u32 addr)14cbb3ec25SBjoern A. Zeeb u32 mt792xu_rr(struct mt76_dev *dev, u32 addr)
15cbb3ec25SBjoern A. Zeeb {
16cbb3ec25SBjoern A. Zeeb 	u32 ret;
17cbb3ec25SBjoern A. Zeeb 
18cbb3ec25SBjoern A. Zeeb 	mutex_lock(&dev->usb.usb_ctrl_mtx);
19cbb3ec25SBjoern A. Zeeb 	ret = ___mt76u_rr(dev, MT_VEND_READ_EXT,
20cbb3ec25SBjoern A. Zeeb 			  USB_DIR_IN | MT_USB_TYPE_VENDOR, addr);
21cbb3ec25SBjoern A. Zeeb 	mutex_unlock(&dev->usb.usb_ctrl_mtx);
22cbb3ec25SBjoern A. Zeeb 
23cbb3ec25SBjoern A. Zeeb 	return ret;
24cbb3ec25SBjoern A. Zeeb }
25cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_rr);
26cbb3ec25SBjoern A. Zeeb 
mt792xu_wr(struct mt76_dev * dev,u32 addr,u32 val)27cbb3ec25SBjoern A. Zeeb void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val)
28cbb3ec25SBjoern A. Zeeb {
29cbb3ec25SBjoern A. Zeeb 	mutex_lock(&dev->usb.usb_ctrl_mtx);
30cbb3ec25SBjoern A. Zeeb 	___mt76u_wr(dev, MT_VEND_WRITE_EXT,
31cbb3ec25SBjoern A. Zeeb 		    USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
32cbb3ec25SBjoern A. Zeeb 	mutex_unlock(&dev->usb.usb_ctrl_mtx);
33cbb3ec25SBjoern A. Zeeb }
34cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_wr);
35cbb3ec25SBjoern A. Zeeb 
mt792xu_rmw(struct mt76_dev * dev,u32 addr,u32 mask,u32 val)36cbb3ec25SBjoern A. Zeeb u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val)
37cbb3ec25SBjoern A. Zeeb {
38cbb3ec25SBjoern A. Zeeb 	mutex_lock(&dev->usb.usb_ctrl_mtx);
39cbb3ec25SBjoern A. Zeeb 	val |= ___mt76u_rr(dev, MT_VEND_READ_EXT,
40cbb3ec25SBjoern A. Zeeb 			   USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask;
41cbb3ec25SBjoern A. Zeeb 	___mt76u_wr(dev, MT_VEND_WRITE_EXT,
42cbb3ec25SBjoern A. Zeeb 		    USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
43cbb3ec25SBjoern A. Zeeb 	mutex_unlock(&dev->usb.usb_ctrl_mtx);
44cbb3ec25SBjoern A. Zeeb 
45cbb3ec25SBjoern A. Zeeb 	return val;
46cbb3ec25SBjoern A. Zeeb }
47cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_rmw);
48cbb3ec25SBjoern A. Zeeb 
mt792xu_copy(struct mt76_dev * dev,u32 offset,const void * data,int len)49cbb3ec25SBjoern A. Zeeb void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len)
50cbb3ec25SBjoern A. Zeeb {
51cbb3ec25SBjoern A. Zeeb 	struct mt76_usb *usb = &dev->usb;
52cbb3ec25SBjoern A. Zeeb 	int ret, i = 0, batch_len;
53cbb3ec25SBjoern A. Zeeb 	const u8 *val = data;
54cbb3ec25SBjoern A. Zeeb 
55cbb3ec25SBjoern A. Zeeb 	len = round_up(len, 4);
56cbb3ec25SBjoern A. Zeeb 
57cbb3ec25SBjoern A. Zeeb 	mutex_lock(&usb->usb_ctrl_mtx);
58cbb3ec25SBjoern A. Zeeb 	while (i < len) {
59cbb3ec25SBjoern A. Zeeb 		batch_len = min_t(int, usb->data_len, len - i);
60cbb3ec25SBjoern A. Zeeb 		memcpy(usb->data, val + i, batch_len);
61cbb3ec25SBjoern A. Zeeb 		ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,
62cbb3ec25SBjoern A. Zeeb 					     USB_DIR_OUT | MT_USB_TYPE_VENDOR,
63cbb3ec25SBjoern A. Zeeb 					     (offset + i) >> 16, offset + i,
64cbb3ec25SBjoern A. Zeeb 					     usb->data, batch_len);
65cbb3ec25SBjoern A. Zeeb 		if (ret < 0)
66cbb3ec25SBjoern A. Zeeb 			break;
67cbb3ec25SBjoern A. Zeeb 
68cbb3ec25SBjoern A. Zeeb 		i += batch_len;
69cbb3ec25SBjoern A. Zeeb 	}
70cbb3ec25SBjoern A. Zeeb 	mutex_unlock(&usb->usb_ctrl_mtx);
71cbb3ec25SBjoern A. Zeeb }
72cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_copy);
73cbb3ec25SBjoern A. Zeeb 
mt792xu_mcu_power_on(struct mt792x_dev * dev)74cbb3ec25SBjoern A. Zeeb int mt792xu_mcu_power_on(struct mt792x_dev *dev)
75cbb3ec25SBjoern A. Zeeb {
76cbb3ec25SBjoern A. Zeeb 	int ret;
77cbb3ec25SBjoern A. Zeeb 
78cbb3ec25SBjoern A. Zeeb 	ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
79cbb3ec25SBjoern A. Zeeb 				   USB_DIR_OUT | MT_USB_TYPE_VENDOR,
80cbb3ec25SBjoern A. Zeeb 				   0x0, 0x1, NULL, 0);
81cbb3ec25SBjoern A. Zeeb 	if (ret)
82cbb3ec25SBjoern A. Zeeb 		return ret;
83cbb3ec25SBjoern A. Zeeb 
84cbb3ec25SBjoern A. Zeeb 	if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
85cbb3ec25SBjoern A. Zeeb 			    MT_TOP_MISC2_FW_PWR_ON, 500)) {
86cbb3ec25SBjoern A. Zeeb 		dev_err(dev->mt76.dev, "Timeout for power on\n");
87cbb3ec25SBjoern A. Zeeb 		ret = -EIO;
88cbb3ec25SBjoern A. Zeeb 	}
89cbb3ec25SBjoern A. Zeeb 
90cbb3ec25SBjoern A. Zeeb 	return ret;
91cbb3ec25SBjoern A. Zeeb }
92cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_mcu_power_on);
93cbb3ec25SBjoern A. Zeeb 
mt792xu_cleanup(struct mt792x_dev * dev)94cbb3ec25SBjoern A. Zeeb static void mt792xu_cleanup(struct mt792x_dev *dev)
95cbb3ec25SBjoern A. Zeeb {
96cbb3ec25SBjoern A. Zeeb 	clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
97cbb3ec25SBjoern A. Zeeb 	mt792xu_wfsys_reset(dev);
98cbb3ec25SBjoern A. Zeeb 	skb_queue_purge(&dev->mt76.mcu.res_q);
99cbb3ec25SBjoern A. Zeeb 	mt76u_queues_deinit(&dev->mt76);
100cbb3ec25SBjoern A. Zeeb }
101cbb3ec25SBjoern A. Zeeb 
mt792xu_uhw_rr(struct mt76_dev * dev,u32 addr)102cbb3ec25SBjoern A. Zeeb static u32 mt792xu_uhw_rr(struct mt76_dev *dev, u32 addr)
103cbb3ec25SBjoern A. Zeeb {
104cbb3ec25SBjoern A. Zeeb 	u32 ret;
105cbb3ec25SBjoern A. Zeeb 
106cbb3ec25SBjoern A. Zeeb 	mutex_lock(&dev->usb.usb_ctrl_mtx);
107cbb3ec25SBjoern A. Zeeb 	ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE,
108cbb3ec25SBjoern A. Zeeb 			  USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr);
109cbb3ec25SBjoern A. Zeeb 	mutex_unlock(&dev->usb.usb_ctrl_mtx);
110cbb3ec25SBjoern A. Zeeb 
111cbb3ec25SBjoern A. Zeeb 	return ret;
112cbb3ec25SBjoern A. Zeeb }
113cbb3ec25SBjoern A. Zeeb 
mt792xu_uhw_wr(struct mt76_dev * dev,u32 addr,u32 val)114cbb3ec25SBjoern A. Zeeb static void mt792xu_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val)
115cbb3ec25SBjoern A. Zeeb {
116cbb3ec25SBjoern A. Zeeb 	mutex_lock(&dev->usb.usb_ctrl_mtx);
117cbb3ec25SBjoern A. Zeeb 	___mt76u_wr(dev, MT_VEND_WRITE,
118cbb3ec25SBjoern A. Zeeb 		    USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val);
119cbb3ec25SBjoern A. Zeeb 	mutex_unlock(&dev->usb.usb_ctrl_mtx);
120cbb3ec25SBjoern A. Zeeb }
121cbb3ec25SBjoern A. Zeeb 
mt792xu_dma_prefetch(struct mt792x_dev * dev)122cbb3ec25SBjoern A. Zeeb static void mt792xu_dma_prefetch(struct mt792x_dev *dev)
123cbb3ec25SBjoern A. Zeeb {
124*8ba4d145SBjoern A. Zeeb #define DMA_PREFETCH_CONF(_idx_, _cnt_, _base_) \
125*8ba4d145SBjoern A. Zeeb 	mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL((_idx_)), \
126*8ba4d145SBjoern A. Zeeb 		 MT_WPDMA0_MAX_CNT_MASK | MT_WPDMA0_BASE_PTR_MASK, \
127*8ba4d145SBjoern A. Zeeb 		 FIELD_PREP(MT_WPDMA0_MAX_CNT_MASK, (_cnt_)) | \
128*8ba4d145SBjoern A. Zeeb 		 FIELD_PREP(MT_WPDMA0_BASE_PTR_MASK, (_base_)))
129cbb3ec25SBjoern A. Zeeb 
130*8ba4d145SBjoern A. Zeeb 	DMA_PREFETCH_CONF(0, 4, 0x080);
131*8ba4d145SBjoern A. Zeeb 	DMA_PREFETCH_CONF(1, 4, 0x0c0);
132*8ba4d145SBjoern A. Zeeb 	DMA_PREFETCH_CONF(2, 4, 0x100);
133*8ba4d145SBjoern A. Zeeb 	DMA_PREFETCH_CONF(3, 4, 0x140);
134*8ba4d145SBjoern A. Zeeb 	DMA_PREFETCH_CONF(4, 4, 0x180);
135*8ba4d145SBjoern A. Zeeb 	DMA_PREFETCH_CONF(16, 4, 0x280);
136*8ba4d145SBjoern A. Zeeb 	DMA_PREFETCH_CONF(17, 4, 0x2c0);
137cbb3ec25SBjoern A. Zeeb }
138cbb3ec25SBjoern A. Zeeb 
mt792xu_wfdma_init(struct mt792x_dev * dev)139cbb3ec25SBjoern A. Zeeb static void mt792xu_wfdma_init(struct mt792x_dev *dev)
140cbb3ec25SBjoern A. Zeeb {
141*8ba4d145SBjoern A. Zeeb 	int i;
142*8ba4d145SBjoern A. Zeeb 
143cbb3ec25SBjoern A. Zeeb 	mt792xu_dma_prefetch(dev);
144cbb3ec25SBjoern A. Zeeb 
145cbb3ec25SBjoern A. Zeeb 	mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO);
146cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_UWFDMA0_GLO_CFG,
147cbb3ec25SBjoern A. Zeeb 		 MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
148cbb3ec25SBjoern A. Zeeb 		 MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 |
149cbb3ec25SBjoern A. Zeeb 		 MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL |
150cbb3ec25SBjoern A. Zeeb 		 MT_WFDMA0_GLO_CFG_TX_DMA_EN |
151cbb3ec25SBjoern A. Zeeb 		 MT_WFDMA0_GLO_CFG_RX_DMA_EN);
152cbb3ec25SBjoern A. Zeeb 
153*8ba4d145SBjoern A. Zeeb 	mt76_rmw(dev, MT_DMASHDL_REFILL, MT_DMASHDL_REFILL_MASK, 0xffe00000);
154*8ba4d145SBjoern A. Zeeb 	mt76_clear(dev, MT_DMASHDL_PAGE, MT_DMASHDL_GROUP_SEQ_ORDER);
155*8ba4d145SBjoern A. Zeeb 	mt76_rmw(dev, MT_DMASHDL_PKT_MAX_SIZE,
156*8ba4d145SBjoern A. Zeeb 		 MT_DMASHDL_PKT_MAX_SIZE_PLE | MT_DMASHDL_PKT_MAX_SIZE_PSE,
157*8ba4d145SBjoern A. Zeeb 		 FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PLE, 1) |
158*8ba4d145SBjoern A. Zeeb 		 FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PSE, 0));
159*8ba4d145SBjoern A. Zeeb 	for (i = 0; i < 5; i++)
160*8ba4d145SBjoern A. Zeeb 		mt76_wr(dev, MT_DMASHDL_GROUP_QUOTA(i),
161*8ba4d145SBjoern A. Zeeb 			FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x3) |
162*8ba4d145SBjoern A. Zeeb 			FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0xfff));
163*8ba4d145SBjoern A. Zeeb 	for (i = 5; i < 16; i++)
164*8ba4d145SBjoern A. Zeeb 		mt76_wr(dev, MT_DMASHDL_GROUP_QUOTA(i),
165*8ba4d145SBjoern A. Zeeb 			FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x0) |
166*8ba4d145SBjoern A. Zeeb 			FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x0));
167*8ba4d145SBjoern A. Zeeb 	mt76_wr(dev, MT_DMASHDL_Q_MAP(0), 0x32013201);
168*8ba4d145SBjoern A. Zeeb 	mt76_wr(dev, MT_DMASHDL_Q_MAP(1), 0x32013201);
169*8ba4d145SBjoern A. Zeeb 	mt76_wr(dev, MT_DMASHDL_Q_MAP(2), 0x55555444);
170*8ba4d145SBjoern A. Zeeb 	mt76_wr(dev, MT_DMASHDL_Q_MAP(3), 0x55555444);
171*8ba4d145SBjoern A. Zeeb 
172*8ba4d145SBjoern A. Zeeb 	mt76_wr(dev, MT_DMASHDL_SCHED_SET(0), 0x76540132);
173*8ba4d145SBjoern A. Zeeb 	mt76_wr(dev, MT_DMASHDL_SCHED_SET(1), 0xFEDCBA98);
174cbb3ec25SBjoern A. Zeeb 
175cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
176cbb3ec25SBjoern A. Zeeb }
177cbb3ec25SBjoern A. Zeeb 
mt792xu_dma_rx_evt_ep4(struct mt792x_dev * dev)178cbb3ec25SBjoern A. Zeeb static int mt792xu_dma_rx_evt_ep4(struct mt792x_dev *dev)
179cbb3ec25SBjoern A. Zeeb {
180cbb3ec25SBjoern A. Zeeb 	if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG,
181cbb3ec25SBjoern A. Zeeb 		       MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000))
182cbb3ec25SBjoern A. Zeeb 		return -ETIMEDOUT;
183cbb3ec25SBjoern A. Zeeb 
184cbb3ec25SBjoern A. Zeeb 	mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
185cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_WFDMA_HOST_CONFIG,
186cbb3ec25SBjoern A. Zeeb 		 MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN);
187cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
188cbb3ec25SBjoern A. Zeeb 
189cbb3ec25SBjoern A. Zeeb 	return 0;
190cbb3ec25SBjoern A. Zeeb }
191cbb3ec25SBjoern A. Zeeb 
mt792xu_epctl_rst_opt(struct mt792x_dev * dev,bool reset)192cbb3ec25SBjoern A. Zeeb static void mt792xu_epctl_rst_opt(struct mt792x_dev *dev, bool reset)
193cbb3ec25SBjoern A. Zeeb {
194cbb3ec25SBjoern A. Zeeb 	u32 val;
195cbb3ec25SBjoern A. Zeeb 
196cbb3ec25SBjoern A. Zeeb 	/* usb endpoint reset opt
197cbb3ec25SBjoern A. Zeeb 	 * bits[4,9]: out blk ep 4-9
198cbb3ec25SBjoern A. Zeeb 	 * bits[20,21]: in blk ep 4-5
199cbb3ec25SBjoern A. Zeeb 	 * bits[22]: in int ep 6
200cbb3ec25SBjoern A. Zeeb 	 */
201cbb3ec25SBjoern A. Zeeb 	val = mt792xu_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT);
202cbb3ec25SBjoern A. Zeeb 	if (reset)
203cbb3ec25SBjoern A. Zeeb 		val |= GENMASK(9, 4) | GENMASK(22, 20);
204cbb3ec25SBjoern A. Zeeb 	else
205cbb3ec25SBjoern A. Zeeb 		val &= ~(GENMASK(9, 4) | GENMASK(22, 20));
206cbb3ec25SBjoern A. Zeeb 	mt792xu_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
207cbb3ec25SBjoern A. Zeeb }
208cbb3ec25SBjoern A. Zeeb 
mt792xu_dma_init(struct mt792x_dev * dev,bool resume)209cbb3ec25SBjoern A. Zeeb int mt792xu_dma_init(struct mt792x_dev *dev, bool resume)
210cbb3ec25SBjoern A. Zeeb {
211cbb3ec25SBjoern A. Zeeb 	int err;
212cbb3ec25SBjoern A. Zeeb 
213cbb3ec25SBjoern A. Zeeb 	mt792xu_wfdma_init(dev);
214cbb3ec25SBjoern A. Zeeb 
215cbb3ec25SBjoern A. Zeeb 	mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH);
216cbb3ec25SBjoern A. Zeeb 
217cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_UDMA_WLCFG_0,
218cbb3ec25SBjoern A. Zeeb 		 MT_WL_RX_EN | MT_WL_TX_EN |
219cbb3ec25SBjoern A. Zeeb 		 MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN);
220cbb3ec25SBjoern A. Zeeb 	mt76_clear(dev, MT_UDMA_WLCFG_0,
221cbb3ec25SBjoern A. Zeeb 		   MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT);
222cbb3ec25SBjoern A. Zeeb 	mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT);
223cbb3ec25SBjoern A. Zeeb 
224cbb3ec25SBjoern A. Zeeb 	if (resume)
225cbb3ec25SBjoern A. Zeeb 		return 0;
226cbb3ec25SBjoern A. Zeeb 
227cbb3ec25SBjoern A. Zeeb 	err = mt792xu_dma_rx_evt_ep4(dev);
228cbb3ec25SBjoern A. Zeeb 	if (err)
229cbb3ec25SBjoern A. Zeeb 		return err;
230cbb3ec25SBjoern A. Zeeb 
231cbb3ec25SBjoern A. Zeeb 	mt792xu_epctl_rst_opt(dev, false);
232cbb3ec25SBjoern A. Zeeb 
233cbb3ec25SBjoern A. Zeeb 	return 0;
234cbb3ec25SBjoern A. Zeeb }
235cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_dma_init);
236cbb3ec25SBjoern A. Zeeb 
mt792xu_wfsys_reset(struct mt792x_dev * dev)237cbb3ec25SBjoern A. Zeeb int mt792xu_wfsys_reset(struct mt792x_dev *dev)
238cbb3ec25SBjoern A. Zeeb {
239cbb3ec25SBjoern A. Zeeb 	u32 val;
240cbb3ec25SBjoern A. Zeeb 	int i;
241cbb3ec25SBjoern A. Zeeb 
242cbb3ec25SBjoern A. Zeeb 	mt792xu_epctl_rst_opt(dev, false);
243cbb3ec25SBjoern A. Zeeb 
244cbb3ec25SBjoern A. Zeeb 	val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
245cbb3ec25SBjoern A. Zeeb 	val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
246cbb3ec25SBjoern A. Zeeb 	mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
247cbb3ec25SBjoern A. Zeeb 
248cbb3ec25SBjoern A. Zeeb 	usleep_range(10, 20);
249cbb3ec25SBjoern A. Zeeb 
250cbb3ec25SBjoern A. Zeeb 	val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
251cbb3ec25SBjoern A. Zeeb 	val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
252cbb3ec25SBjoern A. Zeeb 	mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
253cbb3ec25SBjoern A. Zeeb 
254cbb3ec25SBjoern A. Zeeb 	mt792xu_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
255cbb3ec25SBjoern A. Zeeb 	for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) {
256cbb3ec25SBjoern A. Zeeb 		val = mt792xu_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS);
257cbb3ec25SBjoern A. Zeeb 		if (val & MT_UDMA_CONN_WFSYS_INIT_DONE)
258cbb3ec25SBjoern A. Zeeb 			break;
259cbb3ec25SBjoern A. Zeeb 
260cbb3ec25SBjoern A. Zeeb 		msleep(100);
261cbb3ec25SBjoern A. Zeeb 	}
262cbb3ec25SBjoern A. Zeeb 
263cbb3ec25SBjoern A. Zeeb 	if (i == MT792x_WFSYS_INIT_RETRY_COUNT)
264cbb3ec25SBjoern A. Zeeb 		return -ETIMEDOUT;
265cbb3ec25SBjoern A. Zeeb 
266cbb3ec25SBjoern A. Zeeb 	return 0;
267cbb3ec25SBjoern A. Zeeb }
268cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_wfsys_reset);
269cbb3ec25SBjoern A. Zeeb 
mt792xu_init_reset(struct mt792x_dev * dev)270cbb3ec25SBjoern A. Zeeb int mt792xu_init_reset(struct mt792x_dev *dev)
271cbb3ec25SBjoern A. Zeeb {
272cbb3ec25SBjoern A. Zeeb 	set_bit(MT76_RESET, &dev->mphy.state);
273cbb3ec25SBjoern A. Zeeb 
274cbb3ec25SBjoern A. Zeeb 	wake_up(&dev->mt76.mcu.wait);
275cbb3ec25SBjoern A. Zeeb 	skb_queue_purge(&dev->mt76.mcu.res_q);
276cbb3ec25SBjoern A. Zeeb 
277cbb3ec25SBjoern A. Zeeb 	mt76u_stop_rx(&dev->mt76);
278cbb3ec25SBjoern A. Zeeb 	mt76u_stop_tx(&dev->mt76);
279cbb3ec25SBjoern A. Zeeb 
280cbb3ec25SBjoern A. Zeeb 	mt792xu_wfsys_reset(dev);
281cbb3ec25SBjoern A. Zeeb 
282cbb3ec25SBjoern A. Zeeb 	clear_bit(MT76_RESET, &dev->mphy.state);
283cbb3ec25SBjoern A. Zeeb 
284cbb3ec25SBjoern A. Zeeb 	return mt76u_resume_rx(&dev->mt76);
285cbb3ec25SBjoern A. Zeeb }
286cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_init_reset);
287cbb3ec25SBjoern A. Zeeb 
mt792xu_stop(struct ieee80211_hw * hw,bool suspend)288*8ba4d145SBjoern A. Zeeb void mt792xu_stop(struct ieee80211_hw *hw, bool suspend)
289*8ba4d145SBjoern A. Zeeb {
290*8ba4d145SBjoern A. Zeeb 	struct mt792x_dev *dev = mt792x_hw_dev(hw);
291*8ba4d145SBjoern A. Zeeb 
292*8ba4d145SBjoern A. Zeeb 	mt76u_stop_tx(&dev->mt76);
293*8ba4d145SBjoern A. Zeeb 	mt792x_stop(hw, false);
294*8ba4d145SBjoern A. Zeeb }
295*8ba4d145SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_stop);
296*8ba4d145SBjoern A. Zeeb 
mt792xu_disconnect(struct usb_interface * usb_intf)297cbb3ec25SBjoern A. Zeeb void mt792xu_disconnect(struct usb_interface *usb_intf)
298cbb3ec25SBjoern A. Zeeb {
299cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = usb_get_intfdata(usb_intf);
300cbb3ec25SBjoern A. Zeeb 
301cbb3ec25SBjoern A. Zeeb 	cancel_work_sync(&dev->init_work);
302cbb3ec25SBjoern A. Zeeb 	if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
303cbb3ec25SBjoern A. Zeeb 		return;
304cbb3ec25SBjoern A. Zeeb 
305cbb3ec25SBjoern A. Zeeb 	mt76_unregister_device(&dev->mt76);
306cbb3ec25SBjoern A. Zeeb 	mt792xu_cleanup(dev);
307cbb3ec25SBjoern A. Zeeb 
308cbb3ec25SBjoern A. Zeeb 	usb_set_intfdata(usb_intf, NULL);
309cbb3ec25SBjoern A. Zeeb 	usb_put_dev(interface_to_usbdev(usb_intf));
310cbb3ec25SBjoern A. Zeeb 
311cbb3ec25SBjoern A. Zeeb 	mt76_free_device(&dev->mt76);
312cbb3ec25SBjoern A. Zeeb }
313cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792xu_disconnect);
314cbb3ec25SBjoern A. Zeeb 
315*8ba4d145SBjoern A. Zeeb MODULE_DESCRIPTION("MediaTek MT792x USB helpers");
316cbb3ec25SBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
317cbb3ec25SBjoern A. Zeeb MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
318