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