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