1 /* SPDX-License-Identifier: GPL-2.0 */
2 /******************************************************************************
3 *
4 * Copyright(c) 2015 - 2019 Realtek Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 *****************************************************************************/
16 #define _HAL_HALMAC_C_
17
18 #include <drv_types.h> /* PADAPTER, struct dvobj_priv, SDIO_ERR_VAL8 and etc. */
19 #include <hal_data.h> /* efuse, PHAL_DATA_TYPE and etc. */
20 #include "hal_halmac.h" /* dvobj_to_halmac() and ect. */
21
22 /*
23 * HALMAC take return value 0 for fail and 1 for success to replace
24 * _FALSE/_TRUE after V1_04_09
25 */
26 #define RTW_HALMAC_FAIL 0
27 #define RTW_HALMAC_SUCCESS 1
28
29 #define DEFAULT_INDICATOR_TIMELMT 1000 /* ms */
30 #define MSG_PREFIX "[HALMAC]"
31
32 #define RTW_HALMAC_DLFW_MEM_NO_STOP_TX
33
34 /*
35 * Driver API for HALMAC operations
36 */
37
38 #ifdef CONFIG_SDIO_HCI
39 #include <rtw_sdio.h>
40
_halmac_mac_reg_page0_chk(const char * func,struct dvobj_priv * dvobj,u32 offset)41 static u8 _halmac_mac_reg_page0_chk(const char *func, struct dvobj_priv *dvobj, u32 offset)
42 {
43 #if defined(CONFIG_IO_CHECK_IN_ANA_LOW_CLK) && defined(CONFIG_LPS_LCLK)
44 struct pwrctrl_priv *pwrpriv = &dvobj->pwrctl_priv;
45 u32 mac_reg_offset = 0;
46
47 if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
48 return _TRUE;
49
50 if (pwrpriv->lps_level == LPS_NORMAL)
51 return _TRUE;
52
53 if (pwrpriv->rpwm >= PS_STATE_S2)
54 return _TRUE;
55
56 if (offset & (WLAN_IOREG_DEVICE_ID << 13)) { /*WLAN_IOREG_OFFSET*/
57 mac_reg_offset = offset & HALMAC_WLAN_MAC_REG_MSK;
58 if (mac_reg_offset < 0x100) {
59 RTW_ERR(FUNC_ADPT_FMT
60 "access MAC REG -0x%04x in PS-mode:0x%02x (rpwm:0x%02x, lps_level:0x%02x)\n",
61 FUNC_ADPT_ARG(dvobj_get_primary_adapter(dvobj)), mac_reg_offset,
62 pwrpriv->pwr_mode, pwrpriv->rpwm, pwrpriv->lps_level);
63 rtw_warn_on(1);
64 return _FALSE;
65 }
66 }
67 #endif
68 return _TRUE;
69 }
70
_halmac_sdio_cmd52_read(void * p,u32 offset)71 static u8 _halmac_sdio_cmd52_read(void *p, u32 offset)
72 {
73 struct dvobj_priv *d;
74 u8 val;
75 u8 ret;
76
77
78 d = (struct dvobj_priv *)p;
79 _halmac_mac_reg_page0_chk(__func__, d, offset);
80 ret = rtw_sdio_read_cmd52(d, offset, &val, 1);
81 if (_FAIL == ret) {
82 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
83 return SDIO_ERR_VAL8;
84 }
85
86 return val;
87 }
88
_halmac_sdio_cmd52_write(void * p,u32 offset,u8 val)89 static void _halmac_sdio_cmd52_write(void *p, u32 offset, u8 val)
90 {
91 struct dvobj_priv *d;
92 u8 ret;
93
94
95 d = (struct dvobj_priv *)p;
96 _halmac_mac_reg_page0_chk(__func__, d, offset);
97 ret = rtw_sdio_write_cmd52(d, offset, &val, 1);
98 if (_FAIL == ret)
99 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
100 }
101
_halmac_sdio_reg_read_8(void * p,u32 offset)102 static u8 _halmac_sdio_reg_read_8(void *p, u32 offset)
103 {
104 struct dvobj_priv *d;
105 u8 *pbuf;
106 u8 val;
107 u8 ret;
108
109
110 d = (struct dvobj_priv *)p;
111 val = SDIO_ERR_VAL8;
112 _halmac_mac_reg_page0_chk(__func__, d, offset);
113 pbuf = rtw_zmalloc(1);
114 if (!pbuf)
115 return val;
116
117 ret = rtw_sdio_read_cmd53(d, offset, pbuf, 1);
118 if (ret == _FAIL) {
119 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
120 goto exit;
121 }
122
123 val = *pbuf;
124
125 exit:
126 rtw_mfree(pbuf, 1);
127
128 return val;
129 }
130
_halmac_sdio_reg_read_16(void * p,u32 offset)131 static u16 _halmac_sdio_reg_read_16(void *p, u32 offset)
132 {
133 struct dvobj_priv *d;
134 u8 *pbuf;
135 u16 val;
136 u8 ret;
137
138
139 d = (struct dvobj_priv *)p;
140 val = SDIO_ERR_VAL16;
141 _halmac_mac_reg_page0_chk(__func__, d, offset);
142 pbuf = rtw_zmalloc(2);
143 if (!pbuf)
144 return val;
145
146 ret = rtw_sdio_read_cmd53(d, offset, pbuf, 2);
147 if (ret == _FAIL) {
148 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
149 goto exit;
150 }
151
152 val = le16_to_cpu(*(u16 *)pbuf);
153
154 exit:
155 rtw_mfree(pbuf, 2);
156
157 return val;
158 }
159
_halmac_sdio_reg_read_32(void * p,u32 offset)160 static u32 _halmac_sdio_reg_read_32(void *p, u32 offset)
161 {
162 struct dvobj_priv *d;
163 u8 *pbuf;
164 u32 val;
165 u8 ret;
166
167
168 d = (struct dvobj_priv *)p;
169 val = SDIO_ERR_VAL32;
170 _halmac_mac_reg_page0_chk(__func__, d, offset);
171 pbuf = rtw_zmalloc(4);
172 if (!pbuf)
173 return val;
174
175 ret = rtw_sdio_read_cmd53(d, offset, pbuf, 4);
176 if (ret == _FAIL) {
177 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
178 goto exit;
179 }
180
181 val = le32_to_cpu(*(u32 *)pbuf);
182
183 exit:
184 rtw_mfree(pbuf, 4);
185
186 return val;
187 }
188
_halmac_sdio_reg_read_n(void * p,u32 offset,u32 size,u8 * data)189 static u8 _halmac_sdio_reg_read_n(void *p, u32 offset, u32 size, u8 *data)
190 {
191 struct dvobj_priv *d = (struct dvobj_priv *)p;
192 u8 *pbuf;
193 u8 ret;
194 u8 rst = RTW_HALMAC_FAIL;
195 u32 sdio_read_size;
196
197
198 if (!data)
199 return rst;
200
201 sdio_read_size = RND4(size);
202 sdio_read_size = rtw_sdio_cmd53_align_size(d, sdio_read_size);
203
204 pbuf = rtw_zmalloc(sdio_read_size);
205 if (!pbuf)
206 return rst;
207
208 ret = rtw_sdio_read_cmd53(d, offset, pbuf, sdio_read_size);
209 if (ret == _FAIL) {
210 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
211 goto exit;
212 }
213
214 _rtw_memcpy(data, pbuf, size);
215 rst = RTW_HALMAC_SUCCESS;
216 exit:
217 rtw_mfree(pbuf, sdio_read_size);
218
219 return rst;
220 }
221
_halmac_sdio_reg_write_8(void * p,u32 offset,u8 val)222 static void _halmac_sdio_reg_write_8(void *p, u32 offset, u8 val)
223 {
224 struct dvobj_priv *d;
225 u8 *pbuf;
226 u8 ret;
227
228
229 d = (struct dvobj_priv *)p;
230 _halmac_mac_reg_page0_chk(__func__, d, offset);
231 pbuf = rtw_zmalloc(1);
232 if (!pbuf)
233 return;
234 _rtw_memcpy(pbuf, &val, 1);
235
236 ret = rtw_sdio_write_cmd53(d, offset, pbuf, 1);
237 if (ret == _FAIL)
238 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
239
240 rtw_mfree(pbuf, 1);
241 }
242
_halmac_sdio_reg_write_16(void * p,u32 offset,u16 val)243 static void _halmac_sdio_reg_write_16(void *p, u32 offset, u16 val)
244 {
245 struct dvobj_priv *d;
246 u8 *pbuf;
247 u8 ret;
248
249
250 d = (struct dvobj_priv *)p;
251 _halmac_mac_reg_page0_chk(__func__, d, offset);
252 val = cpu_to_le16(val);
253 pbuf = rtw_zmalloc(2);
254 if (!pbuf)
255 return;
256 _rtw_memcpy(pbuf, &val, 2);
257
258 ret = rtw_sdio_write_cmd53(d, offset, pbuf, 2);
259 if (ret == _FAIL)
260 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
261
262 rtw_mfree(pbuf, 2);
263 }
264
_halmac_sdio_reg_write_32(void * p,u32 offset,u32 val)265 static void _halmac_sdio_reg_write_32(void *p, u32 offset, u32 val)
266 {
267 struct dvobj_priv *d;
268 u8 *pbuf;
269 u8 ret;
270
271
272 d = (struct dvobj_priv *)p;
273 _halmac_mac_reg_page0_chk(__func__, d, offset);
274 val = cpu_to_le32(val);
275 pbuf = rtw_zmalloc(4);
276 if (!pbuf)
277 return;
278 _rtw_memcpy(pbuf, &val, 4);
279
280 ret = rtw_sdio_write_cmd53(d, offset, pbuf, 4);
281 if (ret == _FAIL)
282 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
283
284 rtw_mfree(pbuf, 4);
285 }
286
_halmac_sdio_read_cia(void * p,u32 offset)287 static u8 _halmac_sdio_read_cia(void *p, u32 offset)
288 {
289 struct dvobj_priv *d;
290 u8 data = 0;
291 u8 ret;
292
293
294 d = (struct dvobj_priv *)p;
295
296 ret = rtw_sdio_f0_read(d, offset, &data, 1);
297 if (ret == _FAIL)
298 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
299
300 return data;
301 }
302
303 #else /* !CONFIG_SDIO_HCI */
304
_halmac_reg_read_8(void * p,u32 offset)305 static u8 _halmac_reg_read_8(void *p, u32 offset)
306 {
307 struct dvobj_priv *d;
308 PADAPTER adapter;
309
310
311 d = (struct dvobj_priv *)p;
312 adapter = dvobj_get_primary_adapter(d);
313
314 return rtw_read8(adapter, offset);
315 }
316
_halmac_reg_read_16(void * p,u32 offset)317 static u16 _halmac_reg_read_16(void *p, u32 offset)
318 {
319 struct dvobj_priv *d;
320 PADAPTER adapter;
321
322
323 d = (struct dvobj_priv *)p;
324 adapter = dvobj_get_primary_adapter(d);
325
326 return rtw_read16(adapter, offset);
327 }
328
_halmac_reg_read_32(void * p,u32 offset)329 static u32 _halmac_reg_read_32(void *p, u32 offset)
330 {
331 struct dvobj_priv *d;
332 PADAPTER adapter;
333
334
335 d = (struct dvobj_priv *)p;
336 adapter = dvobj_get_primary_adapter(d);
337
338 return rtw_read32(adapter, offset);
339 }
340
_halmac_reg_write_8(void * p,u32 offset,u8 val)341 static void _halmac_reg_write_8(void *p, u32 offset, u8 val)
342 {
343 struct dvobj_priv *d;
344 PADAPTER adapter;
345 int err;
346
347
348 d = (struct dvobj_priv *)p;
349 adapter = dvobj_get_primary_adapter(d);
350
351 err = rtw_write8(adapter, offset, val);
352 if (err == _FAIL)
353 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
354 }
355
_halmac_reg_write_16(void * p,u32 offset,u16 val)356 static void _halmac_reg_write_16(void *p, u32 offset, u16 val)
357 {
358 struct dvobj_priv *d;
359 PADAPTER adapter;
360 int err;
361
362
363 d = (struct dvobj_priv *)p;
364 adapter = dvobj_get_primary_adapter(d);
365
366 err = rtw_write16(adapter, offset, val);
367 if (err == _FAIL)
368 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
369 }
370
_halmac_reg_write_32(void * p,u32 offset,u32 val)371 static void _halmac_reg_write_32(void *p, u32 offset, u32 val)
372 {
373 struct dvobj_priv *d;
374 PADAPTER adapter;
375 int err;
376
377
378 d = (struct dvobj_priv *)p;
379 adapter = dvobj_get_primary_adapter(d);
380
381 err = rtw_write32(adapter, offset, val);
382 if (err == _FAIL)
383 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
384 }
385 #endif /* !CONFIG_SDIO_HCI */
386
_halmac_mfree(void * p,void * buffer,u32 size)387 static u8 _halmac_mfree(void *p, void *buffer, u32 size)
388 {
389 rtw_mfree(buffer, size);
390 return RTW_HALMAC_SUCCESS;
391 }
392
_halmac_malloc(void * p,u32 size)393 static void *_halmac_malloc(void *p, u32 size)
394 {
395 return rtw_zmalloc(size);
396 }
397
_halmac_memcpy(void * p,void * dest,void * src,u32 size)398 static u8 _halmac_memcpy(void *p, void *dest, void *src, u32 size)
399 {
400 _rtw_memcpy(dest, src, size);
401 return RTW_HALMAC_SUCCESS;
402 }
403
_halmac_memset(void * p,void * addr,u8 value,u32 size)404 static u8 _halmac_memset(void *p, void *addr, u8 value, u32 size)
405 {
406 _rtw_memset(addr, value, size);
407 return RTW_HALMAC_SUCCESS;
408 }
409
_halmac_udelay(void * p,u32 us)410 static void _halmac_udelay(void *p, u32 us)
411 {
412 /* Most hardware polling wait time < 50us) */
413 if (us <= 50)
414 rtw_udelay_os(us);
415 else if (us <= 1000)
416 rtw_usleep_os(us);
417 else
418 rtw_msleep_os(RTW_DIV_ROUND_UP(us, 1000));
419 }
420
_halmac_mutex_init(void * p,HALMAC_MUTEX * pMutex)421 static u8 _halmac_mutex_init(void *p, HALMAC_MUTEX *pMutex)
422 {
423 _rtw_mutex_init(pMutex);
424 return RTW_HALMAC_SUCCESS;
425 }
426
_halmac_mutex_deinit(void * p,HALMAC_MUTEX * pMutex)427 static u8 _halmac_mutex_deinit(void *p, HALMAC_MUTEX *pMutex)
428 {
429 _rtw_mutex_free(pMutex);
430 return RTW_HALMAC_SUCCESS;
431 }
432
_halmac_mutex_lock(void * p,HALMAC_MUTEX * pMutex)433 static u8 _halmac_mutex_lock(void *p, HALMAC_MUTEX *pMutex)
434 {
435 int err;
436
437 err = _enter_critical_mutex(pMutex, NULL);
438 if (err)
439 return RTW_HALMAC_FAIL;
440
441 return RTW_HALMAC_SUCCESS;
442 }
443
_halmac_mutex_unlock(void * p,HALMAC_MUTEX * pMutex)444 static u8 _halmac_mutex_unlock(void *p, HALMAC_MUTEX *pMutex)
445 {
446 _exit_critical_mutex(pMutex, NULL);
447 return RTW_HALMAC_SUCCESS;
448 }
449
450 #ifndef CONFIG_SDIO_HCI
451 #define DBG_MSG_FILTER
452 #endif
453
454 #ifdef DBG_MSG_FILTER
is_msg_allowed(uint drv_lv,u8 msg_lv)455 static u8 is_msg_allowed(uint drv_lv, u8 msg_lv)
456 {
457 switch (drv_lv) {
458 case _DRV_NONE_:
459 return _FALSE;
460
461 case _DRV_ALWAYS_:
462 if (msg_lv > HALMAC_DBG_ALWAYS)
463 return _FALSE;
464 break;
465 case _DRV_ERR_:
466 if (msg_lv > HALMAC_DBG_ERR)
467 return _FALSE;
468 break;
469 case _DRV_WARNING_:
470 if (msg_lv > HALMAC_DBG_WARN)
471 return _FALSE;
472 break;
473 case _DRV_INFO_:
474 if (msg_lv >= HALMAC_DBG_TRACE)
475 return _FALSE;
476 break;
477 }
478
479 return _TRUE;
480 }
481 #endif /* DBG_MSG_FILTER */
482
_halmac_msg_print(void * p,u32 msg_type,u8 msg_level,s8 * fmt,...)483 static u8 _halmac_msg_print(void *p, u32 msg_type, u8 msg_level, s8 *fmt, ...)
484 {
485 #define MSG_LEN 100
486 va_list args;
487 u8 str[MSG_LEN] = {0};
488 #ifdef DBG_MSG_FILTER
489 uint drv_level = _DRV_NONE_;
490 #endif
491 int err;
492 u8 ret = RTW_HALMAC_SUCCESS;
493
494
495 #ifdef DBG_MSG_FILTER
496 #ifdef CONFIG_RTW_DEBUG
497 drv_level = rtw_drv_log_level;
498 #endif
499 if (is_msg_allowed(drv_level, msg_level) == _FALSE)
500 return ret;
501 #endif
502
503 str[0] = '\n';
504 va_start(args, fmt);
505 err = vsnprintf(str, MSG_LEN, fmt, args);
506 va_end(args);
507
508 /* An output error is encountered */
509 if (err < 0)
510 return RTW_HALMAC_FAIL;
511 /* Output may be truncated due to size limit */
512 if ((err == (MSG_LEN - 1)) && (str[MSG_LEN - 2] != '\n'))
513 ret = RTW_HALMAC_FAIL;
514
515 if (msg_level == HALMAC_DBG_ALWAYS)
516 RTW_PRINT(MSG_PREFIX "%s", str);
517 else if (msg_level <= HALMAC_DBG_ERR)
518 RTW_ERR(MSG_PREFIX "%s", str);
519 else if (msg_level <= HALMAC_DBG_WARN)
520 RTW_WARN(MSG_PREFIX "%s", str);
521 else
522 RTW_DBG(MSG_PREFIX "%s", str);
523
524 return ret;
525 }
526
_halmac_buff_print(void * p,u32 msg_type,u8 msg_level,s8 * buf,u32 size)527 static u8 _halmac_buff_print(void *p, u32 msg_type, u8 msg_level, s8 *buf, u32 size)
528 {
529 if (msg_level <= HALMAC_DBG_WARN)
530 RTW_INFO_DUMP(MSG_PREFIX, buf, size);
531 else
532 RTW_DBG_DUMP(MSG_PREFIX, buf, size);
533
534 return RTW_HALMAC_SUCCESS;
535 }
536
537
538 const char *const RTW_HALMAC_FEATURE_NAME[] = {
539 "HALMAC_FEATURE_CFG_PARA",
540 "HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE",
541 "HALMAC_FEATURE_DUMP_LOGICAL_EFUSE",
542 "HALMAC_FEATURE_UPDATE_PACKET",
543 "HALMAC_FEATURE_UPDATE_DATAPACK",
544 "HALMAC_FEATURE_RUN_DATAPACK",
545 "HALMAC_FEATURE_CHANNEL_SWITCH",
546 "HALMAC_FEATURE_IQK",
547 "HALMAC_FEATURE_POWER_TRACKING",
548 "HALMAC_FEATURE_PSD",
549 "HALMAC_FEATURE_FW_SNDING",
550 "HALMAC_FEATURE_ALL"
551 };
552
is_valid_id_status(enum halmac_feature_id id,enum halmac_cmd_process_status status)553 static inline u8 is_valid_id_status(enum halmac_feature_id id, enum halmac_cmd_process_status status)
554 {
555 switch (id) {
556 case HALMAC_FEATURE_CFG_PARA:
557 RTW_DBG("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
558 break;
559 case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
560 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
561 if (HALMAC_CMD_PROCESS_DONE != status)
562 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
563 __FUNCTION__, id, status);
564 break;
565 case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
566 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
567 if (HALMAC_CMD_PROCESS_DONE != status)
568 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
569 __FUNCTION__, id, status);
570 break;
571 case HALMAC_FEATURE_UPDATE_PACKET:
572 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
573 if (status != HALMAC_CMD_PROCESS_DONE)
574 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
575 __FUNCTION__, id, status);
576 break;
577 case HALMAC_FEATURE_UPDATE_DATAPACK:
578 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
579 break;
580 case HALMAC_FEATURE_RUN_DATAPACK:
581 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
582 break;
583 case HALMAC_FEATURE_CHANNEL_SWITCH:
584 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
585 if ((status != HALMAC_CMD_PROCESS_DONE) && (status != HALMAC_CMD_PROCESS_RCVD))
586 RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
587 __FUNCTION__, id, status);
588 if (status == HALMAC_CMD_PROCESS_DONE)
589 return _FALSE;
590 break;
591 case HALMAC_FEATURE_IQK:
592 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
593 break;
594 case HALMAC_FEATURE_POWER_TRACKING:
595 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
596 break;
597 case HALMAC_FEATURE_PSD:
598 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
599 break;
600 case HALMAC_FEATURE_FW_SNDING:
601 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
602 break;
603 case HALMAC_FEATURE_ALL:
604 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
605 break;
606 default:
607 RTW_ERR("%s: unknown feature id(%d)\n", __FUNCTION__, id);
608 return _FALSE;
609 }
610
611 return _TRUE;
612 }
613
init_halmac_event_with_waittime(struct dvobj_priv * d,enum halmac_feature_id id,u8 * buf,u32 size,u32 time)614 static int init_halmac_event_with_waittime(struct dvobj_priv *d, enum halmac_feature_id id, u8 *buf, u32 size, u32 time)
615 {
616 struct submit_ctx *sctx;
617
618
619 if (!d->hmpriv.indicator[id].sctx) {
620 sctx = (struct submit_ctx *)rtw_zmalloc(sizeof(*sctx));
621 if (!sctx)
622 return -1;
623 } else {
624 RTW_WARN("%s: id(%d) sctx is not NULL!!\n", __FUNCTION__, id);
625 sctx = d->hmpriv.indicator[id].sctx;
626 d->hmpriv.indicator[id].sctx = NULL;
627 }
628
629 rtw_sctx_init(sctx, time);
630 d->hmpriv.indicator[id].buffer = buf;
631 d->hmpriv.indicator[id].buf_size = size;
632 d->hmpriv.indicator[id].ret_size = 0;
633 d->hmpriv.indicator[id].status = 0;
634 /* fill sctx at least to sure other variables are all ready! */
635 d->hmpriv.indicator[id].sctx = sctx;
636
637 return 0;
638 }
639
init_halmac_event(struct dvobj_priv * d,enum halmac_feature_id id,u8 * buf,u32 size)640 static inline int init_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id, u8 *buf, u32 size)
641 {
642 return init_halmac_event_with_waittime(d, id, buf, size, DEFAULT_INDICATOR_TIMELMT);
643 }
644
free_halmac_event(struct dvobj_priv * d,enum halmac_feature_id id)645 static void free_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id)
646 {
647 struct submit_ctx *sctx;
648
649
650 if (!d->hmpriv.indicator[id].sctx)
651 return;
652
653 sctx = d->hmpriv.indicator[id].sctx;
654 d->hmpriv.indicator[id].sctx = NULL;
655 rtw_mfree((u8 *)sctx, sizeof(*sctx));
656 }
657
wait_halmac_event(struct dvobj_priv * d,enum halmac_feature_id id)658 static int wait_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id)
659 {
660 struct halmac_adapter *mac;
661 struct halmac_api *api;
662 struct submit_ctx *sctx;
663 int ret;
664
665
666 sctx = d->hmpriv.indicator[id].sctx;
667 if (!sctx)
668 return -1;
669
670 ret = rtw_sctx_wait(sctx, RTW_HALMAC_FEATURE_NAME[id]);
671 free_halmac_event(d, id);
672 if (_SUCCESS == ret)
673 return 0;
674
675 /* timeout! We have to reset halmac state */
676 RTW_ERR("%s: Wait id(%d, %s) TIMEOUT! Reset HALMAC state!\n",
677 __FUNCTION__, id, RTW_HALMAC_FEATURE_NAME[id]);
678 mac = dvobj_to_halmac(d);
679 api = HALMAC_GET_API(mac);
680 api->halmac_reset_feature(mac, id);
681
682 return -1;
683 }
684
685 /*
686 * Return:
687 * Always return RTW_HALMAC_SUCCESS, HALMAC don't care the return value.
688 */
_halmac_event_indication(void * p,enum halmac_feature_id feature_id,enum halmac_cmd_process_status process_status,u8 * buf,u32 size)689 static u8 _halmac_event_indication(void *p, enum halmac_feature_id feature_id, enum halmac_cmd_process_status process_status, u8 *buf, u32 size)
690 {
691 struct dvobj_priv *d;
692 PADAPTER adapter;
693 PHAL_DATA_TYPE hal;
694 struct halmac_indicator *tbl, *indicator;
695 struct submit_ctx *sctx;
696 u32 cpsz;
697 u8 ret;
698
699
700 d = (struct dvobj_priv *)p;
701 adapter = dvobj_get_primary_adapter(d);
702 hal = GET_HAL_DATA(adapter);
703 tbl = d->hmpriv.indicator;
704
705 /* Filter(Skip) middle status indication */
706 ret = is_valid_id_status(feature_id, process_status);
707 if (_FALSE == ret)
708 goto exit;
709
710 indicator = &tbl[feature_id];
711 indicator->status = process_status;
712 indicator->ret_size = size;
713 if (!indicator->sctx) {
714 RTW_WARN("%s: No feature id(%d, %s) waiting!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
715 goto exit;
716 }
717 sctx = indicator->sctx;
718
719 if (HALMAC_CMD_PROCESS_ERROR == process_status) {
720 RTW_ERR("%s: Something wrong id(%d, %s)!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
721 rtw_sctx_done_err(&sctx, RTW_SCTX_DONE_UNKNOWN);
722 goto exit;
723 }
724
725 if (size > indicator->buf_size) {
726 RTW_WARN("%s: id(%d, %s) buffer is not enough(%d<%d), data will be truncated!\n",
727 __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id], indicator->buf_size, size);
728 cpsz = indicator->buf_size;
729 } else {
730 cpsz = size;
731 }
732 if (cpsz && indicator->buffer)
733 _rtw_memcpy(indicator->buffer, buf, cpsz);
734
735 rtw_sctx_done(&sctx);
736
737 exit:
738 return RTW_HALMAC_SUCCESS;
739 }
740
741 struct halmac_platform_api rtw_halmac_platform_api = {
742 /* R/W register */
743 #ifdef CONFIG_SDIO_HCI
744 .SDIO_CMD52_READ = _halmac_sdio_cmd52_read,
745 .SDIO_CMD53_READ_8 = _halmac_sdio_reg_read_8,
746 .SDIO_CMD53_READ_16 = _halmac_sdio_reg_read_16,
747 .SDIO_CMD53_READ_32 = _halmac_sdio_reg_read_32,
748 .SDIO_CMD53_READ_N = _halmac_sdio_reg_read_n,
749 .SDIO_CMD52_WRITE = _halmac_sdio_cmd52_write,
750 .SDIO_CMD53_WRITE_8 = _halmac_sdio_reg_write_8,
751 .SDIO_CMD53_WRITE_16 = _halmac_sdio_reg_write_16,
752 .SDIO_CMD53_WRITE_32 = _halmac_sdio_reg_write_32,
753 .SDIO_CMD52_CIA_READ = _halmac_sdio_read_cia,
754 #endif /* CONFIG_SDIO_HCI */
755 #if defined(CONFIG_USB_HCI) || defined(CONFIG_PCI_HCI)
756 .REG_READ_8 = _halmac_reg_read_8,
757 .REG_READ_16 = _halmac_reg_read_16,
758 .REG_READ_32 = _halmac_reg_read_32,
759 .REG_WRITE_8 = _halmac_reg_write_8,
760 .REG_WRITE_16 = _halmac_reg_write_16,
761 .REG_WRITE_32 = _halmac_reg_write_32,
762 #endif /* CONFIG_USB_HCI || CONFIG_PCI_HCI */
763
764 /* Write data */
765 #if 0
766 /* impletement in HAL-IC level */
767 .SEND_RSVD_PAGE = sdio_write_data_rsvd_page,
768 .SEND_H2C_PKT = sdio_write_data_h2c,
769 #endif
770 /* Memory allocate */
771 .RTL_FREE = _halmac_mfree,
772 .RTL_MALLOC = _halmac_malloc,
773 .RTL_MEMCPY = _halmac_memcpy,
774 .RTL_MEMSET = _halmac_memset,
775
776 /* Sleep */
777 .RTL_DELAY_US = _halmac_udelay,
778
779 /* Process Synchronization */
780 .MUTEX_INIT = _halmac_mutex_init,
781 .MUTEX_DEINIT = _halmac_mutex_deinit,
782 .MUTEX_LOCK = _halmac_mutex_lock,
783 .MUTEX_UNLOCK = _halmac_mutex_unlock,
784
785 .MSG_PRINT = _halmac_msg_print,
786 .BUFF_PRINT = _halmac_buff_print,
787 .EVENT_INDICATION = _halmac_event_indication,
788 };
789
rtw_halmac_read8(struct intf_hdl * pintfhdl,u32 addr)790 u8 rtw_halmac_read8(struct intf_hdl *pintfhdl, u32 addr)
791 {
792 struct halmac_adapter *mac;
793 struct halmac_api *api;
794
795
796 /* WARNING: pintf_dev should not be null! */
797 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
798 api = HALMAC_GET_API(mac);
799
800 return api->halmac_reg_read_8(mac, addr);
801 }
802
rtw_halmac_read16(struct intf_hdl * pintfhdl,u32 addr)803 u16 rtw_halmac_read16(struct intf_hdl *pintfhdl, u32 addr)
804 {
805 struct halmac_adapter *mac;
806 struct halmac_api *api;
807
808
809 /* WARNING: pintf_dev should not be null! */
810 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
811 api = HALMAC_GET_API(mac);
812
813 return api->halmac_reg_read_16(mac, addr);
814 }
815
rtw_halmac_read32(struct intf_hdl * pintfhdl,u32 addr)816 u32 rtw_halmac_read32(struct intf_hdl *pintfhdl, u32 addr)
817 {
818 struct halmac_adapter *mac;
819 struct halmac_api *api;
820
821
822 /* WARNING: pintf_dev should not be null! */
823 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
824 api = HALMAC_GET_API(mac);
825
826 return api->halmac_reg_read_32(mac, addr);
827 }
828
_read_register(struct dvobj_priv * d,u32 addr,u32 cnt,u8 * buf)829 static void _read_register(struct dvobj_priv *d, u32 addr, u32 cnt, u8 *buf)
830 {
831 #if 1
832 struct _ADAPTER *a;
833 u32 i, n;
834 u16 val16;
835 u32 val32;
836
837
838 a = dvobj_get_primary_adapter(d);
839
840 i = addr & 0x3;
841 /* Handle address not start from 4 bytes alignment case */
842 if (i) {
843 val32 = cpu_to_le32(rtw_read32(a, addr & ~0x3));
844 n = 4 - i;
845 _rtw_memcpy(buf, ((u8 *)&val32) + i, n);
846 i = n;
847 cnt -= n;
848 }
849
850 while (cnt) {
851 if (cnt >= 4)
852 n = 4;
853 else if (cnt >= 2)
854 n = 2;
855 else
856 n = 1;
857 cnt -= n;
858
859 switch (n) {
860 case 1:
861 buf[i] = rtw_read8(a, addr+i);
862 i++;
863 break;
864 case 2:
865 val16 = cpu_to_le16(rtw_read16(a, addr+i));
866 _rtw_memcpy(&buf[i], &val16, 2);
867 i += 2;
868 break;
869 case 4:
870 val32 = cpu_to_le32(rtw_read32(a, addr+i));
871 _rtw_memcpy(&buf[i], &val32, 4);
872 i += 4;
873 break;
874 }
875 }
876 #else
877 struct _ADAPTER *a;
878 u32 i;
879
880
881 a = dvobj_get_primary_adapter(d);
882 for (i = 0; i < cnt; i++)
883 buf[i] = rtw_read8(a, addr + i);
884 #endif
885 }
886
887 #ifdef CONFIG_SDIO_HCI
_sdio_read_local(struct dvobj_priv * d,u32 addr,u32 cnt,u8 * buf)888 static int _sdio_read_local(struct dvobj_priv *d, u32 addr, u32 cnt, u8 *buf)
889 {
890 struct halmac_adapter *mac;
891 struct halmac_api *api;
892 enum halmac_ret_status status;
893
894
895 if (buf == NULL)
896 return -1;
897
898 mac = dvobj_to_halmac(d);
899 api = HALMAC_GET_API(mac);
900
901 status = api->halmac_reg_sdio_cmd53_read_n(mac, addr, cnt, buf);
902 if (status != HALMAC_RET_SUCCESS) {
903 RTW_ERR("%s: addr=0x%08x cnt=%d err=%d\n",
904 __FUNCTION__, addr, cnt, status);
905 return -1;
906 }
907
908 return 0;
909 }
910 #endif /* CONFIG_SDIO_HCI */
911
rtw_halmac_read_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pmem)912 void rtw_halmac_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem)
913 {
914 struct dvobj_priv *d;
915
916
917 if (pmem == NULL) {
918 RTW_ERR("pmem is NULL\n");
919 return;
920 }
921
922 d = pintfhdl->pintf_dev;
923
924 #ifdef CONFIG_SDIO_HCI
925 if (addr & 0xFFFF0000) {
926 int err = 0;
927
928 err = _sdio_read_local(d, addr, cnt, pmem);
929 if (!err)
930 return;
931 }
932 #endif /* CONFIG_SDIO_HCI */
933
934 _read_register(d, addr, cnt, pmem);
935 }
936
937 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
rtw_halmac_iread8(struct intf_hdl * pintfhdl,u32 addr)938 u8 rtw_halmac_iread8(struct intf_hdl *pintfhdl, u32 addr)
939 {
940 struct halmac_adapter *mac;
941 struct halmac_api *api;
942
943 /* WARNING: pintf_dev should not be null! */
944 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
945 api = HALMAC_GET_API(mac);
946
947 /*return api->halmac_reg_read_indirect_8(mac, addr);*/
948 return api->halmac_reg_read_8(mac, addr);
949 }
950
rtw_halmac_iread16(struct intf_hdl * pintfhdl,u32 addr)951 u16 rtw_halmac_iread16(struct intf_hdl *pintfhdl, u32 addr)
952 {
953 struct halmac_adapter *mac;
954 struct halmac_api *api;
955 u16 val16 = 0;
956
957 /* WARNING: pintf_dev should not be null! */
958 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
959 api = HALMAC_GET_API(mac);
960
961 /*return api->halmac_reg_read_indirect_16(mac, addr);*/
962 return api->halmac_reg_read_16(mac, addr);
963 }
964
rtw_halmac_iread32(struct intf_hdl * pintfhdl,u32 addr)965 u32 rtw_halmac_iread32(struct intf_hdl *pintfhdl, u32 addr)
966 {
967 struct halmac_adapter *mac;
968 struct halmac_api *api;
969
970
971 /* WARNING: pintf_dev should not be null! */
972 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
973 api = HALMAC_GET_API(mac);
974
975 return api->halmac_reg_read_indirect_32(mac, addr);
976 }
977 #endif /* CONFIG_SDIO_INDIRECT_ACCESS */
978
rtw_halmac_write8(struct intf_hdl * pintfhdl,u32 addr,u8 value)979 int rtw_halmac_write8(struct intf_hdl *pintfhdl, u32 addr, u8 value)
980 {
981 struct halmac_adapter *mac;
982 struct halmac_api *api;
983 enum halmac_ret_status status;
984
985
986 /* WARNING: pintf_dev should not be null! */
987 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
988 api = HALMAC_GET_API(mac);
989
990 status = api->halmac_reg_write_8(mac, addr, value);
991
992 if (status == HALMAC_RET_SUCCESS)
993 return 0;
994
995 return -1;
996 }
997
rtw_halmac_write16(struct intf_hdl * pintfhdl,u32 addr,u16 value)998 int rtw_halmac_write16(struct intf_hdl *pintfhdl, u32 addr, u16 value)
999 {
1000 struct halmac_adapter *mac;
1001 struct halmac_api *api;
1002 enum halmac_ret_status status;
1003
1004
1005 /* WARNING: pintf_dev should not be null! */
1006 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
1007 api = HALMAC_GET_API(mac);
1008
1009 status = api->halmac_reg_write_16(mac, addr, value);
1010
1011 if (status == HALMAC_RET_SUCCESS)
1012 return 0;
1013
1014 return -1;
1015 }
1016
rtw_halmac_write32(struct intf_hdl * pintfhdl,u32 addr,u32 value)1017 int rtw_halmac_write32(struct intf_hdl *pintfhdl, u32 addr, u32 value)
1018 {
1019 struct halmac_adapter *mac;
1020 struct halmac_api *api;
1021 enum halmac_ret_status status;
1022
1023
1024 /* WARNING: pintf_dev should not be null! */
1025 mac = dvobj_to_halmac(pintfhdl->pintf_dev);
1026 api = HALMAC_GET_API(mac);
1027
1028 status = api->halmac_reg_write_32(mac, addr, value);
1029
1030 if (status == HALMAC_RET_SUCCESS)
1031 return 0;
1032
1033 return -1;
1034 }
1035
init_write_rsvd_page_size(struct dvobj_priv * d)1036 static int init_write_rsvd_page_size(struct dvobj_priv *d)
1037 {
1038 struct halmac_adapter *mac;
1039 struct halmac_api *api;
1040 u32 size = 0;
1041 struct halmac_ofld_func_info ofld_info;
1042 enum halmac_ret_status status;
1043 int err = 0;
1044
1045
1046 #ifdef CONFIG_USB_HCI
1047 /* for USB do not exceed MAX_CMDBUF_SZ */
1048 size = 0x1000;
1049 #elif defined(CONFIG_PCI_HCI)
1050 size = MAX_CMDBUF_SZ - TXDESC_OFFSET;
1051 #elif defined(CONFIG_SDIO_HCI)
1052 size = 0x7000; /* 28KB */
1053 #endif
1054
1055 /* If size==0, use HALMAC default setting and don't call any function */
1056 if (!size)
1057 return 0;
1058
1059 err = rtw_halmac_set_max_dl_fw_size(d, size);
1060 if (err) {
1061 RTW_ERR("%s: Fail to set max download fw size!\n", __FUNCTION__);
1062 return -1;
1063 }
1064
1065 mac = dvobj_to_halmac(d);
1066 api = HALMAC_GET_API(mac);
1067
1068 _rtw_memset(&ofld_info, 0, sizeof(ofld_info));
1069 ofld_info.halmac_malloc_max_sz = 0xFFFFFFFF;
1070 ofld_info.rsvd_pg_drv_buf_max_sz = size;
1071 status = api->halmac_ofld_func_cfg(mac, &ofld_info);
1072 if (status != HALMAC_RET_SUCCESS) {
1073 RTW_ERR("%s: Fail to config offload parameters!\n", __FUNCTION__);
1074 return -1;
1075 }
1076
1077 return 0;
1078 }
1079
init_priv(struct halmacpriv * priv)1080 static int init_priv(struct halmacpriv *priv)
1081 {
1082 struct halmac_indicator *indicator;
1083 u32 count, size;
1084
1085
1086 if (priv->indicator)
1087 RTW_WARN("%s: HALMAC private data is not CLEAR!\n", __FUNCTION__);
1088 count = HALMAC_FEATURE_ALL + 1;
1089 size = sizeof(*indicator) * count;
1090 indicator = (struct halmac_indicator *)rtw_zmalloc(size);
1091 if (!indicator)
1092 return -1;
1093 priv->indicator = indicator;
1094
1095 return 0;
1096 }
1097
deinit_priv(struct halmacpriv * priv)1098 static void deinit_priv(struct halmacpriv *priv)
1099 {
1100 struct halmac_indicator *indicator;
1101
1102
1103 indicator = priv->indicator;
1104 priv->indicator = NULL;
1105 if (indicator) {
1106 u32 count, size;
1107
1108 count = HALMAC_FEATURE_ALL + 1;
1109 #ifdef CONFIG_RTW_DEBUG
1110 {
1111 struct submit_ctx *sctx;
1112 u32 i;
1113
1114 for (i = 0; i < count; i++) {
1115 if (!indicator[i].sctx)
1116 continue;
1117
1118 RTW_WARN("%s: %s id(%d) sctx still exist!!\n",
1119 __FUNCTION__, RTW_HALMAC_FEATURE_NAME[i], i);
1120 sctx = indicator[i].sctx;
1121 indicator[i].sctx = NULL;
1122 rtw_mfree((u8 *)sctx, sizeof(*sctx));
1123 }
1124 }
1125 #endif /* !CONFIG_RTW_DEBUG */
1126 size = sizeof(*indicator) * count;
1127 rtw_mfree((u8 *)indicator, size);
1128 }
1129 }
1130
1131 #ifdef CONFIG_SDIO_HCI
_sdio_ver_drv2halmac(struct dvobj_priv * d)1132 static enum halmac_sdio_spec_ver _sdio_ver_drv2halmac(struct dvobj_priv *d)
1133 {
1134 bool v3;
1135 enum halmac_sdio_spec_ver ver;
1136
1137
1138 v3 = rtw_is_sdio30(dvobj_get_primary_adapter(d));
1139 if (v3)
1140 ver = HALMAC_SDIO_SPEC_VER_3_00;
1141 else
1142 ver = HALMAC_SDIO_SPEC_VER_2_00;
1143
1144 return ver;
1145 }
1146 #endif /* CONFIG_SDIO_HCI */
1147
rtw_halmac_get_version(char * str,u32 len)1148 void rtw_halmac_get_version(char *str, u32 len)
1149 {
1150 enum halmac_ret_status status;
1151 struct halmac_ver ver;
1152
1153
1154 status = halmac_get_version(&ver);
1155 if (status != HALMAC_RET_SUCCESS)
1156 return;
1157
1158 rtw_sprintf(str, len, "V%d_%02d_%02d",
1159 ver.major_ver, ver.prototype_ver, ver.minor_ver);
1160 }
1161
rtw_halmac_init_adapter(struct dvobj_priv * d,struct halmac_platform_api * pf_api)1162 int rtw_halmac_init_adapter(struct dvobj_priv *d, struct halmac_platform_api *pf_api)
1163 {
1164 struct halmac_adapter *halmac;
1165 struct halmac_api *api;
1166 enum halmac_interface intf;
1167 enum halmac_intf_phy_platform pltfm = HALMAC_INTF_PHY_PLATFORM_ALL;
1168 enum halmac_ret_status status;
1169 int err = 0;
1170 #ifdef CONFIG_SDIO_HCI
1171 struct halmac_sdio_hw_info info;
1172 #endif /* CONFIG_SDIO_HCI */
1173
1174
1175 halmac = dvobj_to_halmac(d);
1176 if (halmac) {
1177 RTW_WARN("%s: initialize already completed!\n", __FUNCTION__);
1178 goto error;
1179 }
1180
1181 err = init_priv(&d->hmpriv);
1182 if (err)
1183 goto error;
1184
1185 #ifdef CONFIG_SDIO_HCI
1186 intf = HALMAC_INTERFACE_SDIO;
1187 #elif defined(CONFIG_USB_HCI)
1188 intf = HALMAC_INTERFACE_USB;
1189 #elif defined(CONFIG_PCI_HCI)
1190 intf = HALMAC_INTERFACE_PCIE;
1191 #else
1192 #warning "INTERFACE(CONFIG_XXX_HCI) not be defined!!"
1193 intf = HALMAC_INTERFACE_UNDEFINE;
1194 #endif
1195 status = halmac_init_adapter(d, pf_api, intf, &halmac, &api);
1196 if (HALMAC_RET_SUCCESS != status) {
1197 RTW_ERR("%s: halmac_init_adapter fail!(status=%d)\n", __FUNCTION__, status);
1198 err = -1;
1199 if (halmac)
1200 goto deinit;
1201 goto free;
1202 }
1203
1204 dvobj_set_halmac(d, halmac);
1205
1206 status = api->halmac_interface_integration_tuning(halmac);
1207 if (status != HALMAC_RET_SUCCESS) {
1208 RTW_ERR("%s: halmac_interface_integration_tuning fail!(status=%d)\n", __FUNCTION__, status);
1209 err = -1;
1210 goto deinit;
1211 }
1212
1213 #ifdef CONFIG_PLATFORM_RTK1319
1214 pltfm = HALMAC_INTF_PHY_PLATFORM_DHC;
1215 #endif /* CONFIG_PLATFORM_RTK1319 */
1216 status = api->halmac_phy_cfg(halmac, pltfm);
1217 if (status != HALMAC_RET_SUCCESS) {
1218 RTW_ERR("%s: halmac_phy_cfg fail! (platform=%d, status=%d)\n",
1219 __FUNCTION__, pltfm, status);
1220 err = -1;
1221 goto deinit;
1222 }
1223
1224 init_write_rsvd_page_size(d);
1225
1226 #ifdef CONFIG_SDIO_HCI
1227 _rtw_memset(&info, 0, sizeof(info));
1228 info.spec_ver = _sdio_ver_drv2halmac(d);
1229 /* Convert clock speed unit to MHz from Hz */
1230 info.clock_speed = RTW_DIV_ROUND_UP(rtw_sdio_get_clock(d), 1000000);
1231 info.block_size = rtw_sdio_get_block_size(d);
1232 RTW_DBG("%s: SDIO ver=%u clock=%uMHz blk_size=%u bytes\n",
1233 __FUNCTION__, info.spec_ver+2, info.clock_speed,
1234 info.block_size);
1235 status = api->halmac_sdio_hw_info(halmac, &info);
1236 if (status != HALMAC_RET_SUCCESS) {
1237 RTW_ERR("%s: halmac_sdio_hw_info fail!(status=%d)\n",
1238 __FUNCTION__, status);
1239 err = -1;
1240 goto deinit;
1241 }
1242 #endif /* CONFIG_SDIO_HCI */
1243
1244 return 0;
1245
1246 deinit:
1247 status = halmac_deinit_adapter(halmac);
1248 dvobj_set_halmac(d, NULL);
1249 if (status != HALMAC_RET_SUCCESS)
1250 RTW_ERR("%s: halmac_deinit_adapter fail!(status=%d)\n",
1251 __FUNCTION__, status);
1252
1253 free:
1254 deinit_priv(&d->hmpriv);
1255
1256 error:
1257 return err;
1258 }
1259
rtw_halmac_deinit_adapter(struct dvobj_priv * d)1260 int rtw_halmac_deinit_adapter(struct dvobj_priv *d)
1261 {
1262 struct halmac_adapter *halmac;
1263 enum halmac_ret_status status;
1264 int err = 0;
1265
1266
1267 halmac = dvobj_to_halmac(d);
1268 if (halmac) {
1269 status = halmac_deinit_adapter(halmac);
1270 dvobj_set_halmac(d, NULL);
1271 if (status != HALMAC_RET_SUCCESS)
1272 err = -1;
1273 }
1274
1275 deinit_priv(&d->hmpriv);
1276
1277 return err;
1278 }
1279
_hw_port_drv2halmac(enum _hw_port hwport)1280 static inline enum halmac_portid _hw_port_drv2halmac(enum _hw_port hwport)
1281 {
1282 enum halmac_portid port = HALMAC_PORTID_NUM;
1283
1284
1285 switch (hwport) {
1286 case HW_PORT0:
1287 port = HALMAC_PORTID0;
1288 break;
1289 case HW_PORT1:
1290 port = HALMAC_PORTID1;
1291 break;
1292 case HW_PORT2:
1293 port = HALMAC_PORTID2;
1294 break;
1295 case HW_PORT3:
1296 port = HALMAC_PORTID3;
1297 break;
1298 case HW_PORT4:
1299 port = HALMAC_PORTID4;
1300 break;
1301 default:
1302 break;
1303 }
1304
1305 return port;
1306 }
1307
_network_type_drv2halmac(u8 type)1308 static enum halmac_network_type_select _network_type_drv2halmac(u8 type)
1309 {
1310 enum halmac_network_type_select network = HALMAC_NETWORK_UNDEFINE;
1311
1312
1313 switch (type) {
1314 case _HW_STATE_NOLINK_:
1315 case _HW_STATE_MONITOR_:
1316 network = HALMAC_NETWORK_NO_LINK;
1317 break;
1318
1319 case _HW_STATE_ADHOC_:
1320 network = HALMAC_NETWORK_ADHOC;
1321 break;
1322
1323 case _HW_STATE_STATION_:
1324 network = HALMAC_NETWORK_INFRASTRUCTURE;
1325 break;
1326
1327 case _HW_STATE_AP_:
1328 network = HALMAC_NETWORK_AP;
1329 break;
1330 }
1331
1332 return network;
1333 }
1334
_network_type_halmac2drv(enum halmac_network_type_select network)1335 static u8 _network_type_halmac2drv(enum halmac_network_type_select network)
1336 {
1337 u8 type = _HW_STATE_NOLINK_;
1338
1339
1340 switch (network) {
1341 case HALMAC_NETWORK_NO_LINK:
1342 case HALMAC_NETWORK_UNDEFINE:
1343 type = _HW_STATE_NOLINK_;
1344 break;
1345
1346 case HALMAC_NETWORK_ADHOC:
1347 type = _HW_STATE_ADHOC_;
1348 break;
1349
1350 case HALMAC_NETWORK_INFRASTRUCTURE:
1351 type = _HW_STATE_STATION_;
1352 break;
1353
1354 case HALMAC_NETWORK_AP:
1355 type = _HW_STATE_AP_;
1356 break;
1357 }
1358
1359 return type;
1360 }
1361
_beacon_ctrl_halmac2drv(struct halmac_bcn_ctrl * ctrl,struct rtw_halmac_bcn_ctrl * drv_ctrl)1362 static void _beacon_ctrl_halmac2drv(struct halmac_bcn_ctrl *ctrl,
1363 struct rtw_halmac_bcn_ctrl *drv_ctrl)
1364 {
1365 drv_ctrl->rx_bssid_fit = ctrl->dis_rx_bssid_fit ? 0 : 1;
1366 drv_ctrl->txbcn_rpt = ctrl->en_txbcn_rpt ? 1 : 0;
1367 drv_ctrl->tsf_update = ctrl->dis_tsf_udt ? 0 : 1;
1368 drv_ctrl->enable_bcn = ctrl->en_bcn ? 1 : 0;
1369 drv_ctrl->rxbcn_rpt = ctrl->en_rxbcn_rpt ? 1 : 0;
1370 drv_ctrl->p2p_ctwin = ctrl->en_p2p_ctwin ? 1 : 0;
1371 drv_ctrl->p2p_bcn_area = ctrl->en_p2p_bcn_area ? 1 : 0;
1372 }
1373
_beacon_ctrl_drv2halmac(struct rtw_halmac_bcn_ctrl * drv_ctrl,struct halmac_bcn_ctrl * ctrl)1374 static void _beacon_ctrl_drv2halmac(struct rtw_halmac_bcn_ctrl *drv_ctrl,
1375 struct halmac_bcn_ctrl *ctrl)
1376 {
1377 ctrl->dis_rx_bssid_fit = drv_ctrl->rx_bssid_fit ? 0 : 1;
1378 ctrl->en_txbcn_rpt = drv_ctrl->txbcn_rpt ? 1 : 0;
1379 ctrl->dis_tsf_udt = drv_ctrl->tsf_update ? 0 : 1;
1380 ctrl->en_bcn = drv_ctrl->enable_bcn ? 1 : 0;
1381 ctrl->en_rxbcn_rpt = drv_ctrl->rxbcn_rpt ? 1 : 0;
1382 ctrl->en_p2p_ctwin = drv_ctrl->p2p_ctwin ? 1 : 0;
1383 ctrl->en_p2p_bcn_area = drv_ctrl->p2p_bcn_area ? 1 : 0;
1384 }
1385
rtw_halmac_get_hw_value(struct dvobj_priv * d,enum halmac_hw_id hw_id,void * pvalue)1386 int rtw_halmac_get_hw_value(struct dvobj_priv *d, enum halmac_hw_id hw_id, void *pvalue)
1387 {
1388 struct halmac_adapter *mac;
1389 struct halmac_api *api;
1390 enum halmac_ret_status status;
1391
1392
1393 mac = dvobj_to_halmac(d);
1394 api = HALMAC_GET_API(mac);
1395
1396 status = api->halmac_get_hw_value(mac, hw_id, pvalue);
1397 if (HALMAC_RET_SUCCESS != status)
1398 return -1;
1399
1400 return 0;
1401 }
1402
1403 /**
1404 * rtw_halmac_get_tx_fifo_size() - TX FIFO size
1405 * @d: struct dvobj_priv*
1406 * @size: TX FIFO size, unit is byte.
1407 *
1408 * Get TX FIFO size(byte) from HALMAC.
1409 *
1410 * Rteurn 0 for OK, otherwise fail.
1411 */
rtw_halmac_get_tx_fifo_size(struct dvobj_priv * d,u32 * size)1412 int rtw_halmac_get_tx_fifo_size(struct dvobj_priv *d, u32 *size)
1413 {
1414 struct halmac_adapter *halmac;
1415 struct halmac_api *api;
1416 enum halmac_ret_status status;
1417 u32 val = 0;
1418
1419
1420 halmac = dvobj_to_halmac(d);
1421 api = HALMAC_GET_API(halmac);
1422
1423 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TXFIFO_SIZE, &val);
1424 if (status != HALMAC_RET_SUCCESS)
1425 return -1;
1426
1427 *size = val;
1428
1429 return 0;
1430 }
1431
1432 /**
1433 * rtw_halmac_get_rx_fifo_size() - RX FIFO size
1434 * @d: struct dvobj_priv*
1435 * @size: RX FIFO size, unit is byte
1436 *
1437 * Get RX FIFO size(byte) from HALMAC.
1438 *
1439 * Rteurn 0 for OK, otherwise fail.
1440 */
rtw_halmac_get_rx_fifo_size(struct dvobj_priv * d,u32 * size)1441 int rtw_halmac_get_rx_fifo_size(struct dvobj_priv *d, u32 *size)
1442 {
1443 struct halmac_adapter *halmac;
1444 struct halmac_api *api;
1445 enum halmac_ret_status status;
1446 u32 val = 0;
1447
1448
1449 halmac = dvobj_to_halmac(d);
1450 api = HALMAC_GET_API(halmac);
1451
1452 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RXFIFO_SIZE, &val);
1453 if (status != HALMAC_RET_SUCCESS)
1454 return -1;
1455
1456 *size = val;
1457
1458 return 0;
1459 }
1460
1461 /**
1462 * rtw_halmac_get_rsvd_drv_pg_bndy() - Reserve page boundary of driver
1463 * @d: struct dvobj_priv*
1464 * @size: Page size, unit is byte
1465 *
1466 * Get reserve page boundary of driver from HALMAC.
1467 *
1468 * Rteurn 0 for OK, otherwise fail.
1469 */
rtw_halmac_get_rsvd_drv_pg_bndy(struct dvobj_priv * d,u16 * bndy)1470 int rtw_halmac_get_rsvd_drv_pg_bndy(struct dvobj_priv *d, u16 *bndy)
1471 {
1472 struct halmac_adapter *halmac;
1473 struct halmac_api *api;
1474 enum halmac_ret_status status;
1475 u16 val = 0;
1476
1477
1478 halmac = dvobj_to_halmac(d);
1479 api = HALMAC_GET_API(halmac);
1480
1481 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RSVD_PG_BNDY, &val);
1482 if (status != HALMAC_RET_SUCCESS)
1483 return -1;
1484
1485 *bndy = val;
1486
1487 return 0;
1488 }
1489
1490 /**
1491 * rtw_halmac_get_page_size() - Page size
1492 * @d: struct dvobj_priv*
1493 * @size: Page size, unit is byte
1494 *
1495 * Get TX/RX page size(byte) from HALMAC.
1496 *
1497 * Rteurn 0 for OK, otherwise fail.
1498 */
rtw_halmac_get_page_size(struct dvobj_priv * d,u32 * size)1499 int rtw_halmac_get_page_size(struct dvobj_priv *d, u32 *size)
1500 {
1501 struct halmac_adapter *halmac;
1502 struct halmac_api *api;
1503 enum halmac_ret_status status;
1504 u32 val = 0;
1505
1506
1507 halmac = dvobj_to_halmac(d);
1508 api = HALMAC_GET_API(halmac);
1509
1510 status = api->halmac_get_hw_value(halmac, HALMAC_HW_PAGE_SIZE, &val);
1511 if (status != HALMAC_RET_SUCCESS)
1512 return -1;
1513
1514 *size = val;
1515
1516 return 0;
1517 }
1518
1519 /**
1520 * rtw_halmac_get_tx_agg_align_size() - TX aggregation align size
1521 * @d: struct dvobj_priv*
1522 * @size: TX aggregation align size, unit is byte
1523 *
1524 * Get TX aggregation align size(byte) from HALMAC.
1525 *
1526 * Rteurn 0 for OK, otherwise fail.
1527 */
rtw_halmac_get_tx_agg_align_size(struct dvobj_priv * d,u16 * size)1528 int rtw_halmac_get_tx_agg_align_size(struct dvobj_priv *d, u16 *size)
1529 {
1530 struct halmac_adapter *halmac;
1531 struct halmac_api *api;
1532 enum halmac_ret_status status;
1533 u16 val = 0;
1534
1535
1536 halmac = dvobj_to_halmac(d);
1537 api = HALMAC_GET_API(halmac);
1538
1539 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TX_AGG_ALIGN_SIZE, &val);
1540 if (status != HALMAC_RET_SUCCESS)
1541 return -1;
1542
1543 *size = val;
1544
1545 return 0;
1546 }
1547
1548 /**
1549 * rtw_halmac_get_rx_agg_align_size() - RX aggregation align size
1550 * @d: struct dvobj_priv*
1551 * @size: RX aggregation align size, unit is byte
1552 *
1553 * Get RX aggregation align size(byte) from HALMAC.
1554 *
1555 * Rteurn 0 for OK, otherwise fail.
1556 */
rtw_halmac_get_rx_agg_align_size(struct dvobj_priv * d,u8 * size)1557 int rtw_halmac_get_rx_agg_align_size(struct dvobj_priv *d, u8 *size)
1558 {
1559 struct halmac_adapter *halmac;
1560 struct halmac_api *api;
1561 enum halmac_ret_status status;
1562 u8 val = 0;
1563
1564
1565 halmac = dvobj_to_halmac(d);
1566 api = HALMAC_GET_API(halmac);
1567
1568 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RX_AGG_ALIGN_SIZE, &val);
1569 if (status != HALMAC_RET_SUCCESS)
1570 return -1;
1571
1572 *size = val;
1573
1574 return 0;
1575 }
1576
1577 /*
1578 * Description:
1579 * Get RX driver info size. RX driver info is a small memory space between
1580 * scriptor and RX payload.
1581 *
1582 * +-------------------------+
1583 * | RX descriptor |
1584 * | usually 24 bytes |
1585 * +-------------------------+
1586 * | RX driver info |
1587 * | depends on driver cfg |
1588 * +-------------------------+
1589 * | RX paylad |
1590 * | |
1591 * +-------------------------+
1592 *
1593 * Parameter:
1594 * d pointer to struct dvobj_priv of driver
1595 * sz rx driver info size in bytes.
1596 *
1597 * Rteurn:
1598 * 0 Success
1599 * other Fail
1600 */
rtw_halmac_get_rx_drv_info_sz(struct dvobj_priv * d,u8 * sz)1601 int rtw_halmac_get_rx_drv_info_sz(struct dvobj_priv *d, u8 *sz)
1602 {
1603 enum halmac_ret_status status;
1604 struct halmac_adapter *halmac = dvobj_to_halmac(d);
1605 struct halmac_api *api = HALMAC_GET_API(halmac);
1606 u8 dw = 0;
1607
1608 status = api->halmac_get_hw_value(halmac, HALMAC_HW_DRV_INFO_SIZE, &dw);
1609 if (status != HALMAC_RET_SUCCESS)
1610 return -1;
1611
1612 *sz = dw * 8;
1613 return 0;
1614 }
1615
1616 /**
1617 * rtw_halmac_get_tx_desc_size() - TX descriptor size
1618 * @d: struct dvobj_priv*
1619 * @size: TX descriptor size, unit is byte.
1620 *
1621 * Get TX descriptor size(byte) from HALMAC.
1622 *
1623 * Rteurn 0 for OK, otherwise fail.
1624 */
rtw_halmac_get_tx_desc_size(struct dvobj_priv * d,u32 * size)1625 int rtw_halmac_get_tx_desc_size(struct dvobj_priv *d, u32 *size)
1626 {
1627 struct halmac_adapter *halmac;
1628 struct halmac_api *api;
1629 enum halmac_ret_status status;
1630 u32 val = 0;
1631
1632
1633 halmac = dvobj_to_halmac(d);
1634 api = HALMAC_GET_API(halmac);
1635
1636 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TX_DESC_SIZE, &val);
1637 if (status != HALMAC_RET_SUCCESS)
1638 return -1;
1639
1640 *size = val;
1641
1642 return 0;
1643 }
1644
1645 /**
1646 * rtw_halmac_get_rx_desc_size() - RX descriptor size
1647 * @d: struct dvobj_priv*
1648 * @size: RX descriptor size, unit is byte.
1649 *
1650 * Get RX descriptor size(byte) from HALMAC.
1651 *
1652 * Rteurn 0 for OK, otherwise fail.
1653 */
rtw_halmac_get_rx_desc_size(struct dvobj_priv * d,u32 * size)1654 int rtw_halmac_get_rx_desc_size(struct dvobj_priv *d, u32 *size)
1655 {
1656 struct halmac_adapter *halmac;
1657 struct halmac_api *api;
1658 enum halmac_ret_status status;
1659 u32 val = 0;
1660
1661
1662 halmac = dvobj_to_halmac(d);
1663 api = HALMAC_GET_API(halmac);
1664
1665 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RX_DESC_SIZE, &val);
1666 if (status != HALMAC_RET_SUCCESS)
1667 return -1;
1668
1669 *size = val;
1670
1671 return 0;
1672 }
1673
1674
1675 /**
1676 * rtw_halmac_get_fw_max_size() - Firmware MAX size
1677 * @d: struct dvobj_priv*
1678 * @size: MAX Firmware size, unit is byte.
1679 *
1680 * Get Firmware MAX size(byte) from HALMAC.
1681 *
1682 * Rteurn 0 for OK, otherwise fail.
1683 */
rtw_halmac_get_fw_max_size(struct dvobj_priv * d,u32 * size)1684 static int rtw_halmac_get_fw_max_size(struct dvobj_priv *d, u32 *size)
1685 {
1686 struct halmac_adapter *halmac;
1687 struct halmac_api *api;
1688 enum halmac_ret_status status;
1689 u32 val = 0;
1690
1691
1692 halmac = dvobj_to_halmac(d);
1693 api = HALMAC_GET_API(halmac);
1694
1695 status = api->halmac_get_hw_value(halmac, HALMAC_HW_FW_MAX_SIZE, &val);
1696 if (status != HALMAC_RET_SUCCESS)
1697 return -1;
1698
1699 *size = val;
1700
1701 return 0;
1702 }
1703
1704 /**
1705 * rtw_halmac_get_ori_h2c_size() - Original H2C MAX size
1706 * @d: struct dvobj_priv*
1707 * @size: H2C MAX size, unit is byte.
1708 *
1709 * Get original H2C MAX size(byte) from HALMAC.
1710 *
1711 * Rteurn 0 for OK, otherwise fail.
1712 */
rtw_halmac_get_ori_h2c_size(struct dvobj_priv * d,u32 * size)1713 int rtw_halmac_get_ori_h2c_size(struct dvobj_priv *d, u32 *size)
1714 {
1715 struct halmac_adapter *halmac;
1716 struct halmac_api *api;
1717 enum halmac_ret_status status;
1718 u32 val = 0;
1719
1720
1721 halmac = dvobj_to_halmac(d);
1722 api = HALMAC_GET_API(halmac);
1723
1724 status = api->halmac_get_hw_value(halmac, HALMAC_HW_ORI_H2C_SIZE, &val);
1725 if (status != HALMAC_RET_SUCCESS)
1726 return -1;
1727
1728 *size = val;
1729
1730 return 0;
1731 }
1732
rtw_halmac_get_oqt_size(struct dvobj_priv * d,u8 * size)1733 int rtw_halmac_get_oqt_size(struct dvobj_priv *d, u8 *size)
1734 {
1735 enum halmac_ret_status status;
1736 struct halmac_adapter *halmac;
1737 struct halmac_api *api;
1738 u8 val;
1739
1740
1741 if (!size)
1742 return -1;
1743
1744 halmac = dvobj_to_halmac(d);
1745 api = HALMAC_GET_API(halmac);
1746
1747 status = api->halmac_get_hw_value(halmac, HALMAC_HW_AC_OQT_SIZE, &val);
1748 if (status != HALMAC_RET_SUCCESS)
1749 return -1;
1750
1751 *size = val;
1752 return 0;
1753 }
1754
rtw_halmac_get_ac_queue_number(struct dvobj_priv * d,u8 * num)1755 int rtw_halmac_get_ac_queue_number(struct dvobj_priv *d, u8 *num)
1756 {
1757 enum halmac_ret_status status;
1758 struct halmac_adapter *halmac;
1759 struct halmac_api *api;
1760 u8 val;
1761
1762
1763 if (!num)
1764 return -1;
1765
1766 halmac = dvobj_to_halmac(d);
1767 api = HALMAC_GET_API(halmac);
1768
1769 status = api->halmac_get_hw_value(halmac, HALMAC_HW_AC_QUEUE_NUM, &val);
1770 if (status != HALMAC_RET_SUCCESS)
1771 return -1;
1772
1773 *num = val;
1774 return 0;
1775 }
1776
1777 /**
1778 * rtw_halmac_get_mac_address() - Get MAC address of specific port
1779 * @d: struct dvobj_priv*
1780 * @hwport: port
1781 * @addr: buffer for storing MAC address
1782 *
1783 * Get MAC address of specific port from HALMAC.
1784 *
1785 * Rteurn 0 for OK, otherwise fail.
1786 */
rtw_halmac_get_mac_address(struct dvobj_priv * d,enum _hw_port hwport,u8 * addr)1787 int rtw_halmac_get_mac_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
1788 {
1789 struct halmac_adapter *halmac;
1790 struct halmac_api *api;
1791 enum halmac_portid port;
1792 union halmac_wlan_addr hwa;
1793 enum halmac_ret_status status;
1794 int err = -1;
1795
1796
1797 if (!addr)
1798 goto out;
1799
1800 halmac = dvobj_to_halmac(d);
1801 api = HALMAC_GET_API(halmac);
1802 port = _hw_port_drv2halmac(hwport);
1803 _rtw_memset(&hwa, 0, sizeof(hwa));
1804
1805 status = api->halmac_get_mac_addr(halmac, port, &hwa);
1806 if (status != HALMAC_RET_SUCCESS)
1807 goto out;
1808
1809 _rtw_memcpy(addr, hwa.addr, 6);
1810
1811 err = 0;
1812 out:
1813 return err;
1814 }
1815
1816 /**
1817 * rtw_halmac_get_network_type() - Get network type of specific port
1818 * @d: struct dvobj_priv*
1819 * @hwport: port
1820 * @type: buffer to put network type (_HW_STATE_*)
1821 *
1822 * Get network type of specific port from HALMAC.
1823 *
1824 * Rteurn 0 for OK, otherwise fail.
1825 */
rtw_halmac_get_network_type(struct dvobj_priv * d,enum _hw_port hwport,u8 * type)1826 int rtw_halmac_get_network_type(struct dvobj_priv *d, enum _hw_port hwport, u8 *type)
1827 {
1828 #if 0
1829 struct halmac_adapter *halmac;
1830 struct halmac_api *api;
1831 enum halmac_portid port;
1832 enum halmac_network_type_select network;
1833 enum halmac_ret_status status;
1834 int err = -1;
1835
1836
1837 halmac = dvobj_to_halmac(d);
1838 api = HALMAC_GET_API(halmac);
1839 port = _hw_port_drv2halmac(hwport);
1840 network = HALMAC_NETWORK_UNDEFINE;
1841
1842 status = api->halmac_get_net_type(halmac, port, &network);
1843 if (status != HALMAC_RET_SUCCESS)
1844 goto out;
1845
1846 *type = _network_type_halmac2drv(network);
1847
1848 err = 0;
1849 out:
1850 return err;
1851 #else
1852 struct _ADAPTER *a;
1853 enum halmac_portid port;
1854 enum halmac_network_type_select network;
1855 u32 val;
1856 int err = -1;
1857
1858
1859 a = dvobj_get_primary_adapter(d);
1860 port = _hw_port_drv2halmac(hwport);
1861 network = HALMAC_NETWORK_UNDEFINE;
1862
1863 switch (port) {
1864 case HALMAC_PORTID0:
1865 val = rtw_read32(a, REG_CR);
1866 network = BIT_GET_NETYPE0(val);
1867 break;
1868
1869 case HALMAC_PORTID1:
1870 val = rtw_read32(a, REG_CR);
1871 network = BIT_GET_NETYPE1(val);
1872 break;
1873
1874 case HALMAC_PORTID2:
1875 val = rtw_read32(a, REG_CR_EXT);
1876 network = BIT_GET_NETYPE2(val);
1877 break;
1878
1879 case HALMAC_PORTID3:
1880 val = rtw_read32(a, REG_CR_EXT);
1881 network = BIT_GET_NETYPE3(val);
1882 break;
1883
1884 case HALMAC_PORTID4:
1885 val = rtw_read32(a, REG_CR_EXT);
1886 network = BIT_GET_NETYPE4(val);
1887 break;
1888
1889 default:
1890 goto out;
1891 }
1892
1893 *type = _network_type_halmac2drv(network);
1894
1895 err = 0;
1896 out:
1897 return err;
1898 #endif
1899 }
1900
1901 /**
1902 * rtw_halmac_get_bcn_ctrl() - Get beacon control setting of specific port
1903 * @d: struct dvobj_priv*
1904 * @hwport: port
1905 * @bcn_ctrl: setting of beacon control
1906 *
1907 * Get beacon control setting of specific port from HALMAC.
1908 *
1909 * Rteurn 0 for OK, otherwise fail.
1910 */
rtw_halmac_get_bcn_ctrl(struct dvobj_priv * d,enum _hw_port hwport,struct rtw_halmac_bcn_ctrl * bcn_ctrl)1911 int rtw_halmac_get_bcn_ctrl(struct dvobj_priv *d, enum _hw_port hwport,
1912 struct rtw_halmac_bcn_ctrl *bcn_ctrl)
1913 {
1914 struct halmac_adapter *halmac;
1915 struct halmac_api *api;
1916 enum halmac_portid port;
1917 struct halmac_bcn_ctrl ctrl;
1918 enum halmac_ret_status status;
1919 int err = -1;
1920
1921
1922 halmac = dvobj_to_halmac(d);
1923 api = HALMAC_GET_API(halmac);
1924 port = _hw_port_drv2halmac(hwport);
1925 _rtw_memset(&ctrl, 0, sizeof(ctrl));
1926
1927 status = api->halmac_rw_bcn_ctrl(halmac, port, 0, &ctrl);
1928 if (status != HALMAC_RET_SUCCESS)
1929 goto out;
1930 _beacon_ctrl_halmac2drv(&ctrl, bcn_ctrl);
1931
1932 err = 0;
1933 out:
1934 return err;
1935 }
1936
1937 /*
1938 * Note:
1939 * When this function return, the register REG_RCR may be changed.
1940 */
rtw_halmac_config_rx_info(struct dvobj_priv * d,enum halmac_drv_info info)1941 int rtw_halmac_config_rx_info(struct dvobj_priv *d, enum halmac_drv_info info)
1942 {
1943 struct halmac_adapter *halmac;
1944 struct halmac_api *api;
1945 enum halmac_ret_status status;
1946 int err = -1;
1947
1948
1949 halmac = dvobj_to_halmac(d);
1950 api = HALMAC_GET_API(halmac);
1951
1952 status = api->halmac_cfg_drv_info(halmac, info);
1953 if (status != HALMAC_RET_SUCCESS)
1954 goto out;
1955
1956 err = 0;
1957 out:
1958 /* Sync driver RCR cache with register setting */
1959 rtw_hal_get_hwreg(dvobj_get_primary_adapter(d), HW_VAR_RCR, NULL);
1960
1961 return err;
1962 }
1963
1964 /**
1965 * rtw_halmac_set_max_dl_fw_size() - Set the MAX download firmware size
1966 * @d: struct dvobj_priv*
1967 * @size: the max download firmware size in one I/O
1968 *
1969 * Set the max download firmware size in one I/O.
1970 * Please also consider the max size of the callback function "SEND_RSVD_PAGE"
1971 * could accept, because download firmware would call "SEND_RSVD_PAGE" to send
1972 * firmware to IC.
1973 *
1974 * If the value of "size" is not even, it would be rounded down to nearest
1975 * even, and 0 and 1 are both invalid value.
1976 *
1977 * Return 0 for setting OK, otherwise fail.
1978 */
rtw_halmac_set_max_dl_fw_size(struct dvobj_priv * d,u32 size)1979 int rtw_halmac_set_max_dl_fw_size(struct dvobj_priv *d, u32 size)
1980 {
1981 struct halmac_adapter *mac;
1982 struct halmac_api *api;
1983 enum halmac_ret_status status;
1984
1985
1986 if (!size || (size == 1))
1987 return -1;
1988
1989 mac = dvobj_to_halmac(d);
1990 if (!mac) {
1991 RTW_ERR("%s: HALMAC is not ready!!\n", __FUNCTION__);
1992 return -1;
1993 }
1994 api = HALMAC_GET_API(mac);
1995
1996 size &= ~1; /* round down to even */
1997 status = api->halmac_cfg_max_dl_size(mac, size);
1998 if (status != HALMAC_RET_SUCCESS) {
1999 RTW_WARN("%s: Fail to cfg_max_dl_size(%d), err=%d!!\n",
2000 __FUNCTION__, size, status);
2001 return -1;
2002 }
2003
2004 return 0;
2005 }
2006
2007 /**
2008 * rtw_halmac_set_mac_address() - Set mac address of specific port
2009 * @d: struct dvobj_priv*
2010 * @hwport: port
2011 * @addr: mac address
2012 *
2013 * Set self mac address of specific port to HALMAC.
2014 *
2015 * Rteurn 0 for OK, otherwise fail.
2016 */
rtw_halmac_set_mac_address(struct dvobj_priv * d,enum _hw_port hwport,u8 * addr)2017 int rtw_halmac_set_mac_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2018 {
2019 struct halmac_adapter *halmac;
2020 struct halmac_api *api;
2021 enum halmac_portid port;
2022 union halmac_wlan_addr hwa;
2023 enum halmac_ret_status status;
2024 int err = -1;
2025
2026
2027 halmac = dvobj_to_halmac(d);
2028 api = HALMAC_GET_API(halmac);
2029
2030 port = _hw_port_drv2halmac(hwport);
2031 _rtw_memset(&hwa, 0, sizeof(hwa));
2032 _rtw_memcpy(hwa.addr, addr, 6);
2033
2034 status = api->halmac_cfg_mac_addr(halmac, port, &hwa);
2035 if (status != HALMAC_RET_SUCCESS)
2036 goto out;
2037
2038 err = 0;
2039 out:
2040 return err;
2041 }
2042
2043 /**
2044 * rtw_halmac_set_bssid() - Set BSSID of specific port
2045 * @d: struct dvobj_priv*
2046 * @hwport: port
2047 * @addr: BSSID, mac address of AP
2048 *
2049 * Set BSSID of specific port to HALMAC.
2050 *
2051 * Rteurn 0 for OK, otherwise fail.
2052 */
rtw_halmac_set_bssid(struct dvobj_priv * d,enum _hw_port hwport,u8 * addr)2053 int rtw_halmac_set_bssid(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2054 {
2055 struct halmac_adapter *halmac;
2056 struct halmac_api *api;
2057 enum halmac_portid port;
2058 union halmac_wlan_addr hwa;
2059 enum halmac_ret_status status;
2060 int err = -1;
2061
2062
2063 halmac = dvobj_to_halmac(d);
2064 api = HALMAC_GET_API(halmac);
2065 port = _hw_port_drv2halmac(hwport);
2066
2067 _rtw_memset(&hwa, 0, sizeof(hwa));
2068 _rtw_memcpy(hwa.addr, addr, 6);
2069 status = api->halmac_cfg_bssid(halmac, port, &hwa);
2070 if (status != HALMAC_RET_SUCCESS)
2071 goto out;
2072
2073 err = 0;
2074 out:
2075 return err;
2076 }
2077
2078 /**
2079 * rtw_halmac_set_tx_address() - Set transmitter address of specific port
2080 * @d: struct dvobj_priv*
2081 * @hwport: port
2082 * @addr: transmitter address
2083 *
2084 * Set transmitter address of specific port to HALMAC.
2085 *
2086 * Rteurn 0 for OK, otherwise fail.
2087 */
rtw_halmac_set_tx_address(struct dvobj_priv * d,enum _hw_port hwport,u8 * addr)2088 int rtw_halmac_set_tx_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2089 {
2090 struct halmac_adapter *halmac;
2091 struct halmac_api *api;
2092 enum halmac_portid port;
2093 union halmac_wlan_addr hwa;
2094 enum halmac_ret_status status;
2095 int err = -1;
2096
2097
2098 halmac = dvobj_to_halmac(d);
2099 api = HALMAC_GET_API(halmac);
2100 port = _hw_port_drv2halmac(hwport);
2101 _rtw_memset(&hwa, 0, sizeof(hwa));
2102 _rtw_memcpy(hwa.addr, addr, 6);
2103
2104 status = api->halmac_cfg_transmitter_addr(halmac, port, &hwa);
2105 if (status != HALMAC_RET_SUCCESS)
2106 goto out;
2107
2108 err = 0;
2109 out:
2110 return err;
2111 }
2112
2113 /**
2114 * rtw_halmac_set_network_type() - Set network type of specific port
2115 * @d: struct dvobj_priv*
2116 * @hwport: port
2117 * @type: network type (_HW_STATE_*)
2118 *
2119 * Set network type of specific port to HALMAC.
2120 *
2121 * Rteurn 0 for OK, otherwise fail.
2122 */
rtw_halmac_set_network_type(struct dvobj_priv * d,enum _hw_port hwport,u8 type)2123 int rtw_halmac_set_network_type(struct dvobj_priv *d, enum _hw_port hwport, u8 type)
2124 {
2125 struct halmac_adapter *halmac;
2126 struct halmac_api *api;
2127 enum halmac_portid port;
2128 enum halmac_network_type_select network;
2129 enum halmac_ret_status status;
2130 int err = -1;
2131
2132
2133 halmac = dvobj_to_halmac(d);
2134 api = HALMAC_GET_API(halmac);
2135 port = _hw_port_drv2halmac(hwport);
2136 network = _network_type_drv2halmac(type);
2137
2138 status = api->halmac_cfg_net_type(halmac, port, network);
2139 if (status != HALMAC_RET_SUCCESS)
2140 goto out;
2141
2142 err = 0;
2143 out:
2144 return err;
2145 }
2146
2147 /**
2148 * rtw_halmac_reset_tsf() - Reset TSF timer of specific port
2149 * @d: struct dvobj_priv*
2150 * @hwport: port
2151 *
2152 * Notice HALMAC to reset timing synchronization function(TSF) timer of
2153 * specific port.
2154 *
2155 * Rteurn 0 for OK, otherwise fail.
2156 */
rtw_halmac_reset_tsf(struct dvobj_priv * d,enum _hw_port hwport)2157 int rtw_halmac_reset_tsf(struct dvobj_priv *d, enum _hw_port hwport)
2158 {
2159 struct halmac_adapter *halmac;
2160 struct halmac_api *api;
2161 enum halmac_portid port;
2162 enum halmac_ret_status status;
2163 int err = -1;
2164
2165
2166 halmac = dvobj_to_halmac(d);
2167 api = HALMAC_GET_API(halmac);
2168 port = _hw_port_drv2halmac(hwport);
2169
2170 status = api->halmac_cfg_tsf_rst(halmac, port);
2171 if (status != HALMAC_RET_SUCCESS)
2172 goto out;
2173
2174 err = 0;
2175 out:
2176 return err;
2177 }
2178
2179 /**
2180 * rtw_halmac_set_bcn_interval() - Set beacon interval of each port
2181 * @d: struct dvobj_priv*
2182 * @hwport: port
2183 * @space: beacon interval, unit is ms
2184 *
2185 * Set beacon interval of specific port to HALMAC.
2186 *
2187 * Rteurn 0 for OK, otherwise fail.
2188 */
rtw_halmac_set_bcn_interval(struct dvobj_priv * d,enum _hw_port hwport,u32 interval)2189 int rtw_halmac_set_bcn_interval(struct dvobj_priv *d, enum _hw_port hwport,
2190 u32 interval)
2191 {
2192 struct halmac_adapter *halmac;
2193 struct halmac_api *api;
2194 enum halmac_portid port;
2195 enum halmac_ret_status status;
2196 int err = -1;
2197
2198
2199 halmac = dvobj_to_halmac(d);
2200 api = HALMAC_GET_API(halmac);
2201 port = _hw_port_drv2halmac(hwport);
2202
2203 status = api->halmac_cfg_bcn_space(halmac, port, interval);
2204 if (status != HALMAC_RET_SUCCESS)
2205 goto out;
2206
2207 err = 0;
2208 out:
2209 return err;
2210 }
2211
2212 /**
2213 * rtw_halmac_set_bcn_ctrl() - Set beacon control setting of each port
2214 * @d: struct dvobj_priv*
2215 * @hwport: port
2216 * @bcn_ctrl: setting of beacon control
2217 *
2218 * Set beacon control setting of specific port to HALMAC.
2219 *
2220 * Rteurn 0 for OK, otherwise fail.
2221 */
rtw_halmac_set_bcn_ctrl(struct dvobj_priv * d,enum _hw_port hwport,struct rtw_halmac_bcn_ctrl * bcn_ctrl)2222 int rtw_halmac_set_bcn_ctrl(struct dvobj_priv *d, enum _hw_port hwport,
2223 struct rtw_halmac_bcn_ctrl *bcn_ctrl)
2224 {
2225 struct halmac_adapter *halmac;
2226 struct halmac_api *api;
2227 enum halmac_portid port;
2228 struct halmac_bcn_ctrl ctrl;
2229 enum halmac_ret_status status;
2230 int err = -1;
2231
2232
2233 halmac = dvobj_to_halmac(d);
2234 api = HALMAC_GET_API(halmac);
2235 port = _hw_port_drv2halmac(hwport);
2236 _rtw_memset(&ctrl, 0, sizeof(ctrl));
2237 _beacon_ctrl_drv2halmac(bcn_ctrl, &ctrl);
2238
2239 status = api->halmac_rw_bcn_ctrl(halmac, port, 1, &ctrl);
2240 if (status != HALMAC_RET_SUCCESS)
2241 goto out;
2242
2243 err = 0;
2244 out:
2245 return err;
2246 }
2247
2248 /**
2249 * rtw_halmac_set_aid() - Set association identifier(AID) of specific port
2250 * @d: struct dvobj_priv*
2251 * @hwport: port
2252 * @aid: Association identifier
2253 *
2254 * Set association identifier(AID) of specific port to HALMAC.
2255 *
2256 * Rteurn 0 for OK, otherwise fail.
2257 */
rtw_halmac_set_aid(struct dvobj_priv * d,enum _hw_port hwport,u16 aid)2258 int rtw_halmac_set_aid(struct dvobj_priv *d, enum _hw_port hwport, u16 aid)
2259 {
2260 struct halmac_adapter *halmac;
2261 struct halmac_api *api;
2262 enum halmac_portid port;
2263 enum halmac_ret_status status;
2264 int err = -1;
2265
2266
2267 halmac = dvobj_to_halmac(d);
2268 api = HALMAC_GET_API(halmac);
2269 port = _hw_port_drv2halmac(hwport);
2270
2271 #if 0
2272 status = api->halmac_cfg_aid(halmac, port, aid);
2273 if (status != HALMAC_RET_SUCCESS)
2274 goto out;
2275 #else
2276 {
2277 struct _ADAPTER *a;
2278 u32 addr;
2279 u16 val;
2280
2281 a = dvobj_get_primary_adapter(d);
2282
2283 switch (port) {
2284 case 0:
2285 addr = REG_BCN_PSR_RPT;
2286 val = rtw_read16(a, addr);
2287 val = BIT_SET_PS_AID_0(val, aid);
2288 rtw_write16(a, addr, val);
2289 break;
2290
2291 case 1:
2292 addr = REG_BCN_PSR_RPT1;
2293 val = rtw_read16(a, addr);
2294 val = BIT_SET_PS_AID_1(val, aid);
2295 rtw_write16(a, addr, val);
2296 break;
2297
2298 case 2:
2299 addr = REG_BCN_PSR_RPT2;
2300 val = rtw_read16(a, addr);
2301 val = BIT_SET_PS_AID_2(val, aid);
2302 rtw_write16(a, addr, val);
2303 break;
2304
2305 case 3:
2306 addr = REG_BCN_PSR_RPT3;
2307 val = rtw_read16(a, addr);
2308 val = BIT_SET_PS_AID_3(val, aid);
2309 rtw_write16(a, addr, val);
2310 break;
2311
2312 case 4:
2313 addr = REG_BCN_PSR_RPT4;
2314 val = rtw_read16(a, addr);
2315 val = BIT_SET_PS_AID_4(val, aid);
2316 rtw_write16(a, addr, val);
2317 break;
2318
2319 default:
2320 goto out;
2321 }
2322 }
2323 #endif
2324
2325 err = 0;
2326 out:
2327 return err;
2328 }
2329
rtw_halmac_set_bandwidth(struct dvobj_priv * d,u8 channel,u8 pri_ch_idx,u8 bw)2330 int rtw_halmac_set_bandwidth(struct dvobj_priv *d, u8 channel, u8 pri_ch_idx, u8 bw)
2331 {
2332 struct halmac_adapter *mac;
2333 struct halmac_api *api;
2334 enum halmac_ret_status status;
2335
2336
2337 mac = dvobj_to_halmac(d);
2338 api = HALMAC_GET_API(mac);
2339
2340 status = api->halmac_cfg_ch_bw(mac, channel, pri_ch_idx, bw);
2341 if (HALMAC_RET_SUCCESS != status)
2342 return -1;
2343
2344 return 0;
2345 }
2346
2347 /**
2348 * rtw_halmac_set_edca() - config edca parameter
2349 * @d: struct dvobj_priv*
2350 * @queue: XMIT_[VO/VI/BE/BK]_QUEUE
2351 * @aifs: Arbitration inter-frame space(AIFS)
2352 * @cw: Contention window(CW)
2353 * @txop: MAX Transmit Opportunity(TXOP)
2354 *
2355 * Return: 0 if process OK, otherwise -1.
2356 */
rtw_halmac_set_edca(struct dvobj_priv * d,u8 queue,u8 aifs,u8 cw,u16 txop)2357 int rtw_halmac_set_edca(struct dvobj_priv *d, u8 queue, u8 aifs, u8 cw, u16 txop)
2358 {
2359 struct halmac_adapter *mac;
2360 struct halmac_api *api;
2361 enum halmac_acq_id ac;
2362 struct halmac_edca_para edca;
2363 enum halmac_ret_status status;
2364
2365
2366 mac = dvobj_to_halmac(d);
2367 api = HALMAC_GET_API(mac);
2368
2369 switch (queue) {
2370 case XMIT_VO_QUEUE:
2371 ac = HALMAC_ACQ_ID_VO;
2372 break;
2373 case XMIT_VI_QUEUE:
2374 ac = HALMAC_ACQ_ID_VI;
2375 break;
2376 case XMIT_BE_QUEUE:
2377 ac = HALMAC_ACQ_ID_BE;
2378 break;
2379 case XMIT_BK_QUEUE:
2380 ac = HALMAC_ACQ_ID_BK;
2381 break;
2382 default:
2383 return -1;
2384 }
2385
2386 edca.aifs = aifs;
2387 edca.cw = cw;
2388 edca.txop_limit = txop;
2389
2390 status = api->halmac_cfg_edca_para(mac, ac, &edca);
2391 if (status != HALMAC_RET_SUCCESS)
2392 return -1;
2393
2394 return 0;
2395 }
2396
2397 /**
2398 * rtw_halmac_set_rts_full_bw() - Send RTS to all covered channels
2399 * @d: struct dvobj_priv*
2400 * @enable: _TRUE(enable), _FALSE(disable)
2401 *
2402 * Hradware will duplicate RTS packet to all channels which are covered in used
2403 * bandwidth.
2404 *
2405 * Return 0 if process OK, otherwise -1.
2406 */
rtw_halmac_set_rts_full_bw(struct dvobj_priv * d,u8 enable)2407 int rtw_halmac_set_rts_full_bw(struct dvobj_priv *d, u8 enable)
2408 {
2409 struct halmac_adapter *mac;
2410 struct halmac_api *api;
2411 enum halmac_ret_status status;
2412 u8 full;
2413
2414
2415 mac = dvobj_to_halmac(d);
2416 api = HALMAC_GET_API(mac);
2417 full = (enable == _TRUE) ? 1 : 0;
2418
2419 status = api->halmac_set_hw_value(mac, HALMAC_HW_RTS_FULL_BW, &full);
2420 if (HALMAC_RET_SUCCESS != status)
2421 return -1;
2422
2423 return 0;
2424 }
2425
2426 #ifdef RTW_HALMAC_DBG_POWER_SWITCH
_dump_mac_reg(struct dvobj_priv * d,u32 start,u32 end)2427 static void _dump_mac_reg(struct dvobj_priv *d, u32 start, u32 end)
2428 {
2429 struct _ADAPTER *adapter;
2430 int i, j = 1;
2431
2432
2433 adapter = dvobj_get_primary_adapter(d);
2434 for (i = start; i < end; i += 4) {
2435 if (j % 4 == 1)
2436 RTW_PRINT("0x%04x", i);
2437 _RTW_PRINT(" 0x%08x ", rtw_read32(adapter, i));
2438 if ((j++) % 4 == 0)
2439 _RTW_PRINT("\n");
2440 }
2441 }
2442
dump_dbg_val(struct _ADAPTER * a,u32 reg)2443 void dump_dbg_val(struct _ADAPTER *a, u32 reg)
2444 {
2445 u32 v32;
2446
2447
2448 rtw_write8(a, 0x3A, reg);
2449 v32 = rtw_read32(a, 0xC0);
2450 RTW_PRINT("0x3A = %02x, 0xC0 = 0x%08x\n",reg, v32);
2451 }
2452
2453 #ifdef CONFIG_PCI_HCI
_dump_pcie_cfg_space(struct dvobj_priv * d)2454 static void _dump_pcie_cfg_space(struct dvobj_priv *d)
2455 {
2456 struct _ADAPTER *padapter = dvobj_get_primary_adapter(d);
2457 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
2458 struct pci_dev *pdev = pdvobjpriv->ppcidev;
2459 struct pci_dev *bridge_pdev = pdev->bus->self;
2460
2461 u32 tmp[4] = { 0 };
2462 u32 i, j;
2463
2464 RTW_PRINT("\n***** PCI Device Configuration Space *****\n\n");
2465
2466 for(i = 0; i < 0x100; i += 0x10)
2467 {
2468 for (j = 0 ; j < 4 ; j++)
2469 pci_read_config_dword(pdev, i + j * 4, tmp+j);
2470
2471 RTW_PRINT("%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2472 i, tmp[0] & 0xFF, (tmp[0] >> 8) & 0xFF, (tmp[0] >> 16) & 0xFF, (tmp[0] >> 24) & 0xFF,
2473 tmp[1] & 0xFF, (tmp[1] >> 8) & 0xFF, (tmp[1] >> 16) & 0xFF, (tmp[1] >> 24) & 0xFF,
2474 tmp[2] & 0xFF, (tmp[2] >> 8) & 0xFF, (tmp[2] >> 16) & 0xFF, (tmp[2] >> 24) & 0xFF,
2475 tmp[3] & 0xFF, (tmp[3] >> 8) & 0xFF, (tmp[3] >> 16) & 0xFF, (tmp[3] >> 24) & 0xFF);
2476 }
2477
2478 RTW_PRINT("\n***** PCI Host Device Configuration Space*****\n\n");
2479
2480 for(i = 0; i < 0x100; i += 0x10)
2481 {
2482 for (j = 0 ; j < 4 ; j++)
2483 pci_read_config_dword(bridge_pdev, i + j * 4, tmp+j);
2484
2485 RTW_PRINT("%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2486 i, tmp[0] & 0xFF, (tmp[0] >> 8) & 0xFF, (tmp[0] >> 16) & 0xFF, (tmp[0] >> 24) & 0xFF,
2487 tmp[1] & 0xFF, (tmp[1] >> 8) & 0xFF, (tmp[1] >> 16) & 0xFF, (tmp[1] >> 24) & 0xFF,
2488 tmp[2] & 0xFF, (tmp[2] >> 8) & 0xFF, (tmp[2] >> 16) & 0xFF, (tmp[2] >> 24) & 0xFF,
2489 tmp[3] & 0xFF, (tmp[3] >> 8) & 0xFF, (tmp[3] >> 16) & 0xFF, (tmp[3] >> 24) & 0xFF);
2490 }
2491 }
2492 #endif
2493
_dump_mac_reg_for_power_switch(struct dvobj_priv * d,const char * caller,char * desc)2494 static void _dump_mac_reg_for_power_switch(struct dvobj_priv *d,
2495 const char* caller, char* desc)
2496 {
2497 struct _ADAPTER *a;
2498 u8 v8;
2499
2500
2501 RTW_PRINT("%s: %s\n", caller, desc);
2502 RTW_PRINT("======= MAC REG =======\n");
2503 /* page 0/1 */
2504 _dump_mac_reg(d, 0x0, 0x200);
2505 _dump_mac_reg(d, 0x300, 0x400); /* also dump page 3 */
2506
2507 /* dump debug register */
2508 a = dvobj_get_primary_adapter(d);
2509
2510 #ifdef CONFIG_PCI_HCI
2511 _dump_pcie_cfg_space(d);
2512
2513 v8 = rtw_read8(a, 0xF6) | 0x01;
2514 rtw_write8(a, 0xF6, v8);
2515 RTW_PRINT("0xF6 = %02x\n", v8);
2516
2517 dump_dbg_val(a, 0x63);
2518 dump_dbg_val(a, 0x64);
2519 dump_dbg_val(a, 0x68);
2520 dump_dbg_val(a, 0x69);
2521 dump_dbg_val(a, 0x6a);
2522 dump_dbg_val(a, 0x6b);
2523 dump_dbg_val(a, 0x71);
2524 dump_dbg_val(a, 0x72);
2525 #endif
2526 }
2527
_power_switch(struct halmac_adapter * halmac,struct halmac_api * api,enum halmac_mac_power pwr)2528 static enum halmac_ret_status _power_switch(struct halmac_adapter *halmac,
2529 struct halmac_api *api,
2530 enum halmac_mac_power pwr)
2531 {
2532 enum halmac_ret_status status;
2533 char desc[80] = {0};
2534
2535
2536 rtw_sprintf(desc, 80, "before calling power %s",
2537 (pwr==HALMAC_MAC_POWER_ON)?"on":"off");
2538 _dump_mac_reg_for_power_switch((struct dvobj_priv *)halmac->drv_adapter,
2539 __FUNCTION__, desc);
2540
2541 status = api->halmac_mac_power_switch(halmac, pwr);
2542 RTW_PRINT("%s: status=%d\n", __FUNCTION__, status);
2543
2544 rtw_sprintf(desc, 80, "after calling power %s",
2545 (pwr==HALMAC_MAC_POWER_ON)?"on":"off");
2546 _dump_mac_reg_for_power_switch((struct dvobj_priv *)halmac->drv_adapter,
2547 __FUNCTION__, desc);
2548
2549 return status;
2550 }
2551 #else /* !RTW_HALMAC_DBG_POWER_SWITCH */
2552 #define _power_switch(mac, api, pwr) (api)->halmac_mac_power_switch(mac, pwr)
2553 #endif /* !RTW_HALMAC_DBG_POWER_SWITCH */
2554
2555 /*
2556 * Description:
2557 * Power on device hardware.
2558 * [Notice!] If device's power state is on before,
2559 * it would be power off first and turn on power again.
2560 *
2561 * Return:
2562 * 0 power on success
2563 * -1 power on fail
2564 * -2 power state unchange
2565 */
rtw_halmac_poweron(struct dvobj_priv * d)2566 int rtw_halmac_poweron(struct dvobj_priv *d)
2567 {
2568 struct halmac_adapter *halmac;
2569 struct halmac_api *api;
2570 enum halmac_ret_status status;
2571 int err = -1;
2572 #if defined(CONFIG_PCI_HCI) && defined(CONFIG_RTL8822B)
2573 struct _ADAPTER *a;
2574 u8 v8;
2575 u32 addr;
2576
2577 a = dvobj_get_primary_adapter(d);
2578 #endif
2579
2580 halmac = dvobj_to_halmac(d);
2581 if (!halmac)
2582 goto out;
2583
2584 api = HALMAC_GET_API(halmac);
2585
2586 status = api->halmac_pre_init_system_cfg(halmac);
2587 if (status != HALMAC_RET_SUCCESS)
2588 goto out;
2589
2590 #ifdef CONFIG_SDIO_HCI
2591 status = api->halmac_sdio_cmd53_4byte(halmac, HALMAC_SDIO_CMD53_4BYTE_MODE_RW);
2592 if (status != HALMAC_RET_SUCCESS)
2593 goto out;
2594 #endif /* CONFIG_SDIO_HCI */
2595
2596 #if defined(CONFIG_PCI_HCI) && defined(CONFIG_RTL8822B)
2597 addr = 0x3F3;
2598 v8 = rtw_read8(a, addr);
2599 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2600 /* are we in pcie debug mode? */
2601 if (!(v8 & BIT(2))) {
2602 RTW_PRINT("%s: Enable pcie debug mode\n", __FUNCTION__);
2603 v8 |= BIT(2);
2604 v8 = rtw_write8(a, addr, v8);
2605 }
2606 #endif
2607
2608 status = _power_switch(halmac, api, HALMAC_MAC_POWER_ON);
2609 if (HALMAC_RET_PWR_UNCHANGE == status) {
2610
2611 #if defined(CONFIG_PCI_HCI) && defined(CONFIG_RTL8822B)
2612 addr = 0x3F3;
2613 v8 = rtw_read8(a, addr);
2614 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2615
2616 /* are we in pcie debug mode? */
2617 if (!(v8 & BIT(2))) {
2618 RTW_PRINT("%s: Enable pcie debug mode\n", __FUNCTION__);
2619 v8 |= BIT(2);
2620 v8 = rtw_write8(a, addr, v8);
2621 } else if (v8 & BIT(0)) {
2622 /* DMA stuck */
2623 addr = 0x1350;
2624 v8 = rtw_read8(a, addr);
2625 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2626 RTW_PRINT("%s: recover DMA stuck\n", __FUNCTION__);
2627 v8 |= BIT(6);
2628 v8 = rtw_write8(a, addr, v8);
2629 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2630 }
2631 #endif
2632 /*
2633 * Work around for warm reboot but device not power off,
2634 * but it would also fall into this case when auto power on is enabled.
2635 */
2636 _power_switch(halmac, api, HALMAC_MAC_POWER_OFF);
2637 status = _power_switch(halmac, api, HALMAC_MAC_POWER_ON);
2638 RTW_WARN("%s: Power state abnormal, try to recover...%s\n",
2639 __FUNCTION__, (HALMAC_RET_SUCCESS == status)?"OK":"FAIL!");
2640 }
2641 if (HALMAC_RET_SUCCESS != status) {
2642 if (HALMAC_RET_PWR_UNCHANGE == status)
2643 err = -2;
2644 goto out;
2645 }
2646
2647 status = api->halmac_init_system_cfg(halmac);
2648 if (status != HALMAC_RET_SUCCESS)
2649 goto out;
2650
2651 err = 0;
2652 out:
2653 return err;
2654 }
2655
2656 /*
2657 * Description:
2658 * Power off device hardware.
2659 *
2660 * Return:
2661 * 0 Power off success
2662 * -1 Power off fail
2663 */
rtw_halmac_poweroff(struct dvobj_priv * d)2664 int rtw_halmac_poweroff(struct dvobj_priv *d)
2665 {
2666 struct halmac_adapter *halmac;
2667 struct halmac_api *api;
2668 enum halmac_ret_status status;
2669 int err = -1;
2670
2671
2672 halmac = dvobj_to_halmac(d);
2673 if (!halmac)
2674 goto out;
2675
2676 api = HALMAC_GET_API(halmac);
2677
2678 status = _power_switch(halmac, api, HALMAC_MAC_POWER_OFF);
2679 if ((HALMAC_RET_SUCCESS != status)
2680 && (HALMAC_RET_PWR_UNCHANGE != status))
2681 goto out;
2682
2683 err = 0;
2684 out:
2685 return err;
2686 }
2687
2688 #ifdef CONFIG_SUPPORT_TRX_SHARED
_trx_share_mode_drv2halmac(u8 trx_share_mode)2689 static inline enum halmac_rx_fifo_expanding_mode _trx_share_mode_drv2halmac(u8 trx_share_mode)
2690 {
2691 if (0 == trx_share_mode)
2692 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
2693 else if (1 == trx_share_mode)
2694 return HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK;
2695 else if (2 == trx_share_mode)
2696 return HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK;
2697 else if (3 == trx_share_mode)
2698 return HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK;
2699 else
2700 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
2701 }
2702
_rtw_get_trx_share_mode(struct _ADAPTER * adapter)2703 static enum halmac_rx_fifo_expanding_mode _rtw_get_trx_share_mode(struct _ADAPTER *adapter)
2704 {
2705 struct registry_priv *registry_par = &adapter->registrypriv;
2706
2707 return _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
2708 }
2709
dump_trx_share_mode(void * sel,struct _ADAPTER * adapter)2710 void dump_trx_share_mode(void *sel, struct _ADAPTER *adapter)
2711 {
2712 struct registry_priv *registry_par = &adapter->registrypriv;
2713 u8 mode = _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
2714
2715 if (HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK == mode)
2716 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_1");
2717 else if (HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK == mode)
2718 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_2");
2719 else if (HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK == mode)
2720 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_3");
2721 else
2722 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "DISABLE");
2723 }
2724 #endif
2725
_rsvd_page_num_drv2halmac(u16 num)2726 static enum halmac_drv_rsvd_pg_num _rsvd_page_num_drv2halmac(u16 num)
2727 {
2728 if (num <= 8)
2729 return HALMAC_RSVD_PG_NUM8;
2730 if (num <= 16)
2731 return HALMAC_RSVD_PG_NUM16;
2732 if (num <= 24)
2733 return HALMAC_RSVD_PG_NUM24;
2734 if (num <= 32)
2735 return HALMAC_RSVD_PG_NUM32;
2736 if (num <= 64)
2737 return HALMAC_RSVD_PG_NUM64;
2738 if (num <= 128)
2739 return HALMAC_RSVD_PG_NUM128;
2740
2741 if (num > 256)
2742 RTW_WARN("%s: Fail to allocate RSVD page(%d)!!"
2743 " The MAX RSVD page number is 256...\n",
2744 __FUNCTION__, num);
2745
2746 return HALMAC_RSVD_PG_NUM256;
2747 }
2748
_rsvd_page_num_halmac2drv(enum halmac_drv_rsvd_pg_num rsvd_page_number)2749 static u16 _rsvd_page_num_halmac2drv(enum halmac_drv_rsvd_pg_num rsvd_page_number)
2750 {
2751 u16 num = 0;
2752
2753
2754 switch (rsvd_page_number) {
2755 case HALMAC_RSVD_PG_NUM8:
2756 num = 8;
2757 break;
2758
2759 case HALMAC_RSVD_PG_NUM16:
2760 num = 16;
2761 break;
2762
2763 case HALMAC_RSVD_PG_NUM24:
2764 num = 24;
2765 break;
2766
2767 case HALMAC_RSVD_PG_NUM32:
2768 num = 32;
2769 break;
2770
2771 case HALMAC_RSVD_PG_NUM64:
2772 num = 64;
2773 break;
2774
2775 case HALMAC_RSVD_PG_NUM128:
2776 num = 128;
2777 break;
2778
2779 case HALMAC_RSVD_PG_NUM256:
2780 num = 256;
2781 break;
2782 }
2783
2784 return num;
2785 }
2786
_choose_trx_mode(struct dvobj_priv * d)2787 static enum halmac_trx_mode _choose_trx_mode(struct dvobj_priv *d)
2788 {
2789 PADAPTER p;
2790
2791
2792 p = dvobj_get_primary_adapter(d);
2793
2794 if (p->registrypriv.wifi_spec)
2795 return HALMAC_TRX_MODE_WMM;
2796
2797 #ifdef CONFIG_SUPPORT_TRX_SHARED
2798 if (_rtw_get_trx_share_mode(p))
2799 return HALMAC_TRX_MODE_TRXSHARE;
2800 #endif
2801
2802 return HALMAC_TRX_MODE_NORMAL;
2803 }
2804
_rf_type_drv2halmac(enum rf_type rf_drv)2805 static inline enum halmac_rf_type _rf_type_drv2halmac(enum rf_type rf_drv)
2806 {
2807 enum halmac_rf_type rf_mac;
2808
2809
2810 switch (rf_drv) {
2811 case RF_1T1R:
2812 rf_mac = HALMAC_RF_1T1R;
2813 break;
2814 case RF_1T2R:
2815 rf_mac = HALMAC_RF_1T2R;
2816 break;
2817 case RF_2T2R:
2818 rf_mac = HALMAC_RF_2T2R;
2819 break;
2820 case RF_2T3R:
2821 rf_mac = HALMAC_RF_2T3R;
2822 break;
2823 case RF_2T4R:
2824 rf_mac = HALMAC_RF_2T4R;
2825 break;
2826 case RF_3T3R:
2827 rf_mac = HALMAC_RF_3T3R;
2828 break;
2829 case RF_3T4R:
2830 rf_mac = HALMAC_RF_3T4R;
2831 break;
2832 case RF_4T4R:
2833 rf_mac = HALMAC_RF_4T4R;
2834 break;
2835 default:
2836 rf_mac = HALMAC_RF_MAX_TYPE;
2837 RTW_ERR("%s: Invalid RF type(0x%x)!\n", __FUNCTION__, rf_drv);
2838 break;
2839 }
2840
2841 return rf_mac;
2842 }
2843
_rf_type_halmac2drv(enum halmac_rf_type rf_mac)2844 static inline enum rf_type _rf_type_halmac2drv(enum halmac_rf_type rf_mac)
2845 {
2846 enum rf_type rf_drv;
2847
2848
2849 switch (rf_mac) {
2850 case HALMAC_RF_1T2R:
2851 rf_drv = RF_1T2R;
2852 break;
2853 case HALMAC_RF_2T4R:
2854 rf_drv = RF_2T4R;
2855 break;
2856 case HALMAC_RF_2T2R:
2857 case HALMAC_RF_2T2R_GREEN:
2858 rf_drv = RF_2T2R;
2859 break;
2860 case HALMAC_RF_2T3R:
2861 rf_drv = RF_2T3R;
2862 break;
2863 case HALMAC_RF_1T1R:
2864 rf_drv = RF_1T1R;
2865 break;
2866 case HALMAC_RF_3T3R:
2867 rf_drv = RF_3T3R;
2868 break;
2869 case HALMAC_RF_3T4R:
2870 rf_drv = RF_3T4R;
2871 break;
2872 case HALMAC_RF_4T4R:
2873 rf_drv = RF_4T4R;
2874 break;
2875 default:
2876 rf_drv = RF_TYPE_MAX;
2877 RTW_ERR("%s: Invalid RF type(0x%x)!\n", __FUNCTION__, rf_mac);
2878 break;
2879 }
2880
2881 return rf_drv;
2882 }
2883
_cut_version_drv2phydm(enum tag_HAL_Cut_Version_Definition cut_drv)2884 static enum odm_cut_version _cut_version_drv2phydm(
2885 enum tag_HAL_Cut_Version_Definition cut_drv)
2886 {
2887 enum odm_cut_version cut_phydm = ODM_CUT_A;
2888 u32 diff;
2889
2890
2891 if (cut_drv > K_CUT_VERSION)
2892 RTW_WARN("%s: unknown cut_ver=%d !!\n", __FUNCTION__, cut_drv);
2893
2894 diff = cut_drv - A_CUT_VERSION;
2895 cut_phydm += diff;
2896
2897 return cut_phydm;
2898 }
2899
_send_general_info_by_reg(struct dvobj_priv * d,struct halmac_general_info * info)2900 static int _send_general_info_by_reg(struct dvobj_priv *d,
2901 struct halmac_general_info *info)
2902 {
2903 struct _ADAPTER *a;
2904 struct hal_com_data *hal;
2905 enum tag_HAL_Cut_Version_Definition cut_drv;
2906 enum rf_type rftype;
2907 enum odm_cut_version cut_phydm;
2908 u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
2909
2910
2911 a = dvobj_get_primary_adapter(d);
2912 hal = GET_HAL_DATA(a);
2913 rftype = _rf_type_halmac2drv(info->rf_type);
2914 cut_drv = GET_CVID_CUT_VERSION(hal->version_id);
2915 cut_phydm = _cut_version_drv2phydm(cut_drv);
2916
2917 #define CLASS_GENERAL_INFO_REG 0x02
2918 #define CMD_ID_GENERAL_INFO_REG 0x0C
2919 #define GENERAL_INFO_REG_SET_CMD_ID(buf, v) SET_BITS_TO_LE_4BYTE(buf, 0, 5, v)
2920 #define GENERAL_INFO_REG_SET_CLASS(buf, v) SET_BITS_TO_LE_4BYTE(buf, 5, 3, v)
2921 #define GENERAL_INFO_REG_SET_RFE_TYPE(buf, v) SET_BITS_TO_LE_4BYTE(buf, 8, 8, v)
2922 #define GENERAL_INFO_REG_SET_RF_TYPE(buf, v) SET_BITS_TO_LE_4BYTE(buf, 16, 8, v)
2923 #define GENERAL_INFO_REG_SET_CUT_VERSION(buf, v) SET_BITS_TO_LE_4BYTE(buf, 24, 8, v)
2924 #define GENERAL_INFO_REG_SET_RX_ANT_STATUS(buf, v) SET_BITS_TO_LE_1BYTE(buf+4, 0, 4, v)
2925 #define GENERAL_INFO_REG_SET_TX_ANT_STATUS(buf, v) SET_BITS_TO_LE_1BYTE(buf+4, 4, 4, v)
2926
2927 GENERAL_INFO_REG_SET_CMD_ID(h2c, CMD_ID_GENERAL_INFO_REG);
2928 GENERAL_INFO_REG_SET_CLASS(h2c, CLASS_GENERAL_INFO_REG);
2929 GENERAL_INFO_REG_SET_RFE_TYPE(h2c, info->rfe_type);
2930 GENERAL_INFO_REG_SET_RF_TYPE(h2c, rftype);
2931 GENERAL_INFO_REG_SET_CUT_VERSION(h2c, cut_phydm);
2932 GENERAL_INFO_REG_SET_RX_ANT_STATUS(h2c, info->rx_ant_status);
2933 GENERAL_INFO_REG_SET_TX_ANT_STATUS(h2c, info->tx_ant_status);
2934
2935 return rtw_halmac_send_h2c(d, h2c);
2936 }
2937
_send_general_info(struct dvobj_priv * d)2938 static int _send_general_info(struct dvobj_priv *d)
2939 {
2940 struct _ADAPTER *adapter;
2941 struct hal_com_data *hal;
2942 struct halmac_adapter *halmac;
2943 struct halmac_api *api;
2944 struct halmac_general_info info;
2945 enum halmac_ret_status status;
2946 enum rf_type rf = RF_1T1R;
2947 enum bb_path txpath = BB_PATH_A;
2948 enum bb_path rxpath = BB_PATH_A;
2949 int err;
2950
2951
2952 adapter = dvobj_get_primary_adapter(d);
2953 hal = GET_HAL_DATA(adapter);
2954 halmac = dvobj_to_halmac(d);
2955 if (!halmac)
2956 return -1;
2957 api = HALMAC_GET_API(halmac);
2958
2959 _rtw_memset(&info, 0, sizeof(info));
2960 info.rfe_type = (u8)hal->rfe_type;
2961 rtw_hal_get_rf_path(d, &rf, &txpath, &rxpath);
2962 info.rf_type = _rf_type_drv2halmac(rf);
2963 info.tx_ant_status = (u8)txpath;
2964 info.rx_ant_status = (u8)rxpath;
2965
2966 status = api->halmac_send_general_info(halmac, &info);
2967 switch (status) {
2968 case HALMAC_RET_SUCCESS:
2969 break;
2970 case HALMAC_RET_NO_DLFW:
2971 RTW_WARN("%s: halmac_send_general_info() fail because fw not dl!\n",
2972 __FUNCTION__);
2973 /* fall through */
2974 default:
2975 return -1;
2976 }
2977
2978 err = _send_general_info_by_reg(d, &info);
2979 if (err) {
2980 RTW_ERR("%s: Fail to send general info by register!\n",
2981 __FUNCTION__);
2982 return -1;
2983 }
2984
2985 return 0;
2986 }
2987
_cfg_drv_rsvd_pg_num(struct dvobj_priv * d)2988 static int _cfg_drv_rsvd_pg_num(struct dvobj_priv *d)
2989 {
2990 struct _ADAPTER *a;
2991 struct hal_com_data *hal;
2992 struct halmac_adapter *halmac;
2993 struct halmac_api *api;
2994 enum halmac_drv_rsvd_pg_num rsvd_page_number;
2995 enum halmac_ret_status status;
2996 u16 drv_rsvd_num;
2997 int ret = 0;
2998
2999
3000 a = dvobj_get_primary_adapter(d);
3001 hal = GET_HAL_DATA(a);
3002 halmac = dvobj_to_halmac(d);
3003 api = HALMAC_GET_API(halmac);
3004
3005 drv_rsvd_num = rtw_hal_get_rsvd_page_num(a);
3006 rsvd_page_number = _rsvd_page_num_drv2halmac(drv_rsvd_num);
3007 status = api->halmac_cfg_drv_rsvd_pg_num(halmac, rsvd_page_number);
3008 if (status != HALMAC_RET_SUCCESS) {
3009 ret = -1;
3010 goto exit;
3011 }
3012 hal->drv_rsvd_page_number = _rsvd_page_num_halmac2drv(rsvd_page_number);
3013
3014 exit:
3015 #ifndef DBG_RSVD_PAGE_CFG
3016 if (drv_rsvd_num != _rsvd_page_num_halmac2drv(rsvd_page_number))
3017 #endif
3018 RTW_INFO("%s: request %d pages => halmac %d pages %s\n"
3019 , __FUNCTION__, drv_rsvd_num, _rsvd_page_num_halmac2drv(rsvd_page_number)
3020 , ret ? "fail" : "success");
3021
3022 return ret;
3023 }
3024
_debug_dlfw_fail(struct dvobj_priv * d)3025 static void _debug_dlfw_fail(struct dvobj_priv *d)
3026 {
3027 struct _ADAPTER *a;
3028 u32 addr;
3029 u32 v32, i, n;
3030 u8 data[0x100] = {0};
3031
3032
3033 a = dvobj_get_primary_adapter(d);
3034
3035 /* read 0x80[15:0], 0x10F8[31:0] once */
3036 addr = 0x80;
3037 v32 = rtw_read16(a, addr);
3038 RTW_PRINT("%s: 0x%X = 0x%04x\n", __FUNCTION__, addr, v32);
3039
3040 addr = 0x10F8;
3041 v32 = rtw_read32(a, addr);
3042 RTW_PRINT("%s: 0x%X = 0x%08x\n", __FUNCTION__, addr, v32);
3043
3044 /* read 0x10FC[31:0], 5 times */
3045 addr = 0x10FC;
3046 n = 5;
3047 for (i = 0; i < n; i++) {
3048 v32 = rtw_read32(a, addr);
3049 RTW_PRINT("%s: 0x%X = 0x%08x (%u/%u)\n",
3050 __FUNCTION__, addr, v32, i, n);
3051 }
3052
3053 /*
3054 * write 0x3A[7:0]=0x28 and 0xF6[7:0]=0x01
3055 * and then read 0xC0[31:0] 5 times
3056 */
3057 addr = 0x3A;
3058 v32 = 0x28;
3059 rtw_write8(a, addr, (u8)v32);
3060 v32 = rtw_read8(a, addr);
3061 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v32);
3062
3063 addr = 0xF6;
3064 v32 = 0x1;
3065 rtw_write8(a, addr, (u8)v32);
3066 v32 = rtw_read8(a, addr);
3067 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v32);
3068
3069 addr = 0xC0;
3070 n = 5;
3071 for (i = 0; i < n; i++) {
3072 v32 = rtw_read32(a, addr);
3073 RTW_PRINT("%s: 0x%X = 0x%08x (%u/%u)\n",
3074 __FUNCTION__, addr, v32, i, n);
3075 }
3076
3077 /* 0x00~0xFF, 0x1000~0x10FF */
3078 addr = 0;
3079 n = 0x100;
3080 for (i = 0; i < n; i+=4)
3081 *(u32*)&data[i] = cpu_to_le32(rtw_read32(a, addr+i));
3082 for (i = 0; i < n; i++) {
3083 if (i % 16 == 0)
3084 RTW_PRINT("0x%04x\t", addr+i);
3085 _RTW_PRINT("0x%02x", data[i]);
3086 if (i % 16 == 15)
3087 _RTW_PRINT("\n");
3088 else
3089 _RTW_PRINT(" ");
3090 }
3091
3092 addr = 0x1000;
3093 n = 0x100;
3094 for (i = 0; i < n; i+=4)
3095 *(u32*)&data[i] = cpu_to_le32(rtw_read32(a, addr+i));
3096 for (i = 0; i < n; i++) {
3097 if (i % 16 == 0)
3098 RTW_PRINT("0x%04x\t", addr+i);
3099 _RTW_PRINT("0x%02x", data[i]);
3100 if (i % 16 == 15)
3101 _RTW_PRINT("\n");
3102 else
3103 _RTW_PRINT(" ");
3104 }
3105
3106 /* read 0x80 after 10 secs */
3107 rtw_msleep_os(10000);
3108 addr = 0x80;
3109 v32 = rtw_read16(a, addr);
3110 RTW_PRINT("%s: 0x%X = 0x%04x (after 10 secs)\n",
3111 __FUNCTION__, addr, v32);
3112 }
3113
_enter_cpu_sleep_mode(struct dvobj_priv * d)3114 static enum halmac_ret_status _enter_cpu_sleep_mode(struct dvobj_priv *d)
3115 {
3116 struct hal_com_data *hal;
3117 struct halmac_adapter *mac;
3118 struct halmac_api *api;
3119
3120
3121 hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
3122 mac = dvobj_to_halmac(d);
3123 api = HALMAC_GET_API(mac);
3124
3125 #ifdef CONFIG_RTL8822B
3126 /* Support after firmware version 21 */
3127 if (hal->firmware_version < 21)
3128 return HALMAC_RET_NOT_SUPPORT;
3129 #elif defined(CONFIG_RTL8821C)
3130 /* Support after firmware version 13.6 or 16 */
3131 if (hal->firmware_version == 13) {
3132 if (hal->firmware_sub_version < 6)
3133 return HALMAC_RET_NOT_SUPPORT;
3134 } else if (hal->firmware_version < 16) {
3135 return HALMAC_RET_NOT_SUPPORT;
3136 }
3137 #endif
3138
3139 return api->halmac_enter_cpu_sleep_mode(mac);
3140 }
3141
3142 /*
3143 * _cpu_sleep() - Let IC CPU enter sleep mode
3144 * @d: struct dvobj_priv*
3145 * @timeout: time limit of wait, unit is ms
3146 * 0 for no limit
3147 *
3148 * Rteurn 0 for CPU in sleep mode, otherwise fail to enter sleep mode.
3149 * Error codes definition are as follow:
3150 * -1 HALMAC enter sleep return fail
3151 * -2 HALMAC get CPU mode return fail
3152 * -110 timeout
3153 */
_cpu_sleep(struct dvobj_priv * d,u32 timeout)3154 static int _cpu_sleep(struct dvobj_priv *d, u32 timeout)
3155 {
3156 struct halmac_adapter *mac;
3157 struct halmac_api *api;
3158 enum halmac_ret_status status;
3159 enum halmac_wlcpu_mode mode = HALMAC_WLCPU_UNDEFINE;
3160 systime start_t;
3161 s32 period = 0;
3162 u32 cnt = 0;
3163 int err = 0;
3164
3165
3166 mac = dvobj_to_halmac(d);
3167 api = HALMAC_GET_API(mac);
3168
3169 start_t = rtw_get_current_time();
3170
3171 status = _enter_cpu_sleep_mode(d);
3172 if (status != HALMAC_RET_SUCCESS) {
3173 if (status != HALMAC_RET_NOT_SUPPORT)
3174 err = -1;
3175 goto exit;
3176 }
3177
3178 do {
3179 cnt++;
3180
3181 mode = HALMAC_WLCPU_UNDEFINE;
3182 status = api->halmac_get_cpu_mode(mac, &mode);
3183
3184 period = rtw_get_passing_time_ms(start_t);
3185
3186 if (status != HALMAC_RET_SUCCESS) {
3187 err = -2;
3188 break;
3189 }
3190 if (mode == HALMAC_WLCPU_SLEEP)
3191 break;
3192 if (period > timeout) {
3193 err = -110;
3194 break;
3195 }
3196
3197 rtw_msleep_os(1);
3198 } while (1);
3199
3200 exit:
3201 if (err)
3202 RTW_ERR("%s: Fail to enter sleep mode! (%d, %d)\n",
3203 __FUNCTION__, status, mode);
3204
3205 RTW_INFO("%s: Cost %dms to polling %u times. (err=%d)\n",
3206 __FUNCTION__, period, cnt, err);
3207
3208 return err;
3209 }
3210
_init_trx_cfg_drv(struct dvobj_priv * d)3211 static void _init_trx_cfg_drv(struct dvobj_priv *d)
3212 {
3213 #ifdef CONFIG_PCI_HCI
3214 rtw_hal_irp_reset(dvobj_get_primary_adapter(d));
3215 #endif
3216 }
3217
3218 /*
3219 * Description:
3220 * Downlaod Firmware Flow
3221 *
3222 * Parameters:
3223 * d pointer of struct dvobj_priv
3224 * fw firmware array
3225 * fwsize firmware size
3226 * re_dl re-download firmware or not
3227 * 0: run in init hal flow, not re-download
3228 * 1: it is a stand alone operation, not in init hal flow
3229 *
3230 * Return:
3231 * 0 Success
3232 * others Fail
3233 */
download_fw(struct dvobj_priv * d,u8 * fw,u32 fwsize,u8 re_dl)3234 static int download_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize, u8 re_dl)
3235 {
3236 PHAL_DATA_TYPE hal;
3237 struct halmac_adapter *mac;
3238 struct halmac_api *api;
3239 struct halmac_fw_version fw_vesion;
3240 enum halmac_ret_status status;
3241 int err = 0;
3242
3243
3244 hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
3245 mac = dvobj_to_halmac(d);
3246 api = HALMAC_GET_API(mac);
3247
3248 if ((!fw) || (!fwsize))
3249 return -1;
3250
3251 /* 1. Driver Stop Tx */
3252 /* ToDo */
3253
3254 /* 2. Driver Check Tx FIFO is empty */
3255 err = rtw_halmac_txfifo_wait_empty(d, 2000); /* wait 2s */
3256 if (err) {
3257 err = -1;
3258 goto resume_tx;
3259 }
3260
3261 /* 3. Config MAX download size */
3262 /*
3263 * Already done in rtw_halmac_init_adapter() or
3264 * somewhere calling rtw_halmac_set_max_dl_fw_size().
3265 */
3266
3267 if (re_dl) {
3268 /* 4. Enter IC CPU sleep mode */
3269 err = _cpu_sleep(d, 2000);
3270 if (err) {
3271 RTW_ERR("%s: IC CPU fail to enter sleep mode!(%d)\n",
3272 __FUNCTION__, err);
3273 /* skip this error */
3274 err = 0;
3275 }
3276 }
3277
3278 /* 5. Download Firmware */
3279 status = api->halmac_download_firmware(mac, fw, fwsize);
3280 if (status != HALMAC_RET_SUCCESS) {
3281 RTW_ERR("%s: download firmware FAIL! status=0x%02x\n",
3282 __FUNCTION__, status);
3283 _debug_dlfw_fail(d);
3284 err = -1;
3285 goto resume_tx;
3286 }
3287
3288 /* 5.1. (Driver) Reset driver variables if needed */
3289 hal->LastHMEBoxNum = 0;
3290
3291 /* 5.2. (Driver) Get FW version */
3292 status = api->halmac_get_fw_version(mac, &fw_vesion);
3293 if (status == HALMAC_RET_SUCCESS) {
3294 hal->firmware_version = fw_vesion.version;
3295 hal->firmware_sub_version = fw_vesion.sub_version;
3296 hal->firmware_size = fwsize;
3297 }
3298
3299 resume_tx:
3300 /* 6. Driver resume TX if needed */
3301 /* ToDo */
3302
3303 if (err)
3304 goto exit;
3305
3306 if (re_dl) {
3307 enum halmac_trx_mode mode;
3308
3309 /* 7. Change reserved page size */
3310 err = _cfg_drv_rsvd_pg_num(d);
3311 if (err)
3312 return -1;
3313
3314 /* 8. Init TRX Configuration */
3315 mode = _choose_trx_mode(d);
3316 status = api->halmac_init_trx_cfg(mac, mode);
3317 if (HALMAC_RET_SUCCESS != status)
3318 return -1;
3319 _init_trx_cfg_drv(d);
3320
3321 /* 9. Config RX Aggregation */
3322 err = rtw_halmac_rx_agg_switch(d, _TRUE);
3323 if (err)
3324 return -1;
3325
3326 /* 10. Send General Info */
3327 err = _send_general_info(d);
3328 if (err)
3329 return -1;
3330 }
3331
3332 exit:
3333 return err;
3334 }
3335
init_mac_flow(struct dvobj_priv * d)3336 static int init_mac_flow(struct dvobj_priv *d)
3337 {
3338 PADAPTER p;
3339 struct hal_com_data *hal;
3340 struct halmac_adapter *halmac;
3341 struct halmac_api *api;
3342 enum halmac_drv_rsvd_pg_num rsvd_page_number;
3343 union halmac_wlan_addr hwa;
3344 enum halmac_trx_mode trx_mode;
3345 enum halmac_ret_status status;
3346 u8 drv_rsvd_num;
3347 u8 nettype;
3348 int err, err_ret = -1;
3349
3350
3351 p = dvobj_get_primary_adapter(d);
3352 hal = GET_HAL_DATA(p);
3353 halmac = dvobj_to_halmac(d);
3354 api = HALMAC_GET_API(halmac);
3355
3356 #ifdef CONFIG_SUPPORT_TRX_SHARED
3357 status = api->halmac_cfg_rxff_expand_mode(halmac,
3358 _rtw_get_trx_share_mode(p));
3359 if (status != HALMAC_RET_SUCCESS)
3360 goto out;
3361 #endif
3362
3363 #ifdef DBG_LA_MODE
3364 if (dvobj_to_regsty(d)->la_mode_en) {
3365 status = api->halmac_cfg_la_mode(halmac, HALMAC_LA_MODE_PARTIAL);
3366 if (status != HALMAC_RET_SUCCESS) {
3367 RTW_ERR("%s: Fail to enable LA mode!\n", __FUNCTION__);
3368 goto out;
3369 }
3370 RTW_PRINT("%s: Enable LA mode OK.\n", __FUNCTION__);
3371 }
3372 #endif
3373
3374 err = _cfg_drv_rsvd_pg_num(d);
3375 if (err)
3376 goto out;
3377
3378 #ifdef CONFIG_USB_HCI
3379 status = api->halmac_set_bulkout_num(halmac, d->RtNumOutPipes);
3380 if (status != HALMAC_RET_SUCCESS)
3381 goto out;
3382 #endif /* CONFIG_USB_HCI */
3383
3384 trx_mode = _choose_trx_mode(d);
3385 status = api->halmac_init_mac_cfg(halmac, trx_mode);
3386 if (status != HALMAC_RET_SUCCESS)
3387 goto out;
3388
3389 /* Driver insert flow: Sync driver setting with register */
3390 /* Sync driver RCR cache with register setting */
3391 rtw_hal_get_hwreg(dvobj_get_primary_adapter(d), HW_VAR_RCR, NULL);
3392
3393 _init_trx_cfg_drv(d);
3394 /* Driver inser flow end */
3395
3396 err = rtw_halmac_rx_agg_switch(d, _TRUE);
3397 if (err)
3398 goto out;
3399
3400 nettype = dvobj_to_regsty(d)->wireless_mode;
3401 if (is_supported_vht(nettype) == _TRUE)
3402 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_AC);
3403 else if (is_supported_ht(nettype) == _TRUE)
3404 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_N);
3405 else if (IsSupportedTxOFDM(nettype) == _TRUE)
3406 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_G);
3407 else
3408 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_B);
3409 if (status != HALMAC_RET_SUCCESS)
3410 goto out;
3411
3412 err_ret = 0;
3413 out:
3414 return err_ret;
3415 }
3416
_drv_enable_trx(struct dvobj_priv * d)3417 static int _drv_enable_trx(struct dvobj_priv *d)
3418 {
3419 struct _ADAPTER *adapter;
3420 u32 status;
3421
3422
3423 adapter = dvobj_get_primary_adapter(d);
3424 if (adapter->bup == _FALSE) {
3425 #ifdef CONFIG_NEW_NETDEV_HDL
3426 status = rtw_mi_start_drv_threads(adapter);
3427 #else
3428 status = rtw_start_drv_threads(adapter);
3429 #endif
3430 if (status == _FAIL) {
3431 RTW_ERR("%s: Start threads Failed!\n", __FUNCTION__);
3432 return -1;
3433 }
3434 }
3435
3436 rtw_intf_start(adapter);
3437
3438 return 0;
3439 }
3440
3441 /*
3442 * Notices:
3443 * Make sure
3444 * 1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
3445 * 2. HAL_DATA_TYPE.rfe_type
3446 * already ready for use before calling this function.
3447 */
_halmac_init_hal(struct dvobj_priv * d,u8 * fw,u32 fwsize)3448 static int _halmac_init_hal(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3449 {
3450 PADAPTER adapter;
3451 struct halmac_adapter *halmac;
3452 struct halmac_api *api;
3453 enum halmac_ret_status status;
3454 u32 ok;
3455 u8 fw_ok = _FALSE;
3456 int err, err_ret = -1;
3457
3458
3459 adapter = dvobj_get_primary_adapter(d);
3460 halmac = dvobj_to_halmac(d);
3461 if (!halmac)
3462 goto out;
3463 api = HALMAC_GET_API(halmac);
3464
3465 /* StatePowerOff */
3466
3467 /* SKIP: halmac_init_adapter (Already done before) */
3468
3469 /* halmac_pre_Init_system_cfg */
3470 /* halmac_mac_power_switch(on) */
3471 /* halmac_Init_system_cfg */
3472 ok = rtw_hal_power_on(adapter);
3473 if (_FAIL == ok)
3474 goto out;
3475
3476 /* StatePowerOn */
3477
3478 /* DownloadFW */
3479 if (fw && fwsize) {
3480 err = download_fw(d, fw, fwsize, 0);
3481 if (err)
3482 goto out;
3483 fw_ok = _TRUE;
3484 }
3485
3486 /* InitMACFlow */
3487 err = init_mac_flow(d);
3488 if (err)
3489 goto out;
3490
3491 /* Driver insert flow: Enable TR/RX */
3492 err = _drv_enable_trx(d);
3493 if (err)
3494 goto out;
3495
3496 /* halmac_send_general_info */
3497 if (_TRUE == fw_ok) {
3498 err = _send_general_info(d);
3499 if (err)
3500 goto out;
3501 }
3502
3503 /* Init Phy parameter-MAC */
3504 ok = rtw_hal_init_mac_register(adapter);
3505 if (_FALSE == ok)
3506 goto out;
3507
3508 /* StateMacInitialized */
3509
3510 /* halmac_cfg_drv_info */
3511 err = rtw_halmac_config_rx_info(d, HALMAC_DRV_INFO_PHY_STATUS);
3512 if (err)
3513 goto out;
3514
3515 /* halmac_set_hw_value(HALMAC_HW_EN_BB_RF) */
3516 /* Init BB, RF */
3517 ok = rtw_hal_init_phy(adapter);
3518 if (_FALSE == ok)
3519 goto out;
3520
3521 status = api->halmac_init_interface_cfg(halmac);
3522 if (status != HALMAC_RET_SUCCESS)
3523 goto out;
3524
3525 /* SKIP: halmac_verify_platform_api */
3526 /* SKIP: halmac_h2c_lb */
3527
3528 /* StateRxIdle */
3529
3530 err_ret = 0;
3531 out:
3532 return err_ret;
3533 }
3534
rtw_halmac_init_hal(struct dvobj_priv * d)3535 int rtw_halmac_init_hal(struct dvobj_priv *d)
3536 {
3537 return _halmac_init_hal(d, NULL, 0);
3538 }
3539
3540 /*
3541 * Notices:
3542 * Make sure
3543 * 1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
3544 * 2. HAL_DATA_TYPE.rfe_type
3545 * already ready for use before calling this function.
3546 */
rtw_halmac_init_hal_fw(struct dvobj_priv * d,u8 * fw,u32 fwsize)3547 int rtw_halmac_init_hal_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3548 {
3549 return _halmac_init_hal(d, fw, fwsize);
3550 }
3551
3552 /*
3553 * Notices:
3554 * Make sure
3555 * 1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
3556 * 2. HAL_DATA_TYPE.rfe_type
3557 * already ready for use before calling this function.
3558 */
rtw_halmac_init_hal_fw_file(struct dvobj_priv * d,u8 * fwpath)3559 int rtw_halmac_init_hal_fw_file(struct dvobj_priv *d, u8 *fwpath)
3560 {
3561 u8 *fw = NULL;
3562 u32 fwmaxsize = 0, size = 0;
3563 int err = 0;
3564
3565
3566 err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3567 if (err) {
3568 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3569 return -1;
3570 }
3571
3572 fw = rtw_zmalloc(fwmaxsize);
3573 if (!fw)
3574 return -1;
3575
3576 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3577 if (!size) {
3578 err = -1;
3579 goto exit;
3580 }
3581
3582 err = _halmac_init_hal(d, fw, size);
3583
3584 exit:
3585 rtw_mfree(fw, fwmaxsize);
3586 /*fw = NULL;*/
3587
3588 return err;
3589 }
3590
rtw_halmac_deinit_hal(struct dvobj_priv * d)3591 int rtw_halmac_deinit_hal(struct dvobj_priv *d)
3592 {
3593 PADAPTER adapter;
3594 struct halmac_adapter *halmac;
3595 struct halmac_api *api;
3596 enum halmac_ret_status status;
3597 int err = -1;
3598
3599
3600 adapter = dvobj_get_primary_adapter(d);
3601 halmac = dvobj_to_halmac(d);
3602 if (!halmac)
3603 goto out;
3604 api = HALMAC_GET_API(halmac);
3605
3606 status = api->halmac_deinit_interface_cfg(halmac);
3607 if (status != HALMAC_RET_SUCCESS)
3608 goto out;
3609
3610 rtw_hal_power_off(adapter);
3611
3612 err = 0;
3613 out:
3614 return err;
3615 }
3616
rtw_halmac_self_verify(struct dvobj_priv * d)3617 int rtw_halmac_self_verify(struct dvobj_priv *d)
3618 {
3619 struct halmac_adapter *mac;
3620 struct halmac_api *api;
3621 enum halmac_ret_status status;
3622 int err = -1;
3623
3624
3625 mac = dvobj_to_halmac(d);
3626 api = HALMAC_GET_API(mac);
3627
3628 status = api->halmac_verify_platform_api(mac);
3629 if (status != HALMAC_RET_SUCCESS)
3630 goto out;
3631
3632 status = api->halmac_h2c_lb(mac);
3633 if (status != HALMAC_RET_SUCCESS)
3634 goto out;
3635
3636 err = 0;
3637 out:
3638 return err;
3639 }
3640
rtw_halmac_txfifo_is_empty(struct dvobj_priv * d)3641 static u8 rtw_halmac_txfifo_is_empty(struct dvobj_priv *d)
3642 {
3643 struct halmac_adapter *mac;
3644 struct halmac_api *api;
3645 enum halmac_ret_status status;
3646 u32 chk_num = 10;
3647 u8 rst = _FALSE;
3648
3649
3650 mac = dvobj_to_halmac(d);
3651 api = HALMAC_GET_API(mac);
3652
3653 status = api->halmac_txfifo_is_empty(mac, chk_num);
3654 if (status == HALMAC_RET_SUCCESS)
3655 rst = _TRUE;
3656
3657 return rst;
3658 }
3659
3660 /**
3661 * rtw_halmac_txfifo_wait_empty() - Wait TX FIFO to be emtpy
3662 * @d: struct dvobj_priv*
3663 * @timeout: time limit of wait, unit is ms
3664 * 0 for no limit
3665 *
3666 * Wait TX FIFO to be emtpy.
3667 *
3668 * Rteurn 0 for TX FIFO is empty, otherwise not empty.
3669 */
rtw_halmac_txfifo_wait_empty(struct dvobj_priv * d,u32 timeout)3670 int rtw_halmac_txfifo_wait_empty(struct dvobj_priv *d, u32 timeout)
3671 {
3672 struct _ADAPTER *a;
3673 u8 empty = _FALSE;
3674 u32 cnt = 0;
3675 systime start_time = 0;
3676 u32 pass_time; /* ms */
3677
3678
3679 a = dvobj_get_primary_adapter(d);
3680 start_time = rtw_get_current_time();
3681
3682 do {
3683 cnt++;
3684 empty = rtw_halmac_txfifo_is_empty(d);
3685 if (empty == _TRUE)
3686 break;
3687
3688 if (timeout) {
3689 pass_time = rtw_get_passing_time_ms(start_time);
3690 if (pass_time > timeout)
3691 break;
3692 }
3693 if (RTW_CANNOT_IO(a)) {
3694 RTW_WARN("%s: Interrupted by I/O forbiden!\n", __FUNCTION__);
3695 break;
3696 }
3697
3698 rtw_msleep_os(2);
3699 } while (1);
3700
3701 if (empty == _FALSE) {
3702 #ifdef CONFIG_RTW_DEBUG
3703 u16 dbg_reg[] = {0x210, 0x230, 0x234, 0x238, 0x23C, 0x240,
3704 0x418, 0x10FC, 0x10F8, 0x11F4, 0x11F8};
3705 u8 i;
3706 u32 val;
3707
3708 if (!RTW_CANNOT_IO(a)) {
3709 for (i = 0; i < ARRAY_SIZE(dbg_reg); i++) {
3710 val = rtw_read32(a, dbg_reg[i]);
3711 RTW_ERR("REG_%X:0x%08x\n", dbg_reg[i], val);
3712 }
3713 }
3714 #endif /* CONFIG_RTW_DEBUG */
3715
3716 RTW_ERR("%s: Fail to wait txfifo empty!(cnt=%d)\n",
3717 __FUNCTION__, cnt);
3718 return -1;
3719 }
3720
3721 return 0;
3722 }
3723
_fw_mem_drv2halmac(enum fw_mem mem,u8 tx_stop)3724 static enum halmac_dlfw_mem _fw_mem_drv2halmac(enum fw_mem mem, u8 tx_stop)
3725 {
3726 enum halmac_dlfw_mem mem_halmac = HALMAC_DLFW_MEM_UNDEFINE;
3727
3728
3729 switch (mem) {
3730 case FW_EMEM:
3731 if (tx_stop == _FALSE)
3732 mem_halmac = HALMAC_DLFW_MEM_EMEM_RSVD_PG;
3733 else
3734 mem_halmac = HALMAC_DLFW_MEM_EMEM;
3735 break;
3736
3737 case FW_IMEM:
3738 case FW_DMEM:
3739 mem_halmac = HALMAC_DLFW_MEM_UNDEFINE;
3740 break;
3741 }
3742
3743 return mem_halmac;
3744 }
3745
rtw_halmac_dlfw_mem(struct dvobj_priv * d,u8 * fw,u32 fwsize,enum fw_mem mem)3746 int rtw_halmac_dlfw_mem(struct dvobj_priv *d, u8 *fw, u32 fwsize, enum fw_mem mem)
3747 {
3748 struct halmac_adapter *mac;
3749 struct halmac_api *api;
3750 enum halmac_ret_status status;
3751 enum halmac_dlfw_mem dlfw_mem;
3752 u8 tx_stop = _FALSE;
3753 u32 chk_timeout = 2000; /* unit: ms */
3754 int err = 0;
3755
3756
3757 mac = dvobj_to_halmac(d);
3758 api = HALMAC_GET_API(mac);
3759
3760 if ((!fw) || (!fwsize))
3761 return -1;
3762
3763 #ifndef RTW_HALMAC_DLFW_MEM_NO_STOP_TX
3764 /* 1. Driver Stop Tx */
3765 /* ToDo */
3766
3767 /* 2. Driver Check Tx FIFO is empty */
3768 err = rtw_halmac_txfifo_wait_empty(d, chk_timeout);
3769 if (err)
3770 tx_stop = _FALSE;
3771 else
3772 tx_stop = _TRUE;
3773 #endif /* !RTW_HALMAC_DLFW_MEM_NO_STOP_TX */
3774
3775 /* 3. Download Firmware MEM */
3776 dlfw_mem = _fw_mem_drv2halmac(mem, tx_stop);
3777 if (dlfw_mem == HALMAC_DLFW_MEM_UNDEFINE) {
3778 err = -1;
3779 goto resume_tx;
3780 }
3781 status = api->halmac_free_download_firmware(mac, dlfw_mem, fw, fwsize);
3782 if (status != HALMAC_RET_SUCCESS) {
3783 RTW_ERR("%s: halmac_free_download_firmware fail(err=0x%x)\n",
3784 __FUNCTION__, status);
3785 err = -1;
3786 goto resume_tx;
3787 }
3788
3789 resume_tx:
3790 #ifndef RTW_HALMAC_DLFW_MEM_NO_STOP_TX
3791 /* 4. Driver resume TX if needed */
3792 /* ToDo */
3793 #endif /* !RTW_HALMAC_DLFW_MEM_NO_STOP_TX */
3794
3795 return err;
3796 }
3797
rtw_halmac_dlfw_mem_from_file(struct dvobj_priv * d,u8 * fwpath,enum fw_mem mem)3798 int rtw_halmac_dlfw_mem_from_file(struct dvobj_priv *d, u8 *fwpath, enum fw_mem mem)
3799 {
3800 u8 *fw = NULL;
3801 u32 fwmaxsize = 0, size = 0;
3802 int err = 0;
3803
3804
3805 err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3806 if (err) {
3807 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3808 return -1;
3809 }
3810
3811 fw = rtw_zmalloc(fwmaxsize);
3812 if (!fw)
3813 return -1;
3814
3815 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3816 if (size)
3817 err = rtw_halmac_dlfw_mem(d, fw, size, mem);
3818 else
3819 err = -1;
3820
3821 rtw_mfree(fw, fwmaxsize);
3822 /*fw = NULL;*/
3823
3824 return err;
3825 }
3826
3827 /*
3828 * Return:
3829 * 0 Success
3830 * -22 Invalid arguemnt
3831 */
rtw_halmac_dlfw(struct dvobj_priv * d,u8 * fw,u32 fwsize)3832 int rtw_halmac_dlfw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3833 {
3834 PADAPTER adapter;
3835 enum halmac_ret_status status;
3836 u32 ok;
3837 int err, err_ret = -1;
3838
3839
3840 if (!fw || !fwsize)
3841 return -22;
3842
3843 adapter = dvobj_get_primary_adapter(d);
3844
3845 /* re-download firmware */
3846 if (rtw_is_hw_init_completed(adapter))
3847 return download_fw(d, fw, fwsize, 1);
3848
3849 /* Download firmware before hal init */
3850 /* Power on, download firmware and init mac */
3851 ok = rtw_hal_power_on(adapter);
3852 if (_FAIL == ok)
3853 goto out;
3854
3855 err = download_fw(d, fw, fwsize, 0);
3856 if (err) {
3857 err_ret = err;
3858 goto out;
3859 }
3860
3861 err = init_mac_flow(d);
3862 if (err)
3863 goto out;
3864
3865 err = _send_general_info(d);
3866 if (err)
3867 goto out;
3868
3869 err_ret = 0;
3870
3871 out:
3872 return err_ret;
3873 }
3874
rtw_halmac_dlfw_from_file(struct dvobj_priv * d,u8 * fwpath)3875 int rtw_halmac_dlfw_from_file(struct dvobj_priv *d, u8 *fwpath)
3876 {
3877 u8 *fw = NULL;
3878 u32 fwmaxsize = 0, size = 0;
3879 int err = 0;
3880
3881
3882 err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3883 if (err) {
3884 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3885 return -1;
3886 }
3887
3888 fw = rtw_zmalloc(fwmaxsize);
3889 if (!fw)
3890 return -1;
3891
3892 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3893 if (size)
3894 err = rtw_halmac_dlfw(d, fw, size);
3895 else
3896 err = -1;
3897
3898 rtw_mfree(fw, fwmaxsize);
3899 /*fw = NULL;*/
3900
3901 return err;
3902 }
3903
3904 /*
3905 * Description:
3906 * Power on/off BB/RF domain.
3907 *
3908 * Parameters:
3909 * enable _TRUE/_FALSE for power on/off
3910 *
3911 * Return:
3912 * 0 Success
3913 * others Fail
3914 */
rtw_halmac_phy_power_switch(struct dvobj_priv * d,u8 enable)3915 int rtw_halmac_phy_power_switch(struct dvobj_priv *d, u8 enable)
3916 {
3917 PADAPTER adapter;
3918 struct halmac_adapter *halmac;
3919 struct halmac_api *api;
3920 enum halmac_ret_status status;
3921 u8 on;
3922
3923
3924 adapter = dvobj_get_primary_adapter(d);
3925 halmac = dvobj_to_halmac(d);
3926 if (!halmac)
3927 return -1;
3928 api = HALMAC_GET_API(halmac);
3929 on = (enable == _TRUE) ? 1 : 0;
3930
3931 status = api->halmac_set_hw_value(halmac, HALMAC_HW_EN_BB_RF, &on);
3932 if (status != HALMAC_RET_SUCCESS)
3933 return -1;
3934
3935 return 0;
3936 }
3937
_is_fw_read_cmd_down(PADAPTER adapter,u8 msgbox_num)3938 static u8 _is_fw_read_cmd_down(PADAPTER adapter, u8 msgbox_num)
3939 {
3940 u8 read_down = _FALSE;
3941 int retry_cnts = 100;
3942 u8 valid;
3943
3944 do {
3945 valid = rtw_read8(adapter, REG_HMETFR) & BIT(msgbox_num);
3946 if (0 == valid)
3947 read_down = _TRUE;
3948 else
3949 rtw_msleep_os(1);
3950 } while ((!read_down) && (retry_cnts--));
3951
3952 if (_FALSE == read_down)
3953 RTW_WARN("%s, reg_1cc(%x), msg_box(%d)...\n", __func__, rtw_read8(adapter, REG_HMETFR), msgbox_num);
3954
3955 return read_down;
3956 }
3957
3958 /**
3959 * rtw_halmac_send_h2c() - Send H2C to firmware
3960 * @d: struct dvobj_priv*
3961 * @h2c: H2C data buffer, suppose to be 8 bytes
3962 *
3963 * Send H2C to firmware by message box register(0x1D0~0x1D3 & 0x1F0~0x1F3).
3964 *
3965 * Assume firmware be ready to accept H2C here, please check
3966 * (hal->bFWReady == _TRUE) before call this function or make sure firmware is
3967 * ready.
3968 *
3969 * Return: 0 if process OK, otherwise fail to send this H2C.
3970 */
rtw_halmac_send_h2c(struct dvobj_priv * d,u8 * h2c)3971 int rtw_halmac_send_h2c(struct dvobj_priv *d, u8 *h2c)
3972 {
3973 PADAPTER adapter = dvobj_get_primary_adapter(d);
3974 PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
3975 u8 h2c_box_num = 0;
3976 u32 msgbox_addr = 0;
3977 u32 msgbox_ex_addr = 0;
3978 u32 h2c_cmd = 0;
3979 u32 h2c_cmd_ex = 0;
3980 int err = -1;
3981
3982
3983 if (!h2c) {
3984 RTW_WARN("%s: pbuf is NULL\n", __FUNCTION__);
3985 return err;
3986 }
3987
3988 if (rtw_is_surprise_removed(adapter)) {
3989 RTW_WARN("%s: surprise removed\n", __FUNCTION__);
3990 return err;
3991 }
3992
3993 _enter_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
3994
3995 /* pay attention to if race condition happened in H2C cmd setting */
3996 h2c_box_num = hal->LastHMEBoxNum;
3997
3998 if (!_is_fw_read_cmd_down(adapter, h2c_box_num)) {
3999 RTW_WARN(" fw read cmd failed...\n");
4000 #ifdef DBG_CONFIG_ERROR_DETECT
4001 hal->srestpriv.self_dect_fw = _TRUE;
4002 hal->srestpriv.self_dect_fw_cnt++;
4003 #endif /* DBG_CONFIG_ERROR_DETECT */
4004 goto exit;
4005 }
4006
4007 /* Write Ext command (byte 4~7) */
4008 msgbox_ex_addr = REG_HMEBOX_E0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
4009 _rtw_memcpy((u8 *)(&h2c_cmd_ex), h2c + 4, EX_MESSAGE_BOX_SIZE);
4010 h2c_cmd_ex = le32_to_cpu(h2c_cmd_ex);
4011 rtw_write32(adapter, msgbox_ex_addr, h2c_cmd_ex);
4012
4013 /* Write command (byte 0~3) */
4014 msgbox_addr = REG_HMEBOX0 + (h2c_box_num * MESSAGE_BOX_SIZE);
4015 _rtw_memcpy((u8 *)(&h2c_cmd), h2c, 4);
4016 h2c_cmd = le32_to_cpu(h2c_cmd);
4017 rtw_write32(adapter, msgbox_addr, h2c_cmd);
4018
4019 /* update last msg box number */
4020 hal->LastHMEBoxNum = (h2c_box_num + 1) % MAX_H2C_BOX_NUMS;
4021 err = 0;
4022
4023 #ifdef DBG_H2C_CONTENT
4024 RTW_INFO_DUMP("[H2C] - ", h2c, RTW_HALMAC_H2C_MAX_SIZE);
4025 #endif
4026 exit:
4027 _exit_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
4028 return err;
4029 }
4030
4031 /**
4032 * rtw_halmac_c2h_handle() - Handle C2H for HALMAC
4033 * @d: struct dvobj_priv*
4034 * @c2h: Full C2H packet, including RX description and payload
4035 * @size: Size(byte) of c2h
4036 *
4037 * Send C2H packet to HALMAC to process C2H packets, and the expected C2H ID is
4038 * 0xFF. This function won't have any I/O, so caller doesn't have to call it in
4039 * I/O safe place(ex. command thread).
4040 *
4041 * Please sure doesn't call this function in the same thread as someone is
4042 * waiting HALMAC C2H ack, otherwise there is a deadlock happen.
4043 *
4044 * Return: 0 if process OK, otherwise no action for this C2H.
4045 */
rtw_halmac_c2h_handle(struct dvobj_priv * d,u8 * c2h,u32 size)4046 int rtw_halmac_c2h_handle(struct dvobj_priv *d, u8 *c2h, u32 size)
4047 {
4048 struct halmac_adapter *mac;
4049 struct halmac_api *api;
4050 enum halmac_ret_status status;
4051
4052
4053 mac = dvobj_to_halmac(d);
4054 api = HALMAC_GET_API(mac);
4055
4056 status = api->halmac_get_c2h_info(mac, c2h, size);
4057 if (HALMAC_RET_SUCCESS != status)
4058 return -1;
4059
4060 return 0;
4061 }
4062
rtw_halmac_get_available_efuse_size(struct dvobj_priv * d,u32 * size)4063 int rtw_halmac_get_available_efuse_size(struct dvobj_priv *d, u32 *size)
4064 {
4065 struct halmac_adapter *mac;
4066 struct halmac_api *api;
4067 enum halmac_ret_status status;
4068 u32 val;
4069
4070
4071 mac = dvobj_to_halmac(d);
4072 api = HALMAC_GET_API(mac);
4073
4074 status = api->halmac_get_efuse_available_size(mac, &val);
4075 if (HALMAC_RET_SUCCESS != status)
4076 return -1;
4077
4078 *size = val;
4079 return 0;
4080 }
4081
rtw_halmac_get_physical_efuse_size(struct dvobj_priv * d,u32 * size)4082 int rtw_halmac_get_physical_efuse_size(struct dvobj_priv *d, u32 *size)
4083 {
4084 struct halmac_adapter *mac;
4085 struct halmac_api *api;
4086 enum halmac_ret_status status;
4087 u32 val;
4088
4089
4090 mac = dvobj_to_halmac(d);
4091 api = HALMAC_GET_API(mac);
4092
4093 status = api->halmac_get_efuse_size(mac, &val);
4094 if (HALMAC_RET_SUCCESS != status)
4095 return -1;
4096
4097 *size = val;
4098 return 0;
4099 }
4100
rtw_halmac_read_physical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size)4101 int rtw_halmac_read_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
4102 {
4103 struct halmac_adapter *mac;
4104 struct halmac_api *api;
4105 enum halmac_ret_status status;
4106 enum halmac_feature_id id;
4107 int ret;
4108
4109
4110 mac = dvobj_to_halmac(d);
4111 api = HALMAC_GET_API(mac);
4112 id = HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE;
4113
4114 ret = init_halmac_event(d, id, map, size);
4115 if (ret)
4116 return -1;
4117
4118 status = api->halmac_dump_efuse_map(mac, HALMAC_EFUSE_R_DRV);
4119 if (HALMAC_RET_SUCCESS != status) {
4120 free_halmac_event(d, id);
4121 return -1;
4122 }
4123
4124 ret = wait_halmac_event(d, id);
4125 if (ret)
4126 return -1;
4127
4128 return 0;
4129 }
4130
rtw_halmac_read_physical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4131 int rtw_halmac_read_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4132 {
4133 struct halmac_adapter *mac;
4134 struct halmac_api *api;
4135 enum halmac_ret_status status;
4136 u8 v;
4137 u32 i;
4138 u8 *efuse = NULL;
4139 u32 size = 0;
4140 int err = 0;
4141
4142
4143 mac = dvobj_to_halmac(d);
4144 api = HALMAC_GET_API(mac);
4145
4146 if (api->halmac_read_efuse) {
4147 for (i = 0; i < cnt; i++) {
4148 status = api->halmac_read_efuse(mac, offset + i, &v);
4149 if (HALMAC_RET_SUCCESS != status)
4150 return -1;
4151 data[i] = v;
4152 }
4153 } else {
4154 err = rtw_halmac_get_physical_efuse_size(d, &size);
4155 if (err)
4156 return -1;
4157
4158 efuse = rtw_zmalloc(size);
4159 if (!efuse)
4160 return -1;
4161
4162 err = rtw_halmac_read_physical_efuse_map(d, efuse, size);
4163 if (err)
4164 err = -1;
4165 else
4166 _rtw_memcpy(data, efuse + offset, cnt);
4167
4168 rtw_mfree(efuse, size);
4169 }
4170
4171 return err;
4172 }
4173
rtw_halmac_write_physical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4174 int rtw_halmac_write_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4175 {
4176 struct halmac_adapter *mac;
4177 struct halmac_api *api;
4178 enum halmac_ret_status status;
4179 u32 i;
4180
4181
4182 mac = dvobj_to_halmac(d);
4183 api = HALMAC_GET_API(mac);
4184
4185 if (api->halmac_write_efuse == NULL)
4186 return -1;
4187
4188 for (i = 0; i < cnt; i++) {
4189 status = api->halmac_write_efuse(mac, offset + i, data[i]);
4190 if (HALMAC_RET_SUCCESS != status)
4191 return -1;
4192 }
4193
4194 return 0;
4195 }
4196
rtw_halmac_get_logical_efuse_size(struct dvobj_priv * d,u32 * size)4197 int rtw_halmac_get_logical_efuse_size(struct dvobj_priv *d, u32 *size)
4198 {
4199 struct halmac_adapter *mac;
4200 struct halmac_api *api;
4201 enum halmac_ret_status status;
4202 u32 val;
4203
4204
4205 mac = dvobj_to_halmac(d);
4206 api = HALMAC_GET_API(mac);
4207
4208 status = api->halmac_get_logical_efuse_size(mac, &val);
4209 if (HALMAC_RET_SUCCESS != status)
4210 return -1;
4211
4212 *size = val;
4213 return 0;
4214 }
4215
rtw_halmac_read_logical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size,u8 * maskmap,u32 masksize)4216 int rtw_halmac_read_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
4217 {
4218 struct halmac_adapter *mac;
4219 struct halmac_api *api;
4220 enum halmac_ret_status status;
4221 enum halmac_feature_id id;
4222 int ret;
4223
4224
4225 mac = dvobj_to_halmac(d);
4226 api = HALMAC_GET_API(mac);
4227 id = HALMAC_FEATURE_DUMP_LOGICAL_EFUSE;
4228
4229 ret = init_halmac_event(d, id, map, size);
4230 if (ret)
4231 return -1;
4232
4233 status = api->halmac_dump_logical_efuse_map(mac, HALMAC_EFUSE_R_DRV);
4234 if (HALMAC_RET_SUCCESS != status) {
4235 free_halmac_event(d, id);
4236 return -1;
4237 }
4238
4239 ret = wait_halmac_event(d, id);
4240 if (ret)
4241 return -1;
4242
4243 if (maskmap && masksize) {
4244 struct halmac_pg_efuse_info pginfo;
4245
4246 pginfo.efuse_map = map;
4247 pginfo.efuse_map_size = size;
4248 pginfo.efuse_mask = maskmap;
4249 pginfo.efuse_mask_size = masksize;
4250
4251 status = api->halmac_mask_logical_efuse(mac, &pginfo);
4252 if (status != HALMAC_RET_SUCCESS)
4253 RTW_WARN("%s: mask logical efuse FAIL!\n", __FUNCTION__);
4254 }
4255
4256 return 0;
4257 }
4258
rtw_halmac_write_logical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size,u8 * maskmap,u32 masksize)4259 int rtw_halmac_write_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
4260 {
4261 struct halmac_adapter *mac;
4262 struct halmac_api *api;
4263 struct halmac_pg_efuse_info pginfo;
4264 enum halmac_ret_status status;
4265
4266
4267 mac = dvobj_to_halmac(d);
4268 api = HALMAC_GET_API(mac);
4269
4270 pginfo.efuse_map = map;
4271 pginfo.efuse_map_size = size;
4272 pginfo.efuse_mask = maskmap;
4273 pginfo.efuse_mask_size = masksize;
4274
4275 status = api->halmac_pg_efuse_by_map(mac, &pginfo, HALMAC_EFUSE_R_AUTO);
4276 if (HALMAC_RET_SUCCESS != status)
4277 return -1;
4278
4279 return 0;
4280 }
4281
rtw_halmac_read_logical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4282 int rtw_halmac_read_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4283 {
4284 struct halmac_adapter *mac;
4285 struct halmac_api *api;
4286 enum halmac_ret_status status;
4287 u8 v;
4288 u32 i;
4289
4290
4291 mac = dvobj_to_halmac(d);
4292 api = HALMAC_GET_API(mac);
4293
4294 for (i = 0; i < cnt; i++) {
4295 status = api->halmac_read_logical_efuse(mac, offset + i, &v);
4296 if (HALMAC_RET_SUCCESS != status)
4297 return -1;
4298 data[i] = v;
4299 }
4300
4301 return 0;
4302 }
4303
rtw_halmac_write_logical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4304 int rtw_halmac_write_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4305 {
4306 struct halmac_adapter *mac;
4307 struct halmac_api *api;
4308 enum halmac_ret_status status;
4309 u32 i;
4310
4311
4312 mac = dvobj_to_halmac(d);
4313 api = HALMAC_GET_API(mac);
4314
4315 for (i = 0; i < cnt; i++) {
4316 status = api->halmac_write_logical_efuse(mac, offset + i, data[i]);
4317 if (HALMAC_RET_SUCCESS != status)
4318 return -1;
4319 }
4320
4321 return 0;
4322 }
4323
rtw_halmac_write_bt_physical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4324 int rtw_halmac_write_bt_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4325 {
4326 struct halmac_adapter *mac;
4327 struct halmac_api *api;
4328 enum halmac_ret_status status;
4329 u32 i;
4330 u8 bank = 1;
4331
4332
4333 mac = dvobj_to_halmac(d);
4334 api = HALMAC_GET_API(mac);
4335
4336 for (i = 0; i < cnt; i++) {
4337 status = api->halmac_write_efuse_bt(mac, offset + i, data[i], bank);
4338 if (HALMAC_RET_SUCCESS != status) {
4339 printk("%s: halmac_write_efuse_bt status = %d\n", __FUNCTION__, status);
4340 return -1;
4341 }
4342 }
4343 printk("%s: halmac_write_efuse_bt status = HALMAC_RET_SUCCESS %d\n", __FUNCTION__, status);
4344 return 0;
4345 }
4346
4347
rtw_halmac_read_bt_physical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size)4348 int rtw_halmac_read_bt_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
4349 {
4350 struct halmac_adapter *mac;
4351 struct halmac_api *api;
4352 enum halmac_ret_status status;
4353 int bank = 1;
4354
4355
4356 mac = dvobj_to_halmac(d);
4357 api = HALMAC_GET_API(mac);
4358
4359 status = api->halmac_dump_efuse_map_bt(mac, bank, size, map);
4360 if (HALMAC_RET_SUCCESS != status) {
4361 printk("%s: halmac_dump_efuse_map_bt fail!\n", __FUNCTION__);
4362 return -1;
4363 }
4364
4365 printk("%s: OK!\n", __FUNCTION__);
4366
4367 return 0;
4368 }
4369
_fifo_sel_drv2halmac(u8 fifo_sel)4370 static enum hal_fifo_sel _fifo_sel_drv2halmac(u8 fifo_sel)
4371 {
4372 switch (fifo_sel) {
4373 case 0:
4374 return HAL_FIFO_SEL_TX;
4375 case 1:
4376 return HAL_FIFO_SEL_RX;
4377 case 2:
4378 return HAL_FIFO_SEL_RSVD_PAGE;
4379 case 3:
4380 return HAL_FIFO_SEL_REPORT;
4381 case 4:
4382 return HAL_FIFO_SEL_LLT;
4383 case 5:
4384 return HAL_FIFO_SEL_RXBUF_FW;
4385 }
4386
4387 return HAL_FIFO_SEL_RSVD_PAGE;
4388 }
4389
4390 /*#define CONFIG_HALMAC_FIFO_DUMP*/
rtw_halmac_dump_fifo(struct dvobj_priv * d,u8 fifo_sel,u32 addr,u32 size,u8 * buffer)4391 int rtw_halmac_dump_fifo(struct dvobj_priv *d, u8 fifo_sel, u32 addr, u32 size, u8 *buffer)
4392 {
4393 struct halmac_adapter *mac;
4394 struct halmac_api *api;
4395 enum hal_fifo_sel halmac_fifo_sel;
4396 enum halmac_ret_status status;
4397 u8 *pfifo_map = NULL;
4398 u32 fifo_size = 0;
4399 s8 ret = 0;/* 0:success, -1:error */
4400 u8 mem_created = _FALSE;
4401
4402
4403 mac = dvobj_to_halmac(d);
4404 api = HALMAC_GET_API(mac);
4405
4406 if ((size != 0) && (buffer == NULL))
4407 return -1;
4408
4409 halmac_fifo_sel = _fifo_sel_drv2halmac(fifo_sel);
4410
4411 if ((size) && (buffer)) {
4412 pfifo_map = buffer;
4413 fifo_size = size;
4414 } else {
4415 fifo_size = api->halmac_get_fifo_size(mac, halmac_fifo_sel);
4416
4417 if (fifo_size)
4418 pfifo_map = rtw_zvmalloc(fifo_size);
4419 if (pfifo_map == NULL)
4420 return -1;
4421 mem_created = _TRUE;
4422 }
4423
4424 status = api->halmac_dump_fifo(mac, halmac_fifo_sel, addr, fifo_size, pfifo_map);
4425 if (HALMAC_RET_SUCCESS != status) {
4426 ret = -1;
4427 goto _exit;
4428 }
4429
4430 #ifdef CONFIG_HALMAC_FIFO_DUMP
4431 {
4432 static const char * const fifo_sel_str[] = {
4433 "TX", "RX", "RSVD_PAGE", "REPORT", "LLT", "RXBUF_FW"
4434 };
4435
4436 RTW_INFO("%s FIFO DUMP [start_addr:0x%04x , size:%d]\n", fifo_sel_str[halmac_fifo_sel], addr, fifo_size);
4437 RTW_INFO_DUMP("\n", pfifo_map, fifo_size);
4438 RTW_INFO(" ==================================================\n");
4439 }
4440 #endif /* CONFIG_HALMAC_FIFO_DUMP */
4441
4442 _exit:
4443 if ((mem_created == _TRUE) && pfifo_map)
4444 rtw_vmfree(pfifo_map, fifo_size);
4445
4446 return ret;
4447 }
4448
4449 /*
4450 * rtw_halmac_rx_agg_switch() - Switch RX aggregation function and setting
4451 * @d struct dvobj_priv *
4452 * @enable _FALSE/_TRUE for disable/enable RX aggregation function
4453 *
4454 * This function could help to on/off bus RX aggregation function, and is only
4455 * useful for SDIO and USB interface. Although only "enable" flag is brough in,
4456 * some setting would be taken from other places, and they are from:
4457 * [DMA aggregation]
4458 * struct hal_com_data.rxagg_dma_size
4459 * struct hal_com_data.rxagg_dma_timeout
4460 * [USB aggregation] (only use for USB interface)
4461 * struct hal_com_data.rxagg_usb_size
4462 * struct hal_com_data.rxagg_usb_timeout
4463 * If above values of size and timeout are both 0 means driver would not
4464 * control the threshold setting and leave it to HALMAC handle.
4465 *
4466 * From HALMAC V1_04_04, driver force the size threshold be hard limit, and the
4467 * rx size can not exceed the setting.
4468 *
4469 * Return 0 for success, otherwise fail.
4470 */
rtw_halmac_rx_agg_switch(struct dvobj_priv * d,u8 enable)4471 int rtw_halmac_rx_agg_switch(struct dvobj_priv *d, u8 enable)
4472 {
4473 struct _ADAPTER *adapter;
4474 struct hal_com_data *hal;
4475 struct halmac_adapter *halmac;
4476 struct halmac_api *api;
4477 struct halmac_rxagg_cfg rxaggcfg;
4478 enum halmac_ret_status status;
4479
4480
4481 adapter = dvobj_get_primary_adapter(d);
4482 hal = GET_HAL_DATA(adapter);
4483 halmac = dvobj_to_halmac(d);
4484 api = HALMAC_GET_API(halmac);
4485 _rtw_memset((void *)&rxaggcfg, 0, sizeof(rxaggcfg));
4486 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
4487 /*
4488 * Always enable size limit to avoid rx size exceed
4489 * driver defined size.
4490 */
4491 rxaggcfg.threshold.size_limit_en = 1;
4492
4493 #ifdef RTW_RX_AGGREGATION
4494 if (_TRUE == enable) {
4495 #ifdef CONFIG_SDIO_HCI
4496 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
4497 rxaggcfg.threshold.drv_define = 0;
4498 if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
4499 rxaggcfg.threshold.drv_define = 1;
4500 rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
4501 rxaggcfg.threshold.size = hal->rxagg_dma_size;
4502 RTW_INFO("%s: RX aggregation threshold: "
4503 "timeout=%u size=%u\n",
4504 __FUNCTION__,
4505 hal->rxagg_dma_timeout,
4506 hal->rxagg_dma_size);
4507 }
4508 #elif defined(CONFIG_USB_HCI)
4509 switch (hal->rxagg_mode) {
4510 case RX_AGG_DISABLE:
4511 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
4512 break;
4513
4514 case RX_AGG_DMA:
4515 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
4516 if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
4517 rxaggcfg.threshold.drv_define = 1;
4518 rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
4519 rxaggcfg.threshold.size = hal->rxagg_dma_size;
4520 }
4521 break;
4522
4523 case RX_AGG_USB:
4524 case RX_AGG_MIX:
4525 rxaggcfg.mode = HALMAC_RX_AGG_MODE_USB;
4526 if (hal->rxagg_usb_size || hal->rxagg_usb_timeout) {
4527 rxaggcfg.threshold.drv_define = 1;
4528 rxaggcfg.threshold.timeout = hal->rxagg_usb_timeout;
4529 rxaggcfg.threshold.size = hal->rxagg_usb_size;
4530 }
4531 break;
4532 }
4533 #endif /* CONFIG_USB_HCI */
4534 }
4535 #endif /* RTW_RX_AGGREGATION */
4536
4537 status = api->halmac_cfg_rx_aggregation(halmac, &rxaggcfg);
4538 if (status != HALMAC_RET_SUCCESS)
4539 return -1;
4540
4541 return 0;
4542 }
4543
rtw_halmac_download_rsvd_page(struct dvobj_priv * dvobj,u8 pg_offset,u8 * pbuf,u32 size)4544 int rtw_halmac_download_rsvd_page(struct dvobj_priv *dvobj, u8 pg_offset, u8 *pbuf, u32 size)
4545 {
4546 enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4547 struct halmac_adapter *halmac = dvobj_to_halmac(dvobj);
4548 struct halmac_api *api = HALMAC_GET_API(halmac);
4549
4550 status = api->halmac_dl_drv_rsvd_page(halmac, pg_offset, pbuf, size);
4551 if (status != HALMAC_RET_SUCCESS)
4552 return -1;
4553
4554 return 0;
4555 }
4556
4557 /*
4558 * Description
4559 * Fill following spec info from HALMAC API:
4560 * sec_cam_ent_num
4561 *
4562 * Return
4563 * 0 Success
4564 * others Fail
4565 */
rtw_halmac_fill_hal_spec(struct dvobj_priv * dvobj,struct hal_spec_t * spec)4566 int rtw_halmac_fill_hal_spec(struct dvobj_priv *dvobj, struct hal_spec_t *spec)
4567 {
4568 enum halmac_ret_status status;
4569 struct halmac_adapter *halmac;
4570 struct halmac_api *api;
4571 u8 cam = 0; /* Security Cam Entry Number */
4572
4573
4574 halmac = dvobj_to_halmac(dvobj);
4575 api = HALMAC_GET_API(halmac);
4576
4577 /* Prepare data from HALMAC */
4578 status = api->halmac_get_hw_value(halmac, HALMAC_HW_CAM_ENTRY_NUM, &cam);
4579 if (status != HALMAC_RET_SUCCESS)
4580 return -1;
4581
4582 /* Fill data to hal_spec_t */
4583 spec->sec_cam_ent_num = cam;
4584
4585 return 0;
4586 }
4587
rtw_halmac_p2pps(struct dvobj_priv * dvobj,struct hal_p2p_ps_para * pp2p_ps_para)4588 int rtw_halmac_p2pps(struct dvobj_priv *dvobj, struct hal_p2p_ps_para *pp2p_ps_para)
4589 {
4590 enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4591 struct halmac_adapter *halmac = dvobj_to_halmac(dvobj);
4592 struct halmac_api *api = HALMAC_GET_API(halmac);
4593 struct halmac_p2pps halmac_p2p_ps;
4594
4595 (&halmac_p2p_ps)->offload_en = pp2p_ps_para->offload_en;
4596 (&halmac_p2p_ps)->role = pp2p_ps_para->role;
4597 (&halmac_p2p_ps)->ctwindow_en = pp2p_ps_para->ctwindow_en;
4598 (&halmac_p2p_ps)->noa_en = pp2p_ps_para->noa_en;
4599 (&halmac_p2p_ps)->noa_sel = pp2p_ps_para->noa_sel;
4600 (&halmac_p2p_ps)->all_sta_sleep = pp2p_ps_para->all_sta_sleep;
4601 (&halmac_p2p_ps)->discovery = pp2p_ps_para->discovery;
4602 (&halmac_p2p_ps)->disable_close_rf = pp2p_ps_para->disable_close_rf;
4603 (&halmac_p2p_ps)->p2p_port_id = _hw_port_drv2halmac(pp2p_ps_para->p2p_port_id);
4604 (&halmac_p2p_ps)->p2p_group = pp2p_ps_para->p2p_group;
4605 (&halmac_p2p_ps)->p2p_macid = pp2p_ps_para->p2p_macid;
4606 (&halmac_p2p_ps)->ctwindow_length = pp2p_ps_para->ctwindow_length;
4607 (&halmac_p2p_ps)->noa_duration_para = pp2p_ps_para->noa_duration_para;
4608 (&halmac_p2p_ps)->noa_interval_para = pp2p_ps_para->noa_interval_para;
4609 (&halmac_p2p_ps)->noa_start_time_para = pp2p_ps_para->noa_start_time_para;
4610 (&halmac_p2p_ps)->noa_count_para = pp2p_ps_para->noa_count_para;
4611
4612 status = api->halmac_p2pps(halmac, (&halmac_p2p_ps));
4613 if (status != HALMAC_RET_SUCCESS)
4614 return -1;
4615
4616 return 0;
4617
4618 }
4619
4620 /**
4621 * rtw_halmac_iqk() - Run IQ Calibration
4622 * @d: struct dvobj_priv*
4623 * @clear: IQK parameters
4624 * @segment: IQK parameters
4625 *
4626 * Process IQ Calibration(IQK).
4627 *
4628 * Rteurn: 0 for OK, otherwise fail.
4629 */
rtw_halmac_iqk(struct dvobj_priv * d,u8 clear,u8 segment)4630 int rtw_halmac_iqk(struct dvobj_priv *d, u8 clear, u8 segment)
4631 {
4632 struct halmac_adapter *mac;
4633 struct halmac_api *api;
4634 enum halmac_ret_status status;
4635 enum halmac_feature_id id;
4636 struct halmac_iqk_para para;
4637 int ret;
4638 u8 retry = 3;
4639 u8 delay = 1; /* ms */
4640
4641
4642 mac = dvobj_to_halmac(d);
4643 api = HALMAC_GET_API(mac);
4644 id = HALMAC_FEATURE_IQK;
4645
4646 ret = init_halmac_event(d, id, NULL, 0);
4647 if (ret)
4648 return -1;
4649
4650 para.clear = clear;
4651 para.segment_iqk = segment;
4652
4653 do {
4654 status = api->halmac_start_iqk(mac, ¶);
4655 if (status != HALMAC_RET_BUSY_STATE)
4656 break;
4657 RTW_WARN("%s: Fail to start IQK, status is BUSY! retry=%d\n", __FUNCTION__, retry);
4658 if (!retry)
4659 break;
4660 retry--;
4661 rtw_msleep_os(delay);
4662 } while (1);
4663 if (status != HALMAC_RET_SUCCESS) {
4664 free_halmac_event(d, id);
4665 return -1;
4666 }
4667
4668 ret = wait_halmac_event(d, id);
4669 if (ret)
4670 return -1;
4671
4672 return 0;
4673 }
4674
_phy_parameter_val_drv2halmac(u32 val,u8 msk_en,u32 msk)4675 static inline u32 _phy_parameter_val_drv2halmac(u32 val, u8 msk_en, u32 msk)
4676 {
4677 if (!msk_en)
4678 return val;
4679
4680 return (val << bitshift(msk));
4681 }
4682
_phy_parameter_drv2halmac(struct rtw_phy_parameter * para,struct halmac_phy_parameter_info * info)4683 static int _phy_parameter_drv2halmac(struct rtw_phy_parameter *para, struct halmac_phy_parameter_info *info)
4684 {
4685 if (!para || !info)
4686 return -1;
4687
4688 _rtw_memset(info, 0, sizeof(*info));
4689
4690 switch (para->cmd) {
4691 case 0:
4692 /* MAC register */
4693 switch (para->data.mac.size) {
4694 case 1:
4695 info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W8;
4696 break;
4697 case 2:
4698 info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W16;
4699 break;
4700 default:
4701 info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W32;
4702 break;
4703 }
4704 info->content.MAC_REG_W.value = _phy_parameter_val_drv2halmac(
4705 para->data.mac.value,
4706 para->data.mac.msk_en,
4707 para->data.mac.msk);
4708 info->content.MAC_REG_W.msk = para->data.mac.msk;
4709 info->content.MAC_REG_W.offset = para->data.mac.offset;
4710 info->content.MAC_REG_W.msk_en = para->data.mac.msk_en;
4711 break;
4712
4713 case 1:
4714 /* BB register */
4715 switch (para->data.bb.size) {
4716 case 1:
4717 info->cmd_id = HALMAC_PARAMETER_CMD_BB_W8;
4718 break;
4719 case 2:
4720 info->cmd_id = HALMAC_PARAMETER_CMD_BB_W16;
4721 break;
4722 default:
4723 info->cmd_id = HALMAC_PARAMETER_CMD_BB_W32;
4724 break;
4725 }
4726 info->content.BB_REG_W.value = _phy_parameter_val_drv2halmac(
4727 para->data.bb.value,
4728 para->data.bb.msk_en,
4729 para->data.bb.msk);
4730 info->content.BB_REG_W.msk = para->data.bb.msk;
4731 info->content.BB_REG_W.offset = para->data.bb.offset;
4732 info->content.BB_REG_W.msk_en = para->data.bb.msk_en;
4733 break;
4734
4735 case 2:
4736 /* RF register */
4737 info->cmd_id = HALMAC_PARAMETER_CMD_RF_W;
4738 info->content.RF_REG_W.value = _phy_parameter_val_drv2halmac(
4739 para->data.rf.value,
4740 para->data.rf.msk_en,
4741 para->data.rf.msk);
4742 info->content.RF_REG_W.msk = para->data.rf.msk;
4743 info->content.RF_REG_W.offset = para->data.rf.offset;
4744 info->content.RF_REG_W.msk_en = para->data.rf.msk_en;
4745 info->content.RF_REG_W.rf_path = para->data.rf.path;
4746 break;
4747
4748 case 3:
4749 /* Delay register */
4750 if (para->data.delay.unit == 0)
4751 info->cmd_id = HALMAC_PARAMETER_CMD_DELAY_US;
4752 else
4753 info->cmd_id = HALMAC_PARAMETER_CMD_DELAY_MS;
4754 info->content.DELAY_TIME.delay_time = para->data.delay.value;
4755 break;
4756
4757 case 0xFF:
4758 /* Latest(End) command */
4759 info->cmd_id = HALMAC_PARAMETER_CMD_END;
4760 break;
4761
4762 default:
4763 return -1;
4764 }
4765
4766 return 0;
4767 }
4768
4769 /**
4770 * rtw_halmac_cfg_phy_para() - Register(Phy parameter) configuration
4771 * @d: struct dvobj_priv*
4772 * @para: phy parameter
4773 *
4774 * Configure registers by firmware using H2C/C2H mechanism.
4775 * The latest command should be para->cmd==0xFF(End command) to finish all
4776 * processes.
4777 *
4778 * Return: 0 for OK, otherwise fail.
4779 */
rtw_halmac_cfg_phy_para(struct dvobj_priv * d,struct rtw_phy_parameter * para)4780 int rtw_halmac_cfg_phy_para(struct dvobj_priv *d, struct rtw_phy_parameter *para)
4781 {
4782 struct halmac_adapter *mac;
4783 struct halmac_api *api;
4784 enum halmac_ret_status status;
4785 enum halmac_feature_id id;
4786 struct halmac_phy_parameter_info info;
4787 u8 full_fifo;
4788 int err, ret;
4789
4790
4791 mac = dvobj_to_halmac(d);
4792 api = HALMAC_GET_API(mac);
4793 id = HALMAC_FEATURE_CFG_PARA;
4794 full_fifo = 1; /* ToDo: How to deciede? */
4795 ret = 0;
4796
4797 err = _phy_parameter_drv2halmac(para, &info);
4798 if (err)
4799 return -1;
4800
4801 err = init_halmac_event(d, id, NULL, 0);
4802 if (err)
4803 return -1;
4804
4805 status = api->halmac_cfg_parameter(mac, &info, full_fifo);
4806 if (info.cmd_id == HALMAC_PARAMETER_CMD_END) {
4807 if (status == HALMAC_RET_SUCCESS) {
4808 err = wait_halmac_event(d, id);
4809 if (err)
4810 ret = -1;
4811 } else {
4812 free_halmac_event(d, id);
4813 ret = -1;
4814 RTW_ERR("%s: Fail to send END of cfg parameter, status is 0x%x!\n", __FUNCTION__, status);
4815 }
4816 } else {
4817 if (status == HALMAC_RET_PARA_SENDING) {
4818 err = wait_halmac_event(d, id);
4819 if (err)
4820 ret = -1;
4821 } else {
4822 free_halmac_event(d, id);
4823 if (status != HALMAC_RET_SUCCESS) {
4824 ret = -1;
4825 RTW_ERR("%s: Fail to cfg parameter, status is 0x%x!\n", __FUNCTION__, status);
4826 }
4827 }
4828 }
4829
4830 return ret;
4831 }
4832
_led_mode_drv2halmac(u8 drv_mode)4833 static enum halmac_wlled_mode _led_mode_drv2halmac(u8 drv_mode)
4834 {
4835 enum halmac_wlled_mode halmac_mode;
4836
4837
4838 switch (drv_mode) {
4839 case 1:
4840 halmac_mode = HALMAC_WLLED_MODE_TX;
4841 break;
4842 case 2:
4843 halmac_mode = HALMAC_WLLED_MODE_RX;
4844 break;
4845 case 3:
4846 halmac_mode = HALMAC_WLLED_MODE_SW_CTRL;
4847 break;
4848 case 0:
4849 default:
4850 halmac_mode = HALMAC_WLLED_MODE_TRX;
4851 break;
4852 }
4853
4854 return halmac_mode;
4855 }
4856
4857 /**
4858 * rtw_halmac_led_cfg() - Configure Hardware LED Mode
4859 * @d: struct dvobj_priv*
4860 * @enable: enable or disable LED function
4861 * 0: disable
4862 * 1: enable
4863 * @mode: WLan LED mode (valid when enable==1)
4864 * 0: Blink when TX(transmit packet) and RX(receive packet)
4865 * 1: Blink when TX only
4866 * 2: Blink when RX only
4867 * 3: Software control
4868 *
4869 * Configure hardware WLan LED mode.
4870 * If want to change LED mode after enabled, need to disable LED first and
4871 * enable again to set new mode.
4872 *
4873 * Rteurn 0 for OK, otherwise fail.
4874 */
rtw_halmac_led_cfg(struct dvobj_priv * d,u8 enable,u8 mode)4875 int rtw_halmac_led_cfg(struct dvobj_priv *d, u8 enable, u8 mode)
4876 {
4877 struct halmac_adapter *halmac;
4878 struct halmac_api *api;
4879 enum halmac_wlled_mode led_mode;
4880 enum halmac_ret_status status;
4881
4882
4883 halmac = dvobj_to_halmac(d);
4884 api = HALMAC_GET_API(halmac);
4885
4886 if (enable) {
4887 status = api->halmac_pinmux_set_func(halmac,
4888 HALMAC_GPIO_FUNC_WL_LED);
4889 if (status != HALMAC_RET_SUCCESS) {
4890 RTW_ERR("%s: pinmux set fail!(0x%x)\n",
4891 __FUNCTION__, status);
4892 return -1;
4893 }
4894
4895 led_mode = _led_mode_drv2halmac(mode);
4896 status = api->halmac_pinmux_wl_led_mode(halmac, led_mode);
4897 if (status != HALMAC_RET_SUCCESS) {
4898 RTW_ERR("%s: mode set fail!(0x%x)\n",
4899 __FUNCTION__, status);
4900 return -1;
4901 }
4902 } else {
4903 /* Change LED to software control and turn off */
4904 api->halmac_pinmux_wl_led_mode(halmac,
4905 HALMAC_WLLED_MODE_SW_CTRL);
4906 api->halmac_pinmux_wl_led_sw_ctrl(halmac, 0);
4907
4908 status = api->halmac_pinmux_free_func(halmac,
4909 HALMAC_GPIO_FUNC_WL_LED);
4910 if (status != HALMAC_RET_SUCCESS) {
4911 RTW_ERR("%s: pinmux free fail!(0x%x)\n",
4912 __FUNCTION__, status);
4913 return -1;
4914 }
4915 }
4916
4917 return 0;
4918 }
4919
4920 /**
4921 * rtw_halmac_led_switch() - Turn Hardware LED on/off
4922 * @d: struct dvobj_priv*
4923 * @on: LED light or not
4924 * 0: Off
4925 * 1: On(Light)
4926 *
4927 * Turn Hardware WLan LED On/Off.
4928 * Before use this function, user should call rtw_halmac_led_ctrl() to switch
4929 * mode to "software control(3)" first, otherwise control would fail.
4930 * The interval between on and off must be longer than 1 ms, or the LED would
4931 * keep light or dark only.
4932 * Ex. Turn off LED at first, turn on after 0.5ms and turn off again after
4933 * 0.5ms. The LED during this flow will only keep dark, and miss the turn on
4934 * operation between two turn off operations.
4935 */
rtw_halmac_led_switch(struct dvobj_priv * d,u8 on)4936 void rtw_halmac_led_switch(struct dvobj_priv *d, u8 on)
4937 {
4938 struct halmac_adapter *halmac;
4939 struct halmac_api *api;
4940
4941
4942 halmac = dvobj_to_halmac(d);
4943 api = HALMAC_GET_API(halmac);
4944
4945 api->halmac_pinmux_wl_led_sw_ctrl(halmac, on);
4946 }
4947
4948 /**
4949 * rtw_halmac_bt_wake_cfg() - Configure BT wake host function
4950 * @d: struct dvobj_priv*
4951 * @enable: enable or disable BT wake host function
4952 * 0: disable
4953 * 1: enable
4954 *
4955 * Configure pinmux to allow BT to control BT wake host pin.
4956 *
4957 * Rteurn 0 for OK, otherwise fail.
4958 */
rtw_halmac_bt_wake_cfg(struct dvobj_priv * d,u8 enable)4959 int rtw_halmac_bt_wake_cfg(struct dvobj_priv *d, u8 enable)
4960 {
4961 struct halmac_adapter *halmac;
4962 struct halmac_api *api;
4963 enum halmac_ret_status status;
4964
4965
4966 halmac = dvobj_to_halmac(d);
4967 api = HALMAC_GET_API(halmac);
4968
4969 if (enable) {
4970 status = api->halmac_pinmux_set_func(halmac,
4971 HALMAC_GPIO_FUNC_BT_HOST_WAKE1);
4972 if (status != HALMAC_RET_SUCCESS) {
4973 RTW_ERR("%s: pinmux set BT_HOST_WAKE1 fail!(0x%x)\n",
4974 __FUNCTION__, status);
4975 return -1;
4976 }
4977 } else {
4978 status = api->halmac_pinmux_free_func(halmac,
4979 HALMAC_GPIO_FUNC_BT_HOST_WAKE1);
4980 if (status != HALMAC_RET_SUCCESS) {
4981 RTW_ERR("%s: pinmux free BT_HOST_WAKE1 fail!(0x%x)\n",
4982 __FUNCTION__, status);
4983 return -1;
4984 }
4985 }
4986
4987 return 0;
4988 }
4989
4990 #ifdef CONFIG_PNO_SUPPORT
4991 /**
4992 * _halmac_scanoffload() - Switch channel by firmware during scanning
4993 * @d: struct dvobj_priv*
4994 * @enable: 1: enable, 0: disable
4995 * @nlo: 1: nlo mode (no c2h event), 0: normal mode
4996 * @ssid: ssid of probe request
4997 * @ssid_len: ssid length
4998 *
4999 * Switch Channel and Send Porbe Request Offloaded by FW
5000 *
5001 * Rteurn 0 for OK, otherwise fail.
5002 */
_halmac_scanoffload(struct dvobj_priv * d,u32 enable,u8 nlo,u8 * ssid,u8 ssid_len)5003 static int _halmac_scanoffload(struct dvobj_priv *d, u32 enable, u8 nlo,
5004 u8 *ssid, u8 ssid_len)
5005 {
5006 struct _ADAPTER *adapter;
5007 struct halmac_adapter *mac;
5008 struct halmac_api *api;
5009 enum halmac_ret_status status;
5010 struct halmac_ch_info ch_info;
5011 struct halmac_ch_switch_option cs_option;
5012 struct mlme_ext_priv *pmlmeext;
5013 enum halmac_feature_id id_update, id_ch_sw;
5014 struct halmac_indicator *indicator, *tbl;
5015
5016 int err = 0;
5017 u8 probereq[64];
5018 u32 len = 0;
5019 int i = 0;
5020 struct pno_ssid pnossid;
5021 struct rf_ctl_t *rfctl = NULL;
5022 struct _RT_CHANNEL_INFO *ch_set;
5023
5024
5025 tbl = d->hmpriv.indicator;
5026 adapter = dvobj_get_primary_adapter(d);
5027 mac = dvobj_to_halmac(d);
5028 if (!mac)
5029 return -1;
5030 api = HALMAC_GET_API(mac);
5031 id_update = HALMAC_FEATURE_UPDATE_PACKET;
5032 id_ch_sw = HALMAC_FEATURE_CHANNEL_SWITCH;
5033 pmlmeext = &(adapter->mlmeextpriv);
5034 rfctl = adapter_to_rfctl(adapter);
5035 ch_set = rfctl->channel_set;
5036
5037 RTW_INFO("%s: %s scanoffload, mode: %s\n",
5038 __FUNCTION__, enable?"Enable":"Disable",
5039 nlo?"PNO/NLO":"Normal");
5040
5041 if (enable) {
5042 _rtw_memset(probereq, 0, sizeof(probereq));
5043
5044 _rtw_memset(&pnossid, 0, sizeof(pnossid));
5045 if (ssid) {
5046 if (ssid_len > sizeof(pnossid.SSID)) {
5047 RTW_ERR("%s: SSID length(%d) is too long(>%d)!!\n",
5048 __FUNCTION__, ssid_len, sizeof(pnossid.SSID));
5049 return -1;
5050 }
5051
5052 pnossid.SSID_len = ssid_len;
5053 _rtw_memcpy(pnossid.SSID, ssid, ssid_len);
5054 }
5055
5056 rtw_hal_construct_ProbeReq(adapter, probereq, &len, &pnossid);
5057
5058 if (!nlo) {
5059 err = init_halmac_event(d, id_update, NULL, 0);
5060 if (err)
5061 return -1;
5062 }
5063
5064 status = api->halmac_update_packet(mac, HALMAC_PACKET_PROBE_REQ,
5065 probereq, len);
5066 if (status != HALMAC_RET_SUCCESS) {
5067 if (!nlo)
5068 free_halmac_event(d, id_update);
5069 RTW_ERR("%s: halmac_update_packet FAIL(%d)!!\n",
5070 __FUNCTION__, status);
5071 return -1;
5072 }
5073
5074 if (!nlo) {
5075 err = wait_halmac_event(d, id_update);
5076 if (err)
5077 RTW_ERR("%s: wait update packet FAIL(%d)!!\n",
5078 __FUNCTION__, err);
5079 }
5080
5081 api->halmac_clear_ch_info(mac);
5082
5083 for (i = 0; i < rfctl->max_chan_nums && ch_set[i].ChannelNum != 0; i++) {
5084 _rtw_memset(&ch_info, 0, sizeof(ch_info));
5085 ch_info.extra_info = 0;
5086 ch_info.channel = ch_set[i].ChannelNum;
5087 ch_info.bw = HALMAC_BW_20;
5088 ch_info.pri_ch_idx = HALMAC_CH_IDX_1;
5089 ch_info.action_id = HALMAC_CS_ACTIVE_SCAN;
5090 ch_info.timeout = 1;
5091 status = api->halmac_add_ch_info(mac, &ch_info);
5092 if (status != HALMAC_RET_SUCCESS) {
5093 RTW_ERR("%s: add_ch_info FAIL(%d)!!\n",
5094 __FUNCTION__, status);
5095 return -1;
5096 }
5097 }
5098
5099 /* set channel switch option */
5100 _rtw_memset(&cs_option, 0, sizeof(cs_option));
5101 cs_option.dest_bw = HALMAC_BW_20;
5102 cs_option.periodic_option = HALMAC_CS_PERIODIC_2_PHASE;
5103 cs_option.dest_pri_ch_idx = HALMAC_CH_IDX_UNDEFINE;
5104 cs_option.tsf_low = 0;
5105 cs_option.switch_en = 1;
5106 cs_option.dest_ch_en = 1;
5107 cs_option.absolute_time_en = 0;
5108 cs_option.dest_ch = 1;
5109
5110 cs_option.normal_period = 5;
5111 cs_option.normal_period_sel = 0;
5112 cs_option.normal_cycle = 10;
5113
5114 cs_option.phase_2_period = 1;
5115 cs_option.phase_2_period_sel = 1;
5116
5117 /* nlo is for wow fw, 1: no c2h response */
5118 cs_option.nlo_en = nlo;
5119
5120 if (!nlo) {
5121 err = init_halmac_event(d, id_ch_sw, NULL, 0);
5122 if (err)
5123 return -1;
5124 }
5125
5126 status = api->halmac_ctrl_ch_switch(mac, &cs_option);
5127 if (status != HALMAC_RET_SUCCESS) {
5128 if (!nlo)
5129 free_halmac_event(d, id_ch_sw);
5130 RTW_ERR("%s: halmac_ctrl_ch_switch FAIL(%d)!!\n",
5131 __FUNCTION__, status);
5132 return -1;
5133 }
5134
5135 if (!nlo) {
5136 err = wait_halmac_event(d, id_ch_sw);
5137 if (err)
5138 RTW_ERR("%s: wait ctrl_ch_switch FAIL(%d)!!\n",
5139 __FUNCTION__, err);
5140 }
5141 } else {
5142 api->halmac_clear_ch_info(mac);
5143
5144 _rtw_memset(&cs_option, 0, sizeof(cs_option));
5145 cs_option.switch_en = 0;
5146
5147 if (!nlo) {
5148 err = init_halmac_event(d, id_ch_sw, NULL, 0);
5149 if (err)
5150 return -1;
5151 }
5152
5153 status = api->halmac_ctrl_ch_switch(mac, &cs_option);
5154 if (status != HALMAC_RET_SUCCESS) {
5155 if (!nlo)
5156 free_halmac_event(d, id_ch_sw);
5157 RTW_ERR("%s: halmac_ctrl_ch_switch FAIL(%d)!!\n",
5158 __FUNCTION__, status);
5159 return -1;
5160 }
5161
5162 if (!nlo) {
5163 err = wait_halmac_event(d, id_ch_sw);
5164 if (err)
5165 RTW_ERR("%s: wait ctrl_ch_switch FAIL(%d)!!\n",
5166 __FUNCTION__, err);
5167 }
5168 }
5169
5170 return 0;
5171 }
5172
5173 /**
5174 * rtw_halmac_pno_scanoffload() - Control firmware scan AP function for PNO
5175 * @d: struct dvobj_priv*
5176 * @enable: 1: enable, 0: disable
5177 *
5178 * Switch firmware scan AP function for PNO(prefer network offload) or
5179 * NLO(network list offload).
5180 *
5181 * Rteurn 0 for OK, otherwise fail.
5182 */
rtw_halmac_pno_scanoffload(struct dvobj_priv * d,u32 enable)5183 int rtw_halmac_pno_scanoffload(struct dvobj_priv *d, u32 enable)
5184 {
5185 return _halmac_scanoffload(d, enable, 1, NULL, 0);
5186 }
5187 #endif /* CONFIG_PNO_SUPPORT */
5188
5189 #ifdef CONFIG_SDIO_HCI
5190
5191 /*
5192 * Description:
5193 * Update queue allocated page number to driver
5194 *
5195 * Parameter:
5196 * d pointer to struct dvobj_priv of driver
5197 *
5198 * Rteurn:
5199 * 0 Success, "page" is valid.
5200 * others Fail, "page" is invalid.
5201 */
rtw_halmac_query_tx_page_num(struct dvobj_priv * d)5202 int rtw_halmac_query_tx_page_num(struct dvobj_priv *d)
5203 {
5204 PADAPTER adapter;
5205 struct halmacpriv *hmpriv;
5206 struct halmac_adapter *halmac;
5207 struct halmac_api *api;
5208 struct halmac_rqpn_map rqpn;
5209 enum halmac_dma_mapping dmaqueue;
5210 struct halmac_txff_allocation fifosize;
5211 enum halmac_ret_status status;
5212 u8 i;
5213
5214
5215 adapter = dvobj_get_primary_adapter(d);
5216 hmpriv = &d->hmpriv;
5217 halmac = dvobj_to_halmac(d);
5218 api = HALMAC_GET_API(halmac);
5219 _rtw_memset((void *)&rqpn, 0, sizeof(rqpn));
5220 _rtw_memset((void *)&fifosize, 0, sizeof(fifosize));
5221
5222 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RQPN_MAPPING, &rqpn);
5223 if (status != HALMAC_RET_SUCCESS)
5224 return -1;
5225 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TXFF_ALLOCATION, &fifosize);
5226 if (status != HALMAC_RET_SUCCESS)
5227 return -1;
5228
5229 for (i = 0; i < HW_QUEUE_ENTRY; i++) {
5230 hmpriv->txpage[i] = 0;
5231
5232 /* Driver index mapping to HALMAC DMA queue */
5233 dmaqueue = HALMAC_DMA_MAPPING_UNDEFINE;
5234 switch (i) {
5235 case VO_QUEUE_INX:
5236 dmaqueue = rqpn.dma_map_vo;
5237 break;
5238 case VI_QUEUE_INX:
5239 dmaqueue = rqpn.dma_map_vi;
5240 break;
5241 case BE_QUEUE_INX:
5242 dmaqueue = rqpn.dma_map_be;
5243 break;
5244 case BK_QUEUE_INX:
5245 dmaqueue = rqpn.dma_map_bk;
5246 break;
5247 case MGT_QUEUE_INX:
5248 dmaqueue = rqpn.dma_map_mg;
5249 break;
5250 case HIGH_QUEUE_INX:
5251 dmaqueue = rqpn.dma_map_hi;
5252 break;
5253 case BCN_QUEUE_INX:
5254 case TXCMD_QUEUE_INX:
5255 /* Unlimited */
5256 hmpriv->txpage[i] = 0xFFFF;
5257 continue;
5258 }
5259
5260 switch (dmaqueue) {
5261 case HALMAC_DMA_MAPPING_EXTRA:
5262 hmpriv->txpage[i] = fifosize.extra_queue_pg_num;
5263 break;
5264 case HALMAC_DMA_MAPPING_LOW:
5265 hmpriv->txpage[i] = fifosize.low_queue_pg_num;
5266 break;
5267 case HALMAC_DMA_MAPPING_NORMAL:
5268 hmpriv->txpage[i] = fifosize.normal_queue_pg_num;
5269 break;
5270 case HALMAC_DMA_MAPPING_HIGH:
5271 hmpriv->txpage[i] = fifosize.high_queue_pg_num;
5272 break;
5273 case HALMAC_DMA_MAPPING_UNDEFINE:
5274 break;
5275 }
5276 hmpriv->txpage[i] += fifosize.pub_queue_pg_num;
5277 }
5278
5279 return 0;
5280 }
5281
5282 /*
5283 * Description:
5284 * Get specific queue allocated page number
5285 *
5286 * Parameter:
5287 * d pointer to struct dvobj_priv of driver
5288 * queue target queue to query, VO/VI/BE/BK/.../TXCMD_QUEUE_INX
5289 * page return allocated page number
5290 *
5291 * Rteurn:
5292 * 0 Success, "page" is valid.
5293 * others Fail, "page" is invalid.
5294 */
rtw_halmac_get_tx_queue_page_num(struct dvobj_priv * d,u8 queue,u32 * page)5295 int rtw_halmac_get_tx_queue_page_num(struct dvobj_priv *d, u8 queue, u32 *page)
5296 {
5297 *page = 0;
5298 if (queue < HW_QUEUE_ENTRY)
5299 *page = d->hmpriv.txpage[queue];
5300
5301 return 0;
5302 }
5303
5304 /*
5305 * Return:
5306 * address for SDIO command
5307 */
rtw_halmac_sdio_get_tx_addr(struct dvobj_priv * d,u8 * desc,u32 size)5308 u32 rtw_halmac_sdio_get_tx_addr(struct dvobj_priv *d, u8 *desc, u32 size)
5309 {
5310 struct halmac_adapter *mac;
5311 struct halmac_api *api;
5312 enum halmac_ret_status status;
5313 u32 addr;
5314
5315
5316 mac = dvobj_to_halmac(d);
5317 api = HALMAC_GET_API(mac);
5318
5319 status = api->halmac_get_sdio_tx_addr(mac, desc, size, &addr);
5320 if (HALMAC_RET_SUCCESS != status)
5321 return 0;
5322
5323 return addr;
5324 }
5325
rtw_halmac_sdio_tx_allowed(struct dvobj_priv * d,u8 * buf,u32 size)5326 int rtw_halmac_sdio_tx_allowed(struct dvobj_priv *d, u8 *buf, u32 size)
5327 {
5328 struct halmac_adapter *mac;
5329 struct halmac_api *api;
5330 enum halmac_ret_status status;
5331
5332
5333 mac = dvobj_to_halmac(d);
5334 api = HALMAC_GET_API(mac);
5335
5336 status = api->halmac_tx_allowed_sdio(mac, buf, size);
5337 if (HALMAC_RET_SUCCESS != status)
5338 return -1;
5339
5340 return 0;
5341 }
5342
rtw_halmac_sdio_get_rx_addr(struct dvobj_priv * d,u8 * seq)5343 u32 rtw_halmac_sdio_get_rx_addr(struct dvobj_priv *d, u8 *seq)
5344 {
5345 u8 id;
5346
5347 #define RTW_SDIO_ADDR_RX_RX0FF_PRFIX 0x0E000
5348 #define RTW_SDIO_ADDR_RX_RX0FF_GEN(a) (RTW_SDIO_ADDR_RX_RX0FF_PRFIX|(a&0x3))
5349
5350 id = *seq;
5351 (*seq)++;
5352 return RTW_SDIO_ADDR_RX_RX0FF_GEN(id);
5353 }
5354
rtw_halmac_sdio_set_tx_format(struct dvobj_priv * d,enum halmac_sdio_tx_format format)5355 int rtw_halmac_sdio_set_tx_format(struct dvobj_priv *d, enum halmac_sdio_tx_format format)
5356 {
5357 struct halmac_adapter *mac;
5358 struct halmac_api *api;
5359 enum halmac_ret_status status;
5360
5361 mac = dvobj_to_halmac(d);
5362 api = HALMAC_GET_API(mac);
5363
5364 status = api->halmac_set_hw_value(mac, HALMAC_HW_SDIO_TX_FORMAT, &format);
5365 if (HALMAC_RET_SUCCESS != status)
5366 return -1;
5367
5368 return 0;
5369 }
5370 #endif /* CONFIG_SDIO_HCI */
5371
5372 #ifdef CONFIG_USB_HCI
rtw_halmac_usb_get_bulkout_id(struct dvobj_priv * d,u8 * buf,u32 size)5373 u8 rtw_halmac_usb_get_bulkout_id(struct dvobj_priv *d, u8 *buf, u32 size)
5374 {
5375 struct halmac_adapter *mac;
5376 struct halmac_api *api;
5377 enum halmac_ret_status status;
5378 u8 bulkout_id;
5379
5380
5381 mac = dvobj_to_halmac(d);
5382 api = HALMAC_GET_API(mac);
5383
5384 status = api->halmac_get_usb_bulkout_id(mac, buf, size, &bulkout_id);
5385 if (HALMAC_RET_SUCCESS != status)
5386 return 0;
5387
5388 return bulkout_id;
5389 }
5390
5391 /**
5392 * rtw_halmac_usb_get_txagg_desc_num() - MAX descriptor number in one bulk for TX
5393 * @d: struct dvobj_priv*
5394 * @size: TX FIFO size, unit is byte.
5395 *
5396 * Get MAX descriptor number in one bulk out from HALMAC.
5397 *
5398 * Rteurn 0 for OK, otherwise fail.
5399 */
rtw_halmac_usb_get_txagg_desc_num(struct dvobj_priv * d,u8 * num)5400 int rtw_halmac_usb_get_txagg_desc_num(struct dvobj_priv *d, u8 *num)
5401 {
5402 struct halmac_adapter *halmac;
5403 struct halmac_api *api;
5404 enum halmac_ret_status status;
5405 u8 val = 0;
5406
5407
5408 halmac = dvobj_to_halmac(d);
5409 api = HALMAC_GET_API(halmac);
5410
5411 status = api->halmac_get_hw_value(halmac, HALMAC_HW_USB_TXAGG_DESC_NUM, &val);
5412 if (status != HALMAC_RET_SUCCESS)
5413 return -1;
5414
5415 *num = val;
5416
5417 return 0;
5418 }
5419
_usb_mode_drv2halmac(enum RTW_USB_SPEED usb_mode)5420 static inline enum halmac_usb_mode _usb_mode_drv2halmac(enum RTW_USB_SPEED usb_mode)
5421 {
5422 enum halmac_usb_mode halmac_usb_mode = HALMAC_USB_MODE_U2;
5423
5424 switch (usb_mode) {
5425 case RTW_USB_SPEED_2:
5426 halmac_usb_mode = HALMAC_USB_MODE_U2;
5427 break;
5428 case RTW_USB_SPEED_3:
5429 halmac_usb_mode = HALMAC_USB_MODE_U3;
5430 break;
5431 default:
5432 halmac_usb_mode = HALMAC_USB_MODE_U2;
5433 break;
5434 }
5435
5436 return halmac_usb_mode;
5437 }
5438
rtw_halmac_switch_usb_mode(struct dvobj_priv * d,enum RTW_USB_SPEED usb_mode)5439 u8 rtw_halmac_switch_usb_mode(struct dvobj_priv *d, enum RTW_USB_SPEED usb_mode)
5440 {
5441 PADAPTER adapter;
5442 struct halmac_adapter *mac;
5443 struct halmac_api *api;
5444 enum halmac_ret_status status;
5445 enum halmac_usb_mode halmac_usb_mode;
5446
5447 adapter = dvobj_get_primary_adapter(d);
5448 mac = dvobj_to_halmac(d);
5449 api = HALMAC_GET_API(mac);
5450 halmac_usb_mode = _usb_mode_drv2halmac(usb_mode);
5451 status = api->halmac_set_hw_value(mac, HALMAC_HW_USB_MODE, (void *)&halmac_usb_mode);
5452
5453 if (HALMAC_RET_SUCCESS != status)
5454 return _FAIL;
5455
5456 return _SUCCESS;
5457 }
5458 #endif /* CONFIG_USB_HCI */
5459
5460 #ifdef CONFIG_BEAMFORMING
5461 #ifdef RTW_BEAMFORMING_VERSION_2
rtw_halmac_bf_add_mu_bfer(struct dvobj_priv * d,u16 paid,u16 csi_para,u16 my_aid,enum halmac_csi_seg_len sel,u8 * addr)5462 int rtw_halmac_bf_add_mu_bfer(struct dvobj_priv *d, u16 paid, u16 csi_para,
5463 u16 my_aid, enum halmac_csi_seg_len sel, u8 *addr)
5464 {
5465 struct halmac_adapter *mac;
5466 struct halmac_api *api;
5467 enum halmac_ret_status status;
5468 struct halmac_mu_bfer_init_para param;
5469
5470
5471 mac = dvobj_to_halmac(d);
5472 api = HALMAC_GET_API(mac);
5473
5474 _rtw_memset(¶m, 0, sizeof(param));
5475 param.paid = paid;
5476 param.csi_para = csi_para;
5477 param.my_aid = my_aid;
5478 param.csi_length_sel = sel;
5479 _rtw_memcpy(param.bfer_address.addr, addr, 6);
5480
5481 status = api->halmac_mu_bfer_entry_init(mac, ¶m);
5482 if (status != HALMAC_RET_SUCCESS)
5483 return -1;
5484
5485 return 0;
5486 }
5487
rtw_halmac_bf_del_mu_bfer(struct dvobj_priv * d)5488 int rtw_halmac_bf_del_mu_bfer(struct dvobj_priv *d)
5489 {
5490 struct halmac_adapter *mac;
5491 struct halmac_api *api;
5492 enum halmac_ret_status status;
5493
5494
5495 mac = dvobj_to_halmac(d);
5496 api = HALMAC_GET_API(mac);
5497
5498 status = api->halmac_mu_bfer_entry_del(mac);
5499 if (status != HALMAC_RET_SUCCESS)
5500 return -1;
5501
5502 return 0;
5503 }
5504
5505
rtw_halmac_bf_cfg_sounding(struct dvobj_priv * d,enum halmac_snd_role role,enum halmac_data_rate rate)5506 int rtw_halmac_bf_cfg_sounding(struct dvobj_priv *d,
5507 enum halmac_snd_role role, enum halmac_data_rate rate)
5508 {
5509 struct halmac_adapter *mac;
5510 struct halmac_api *api;
5511 enum halmac_ret_status status;
5512
5513
5514 mac = dvobj_to_halmac(d);
5515 api = HALMAC_GET_API(mac);
5516
5517 status = api->halmac_cfg_sounding(mac, role, rate);
5518 if (status != HALMAC_RET_SUCCESS)
5519 return -1;
5520
5521 return 0;
5522 }
5523
rtw_halmac_bf_del_sounding(struct dvobj_priv * d,enum halmac_snd_role role)5524 int rtw_halmac_bf_del_sounding(struct dvobj_priv *d,
5525 enum halmac_snd_role role)
5526 {
5527 struct halmac_adapter *mac;
5528 struct halmac_api *api;
5529 enum halmac_ret_status status;
5530
5531
5532 mac = dvobj_to_halmac(d);
5533 api = HALMAC_GET_API(mac);
5534
5535 status = api->halmac_del_sounding(mac, role);
5536 if (status != HALMAC_RET_SUCCESS)
5537 return -1;
5538
5539 return 0;
5540 }
5541
5542 /**
5543 * rtw_halmac_bf_cfg_csi_rate() - Config data rate for CSI report by CSSI
5544 * @d: struct dvobj_priv*
5545 * @rssi: RSSI vlaue, unit is percentage (0~100).
5546 * @current_rate: Current CSI frame rate
5547 * Valid value example
5548 * 0 CCK 1M
5549 * 3 CCK 11M
5550 * 4 OFDM 6M
5551 * and so on
5552 * @fixrate_en: Enable to fix CSI frame in VHT rate, otherwise legacy OFDM rate.
5553 * The value "0" for disable, otheriwse enable.
5554 * @new_rate: Return new data rate, and value range is the same as current_rate
5555 * @bmp_ofdm54: Return to suggest enabling OFDM 54M for CSI report frame or not,
5556 * The valid values and meanings are:
5557 * 0x00 disable
5558 * 0x01 enable
5559 * 0xFF Keep current setting
5560 *
5561 * According RSSI to config data rate for CSI report frame of Beamforming.
5562 *
5563 * Rteurn 0 for OK, otherwise fail.
5564 */
rtw_halmac_bf_cfg_csi_rate(struct dvobj_priv * d,u8 rssi,u8 current_rate,u8 fixrate_en,u8 * new_rate,u8 * bmp_ofdm54)5565 int rtw_halmac_bf_cfg_csi_rate(struct dvobj_priv *d,
5566 u8 rssi, u8 current_rate, u8 fixrate_en,
5567 u8 *new_rate, u8 *bmp_ofdm54)
5568 {
5569 struct halmac_adapter *mac;
5570 struct halmac_api *api;
5571 enum halmac_ret_status status;
5572
5573
5574 mac = dvobj_to_halmac(d);
5575 api = HALMAC_GET_API(mac);
5576
5577 status = api->halmac_cfg_csi_rate(mac,
5578 rssi, current_rate, fixrate_en, new_rate, bmp_ofdm54);
5579 if (status != HALMAC_RET_SUCCESS)
5580 return -1;
5581
5582 return 0;
5583 }
5584
rtw_halmac_bf_cfg_mu_mimo(struct dvobj_priv * d,enum halmac_snd_role role,u8 * sounding_sts,u16 grouping_bitmap,u8 mu_tx_en,u32 * given_gid_tab,u32 * given_user_pos)5585 int rtw_halmac_bf_cfg_mu_mimo(struct dvobj_priv *d, enum halmac_snd_role role,
5586 u8 *sounding_sts, u16 grouping_bitmap, u8 mu_tx_en,
5587 u32 *given_gid_tab, u32 *given_user_pos)
5588 {
5589 struct halmac_adapter *mac;
5590 struct halmac_api *api;
5591 enum halmac_ret_status status;
5592 struct halmac_cfg_mumimo_para param;
5593
5594
5595 mac = dvobj_to_halmac(d);
5596 api = HALMAC_GET_API(mac);
5597
5598 _rtw_memset(¶m, 0, sizeof(param));
5599
5600 param.role = role;
5601 param.grouping_bitmap = grouping_bitmap;
5602 param.mu_tx_en = mu_tx_en;
5603
5604 if (sounding_sts)
5605 _rtw_memcpy(param.sounding_sts, sounding_sts, 6);
5606
5607 if (given_gid_tab)
5608 _rtw_memcpy(param.given_gid_tab, given_gid_tab, 8);
5609
5610 if (given_user_pos)
5611 _rtw_memcpy(param.given_user_pos, given_user_pos, 16);
5612
5613 status = api->halmac_cfg_mumimo(mac, ¶m);
5614 if (status != HALMAC_RET_SUCCESS)
5615 return -1;
5616
5617 return 0;
5618 }
5619
5620 #endif /* RTW_BEAMFORMING_VERSION_2 */
5621 #endif /* CONFIG_BEAMFORMING */
5622