blob: 652c4e4e7e7add1a7d181c1edf2bf02c03278c4d [file] [log] [blame]
developer5e5d6802022-09-01 10:53:06 +08001From c98da6a8443de7aeb6104de3ddc200253f0ee116 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
developer5ce5ea42022-08-31 14:12:29 +08004Subject: [PATCH 1006/1009] mt76: mt7915: add L0.5 system error recovery
5 support
developere3d01472022-05-09 14:01:49 +08006
developere3d01472022-05-09 14:01:49 +08007---
developer1d9fede2022-08-29 15:24:07 +08008 mt7915/debugfs.c | 88 ++++++++++++---
9 mt7915/dma.c | 48 ++++++++
10 mt7915/init.c | 8 +-
11 mt7915/mac.c | 283 +++++++++++++++++++++++++++++++++++++----------
12 mt7915/main.c | 19 +++-
13 mt7915/mcu.c | 95 ++++++++++++++--
14 mt7915/mcu.h | 3 +-
15 mt7915/mmio.c | 8 +-
16 mt7915/mt7915.h | 23 ++++
17 mt7915/regs.h | 16 +++
18 10 files changed, 492 insertions(+), 99 deletions(-)
developere3d01472022-05-09 14:01:49 +080019
20diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
developer5ce5ea42022-08-31 14:12:29 +080021index 0cfb606..07de2ee 100644
developere3d01472022-05-09 14:01:49 +080022--- a/mt7915/debugfs.c
23+++ b/mt7915/debugfs.c
developerbd398d52022-06-06 20:53:24 +080024@@ -52,12 +52,17 @@ static ssize_t
developere3d01472022-05-09 14:01:49 +080025 mt7915_fw_ser_set(struct file *file, const char __user *user_buf,
26 size_t count, loff_t *ppos)
27 {
28+#define SER_LEVEL GENMASK(3, 0)
29+#define SER_ACTION GENMASK(11, 8)
30+
31 struct mt7915_phy *phy = file->private_data;
32 struct mt7915_dev *dev = phy->dev;
33- bool ext_phy = phy != &dev->phy;
34+ u8 ser_action, ser_set, set_val;
35+ u8 band_idx = phy->band_idx;
36 char buf[16];
37 int ret = 0;
38 u16 val;
39+ u32 intr;
40
41 if (count >= sizeof(buf))
42 return -EINVAL;
developerbd398d52022-06-06 20:53:24 +080043@@ -73,28 +78,71 @@ mt7915_fw_ser_set(struct file *file, const char __user *user_buf,
developere3d01472022-05-09 14:01:49 +080044 if (kstrtou16(buf, 0, &val))
45 return -EINVAL;
46
47- switch (val) {
48+ ser_action = FIELD_GET(SER_ACTION, val);
49+ ser_set = set_val = FIELD_GET(SER_LEVEL, val);
50+
51+ switch (ser_action) {
52 case SER_QUERY:
53 /* grab firmware SER stats */
54- ret = mt7915_mcu_set_ser(dev, 0, 0, ext_phy);
55+ ser_set = 0;
56 break;
57- case SER_SET_RECOVER_L1:
58- case SER_SET_RECOVER_L2:
59- case SER_SET_RECOVER_L3_RX_ABORT:
60- case SER_SET_RECOVER_L3_TX_ABORT:
61- case SER_SET_RECOVER_L3_TX_DISABLE:
62- case SER_SET_RECOVER_L3_BF:
63- ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), ext_phy);
64- if (ret)
65- return ret;
66-
67- ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, ext_phy);
68+ case SER_SET:
69+ /*
70+ * 0x100: disable system error recovery function.
71+ * 0x101: enable system error recovery function.
72+ * 0x103: enable l0.5 recover function.
73+ */
74+ ser_set = !!set_val;
75+
76+ dev->ser.reset_enable = ser_set;
77+ intr = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
78+ if (dev->ser.reset_enable)
79+ intr |= MT_MCU_CMD_WDT_MASK;
80+ else
81+ intr &= ~MT_MCU_CMD_WDT_MASK;
82+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, intr);
83 break;
84- default:
85+ case SER_ENABLE:
86+ /*
87+ * 0x200: enable system error tracking.
88+ * 0x201: enable system error L1 recover.
89+ * 0x202: enable system error L2 recover.
90+ * 0x203: enable system error L3 rx abort.
91+ * 0x204: enable system error L3 tx abort.
92+ * 0x205: enable system error L3 tx disable.
93+ * 0x206: enable system error L3 bf recover.
94+ * 0x207: enable system error all recover.
95+ */
96+ ser_set = set_val > 7 ? 0x7f : BIT(set_val);
97+ break;
98+ case SER_RECOVER:
99+ /*
100+ * 0x300: trigger L0.5 recover.
101+ * 0x301: trigger L1 recover.
102+ * 0x302: trigger L2 recover.
103+ * 0x303: trigger L3 rx abort.
104+ * 0x304: trigger L3 tx abort
105+ * 0x305: trigger L3 tx disable.
106+ * 0x306: trigger L3 bf recover.
107+ */
108+ if (!ser_set) {
109+ if (dev->ser.reset_enable) {
110+ dev->reset_state |= MT_MCU_CMD_WDT_MASK;
111+ mt7915_reset(dev);
112+ } else {
113+ dev_info(dev->mt76.dev, "SER: chip full recovery not enable\n");
114+ }
115+ goto out;
116+ }
117 break;
118+ default:
119+ goto out;
120 }
121-
122- return ret ? ret : count;
123+ ret = mt7915_mcu_set_ser(dev, ser_action, ser_set, band_idx);
124+ if (ret)
125+ return ret;
126+out:
127+ return count;
128 }
129
130 static ssize_t
developerbd398d52022-06-06 20:53:24 +0800131@@ -143,6 +191,12 @@ mt7915_fw_ser_get(struct file *file, char __user *user_buf,
developere3d01472022-05-09 14:01:49 +0800132 "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n",
133 mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
134
135+ desc += scnprintf(buff + desc, bufsz - desc,
136+ "\nWF RESET STATUS: EN %d, WM %d, WA %d\n",
137+ dev->ser.reset_enable,
138+ dev->ser.wf_reset_wm_count,
139+ dev->ser.wf_reset_wa_count);
140+
141 ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
142 kfree(buff);
143 return ret;
144diff --git a/mt7915/dma.c b/mt7915/dma.c
developer5ce5ea42022-08-31 14:12:29 +0800145index f7e6bb1..4b594a5 100644
developere3d01472022-05-09 14:01:49 +0800146--- a/mt7915/dma.c
147+++ b/mt7915/dma.c
developer1d9fede2022-08-29 15:24:07 +0800148@@ -479,6 +479,54 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
developere3d01472022-05-09 14:01:49 +0800149 return 0;
150 }
151
152+int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
153+{
developer1d9fede2022-08-29 15:24:07 +0800154+ struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800155+ int i;
156+
157+ /* clean up hw queues */
158+ for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++) {
159+ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
160+ if (mphy_ext)
161+ mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
162+ }
163+
164+ for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
165+ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
166+
167+ mt76_for_each_q_rx(&dev->mt76, i)
168+ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
169+
170+ /* reset wfsys */
171+ if (force)
172+ mt7915_wfsys_reset(dev);
173+
174+ /* disable wfdma */
175+ mt7915_dma_disable(dev, force);
176+
177+ /* reset hw queues */
178+ for (i = 0; i < __MT_TXQ_MAX; i++) {
179+ mt76_queue_reset(dev, dev->mphy.q_tx[i]);
180+ if (mphy_ext)
181+ mt76_queue_reset(dev, mphy_ext->q_tx[i]);
182+ }
183+
184+ for (i = 0; i < __MT_MCUQ_MAX; i++)
185+ mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
186+
187+ mt76_for_each_q_rx(&dev->mt76, i)
188+ mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
189+
190+ mt76_tx_status_check(&dev->mt76, true);
191+
192+ mt7915_dma_enable(dev);
193+
194+ mt76_for_each_q_rx(&dev->mt76, i)
195+ mt76_queue_rx_reset(dev, i);
196+
197+ return 0;
198+}
199+
200 void mt7915_dma_cleanup(struct mt7915_dev *dev)
201 {
202 mt7915_dma_disable(dev, true);
203diff --git a/mt7915/init.c b/mt7915/init.c
developer5ce5ea42022-08-31 14:12:29 +0800204index 37b7b54..141c5ad 100644
developere3d01472022-05-09 14:01:49 +0800205--- a/mt7915/init.c
206+++ b/mt7915/init.c
207@@ -262,7 +262,7 @@ static void mt7915_led_set_brightness(struct led_classdev *led_cdev,
208 mt7915_led_set_config(led_cdev, 0xff, 0);
209 }
210
211-static void
212+void
213 mt7915_init_txpower(struct mt7915_dev *dev,
214 struct ieee80211_supported_band *sband)
215 {
developerf64861f2022-06-22 11:44:53 +0800216@@ -449,7 +449,7 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
developere3d01472022-05-09 14:01:49 +0800217 mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
218 }
219
220-static void mt7915_mac_init(struct mt7915_dev *dev)
221+void mt7915_mac_init(struct mt7915_dev *dev)
222 {
223 int i;
224 u32 rx_len = is_mt7915(&dev->mt76) ? 0x400 : 0x680;
developerf64861f2022-06-22 11:44:53 +0800225@@ -479,7 +479,7 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
developere3d01472022-05-09 14:01:49 +0800226 }
227 }
228
229-static int mt7915_txbf_init(struct mt7915_dev *dev)
230+int mt7915_txbf_init(struct mt7915_dev *dev)
231 {
232 int ret;
233
developerf64861f2022-06-22 11:44:53 +0800234@@ -1162,6 +1162,8 @@ int mt7915_register_device(struct mt7915_dev *dev)
developere3d01472022-05-09 14:01:49 +0800235
236 mt7915_init_debugfs(&dev->phy);
237
238+ dev->ser.hw_init_done = true;
239+
240 return 0;
241
242 unreg_thermal:
243diff --git a/mt7915/mac.c b/mt7915/mac.c
developer5ce5ea42022-08-31 14:12:29 +0800244index 6b3fa4c..e540941 100644
developere3d01472022-05-09 14:01:49 +0800245--- a/mt7915/mac.c
246+++ b/mt7915/mac.c
247@@ -3,6 +3,7 @@
248
249 #include <linux/etherdevice.h>
250 #include <linux/timekeeping.h>
251+#include <linux/pci.h>
252 #include "mt7915.h"
253 #include "../dma.h"
254 #include "mac.h"
developer1d9fede2022-08-29 15:24:07 +0800255@@ -1315,85 +1316,187 @@ mt7915_update_beacons(struct mt7915_dev *dev)
256 mt7915_update_vif_beacon, mphy_ext->hw);
developere3d01472022-05-09 14:01:49 +0800257 }
258
259-static void
260-mt7915_dma_reset(struct mt7915_dev *dev)
261+void mt7915_tx_token_put(struct mt7915_dev *dev)
262 {
developer1d9fede2022-08-29 15:24:07 +0800263- struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800264- u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
265- int i;
266+ struct mt76_txwi_cache *txwi;
267+ int id;
developerf64861f2022-06-22 11:44:53 +0800268+
developere3d01472022-05-09 14:01:49 +0800269+ spin_lock_bh(&dev->mt76.token_lock);
270+ idr_for_each_entry(&dev->mt76.token, txwi, id) {
271+ mt7915_txwi_free(dev, txwi, NULL, NULL);
272+ dev->mt76.token_count--;
273+ }
274+ spin_unlock_bh(&dev->mt76.token_lock);
275+ idr_destroy(&dev->mt76.token);
276+}
developerf64861f2022-06-22 11:44:53 +0800277+
developere3d01472022-05-09 14:01:49 +0800278+static int
279+mt7915_mac_reset(struct mt7915_dev *dev)
280+{
281+ struct mt7915_phy *phy2;
282+ struct mt76_phy *ext_phy;
283+ struct mt76_dev *mdev = &dev->mt76;
284+ int i, ret;
285+ u32 irq_mask;
developerf64861f2022-06-22 11:44:53 +0800286
287- mt76_clear(dev, MT_WFDMA0_GLO_CFG,
288- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
289- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
developer1d9fede2022-08-29 15:24:07 +0800290+ ext_phy = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800291+ phy2 = ext_phy ? ext_phy->priv : NULL;
developerf64861f2022-06-22 11:44:53 +0800292
293- if (is_mt7915(&dev->mt76))
294- mt76_clear(dev, MT_WFDMA1_GLO_CFG,
295- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
296- MT_WFDMA1_GLO_CFG_RX_DMA_EN);
developere3d01472022-05-09 14:01:49 +0800297 if (dev->hif2) {
298- mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
299- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
300- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
developerf64861f2022-06-22 11:44:53 +0800301-
302- if (is_mt7915(&dev->mt76))
303- mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
304- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
305- MT_WFDMA1_GLO_CFG_RX_DMA_EN);
developere3d01472022-05-09 14:01:49 +0800306+ mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
307+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
developer1d9fede2022-08-29 15:24:07 +0800308 }
309
310- usleep_range(1000, 2000);
developere3d01472022-05-09 14:01:49 +0800311+ if (dev_is_pci(mdev->dev)) {
312+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
313+ if (dev->hif2)
314+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
developer1d9fede2022-08-29 15:24:07 +0800315+ }
developere3d01472022-05-09 14:01:49 +0800316
developerf64861f2022-06-22 11:44:53 +0800317- for (i = 0; i < __MT_TXQ_MAX; i++) {
318- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
319- if (mphy_ext)
320- mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true);
developere3d01472022-05-09 14:01:49 +0800321+ set_bit(MT76_RESET, &dev->mphy.state);
322+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
323+ wake_up(&dev->mt76.mcu.wait);
324+ if (ext_phy) {
325+ set_bit(MT76_RESET, &ext_phy->state);
326+ set_bit(MT76_MCU_RESET, &ext_phy->state);
327 }
328
developerf64861f2022-06-22 11:44:53 +0800329- for (i = 0; i < __MT_MCUQ_MAX; i++)
330- mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
developere3d01472022-05-09 14:01:49 +0800331+ /* lock/unlock all queues to ensure that no tx is pending */
332+ mt76_txq_schedule_all(&dev->mphy);
333+ if (ext_phy)
334+ mt76_txq_schedule_all(ext_phy);
335
developerf64861f2022-06-22 11:44:53 +0800336- mt76_for_each_q_rx(&dev->mt76, i)
337- mt76_queue_rx_reset(dev, i);
developere3d01472022-05-09 14:01:49 +0800338+ /* disable all tx/rx napi */
339+ mt76_worker_disable(&dev->mt76.tx_worker);
340+ mt76_for_each_q_rx(mdev, i) {
341+ if (mdev->q_rx[i].ndesc)
342+ napi_disable(&dev->mt76.napi[i]);
developerf64861f2022-06-22 11:44:53 +0800343+ }
developere3d01472022-05-09 14:01:49 +0800344+ napi_disable(&dev->mt76.tx_napi);
345
developerf64861f2022-06-22 11:44:53 +0800346- mt76_tx_status_check(&dev->mt76, true);
developere3d01472022-05-09 14:01:49 +0800347+ /* token reinit */
348+ mt7915_tx_token_put(dev);
349+ idr_init(&dev->mt76.token);
350
developere3d01472022-05-09 14:01:49 +0800351- /* re-init prefetch settings after reset */
352- mt7915_dma_prefetch(dev);
developerf64861f2022-06-22 11:44:53 +0800353+ mt7915_dma_reset(dev, true);
developer1d9fede2022-08-29 15:24:07 +0800354+
developere3d01472022-05-09 14:01:49 +0800355+ local_bh_disable();
356+ mt76_for_each_q_rx(mdev, i) {
357+ if (mdev->q_rx[i].ndesc) {
358+ napi_enable(&dev->mt76.napi[i]);
359+ napi_schedule(&dev->mt76.napi[i]);
360+ }
361+ }
362+ local_bh_enable();
363+ clear_bit(MT76_MCU_RESET, &dev->mphy.state);
364+ clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
developerf64861f2022-06-22 11:44:53 +0800365+
developere3d01472022-05-09 14:01:49 +0800366+ mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
367+ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
developer1d9fede2022-08-29 15:24:07 +0800368
369- mt76_set(dev, MT_WFDMA0_GLO_CFG,
370- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
371- if (is_mt7915(&dev->mt76))
372- mt76_set(dev, MT_WFDMA1_GLO_CFG,
373- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
374- MT_WFDMA1_GLO_CFG_RX_DMA_EN |
375- MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
376- MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
developere3d01472022-05-09 14:01:49 +0800377 if (dev->hif2) {
378- mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
379- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
380- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
developerf64861f2022-06-22 11:44:53 +0800381-
382- if (is_mt7915(&dev->mt76))
383- mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
384- MT_WFDMA1_GLO_CFG_TX_DMA_EN |
385- MT_WFDMA1_GLO_CFG_RX_DMA_EN |
386- MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
387- MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
developere3d01472022-05-09 14:01:49 +0800388+ mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
389+ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
390+ }
391+ if (dev_is_pci(mdev->dev)) {
392+ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
393+ if (dev->hif2)
394+ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
395+ }
developerf64861f2022-06-22 11:44:53 +0800396+
developere3d01472022-05-09 14:01:49 +0800397+ /* load firmware */
398+ ret = mt7915_run_firmware(dev);
399+ if (ret)
400+ goto out;
401+
402+ /* set the necessary init items */
403+ ret = mt7915_mcu_set_eeprom(dev, dev->flash_mode);
404+ if (ret)
405+ goto out;
406+
407+ mt7915_mac_init(dev);
408+ mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
409+ mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
410+ ret = mt7915_txbf_init(dev);
developerbd398d52022-06-06 20:53:24 +0800411+
developere3d01472022-05-09 14:01:49 +0800412+ if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
413+ ret = __mt7915_start(dev->mphy.hw);
414+ if (ret)
415+ goto out;
developerbd398d52022-06-06 20:53:24 +0800416 }
developere3d01472022-05-09 14:01:49 +0800417+
418+ if (ext_phy && test_bit(MT76_STATE_RUNNING, &ext_phy->state)) {
419+ ret = __mt7915_start(ext_phy->hw);
420+ if (ret)
421+ goto out;
developerbd398d52022-06-06 20:53:24 +0800422+ }
developere3d01472022-05-09 14:01:49 +0800423+
424+out:
425+ /* reset done */
426+ clear_bit(MT76_RESET, &dev->mphy.state);
427+ if (phy2)
428+ clear_bit(MT76_RESET, &phy2->mt76->state);
429+
430+ local_bh_disable();
431+ napi_enable(&dev->mt76.tx_napi);
432+ napi_schedule(&dev->mt76.tx_napi);
433+ local_bh_enable();
434+
435+ mt76_worker_enable(&dev->mt76.tx_worker);
436+
437+ return ret;
438 }
439
440-void mt7915_tx_token_put(struct mt7915_dev *dev)
441+static void
442+mt7915_mac_full_reset(struct mt7915_dev *dev)
443 {
444- struct mt76_txwi_cache *txwi;
445- int id;
446+ struct mt7915_phy *phy2;
447+ struct mt76_phy *ext_phy;
448+ int i;
449
450- spin_lock_bh(&dev->mt76.token_lock);
451- idr_for_each_entry(&dev->mt76.token, txwi, id) {
452- mt7915_txwi_free(dev, txwi, NULL, NULL);
453- dev->mt76.token_count--;
developer1d9fede2022-08-29 15:24:07 +0800454- }
455- spin_unlock_bh(&dev->mt76.token_lock);
456- idr_destroy(&dev->mt76.token);
457+ ext_phy = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800458+ phy2 = ext_phy ? ext_phy->priv : NULL;
459+
460+ dev->ser.hw_full_reset = true;
461+ if (READ_ONCE(dev->reset_state) & MT_MCU_CMD_WA_WDT)
462+ dev->ser.wf_reset_wa_count++;
463+ else
464+ dev->ser.wf_reset_wm_count++;
465+
466+ wake_up(&dev->mt76.mcu.wait);
467+ ieee80211_stop_queues(mt76_hw(dev));
468+ if (ext_phy)
469+ ieee80211_stop_queues(ext_phy->hw);
470+
471+ cancel_delayed_work_sync(&dev->mphy.mac_work);
472+ if (ext_phy)
473+ cancel_delayed_work_sync(&ext_phy->mac_work);
474+
475+ mutex_lock(&dev->mt76.mutex);
476+ for (i = 0; i < 10; i++) {
477+ if (!mt7915_mac_reset(dev))
478+ break;
developer1d9fede2022-08-29 15:24:07 +0800479+ }
developere3d01472022-05-09 14:01:49 +0800480+ mutex_unlock(&dev->mt76.mutex);
481+
482+ if (i == 10)
483+ dev_err(dev->mt76.dev, "chip full reset failed\n");
484+
485+ ieee80211_restart_hw(mt76_hw(dev));
486+ if (ext_phy)
487+ ieee80211_restart_hw(ext_phy->hw);
488+
489+ ieee80211_wake_queues(mt76_hw(dev));
490+ if (ext_phy)
491+ ieee80211_wake_queues(ext_phy->hw);
492+
493+ dev->ser.hw_full_reset = false;
494+ ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
495+ MT7915_WATCHDOG_TIME);
496+ if (ext_phy)
497+ ieee80211_queue_delayed_work(ext_phy->hw,
498+ &ext_phy->mac_work,
499+ MT7915_WATCHDOG_TIME);
500 }
501
502 /* system error recovery */
developer1d9fede2022-08-29 15:24:07 +0800503@@ -1408,6 +1511,36 @@ void mt7915_mac_reset_work(struct work_struct *work)
504 ext_phy = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800505 phy2 = ext_phy ? ext_phy->priv : NULL;
506
507+ /* chip full reset */
508+ if (dev->ser.reset_type == SER_TYPE_FULL_RESET) {
509+ u32 intr;
510+
511+ /* disable WA/WM WDT */
512+ intr = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
513+ intr &= ~MT_MCU_CMD_WDT_MASK;
514+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, intr);
515+
516+ mt7915_mac_full_reset(dev);
517+
518+ /* enable the mcu irq*/
519+ mt7915_irq_enable(dev, MT_INT_MCU_CMD);
520+ mt7915_irq_disable(dev, 0);
521+
522+ /* re-enable WA/WM WDT */
523+ intr = mt76_rr(dev, MT_WFDMA0_MCU_HOST_INT_ENA);
524+ intr |= MT_MCU_CMD_WDT_MASK;
525+ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, intr);
526+
527+ dev->reset_state = MT_MCU_CMD_NORMAL_STATE;
528+ dev->ser.reset_type = SER_TYPE_NONE;
529+ dev_info(dev->mt76.dev, "SER: chip full reset completed, WM %d, WA %d\n",
530+ dev->ser.wf_reset_wm_count,
531+ dev->ser.wf_reset_wa_count);
532+ return;
533+ }
534+
535+ /* chip partial reset */
536+ dev->ser.reset_type = SER_TYPE_NONE;
537 if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
538 return;
539
developer1d9fede2022-08-29 15:24:07 +0800540@@ -1433,7 +1566,7 @@ void mt7915_mac_reset_work(struct work_struct *work)
developere3d01472022-05-09 14:01:49 +0800541 mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
542
543 if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
544- mt7915_dma_reset(dev);
545+ mt7915_dma_reset(dev, false);
546
547 mt7915_tx_token_put(dev);
548 idr_init(&dev->mt76.token);
developer1d9fede2022-08-29 15:24:07 +0800549@@ -1482,6 +1615,34 @@ void mt7915_mac_reset_work(struct work_struct *work)
developere3d01472022-05-09 14:01:49 +0800550 MT7915_WATCHDOG_TIME);
551 }
552
553+void mt7915_reset(struct mt7915_dev *dev)
554+{
555+ if (!dev->ser.hw_init_done)
556+ return;
557+
558+ if (dev->ser.hw_full_reset)
559+ return;
560+
561+ /* wm/wa exception: do full recovery */
562+ if (READ_ONCE(dev->reset_state) & MT_MCU_CMD_WDT_MASK) {
563+ dev_info(dev->mt76.dev, "SER: chip full recovery start, WM %d, WA %d\n",
564+ dev->ser.wf_reset_wm_count,
565+ dev->ser.wf_reset_wa_count);
566+
567+ dev->ser.reset_type = SER_TYPE_FULL_RESET;
568+
569+ mt7915_irq_disable(dev, MT_INT_MCU_CMD);
570+ queue_work(dev->mt76.wq, &dev->reset_work);
571+ return;
572+ }
573+
574+ dev_info(dev->mt76.dev, "SER: chip partial recovery, reset_state(0x%08X)\n",
575+ READ_ONCE(dev->reset_state));
576+ dev->ser.reset_type = SER_TYPE_PARTIAL_RESET;
577+ queue_work(dev->mt76.wq, &dev->reset_work);
578+ wake_up(&dev->reset_wait);
579+}
580+
581 void mt7915_mac_update_stats(struct mt7915_phy *phy)
582 {
583 struct mt7915_dev *dev = phy->dev;
584diff --git a/mt7915/main.c b/mt7915/main.c
developer5ce5ea42022-08-31 14:12:29 +0800585index 4e82904..7a7ff86 100644
developere3d01472022-05-09 14:01:49 +0800586--- a/mt7915/main.c
587+++ b/mt7915/main.c
588@@ -20,17 +20,13 @@ static bool mt7915_dev_running(struct mt7915_dev *dev)
589 return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
590 }
591
592-static int mt7915_start(struct ieee80211_hw *hw)
593+int __mt7915_start(struct ieee80211_hw *hw)
594 {
595 struct mt7915_dev *dev = mt7915_hw_dev(hw);
596 struct mt7915_phy *phy = mt7915_hw_phy(hw);
597 bool running;
598 int ret;
599
600- flush_work(&dev->init_work);
601-
602- mutex_lock(&dev->mt76.mutex);
603-
604 running = mt7915_dev_running(dev);
605
606 if (!running) {
developer4721e252022-06-21 16:41:28 +0800607@@ -84,6 +80,18 @@ static int mt7915_start(struct ieee80211_hw *hw)
developere3d01472022-05-09 14:01:49 +0800608 mt7915_mac_reset_counters(phy);
609
610 out:
611+ return ret;
612+}
613+
614+static int mt7915_start(struct ieee80211_hw *hw)
615+{
616+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
developere3d01472022-05-09 14:01:49 +0800617+ int ret;
618+
619+ flush_work(&dev->init_work);
620+
621+ mutex_lock(&dev->mt76.mutex);
622+ ret = __mt7915_start(hw);
623 mutex_unlock(&dev->mt76.mutex);
624
625 return ret;
developer4721e252022-06-21 16:41:28 +0800626@@ -95,6 +103,7 @@ static void mt7915_stop(struct ieee80211_hw *hw)
developere3d01472022-05-09 14:01:49 +0800627 struct mt7915_phy *phy = mt7915_hw_phy(hw);
628
629 cancel_delayed_work_sync(&phy->mt76->mac_work);
630+ cancel_work_sync(&dev->reset_work);
631
632 mutex_lock(&dev->mt76.mutex);
633
634diff --git a/mt7915/mcu.c b/mt7915/mcu.c
developer5ce5ea42022-08-31 14:12:29 +0800635index f692e52..5eac6ed 100644
developere3d01472022-05-09 14:01:49 +0800636--- a/mt7915/mcu.c
637+++ b/mt7915/mcu.c
developerf64861f2022-06-22 11:44:53 +0800638@@ -150,19 +150,90 @@ mt7915_mcu_set_sta_ht_mcs(struct ieee80211_sta *sta, u8 *ht_mcs,
developere3d01472022-05-09 14:01:49 +0800639 ht_mcs[nss] = sta->ht_cap.mcs.rx_mask[nss] & mask[nss];
640 }
641
642+static int
643+mt7915_fw_exception_chk(struct mt7915_dev *dev)
644+{
645+ u32 reg_val;
646+
647+ reg_val = mt76_rr(dev, MT_EXCEPTION_ADDR);
648+
649+ if (is_mt7915(&dev->mt76))
650+ reg_val >>= 8;
651+
652+ return !!(reg_val & 0xff);
653+}
654+
655+static void
656+mt7915_fw_heart_beat_chk(struct mt7915_dev *dev)
657+{
658+#define WM_TIMEOUT_COUNT_CHECK 5
659+#define WM_HANG_COUNT_CHECK 9
660+ static u32 cidx_rec[5], didx_rec[5];
661+ u32 cnt, cidx, didx, queue;
662+ u32 idx, i;
663+
664+ if (dev->ser.hw_full_reset)
665+ return;
666+
667+ if (dev->ser.cmd_fail_cnt >= WM_TIMEOUT_COUNT_CHECK) {
668+ cnt = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 4);
669+ cidx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 8);
670+ didx = mt76_rr(dev, WF_WFDMA_MEM_DMA_RX_RING_CTL + 12);
671+ queue = (didx > cidx) ?
672+ (didx - cidx - 1) : (didx - cidx + cnt - 1);
673+
674+ idx = (dev->ser.cmd_fail_cnt - WM_TIMEOUT_COUNT_CHECK) % 5;
675+ cidx_rec[idx] = cidx;
676+ didx_rec[idx] = didx;
677+
678+ if ((cnt - 1) == queue &&
679+ dev->ser.cmd_fail_cnt >= WM_HANG_COUNT_CHECK) {
680+
681+ for (i = 0; i < 5; i++) {
682+ if (cidx_rec[i] != cidx ||
683+ didx_rec[i] != didx)
684+ return;
685+ }
686+ dev_err(dev->mt76.dev, "detect mem dma hang!\n");
687+ if (dev->ser.reset_enable) {
688+ dev->reset_state |= MT_MCU_CMD_WDT_MASK;
689+ mt7915_reset(dev);
690+ }
691+ dev->ser.cmd_fail_cnt = 0;
692+ }
693+ }
694+}
695+
696 static int
697 mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
698 struct sk_buff *skb, int seq)
699 {
700+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
developerf64861f2022-06-22 11:44:53 +0800701 struct mt76_connac2_mcu_rxd *rxd;
developere3d01472022-05-09 14:01:49 +0800702 int ret = 0;
703
704 if (!skb) {
705 dev_err(mdev->dev, "Message %08x (seq %d) timeout\n",
706 cmd, seq);
707+
708+ dev->ser.cmd_fail_cnt++;
709+
710+ if (dev->ser.cmd_fail_cnt < 5) {
711+ int exp_type = mt7915_fw_exception_chk(dev);
712+
713+ dev_err(mdev->dev, "Fw is status(%d)\n", exp_type);
714+ if (exp_type && dev->ser.reset_enable) {
715+ dev->reset_state |= MT_MCU_CMD_WDT_MASK;
716+ mt7915_reset(dev);
717+ }
718+ }
719+ mt7915_fw_heart_beat_chk(dev);
720+
721 return -ETIMEDOUT;
722 }
723
724+ dev->ser.cmd_fail_cnt = 0;
725+
developerf64861f2022-06-22 11:44:53 +0800726 rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
developere3d01472022-05-09 14:01:49 +0800727 if (seq != rxd->seq)
728 return -EAGAIN;
developer1d9fede2022-08-29 15:24:07 +0800729@@ -2266,18 +2337,10 @@ mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)
developere3d01472022-05-09 14:01:49 +0800730 sizeof(req), true);
731 }
732
733-int mt7915_mcu_init(struct mt7915_dev *dev)
734+int mt7915_run_firmware(struct mt7915_dev *dev)
735 {
736- static const struct mt76_mcu_ops mt7915_mcu_ops = {
developerf64861f2022-06-22 11:44:53 +0800737- .headroom = sizeof(struct mt76_connac2_mcu_txd),
developere3d01472022-05-09 14:01:49 +0800738- .mcu_skb_send_msg = mt7915_mcu_send_message,
739- .mcu_parse_response = mt7915_mcu_parse_response,
740- .mcu_restart = mt76_connac_mcu_restart,
741- };
742 int ret;
743
744- dev->mt76.mcu_ops = &mt7915_mcu_ops;
745-
746 /* force firmware operation mode into normal state,
747 * which should be set before firmware download stage.
748 */
developer1d9fede2022-08-29 15:24:07 +0800749@@ -2326,6 +2389,20 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
developere3d01472022-05-09 14:01:49 +0800750 MCU_WA_PARAM_RED, 0, 0);
751 }
752
753+int mt7915_mcu_init(struct mt7915_dev *dev)
754+{
755+ static const struct mt76_mcu_ops mt7915_mcu_ops = {
developerf64861f2022-06-22 11:44:53 +0800756+ .headroom = sizeof(struct mt76_connac2_mcu_txd),
developere3d01472022-05-09 14:01:49 +0800757+ .mcu_skb_send_msg = mt7915_mcu_send_message,
758+ .mcu_parse_response = mt7915_mcu_parse_response,
759+ .mcu_restart = mt76_connac_mcu_restart,
760+ };
developere3d01472022-05-09 14:01:49 +0800761+
762+ dev->mt76.mcu_ops = &mt7915_mcu_ops;
763+
764+ return mt7915_run_firmware(dev);
765+}
766+
767 void mt7915_mcu_exit(struct mt7915_dev *dev)
768 {
769 __mt76_mcu_restart(&dev->mt76);
770diff --git a/mt7915/mcu.h b/mt7915/mcu.h
developer5ce5ea42022-08-31 14:12:29 +0800771index aab1a6a..c485064 100644
developere3d01472022-05-09 14:01:49 +0800772--- a/mt7915/mcu.h
773+++ b/mt7915/mcu.h
developerd59e4772022-07-14 13:48:49 +0800774@@ -453,8 +453,9 @@ enum {
developere3d01472022-05-09 14:01:49 +0800775
776 enum {
777 SER_QUERY,
778+ SER_SET,
779 /* recovery */
780- SER_SET_RECOVER_L1,
781+ SER_SET_RECOVER_L1 = 1,
782 SER_SET_RECOVER_L2,
783 SER_SET_RECOVER_L3_RX_ABORT,
784 SER_SET_RECOVER_L3_TX_ABORT,
785diff --git a/mt7915/mmio.c b/mt7915/mmio.c
developer5ce5ea42022-08-31 14:12:29 +0800786index c81fa09..8469d8f 100644
developere3d01472022-05-09 14:01:49 +0800787--- a/mt7915/mmio.c
788+++ b/mt7915/mmio.c
developerbd398d52022-06-06 20:53:24 +0800789@@ -24,6 +24,7 @@ static const u32 mt7915_reg[] = {
developere3d01472022-05-09 14:01:49 +0800790 [INFRA_MCU_ADDR_END] = 0x7c3fffff,
developerbd398d52022-06-06 20:53:24 +0800791 [FW_EXCEPTION_ADDR] = 0x219848,
developere3d01472022-05-09 14:01:49 +0800792 [SWDEF_BASE_ADDR] = 0x41f200,
793+ [EXCEPTION_BASE_ADDR] = 0x219848,
794 };
795
796 static const u32 mt7916_reg[] = {
developerbd398d52022-06-06 20:53:24 +0800797@@ -40,6 +41,7 @@ static const u32 mt7916_reg[] = {
developere3d01472022-05-09 14:01:49 +0800798 [INFRA_MCU_ADDR_END] = 0x7c085fff,
developerbd398d52022-06-06 20:53:24 +0800799 [FW_EXCEPTION_ADDR] = 0x022050bc,
developere3d01472022-05-09 14:01:49 +0800800 [SWDEF_BASE_ADDR] = 0x411400,
801+ [EXCEPTION_BASE_ADDR] = 0x022050BC,
802 };
803
804 static const u32 mt7986_reg[] = {
developerbd398d52022-06-06 20:53:24 +0800805@@ -56,6 +58,7 @@ static const u32 mt7986_reg[] = {
developere3d01472022-05-09 14:01:49 +0800806 [INFRA_MCU_ADDR_END] = 0x7c085fff,
developerbd398d52022-06-06 20:53:24 +0800807 [FW_EXCEPTION_ADDR] = 0x02204ffc,
developere3d01472022-05-09 14:01:49 +0800808 [SWDEF_BASE_ADDR] = 0x411400,
809+ [EXCEPTION_BASE_ADDR] = 0x02204FFC,
810 };
811
812 static const u32 mt7915_offs[] = {
developerbd398d52022-06-06 20:53:24 +0800813@@ -613,10 +616,9 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
developere3d01472022-05-09 14:01:49 +0800814 u32 val = mt76_rr(dev, MT_MCU_CMD);
815
816 mt76_wr(dev, MT_MCU_CMD, val);
817- if (val & MT_MCU_CMD_ERROR_MASK) {
818+ if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) {
819 dev->reset_state = val;
820- queue_work(dev->mt76.wq, &dev->reset_work);
821- wake_up(&dev->reset_wait);
822+ mt7915_reset(dev);
823 }
824 }
825 }
826diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
developer5ce5ea42022-08-31 14:12:29 +0800827index 267fa7e..d214b18 100644
developere3d01472022-05-09 14:01:49 +0800828--- a/mt7915/mt7915.h
829+++ b/mt7915/mt7915.h
developerf64861f2022-06-22 11:44:53 +0800830@@ -352,6 +352,15 @@ struct mt7915_dev {
developere3d01472022-05-09 14:01:49 +0800831 struct work_struct reset_work;
832 wait_queue_head_t reset_wait;
833 u32 reset_state;
834+ struct {
835+ bool hw_full_reset:1;
836+ bool hw_init_done:1;
837+ bool reset_enable:1;
838+ u32 reset_type;
839+ u32 cmd_fail_cnt;
840+ u32 wf_reset_wm_count;
841+ u32 wf_reset_wa_count;
842+ }ser;
843
844 struct list_head sta_rc_list;
845 struct list_head sta_poll_list;
developer4721e252022-06-21 16:41:28 +0800846@@ -416,6 +425,12 @@ enum {
developere3d01472022-05-09 14:01:49 +0800847 __MT_WFDMA_MAX,
848 };
849
850+enum {
851+ SER_TYPE_NONE,
852+ SER_TYPE_PARTIAL_RESET,
853+ SER_TYPE_FULL_RESET,
854+};
855+
856 enum {
developerf64861f2022-06-22 11:44:53 +0800857 MT_RX_SEL0,
858 MT_RX_SEL1,
developer1d9fede2022-08-29 15:24:07 +0800859@@ -514,6 +529,14 @@ s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band);
developere3d01472022-05-09 14:01:49 +0800860 int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2);
861 void mt7915_dma_prefetch(struct mt7915_dev *dev);
862 void mt7915_dma_cleanup(struct mt7915_dev *dev);
863+void mt7915_reset(struct mt7915_dev *dev);
864+int mt7915_dma_reset(struct mt7915_dev *dev, bool force);
865+int __mt7915_start(struct ieee80211_hw *hw);
866+void mt7915_init_txpower(struct mt7915_dev *dev,
867+ struct ieee80211_supported_band *sband);
868+int mt7915_txbf_init(struct mt7915_dev *dev);
869+void mt7915_mac_init(struct mt7915_dev *dev);
870+int mt7915_run_firmware(struct mt7915_dev *dev);
871 int mt7915_mcu_init(struct mt7915_dev *dev);
872 int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
873 struct mt7915_vif *mvif,
874diff --git a/mt7915/regs.h b/mt7915/regs.h
developer5ce5ea42022-08-31 14:12:29 +0800875index 1687568..3d2c15b 100644
developere3d01472022-05-09 14:01:49 +0800876--- a/mt7915/regs.h
877+++ b/mt7915/regs.h
developer1d9fede2022-08-29 15:24:07 +0800878@@ -26,6 +26,7 @@ enum reg_rev {
developere3d01472022-05-09 14:01:49 +0800879 INFRA_MCU_ADDR_END,
developerbd398d52022-06-06 20:53:24 +0800880 FW_EXCEPTION_ADDR,
developere3d01472022-05-09 14:01:49 +0800881 SWDEF_BASE_ADDR,
882+ EXCEPTION_BASE_ADDR,
883 __MT_REG_MAX,
884 };
885
developer1d9fede2022-08-29 15:24:07 +0800886@@ -107,6 +108,11 @@ enum offs_rev {
developere3d01472022-05-09 14:01:49 +0800887 #define __REG(id) (dev->reg.reg_rev[(id)])
888 #define __OFFS(id) (dev->reg.offs_rev[(id)])
889
890+/* MEM WFDMA */
891+#define WF_WFDMA_MEM_DMA 0x58000000
892+
893+#define WF_WFDMA_MEM_DMA_RX_RING_CTL (WF_WFDMA_MEM_DMA + (0x510))
894+
895 /* MCU WFDMA0 */
896 #define MT_MCU_WFDMA0_BASE 0x2000
897 #define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs))
developer1d9fede2022-08-29 15:24:07 +0800898@@ -559,6 +565,10 @@ enum offs_rev {
developere3d01472022-05-09 14:01:49 +0800899 #define MT_WFDMA0_PRI_DLY_INT_CFG1 MT_WFDMA0(0x2f4)
900 #define MT_WFDMA0_PRI_DLY_INT_CFG2 MT_WFDMA0(0x2f8)
901
902+#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
903+#define MT_WFDMA0_MT_WA_WDT_INT BIT(31)
904+#define MT_WFDMA0_MT_WM_WDT_INT BIT(30)
905+
906 /* WFDMA1 */
907 #define MT_WFDMA1_BASE 0xd5000
908 #define MT_WFDMA1(ofs) (MT_WFDMA1_BASE + (ofs))
developer1d9fede2022-08-29 15:24:07 +0800909@@ -704,6 +714,10 @@ enum offs_rev {
developere3d01472022-05-09 14:01:49 +0800910 #define MT_MCU_CMD_NORMAL_STATE BIT(5)
911 #define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
912
913+#define MT_MCU_CMD_WA_WDT BIT(31)
914+#define MT_MCU_CMD_WM_WDT BIT(30)
915+#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30)
916+
917 /* TOP RGU */
918 #define MT_TOP_RGU_BASE 0x18000000
919 #define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0))
developer1d9fede2022-08-29 15:24:07 +0800920@@ -979,6 +993,8 @@ enum offs_rev {
developere3d01472022-05-09 14:01:49 +0800921 #define MT_CPU_UTIL_PEAK_IDLE_CNT MT_CPU_UTIL(0x0c)
922 #define MT_CPU_UTIL_CTRL MT_CPU_UTIL(0x1c)
923
924+#define MT_EXCEPTION_ADDR __REG(EXCEPTION_BASE_ADDR)
925+
926 /* LED */
927 #define MT_LED_TOP_BASE 0x18013000
928 #define MT_LED_PHYS(_n) (MT_LED_TOP_BASE + (_n))
929--
developer1d9fede2022-08-29 15:24:07 +08009302.18.0
developere3d01472022-05-09 14:01:49 +0800931