blob: 76ecbcf9dbeb17bce8af8cb323db63820851707d [file] [log] [blame]
developer20747c12022-09-16 14:09:40 +08001From 18093d743469680c1ae7b8f91837dc3804cc1756 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 +-
developer20747c12022-09-16 14:09:40 +080011 mt7915/mac.c | 281 +++++++++++++++++++++++++++++++++++++----------
developer1d9fede2022-08-29 15:24:07 +080012 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 +++
developer20747c12022-09-16 14:09:40 +080018 10 files changed, 491 insertions(+), 98 deletions(-)
developere3d01472022-05-09 14:01:49 +080019
20diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
developer20747c12022-09-16 14:09:40 +080021index ea512fd1..0fe95f84 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
developer20747c12022-09-16 14:09:40 +0800145index f7e6bb10..4b594a53 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
developer20747c12022-09-16 14:09:40 +0800204index 37b7b54a..141c5ad8 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
developer20747c12022-09-16 14:09:40 +0800244index 4d777fd5..d44af409 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"
developer20747c12022-09-16 14:09:40 +0800255@@ -1318,85 +1319,187 @@ mt7915_update_beacons(struct mt7915_dev *dev)
developer1d9fede2022-08-29 15:24:07 +0800256 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+ ext_phy = dev->mt76.phys[MT_BAND1];
developere3d01472022-05-09 14:01:49 +0800455+ phy2 = ext_phy ? ext_phy->priv : NULL;
456+
457+ dev->ser.hw_full_reset = true;
458+ if (READ_ONCE(dev->reset_state) & MT_MCU_CMD_WA_WDT)
459+ dev->ser.wf_reset_wa_count++;
460+ else
461+ dev->ser.wf_reset_wm_count++;
462+
463+ wake_up(&dev->mt76.mcu.wait);
464+ ieee80211_stop_queues(mt76_hw(dev));
465+ if (ext_phy)
466+ ieee80211_stop_queues(ext_phy->hw);
467+
468+ cancel_delayed_work_sync(&dev->mphy.mac_work);
469+ if (ext_phy)
470+ cancel_delayed_work_sync(&ext_phy->mac_work);
471+
472+ mutex_lock(&dev->mt76.mutex);
473+ for (i = 0; i < 10; i++) {
474+ if (!mt7915_mac_reset(dev))
475+ break;
developer20747c12022-09-16 14:09:40 +0800476 }
477- spin_unlock_bh(&dev->mt76.token_lock);
478- idr_destroy(&dev->mt76.token);
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 */
developer20747c12022-09-16 14:09:40 +0800502@@ -1411,6 +1514,36 @@ void mt7915_mac_reset_work(struct work_struct *work)
developer1d9fede2022-08-29 15:24:07 +0800503 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
developer20747c12022-09-16 14:09:40 +0800539@@ -1436,7 +1569,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);
developer20747c12022-09-16 14:09:40 +0800548@@ -1485,6 +1618,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
developer20747c12022-09-16 14:09:40 +0800584index e2f557a2..5b25604e 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
developer20747c12022-09-16 14:09:40 +0800634index b4cf4d86..3f18967a 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;
developer20747c12022-09-16 14:09:40 +0800728@@ -2268,18 +2339,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 */
developer20747c12022-09-16 14:09:40 +0800748@@ -2328,6 +2391,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
developer20747c12022-09-16 14:09:40 +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
developer20747c12022-09-16 14:09:40 +0800785index 68d978f4..fd2f70e3 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[] = {
developer20747c12022-09-16 14:09:40 +0800812@@ -615,10 +618,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
developer20747c12022-09-16 14:09:40 +0800826index f08974bb..e8feba36 100644
developere3d01472022-05-09 14:01:49 +0800827--- a/mt7915/mt7915.h
828+++ b/mt7915/mt7915.h
developer20747c12022-09-16 14:09:40 +0800829@@ -350,6 +350,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;
developer20747c12022-09-16 14:09:40 +0800845@@ -414,6 +423,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,
developer20747c12022-09-16 14:09:40 +0800858@@ -512,6 +527,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
developer20747c12022-09-16 14:09:40 +0800874index 6d9d187a..e2b0ff7d 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
developer20747c12022-09-16 14:09:40 +0800885@@ -108,6 +109,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))
developer20747c12022-09-16 14:09:40 +0800897@@ -563,6 +569,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))
developer20747c12022-09-16 14:09:40 +0800908@@ -708,6 +718,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))
developer20747c12022-09-16 14:09:40 +0800919@@ -983,6 +997,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--
developer20747c12022-09-16 14:09:40 +08009292.25.1
developere3d01472022-05-09 14:01:49 +0800930