9ee82e2d262c15147233f19c5369225f54c87db7
[linux-2.6-microblaze.git] / drivers / net / wireless / mediatek / mt76 / mt7915 / testmode.c
1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2020 MediaTek Inc. */
3
4 #include "mt7915.h"
5 #include "mac.h"
6 #include "mcu.h"
7 #include "testmode.h"
8
9 enum {
10         TM_CHANGED_TXPOWER,
11         TM_CHANGED_FREQ_OFFSET,
12
13         /* must be last */
14         NUM_TM_CHANGED
15 };
16
17 static const u8 tm_change_map[] = {
18         [TM_CHANGED_TXPOWER] = MT76_TM_ATTR_TX_POWER,
19         [TM_CHANGED_FREQ_OFFSET] = MT76_TM_ATTR_FREQ_OFFSET,
20 };
21
22 struct reg_band {
23         u32 band[2];
24 };
25
26 #define REG_BAND(_reg) \
27         { .band[0] = MT_##_reg(0), .band[1] = MT_##_reg(1) }
28 #define REG_BAND_IDX(_reg, _idx) \
29         { .band[0] = MT_##_reg(0, _idx), .band[1] = MT_##_reg(1, _idx) }
30
31 static const struct reg_band reg_backup_list[] = {
32         REG_BAND_IDX(AGG_PCR0, 0),
33         REG_BAND_IDX(AGG_PCR0, 1),
34         REG_BAND_IDX(AGG_AWSCR0, 0),
35         REG_BAND_IDX(AGG_AWSCR0, 1),
36         REG_BAND_IDX(AGG_AWSCR0, 2),
37         REG_BAND_IDX(AGG_AWSCR0, 3),
38         REG_BAND(AGG_MRCR),
39         REG_BAND(TMAC_TFCR0),
40         REG_BAND(TMAC_TCR0),
41         REG_BAND(AGG_ATCR1),
42         REG_BAND(AGG_ATCR3),
43         REG_BAND(TMAC_TRCR0),
44         REG_BAND(TMAC_ICR0),
45         REG_BAND_IDX(ARB_DRNGR0, 0),
46         REG_BAND_IDX(ARB_DRNGR0, 1),
47         REG_BAND(WF_RFCR),
48         REG_BAND(WF_RFCR1),
49 };
50
51 static int
52 mt7915_tm_set_tx_power(struct mt7915_phy *phy)
53 {
54         struct mt7915_dev *dev = phy->dev;
55         struct mt76_phy *mphy = phy->mt76;
56         struct cfg80211_chan_def *chandef = &mphy->chandef;
57         int freq = chandef->center_freq1;
58         int ret;
59         struct {
60                 u8 format_id;
61                 u8 dbdc_idx;
62                 s8 tx_power;
63                 u8 ant_idx;     /* Only 0 is valid */
64                 u8 center_chan;
65                 u8 rsv[3];
66         } __packed req = {
67                 .format_id = 0xf,
68                 .dbdc_idx = phy != &dev->phy,
69                 .center_chan = ieee80211_frequency_to_channel(freq),
70         };
71         u8 *tx_power = NULL;
72
73         if (dev->mt76.test.state != MT76_TM_STATE_OFF)
74                 tx_power = dev->mt76.test.tx_power;
75
76         /* Tx power of the other antennas are the same as antenna 0 */
77         if (tx_power && tx_power[0])
78                 req.tx_power = tx_power[0];
79
80         ret = mt76_mcu_send_msg(&dev->mt76,
81                                 MCU_EXT_CMD_TX_POWER_FEATURE_CTRL,
82                                 &req, sizeof(req), false);
83
84         return ret;
85 }
86
87 static int
88 mt7915_tm_set_freq_offset(struct mt7915_dev *dev, bool en, u32 val)
89 {
90         struct mt7915_tm_cmd req = {
91                 .testmode_en = en,
92                 .param_idx = MCU_ATE_SET_FREQ_OFFSET,
93                 .param.freq.freq_offset = cpu_to_le32(val),
94         };
95
96         return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req,
97                                  sizeof(req), false);
98 }
99
100 static int
101 mt7915_tm_mode_ctrl(struct mt7915_dev *dev, bool enable)
102 {
103         struct {
104                 u8 format_id;
105                 bool enable;
106                 u8 rsv[2];
107         } __packed req = {
108                 .format_id = 0x6,
109                 .enable = enable,
110         };
111
112         return mt76_mcu_send_msg(&dev->mt76,
113                                  MCU_EXT_CMD_TX_POWER_FEATURE_CTRL,
114                                  &req, sizeof(req), false);
115 }
116
117 static int
118 mt7915_tm_set_trx(struct mt7915_dev *dev, struct mt7915_phy *phy,
119                   int type, bool en)
120 {
121         struct mt7915_tm_cmd req = {
122                 .testmode_en = 1,
123                 .param_idx = MCU_ATE_SET_TRX,
124                 .param.trx.type = type,
125                 .param.trx.enable = en,
126                 .param.trx.band = phy != &dev->phy,
127         };
128
129         return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req,
130                                  sizeof(req), false);
131 }
132
133 static void
134 mt7915_tm_reg_backup_restore(struct mt7915_dev *dev, struct mt7915_phy *phy)
135 {
136         int n_regs = ARRAY_SIZE(reg_backup_list);
137         bool ext_phy = phy != &dev->phy;
138         u32 *b = dev->test.reg_backup;
139         int i;
140
141         if (dev->mt76.test.state == MT76_TM_STATE_OFF) {
142                 for (i = 0; i < n_regs; i++)
143                         mt76_wr(dev, reg_backup_list[i].band[ext_phy], b[i]);
144                 return;
145         }
146
147         if (b)
148                 return;
149
150         b = devm_kzalloc(dev->mt76.dev, 4 * n_regs, GFP_KERNEL);
151         if (!b)
152                 return;
153
154         dev->test.reg_backup = b;
155         for (i = 0; i < n_regs; i++)
156                 b[i] = mt76_rr(dev, reg_backup_list[i].band[ext_phy]);
157
158         mt76_clear(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_MM_PROT |
159                    MT_AGG_PCR0_GF_PROT | MT_AGG_PCR0_ERP_PROT |
160                    MT_AGG_PCR0_VHT_PROT | MT_AGG_PCR0_BW20_PROT |
161                    MT_AGG_PCR0_BW40_PROT | MT_AGG_PCR0_BW80_PROT);
162         mt76_set(dev, MT_AGG_PCR0(ext_phy, 0), MT_AGG_PCR0_PTA_WIN_DIS);
163
164         mt76_wr(dev, MT_AGG_PCR0(ext_phy, 1), MT_AGG_PCR1_RTS0_NUM_THRES |
165                 MT_AGG_PCR1_RTS0_LEN_THRES);
166
167         mt76_clear(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_BAR_CNT_LIMIT |
168                    MT_AGG_MRCR_LAST_RTS_CTS_RN | MT_AGG_MRCR_RTS_FAIL_LIMIT |
169                    MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT);
170
171         mt76_rmw(dev, MT_AGG_MRCR(ext_phy), MT_AGG_MRCR_RTS_FAIL_LIMIT |
172                  MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT,
173                  FIELD_PREP(MT_AGG_MRCR_RTS_FAIL_LIMIT, 1) |
174                  FIELD_PREP(MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT, 1));
175
176         mt76_wr(dev, MT_TMAC_TFCR0(ext_phy), 0);
177         mt76_clear(dev, MT_TMAC_TCR0(ext_phy), MT_TMAC_TCR0_TBTT_STOP_CTRL);
178
179         /* config rx filter for testmode rx */
180         mt76_wr(dev, MT_WF_RFCR(ext_phy), 0xcf70a);
181         mt76_wr(dev, MT_WF_RFCR1(ext_phy), 0);
182 }
183
184 static void
185 mt7915_tm_init(struct mt7915_dev *dev)
186 {
187         bool en = !(dev->mt76.test.state == MT76_TM_STATE_OFF);
188
189         if (!test_bit(MT76_STATE_RUNNING, &dev->phy.mt76->state))
190                 return;
191
192         mt7915_tm_mode_ctrl(dev, en);
193         mt7915_tm_reg_backup_restore(dev, &dev->phy);
194         mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_TXRX, !en);
195 }
196
197 static void
198 mt7915_tm_set_tx_frames(struct mt7915_dev *dev, bool en)
199 {
200         static const u8 spe_idx_map[] = {0, 0, 1, 0, 3, 2, 4, 0,
201                                          9, 8, 6, 10, 16, 12, 18, 0};
202         struct sk_buff *skb = dev->mt76.test.tx_skb;
203         struct ieee80211_tx_info *info;
204
205         mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_RX_RXV, false);
206
207         if (en) {
208                 u8 tx_ant = dev->mt76.test.tx_antenna_mask;
209
210                 mutex_unlock(&dev->mt76.mutex);
211                 mt7915_set_channel(&dev->phy);
212                 mutex_lock(&dev->mt76.mutex);
213
214                 mt7915_mcu_set_chan_info(&dev->phy, MCU_EXT_CMD_SET_RX_PATH);
215                 dev->test.spe_idx = spe_idx_map[tx_ant];
216         }
217
218         mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_TX, en);
219
220         if (!en || !skb)
221                 return;
222
223         info = IEEE80211_SKB_CB(skb);
224         info->control.vif = dev->phy.monitor_vif;
225 }
226
227 static void
228 mt7915_tm_set_rx_frames(struct mt7915_dev *dev, bool en)
229 {
230         if (en) {
231                 mutex_unlock(&dev->mt76.mutex);
232                 mt7915_set_channel(&dev->phy);
233                 mutex_lock(&dev->mt76.mutex);
234
235                 mt7915_mcu_set_chan_info(&dev->phy, MCU_EXT_CMD_SET_RX_PATH);
236         }
237
238         mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_RX_RXV, en);
239 }
240
241 static void
242 mt7915_tm_update_params(struct mt7915_dev *dev, u32 changed)
243 {
244         struct mt76_testmode_data *td = &dev->mt76.test;
245         bool en = dev->mt76.test.state != MT76_TM_STATE_OFF;
246
247         if (changed & BIT(TM_CHANGED_FREQ_OFFSET))
248                 mt7915_tm_set_freq_offset(dev, en, en ? td->freq_offset : 0);
249         if (changed & BIT(TM_CHANGED_TXPOWER))
250                 mt7915_tm_set_tx_power(&dev->phy);
251 }
252
253 static int
254 mt7915_tm_set_state(struct mt76_dev *mdev, enum mt76_testmode_state state)
255 {
256         struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
257         struct mt76_testmode_data *td = &mdev->test;
258         enum mt76_testmode_state prev_state = td->state;
259
260         mdev->test.state = state;
261
262         if (prev_state == MT76_TM_STATE_TX_FRAMES)
263                 mt7915_tm_set_tx_frames(dev, false);
264         else if (state == MT76_TM_STATE_TX_FRAMES)
265                 mt7915_tm_set_tx_frames(dev, true);
266         else if (prev_state == MT76_TM_STATE_RX_FRAMES)
267                 mt7915_tm_set_rx_frames(dev, false);
268         else if (state == MT76_TM_STATE_RX_FRAMES)
269                 mt7915_tm_set_rx_frames(dev, true);
270         else if (prev_state == MT76_TM_STATE_OFF || state == MT76_TM_STATE_OFF)
271                 mt7915_tm_init(dev);
272
273         if ((state == MT76_TM_STATE_IDLE &&
274              prev_state == MT76_TM_STATE_OFF) ||
275             (state == MT76_TM_STATE_OFF &&
276              prev_state == MT76_TM_STATE_IDLE)) {
277                 u32 changed = 0;
278                 int i;
279
280                 for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
281                         u16 cur = tm_change_map[i];
282
283                         if (td->param_set[cur / 32] & BIT(cur % 32))
284                                 changed |= BIT(i);
285                 }
286
287                 mt7915_tm_update_params(dev, changed);
288         }
289
290         return 0;
291 }
292
293 static int
294 mt7915_tm_set_params(struct mt76_dev *mdev, struct nlattr **tb,
295                      enum mt76_testmode_state new_state)
296 {
297         struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
298         struct mt76_testmode_data *td = &dev->mt76.test;
299         u32 changed = 0;
300         int i;
301
302         BUILD_BUG_ON(NUM_TM_CHANGED >= 32);
303
304         if (new_state == MT76_TM_STATE_OFF ||
305             td->state == MT76_TM_STATE_OFF)
306                 return 0;
307
308         if (td->tx_antenna_mask & ~dev->phy.chainmask)
309                 return -EINVAL;
310
311         for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
312                 if (tb[tm_change_map[i]])
313                         changed |= BIT(i);
314         }
315
316         mt7915_tm_update_params(dev, changed);
317
318         return 0;
319 }
320
321 static int
322 mt7915_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)
323 {
324         struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
325         void *rx, *rssi;
326         int i;
327
328         rx = nla_nest_start(msg, MT76_TM_STATS_ATTR_LAST_RX);
329         if (!rx)
330                 return -ENOMEM;
331
332         if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, dev->test.last_freq_offset))
333                 return -ENOMEM;
334
335         rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RCPI);
336         if (!rssi)
337                 return -ENOMEM;
338
339         for (i = 0; i < ARRAY_SIZE(dev->test.last_rcpi); i++)
340                 if (nla_put_u8(msg, i, dev->test.last_rcpi[i]))
341                         return -ENOMEM;
342
343         nla_nest_end(msg, rssi);
344
345         rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_IB_RSSI);
346         if (!rssi)
347                 return -ENOMEM;
348
349         for (i = 0; i < ARRAY_SIZE(dev->test.last_ib_rssi); i++)
350                 if (nla_put_s8(msg, i, dev->test.last_ib_rssi[i]))
351                         return -ENOMEM;
352
353         nla_nest_end(msg, rssi);
354
355         rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_WB_RSSI);
356         if (!rssi)
357                 return -ENOMEM;
358
359         for (i = 0; i < ARRAY_SIZE(dev->test.last_wb_rssi); i++)
360                 if (nla_put_s8(msg, i, dev->test.last_wb_rssi[i]))
361                         return -ENOMEM;
362
363         nla_nest_end(msg, rssi);
364
365         if (nla_put_u8(msg, MT76_TM_RX_ATTR_SNR, dev->test.last_snr))
366                 return -ENOMEM;
367
368         nla_nest_end(msg, rx);
369
370         return 0;
371 }
372
373 const struct mt76_testmode_ops mt7915_testmode_ops = {
374         .set_state = mt7915_tm_set_state,
375         .set_params = mt7915_tm_set_params,
376         .dump_stats = mt7915_tm_dump_stats,
377 };