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