blob: 777dfbeb5fd38368c5bdae39723ff198a858bed6 [file] [log] [blame]
developer1d9fede2022-08-29 15:24:07 +08001From a9856ee394084946e0fb59c6b56dfd66108761ba Mon Sep 17 00:00:00 2001
developere3d01472022-05-09 14:01:49 +08002From: Bo Jiao <Bo.Jiao@mediatek.com>
developerf64861f2022-06-22 11:44:53 +08003Date: Wed, 22 Jun 2022 10:51:59 +0800
developer1d9fede2022-08-29 15:24:07 +08004Subject: [PATCH] mt76: mt7915: add L0.5 system error recovery support
developere3d01472022-05-09 14:01:49 +08005
developere3d01472022-05-09 14:01:49 +08006---
developer1d9fede2022-08-29 15:24:07 +08007 mt7915/debugfs.c | 88 ++++++++++++---
8 mt7915/dma.c | 48 ++++++++
9 mt7915/init.c | 8 +-
10 mt7915/mac.c | 283 +++++++++++++++++++++++++++++++++++++----------
11 mt7915/main.c | 19 +++-
12 mt7915/mcu.c | 95 ++++++++++++++--
13 mt7915/mcu.h | 3 +-
14 mt7915/mmio.c | 8 +-
15 mt7915/mt7915.h | 23 ++++
16 mt7915/regs.h | 16 +++
17 10 files changed, 492 insertions(+), 99 deletions(-)
developere3d01472022-05-09 14:01:49 +080018
19diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
developerd59e4772022-07-14 13:48:49 +080020index 0cfb6068..07de2eef 100644
developere3d01472022-05-09 14:01:49 +080021--- a/mt7915/debugfs.c
22+++ b/mt7915/debugfs.c
developerbd398d52022-06-06 20:53:24 +080023@@ -52,12 +52,17 @@ static ssize_t
developere3d01472022-05-09 14:01:49 +080024 mt7915_fw_ser_set(struct file *file, const char __user *user_buf,
25 size_t count, loff_t *ppos)
26 {
27+#define SER_LEVEL GENMASK(3, 0)
28+#define SER_ACTION GENMASK(11, 8)
29+
30 struct mt7915_phy *phy = file->private_data;
31 struct mt7915_dev *dev = phy->dev;
32- bool ext_phy = phy != &dev->phy;
33+ u8 ser_action, ser_set, set_val;
34+ u8 band_idx = phy->band_idx;
35 char buf[16];
36 int ret = 0;
37 u16 val;
38+ u32 intr;
39
40 if (count >= sizeof(buf))
41 return -EINVAL;
developerbd398d52022-06-06 20:53:24 +080042@@ -73,28 +78,71 @@ mt7915_fw_ser_set(struct file *file, const char __user *user_buf,
developere3d01472022-05-09 14:01:49 +080043 if (kstrtou16(buf, 0, &val))
44 return -EINVAL;
45
46- switch (val) {
47+ ser_action = FIELD_GET(SER_ACTION, val);
48+ ser_set = set_val = FIELD_GET(SER_LEVEL, val);
49+
50+ switch (ser_action) {
51 case SER_QUERY:
52 /* grab firmware SER stats */
53- ret = mt7915_mcu_set_ser(dev, 0, 0, ext_phy);
54+ ser_set = 0;
55 break;
56- case SER_SET_RECOVER_L1:
57- case SER_SET_RECOVER_L2:
58- case SER_SET_RECOVER_L3_RX_ABORT:
59- case SER_SET_RECOVER_L3_TX_ABORT:
60- case SER_SET_RECOVER_L3_TX_DISABLE:
61- case SER_SET_RECOVER_L3_BF:
62- ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), ext_phy);
63- if (ret)
64- return ret;
65-
66- ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, ext_phy);
67+ case SER_SET:
68+ /*
69+ * 0x100: disable system error recovery function.
70+ * 0x101: enable system error recovery function.
71+ * 0x103: enable l0.5 recover function.
72+ */
73+ ser_set = !!set_val;
74+
75+ dev->ser.reset_enable = ser_set;
76+ intr = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
77+ if (dev->ser.reset_enable)
78+ intr |= MT_MCU_CMD_WDT_MASK;
79+ else
80+ intr &= ~MT_MCU_CMD_WDT_MASK;
81+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, intr);
82 break;
83- default:
84+ case SER_ENABLE:
85+ /*
86+ * 0x200: enable system error tracking.
87+ * 0x201: enable system error L1 recover.
88+ * 0x202: enable system error L2 recover.
89+ * 0x203: enable system error L3 rx abort.
90+ * 0x204: enable system error L3 tx abort.
91+ * 0x205: enable system error L3 tx disable.
92+ * 0x206: enable system error L3 bf recover.
93+ * 0x207: enable system error all recover.
94+ */
95+ ser_set = set_val > 7 ? 0x7f : BIT(set_val);
96+ break;
97+ case SER_RECOVER:
98+ /*
99+ * 0x300: trigger L0.5 recover.
100+ * 0x301: trigger L1 recover.
101+ * 0x302: trigger L2 recover.
102+ * 0x303: trigger L3 rx abort.
103+ * 0x304: trigger L3 tx abort
104+ * 0x305: trigger L3 tx disable.
105+ * 0x306: trigger L3 bf recover.
106+ */
107+ if (!ser_set) {
108+ if (dev->ser.reset_enable) {
109+ dev->reset_state |= MT_MCU_CMD_WDT_MASK;
110+ mt7915_reset(dev);
111+ } else {
112+ dev_info(dev->mt76.dev, "SER: chip full recovery not enable\n");
113+ }
114+ goto out;
115+ }
116 break;
117+ default:
118+ goto out;
119 }
120-
121- return ret ? ret : count;
122+ ret = mt7915_mcu_set_ser(dev, ser_action, ser_set, band_idx);
123+ if (ret)
124+ return ret;
125+out:
126+ return count;
127 }
128
129 static ssize_t
developerbd398d52022-06-06 20:53:24 +0800130@@ -143,6 +191,12 @@ mt7915_fw_ser_get(struct file *file, char __user *user_buf,
developere3d01472022-05-09 14:01:49 +0800131 "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n",
132 mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
133
134+ desc += scnprintf(buff + desc, bufsz - desc,
135+ "\nWF RESET STATUS: EN %d, WM %d, WA %d\n",
136+ dev->ser.reset_enable,
137+ dev->ser.wf_reset_wm_count,
138+ dev->ser.wf_reset_wa_count);
139+
140 ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
141 kfree(buff);
142 return ret;
143diff --git a/mt7915/dma.c b/mt7915/dma.c
developer1d9fede2022-08-29 15:24:07 +0800144index f7e6bb10..4b594a53 100644
developere3d01472022-05-09 14:01:49 +0800145--- a/mt7915/dma.c
146+++ b/mt7915/dma.c
developer1d9fede2022-08-29 15:24:07 +0800147@@ -479,6 +479,54 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
developere3d01472022-05-09 14:01:49 +0800148 return 0;
149 }
150
151+int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
152+{
developer1d9fede2022-08-29 15:24:07 +0800153+ struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800154+ int i;
155+
156+ /* clean up hw queues */
157+ for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) {
158+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
159+ if (mphy_ext)
160+ mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
161+ }
162+
163+ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
164+ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
165+
166+ mt76_for_each_q_rx(&dev->mt76, i)
167+ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
168+
169+ /* reset wfsys */
170+ if (force)
171+ mt7915_wfsys_reset(dev);
172+
173+ /* disable wfdma */
174+ mt7915_dma_disable(dev, force);
175+
176+ /* reset hw queues */
177+ for (i = 0; i < __MT_TXQ_MAX; i++) {
178+ mt76_queue_reset(dev, dev->mphy.q_tx[i]);
179+ if (mphy_ext)
180+ mt76_queue_reset(dev, mphy_ext->q_tx[i]);
181+ }
182+
183+ for (i = 0; i < __MT_MCUQ_MAX; i++)
184+ mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
185+
186+ mt76_for_each_q_rx(&dev->mt76, i)
187+ mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
188+
189+ mt76_tx_status_check(&dev->mt76, true);
190+
191+ mt7915_dma_enable(dev);
192+
193+ mt76_for_each_q_rx(&dev->mt76, i)
194+ mt76_queue_rx_reset(dev, i);
195+
196+ return 0;
197+}
198+
199 void mt7915_dma_cleanup(struct mt7915_dev *dev)
200 {
201 mt7915_dma_disable(dev, true);
202diff --git a/mt7915/init.c b/mt7915/init.c
developer1d9fede2022-08-29 15:24:07 +0800203index 37b7b54a..141c5ad8 100644
developere3d01472022-05-09 14:01:49 +0800204--- a/mt7915/init.c
205+++ b/mt7915/init.c
206@@ -262,7 +262,7 @@ static void mt7915_led_set_brightness(struct led_classdev *led_cdev,
207 mt7915_led_set_config(led_cdev, 0xff, 0);
208 }
209
210-static void
211+void
212 mt7915_init_txpower(struct mt7915_dev *dev,
213 struct ieee80211_supported_band *sband)
214 {
developerf64861f2022-06-22 11:44:53 +0800215@@ -449,7 +449,7 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
developere3d01472022-05-09 14:01:49 +0800216 mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
217 }
218
219-static void mt7915_mac_init(struct mt7915_dev *dev)
220+void mt7915_mac_init(struct mt7915_dev *dev)
221 {
222 int i;
223 u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680;
developerf64861f2022-06-22 11:44:53 +0800224@@ -479,7 +479,7 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
developere3d01472022-05-09 14:01:49 +0800225 }
226 }
227
228-static int mt7915_txbf_init(struct mt7915_dev *dev)
229+int mt7915_txbf_init(struct mt7915_dev *dev)
230 {
231 int ret;
232
developerf64861f2022-06-22 11:44:53 +0800233@@ -1162,6 +1162,8 @@ int mt7915_register_device(struct mt7915_dev *dev)
developere3d01472022-05-09 14:01:49 +0800234
235 mt7915_init_debugfs(&dev->phy);
236
237+ dev->ser.hw_init_done = true;
238+
239 return 0;
240
241 unreg_thermal:
242diff --git a/mt7915/mac.c b/mt7915/mac.c
developer1d9fede2022-08-29 15:24:07 +0800243index 6b3fa4ce..e5409413 100644
developere3d01472022-05-09 14:01:49 +0800244--- a/mt7915/mac.c
245+++ b/mt7915/mac.c
246@@ -3,6 +3,7 @@
247
248 #include <linux/etherdevice.h>
249 #include <linux/timekeeping.h>
250+#include <linux/pci.h>
251 #include "mt7915.h"
252 #include "../dma.h"
253 #include "mac.h"
developer1d9fede2022-08-29 15:24:07 +0800254@@ -1315,85 +1316,187 @@ mt7915_update_beacons(struct mt7915_dev *dev)
255 mt7915_update_vif_beacon, mphy_ext->hw);
developere3d01472022-05-09 14:01:49 +0800256 }
257
258-static void
259-mt7915_dma_reset(struct mt7915_dev *dev)
260+void mt7915_tx_token_put(struct mt7915_dev *dev)
261 {
developer1d9fede2022-08-29 15:24:07 +0800262- struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800263- u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
264- int i;
265+ struct mt76_txwi_cache *txwi;
266+ int id;
developerf64861f2022-06-22 11:44:53 +0800267+
developere3d01472022-05-09 14:01:49 +0800268+ spin_lock_bh(&dev->mt76.token_lock);
269+ idr_for_each_entry(&dev->mt76.token, txwi, id) {
270+ mt7915_txwi_free(dev, txwi, NULL, NULL);
271+ dev->mt76.token_count--;
272+ }
273+ spin_unlock_bh(&dev->mt76.token_lock);
274+ idr_destroy(&dev->mt76.token);
275+}
developerf64861f2022-06-22 11:44:53 +0800276+
developere3d01472022-05-09 14:01:49 +0800277+static int
278+mt7915_mac_reset(struct mt7915_dev *dev)
279+{
280+ struct mt7915_phy *phy2;
281+ struct mt76_phy *ext_phy;
282+ struct mt76_dev *mdev = &dev->mt76;
283+ int i, ret;
284+ u32 irq_mask;
developerf64861f2022-06-22 11:44:53 +0800285
286- mt76_clear(dev, MT_WFDMA0_GLO_CFG,
287- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
288- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
developer1d9fede2022-08-29 15:24:07 +0800289+ ext_phy = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800290+ phy2 = ext_phy ? ext_phy->priv : NULL;
developerf64861f2022-06-22 11:44:53 +0800291
292- if (is_mt7915(&dev->mt76))
293- mt76_clear(dev, MT_WFDMA1_GLO_CFG,
294- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
295- MT_WFDMA1_GLO_CFG_RX_DMA_EN);
developere3d01472022-05-09 14:01:49 +0800296 if (dev->hif2) {
297- mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
298- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
299- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
developerf64861f2022-06-22 11:44:53 +0800300-
301- if (is_mt7915(&dev->mt76))
302- mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
303- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
304- MT_WFDMA1_GLO_CFG_RX_DMA_EN);
developere3d01472022-05-09 14:01:49 +0800305+ mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
306+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
developer1d9fede2022-08-29 15:24:07 +0800307 }
308
309- usleep_range(1000, 2000);
developere3d01472022-05-09 14:01:49 +0800310+ if (dev_is_pci(mdev->dev)) {
311+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
312+ if (dev->hif2)
313+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
developer1d9fede2022-08-29 15:24:07 +0800314+ }
developere3d01472022-05-09 14:01:49 +0800315
developerf64861f2022-06-22 11:44:53 +0800316- for (i = 0; i < __MT_TXQ_MAX; i++) {
317- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
318- if (mphy_ext)
319- mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
developere3d01472022-05-09 14:01:49 +0800320+ set_bit(MT76_RESET, &dev->mphy.state);
321+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
322+ wake_up(&dev->mt76.mcu.wait);
323+ if (ext_phy) {
324+ set_bit(MT76_RESET, &ext_phy->state);
325+ set_bit(MT76_MCU_RESET, &ext_phy->state);
326 }
327
developerf64861f2022-06-22 11:44:53 +0800328- for (i = 0; i < __MT_MCUQ_MAX; i++)
329- mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
developere3d01472022-05-09 14:01:49 +0800330+ /* lock/unlock all queues to ensure that no tx is pending */
331+ mt76_txq_schedule_all(&dev->mphy);
332+ if (ext_phy)
333+ mt76_txq_schedule_all(ext_phy);
334
developerf64861f2022-06-22 11:44:53 +0800335- mt76_for_each_q_rx(&dev->mt76, i)
336- mt76_queue_rx_reset(dev, i);
developere3d01472022-05-09 14:01:49 +0800337+ /* disable all tx/rx napi */
338+ mt76_worker_disable(&dev->mt76.tx_worker);
339+ mt76_for_each_q_rx(mdev, i) {
340+ if (mdev->q_rx[i].ndesc)
341+ napi_disable(&dev->mt76.napi[i]);
developerf64861f2022-06-22 11:44:53 +0800342+ }
developere3d01472022-05-09 14:01:49 +0800343+ napi_disable(&dev->mt76.tx_napi);
344
developerf64861f2022-06-22 11:44:53 +0800345- mt76_tx_status_check(&dev->mt76, true);
developere3d01472022-05-09 14:01:49 +0800346+ /* token reinit */
347+ mt7915_tx_token_put(dev);
348+ idr_init(&dev->mt76.token);
349
developere3d01472022-05-09 14:01:49 +0800350- /* re-init prefetch settings after reset */
351- mt7915_dma_prefetch(dev);
developerf64861f2022-06-22 11:44:53 +0800352+ mt7915_dma_reset(dev, true);
developer1d9fede2022-08-29 15:24:07 +0800353+
developere3d01472022-05-09 14:01:49 +0800354+ local_bh_disable();
355+ mt76_for_each_q_rx(mdev, i) {
356+ if (mdev->q_rx[i].ndesc) {
357+ napi_enable(&dev->mt76.napi[i]);
358+ napi_schedule(&dev->mt76.napi[i]);
359+ }
360+ }
361+ local_bh_enable();
362+ clear_bit(MT76_MCU_RESET, &dev->mphy.state);
363+ clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
developerf64861f2022-06-22 11:44:53 +0800364+
developere3d01472022-05-09 14:01:49 +0800365+ mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
366+ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
developer1d9fede2022-08-29 15:24:07 +0800367
368- mt76_set(dev, MT_WFDMA0_GLO_CFG,
369- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
370- if (is_mt7915(&dev->mt76))
371- mt76_set(dev, MT_WFDMA1_GLO_CFG,
372- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
373- MT_WFDMA1_GLO_CFG_RX_DMA_EN |
374- MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
375- MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
developere3d01472022-05-09 14:01:49 +0800376 if (dev->hif2) {
377- mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
378- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
379- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
developerf64861f2022-06-22 11:44:53 +0800380-
381- if (is_mt7915(&dev->mt76))
382- mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
383- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
384- MT_WFDMA1_GLO_CFG_RX_DMA_EN |
385- MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
386- MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
developere3d01472022-05-09 14:01:49 +0800387+ mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
388+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
389+ }
390+ if (dev_is_pci(mdev->dev)) {
391+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
392+ if (dev->hif2)
393+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
394+ }
developerf64861f2022-06-22 11:44:53 +0800395+
developere3d01472022-05-09 14:01:49 +0800396+ /* load firmware */
397+ ret = mt7915_run_firmware(dev);
398+ if (ret)
399+ goto out;
400+
401+ /* set the necessary init items */
402+ ret = mt7915_mcu_set_eeprom(dev, dev->flash_mode);
403+ if (ret)
404+ goto out;
405+
406+ mt7915_mac_init(dev);
407+ mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
408+ mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
409+ ret = mt7915_txbf_init(dev);
developerbd398d52022-06-06 20:53:24 +0800410+
developere3d01472022-05-09 14:01:49 +0800411+ if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
412+ ret = __mt7915_start(dev->mphy.hw);
413+ if (ret)
414+ goto out;
developerbd398d52022-06-06 20:53:24 +0800415 }
developere3d01472022-05-09 14:01:49 +0800416+
417+ if (ext_phy && test_bit(MT76_STATE_RUNNING, &ext_phy->state)) {
418+ ret = __mt7915_start(ext_phy->hw);
419+ if (ret)
420+ goto out;
developerbd398d52022-06-06 20:53:24 +0800421+ }
developere3d01472022-05-09 14:01:49 +0800422+
423+out:
424+ /* reset done */
425+ clear_bit(MT76_RESET, &dev->mphy.state);
426+ if (phy2)
427+ clear_bit(MT76_RESET, &phy2->mt76->state);
428+
429+ local_bh_disable();
430+ napi_enable(&dev->mt76.tx_napi);
431+ napi_schedule(&dev->mt76.tx_napi);
432+ local_bh_enable();
433+
434+ mt76_worker_enable(&dev->mt76.tx_worker);
435+
436+ return ret;
437 }
438
439-void mt7915_tx_token_put(struct mt7915_dev *dev)
440+static void
441+mt7915_mac_full_reset(struct mt7915_dev *dev)
442 {
443- struct mt76_txwi_cache *txwi;
444- int id;
445+ struct mt7915_phy *phy2;
446+ struct mt76_phy *ext_phy;
447+ int i;
448
449- spin_lock_bh(&dev->mt76.token_lock);
450- idr_for_each_entry(&dev->mt76.token, txwi, id) {
451- mt7915_txwi_free(dev, txwi, NULL, NULL);
452- dev->mt76.token_count--;
developer1d9fede2022-08-29 15:24:07 +0800453- }
454- spin_unlock_bh(&dev->mt76.token_lock);
455- idr_destroy(&dev->mt76.token);
456+ ext_phy = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800457+ phy2 = ext_phy ? ext_phy->priv : NULL;
458+
459+ dev->ser.hw_full_reset = true;
460+ if (READ_ONCE(dev->reset_state) & MT_MCU_CMD_WA_WDT)
461+ dev->ser.wf_reset_wa_count++;
462+ else
463+ dev->ser.wf_reset_wm_count++;
464+
465+ wake_up(&dev->mt76.mcu.wait);
466+ ieee80211_stop_queues(mt76_hw(dev));
467+ if (ext_phy)
468+ ieee80211_stop_queues(ext_phy->hw);
469+
470+ cancel_delayed_work_sync(&dev->mphy.mac_work);
471+ if (ext_phy)
472+ cancel_delayed_work_sync(&ext_phy->mac_work);
473+
474+ mutex_lock(&dev->mt76.mutex);
475+ for (i = 0; i < 10; i++) {
476+ if (!mt7915_mac_reset(dev))
477+ break;
developer1d9fede2022-08-29 15:24:07 +0800478+ }
developere3d01472022-05-09 14:01:49 +0800479+ mutex_unlock(&dev->mt76.mutex);
480+
481+ if (i == 10)
482+ dev_err(dev->mt76.dev, "chip full reset failed\n");
483+
484+ ieee80211_restart_hw(mt76_hw(dev));
485+ if (ext_phy)
486+ ieee80211_restart_hw(ext_phy->hw);
487+
488+ ieee80211_wake_queues(mt76_hw(dev));
489+ if (ext_phy)
490+ ieee80211_wake_queues(ext_phy->hw);
491+
492+ dev->ser.hw_full_reset = false;
493+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
494+ MT7915_WATCHDOG_TIME);
495+ if (ext_phy)
496+ ieee80211_queue_delayed_work(ext_phy->hw,
497+ &ext_phy->mac_work,
498+ MT7915_WATCHDOG_TIME);
499 }
500
501 /* system error recovery */
developer1d9fede2022-08-29 15:24:07 +0800502@@ -1408,6 +1511,36 @@ void mt7915_mac_reset_work(struct work_struct *work)
503 ext_phy = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800504 phy2 = ext_phy ? ext_phy->priv : NULL;
505
506+ /* chip full reset */
507+ if (dev->ser.reset_type == SER_TYPE_FULL_RESET) {
508+ u32 intr;
509+
510+ /* disable WA/WM WDT */
511+ intr = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
512+ intr &= ~MT_MCU_CMD_WDT_MASK;
513+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, intr);
514+
515+ mt7915_mac_full_reset(dev);
516+
517+ /* enable the mcu irq*/
518+ mt7915_irq_enable(dev, MT_INT_MCU_CMD);
519+ mt7915_irq_disable(dev, 0);
520+
521+ /* re-enable WA/WM WDT */
522+ intr = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
523+ intr |= MT_MCU_CMD_WDT_MASK;
524+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, intr);
525+
526+ dev->reset_state = MT_MCU_CMD_NORMAL_STATE;
527+ dev->ser.reset_type = SER_TYPE_NONE;
528+ dev_info(dev->mt76.dev, "SER: chip full reset completed, WM %d, WA %d\n",
529+ dev->ser.wf_reset_wm_count,
530+ dev->ser.wf_reset_wa_count);
531+ return;
532+ }
533+
534+ /* chip partial reset */
535+ dev->ser.reset_type = SER_TYPE_NONE;
536 if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
537 return;
538
developer1d9fede2022-08-29 15:24:07 +0800539@@ -1433,7 +1566,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
developere3d01472022-05-09 14:01:49 +0800540 mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
541
542 if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
543- mt7915_dma_reset(dev);
544+ mt7915_dma_reset(dev, false);
545
546 mt7915_tx_token_put(dev);
547 idr_init(&dev->mt76.token);
developer1d9fede2022-08-29 15:24:07 +0800548@@ -1482,6 +1615,34 @@ void mt7915_mac_reset_work(struct work_struct *work)
developere3d01472022-05-09 14:01:49 +0800549 MT7915_WATCHDOG_TIME);
550 }
551
552+void mt7915_reset(struct mt7915_dev *dev)
553+{
554+ if (!dev->ser.hw_init_done)
555+ return;
556+
557+ if (dev->ser.hw_full_reset)
558+ return;
559+
560+ /* wm/wa exception: do full recovery */
561+ if (READ_ONCE(dev->reset_state) & MT_MCU_CMD_WDT_MASK) {
562+ dev_info(dev->mt76.dev, "SER: chip full recovery start, WM %d, WA %d\n",
563+ dev->ser.wf_reset_wm_count,
564+ dev->ser.wf_reset_wa_count);
565+
566+ dev->ser.reset_type = SER_TYPE_FULL_RESET;
567+
568+ mt7915_irq_disable(dev, MT_INT_MCU_CMD);
569+ queue_work(dev->mt76.wq, &dev->reset_work);
570+ return;
571+ }
572+
573+ dev_info(dev->mt76.dev, "SER: chip partial recovery, reset_state(0x%08X)\n",
574+ READ_ONCE(dev->reset_state));
575+ dev->ser.reset_type = SER_TYPE_PARTIAL_RESET;
576+ queue_work(dev->mt76.wq, &dev->reset_work);
577+ wake_up(&dev->reset_wait);
578+}
579+
580 void mt7915_mac_update_stats(struct mt7915_phy *phy)
581 {
582 struct mt7915_dev *dev = phy->dev;
583diff --git a/mt7915/main.c b/mt7915/main.c
developer1d9fede2022-08-29 15:24:07 +0800584index 4e82904f..7a7ff86a 100644
developere3d01472022-05-09 14:01:49 +0800585--- a/mt7915/main.c
586+++ b/mt7915/main.c
587@@ -20,17 +20,13 @@ static bool mt7915_dev_running(struct mt7915_dev *dev)
588 return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
589 }
590
591-static int mt7915_start(struct ieee80211_hw *hw)
592+int __mt7915_start(struct ieee80211_hw *hw)
593 {
594 struct mt7915_dev *dev = mt7915_hw_dev(hw);
595 struct mt7915_phy *phy = mt7915_hw_phy(hw);
596 bool running;
597 int ret;
598
599- flush_work(&dev->init_work);
600-
601- mutex_lock(&dev->mt76.mutex);
602-
603 running = mt7915_dev_running(dev);
604
605 if (!running) {
developer4721e252022-06-21 16:41:28 +0800606@@ -84,6 +80,18 @@ static int mt7915_start(struct ieee80211_hw *hw)
developere3d01472022-05-09 14:01:49 +0800607 mt7915_mac_reset_counters(phy);
608
609 out:
610+ return ret;
611+}
612+
613+static int mt7915_start(struct ieee80211_hw *hw)
614+{
615+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
developere3d01472022-05-09 14:01:49 +0800616+ int ret;
617+
618+ flush_work(&dev->init_work);
619+
620+ mutex_lock(&dev->mt76.mutex);
621+ ret = __mt7915_start(hw);
622 mutex_unlock(&dev->mt76.mutex);
623
624 return ret;
developer4721e252022-06-21 16:41:28 +0800625@@ -95,6 +103,7 @@ static void mt7915_stop(struct ieee80211_hw *hw)
developere3d01472022-05-09 14:01:49 +0800626 struct mt7915_phy *phy = mt7915_hw_phy(hw);
627
628 cancel_delayed_work_sync(&phy->mt76->mac_work);
629+ cancel_work_sync(&dev->reset_work);
630
631 mutex_lock(&dev->mt76.mutex);
632
633diff --git a/mt7915/mcu.c b/mt7915/mcu.c
developer1d9fede2022-08-29 15:24:07 +0800634index f692e520..5eac6ed6 100644
developere3d01472022-05-09 14:01:49 +0800635--- a/mt7915/mcu.c
636+++ b/mt7915/mcu.c
developerf64861f2022-06-22 11:44:53 +0800637@@ -150,19 +150,90 @@ mt7915_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs,
developere3d01472022-05-09 14:01:49 +0800638 ht_mcs[nss] = sta->ht_cap.mcs.rx_mask[nss] & mask[nss];
639 }
640
641+static int
642+mt7915_fw_exception_chk(struct mt7915_dev *dev)
643+{
644+ u32 reg_val;
645+
646+ reg_val = mt76_rr(dev, MT_EXCEPTION_ADDR);
647+
648+ if (is_mt7915(&dev->mt76))
649+ reg_val >>= 8;
650+
651+ return !!(reg_val & 0xff);
652+}
653+
654+static void
655+mt7915_fw_heart_beat_chk(struct mt7915_dev *dev)
656+{
657+#define WM_TIMEOUT_COUNT_CHECK 5
658+#define WM_HANG_COUNT_CHECK 9
659+ static u32 cidx_rec[5], didx_rec[5];
660+ u32 cnt, cidx, didx, queue;
661+ u32 idx, i;
662+
663+ if (dev->ser.hw_full_reset)
664+ return;
665+
666+ if (dev->ser.cmd_fail_cnt >= WM_TIMEOUT_COUNT_CHECK) {
667+ cnt = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 4);
668+ cidx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 8);
669+ didx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 12);
670+ queue = (didx > cidx) ?
671+ (didx - cidx - 1) : (didx - cidx + cnt - 1);
672+
673+ idx = (dev->ser.cmd_fail_cnt - WM_TIMEOUT_COUNT_CHECK) % 5;
674+ cidx_rec[idx] = cidx;
675+ didx_rec[idx] = didx;
676+
677+ if ((cnt - 1) == queue &&
678+ dev->ser.cmd_fail_cnt >= WM_HANG_COUNT_CHECK) {
679+
680+ for (i = 0; i < 5; i++) {
681+ if (cidx_rec[i] != cidx ||
682+ didx_rec[i] != didx)
683+ return;
684+ }
685+ dev_err(dev->mt76.dev, "detect mem dma hang!\n");
686+ if (dev->ser.reset_enable) {
687+ dev->reset_state |= MT_MCU_CMD_WDT_MASK;
688+ mt7915_reset(dev);
689+ }
690+ dev->ser.cmd_fail_cnt = 0;
691+ }
692+ }
693+}
694+
695 static int
696 mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
697 struct sk_buff *skb, int seq)
698 {
699+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
developerf64861f2022-06-22 11:44:53 +0800700 struct mt76_connac2_mcu_rxd *rxd;
developere3d01472022-05-09 14:01:49 +0800701 int ret = 0;
702
703 if (!skb) {
704 dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
705 cmd, seq);
706+
707+ dev->ser.cmd_fail_cnt++;
708+
709+ if (dev->ser.cmd_fail_cnt < 5) {
710+ int exp_type = mt7915_fw_exception_chk(dev);
711+
712+ dev_err(mdev->dev, "Fw is status(%d)\n", exp_type);
713+ if (exp_type && dev->ser.reset_enable) {
714+ dev->reset_state |= MT_MCU_CMD_WDT_MASK;
715+ mt7915_reset(dev);
716+ }
717+ }
718+ mt7915_fw_heart_beat_chk(dev);
719+
720 return -ETIMEDOUT;
721 }
722
723+ dev->ser.cmd_fail_cnt = 0;
724+
developerf64861f2022-06-22 11:44:53 +0800725 rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
developere3d01472022-05-09 14:01:49 +0800726 if (seq != rxd->seq)
727 return -EAGAIN;
developer1d9fede2022-08-29 15:24:07 +0800728@@ -2266,18 +2337,10 @@ mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)
developere3d01472022-05-09 14:01:49 +0800729 sizeof(req), true);
730 }
731
732-int mt7915_mcu_init(struct mt7915_dev *dev)
733+int mt7915_run_firmware(struct mt7915_dev *dev)
734 {
735- static const struct mt76_mcu_ops mt7915_mcu_ops = {
developerf64861f2022-06-22 11:44:53 +0800736- .headroom = sizeof(struct mt76_connac2_mcu_txd),
developere3d01472022-05-09 14:01:49 +0800737- .mcu_skb_send_msg = mt7915_mcu_send_message,
738- .mcu_parse_response = mt7915_mcu_parse_response,
739- .mcu_restart = mt76_connac_mcu_restart,
740- };
741 int ret;
742
743- dev->mt76.mcu_ops = &mt7915_mcu_ops;
744-
745 /* force firmware operation mode into normal state,
746 * which should be set before firmware download stage.
747 */
developer1d9fede2022-08-29 15:24:07 +0800748@@ -2326,6 +2389,20 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
developere3d01472022-05-09 14:01:49 +0800749 MCU_WA_PARAM_RED, 0, 0);
750 }
751
752+int mt7915_mcu_init(struct mt7915_dev *dev)
753+{
754+ static const struct mt76_mcu_ops mt7915_mcu_ops = {
developerf64861f2022-06-22 11:44:53 +0800755+ .headroom = sizeof(struct mt76_connac2_mcu_txd),
developere3d01472022-05-09 14:01:49 +0800756+ .mcu_skb_send_msg = mt7915_mcu_send_message,
757+ .mcu_parse_response = mt7915_mcu_parse_response,
758+ .mcu_restart = mt76_connac_mcu_restart,
759+ };
developere3d01472022-05-09 14:01:49 +0800760+
761+ dev->mt76.mcu_ops = &mt7915_mcu_ops;
762+
763+ return mt7915_run_firmware(dev);
764+}
765+
766 void mt7915_mcu_exit(struct mt7915_dev *dev)
767 {
768 __mt76_mcu_restart(&dev->mt76);
769diff --git a/mt7915/mcu.h b/mt7915/mcu.h
developerd59e4772022-07-14 13:48:49 +0800770index aab1a6a3..c4850644 100644
developere3d01472022-05-09 14:01:49 +0800771--- a/mt7915/mcu.h
772+++ b/mt7915/mcu.h
developerd59e4772022-07-14 13:48:49 +0800773@@ -453,8 +453,9 @@ enum {
developere3d01472022-05-09 14:01:49 +0800774
775 enum {
776 SER_QUERY,
777+ SER_SET,
778 /* recovery */
779- SER_SET_RECOVER_L1,
780+ SER_SET_RECOVER_L1 = 1,
781 SER_SET_RECOVER_L2,
782 SER_SET_RECOVER_L3_RX_ABORT,
783 SER_SET_RECOVER_L3_TX_ABORT,
784diff --git a/mt7915/mmio.c b/mt7915/mmio.c
developer1d9fede2022-08-29 15:24:07 +0800785index c81fa091..8469d8fb 100644
developere3d01472022-05-09 14:01:49 +0800786--- a/mt7915/mmio.c
787+++ b/mt7915/mmio.c
developerbd398d52022-06-06 20:53:24 +0800788@@ -24,6 +24,7 @@ static const u32 mt7915_reg[] = {
developere3d01472022-05-09 14:01:49 +0800789 [INFRA_MCU_ADDR_END] = 0x7c3fffff,
developerbd398d52022-06-06 20:53:24 +0800790 [FW_EXCEPTION_ADDR] = 0x219848,
developere3d01472022-05-09 14:01:49 +0800791 [SWDEF_BASE_ADDR] = 0x41f200,
792+ [EXCEPTION_BASE_ADDR] = 0x219848,
793 };
794
795 static const u32 mt7916_reg[] = {
developerbd398d52022-06-06 20:53:24 +0800796@@ -40,6 +41,7 @@ static const u32 mt7916_reg[] = {
developere3d01472022-05-09 14:01:49 +0800797 [INFRA_MCU_ADDR_END] = 0x7c085fff,
developerbd398d52022-06-06 20:53:24 +0800798 [FW_EXCEPTION_ADDR] = 0x022050bc,
developere3d01472022-05-09 14:01:49 +0800799 [SWDEF_BASE_ADDR] = 0x411400,
800+ [EXCEPTION_BASE_ADDR] = 0x022050BC,
801 };
802
803 static const u32 mt7986_reg[] = {
developerbd398d52022-06-06 20:53:24 +0800804@@ -56,6 +58,7 @@ static const u32 mt7986_reg[] = {
developere3d01472022-05-09 14:01:49 +0800805 [INFRA_MCU_ADDR_END] = 0x7c085fff,
developerbd398d52022-06-06 20:53:24 +0800806 [FW_EXCEPTION_ADDR] = 0x02204ffc,
developere3d01472022-05-09 14:01:49 +0800807 [SWDEF_BASE_ADDR] = 0x411400,
808+ [EXCEPTION_BASE_ADDR] = 0x02204FFC,
809 };
810
811 static const u32 mt7915_offs[] = {
developerbd398d52022-06-06 20:53:24 +0800812@@ -613,10 +616,9 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
developere3d01472022-05-09 14:01:49 +0800813 u32 val = mt76_rr(dev, MT_MCU_CMD);
814
815 mt76_wr(dev, MT_MCU_CMD, val);
816- if (val & MT_MCU_CMD_ERROR_MASK) {
817+ if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) {
818 dev->reset_state = val;
819- queue_work(dev->mt76.wq, &dev->reset_work);
820- wake_up(&dev->reset_wait);
821+ mt7915_reset(dev);
822 }
823 }
824 }
825diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
developer1d9fede2022-08-29 15:24:07 +0800826index 267fa7eb..d214b181 100644
developere3d01472022-05-09 14:01:49 +0800827--- a/mt7915/mt7915.h
828+++ b/mt7915/mt7915.h
developerf64861f2022-06-22 11:44:53 +0800829@@ -352,6 +352,15 @@ struct mt7915_dev {
developere3d01472022-05-09 14:01:49 +0800830 struct work_struct reset_work;
831 wait_queue_head_t reset_wait;
832 u32 reset_state;
833+ struct {
834+ bool hw_full_reset:1;
835+ bool hw_init_done:1;
836+ bool reset_enable:1;
837+ u32 reset_type;
838+ u32 cmd_fail_cnt;
839+ u32 wf_reset_wm_count;
840+ u32 wf_reset_wa_count;
841+ }ser;
842
843 struct list_head sta_rc_list;
844 struct list_head sta_poll_list;
developer4721e252022-06-21 16:41:28 +0800845@@ -416,6 +425,12 @@ enum {
developere3d01472022-05-09 14:01:49 +0800846 __MT_WFDMA_MAX,
847 };
848
849+enum {
850+ SER_TYPE_NONE,
851+ SER_TYPE_PARTIAL_RESET,
852+ SER_TYPE_FULL_RESET,
853+};
854+
855 enum {
developerf64861f2022-06-22 11:44:53 +0800856 MT_RX_SEL0,
857 MT_RX_SEL1,
developer1d9fede2022-08-29 15:24:07 +0800858@@ -514,6 +529,14 @@ s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band);
developere3d01472022-05-09 14:01:49 +0800859 int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2);
860 void mt7915_dma_prefetch(struct mt7915_dev *dev);
861 void mt7915_dma_cleanup(struct mt7915_dev *dev);
862+void mt7915_reset(struct mt7915_dev *dev);
863+int mt7915_dma_reset(struct mt7915_dev *dev, bool force);
864+int __mt7915_start(struct ieee80211_hw *hw);
865+void mt7915_init_txpower(struct mt7915_dev *dev,
866+ struct ieee80211_supported_band *sband);
867+int mt7915_txbf_init(struct mt7915_dev *dev);
868+void mt7915_mac_init(struct mt7915_dev *dev);
869+int mt7915_run_firmware(struct mt7915_dev *dev);
870 int mt7915_mcu_init(struct mt7915_dev *dev);
871 int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
872 struct mt7915_vif *mvif,
873diff --git a/mt7915/regs.h b/mt7915/regs.h
developer1d9fede2022-08-29 15:24:07 +0800874index 16875680..3d2c15be 100644
developere3d01472022-05-09 14:01:49 +0800875--- a/mt7915/regs.h
876+++ b/mt7915/regs.h
developer1d9fede2022-08-29 15:24:07 +0800877@@ -26,6 +26,7 @@ enum reg_rev {
developere3d01472022-05-09 14:01:49 +0800878 INFRA_MCU_ADDR_END,
developerbd398d52022-06-06 20:53:24 +0800879 FW_EXCEPTION_ADDR,
developere3d01472022-05-09 14:01:49 +0800880 SWDEF_BASE_ADDR,
881+ EXCEPTION_BASE_ADDR,
882 __MT_REG_MAX,
883 };
884
developer1d9fede2022-08-29 15:24:07 +0800885@@ -107,6 +108,11 @@ enum offs_rev {
developere3d01472022-05-09 14:01:49 +0800886 #define __REG(id) (dev->reg.reg_rev[(id)])
887 #define __OFFS(id) (dev->reg.offs_rev[(id)])
888
889+/* MEM WFDMA */
890+#define WF_WFDMA_MEM_DMA 0x58000000
891+
892+#define WF_WFDMA_MEM_DMA_RX_RING_CTL (WF_WFDMA_MEM_DMA + (0x510))
893+
894 /* MCU WFDMA0 */
895 #define MT_MCU_WFDMA0_BASE 0x2000
896 #define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs))
developer1d9fede2022-08-29 15:24:07 +0800897@@ -559,6 +565,10 @@ enum offs_rev {
developere3d01472022-05-09 14:01:49 +0800898 #define MT_WFDMA0_PRI_DLY_INT_CFG1 MT_WFDMA0(0x2f4)
899 #define MT_WFDMA0_PRI_DLY_INT_CFG2 MT_WFDMA0(0x2f8)
900
901+#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
902+#define MT_WFDMA0_MT_WA_WDT_INT BIT(31)
903+#define MT_WFDMA0_MT_WM_WDT_INT BIT(30)
904+
905 /* WFDMA1 */
906 #define MT_WFDMA1_BASE 0xd5000
907 #define MT_WFDMA1(ofs) (MT_WFDMA1_BASE + (ofs))
developer1d9fede2022-08-29 15:24:07 +0800908@@ -704,6 +714,10 @@ enum offs_rev {
developere3d01472022-05-09 14:01:49 +0800909 #define MT_MCU_CMD_NORMAL_STATE BIT(5)
910 #define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
911
912+#define MT_MCU_CMD_WA_WDT BIT(31)
913+#define MT_MCU_CMD_WM_WDT BIT(30)
914+#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30)
915+
916 /* TOP RGU */
917 #define MT_TOP_RGU_BASE 0x18000000
918 #define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0))
developer1d9fede2022-08-29 15:24:07 +0800919@@ -979,6 +993,8 @@ enum offs_rev {
developere3d01472022-05-09 14:01:49 +0800920 #define MT_CPU_UTIL_PEAK_IDLE_CNT MT_CPU_UTIL(0x0c)
921 #define MT_CPU_UTIL_CTRL MT_CPU_UTIL(0x1c)
922
923+#define MT_EXCEPTION_ADDR __REG(EXCEPTION_BASE_ADDR)
924+
925 /* LED */
926 #define MT_LED_TOP_BASE 0x18013000
927 #define MT_LED_PHYS(_n) (MT_LED_TOP_BASE + (_n))
928--
developer1d9fede2022-08-29 15:24:07 +08009292.18.0
developere3d01472022-05-09 14:01:49 +0800930