-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathmt7927-wifi-10-add-mt7927-hardware-initialization.patch
More file actions
266 lines (243 loc) · 8.32 KB
/
mt7927-wifi-10-add-mt7927-hardware-initialization.patch
File metadata and controls
266 lines (243 loc) · 8.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
wifi: mt76: mt7925: add MT7927 hardware initialization
Add MT7927-specific hardware initialization for the Filogic 380 combo
chip, which has an additional CBInfra (ConnectaBus Infrastructure) bus
fabric between PCIe and the WiFi subsystem.
CBTOP remap: configure PCIe address mapping so MMIO reads to WiFi
registers return valid data instead of zero.
Chip initialization sequence:
1. WF subsystem reset via CBInfra RGU
2. MCU ownership acquisition
3. Poll ROMCODE_INDEX for MCU idle (0x1D1E)
4. MCIF remap for host DMA
5. PCIe sleep disable
Probe flow changes for MT7927:
- Skip early CLR_OWN (CBTOP not yet configured)
- Force chip ID if CHIPID register returns stale value
- Replace wfsys_reset with mt7927_chip_init
CLR_OWN skip in mt7925e_mcu_init(): every CLR_OWN triggers the ROM to
reinitialize WFDMA, destroying ring configuration set up by DMA init.
The controlled SET_OWN/CLR_OWN is already handled in the DMA pre-ring
setup hook.
DBDC enable: MT7927 firmware defaults to single-band (2.4GHz only).
Send explicit SET_DBDC_PARMS to enable dual-band operation.
CNM force: MT7927 firmware lacks the connac2 feature trailer, causing
channel context ops to be replaced with stubs. Force the CNM flag at
probe to preserve ROC support needed for authentication.
mac_reset guard: return -EOPNOTSUPP for MT7927 since the reset path
performs CLR_OWN and logic reset that destroy DMA configuration. Full
reset recovery is follow-up work.
Register values derived from Loong0x00's reverse-engineered MT7927
driver.
Reported-by: 张旭涵 <Loong.0x00@gmail.com>
Closes: https://github.com/openwrt/mt76/issues/927
Tested-by: Marcin FM <marcin@lgic.pl>
Tested-by: Cristian-Florin Radoi <radoi.chris@gmail.com>
Tested-by: George Salukvadze <giosal90@gmail.com>
Tested-by: Evgeny Kapusta <3193631@gmail.com>
Tested-by: Samu Toljamo <samu.toljamo@gmail.com>
Tested-by: Ariel Rosenfeld <ariel.rosenfeld.750@gmail.com>
Tested-by: Chapuis Dario <chapuisdario4@gmail.com>
Tested-by: Thibaut François <tibo@humeurlibre.fr>
Tested-by: 张旭涵 <Loong.0x00@gmail.com>
Signed-off-by: Javier Tia <floss@jetm.me>
1f0c7853737a0d87e7a0604cdf8fd2302a2f61e8
diff --git a/mt7925/init.c b/mt7925/init.c
index 3ce5d6f..c4c9938 100644
--- a/mt7925/init.c
+++ b/mt7925/init.c
@@ -117,2 +117,15 @@ static int __mt7925_init_hardware(struct mt792x_dev *dev)
+ /* MT7927: Enable DBDC (dual-band) mode. Without this, firmware
+ * defaults to 2.4GHz only and ignores 5GHz scan requests.
+ * MT7925 firmware handles DBDC automatically.
+ */
+ if (is_mt7927(&dev->mt76)) {
+ ret = mt7925_mcu_set_dbdc(&dev->mphy, true);
+ if (ret) {
+ dev_warn(dev->mt76.dev,
+ "MT7927 DBDC enable failed: %d\n", ret);
+ ret = 0;
+ }
+ }
+
out:
diff --git a/mt7925/pci.c b/mt7925/pci.c
index 415194a..393d9f4 100644
--- a/mt7925/pci.c
+++ b/mt7925/pci.c
@@ -402,2 +402,60 @@ static const struct mt792x_irq_map mt7927_irq_map = {
};
+
+static int mt7927_chip_init(struct mt792x_dev *dev)
+{
+ struct mt76_dev *mdev = &dev->mt76;
+ u32 val;
+
+ /* EMI sleep protect */
+ mt76_rmw_field(dev, MT_HW_EMI_CTL, MT_HW_EMI_CTL_SLPPROT_EN, 1);
+
+ /* WF subsystem reset via CBInfra RGU */
+ mt76_set(dev, MT7927_CBINFRA_RGU_WF_RST,
+ MT7927_CBINFRA_RGU_WF_RST_WF_SUBSYS);
+ msleep(1);
+ mt76_clear(dev, MT7927_CBINFRA_RGU_WF_RST,
+ MT7927_CBINFRA_RGU_WF_RST_WF_SUBSYS);
+ msleep(5);
+
+ /* MCU ownership */
+ mt76_wr(dev, MT7927_CBINFRA_MCU_OWN_SET, BIT(0));
+
+ /* Poll ROMCODE_INDEX for MCU idle */
+ if (!__mt76_poll_msec(mdev, MT7927_ROMCODE_INDEX,
+ 0xffff, MT7927_MCU_IDLE_VALUE, 2000)) {
+ val = mt76_rr(dev, MT7927_ROMCODE_INDEX);
+ dev_err(mdev->dev,
+ "MT7927 MCU idle timeout (ROMCODE_INDEX=0x%04x)\n",
+ val & 0xffff);
+ return -ETIMEDOUT;
+ }
+
+ /* MCIF remap - MCU needs this to DMA to host memory */
+ mt76_wr(dev, MT7927_MCIF_REMAP_WF_1_BA,
+ MT7927_MCIF_REMAP_WF_1_BA_VAL);
+
+ /* Disable PCIe sleep */
+ mt76_wr(dev, MT7927_CBINFRA_SLP_CTRL, 0xffffffff);
+
+ /* Clear CONNINFRA wakeup */
+ mt76_wr(dev, MT7927_CBINFRA_WAKEPU_TOP, 0x0);
+
+ return 0;
+}
+
+static void mt7927_cbtop_remap(struct mt792x_dev *dev)
+{
+ /* CONNINFRA wakeup - required before CBInfra register access */
+ mt76_wr(dev, MT7927_CBINFRA_WAKEPU_TOP, 0x1);
+ usleep_range(1000, 2000);
+
+ /* Configure CBTOP PCIe address remap for WF and BT */
+ mt76_wr(dev, MT7927_CBINFRA_MISC0_REMAP_WF,
+ MT7927_CBINFRA_REMAP_WF_VAL);
+ mt76_wr(dev, MT7927_CBINFRA_MISC0_REMAP_BT,
+ MT7927_CBINFRA_REMAP_BT_VAL);
+
+ /* Readback to push writes */
+ mt76_rr(dev, MT7927_CBINFRA_MISC0_REMAP_WF);
+}
static int mt7925_pci_probe(struct pci_dev *pdev,
@@ -484,2 +542,13 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
+ /* MT7927 firmware lacks the connac2 feature trailer, so
+ * mt792x_get_mac80211_ops() can't detect CNM support and
+ * replaces chanctx/ROC/mgd_prepare_tx ops with stubs.
+ * Force CNM and restore the original mt7925 ops.
+ */
+ if ((pdev->device == 0x6639 || pdev->device == 0x7927) &&
+ !(features & MT792x_FW_CAP_CNM)) {
+ features |= MT792x_FW_CAP_CNM;
+ memcpy(ops, &mt7925_ops, sizeof(*ops));
+ }
+
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
@@ -519,3 +588,2 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
dev->aspm_supported = true;
-
ret = __mt792x_mcu_fw_pmctrl(dev);
@@ -524,5 +592,10 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
- ret = __mt792xe_mcu_drv_pmctrl(dev);
- if (ret)
- goto err_free_dev;
+ if (!is_mt7927_hw) {
+ ret = __mt792xe_mcu_drv_pmctrl(dev);
+ if (ret)
+ goto err_free_dev;
+ }
+
+ if (is_mt7927_hw)
+ mt7927_cbtop_remap(dev);
@@ -533,7 +606,21 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
- mt76_rmw_field(dev, MT_HW_EMI_CTL, MT_HW_EMI_CTL_SLPPROT_EN, 1);
+ /* Force chip ID for MT7927 hardware if CHIPID read returns garbage */
+ if (is_mt7927_hw && (mdev->rev >> 16) != 0x7927) {
+ dev_info(mdev->dev,
+ "MT7927 raw CHIPID=0x%04x, forcing chip=0x7927\n",
+ (u16)(mdev->rev >> 16));
+ mdev->rev = (0x7927 << 16) | (mdev->rev & 0xff);
+ }
- ret = mt792x_wfsys_reset(dev);
- if (ret)
- goto err_free_dev;
+ if (is_mt7927_hw) {
+ ret = mt7927_chip_init(dev);
+ if (ret)
+ goto err_free_dev;
+ } else {
+ mt76_rmw_field(dev, MT_HW_EMI_CTL,
+ MT_HW_EMI_CTL_SLPPROT_EN, 1);
+ ret = mt792x_wfsys_reset(dev);
+ if (ret)
+ goto err_free_dev;
+ }
diff --git a/mt7925/pci_mac.c b/mt7925/pci_mac.c
index 1626a36..9b3eeb1 100644
--- a/mt7925/pci_mac.c
+++ b/mt7925/pci_mac.c
@@ -74,2 +74,11 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)
+ /* MT7927: CLR_OWN and WPDMA reset destroy DMA ring configuration.
+ * A full reset requires re-running mt7927_dma_init() which is not
+ * yet implemented in the recovery path.
+ */
+ if (is_mt7927(&dev->mt76)) {
+ dev_warn(dev->mt76.dev, "MT7927 mac_reset not supported, reload module to recover\n");
+ return -EOPNOTSUPP;
+ }
+
mt792xe_mcu_drv_pmctrl(dev);
diff --git a/mt7925/pci_mcu.c b/mt7925/pci_mcu.c
index 6cceff8..1f50d1e 100644
--- a/mt7925/pci_mcu.c
+++ b/mt7925/pci_mcu.c
@@ -37,9 +37,17 @@ int mt7925e_mcu_init(struct mt792x_dev *dev)
- err = mt792xe_mcu_fw_pmctrl(dev);
- if (err)
- return err;
+ if (is_mt7927(&dev->mt76)) {
+ /* MT7927: CLR_OWN was already done in mt7927_dma_init().
+ * The ROM re-initializes WFDMA on every CLR_OWN, wiping
+ * ring and prefetch config. Skip SET_OWN/CLR_OWN here
+ * to preserve DMA state.
+ */
+ } else {
+ err = mt792xe_mcu_fw_pmctrl(dev);
+ if (err)
+ return err;
- err = __mt792xe_mcu_drv_pmctrl(dev);
- if (err)
- return err;
+ err = __mt792xe_mcu_drv_pmctrl(dev);
+ if (err)
+ return err;
+ }
diff --git a/mt792x_regs.h b/mt792x_regs.h
index 14ebe82..2a83785 100644
--- a/mt792x_regs.h
+++ b/mt792x_regs.h
@@ -503,2 +503,20 @@
+/* CBInfra registers - MT7927 combo chip */
+#define MT7927_CBINFRA_WAKEPU_TOP 0xe01a0
+#define MT7927_CBINFRA_MISC0_REMAP_WF 0x1f6554
+#define MT7927_CBINFRA_MISC0_REMAP_BT 0x1f6558
+#define MT7927_CBINFRA_RGU_WF_RST 0x1f8600
+#define MT7927_CBINFRA_RGU_WF_RST_WF_SUBSYS BIT(4)
+#define MT7927_CBINFRA_MCU_OWN_SET 0x1f5034
+#define MT7927_CBINFRA_SLP_CTRL 0x1f5018
+#define MT7927_ROMCODE_INDEX 0xc1604
+#define MT7927_MCU_IDLE_VALUE 0x1d1e
+#define MT7927_MCIF_REMAP_WF_1_BA 0xd1034
+
+/* CBInfra CBTOP remap values */
+#define MT7927_CBINFRA_REMAP_WF_VAL 0x74037001
+#define MT7927_CBINFRA_REMAP_BT_VAL 0x70007000
+
+#define MT7927_MCIF_REMAP_WF_1_BA_VAL 0x18051803
+
#endif /* __MT792X_REGS_H */