blob: 24a6e9b27079f91d5a1ff6c083022f9bbcaded2b [file] [log] [blame]
developer3abe1ad2022-01-24 11:13:32 +08001/* Copyright (C) 2021-2022 Mediatek Inc. */
2#include "atenl.h"
3
4#define CHAN(_ch, _freq, _ch_80, _ch_160, ...) { \
5 .ch = _ch, \
6 .freq = _freq, \
7 .ch_80 = _ch_80, \
8 .ch_160 = _ch_160, \
9 __VA_ARGS__ \
10}
11
12struct atenl_channel {
13 /* ctrl ch */
14 u16 ch;
15 u16 freq;
16 /* center ch */
17 u16 ch_80;
18 u16 ch_160;
19 /* only use for channels that don't have 80 but has 40 */
20 u16 ch_40;
21};
22
23static const struct atenl_channel atenl_channels_5ghz[] = {
24 CHAN(8, 5040, 0, 0),
25 CHAN(12, 5060, 0, 0),
26 CHAN(16, 5080, 0, 0),
27
28 CHAN(36, 5180, 42, 50),
29 CHAN(40, 5200, 42, 50),
30 CHAN(44, 5220, 42, 50),
31 CHAN(48, 5240, 42, 50),
32
33 CHAN(52, 5260, 58, 50),
34 CHAN(56, 5280, 58, 50),
35 CHAN(60, 5300, 58, 50),
36 CHAN(64, 5320, 58, 50),
37
38 CHAN(68, 5340, 0, 0),
39 CHAN(80, 5400, 0, 0),
40 CHAN(84, 5420, 0, 0),
41 CHAN(88, 5440, 0, 0),
42 CHAN(92, 5460, 0, 0),
43 CHAN(96, 5480, 0, 0),
44
45 CHAN(100, 5500, 106, 114),
46 CHAN(104, 5520, 106, 114),
47 CHAN(108, 5540, 106, 114),
48 CHAN(112, 5560, 106, 114),
49 CHAN(116, 5580, 122, 114),
50 CHAN(120, 5600, 122, 114),
51 CHAN(124, 5620, 122, 114),
52 CHAN(128, 5640, 122, 114),
53
54 CHAN(132, 5660, 138, 0),
55 CHAN(136, 5680, 138, 0),
56 CHAN(140, 5700, 138, 0),
57 CHAN(144, 5720, 138, 0),
58
59 CHAN(149, 5745, 155, 0),
60 CHAN(153, 5765, 155, 0),
61 CHAN(157, 5785, 155, 0),
62 CHAN(161, 5805, 155, 0),
63 CHAN(165, 5825, 0, 0, .ch_40 = 167),
64 CHAN(169, 5845, 0, 0, .ch_40 = 167),
65 CHAN(173, 5865, 0, 0),
66
67 CHAN(184, 4920, 0, 0),
68 CHAN(188, 4940, 0, 0),
69 CHAN(192, 4960, 0, 0),
70 CHAN(196, 4980, 0, 0),
71};
72
73static const struct atenl_channel atenl_channels_6ghz[] = {
74 /* UNII-5 */
75 CHAN(1, 5955, 7, 15),
76 CHAN(5, 5975, 7, 15),
77 CHAN(9, 5995, 7, 15),
78 CHAN(13, 6015, 7, 15),
79 CHAN(17, 6035, 23, 15),
80 CHAN(21, 6055, 23, 15),
81 CHAN(25, 6075, 23, 15),
82 CHAN(29, 6095, 23, 15),
83 CHAN(33, 6115, 39, 47),
84 CHAN(37, 6135, 39, 47),
85 CHAN(41, 6155, 39, 47),
86 CHAN(45, 6175, 39, 47),
87 CHAN(49, 6195, 55, 47),
88 CHAN(53, 6215, 55, 47),
89 CHAN(57, 6235, 55, 47),
90 CHAN(61, 6255, 55, 47),
91 CHAN(65, 6275, 71, 79),
92 CHAN(69, 6295, 71, 79),
93 CHAN(73, 6315, 71, 79),
94 CHAN(77, 6335, 71, 79),
95 CHAN(81, 6355, 87, 79),
96 CHAN(85, 6375, 87, 79),
97 CHAN(89, 6395, 87, 79),
98 CHAN(93, 6415, 87, 79),
99 /* UNII-6 */
100 CHAN(97, 6435, 103, 111),
101 CHAN(101, 6455, 103, 111),
102 CHAN(105, 6475, 103, 111),
103 CHAN(109, 6495, 103, 111),
104 CHAN(113, 6515, 119, 111),
105 CHAN(117, 6535, 119, 111),
106 /* UNII-7 */
107 CHAN(121, 6555, 119, 111),
108 CHAN(125, 6575, 119, 111),
109 CHAN(129, 6595, 135, 143),
110 CHAN(133, 6615, 135, 143),
111 CHAN(137, 6635, 135, 143),
112 CHAN(141, 6655, 135, 143),
113 CHAN(145, 6675, 151, 143),
114 CHAN(149, 6695, 151, 143),
115 CHAN(153, 6715, 151, 143),
116 CHAN(157, 6735, 151, 143),
117 CHAN(161, 6755, 167, 175),
118 CHAN(165, 6775, 167, 175),
119 CHAN(169, 6795, 167, 175),
120 CHAN(173, 6815, 167, 175),
121 CHAN(177, 6835, 183, 175),
122 CHAN(181, 6855, 183, 175),
123 CHAN(185, 6875, 183, 175),
124 /* UNII-8 */
125 CHAN(189, 6895, 183, 175),
126 CHAN(193, 6915, 199, 207),
127 CHAN(197, 6935, 199, 207),
128 CHAN(201, 6955, 199, 207),
129 CHAN(205, 6975, 199, 207),
130 CHAN(209, 6995, 215, 207),
131 CHAN(213, 7015, 215, 207),
132 CHAN(217, 7035, 215, 207),
133 CHAN(221, 7055, 215, 207),
134 CHAN(225, 7075, 0, 0, .ch_40 = 227),
135 CHAN(229, 7095, 0, 0, .ch_40 = 227),
136 CHAN(233, 7115, 0, 0),
137};
138
139static int
140atenl_hqa_adapter(struct atenl *an, struct atenl_data *data)
141{
142 char cmd[64];
143 u8 i;
144
145 for (i = 0; i < MAX_BAND_NUM; i++) {
146 u8 phy = get_band_val(an, i, phy_idx);
147
148 if (!get_band_val(an, i, valid))
149 continue;
150
151 if (data->cmd == HQA_CMD_OPEN_ADAPTER) {
152 sprintf(cmd, "iw phy phy%u interface add mon%u type monitor", phy, phy);
153 system(cmd);
154 sprintf(cmd, "iw dev wlan%u del", phy);
155 system(cmd);
156 sprintf(cmd, "ifconfig mon%u up", phy);
157 system(cmd);
158 /* set a special-defined country */
159 sprintf(cmd, "iw reg set VV");
160 system(cmd);
161 atenl_nl_set_state(an, i, MT76_TM_STATE_IDLE);
162 } else {
163 atenl_nl_set_state(an, i, MT76_TM_STATE_OFF);
164 sprintf(cmd, "iw reg set 00");
165 system(cmd);
166 sprintf(cmd, "iw dev mon%u del", phy);
167 system(cmd);
168 sprintf(cmd, "iw phy phy%u interface add wlan%u type managed", phy, phy);
169 system(cmd);
170 }
171 }
172
173 return 0;
174}
175
176static int
177atenl_hqa_set_rf_mode(struct atenl *an, struct atenl_data *data)
178{
179 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
180
181 /* The testmode rf mode change applies to all bands */
182 set_band_val(an, 0, rf_mode, ntohl(*(u32 *)hdr->data));
183 set_band_val(an, 1, rf_mode, ntohl(*(u32 *)hdr->data));
184
185 return 0;
186}
187
188static int
189atenl_hqa_get_chip_id(struct atenl *an, struct atenl_data *data)
190{
191 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
192
193 *(u32 *)(hdr->data + 2) = htonl(an->chip_id);
194
195 return 0;
196}
197
198static int
199atenl_hqa_get_sub_chip_id(struct atenl *an, struct atenl_data *data)
200{
201 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
202
203 if (is_mt7986(an)) {
204 u32 sub_id, val;
205 int ret;
206
207 ret = atenl_reg_read(an, 0x18050000, &val);
208 if (ret)
209 return ret;
210
211 switch (val & 0xf) {
212 case MT7975_ONE_ADIE_SINGLE_BAND:
213 case MT7976_ONE_ADIE_SINGLE_BAND:
214 sub_id = htonl(0xa);
215 break;
216 case MT7976_ONE_ADIE_DBDC:
217 sub_id = htonl(0x7);
218 break;
219 case MT7975_DUAL_ADIE_DBDC:
220 case MT7976_DUAL_ADIE_DBDC:
221 default:
222 sub_id = htonl(0xf);
223 break;
224 }
225
226 memcpy(hdr->data + 2, &sub_id, 4);
227 }
228
229 return 0;
230}
231
232static int
233atenl_hqa_get_rf_cap(struct atenl *an, struct atenl_data *data)
234{
235 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
236 u32 band = ntohl(*(u32 *)hdr->data);
237 struct atenl_band *anb;
238
239 if (band >= MAX_BAND_NUM)
240 return -EINVAL;
241
242 anb = &an->anb[band];
243 /* fill tx and rx ant */
244 *(u32 *)(hdr->data + 2) = htonl(__builtin_popcount(anb->chainmask));
245 *(u32 *)(hdr->data + 2 + 4) = *(u32 *)(hdr->data + 2);
246
247 return 0;
248}
249
250static int
251atenl_hqa_reset_counter(struct atenl *an, struct atenl_data *data)
252{
253 struct atenl_band *anb = &an->anb[an->cur_band];
254
255 anb->reset_tx_cnt = true;
256 anb->reset_rx_cnt = true;
257
258 memset(&anb->rx_stat, 0, sizeof(anb->rx_stat));
259
260 return 0;
261}
262
263static int
264atenl_hqa_mac_bbp_reg(struct atenl *an, struct atenl_data *data)
265{
266 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
267 enum atenl_cmd cmd = data->cmd;
268 u32 *v = (u32 *)hdr->data;
269 u32 offset = ntohl(v[0]);
270 int ret;
271
272 if (cmd == HQA_CMD_READ_MAC_BBP_REG) {
273 u16 num = ntohs(*(u16 *)(hdr->data + 4));
274 u32 *ptr = (u32 *)(hdr->data + 2);
275 u32 res;
276 int i;
277
278 if (num > SHRT_MAX) {
279 ret = -EINVAL;
280 goto out;
281 }
282
283 hdr->len = htons(2 + num * 4);
284 for (i = 0; i < num && i < sizeof(hdr->data) / 4; i++) {
285 ret = atenl_reg_read(an, offset + i * 4, &res);
286 if (ret)
287 goto out;
288
289 res = htonl(res);
290 memcpy(ptr + i, &res, 4);
291 }
292 } else {
293 u32 val = ntohl(v[1]);
294
295 ret = atenl_reg_write(an, offset, val);
296 if (ret)
297 goto out;
298 }
299
300 ret = 0;
301out:
302 memset(hdr->data, 0, 2);
303
304 return ret;
305}
306
307static int
308atenl_hqa_eeprom_bulk(struct atenl *an, struct atenl_data *data)
309{
310 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
311 enum atenl_cmd cmd = data->cmd;
312
313 if (cmd == HQA_CMD_WRITE_BUFFER_DONE) {
314 u32 buf_mode = ntohl(*(u32 *)hdr->data);
315
316 switch (buf_mode) {
317 case E2P_EFUSE_MODE:
318 atenl_nl_write_efuse_all(an, data);
319 break;
320 default:
321 break;
322 }
323 } else {
324 u16 *v = (u16 *)hdr->data;
325 u16 offset = ntohs(v[0]), len = ntohs(v[1]);
326 u16 val;
327 size_t i;
328
329 if (offset >= an->eeprom_size || (len > sizeof(hdr->data) - 2))
330 return -EINVAL;
331
332 if (cmd == HQA_CMD_READ_EEPROM_BULK) {
333 hdr->len = htons(len + 2);
334 for (i = 0; i < len; i += 2) {
335 if (offset + i >= an->eeprom_size)
336 val = 0;
337 else
338 val = ntohs(*(u16 *)(an->eeprom_data + offset + i));
339 *(u16 *)(hdr->data + 2 + i) = val;
340 }
341 } else { /* write eeprom */
342 u16 offset_a;
343
344 for (i = 0; i < DIV_ROUND_UP(len, 2); i++) {
345 val = ntohs(v[i + 2]);
346 memcpy(&an->eeprom_data[offset + i * 2], &val, 2);
347 }
348
349 offset_a = offset - (offset % 16);
350 len += (offset - offset_a);
351 for (i = offset_a; i < offset_a + len; i += 16)
352 atenl_nl_write_eeprom(an, i, &an->eeprom_data[i], 16);
353
354 atenl_eeprom_write_mtd(an);
355 }
356 }
357
358 return 0;
359}
360
361static int
362atenl_hqa_get_efuse_free_block(struct atenl *an, struct atenl_data *data)
363{
364 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
365 u32 free_block = htonl(0x14);
366
367 /* TODO */
368 *(u32 *)(hdr->data + 2) = free_block;
369
370 return 0;
371}
372
373static int
374atenl_hqa_get_band(struct atenl *an, struct atenl_data *data)
375{
376 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
377 u32 band = ntohl(*(u32 *)hdr->data);
378
379 if (band >= MAX_BAND_NUM)
380 return -EINVAL;
381
382 *(u32 *)(hdr->data + 2) = htonl(an->anb[band].cap);
383
384 return 0;
385}
386
387static int
388atenl_hqa_get_tx_power(struct atenl *an, struct atenl_data *data)
389{
390 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
391 u32 tx_power = htonl(28);
392
393 memcpy(hdr->data + 6, &tx_power, 4);
394
395 return 0;
396}
397
398static int
399atenl_hqa_get_freq_offset(struct atenl *an, struct atenl_data *data)
400{
401 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
402 u32 freq_offset = htonl(10);
403
404 /* TODO */
405 memcpy(hdr->data + 2, &freq_offset, 4);
406
407 return 0;
408}
409
410static int
411atenl_hqa_get_cfg(struct atenl *an, struct atenl_data *data)
412{
413 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
414 u32 val = htonl(1);
415
416 /* TODO */
417 memcpy(hdr->data + 2, &val, 4);
418
419 return 0;
420}
421
422static int
423atenl_hqa_read_temperature(struct atenl *an, struct atenl_data *data)
424{
425 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
426 char buf[64], *str;
427 int fd, ret;
428 u32 temp;
429 u8 phy_idx = get_band_val(an, an->cur_band, phy_idx);
430
431 ret = snprintf(buf, sizeof(buf),
432 "/sys/class/ieee80211/phy%u/hwmon%u/temp1_input",
433 phy_idx, phy_idx);
434 if (snprintf_error(sizeof(buf), ret))
435 return -1;
436
437 fd = open(buf, O_RDONLY);
438 if (fd < 0)
439 return fd;
440
441 ret = read(fd, buf, sizeof(buf) - 1);
442 if (ret < 0)
443 goto out;
444 buf[ret] = 0;
445
446 str = strchr(buf, ':');
447 str += 2;
448 temp = strtol(str, NULL, 10);
449 /* unit conversion */
450 *(u32 *)(hdr->data + 2) = htonl(temp / 1000);
451
452 ret = 0;
453out:
454 close(fd);
455
456 return ret;
457}
458
459static int
460atenl_hqa_skip(struct atenl *an, struct atenl_data *data)
461{
462 return 0;
463}
464
465static int
466atenl_hqa_check_efuse_mode(struct atenl *an, struct atenl_data *data)
467{
468 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
469 bool flash_mode = an->mtd_part != NULL;
470 enum atenl_cmd cmd = data->cmd;
471 u32 mode;
472
473 switch (cmd) {
474 case HQA_CMD_CHECK_EFUSE_MODE:
475 mode = flash_mode ? 0 : 1;
476 break;
477 case HQA_CMD_CHECK_EFUSE_MODE_TYPE:
478 mode = flash_mode ? E2P_FLASH_MODE : E2P_BIN_MODE;
479 break;
480 case HQA_CMD_CHECK_EFUSE_MODE_NATIVE:
481 mode = flash_mode ? E2P_FLASH_MODE : E2P_EFUSE_MODE;
482 break;
483 default:
484 mode = E2P_BIN_MODE;
485 break;
486 }
487
488 *(u32 *)(hdr->data + 2) = htonl(mode);
489
490 return 0;
491}
492
493static inline u16
494atenl_get_freq_by_channel(u8 ch_band, u16 ch)
495{
496 u16 base;
497
498 if (ch_band == CH_BAND_6GHZ) {
499 base = 5950;
500 } else if (ch_band == CH_BAND_5GHZ) {
501 if (ch >= 184)
502 return 4920 + (ch - 184) * 5;
503
504 base = 5000;
505 } else {
506 base = 2407;
507 }
508
509 return base + ch * 5;
510}
511
512u16 atenl_get_center_channel(u8 bw, u8 ch_band, u16 ctrl_ch)
513{
514 const struct atenl_channel *chan = NULL;
515 const struct atenl_channel *ch_list;
516 u16 center_ch;
517 u8 ch_num;
518 int i;
519
520 if (ch_band == CH_BAND_2GHZ || bw <= TEST_CBW_40MHZ)
521 return 0;
522
523 if (ch_band == CH_BAND_6GHZ) {
524 ch_list = atenl_channels_6ghz;
525 ch_num = ARRAY_SIZE(atenl_channels_6ghz);
526 } else {
527 ch_list = atenl_channels_5ghz;
528 ch_num = ARRAY_SIZE(atenl_channels_5ghz);
529 }
530
531 for (i = 0; i < ch_num; i++) {
532 if (ctrl_ch == ch_list[i].ch) {
533 chan = &ch_list[i];
534 break;
535 }
536 }
537
538 if (!chan)
539 return 0;
540
541 switch (bw) {
542 case TEST_CBW_160MHZ:
543 center_ch = chan->ch_160;
544 break;
545 case TEST_CBW_80MHZ:
546 center_ch = chan->ch_80;
547 break;
548 default:
549 center_ch = 0;
550 break;
551 }
552
553 return center_ch;
554}
555
556static void atenl_get_bw_string(u8 bw, char *buf)
557{
558 switch (bw) {
559 case TEST_CBW_160MHZ:
560 sprintf(buf, "160");
561 break;
562 case TEST_CBW_80MHZ:
563 sprintf(buf, "80");
564 break;
565 case TEST_CBW_40MHZ:
566 sprintf(buf, "40");
567 break;
568 default:
569 sprintf(buf, "20");
570 break;
571 }
572}
573
574void atenl_set_channel(struct atenl *an, u8 bw, u8 ch_band,
575 u16 ch, u16 center_ch1, u16 center_ch2)
576{
577 char bw_str[8] = {};
578 char cmd[128];
579 u16 freq = atenl_get_freq_by_channel(ch_band, ch);
580 u16 freq_center1 = atenl_get_freq_by_channel(ch_band, center_ch1);
581 int ret;
582
583 if (bw > TEST_CBW_MAX)
584 return;
585
586 atenl_get_bw_string(bw, bw_str);
587
588 if (bw == TEST_CBW_20MHZ)
589 ret = snprintf(cmd, sizeof(cmd), "iw dev mon%d set freq %u %s",
590 get_band_val(an, an->cur_band, phy_idx),
591 freq, bw_str);
592 else
593 ret = snprintf(cmd, sizeof(cmd), "iw dev mon%d set freq %u %s %u",
594 get_band_val(an, an->cur_band, phy_idx),
595 freq, bw_str, freq_center1);
596 if (snprintf_error(sizeof(cmd), ret))
597 return;
598
599 atenl_dbg("[%d]%s: cmd: %s\n", getpid(), __func__, cmd);
600
601 system(cmd);
602}
603
604static int
605atenl_hqa_set_channel(struct atenl *an, struct atenl_data *data)
606{
607 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
608 u32 *v = (u32 *)hdr->data;
609 u8 band = ntohl(v[2]);
610 u16 ch1 = ntohl(v[3]); /* center */
611 u16 ch2 = ntohl(v[4]);
612 u8 bw = ntohl(v[5]);
613 u8 pri_sel = ntohl(v[7]);
614 u8 ch_band = ntohl(v[9]);
615 u16 ctrl_ch = 0;
616
617 if (band >= MAX_BAND_NUM)
618 return -EINVAL;
619
620 if ((bw == TEST_CBW_160MHZ && pri_sel > 7) ||
621 (bw == TEST_CBW_80MHZ && pri_sel > 3) ||
622 (bw == TEST_CBW_40MHZ && pri_sel > 1)) {
623 atenl_err("%s: ctrl channel select error\n", __func__);
624 return -EINVAL;
625 }
626
627 an->cur_band = band;
628
629 if (ch_band == CH_BAND_2GHZ) {
630 ctrl_ch = ch1;
631 switch (bw) {
632 case TEST_CBW_40MHZ:
633 if (pri_sel == 1)
634 ctrl_ch += 2;
635 else
636 ctrl_ch -= 2;
637 break;
638 default:
639 break;
640 }
641
642 atenl_set_channel(an, bw, CH_BAND_2GHZ, ctrl_ch, ch1, 0);
643 } else {
644 const struct atenl_channel *chan = NULL;
645 const struct atenl_channel *ch_list;
646 u8 ch_num;
647 int i;
648
649 if (ch_band == CH_BAND_6GHZ) {
650 ch_list = atenl_channels_6ghz;
651 ch_num = ARRAY_SIZE(atenl_channels_6ghz);
652 } else {
653 ch_list = atenl_channels_5ghz;
654 ch_num = ARRAY_SIZE(atenl_channels_5ghz);
655 }
656
657 if (bw == TEST_CBW_160MHZ) {
658 for (i = 0; i < ch_num; i++) {
659 if (ch1 == ch_list[i].ch_160) {
660 chan = &ch_list[i];
661 break;
662 } else if (ch1 < ch_list[i].ch_160) {
663 chan = &ch_list[i - 1];
664 break;
665 }
666 }
667 } else if (bw == TEST_CBW_80MHZ) {
668 for (i = 0; i < ch_num; i++) {
669 if (ch1 == ch_list[i].ch_80) {
670 chan = &ch_list[i];
671 break;
672 } else if (ch1 < ch_list[i].ch_80) {
673 chan = &ch_list[i - 1];
674 break;
675 }
676 }
677 } else {
678 for (i = 0; i < ch_num; i++) {
679 if (ch1 <= ch_list[i].ch) {
680 if (ch1 == ch_list[i].ch)
681 chan = &ch_list[i];
682 else
683 chan = &ch_list[i - 1];
684 break;
685 }
686 }
687 }
688
689 if (!chan)
690 return -EINVAL;
691
692 if (bw != TEST_CBW_20MHZ) {
693 chan += pri_sel;
694 if (chan > &ch_list[ch_num - 1])
695 return -EINVAL;
696 }
697 ctrl_ch = chan->ch;
698
699 atenl_set_channel(an, bw, ch_band, ctrl_ch, ch1, ch2);
700 }
701
702 *(u32 *)(hdr->data + 2) = data->ext_id;
703
704 return 0;
705}
706
707static int
708atenl_hqa_tx_time_option(struct atenl *an, struct atenl_data *data)
709{
710 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
711 u32 *v = (u32 *)hdr->data;
712 u8 band = ntohl(v[1]);
713 u32 option = ntohl(v[2]);
714
715 if (band >= MAX_BAND_NUM)
716 return -EINVAL;
717
718 set_band_val(an, band, use_tx_time, !!option);
719 *(u32 *)(hdr->data + 2) = data->ext_id;
720
721 return 0;
722}
723
724static inline enum atenl_cmd atenl_get_cmd_by_id(u16 cmd_idx)
725{
726#define CMD_ID_GROUP GENMASK(15, 8)
727 u8 group = FIELD_GET(CMD_ID_GROUP, cmd_idx);
728
729 if (cmd_idx == 0x1600)
730 return HQA_CMD_EXT;
731
732 if (group == 0x10) {
733 switch (cmd_idx) {
734 case 0x1000:
735 return HQA_CMD_OPEN_ADAPTER;
736 case 0x1001:
737 return HQA_CMD_CLOSE_ADAPTER;
738 case 0x100b:
739 return HQA_CMD_SET_TX_PATH;
740 case 0x100c:
741 return HQA_CMD_SET_RX_PATH;
742 case 0x1011:
743 return HQA_CMD_SET_TX_POWER;
744 case 0x1018:
745 return HQA_CMD_SET_TX_POWER_MANUAL;
746 case 0x100d:
747 return HQA_CMD_LEGACY;
748 default:
749 break;
750 }
751 } else if (group == 0x11) {
752 switch (cmd_idx) {
753 case 0x1104:
754 return HQA_CMD_SET_TX_BW;
755 case 0x1105:
756 return HQA_CMD_SET_TX_PKT_BW;
757 case 0x1106:
758 return HQA_CMD_SET_TX_PRI_BW;
759 case 0x1107:
760 return HQA_CMD_SET_FREQ_OFFSET;
761 case 0x1109:
762 return HQA_CMD_SET_TSSI;
763 case 0x110d:
764 return HQA_CMD_ANT_SWAP_CAP;
765 case 0x1101:
766 case 0x1102:
767 return HQA_CMD_LEGACY;
768 default:
769 break;
770 }
771 } else if (group == 0x12) {
772 switch (cmd_idx) {
773 case 0x1200:
774 return HQA_CMD_RESET_TX_RX_COUNTER;
775 default:
776 break;
777 }
778 } else if (group == 0x13) {
779 switch (cmd_idx) {
780 case 0x1301:
781 return HQA_CMD_WRITE_MAC_BBP_REG;
782 case 0x1302:
783 return HQA_CMD_READ_MAC_BBP_REG;
784 case 0x1307:
785 return HQA_CMD_READ_EEPROM_BULK;
786 case 0x1306:
787 case 0x1308:
788 return HQA_CMD_WRITE_EEPROM_BULK;
789 case 0x1309:
790 return HQA_CMD_CHECK_EFUSE_MODE;
791 case 0x130a:
792 return HQA_CMD_GET_EFUSE_FREE_BLOCK;
793 case 0x130d:
794 return HQA_CMD_GET_TX_POWER;
795 case 0x130e:
796 return HQA_CMD_SET_CFG;
797 case 0x130f:
798 return HQA_CMD_GET_FREQ_OFFSET;
799 case 0x1311:
800 return HQA_CMD_CONTINUOUS_TX;
801 case 0x1312:
802 return HQA_CMD_SET_RX_PKT_LEN;
803 case 0x1313:
804 return HQA_CMD_GET_TX_INFO;
805 case 0x1314:
806 return HQA_CMD_GET_CFG;
807 case 0x131f:
808 return HQA_CMD_UNKNOWN;
809 case 0x131a:
810 return HQA_CMD_GET_TX_TONE_POWER;
811 default:
812 break;
813 }
814 } else if (group == 0x14) {
815 switch (cmd_idx) {
816 case 0x1401:
817 return HQA_CMD_READ_TEMPERATURE;
818 default:
819 break;
820 }
821 } else if (group == 0x15) {
822 switch (cmd_idx) {
823 case 0x1500:
824 return HQA_CMD_GET_FW_INFO;
825 case 0x1505:
826 return HQA_CMD_SET_TSSI;
827 case 0x1509:
828 return HQA_CMD_SET_RF_MODE;
829 case 0x1511:
830 return HQA_CMD_WRITE_BUFFER_DONE;
831 case 0x1514:
832 return HQA_CMD_GET_CHIP_ID;
833 case 0x151b:
834 return HQA_CMD_GET_SUB_CHIP_ID;
835 case 0x151c:
836 return HQA_CMD_GET_RX_INFO;
837 case 0x151e:
838 return HQA_CMD_GET_RF_CAP;
839 case 0x1522:
840 return HQA_CMD_CHECK_EFUSE_MODE_TYPE;
841 case 0x1523:
842 return HQA_CMD_CHECK_EFUSE_MODE_NATIVE;
843 case 0x152d:
844 return HQA_CMD_GET_BAND;
845 case 0x1594:
846 return HQA_CMD_SET_RU;
847 case 0x1502:
848 case 0x150b:
849 return HQA_CMD_LEGACY;
850 default:
851 break;
852 }
853 }
854
855 return HQA_CMD_ERR;
856}
857
858static inline enum atenl_ext_cmd atenl_get_ext_cmd(u16 ext_cmd_idx)
859{
860#define EXT_CMD_ID_GROUP GENMASK(7, 4)
861 u8 ext_group = FIELD_GET(EXT_CMD_ID_GROUP, ext_cmd_idx);
862
863 if (ext_group == 0) {
864 switch (ext_cmd_idx) {
865 case 0x1:
866 return HQA_EXT_CMD_SET_CHANNEL;
867 case 0x2:
868 return HQA_EXT_CMD_SET_TX;
869 case 0x3:
870 return HQA_EXT_CMD_START_TX;
871 case 0x4:
872 return HQA_EXT_CMD_START_RX;
873 case 0x5:
874 return HQA_EXT_CMD_STOP_TX;
875 case 0x6:
876 return HQA_EXT_CMD_STOP_RX;
877 case 0x8:
878 return HQA_EXT_CMD_IBF_SET_VAL;
879 case 0x9:
880 return HQA_EXT_CMD_IBF_GET_STATUS;
881 case 0xc:
882 return HQA_EXT_CMD_IBF_PROF_UPDATE_ALL;
883 default:
884 break;
885 }
886 } else if (ext_group == 1) {
887 } else if (ext_group == 2) {
888 switch (ext_cmd_idx) {
889 case 0x26:
890 return HQA_EXT_CMD_SET_TX_TIME_OPT;
891 case 0x27:
892 return HQA_EXT_CMD_OFF_CH_SCAN;
893 default:
894 break;
895 }
896 }
897
898 return HQA_EXT_CMD_UNSPEC;
899}
900
901#define ATENL_GROUP(_cmd, _resp_len, _ops) \
902 [HQA_CMD_##_cmd] = { .resp_len=_resp_len, .ops=_ops }
903static const struct atenl_cmd_ops atenl_ops[] = {
904 ATENL_GROUP(OPEN_ADAPTER, 2, atenl_hqa_adapter),
905 ATENL_GROUP(CLOSE_ADAPTER, 2, atenl_hqa_adapter),
906 ATENL_GROUP(SET_TX_PATH, 2, atenl_nl_process),
907 ATENL_GROUP(SET_RX_PATH, 2, atenl_nl_process),
908 ATENL_GROUP(SET_TX_POWER, 2, atenl_nl_process),
909 ATENL_GROUP(SET_TX_POWER_MANUAL, 2, atenl_hqa_skip),
910 ATENL_GROUP(SET_TX_BW, 2, atenl_hqa_skip),
911 ATENL_GROUP(SET_TX_PKT_BW, 2, atenl_hqa_skip),
912 ATENL_GROUP(SET_TX_PRI_BW, 2, atenl_hqa_skip),
913 ATENL_GROUP(SET_FREQ_OFFSET, 2, atenl_nl_process),
914 ATENL_GROUP(ANT_SWAP_CAP, 6, atenl_hqa_skip),
915 ATENL_GROUP(RESET_TX_RX_COUNTER, 2, atenl_hqa_reset_counter),
916 ATENL_GROUP(WRITE_MAC_BBP_REG, 2, atenl_hqa_mac_bbp_reg),
917 ATENL_GROUP(READ_MAC_BBP_REG, 0, atenl_hqa_mac_bbp_reg),
918 ATENL_GROUP(READ_EEPROM_BULK, 0, atenl_hqa_eeprom_bulk),
919 ATENL_GROUP(WRITE_EEPROM_BULK, 2, atenl_hqa_eeprom_bulk),
920 ATENL_GROUP(CHECK_EFUSE_MODE, 6, atenl_hqa_check_efuse_mode),
921 ATENL_GROUP(GET_EFUSE_FREE_BLOCK, 6, atenl_hqa_get_efuse_free_block),
922 ATENL_GROUP(GET_TX_POWER, 10, atenl_hqa_get_tx_power),
923 ATENL_GROUP(GET_FREQ_OFFSET, 6, atenl_hqa_get_freq_offset), /*TODO: MCU CMD, read eeprom?*/
924 ATENL_GROUP(CONTINUOUS_TX, 6, atenl_nl_process),
925 ATENL_GROUP(SET_RX_PKT_LEN, 2, atenl_hqa_skip),
926 ATENL_GROUP(GET_TX_INFO, 10, atenl_nl_process),
927 ATENL_GROUP(GET_CFG, 6, atenl_hqa_get_cfg), /*TODO*/
928 ATENL_GROUP(GET_TX_TONE_POWER, 6, atenl_hqa_skip),
929 ATENL_GROUP(SET_CFG, 2, atenl_nl_process),
930 ATENL_GROUP(READ_TEMPERATURE, 6, atenl_hqa_read_temperature),
931 ATENL_GROUP(GET_FW_INFO, 32, atenl_hqa_skip), /* TODO: check format */
932 ATENL_GROUP(SET_TSSI, 2, atenl_nl_process),
933 ATENL_GROUP(SET_RF_MODE, 2, atenl_hqa_set_rf_mode),
934 ATENL_GROUP(WRITE_BUFFER_DONE, 2, atenl_hqa_eeprom_bulk),
935 ATENL_GROUP(GET_CHIP_ID, 6, atenl_hqa_get_chip_id),
936 ATENL_GROUP(GET_SUB_CHIP_ID, 6, atenl_hqa_get_sub_chip_id),
937 ATENL_GROUP(GET_RX_INFO, 0, atenl_nl_process),
938 ATENL_GROUP(GET_RF_CAP, 10, atenl_hqa_get_rf_cap),
939 ATENL_GROUP(CHECK_EFUSE_MODE_TYPE, 6, atenl_hqa_check_efuse_mode),
940 ATENL_GROUP(CHECK_EFUSE_MODE_NATIVE, 6, atenl_hqa_check_efuse_mode),
941 ATENL_GROUP(GET_BAND, 6, atenl_hqa_get_band),
942 ATENL_GROUP(SET_RU, 2, atenl_nl_process_many),
943
944 ATENL_GROUP(LEGACY, 2, atenl_hqa_skip),
945 ATENL_GROUP(UNKNOWN, 1024, atenl_hqa_skip),
946};
947#undef ATENL_GROUP
948
949#define ATENL_EXT(_cmd, _resp_len, _ops) \
950 [HQA_EXT_CMD_##_cmd] = { .resp_len=_resp_len, .ops=_ops }
951static const struct atenl_cmd_ops atenl_ext_ops[] = {
952 ATENL_EXT(SET_CHANNEL, 6, atenl_hqa_set_channel),
953 ATENL_EXT(SET_TX, 6, atenl_nl_process),
954 ATENL_EXT(START_TX, 6, atenl_nl_process),
955 ATENL_EXT(STOP_TX, 6, atenl_nl_process),
956 ATENL_EXT(START_RX, 6, atenl_nl_process),
957 ATENL_EXT(STOP_RX, 6, atenl_nl_process),
958 ATENL_EXT(SET_TX_TIME_OPT, 6, atenl_hqa_tx_time_option),
959 ATENL_EXT(OFF_CH_SCAN, 6, atenl_nl_process),
960 ATENL_EXT(IBF_SET_VAL, 6, atenl_nl_process),
961 ATENL_EXT(IBF_GET_STATUS, 10, atenl_nl_process),
962 ATENL_EXT(IBF_PROF_UPDATE_ALL, 6, atenl_nl_process_many),
963};
964#undef ATENL_EXT
965
966int atenl_hqa_recv(struct atenl *an, struct atenl_data *data)
967{
968 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
969 u16 cmd_type = ntohs(hdr->cmd_type);
970 int fd = an->pipefd[PIPE_WRITE];
971 int ret;
972
973 if (ntohl(hdr->magic_no) != RACFG_MAGIC_NO)
974 return -EINVAL;
975
976 if (FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_ETHREQ &&
977 FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_PLATFORM_MODULE) {
978 atenl_err("[%d]%s: cmd type error = 0x%x\n", getpid(), __func__, cmd_type);
979 return -EINVAL;
980 }
981
982 atenl_dbg("[%d]%s: recv cmd type = 0x%x, id = 0x%x\n",
983 getpid(), __func__, cmd_type, ntohs(hdr->cmd_id));
984
985 ret = write(fd, data, data->len);
986 if (ret < 0) {
987 perror("pipe write");
988 return ret;
989 }
990
991 return 0;
992}
993
994int atenl_hqa_proc_cmd(struct atenl *an, struct atenl_data *data)
995{
996 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
997 const struct atenl_cmd_ops *ops;
998 u16 cmd_id = ntohs(hdr->cmd_id);
999 u16 status = 0;
1000
1001 data->cmd = atenl_get_cmd_by_id(cmd_id);
1002 if (data->cmd == HQA_CMD_ERR) {
1003 atenl_err("Unknown command id: 0x%04x\n", cmd_id);
1004 goto done;
1005 }
1006
1007 if (data->cmd == HQA_CMD_EXT) {
1008 data->ext_id = ntohl(*(u32 *)hdr->data);
1009 data->ext_cmd = atenl_get_ext_cmd(data->ext_id);
1010 if (data->ext_cmd == HQA_EXT_CMD_UNSPEC) {
1011 atenl_err("Unknown ext command id: 0x%04x\n", data->ext_id);
1012 goto done;
1013 }
1014
1015 ops = &atenl_ext_ops[data->ext_cmd];
1016 } else {
1017 ops = &atenl_ops[data->cmd];
1018 }
1019
1020 atenl_dbg_print_data(data, __func__,
1021 ntohs(hdr->len) + ETH_HLEN + RACFG_HLEN);
1022 if (ops->ops)
1023 status = htons(ops->ops(an, data));
1024 if (ops->resp_len)
1025 hdr->len = htons(ops->resp_len);
1026
1027 *(u16 *)hdr->data = status;
1028
1029done:
1030 data->len = ntohs(hdr->len) + ETH_HLEN + RACFG_HLEN;
1031 hdr->cmd_type |= ~htons(RACFG_CMD_TYPE_MASK);
1032
1033 return 0;
1034}