blob: 2196fe215cb1b60313169fbf665a56b5afa3cac8 [file] [log] [blame]
developer22c7ab62022-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:
developer48fbcb62022-03-10 14:24:55 +0800318 atenl_nl_write_efuse_all(an);
developer22c7ab62022-01-24 11:13:32 +0800319 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 */
developer22c7ab62022-01-24 11:13:32 +0800342 for (i = 0; i < DIV_ROUND_UP(len, 2); i++) {
343 val = ntohs(v[i + 2]);
344 memcpy(&an->eeprom_data[offset + i * 2], &val, 2);
345 }
developer22c7ab62022-01-24 11:13:32 +0800346 }
347 }
348
349 return 0;
350}
351
352static int
353atenl_hqa_get_efuse_free_block(struct atenl *an, struct atenl_data *data)
354{
355 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
356 u32 free_block = htonl(0x14);
357
358 /* TODO */
359 *(u32 *)(hdr->data + 2) = free_block;
360
361 return 0;
362}
363
364static int
365atenl_hqa_get_band(struct atenl *an, struct atenl_data *data)
366{
367 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
368 u32 band = ntohl(*(u32 *)hdr->data);
369
370 if (band >= MAX_BAND_NUM)
371 return -EINVAL;
372
373 *(u32 *)(hdr->data + 2) = htonl(an->anb[band].cap);
374
375 return 0;
376}
377
378static int
379atenl_hqa_get_tx_power(struct atenl *an, struct atenl_data *data)
380{
381 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
382 u32 tx_power = htonl(28);
383
384 memcpy(hdr->data + 6, &tx_power, 4);
385
386 return 0;
387}
388
389static int
390atenl_hqa_get_freq_offset(struct atenl *an, struct atenl_data *data)
391{
392 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
393 u32 freq_offset = htonl(10);
394
395 /* TODO */
396 memcpy(hdr->data + 2, &freq_offset, 4);
397
398 return 0;
399}
400
401static int
402atenl_hqa_get_cfg(struct atenl *an, struct atenl_data *data)
403{
404 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
405 u32 val = htonl(1);
406
407 /* TODO */
408 memcpy(hdr->data + 2, &val, 4);
409
410 return 0;
411}
412
413static int
414atenl_hqa_read_temperature(struct atenl *an, struct atenl_data *data)
415{
416 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
417 char buf[64], *str;
418 int fd, ret;
419 u32 temp;
420 u8 phy_idx = get_band_val(an, an->cur_band, phy_idx);
421
422 ret = snprintf(buf, sizeof(buf),
423 "/sys/class/ieee80211/phy%u/hwmon%u/temp1_input",
424 phy_idx, phy_idx);
425 if (snprintf_error(sizeof(buf), ret))
426 return -1;
427
428 fd = open(buf, O_RDONLY);
429 if (fd < 0)
430 return fd;
431
432 ret = read(fd, buf, sizeof(buf) - 1);
433 if (ret < 0)
434 goto out;
435 buf[ret] = 0;
436
437 str = strchr(buf, ':');
438 str += 2;
439 temp = strtol(str, NULL, 10);
440 /* unit conversion */
441 *(u32 *)(hdr->data + 2) = htonl(temp / 1000);
442
443 ret = 0;
444out:
445 close(fd);
446
447 return ret;
448}
449
450static int
451atenl_hqa_skip(struct atenl *an, struct atenl_data *data)
452{
453 return 0;
454}
455
456static int
457atenl_hqa_check_efuse_mode(struct atenl *an, struct atenl_data *data)
458{
459 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
460 bool flash_mode = an->mtd_part != NULL;
461 enum atenl_cmd cmd = data->cmd;
462 u32 mode;
463
464 switch (cmd) {
465 case HQA_CMD_CHECK_EFUSE_MODE:
466 mode = flash_mode ? 0 : 1;
467 break;
468 case HQA_CMD_CHECK_EFUSE_MODE_TYPE:
469 mode = flash_mode ? E2P_FLASH_MODE : E2P_BIN_MODE;
470 break;
471 case HQA_CMD_CHECK_EFUSE_MODE_NATIVE:
472 mode = flash_mode ? E2P_FLASH_MODE : E2P_EFUSE_MODE;
473 break;
474 default:
475 mode = E2P_BIN_MODE;
476 break;
477 }
478
479 *(u32 *)(hdr->data + 2) = htonl(mode);
480
481 return 0;
482}
483
484static inline u16
485atenl_get_freq_by_channel(u8 ch_band, u16 ch)
486{
487 u16 base;
488
489 if (ch_band == CH_BAND_6GHZ) {
490 base = 5950;
491 } else if (ch_band == CH_BAND_5GHZ) {
492 if (ch >= 184)
493 return 4920 + (ch - 184) * 5;
494
495 base = 5000;
496 } else {
497 base = 2407;
498 }
499
500 return base + ch * 5;
501}
502
503u16 atenl_get_center_channel(u8 bw, u8 ch_band, u16 ctrl_ch)
504{
505 const struct atenl_channel *chan = NULL;
506 const struct atenl_channel *ch_list;
507 u16 center_ch;
508 u8 ch_num;
509 int i;
510
511 if (ch_band == CH_BAND_2GHZ || bw <= TEST_CBW_40MHZ)
512 return 0;
513
514 if (ch_band == CH_BAND_6GHZ) {
515 ch_list = atenl_channels_6ghz;
516 ch_num = ARRAY_SIZE(atenl_channels_6ghz);
517 } else {
518 ch_list = atenl_channels_5ghz;
519 ch_num = ARRAY_SIZE(atenl_channels_5ghz);
520 }
521
522 for (i = 0; i < ch_num; i++) {
523 if (ctrl_ch == ch_list[i].ch) {
524 chan = &ch_list[i];
525 break;
526 }
527 }
528
529 if (!chan)
530 return 0;
531
532 switch (bw) {
533 case TEST_CBW_160MHZ:
534 center_ch = chan->ch_160;
535 break;
536 case TEST_CBW_80MHZ:
537 center_ch = chan->ch_80;
538 break;
539 default:
540 center_ch = 0;
541 break;
542 }
543
544 return center_ch;
545}
546
547static void atenl_get_bw_string(u8 bw, char *buf)
548{
549 switch (bw) {
550 case TEST_CBW_160MHZ:
551 sprintf(buf, "160");
552 break;
553 case TEST_CBW_80MHZ:
554 sprintf(buf, "80");
555 break;
556 case TEST_CBW_40MHZ:
557 sprintf(buf, "40");
558 break;
559 default:
560 sprintf(buf, "20");
561 break;
562 }
563}
564
565void atenl_set_channel(struct atenl *an, u8 bw, u8 ch_band,
566 u16 ch, u16 center_ch1, u16 center_ch2)
567{
568 char bw_str[8] = {};
569 char cmd[128];
570 u16 freq = atenl_get_freq_by_channel(ch_band, ch);
571 u16 freq_center1 = atenl_get_freq_by_channel(ch_band, center_ch1);
572 int ret;
573
574 if (bw > TEST_CBW_MAX)
575 return;
576
577 atenl_get_bw_string(bw, bw_str);
578
579 if (bw == TEST_CBW_20MHZ)
580 ret = snprintf(cmd, sizeof(cmd), "iw dev mon%d set freq %u %s",
581 get_band_val(an, an->cur_band, phy_idx),
582 freq, bw_str);
583 else
584 ret = snprintf(cmd, sizeof(cmd), "iw dev mon%d set freq %u %s %u",
585 get_band_val(an, an->cur_band, phy_idx),
586 freq, bw_str, freq_center1);
587 if (snprintf_error(sizeof(cmd), ret))
588 return;
589
590 atenl_dbg("[%d]%s: cmd: %s\n", getpid(), __func__, cmd);
591
592 system(cmd);
593}
594
595static int
596atenl_hqa_set_channel(struct atenl *an, struct atenl_data *data)
597{
598 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
599 u32 *v = (u32 *)hdr->data;
600 u8 band = ntohl(v[2]);
601 u16 ch1 = ntohl(v[3]); /* center */
602 u16 ch2 = ntohl(v[4]);
603 u8 bw = ntohl(v[5]);
604 u8 pri_sel = ntohl(v[7]);
605 u8 ch_band = ntohl(v[9]);
606 u16 ctrl_ch = 0;
607
608 if (band >= MAX_BAND_NUM)
609 return -EINVAL;
610
611 if ((bw == TEST_CBW_160MHZ && pri_sel > 7) ||
612 (bw == TEST_CBW_80MHZ && pri_sel > 3) ||
613 (bw == TEST_CBW_40MHZ && pri_sel > 1)) {
614 atenl_err("%s: ctrl channel select error\n", __func__);
615 return -EINVAL;
616 }
617
618 an->cur_band = band;
619
620 if (ch_band == CH_BAND_2GHZ) {
621 ctrl_ch = ch1;
622 switch (bw) {
623 case TEST_CBW_40MHZ:
624 if (pri_sel == 1)
625 ctrl_ch += 2;
626 else
627 ctrl_ch -= 2;
628 break;
629 default:
630 break;
631 }
632
633 atenl_set_channel(an, bw, CH_BAND_2GHZ, ctrl_ch, ch1, 0);
634 } else {
635 const struct atenl_channel *chan = NULL;
636 const struct atenl_channel *ch_list;
637 u8 ch_num;
638 int i;
639
640 if (ch_band == CH_BAND_6GHZ) {
641 ch_list = atenl_channels_6ghz;
642 ch_num = ARRAY_SIZE(atenl_channels_6ghz);
643 } else {
644 ch_list = atenl_channels_5ghz;
645 ch_num = ARRAY_SIZE(atenl_channels_5ghz);
646 }
647
648 if (bw == TEST_CBW_160MHZ) {
649 for (i = 0; i < ch_num; i++) {
650 if (ch1 == ch_list[i].ch_160) {
651 chan = &ch_list[i];
652 break;
653 } else if (ch1 < ch_list[i].ch_160) {
654 chan = &ch_list[i - 1];
655 break;
656 }
657 }
658 } else if (bw == TEST_CBW_80MHZ) {
659 for (i = 0; i < ch_num; i++) {
660 if (ch1 == ch_list[i].ch_80) {
661 chan = &ch_list[i];
662 break;
663 } else if (ch1 < ch_list[i].ch_80) {
664 chan = &ch_list[i - 1];
665 break;
666 }
667 }
668 } else {
669 for (i = 0; i < ch_num; i++) {
670 if (ch1 <= ch_list[i].ch) {
671 if (ch1 == ch_list[i].ch)
672 chan = &ch_list[i];
673 else
674 chan = &ch_list[i - 1];
675 break;
676 }
677 }
678 }
679
680 if (!chan)
681 return -EINVAL;
682
683 if (bw != TEST_CBW_20MHZ) {
684 chan += pri_sel;
685 if (chan > &ch_list[ch_num - 1])
686 return -EINVAL;
687 }
688 ctrl_ch = chan->ch;
689
690 atenl_set_channel(an, bw, ch_band, ctrl_ch, ch1, ch2);
691 }
692
693 *(u32 *)(hdr->data + 2) = data->ext_id;
694
695 return 0;
696}
697
698static int
699atenl_hqa_tx_time_option(struct atenl *an, struct atenl_data *data)
700{
701 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
702 u32 *v = (u32 *)hdr->data;
703 u8 band = ntohl(v[1]);
704 u32 option = ntohl(v[2]);
705
706 if (band >= MAX_BAND_NUM)
707 return -EINVAL;
708
709 set_band_val(an, band, use_tx_time, !!option);
710 *(u32 *)(hdr->data + 2) = data->ext_id;
711
712 return 0;
713}
714
715static inline enum atenl_cmd atenl_get_cmd_by_id(u16 cmd_idx)
716{
717#define CMD_ID_GROUP GENMASK(15, 8)
718 u8 group = FIELD_GET(CMD_ID_GROUP, cmd_idx);
719
720 if (cmd_idx == 0x1600)
721 return HQA_CMD_EXT;
722
723 if (group == 0x10) {
724 switch (cmd_idx) {
725 case 0x1000:
726 return HQA_CMD_OPEN_ADAPTER;
727 case 0x1001:
728 return HQA_CMD_CLOSE_ADAPTER;
729 case 0x100b:
730 return HQA_CMD_SET_TX_PATH;
731 case 0x100c:
732 return HQA_CMD_SET_RX_PATH;
733 case 0x1011:
734 return HQA_CMD_SET_TX_POWER;
735 case 0x1018:
736 return HQA_CMD_SET_TX_POWER_MANUAL;
737 case 0x100d:
738 return HQA_CMD_LEGACY;
739 default:
740 break;
741 }
742 } else if (group == 0x11) {
743 switch (cmd_idx) {
744 case 0x1104:
745 return HQA_CMD_SET_TX_BW;
746 case 0x1105:
747 return HQA_CMD_SET_TX_PKT_BW;
748 case 0x1106:
749 return HQA_CMD_SET_TX_PRI_BW;
750 case 0x1107:
751 return HQA_CMD_SET_FREQ_OFFSET;
752 case 0x1109:
753 return HQA_CMD_SET_TSSI;
754 case 0x110d:
755 return HQA_CMD_ANT_SWAP_CAP;
756 case 0x1101:
757 case 0x1102:
758 return HQA_CMD_LEGACY;
759 default:
760 break;
761 }
762 } else if (group == 0x12) {
763 switch (cmd_idx) {
764 case 0x1200:
765 return HQA_CMD_RESET_TX_RX_COUNTER;
766 default:
767 break;
768 }
769 } else if (group == 0x13) {
770 switch (cmd_idx) {
771 case 0x1301:
772 return HQA_CMD_WRITE_MAC_BBP_REG;
773 case 0x1302:
774 return HQA_CMD_READ_MAC_BBP_REG;
775 case 0x1307:
776 return HQA_CMD_READ_EEPROM_BULK;
777 case 0x1306:
778 case 0x1308:
779 return HQA_CMD_WRITE_EEPROM_BULK;
780 case 0x1309:
781 return HQA_CMD_CHECK_EFUSE_MODE;
782 case 0x130a:
783 return HQA_CMD_GET_EFUSE_FREE_BLOCK;
784 case 0x130d:
785 return HQA_CMD_GET_TX_POWER;
786 case 0x130e:
787 return HQA_CMD_SET_CFG;
788 case 0x130f:
789 return HQA_CMD_GET_FREQ_OFFSET;
790 case 0x1311:
791 return HQA_CMD_CONTINUOUS_TX;
792 case 0x1312:
793 return HQA_CMD_SET_RX_PKT_LEN;
794 case 0x1313:
795 return HQA_CMD_GET_TX_INFO;
796 case 0x1314:
797 return HQA_CMD_GET_CFG;
798 case 0x131f:
799 return HQA_CMD_UNKNOWN;
800 case 0x131a:
801 return HQA_CMD_GET_TX_TONE_POWER;
802 default:
803 break;
804 }
805 } else if (group == 0x14) {
806 switch (cmd_idx) {
807 case 0x1401:
808 return HQA_CMD_READ_TEMPERATURE;
809 default:
810 break;
811 }
812 } else if (group == 0x15) {
813 switch (cmd_idx) {
814 case 0x1500:
815 return HQA_CMD_GET_FW_INFO;
816 case 0x1505:
817 return HQA_CMD_SET_TSSI;
818 case 0x1509:
819 return HQA_CMD_SET_RF_MODE;
820 case 0x1511:
821 return HQA_CMD_WRITE_BUFFER_DONE;
822 case 0x1514:
823 return HQA_CMD_GET_CHIP_ID;
824 case 0x151b:
825 return HQA_CMD_GET_SUB_CHIP_ID;
826 case 0x151c:
827 return HQA_CMD_GET_RX_INFO;
828 case 0x151e:
829 return HQA_CMD_GET_RF_CAP;
830 case 0x1522:
831 return HQA_CMD_CHECK_EFUSE_MODE_TYPE;
832 case 0x1523:
833 return HQA_CMD_CHECK_EFUSE_MODE_NATIVE;
834 case 0x152d:
835 return HQA_CMD_GET_BAND;
836 case 0x1594:
837 return HQA_CMD_SET_RU;
838 case 0x1502:
839 case 0x150b:
840 return HQA_CMD_LEGACY;
841 default:
842 break;
843 }
844 }
845
846 return HQA_CMD_ERR;
847}
848
849static inline enum atenl_ext_cmd atenl_get_ext_cmd(u16 ext_cmd_idx)
850{
851#define EXT_CMD_ID_GROUP GENMASK(7, 4)
852 u8 ext_group = FIELD_GET(EXT_CMD_ID_GROUP, ext_cmd_idx);
853
854 if (ext_group == 0) {
855 switch (ext_cmd_idx) {
856 case 0x1:
857 return HQA_EXT_CMD_SET_CHANNEL;
858 case 0x2:
859 return HQA_EXT_CMD_SET_TX;
860 case 0x3:
861 return HQA_EXT_CMD_START_TX;
862 case 0x4:
863 return HQA_EXT_CMD_START_RX;
864 case 0x5:
865 return HQA_EXT_CMD_STOP_TX;
866 case 0x6:
867 return HQA_EXT_CMD_STOP_RX;
868 case 0x8:
869 return HQA_EXT_CMD_IBF_SET_VAL;
870 case 0x9:
871 return HQA_EXT_CMD_IBF_GET_STATUS;
872 case 0xc:
873 return HQA_EXT_CMD_IBF_PROF_UPDATE_ALL;
874 default:
875 break;
876 }
877 } else if (ext_group == 1) {
878 } else if (ext_group == 2) {
879 switch (ext_cmd_idx) {
880 case 0x26:
881 return HQA_EXT_CMD_SET_TX_TIME_OPT;
882 case 0x27:
883 return HQA_EXT_CMD_OFF_CH_SCAN;
884 default:
885 break;
886 }
887 }
888
889 return HQA_EXT_CMD_UNSPEC;
890}
891
892#define ATENL_GROUP(_cmd, _resp_len, _ops) \
893 [HQA_CMD_##_cmd] = { .resp_len=_resp_len, .ops=_ops }
894static const struct atenl_cmd_ops atenl_ops[] = {
895 ATENL_GROUP(OPEN_ADAPTER, 2, atenl_hqa_adapter),
896 ATENL_GROUP(CLOSE_ADAPTER, 2, atenl_hqa_adapter),
897 ATENL_GROUP(SET_TX_PATH, 2, atenl_nl_process),
898 ATENL_GROUP(SET_RX_PATH, 2, atenl_nl_process),
899 ATENL_GROUP(SET_TX_POWER, 2, atenl_nl_process),
900 ATENL_GROUP(SET_TX_POWER_MANUAL, 2, atenl_hqa_skip),
901 ATENL_GROUP(SET_TX_BW, 2, atenl_hqa_skip),
902 ATENL_GROUP(SET_TX_PKT_BW, 2, atenl_hqa_skip),
903 ATENL_GROUP(SET_TX_PRI_BW, 2, atenl_hqa_skip),
904 ATENL_GROUP(SET_FREQ_OFFSET, 2, atenl_nl_process),
905 ATENL_GROUP(ANT_SWAP_CAP, 6, atenl_hqa_skip),
906 ATENL_GROUP(RESET_TX_RX_COUNTER, 2, atenl_hqa_reset_counter),
907 ATENL_GROUP(WRITE_MAC_BBP_REG, 2, atenl_hqa_mac_bbp_reg),
908 ATENL_GROUP(READ_MAC_BBP_REG, 0, atenl_hqa_mac_bbp_reg),
909 ATENL_GROUP(READ_EEPROM_BULK, 0, atenl_hqa_eeprom_bulk),
910 ATENL_GROUP(WRITE_EEPROM_BULK, 2, atenl_hqa_eeprom_bulk),
911 ATENL_GROUP(CHECK_EFUSE_MODE, 6, atenl_hqa_check_efuse_mode),
912 ATENL_GROUP(GET_EFUSE_FREE_BLOCK, 6, atenl_hqa_get_efuse_free_block),
913 ATENL_GROUP(GET_TX_POWER, 10, atenl_hqa_get_tx_power),
914 ATENL_GROUP(GET_FREQ_OFFSET, 6, atenl_hqa_get_freq_offset), /*TODO: MCU CMD, read eeprom?*/
915 ATENL_GROUP(CONTINUOUS_TX, 6, atenl_nl_process),
916 ATENL_GROUP(SET_RX_PKT_LEN, 2, atenl_hqa_skip),
917 ATENL_GROUP(GET_TX_INFO, 10, atenl_nl_process),
918 ATENL_GROUP(GET_CFG, 6, atenl_hqa_get_cfg), /*TODO*/
919 ATENL_GROUP(GET_TX_TONE_POWER, 6, atenl_hqa_skip),
920 ATENL_GROUP(SET_CFG, 2, atenl_nl_process),
921 ATENL_GROUP(READ_TEMPERATURE, 6, atenl_hqa_read_temperature),
922 ATENL_GROUP(GET_FW_INFO, 32, atenl_hqa_skip), /* TODO: check format */
923 ATENL_GROUP(SET_TSSI, 2, atenl_nl_process),
924 ATENL_GROUP(SET_RF_MODE, 2, atenl_hqa_set_rf_mode),
925 ATENL_GROUP(WRITE_BUFFER_DONE, 2, atenl_hqa_eeprom_bulk),
926 ATENL_GROUP(GET_CHIP_ID, 6, atenl_hqa_get_chip_id),
927 ATENL_GROUP(GET_SUB_CHIP_ID, 6, atenl_hqa_get_sub_chip_id),
928 ATENL_GROUP(GET_RX_INFO, 0, atenl_nl_process),
929 ATENL_GROUP(GET_RF_CAP, 10, atenl_hqa_get_rf_cap),
930 ATENL_GROUP(CHECK_EFUSE_MODE_TYPE, 6, atenl_hqa_check_efuse_mode),
931 ATENL_GROUP(CHECK_EFUSE_MODE_NATIVE, 6, atenl_hqa_check_efuse_mode),
932 ATENL_GROUP(GET_BAND, 6, atenl_hqa_get_band),
933 ATENL_GROUP(SET_RU, 2, atenl_nl_process_many),
934
935 ATENL_GROUP(LEGACY, 2, atenl_hqa_skip),
936 ATENL_GROUP(UNKNOWN, 1024, atenl_hqa_skip),
937};
938#undef ATENL_GROUP
939
940#define ATENL_EXT(_cmd, _resp_len, _ops) \
941 [HQA_EXT_CMD_##_cmd] = { .resp_len=_resp_len, .ops=_ops }
942static const struct atenl_cmd_ops atenl_ext_ops[] = {
943 ATENL_EXT(SET_CHANNEL, 6, atenl_hqa_set_channel),
944 ATENL_EXT(SET_TX, 6, atenl_nl_process),
945 ATENL_EXT(START_TX, 6, atenl_nl_process),
946 ATENL_EXT(STOP_TX, 6, atenl_nl_process),
947 ATENL_EXT(START_RX, 6, atenl_nl_process),
948 ATENL_EXT(STOP_RX, 6, atenl_nl_process),
949 ATENL_EXT(SET_TX_TIME_OPT, 6, atenl_hqa_tx_time_option),
950 ATENL_EXT(OFF_CH_SCAN, 6, atenl_nl_process),
951 ATENL_EXT(IBF_SET_VAL, 6, atenl_nl_process),
952 ATENL_EXT(IBF_GET_STATUS, 10, atenl_nl_process),
953 ATENL_EXT(IBF_PROF_UPDATE_ALL, 6, atenl_nl_process_many),
954};
955#undef ATENL_EXT
956
957int atenl_hqa_recv(struct atenl *an, struct atenl_data *data)
958{
959 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
960 u16 cmd_type = ntohs(hdr->cmd_type);
961 int fd = an->pipefd[PIPE_WRITE];
962 int ret;
963
964 if (ntohl(hdr->magic_no) != RACFG_MAGIC_NO)
965 return -EINVAL;
966
967 if (FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_ETHREQ &&
968 FIELD_GET(RACFG_CMD_TYPE_MASK, cmd_type) != RACFG_CMD_TYPE_PLATFORM_MODULE) {
969 atenl_err("[%d]%s: cmd type error = 0x%x\n", getpid(), __func__, cmd_type);
970 return -EINVAL;
971 }
972
973 atenl_dbg("[%d]%s: recv cmd type = 0x%x, id = 0x%x\n",
974 getpid(), __func__, cmd_type, ntohs(hdr->cmd_id));
975
976 ret = write(fd, data, data->len);
977 if (ret < 0) {
978 perror("pipe write");
979 return ret;
980 }
981
982 return 0;
983}
984
985int atenl_hqa_proc_cmd(struct atenl *an, struct atenl_data *data)
986{
987 struct atenl_cmd_hdr *hdr = atenl_hdr(data);
988 const struct atenl_cmd_ops *ops;
989 u16 cmd_id = ntohs(hdr->cmd_id);
990 u16 status = 0;
991
992 data->cmd = atenl_get_cmd_by_id(cmd_id);
993 if (data->cmd == HQA_CMD_ERR) {
994 atenl_err("Unknown command id: 0x%04x\n", cmd_id);
995 goto done;
996 }
997
998 if (data->cmd == HQA_CMD_EXT) {
999 data->ext_id = ntohl(*(u32 *)hdr->data);
1000 data->ext_cmd = atenl_get_ext_cmd(data->ext_id);
1001 if (data->ext_cmd == HQA_EXT_CMD_UNSPEC) {
1002 atenl_err("Unknown ext command id: 0x%04x\n", data->ext_id);
1003 goto done;
1004 }
1005
1006 ops = &atenl_ext_ops[data->ext_cmd];
1007 } else {
1008 ops = &atenl_ops[data->cmd];
1009 }
1010
1011 atenl_dbg_print_data(data, __func__,
1012 ntohs(hdr->len) + ETH_HLEN + RACFG_HLEN);
1013 if (ops->ops)
1014 status = htons(ops->ops(an, data));
1015 if (ops->resp_len)
1016 hdr->len = htons(ops->resp_len);
1017
1018 *(u16 *)hdr->data = status;
1019
1020done:
1021 data->len = ntohs(hdr->len) + ETH_HLEN + RACFG_HLEN;
1022 hdr->cmd_type |= ~htons(RACFG_CMD_TYPE_MASK);
1023
1024 return 0;
1025}