blob: cd2f09743d2f7064288baebe817ec485c8e914bb [file] [log] [blame]
developerb11a5392022-03-31 00:34:47 +08001// SPDX-License-Identifier: ISC
2/* Copyright (C) 2022 MediaTek Inc.
3 *
4 * Author: Lorenzo Bianconi <lorenzo@kernel.org>
5 */
6
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <linux/usb.h>
10
11#include "mt7921.h"
12#include "mcu.h"
13#include "mac.h"
14
15static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr)
16{
17 u32 ret;
18
19 mutex_lock(&dev->usb.usb_ctrl_mtx);
20 ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE,
21 USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr);
22 mutex_unlock(&dev->usb.usb_ctrl_mtx);
23
24 return ret;
25}
26
27static void mt7921u_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val)
28{
29 mutex_lock(&dev->usb.usb_ctrl_mtx);
30 ___mt76u_wr(dev, MT_VEND_WRITE,
31 USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val);
32 mutex_unlock(&dev->usb.usb_ctrl_mtx);
33}
34
35static void mt7921u_dma_prefetch(struct mt7921_dev *dev)
36{
37 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
38 MT_WPDMA0_MAX_CNT_MASK, 4);
39 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
40 MT_WPDMA0_BASE_PTR_MASK, 0x80);
41
42 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
43 MT_WPDMA0_MAX_CNT_MASK, 4);
44 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
45 MT_WPDMA0_BASE_PTR_MASK, 0xc0);
46
47 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
48 MT_WPDMA0_MAX_CNT_MASK, 4);
49 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
50 MT_WPDMA0_BASE_PTR_MASK, 0x100);
51
52 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
53 MT_WPDMA0_MAX_CNT_MASK, 4);
54 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
55 MT_WPDMA0_BASE_PTR_MASK, 0x140);
56
57 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
58 MT_WPDMA0_MAX_CNT_MASK, 4);
59 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
60 MT_WPDMA0_BASE_PTR_MASK, 0x180);
61
62 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
63 MT_WPDMA0_MAX_CNT_MASK, 4);
64 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
65 MT_WPDMA0_BASE_PTR_MASK, 0x280);
66
67 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
68 MT_WPDMA0_MAX_CNT_MASK, 4);
69 mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
70 MT_WPDMA0_BASE_PTR_MASK, 0x2c0);
71}
72
73static void mt7921u_wfdma_init(struct mt7921_dev *dev)
74{
75 mt7921u_dma_prefetch(dev);
76
77 mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO);
78 mt76_set(dev, MT_UWFDMA0_GLO_CFG,
79 MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
80 MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 |
81 MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL |
82 MT_WFDMA0_GLO_CFG_TX_DMA_EN |
83 MT_WFDMA0_GLO_CFG_RX_DMA_EN);
84
85 /* disable dmashdl */
86 mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0,
87 MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
88 mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
89
90 mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
91}
92
93static int mt7921u_dma_rx_evt_ep4(struct mt7921_dev *dev)
94{
95 if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG,
96 MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000))
97 return -ETIMEDOUT;
98
99 mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
100 mt76_set(dev, MT_WFDMA_HOST_CONFIG,
101 MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN);
102 mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
103
104 return 0;
105}
106
107static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset)
108{
109 u32 val;
110
111 /* usb endpoint reset opt
112 * bits[4,9]: out blk ep 4-9
113 * bits[20,21]: in blk ep 4-5
114 * bits[22]: in int ep 6
115 */
116 val = mt7921u_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT);
117 if (reset)
118 val |= GENMASK(9, 4) | GENMASK(22, 20);
119 else
120 val &= ~(GENMASK(9, 4) | GENMASK(22, 20));
121 mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
122}
123
124int mt7921u_dma_init(struct mt7921_dev *dev, bool resume)
125{
126 int err;
127
128 mt7921u_wfdma_init(dev);
129
130 mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH);
131
132 mt76_set(dev, MT_UDMA_WLCFG_0,
133 MT_WL_RX_EN | MT_WL_TX_EN |
134 MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN);
135 mt76_clear(dev, MT_UDMA_WLCFG_0,
136 MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT);
137 mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT);
138
139 if (resume)
140 return 0;
141
142 err = mt7921u_dma_rx_evt_ep4(dev);
143 if (err)
144 return err;
145
146 mt7921u_epctl_rst_opt(dev, false);
147
148 return 0;
149}
150
151int mt7921u_wfsys_reset(struct mt7921_dev *dev)
152{
153 u32 val;
154 int i;
155
156 mt7921u_epctl_rst_opt(dev, false);
157
158 val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
159 val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
160 mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
161
162 usleep_range(10, 20);
163
164 val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
165 val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
166 mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
167
168 mt7921u_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
169 for (i = 0; i < MT7921_WFSYS_INIT_RETRY_COUNT; i++) {
170 val = mt7921u_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS);
171 if (val & MT_UDMA_CONN_WFSYS_INIT_DONE)
172 break;
173
174 msleep(100);
175 }
176
177 if (i == MT7921_WFSYS_INIT_RETRY_COUNT)
178 return -ETIMEDOUT;
179
180 return 0;
181}
182
183int mt7921u_init_reset(struct mt7921_dev *dev)
184{
185 set_bit(MT76_RESET, &dev->mphy.state);
186
187 wake_up(&dev->mt76.mcu.wait);
188 mt7921_mcu_exit(dev);
189
190 mt76u_stop_rx(&dev->mt76);
191 mt76u_stop_tx(&dev->mt76);
192
193 mt7921u_wfsys_reset(dev);
194
195 clear_bit(MT76_RESET, &dev->mphy.state);
196
197 return mt76u_resume_rx(&dev->mt76);
198}
199
200int mt7921u_mac_reset(struct mt7921_dev *dev)
201{
202 int err;
203
204 mt76_txq_schedule_all(&dev->mphy);
205 mt76_worker_disable(&dev->mt76.tx_worker);
206
207 set_bit(MT76_RESET, &dev->mphy.state);
208 set_bit(MT76_MCU_RESET, &dev->mphy.state);
209
210 wake_up(&dev->mt76.mcu.wait);
211 mt7921_mcu_exit(dev);
212
213 mt76u_stop_rx(&dev->mt76);
214 mt76u_stop_tx(&dev->mt76);
215
216 mt7921u_wfsys_reset(dev);
217
218 clear_bit(MT76_MCU_RESET, &dev->mphy.state);
219 err = mt76u_resume_rx(&dev->mt76);
220 if (err)
221 goto out;
222
223 err = mt7921u_mcu_power_on(dev);
224 if (err)
225 goto out;
226
227 err = mt7921u_dma_init(dev, false);
228 if (err)
229 goto out;
230
231 mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
232 mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
233
234 err = mt7921_run_firmware(dev);
235 if (err)
236 goto out;
237
238 mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
239
240 err = mt7921_mcu_set_eeprom(dev);
241 if (err)
242 goto out;
243
244 err = mt7921_mac_init(dev);
245 if (err)
246 goto out;
247
248 err = __mt7921_start(&dev->phy);
249out:
250 clear_bit(MT76_RESET, &dev->mphy.state);
251
252 mt76_worker_enable(&dev->mt76.tx_worker);
253
254 return err;
255}