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",
1213 ver.major_ver, ver.prototype_ver, ver.minor_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 _power_switch(halmac, api, HALMAC_MAC_POWER_OFF);
2772 status = _power_switch(halmac, api, HALMAC_MAC_POWER_ON);
2773 RTW_WARN("%s: Power state abnormal, try to recover...%s\n",
2774 __FUNCTION__, (HALMAC_RET_SUCCESS == status)?"OK":"FAIL!");
2775 }
2776 if (HALMAC_RET_SUCCESS != status) {
2777 if (HALMAC_RET_PWR_UNCHANGE == status)
2778 err = -2;
2779 goto out;
2780 }
2781
2782 status = api->halmac_init_system_cfg(halmac);
2783 if (status != HALMAC_RET_SUCCESS)
2784 goto out;
2785
2786 err = 0;
2787 out:
2788 return err;
2789 }
2790
2791 /*
2792 * Description:
2793 * Power off device hardware.
2794 *
2795 * Return:
2796 * 0 Power off success
2797 * -1 Power off fail
2798 */
rtw_halmac_poweroff(struct dvobj_priv * d)2799 int rtw_halmac_poweroff(struct dvobj_priv *d)
2800 {
2801 struct halmac_adapter *halmac;
2802 struct halmac_api *api;
2803 enum halmac_ret_status status;
2804 int err = -1;
2805
2806
2807 halmac = dvobj_to_halmac(d);
2808 if (!halmac)
2809 goto out;
2810
2811 api = HALMAC_GET_API(halmac);
2812
2813 status = _power_switch(halmac, api, HALMAC_MAC_POWER_OFF);
2814 if ((HALMAC_RET_SUCCESS != status)
2815 && (HALMAC_RET_PWR_UNCHANGE != status))
2816 goto out;
2817
2818 err = 0;
2819 out:
2820 return err;
2821 }
2822
2823 #ifdef CONFIG_SUPPORT_TRX_SHARED
_trx_share_mode_drv2halmac(u8 trx_share_mode)2824 static inline enum halmac_rx_fifo_expanding_mode _trx_share_mode_drv2halmac(u8 trx_share_mode)
2825 {
2826 if (0 == trx_share_mode)
2827 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
2828 else if (1 == trx_share_mode)
2829 return HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK;
2830 else if (2 == trx_share_mode)
2831 return HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK;
2832 else if (3 == trx_share_mode)
2833 return HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK;
2834 else
2835 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
2836 }
2837
_rtw_get_trx_share_mode(struct _ADAPTER * adapter)2838 static enum halmac_rx_fifo_expanding_mode _rtw_get_trx_share_mode(struct _ADAPTER *adapter)
2839 {
2840 struct registry_priv *registry_par = &adapter->registrypriv;
2841
2842 return _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
2843 }
2844
dump_trx_share_mode(void * sel,struct _ADAPTER * adapter)2845 void dump_trx_share_mode(void *sel, struct _ADAPTER *adapter)
2846 {
2847 struct registry_priv *registry_par = &adapter->registrypriv;
2848 u8 mode = _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
2849
2850 if (HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK == mode)
2851 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_1");
2852 else if (HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK == mode)
2853 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_2");
2854 else if (HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK == mode)
2855 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_3");
2856 else
2857 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "DISABLE");
2858 }
2859 #endif
2860
_rsvd_page_num_drv2halmac(u16 num)2861 static enum halmac_drv_rsvd_pg_num _rsvd_page_num_drv2halmac(u16 num)
2862 {
2863 if (num <= 8)
2864 return HALMAC_RSVD_PG_NUM8;
2865 if (num <= 16)
2866 return HALMAC_RSVD_PG_NUM16;
2867 if (num <= 24)
2868 return HALMAC_RSVD_PG_NUM24;
2869 if (num <= 32)
2870 return HALMAC_RSVD_PG_NUM32;
2871 if (num <= 64)
2872 return HALMAC_RSVD_PG_NUM64;
2873 if (num <= 128)
2874 return HALMAC_RSVD_PG_NUM128;
2875
2876 if (num > 256)
2877 RTW_WARN("%s: Fail to allocate RSVD page(%d)!!"
2878 " The MAX RSVD page number is 256...\n",
2879 __FUNCTION__, num);
2880
2881 return HALMAC_RSVD_PG_NUM256;
2882 }
2883
_rsvd_page_num_halmac2drv(enum halmac_drv_rsvd_pg_num rsvd_page_number)2884 static u16 _rsvd_page_num_halmac2drv(enum halmac_drv_rsvd_pg_num rsvd_page_number)
2885 {
2886 u16 num = 0;
2887
2888
2889 switch (rsvd_page_number) {
2890 case HALMAC_RSVD_PG_NUM8:
2891 num = 8;
2892 break;
2893
2894 case HALMAC_RSVD_PG_NUM16:
2895 num = 16;
2896 break;
2897
2898 case HALMAC_RSVD_PG_NUM24:
2899 num = 24;
2900 break;
2901
2902 case HALMAC_RSVD_PG_NUM32:
2903 num = 32;
2904 break;
2905
2906 case HALMAC_RSVD_PG_NUM64:
2907 num = 64;
2908 break;
2909
2910 case HALMAC_RSVD_PG_NUM128:
2911 num = 128;
2912 break;
2913
2914 case HALMAC_RSVD_PG_NUM256:
2915 num = 256;
2916 break;
2917 }
2918
2919 return num;
2920 }
2921
_choose_trx_mode(struct dvobj_priv * d)2922 static enum halmac_trx_mode _choose_trx_mode(struct dvobj_priv *d)
2923 {
2924 PADAPTER p;
2925
2926
2927 p = dvobj_get_primary_adapter(d);
2928
2929 if (p->registrypriv.wifi_spec)
2930 return HALMAC_TRX_MODE_WMM;
2931
2932 #ifdef CONFIG_SUPPORT_TRX_SHARED
2933 if (_rtw_get_trx_share_mode(p))
2934 return HALMAC_TRX_MODE_TRXSHARE;
2935 #endif
2936
2937 return HALMAC_TRX_MODE_NORMAL;
2938 }
2939
_rf_type_drv2halmac(enum rf_type rf_drv)2940 static inline enum halmac_rf_type _rf_type_drv2halmac(enum rf_type rf_drv)
2941 {
2942 enum halmac_rf_type rf_mac;
2943
2944
2945 switch (rf_drv) {
2946 case RF_1T1R:
2947 rf_mac = HALMAC_RF_1T1R;
2948 break;
2949 case RF_1T2R:
2950 rf_mac = HALMAC_RF_1T2R;
2951 break;
2952 case RF_2T2R:
2953 rf_mac = HALMAC_RF_2T2R;
2954 break;
2955 case RF_2T3R:
2956 rf_mac = HALMAC_RF_2T3R;
2957 break;
2958 case RF_2T4R:
2959 rf_mac = HALMAC_RF_2T4R;
2960 break;
2961 case RF_3T3R:
2962 rf_mac = HALMAC_RF_3T3R;
2963 break;
2964 case RF_3T4R:
2965 rf_mac = HALMAC_RF_3T4R;
2966 break;
2967 case RF_4T4R:
2968 rf_mac = HALMAC_RF_4T4R;
2969 break;
2970 default:
2971 rf_mac = HALMAC_RF_MAX_TYPE;
2972 RTW_ERR("%s: Invalid RF type(0x%x)!\n", __FUNCTION__, rf_drv);
2973 break;
2974 }
2975
2976 return rf_mac;
2977 }
2978
_rf_type_halmac2drv(enum halmac_rf_type rf_mac)2979 static inline enum rf_type _rf_type_halmac2drv(enum halmac_rf_type rf_mac)
2980 {
2981 enum rf_type rf_drv;
2982
2983
2984 switch (rf_mac) {
2985 case HALMAC_RF_1T2R:
2986 rf_drv = RF_1T2R;
2987 break;
2988 case HALMAC_RF_2T4R:
2989 rf_drv = RF_2T4R;
2990 break;
2991 case HALMAC_RF_2T2R:
2992 case HALMAC_RF_2T2R_GREEN:
2993 rf_drv = RF_2T2R;
2994 break;
2995 case HALMAC_RF_2T3R:
2996 rf_drv = RF_2T3R;
2997 break;
2998 case HALMAC_RF_1T1R:
2999 rf_drv = RF_1T1R;
3000 break;
3001 case HALMAC_RF_3T3R:
3002 rf_drv = RF_3T3R;
3003 break;
3004 case HALMAC_RF_3T4R:
3005 rf_drv = RF_3T4R;
3006 break;
3007 case HALMAC_RF_4T4R:
3008 rf_drv = RF_4T4R;
3009 break;
3010 default:
3011 rf_drv = RF_TYPE_MAX;
3012 RTW_ERR("%s: Invalid RF type(0x%x)!\n", __FUNCTION__, rf_mac);
3013 break;
3014 }
3015
3016 return rf_drv;
3017 }
3018
_cut_version_drv2phydm(enum tag_HAL_Cut_Version_Definition cut_drv)3019 static enum odm_cut_version _cut_version_drv2phydm(
3020 enum tag_HAL_Cut_Version_Definition cut_drv)
3021 {
3022 enum odm_cut_version cut_phydm = ODM_CUT_A;
3023 u32 diff;
3024
3025
3026 if (cut_drv > K_CUT_VERSION)
3027 RTW_WARN("%s: unknown cut_ver=%d !!\n", __FUNCTION__, cut_drv);
3028
3029 diff = cut_drv - A_CUT_VERSION;
3030 cut_phydm += diff;
3031
3032 return cut_phydm;
3033 }
3034
_send_general_info_by_reg(struct dvobj_priv * d,struct halmac_general_info * info)3035 static int _send_general_info_by_reg(struct dvobj_priv *d,
3036 struct halmac_general_info *info)
3037 {
3038 struct _ADAPTER *a;
3039 struct hal_com_data *hal;
3040 enum tag_HAL_Cut_Version_Definition cut_drv;
3041 enum rf_type rftype;
3042 enum odm_cut_version cut_phydm;
3043 u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
3044
3045
3046 a = dvobj_get_primary_adapter(d);
3047 hal = GET_HAL_DATA(a);
3048 rftype = _rf_type_halmac2drv(info->rf_type);
3049 cut_drv = GET_CVID_CUT_VERSION(hal->version_id);
3050 cut_phydm = _cut_version_drv2phydm(cut_drv);
3051
3052 #define CLASS_GENERAL_INFO_REG 0x02
3053 #define CMD_ID_GENERAL_INFO_REG 0x0C
3054 #define GENERAL_INFO_REG_SET_CMD_ID(buf, v) SET_BITS_TO_LE_4BYTE(buf, 0, 5, v)
3055 #define GENERAL_INFO_REG_SET_CLASS(buf, v) SET_BITS_TO_LE_4BYTE(buf, 5, 3, v)
3056 #define GENERAL_INFO_REG_SET_RFE_TYPE(buf, v) SET_BITS_TO_LE_4BYTE(buf, 8, 8, v)
3057 #define GENERAL_INFO_REG_SET_RF_TYPE(buf, v) SET_BITS_TO_LE_4BYTE(buf, 16, 8, v)
3058 #define GENERAL_INFO_REG_SET_CUT_VERSION(buf, v) SET_BITS_TO_LE_4BYTE(buf, 24, 8, v)
3059 #define GENERAL_INFO_REG_SET_RX_ANT_STATUS(buf, v) SET_BITS_TO_LE_1BYTE(buf+4, 0, 4, v)
3060 #define GENERAL_INFO_REG_SET_TX_ANT_STATUS(buf, v) SET_BITS_TO_LE_1BYTE(buf+4, 4, 4, v)
3061
3062 GENERAL_INFO_REG_SET_CMD_ID(h2c, CMD_ID_GENERAL_INFO_REG);
3063 GENERAL_INFO_REG_SET_CLASS(h2c, CLASS_GENERAL_INFO_REG);
3064 GENERAL_INFO_REG_SET_RFE_TYPE(h2c, info->rfe_type);
3065 GENERAL_INFO_REG_SET_RF_TYPE(h2c, rftype);
3066 GENERAL_INFO_REG_SET_CUT_VERSION(h2c, cut_phydm);
3067 GENERAL_INFO_REG_SET_RX_ANT_STATUS(h2c, info->rx_ant_status);
3068 GENERAL_INFO_REG_SET_TX_ANT_STATUS(h2c, info->tx_ant_status);
3069
3070 return rtw_halmac_send_h2c(d, h2c);
3071 }
3072
_send_general_info(struct dvobj_priv * d)3073 static int _send_general_info(struct dvobj_priv *d)
3074 {
3075 struct _ADAPTER *adapter;
3076 struct hal_com_data *hal;
3077 struct halmac_adapter *halmac;
3078 struct halmac_api *api;
3079 struct halmac_general_info info;
3080 enum halmac_ret_status status;
3081 enum rf_type rf = RF_1T1R;
3082 enum bb_path txpath = BB_PATH_A;
3083 enum bb_path rxpath = BB_PATH_A;
3084 int err;
3085
3086
3087 adapter = dvobj_get_primary_adapter(d);
3088 hal = GET_HAL_DATA(adapter);
3089 halmac = dvobj_to_halmac(d);
3090 if (!halmac)
3091 return -1;
3092 api = HALMAC_GET_API(halmac);
3093
3094 _rtw_memset(&info, 0, sizeof(info));
3095 info.rfe_type = (u8)hal->rfe_type;
3096 rtw_hal_get_trx_path(d, &rf, &txpath, &rxpath);
3097 info.rf_type = _rf_type_drv2halmac(rf);
3098 info.tx_ant_status = (u8)txpath;
3099 info.rx_ant_status = (u8)rxpath;
3100 info.ext_pa = 0; /* 2.4G or 5G? format not known */
3101 info.package_type = hal->PackageType;
3102 info.mp_mode = adapter->registrypriv.mp_mode;
3103
3104 status = api->halmac_send_general_info(halmac, &info);
3105 switch (status) {
3106 case HALMAC_RET_SUCCESS:
3107 break;
3108 case HALMAC_RET_NO_DLFW:
3109 RTW_WARN("%s: halmac_send_general_info() fail because fw not dl!\n",
3110 __FUNCTION__);
3111 /* fall through */
3112 default:
3113 return -1;
3114 }
3115
3116 err = _send_general_info_by_reg(d, &info);
3117 if (err) {
3118 RTW_ERR("%s: Fail to send general info by register!\n",
3119 __FUNCTION__);
3120 return -1;
3121 }
3122
3123 return 0;
3124 }
3125
_cfg_drv_rsvd_pg_num(struct dvobj_priv * d)3126 static int _cfg_drv_rsvd_pg_num(struct dvobj_priv *d)
3127 {
3128 struct _ADAPTER *a;
3129 struct hal_com_data *hal;
3130 struct halmac_adapter *halmac;
3131 struct halmac_api *api;
3132 enum halmac_drv_rsvd_pg_num rsvd_page_number;
3133 enum halmac_ret_status status;
3134 u16 drv_rsvd_num;
3135 int ret = 0;
3136
3137
3138 a = dvobj_get_primary_adapter(d);
3139 hal = GET_HAL_DATA(a);
3140 halmac = dvobj_to_halmac(d);
3141 api = HALMAC_GET_API(halmac);
3142
3143 drv_rsvd_num = rtw_hal_get_rsvd_page_num(a);
3144 rsvd_page_number = _rsvd_page_num_drv2halmac(drv_rsvd_num);
3145 status = api->halmac_cfg_drv_rsvd_pg_num(halmac, rsvd_page_number);
3146 if (status != HALMAC_RET_SUCCESS) {
3147 ret = -1;
3148 goto exit;
3149 }
3150 hal->drv_rsvd_page_number = _rsvd_page_num_halmac2drv(rsvd_page_number);
3151
3152 exit:
3153 #ifndef DBG_RSVD_PAGE_CFG
3154 if (drv_rsvd_num != _rsvd_page_num_halmac2drv(rsvd_page_number))
3155 #endif
3156 RTW_INFO("%s: request %d pages => halmac %d pages %s\n"
3157 , __FUNCTION__, drv_rsvd_num, _rsvd_page_num_halmac2drv(rsvd_page_number)
3158 , ret ? "fail" : "success");
3159
3160 return ret;
3161 }
3162
_debug_dlfw_fail(struct dvobj_priv * d)3163 static void _debug_dlfw_fail(struct dvobj_priv *d)
3164 {
3165 struct _ADAPTER *a;
3166 u32 addr;
3167 u32 v32, i, n;
3168
3169
3170 a = dvobj_get_primary_adapter(d);
3171
3172 /* read 0x80[15:0], 0x10F8[31:0] once */
3173 addr = 0x80;
3174 v32 = rtw_read16(a, addr);
3175 RTW_PRINT("%s: 0x%X = 0x%04x\n", __FUNCTION__, addr, v32);
3176
3177 addr = 0x10F8;
3178 v32 = rtw_read32(a, addr);
3179 RTW_PRINT("%s: 0x%X = 0x%08x\n", __FUNCTION__, addr, v32);
3180
3181 /* read 0x10FC[31:0], 5 times */
3182 addr = 0x10FC;
3183 n = 5;
3184 for (i = 0; i < n; i++) {
3185 v32 = rtw_read32(a, addr);
3186 RTW_PRINT("%s: 0x%X = 0x%08x (%u/%u)\n",
3187 __FUNCTION__, addr, v32, i, n);
3188 }
3189
3190 /*
3191 * write 0x3A[7:0]=0x28 and 0xF6[7:0]=0x01
3192 * and then read 0xC0[31:0] 5 times
3193 */
3194 addr = 0x3A;
3195 v32 = 0x28;
3196 rtw_write8(a, addr, (u8)v32);
3197 v32 = rtw_read8(a, addr);
3198 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v32);
3199
3200 addr = 0xF6;
3201 v32 = 0x1;
3202 rtw_write8(a, addr, (u8)v32);
3203 v32 = rtw_read8(a, addr);
3204 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v32);
3205
3206 addr = 0xC0;
3207 n = 5;
3208 for (i = 0; i < n; i++) {
3209 v32 = rtw_read32(a, addr);
3210 RTW_PRINT("%s: 0x%X = 0x%08x (%u/%u)\n",
3211 __FUNCTION__, addr, v32, i, n);
3212 }
3213
3214 mac_reg_dump(NULL, a);
3215 #ifdef CONFIG_SDIO_HCI
3216 RTW_PRINT("======= SDIO Local REG =======\n");
3217 sdio_local_reg_dump(NULL, a);
3218 RTW_PRINT("======= SDIO CCCR REG =======\n");
3219 sd_f0_reg_dump(NULL, a);
3220 #endif /* CONFIG_SDIO_HCI */
3221
3222 /* read 0x80 after 10 secs */
3223 rtw_msleep_os(10000);
3224 addr = 0x80;
3225 v32 = rtw_read16(a, addr);
3226 RTW_PRINT("%s: 0x%X = 0x%04x (after 10 secs)\n",
3227 __FUNCTION__, addr, v32);
3228 }
3229
_enter_cpu_sleep_mode(struct dvobj_priv * d)3230 static enum halmac_ret_status _enter_cpu_sleep_mode(struct dvobj_priv *d)
3231 {
3232 struct hal_com_data *hal;
3233 struct halmac_adapter *mac;
3234 struct halmac_api *api;
3235
3236
3237 hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
3238 mac = dvobj_to_halmac(d);
3239 api = HALMAC_GET_API(mac);
3240
3241 #ifdef CONFIG_RTL8822B
3242 /* Support after firmware version 21 */
3243 if (hal->firmware_version < 21)
3244 return HALMAC_RET_NOT_SUPPORT;
3245 #elif defined(CONFIG_RTL8821C)
3246 /* Support after firmware version 13.6 or 16 */
3247 if (hal->firmware_version == 13) {
3248 if (hal->firmware_sub_version < 6)
3249 return HALMAC_RET_NOT_SUPPORT;
3250 } else if (hal->firmware_version < 16) {
3251 return HALMAC_RET_NOT_SUPPORT;
3252 }
3253 #endif
3254
3255 return api->halmac_enter_cpu_sleep_mode(mac);
3256 }
3257
3258 /*
3259 * _cpu_sleep() - Let IC CPU enter sleep mode
3260 * @d: struct dvobj_priv*
3261 * @timeout: time limit of wait, unit is ms
3262 * 0 for no limit
3263 *
3264 * Return 0 for CPU in sleep mode, otherwise fail to enter sleep mode.
3265 * Error codes definition are as follow:
3266 * -1 HALMAC enter sleep return fail
3267 * -2 HALMAC get CPU mode return fail
3268 * -110 timeout
3269 */
_cpu_sleep(struct dvobj_priv * d,u32 timeout)3270 static int _cpu_sleep(struct dvobj_priv *d, u32 timeout)
3271 {
3272 struct halmac_adapter *mac;
3273 struct halmac_api *api;
3274 enum halmac_ret_status status;
3275 enum halmac_wlcpu_mode mode = HALMAC_WLCPU_UNDEFINE;
3276 systime start_t;
3277 s32 period = 0;
3278 u32 cnt = 0;
3279 int err = 0;
3280
3281
3282 mac = dvobj_to_halmac(d);
3283 api = HALMAC_GET_API(mac);
3284
3285 start_t = rtw_get_current_time();
3286
3287 status = _enter_cpu_sleep_mode(d);
3288 if (status != HALMAC_RET_SUCCESS) {
3289 if (status != HALMAC_RET_NOT_SUPPORT)
3290 err = -1;
3291 goto exit;
3292 }
3293
3294 do {
3295 cnt++;
3296
3297 mode = HALMAC_WLCPU_UNDEFINE;
3298 status = api->halmac_get_cpu_mode(mac, &mode);
3299
3300 period = rtw_get_passing_time_ms(start_t);
3301
3302 if (status != HALMAC_RET_SUCCESS) {
3303 err = -2;
3304 break;
3305 }
3306 if (mode == HALMAC_WLCPU_SLEEP)
3307 break;
3308 if (period > timeout) {
3309 err = -110;
3310 break;
3311 }
3312
3313 rtw_msleep_os(1);
3314 } while (1);
3315
3316 exit:
3317 if (err)
3318 RTW_ERR("%s: Fail to enter sleep mode! (%d, %d)\n",
3319 __FUNCTION__, status, mode);
3320
3321 RTW_INFO("%s: Cost %dms to polling %u times. (err=%d)\n",
3322 __FUNCTION__, period, cnt, err);
3323
3324 return err;
3325 }
3326
_init_trx_cfg_drv(struct dvobj_priv * d)3327 static void _init_trx_cfg_drv(struct dvobj_priv *d)
3328 {
3329 #ifdef CONFIG_PCI_HCI
3330 rtw_hal_irp_reset(dvobj_get_primary_adapter(d));
3331 #endif
3332 }
3333
3334 /*
3335 * Description:
3336 * Downlaod Firmware Flow
3337 *
3338 * Parameters:
3339 * d pointer of struct dvobj_priv
3340 * fw firmware array
3341 * fwsize firmware size
3342 * re_dl re-download firmware or not
3343 * 0: run in init hal flow, not re-download
3344 * 1: it is a stand alone operation, not in init hal flow
3345 *
3346 * Return:
3347 * 0 Success
3348 * others Fail
3349 */
download_fw(struct dvobj_priv * d,u8 * fw,u32 fwsize,u8 re_dl)3350 static int download_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize, u8 re_dl)
3351 {
3352 PHAL_DATA_TYPE hal;
3353 struct halmac_adapter *mac;
3354 struct halmac_api *api;
3355 struct halmac_fw_version fw_vesion;
3356 enum halmac_ret_status status;
3357 int err = 0;
3358
3359
3360 hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
3361 mac = dvobj_to_halmac(d);
3362 api = HALMAC_GET_API(mac);
3363
3364 if ((!fw) || (!fwsize))
3365 return -1;
3366
3367 /* 1. Driver Stop Tx */
3368 /* ToDo */
3369
3370 /* 2. Driver Check Tx FIFO is empty */
3371 err = rtw_halmac_txfifo_wait_empty(d, 2000); /* wait 2s */
3372 if (err) {
3373 err = -1;
3374 goto resume_tx;
3375 }
3376
3377 /* 3. Config MAX download size */
3378 /*
3379 * Already done in rtw_halmac_init_adapter() or
3380 * somewhere calling rtw_halmac_set_max_dl_fw_size().
3381 */
3382
3383 if (re_dl) {
3384 /* 4. Enter IC CPU sleep mode */
3385 err = _cpu_sleep(d, 2000);
3386 if (err) {
3387 RTW_ERR("%s: IC CPU fail to enter sleep mode!(%d)\n",
3388 __FUNCTION__, err);
3389 /* skip this error */
3390 err = 0;
3391 }
3392 }
3393
3394 /* 5. Download Firmware */
3395 status = api->halmac_download_firmware(mac, fw, fwsize);
3396 if (status != HALMAC_RET_SUCCESS) {
3397 RTW_ERR("%s: download firmware FAIL! status=0x%02x\n",
3398 __FUNCTION__, status);
3399 _debug_dlfw_fail(d);
3400 err = -1;
3401 goto resume_tx;
3402 }
3403
3404 /* 5.1. (Driver) Reset driver variables if needed */
3405 hal->LastHMEBoxNum = 0;
3406
3407 /* 5.2. (Driver) Get FW version */
3408 status = api->halmac_get_fw_version(mac, &fw_vesion);
3409 if (status == HALMAC_RET_SUCCESS) {
3410 hal->firmware_version = fw_vesion.version;
3411 hal->firmware_sub_version = fw_vesion.sub_version;
3412 hal->firmware_size = fwsize;
3413 }
3414
3415 resume_tx:
3416 /* 6. Driver resume TX if needed */
3417 /* ToDo */
3418
3419 if (err)
3420 goto exit;
3421
3422 if (re_dl) {
3423 enum halmac_trx_mode mode;
3424
3425 /* 7. Change reserved page size */
3426 err = _cfg_drv_rsvd_pg_num(d);
3427 if (err)
3428 return -1;
3429
3430 /* 8. Init TRX Configuration */
3431 mode = _choose_trx_mode(d);
3432 status = api->halmac_init_trx_cfg(mac, mode);
3433 if (HALMAC_RET_SUCCESS != status)
3434 return -1;
3435 _init_trx_cfg_drv(d);
3436
3437 /* 9. Config RX Aggregation */
3438 err = rtw_halmac_rx_agg_switch(d, _TRUE);
3439 if (err)
3440 return -1;
3441
3442 /* 10. Send General Info */
3443 err = _send_general_info(d);
3444 if (err)
3445 return -1;
3446 }
3447
3448 exit:
3449 return err;
3450 }
3451
init_mac_flow(struct dvobj_priv * d)3452 static int init_mac_flow(struct dvobj_priv *d)
3453 {
3454 PADAPTER p;
3455 struct hal_com_data *hal;
3456 struct halmac_adapter *halmac;
3457 struct halmac_api *api;
3458 enum halmac_drv_rsvd_pg_num rsvd_page_number;
3459 union halmac_wlan_addr hwa;
3460 enum halmac_trx_mode trx_mode;
3461 enum halmac_ret_status status;
3462 u8 drv_rsvd_num;
3463 u8 nettype;
3464 int err, err_ret = -1;
3465
3466
3467 p = dvobj_get_primary_adapter(d);
3468 hal = GET_HAL_DATA(p);
3469 halmac = dvobj_to_halmac(d);
3470 api = HALMAC_GET_API(halmac);
3471
3472 #ifdef CONFIG_SUPPORT_TRX_SHARED
3473 status = api->halmac_cfg_rxff_expand_mode(halmac,
3474 _rtw_get_trx_share_mode(p));
3475 if (status != HALMAC_RET_SUCCESS)
3476 goto out;
3477 #endif
3478
3479 #ifdef DBG_LA_MODE
3480 if (dvobj_to_regsty(d)->la_mode_en) {
3481 status = api->halmac_cfg_la_mode(halmac, HALMAC_LA_MODE_PARTIAL);
3482 if (status != HALMAC_RET_SUCCESS) {
3483 RTW_ERR("%s: Fail to enable LA mode!\n", __FUNCTION__);
3484 goto out;
3485 }
3486 RTW_PRINT("%s: Enable LA mode OK.\n", __FUNCTION__);
3487 }
3488 #endif
3489
3490 err = _cfg_drv_rsvd_pg_num(d);
3491 if (err)
3492 goto out;
3493
3494 #ifdef CONFIG_USB_HCI
3495 status = api->halmac_set_bulkout_num(halmac, d->RtNumOutPipes);
3496 if (status != HALMAC_RET_SUCCESS)
3497 goto out;
3498 #endif /* CONFIG_USB_HCI */
3499
3500 trx_mode = _choose_trx_mode(d);
3501 status = api->halmac_init_mac_cfg(halmac, trx_mode);
3502 if (status != HALMAC_RET_SUCCESS)
3503 goto out;
3504
3505 /* Driver insert flow: Sync driver setting with register */
3506 /* Sync driver RCR cache with register setting */
3507 rtw_hal_get_hwreg(dvobj_get_primary_adapter(d), HW_VAR_RCR, NULL);
3508
3509 #ifdef CONFIG_RTS_FULL_BW
3510 err = rtw_halmac_set_rts_full_bw(d, _TRUE);
3511 if (err)
3512 RTW_WARN("%s: Fail to set RTS FULL BW mode\n", __FUNCTION__);
3513 #else
3514 err = rtw_halmac_set_rts_full_bw(d, _FALSE);
3515 if (err)
3516 RTW_WARN("%s: Fail to disable RTS FULL BW mode\n", __FUNCTION__);
3517 #endif /* CONFIG_RTS_FULL_BW */
3518
3519 _init_trx_cfg_drv(d);
3520 /* Driver inser flow end */
3521
3522 err = rtw_halmac_rx_agg_switch(d, _TRUE);
3523 if (err)
3524 goto out;
3525
3526 nettype = dvobj_to_regsty(d)->wireless_mode;
3527 if (is_supported_vht(nettype) == _TRUE)
3528 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_AC);
3529 else if (is_supported_ht(nettype) == _TRUE)
3530 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_N);
3531 else if (IsSupportedTxOFDM(nettype) == _TRUE)
3532 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_G);
3533 else
3534 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_B);
3535 if (status != HALMAC_RET_SUCCESS)
3536 goto out;
3537
3538 err_ret = 0;
3539 out:
3540 return err_ret;
3541 }
3542
_drv_enable_trx(struct dvobj_priv * d)3543 static int _drv_enable_trx(struct dvobj_priv *d)
3544 {
3545 struct _ADAPTER *adapter;
3546 u32 status;
3547
3548
3549 adapter = dvobj_get_primary_adapter(d);
3550 if (adapter->bup == _FALSE) {
3551 #ifdef CONFIG_NEW_NETDEV_HDL
3552 status = rtw_mi_start_drv_threads(adapter);
3553 #else
3554 status = rtw_start_drv_threads(adapter);
3555 #endif
3556 if (status == _FAIL) {
3557 RTW_ERR("%s: Start threads Failed!\n", __FUNCTION__);
3558 return -1;
3559 }
3560 }
3561
3562 rtw_intf_start(adapter);
3563
3564 return 0;
3565 }
3566
3567 /*
3568 * Notices:
3569 * Make sure following information
3570 * 1. GET_HAL_RFPATH
3571 * 2. GET_HAL_DATA(dvobj_get_primary_adapter(d))->rfe_type
3572 * 3. GET_HAL_DATA(dvobj_get_primary_adapter(d))->PackageType
3573 * 4. dvobj_get_primary_adapter(d)->registrypriv.mp_mode
3574 * are all ready before calling this function.
3575 */
_halmac_init_hal(struct dvobj_priv * d,u8 * fw,u32 fwsize)3576 static int _halmac_init_hal(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3577 {
3578 PADAPTER adapter;
3579 struct halmac_adapter *halmac;
3580 struct halmac_api *api;
3581 enum halmac_ret_status status;
3582 u32 ok;
3583 u8 fw_ok = _FALSE;
3584 int err, err_ret = -1;
3585
3586
3587 adapter = dvobj_get_primary_adapter(d);
3588 halmac = dvobj_to_halmac(d);
3589 if (!halmac)
3590 goto out;
3591 api = HALMAC_GET_API(halmac);
3592
3593 /* StatePowerOff */
3594
3595 /* SKIP: halmac_init_adapter (Already done before) */
3596
3597 /* halmac_pre_Init_system_cfg */
3598 /* halmac_mac_power_switch(on) */
3599 /* halmac_Init_system_cfg */
3600 ok = rtw_hal_power_on(adapter);
3601 if (_FAIL == ok)
3602 goto out;
3603
3604 /* StatePowerOn */
3605
3606 /* DownloadFW */
3607 if (fw && fwsize) {
3608 err = download_fw(d, fw, fwsize, 0);
3609 if (err)
3610 goto out;
3611 fw_ok = _TRUE;
3612 }
3613
3614 /* InitMACFlow */
3615 err = init_mac_flow(d);
3616 if (err)
3617 goto out;
3618
3619 /* Driver insert flow: Enable TR/RX */
3620 err = _drv_enable_trx(d);
3621 if (err)
3622 goto out;
3623
3624 /* halmac_send_general_info */
3625 if (_TRUE == fw_ok) {
3626 err = _send_general_info(d);
3627 if (err)
3628 goto out;
3629 }
3630
3631 /* Init Phy parameter-MAC */
3632 ok = rtw_hal_init_mac_register(adapter);
3633 if (_FALSE == ok)
3634 goto out;
3635
3636 /* StateMacInitialized */
3637
3638 /* halmac_cfg_drv_info */
3639 err = rtw_halmac_config_rx_info(d, HALMAC_DRV_INFO_PHY_STATUS);
3640 if (err)
3641 goto out;
3642
3643 /* halmac_set_hw_value(HALMAC_HW_EN_BB_RF) */
3644 /* Init BB, RF */
3645 ok = rtw_hal_init_phy(adapter);
3646 if (_FALSE == ok)
3647 goto out;
3648
3649 status = api->halmac_init_interface_cfg(halmac);
3650 if (status != HALMAC_RET_SUCCESS)
3651 goto out;
3652
3653 /* SKIP: halmac_verify_platform_api */
3654 /* SKIP: halmac_h2c_lb */
3655
3656 /* StateRxIdle */
3657
3658 err_ret = 0;
3659 out:
3660 return err_ret;
3661 }
3662
rtw_halmac_init_hal(struct dvobj_priv * d)3663 int rtw_halmac_init_hal(struct dvobj_priv *d)
3664 {
3665 return _halmac_init_hal(d, NULL, 0);
3666 }
3667
3668 /*
3669 * Notices:
3670 * Make sure following information
3671 * 1. GET_HAL_RFPATH
3672 * 2. GET_HAL_DATA(dvobj_get_primary_adapter(d))->rfe_type
3673 * 3. GET_HAL_DATA(dvobj_get_primary_adapter(d))->PackageType
3674 * 4. dvobj_get_primary_adapter(d)->registrypriv.mp_mode
3675 * are all ready before calling this function.
3676 */
rtw_halmac_init_hal_fw(struct dvobj_priv * d,u8 * fw,u32 fwsize)3677 int rtw_halmac_init_hal_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3678 {
3679 return _halmac_init_hal(d, fw, fwsize);
3680 }
3681
3682 /*
3683 * Notices:
3684 * Make sure following information
3685 * 1. GET_HAL_RFPATH
3686 * 2. GET_HAL_DATA(dvobj_get_primary_adapter(d))->rfe_type
3687 * 3. GET_HAL_DATA(dvobj_get_primary_adapter(d))->PackageType
3688 * 4. dvobj_get_primary_adapter(d)->registrypriv.mp_mode
3689 * are all ready before calling this function.
3690 */
rtw_halmac_init_hal_fw_file(struct dvobj_priv * d,u8 * fwpath)3691 int rtw_halmac_init_hal_fw_file(struct dvobj_priv *d, u8 *fwpath)
3692 {
3693 u8 *fw = NULL;
3694 u32 fwmaxsize = 0, size = 0;
3695 int err = 0;
3696
3697
3698 err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3699 if (err) {
3700 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3701 return -1;
3702 }
3703
3704 fw = rtw_zmalloc(fwmaxsize);
3705 if (!fw)
3706 return -1;
3707
3708 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3709 if (!size) {
3710 err = -1;
3711 goto exit;
3712 }
3713
3714 err = _halmac_init_hal(d, fw, size);
3715
3716 exit:
3717 rtw_mfree(fw, fwmaxsize);
3718 /*fw = NULL;*/
3719
3720 return err;
3721 }
3722
rtw_halmac_deinit_hal(struct dvobj_priv * d)3723 int rtw_halmac_deinit_hal(struct dvobj_priv *d)
3724 {
3725 PADAPTER adapter;
3726 struct halmac_adapter *halmac;
3727 struct halmac_api *api;
3728 enum halmac_ret_status status;
3729 int err = -1;
3730
3731
3732 adapter = dvobj_get_primary_adapter(d);
3733 halmac = dvobj_to_halmac(d);
3734 if (!halmac)
3735 goto out;
3736 api = HALMAC_GET_API(halmac);
3737
3738 status = api->halmac_deinit_interface_cfg(halmac);
3739 if (status != HALMAC_RET_SUCCESS)
3740 goto out;
3741
3742 rtw_hal_power_off(adapter);
3743
3744 err = 0;
3745 out:
3746 return err;
3747 }
3748
rtw_halmac_self_verify(struct dvobj_priv * d)3749 int rtw_halmac_self_verify(struct dvobj_priv *d)
3750 {
3751 struct halmac_adapter *mac;
3752 struct halmac_api *api;
3753 enum halmac_ret_status status;
3754 int err = -1;
3755
3756
3757 mac = dvobj_to_halmac(d);
3758 api = HALMAC_GET_API(mac);
3759
3760 status = api->halmac_verify_platform_api(mac);
3761 if (status != HALMAC_RET_SUCCESS)
3762 goto out;
3763
3764 status = api->halmac_h2c_lb(mac);
3765 if (status != HALMAC_RET_SUCCESS)
3766 goto out;
3767
3768 err = 0;
3769 out:
3770 return err;
3771 }
3772
rtw_halmac_txfifo_is_empty(struct dvobj_priv * d)3773 static u8 rtw_halmac_txfifo_is_empty(struct dvobj_priv *d)
3774 {
3775 struct halmac_adapter *mac;
3776 struct halmac_api *api;
3777 enum halmac_ret_status status;
3778 u32 chk_num = 10;
3779 u8 rst = _FALSE;
3780
3781
3782 mac = dvobj_to_halmac(d);
3783 api = HALMAC_GET_API(mac);
3784
3785 status = api->halmac_txfifo_is_empty(mac, chk_num);
3786 if (status == HALMAC_RET_SUCCESS)
3787 rst = _TRUE;
3788
3789 return rst;
3790 }
3791
3792 /**
3793 * rtw_halmac_txfifo_wait_empty() - Wait TX FIFO to be emtpy
3794 * @d: struct dvobj_priv*
3795 * @timeout: time limit of wait, unit is ms
3796 * 0 for no limit
3797 *
3798 * Wait TX FIFO to be emtpy.
3799 *
3800 * Return 0 for TX FIFO is empty, otherwise not empty.
3801 */
rtw_halmac_txfifo_wait_empty(struct dvobj_priv * d,u32 timeout)3802 int rtw_halmac_txfifo_wait_empty(struct dvobj_priv *d, u32 timeout)
3803 {
3804 struct _ADAPTER *a;
3805 u8 empty = _FALSE;
3806 u32 cnt = 0;
3807 systime start_time = 0;
3808 u32 pass_time; /* ms */
3809
3810
3811 a = dvobj_get_primary_adapter(d);
3812 start_time = rtw_get_current_time();
3813
3814 do {
3815 cnt++;
3816 empty = rtw_halmac_txfifo_is_empty(d);
3817 if (empty == _TRUE)
3818 break;
3819
3820 if (timeout) {
3821 pass_time = rtw_get_passing_time_ms(start_time);
3822 if (pass_time > timeout)
3823 break;
3824 }
3825 if (RTW_CANNOT_IO(a)) {
3826 RTW_WARN("%s: Interrupted by I/O forbiden!\n", __FUNCTION__);
3827 break;
3828 }
3829
3830 rtw_msleep_os(2);
3831 } while (1);
3832
3833 if (empty == _FALSE) {
3834 #ifdef CONFIG_RTW_DEBUG
3835 u16 dbg_reg[] = {0x210, 0x230, 0x234, 0x238, 0x23C, 0x240,
3836 0x418, 0x10FC, 0x10F8, 0x11F4, 0x11F8};
3837 u8 i;
3838 u32 val;
3839
3840 if (!RTW_CANNOT_IO(a)) {
3841 for (i = 0; i < ARRAY_SIZE(dbg_reg); i++) {
3842 val = rtw_read32(a, dbg_reg[i]);
3843 RTW_ERR("REG_%X:0x%08x\n", dbg_reg[i], val);
3844 }
3845 }
3846 #endif /* CONFIG_RTW_DEBUG */
3847
3848 RTW_ERR("%s: Fail to wait txfifo empty!(cnt=%d)\n",
3849 __FUNCTION__, cnt);
3850 return -1;
3851 }
3852
3853 return 0;
3854 }
3855
_fw_mem_drv2halmac(enum fw_mem mem,u8 tx_stop)3856 static enum halmac_dlfw_mem _fw_mem_drv2halmac(enum fw_mem mem, u8 tx_stop)
3857 {
3858 enum halmac_dlfw_mem mem_halmac = HALMAC_DLFW_MEM_UNDEFINE;
3859
3860
3861 switch (mem) {
3862 case FW_EMEM:
3863 if (tx_stop == _FALSE)
3864 mem_halmac = HALMAC_DLFW_MEM_EMEM_RSVD_PG;
3865 else
3866 mem_halmac = HALMAC_DLFW_MEM_EMEM;
3867 break;
3868
3869 case FW_IMEM:
3870 case FW_DMEM:
3871 mem_halmac = HALMAC_DLFW_MEM_UNDEFINE;
3872 break;
3873 }
3874
3875 return mem_halmac;
3876 }
3877
rtw_halmac_dlfw_mem(struct dvobj_priv * d,u8 * fw,u32 fwsize,enum fw_mem mem)3878 int rtw_halmac_dlfw_mem(struct dvobj_priv *d, u8 *fw, u32 fwsize, enum fw_mem mem)
3879 {
3880 struct halmac_adapter *mac;
3881 struct halmac_api *api;
3882 enum halmac_ret_status status;
3883 enum halmac_dlfw_mem dlfw_mem;
3884 u8 tx_stop = _FALSE;
3885 u32 chk_timeout = 2000; /* unit: ms */
3886 int err = 0;
3887
3888
3889 mac = dvobj_to_halmac(d);
3890 api = HALMAC_GET_API(mac);
3891
3892 if ((!fw) || (!fwsize))
3893 return -1;
3894
3895 #ifndef RTW_HALMAC_DLFW_MEM_NO_STOP_TX
3896 /* 1. Driver Stop Tx */
3897 /* ToDo */
3898
3899 /* 2. Driver Check Tx FIFO is empty */
3900 err = rtw_halmac_txfifo_wait_empty(d, chk_timeout);
3901 if (err)
3902 tx_stop = _FALSE;
3903 else
3904 tx_stop = _TRUE;
3905 #endif /* !RTW_HALMAC_DLFW_MEM_NO_STOP_TX */
3906
3907 /* 3. Download Firmware MEM */
3908 dlfw_mem = _fw_mem_drv2halmac(mem, tx_stop);
3909 if (dlfw_mem == HALMAC_DLFW_MEM_UNDEFINE) {
3910 err = -1;
3911 goto resume_tx;
3912 }
3913 status = api->halmac_free_download_firmware(mac, dlfw_mem, fw, fwsize);
3914 if (status != HALMAC_RET_SUCCESS) {
3915 RTW_ERR("%s: halmac_free_download_firmware fail(err=0x%x)\n",
3916 __FUNCTION__, status);
3917 err = -1;
3918 goto resume_tx;
3919 }
3920
3921 resume_tx:
3922 #ifndef RTW_HALMAC_DLFW_MEM_NO_STOP_TX
3923 /* 4. Driver resume TX if needed */
3924 /* ToDo */
3925 #endif /* !RTW_HALMAC_DLFW_MEM_NO_STOP_TX */
3926
3927 return err;
3928 }
3929
rtw_halmac_dlfw_mem_from_file(struct dvobj_priv * d,u8 * fwpath,enum fw_mem mem)3930 int rtw_halmac_dlfw_mem_from_file(struct dvobj_priv *d, u8 *fwpath, enum fw_mem mem)
3931 {
3932 u8 *fw = NULL;
3933 u32 fwmaxsize = 0, size = 0;
3934 int err = 0;
3935
3936
3937 err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3938 if (err) {
3939 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3940 return -1;
3941 }
3942
3943 fw = rtw_zmalloc(fwmaxsize);
3944 if (!fw)
3945 return -1;
3946
3947 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3948 if (size)
3949 err = rtw_halmac_dlfw_mem(d, fw, size, mem);
3950 else
3951 err = -1;
3952
3953 rtw_mfree(fw, fwmaxsize);
3954 /*fw = NULL;*/
3955
3956 return err;
3957 }
3958
3959 /*
3960 * Return:
3961 * 0 Success
3962 * -22 Invalid arguemnt
3963 */
rtw_halmac_dlfw(struct dvobj_priv * d,u8 * fw,u32 fwsize)3964 int rtw_halmac_dlfw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3965 {
3966 PADAPTER adapter;
3967 enum halmac_ret_status status;
3968 u32 ok;
3969 int err, err_ret = -1;
3970
3971
3972 if (!fw || !fwsize)
3973 return -22;
3974
3975 adapter = dvobj_get_primary_adapter(d);
3976
3977 /* re-download firmware */
3978 if (rtw_is_hw_init_completed(adapter))
3979 return download_fw(d, fw, fwsize, 1);
3980
3981 /* Download firmware before hal init */
3982 /* Power on, download firmware and init mac */
3983 ok = rtw_hal_power_on(adapter);
3984 if (_FAIL == ok)
3985 goto out;
3986
3987 err = download_fw(d, fw, fwsize, 0);
3988 if (err) {
3989 err_ret = err;
3990 goto out;
3991 }
3992
3993 err = init_mac_flow(d);
3994 if (err)
3995 goto out;
3996
3997 err = _send_general_info(d);
3998 if (err)
3999 goto out;
4000
4001 err_ret = 0;
4002
4003 out:
4004 return err_ret;
4005 }
4006
rtw_halmac_dlfw_from_file(struct dvobj_priv * d,u8 * fwpath)4007 int rtw_halmac_dlfw_from_file(struct dvobj_priv *d, u8 *fwpath)
4008 {
4009 u8 *fw = NULL;
4010 u32 fwmaxsize = 0, size = 0;
4011 int err = 0;
4012
4013
4014 err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
4015 if (err) {
4016 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
4017 return -1;
4018 }
4019
4020 fw = rtw_zmalloc(fwmaxsize);
4021 if (!fw)
4022 return -1;
4023
4024 size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
4025 if (size)
4026 err = rtw_halmac_dlfw(d, fw, size);
4027 else
4028 err = -1;
4029
4030 rtw_mfree(fw, fwmaxsize);
4031 /*fw = NULL;*/
4032
4033 return err;
4034 }
4035
4036 /*
4037 * Description:
4038 * Power on/off BB/RF domain.
4039 *
4040 * Parameters:
4041 * enable _TRUE/_FALSE for power on/off
4042 *
4043 * Return:
4044 * 0 Success
4045 * others Fail
4046 */
rtw_halmac_phy_power_switch(struct dvobj_priv * d,u8 enable)4047 int rtw_halmac_phy_power_switch(struct dvobj_priv *d, u8 enable)
4048 {
4049 PADAPTER adapter;
4050 struct halmac_adapter *halmac;
4051 struct halmac_api *api;
4052 enum halmac_ret_status status;
4053 u8 on;
4054
4055
4056 adapter = dvobj_get_primary_adapter(d);
4057 halmac = dvobj_to_halmac(d);
4058 if (!halmac)
4059 return -1;
4060 api = HALMAC_GET_API(halmac);
4061 on = (enable == _TRUE) ? 1 : 0;
4062
4063 status = api->halmac_set_hw_value(halmac, HALMAC_HW_EN_BB_RF, &on);
4064 if (status != HALMAC_RET_SUCCESS)
4065 return -1;
4066
4067 return 0;
4068 }
4069
_is_fw_read_cmd_down(PADAPTER adapter,u8 msgbox_num)4070 static u8 _is_fw_read_cmd_down(PADAPTER adapter, u8 msgbox_num)
4071 {
4072 u8 read_down = _FALSE;
4073 int retry_cnts = 100;
4074 u8 valid;
4075
4076 do {
4077 valid = rtw_read8(adapter, REG_HMETFR) & BIT(msgbox_num);
4078 if (0 == valid)
4079 read_down = _TRUE;
4080 else
4081 rtw_msleep_os(1);
4082 } while ((!read_down) && (retry_cnts--));
4083
4084 if (_FALSE == read_down)
4085 RTW_WARN("%s, reg_1cc(%x), msg_box(%d)...\n", __func__, rtw_read8(adapter, REG_HMETFR), msgbox_num);
4086
4087 return read_down;
4088 }
4089
4090 /**
4091 * rtw_halmac_send_h2c() - Send H2C to firmware
4092 * @d: struct dvobj_priv*
4093 * @h2c: H2C data buffer, suppose to be 8 bytes
4094 *
4095 * Send H2C to firmware by message box register(0x1D0~0x1D3 & 0x1F0~0x1F3).
4096 *
4097 * Assume firmware be ready to accept H2C here, please check
4098 * (hal->bFWReady == _TRUE) before call this function or make sure firmware is
4099 * ready.
4100 *
4101 * Return: 0 if process OK, otherwise fail to send this H2C.
4102 */
rtw_halmac_send_h2c(struct dvobj_priv * d,u8 * h2c)4103 int rtw_halmac_send_h2c(struct dvobj_priv *d, u8 *h2c)
4104 {
4105 PADAPTER adapter = dvobj_get_primary_adapter(d);
4106 PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
4107 u8 h2c_box_num = 0;
4108 u32 msgbox_addr = 0;
4109 u32 msgbox_ex_addr = 0;
4110 u32 h2c_cmd = 0;
4111 u32 h2c_cmd_ex = 0;
4112 int err = -1;
4113
4114
4115 if (!h2c) {
4116 RTW_WARN("%s: pbuf is NULL\n", __FUNCTION__);
4117 return err;
4118 }
4119
4120 if (rtw_is_surprise_removed(adapter)) {
4121 RTW_WARN("%s: surprise removed\n", __FUNCTION__);
4122 return err;
4123 }
4124
4125 _enter_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
4126
4127 /* pay attention to if race condition happened in H2C cmd setting */
4128 h2c_box_num = hal->LastHMEBoxNum;
4129
4130 if (!_is_fw_read_cmd_down(adapter, h2c_box_num)) {
4131 RTW_WARN(" fw read cmd failed...\n");
4132 #ifdef DBG_CONFIG_ERROR_DETECT
4133 hal->srestpriv.self_dect_fw = _TRUE;
4134 hal->srestpriv.self_dect_fw_cnt++;
4135 #endif /* DBG_CONFIG_ERROR_DETECT */
4136 goto exit;
4137 }
4138
4139 /* Write Ext command (byte 4~7) */
4140 msgbox_ex_addr = REG_HMEBOX_E0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
4141 _rtw_memcpy((u8 *)(&h2c_cmd_ex), h2c + 4, EX_MESSAGE_BOX_SIZE);
4142 h2c_cmd_ex = le32_to_cpu(h2c_cmd_ex);
4143 rtw_write32(adapter, msgbox_ex_addr, h2c_cmd_ex);
4144
4145 /* Write command (byte 0~3) */
4146 msgbox_addr = REG_HMEBOX0 + (h2c_box_num * MESSAGE_BOX_SIZE);
4147 _rtw_memcpy((u8 *)(&h2c_cmd), h2c, 4);
4148 h2c_cmd = le32_to_cpu(h2c_cmd);
4149 rtw_write32(adapter, msgbox_addr, h2c_cmd);
4150
4151 /* update last msg box number */
4152 hal->LastHMEBoxNum = (h2c_box_num + 1) % MAX_H2C_BOX_NUMS;
4153 err = 0;
4154
4155 #ifdef DBG_H2C_CONTENT
4156 RTW_INFO_DUMP("[H2C] - ", h2c, RTW_HALMAC_H2C_MAX_SIZE);
4157 #endif
4158 exit:
4159 _exit_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
4160 return err;
4161 }
4162
4163 /**
4164 * rtw_halmac_c2h_handle() - Handle C2H for HALMAC
4165 * @d: struct dvobj_priv*
4166 * @c2h: Full C2H packet, including RX description and payload
4167 * @size: Size(byte) of c2h
4168 *
4169 * Send C2H packet to HALMAC to process C2H packets, and the expected C2H ID is
4170 * 0xFF. This function won't have any I/O, so caller doesn't have to call it in
4171 * I/O safe place(ex. command thread).
4172 *
4173 * Please sure doesn't call this function in the same thread as someone is
4174 * waiting HALMAC C2H ack, otherwise there is a deadlock happen.
4175 *
4176 * Return: 0 if process OK, otherwise no action for this C2H.
4177 */
rtw_halmac_c2h_handle(struct dvobj_priv * d,u8 * c2h,u32 size)4178 int rtw_halmac_c2h_handle(struct dvobj_priv *d, u8 *c2h, u32 size)
4179 {
4180 struct halmac_adapter *mac;
4181 struct halmac_api *api;
4182 enum halmac_ret_status status;
4183 #ifdef RTW_HALMAC_FILTER_DRV_C2H
4184 u32 desc_size = 0;
4185 u8 *c2h_data;
4186 u8 sub;
4187 #endif /* RTW_HALMAC_FILTER_DRV_C2H */
4188
4189
4190 mac = dvobj_to_halmac(d);
4191 api = HALMAC_GET_API(mac);
4192
4193 #ifdef RTW_HALMAC_FILTER_DRV_C2H
4194 status = api->halmac_get_hw_value(mac, HALMAC_HW_RX_DESC_SIZE,
4195 &desc_size);
4196 if (status != HALMAC_RET_SUCCESS) {
4197 RTW_ERR("%s: fail to get rx desc size!\n", __FUNCTION__);
4198 goto skip_filter;
4199 }
4200
4201 c2h_data = c2h + desc_size;
4202 sub = C2H_HDR_GET_C2H_SUB_CMD_ID(c2h_data);
4203 switch (sub) {
4204 case C2H_SUB_CMD_ID_C2H_PKT_FTM_DBG:
4205 case C2H_SUB_CMD_ID_C2H_PKT_FTM_2_DBG:
4206 case C2H_SUB_CMD_ID_C2H_PKT_FTM_3_DBG:
4207 case C2H_SUB_CMD_ID_C2H_PKT_FTM_4_DBG:
4208 case C2H_SUB_CMD_ID_FTMACKRPT_HDL_DBG:
4209 case C2H_SUB_CMD_ID_FTMC2H_RPT:
4210 case C2H_SUB_CMD_ID_DRVFTMC2H_RPT:
4211 case C2H_SUB_CMD_ID_C2H_PKT_FTM_5_DBG:
4212 case C2H_SUB_CMD_ID_CCX_RPT:
4213 case C2H_SUB_CMD_ID_C2H_PKT_NAN_RPT:
4214 case C2H_SUB_CMD_ID_C2H_PKT_ATM_RPT:
4215 case C2H_SUB_CMD_ID_C2H_PKT_SCC_CSA_RPT:
4216 case C2H_SUB_CMD_ID_C2H_PKT_FW_STATUS_NOTIFY:
4217 case C2H_SUB_CMD_ID_C2H_PKT_FTMSESSION_END:
4218 case C2H_SUB_CMD_ID_C2H_PKT_DETECT_THERMAL:
4219 case C2H_SUB_CMD_ID_FW_FWCTRL_RPT:
4220 case C2H_SUB_CMD_ID_SCAN_CH_NOTIFY:
4221 case C2H_SUB_CMD_ID_FW_TBTT_RPT:
4222 case C2H_SUB_CMD_ID_BCN_OFFLOAD:
4223 case C2H_SUB_CMD_ID_FW_DBG_MSG:
4224 RTW_PRINT("%s: unhandled C2H, id=0xFF subid=0x%x len=%u\n",
4225 __FUNCTION__, sub, C2H_HDR_GET_LEN(c2h_data));
4226 RTW_PRINT_DUMP("C2H: ", c2h_data, size - desc_size);
4227 return 0;
4228 }
4229
4230 skip_filter:
4231 #endif /* RTW_HALMAC_FILTER_DRV_C2H */
4232
4233 status = api->halmac_get_c2h_info(mac, c2h, size);
4234 if (HALMAC_RET_SUCCESS != status)
4235 return -1;
4236
4237 return 0;
4238 }
4239
rtw_halmac_get_available_efuse_size(struct dvobj_priv * d,u32 * size)4240 int rtw_halmac_get_available_efuse_size(struct dvobj_priv *d, u32 *size)
4241 {
4242 struct halmac_adapter *mac;
4243 struct halmac_api *api;
4244 enum halmac_ret_status status;
4245 u32 val;
4246
4247
4248 mac = dvobj_to_halmac(d);
4249 api = HALMAC_GET_API(mac);
4250
4251 status = api->halmac_get_efuse_available_size(mac, &val);
4252 if (HALMAC_RET_SUCCESS != status)
4253 return -1;
4254
4255 *size = val;
4256 return 0;
4257 }
4258
rtw_halmac_get_physical_efuse_size(struct dvobj_priv * d,u32 * size)4259 int rtw_halmac_get_physical_efuse_size(struct dvobj_priv *d, u32 *size)
4260 {
4261 struct halmac_adapter *mac;
4262 struct halmac_api *api;
4263 enum halmac_ret_status status;
4264 u32 val;
4265
4266
4267 mac = dvobj_to_halmac(d);
4268 api = HALMAC_GET_API(mac);
4269
4270 status = api->halmac_get_efuse_size(mac, &val);
4271 if (HALMAC_RET_SUCCESS != status)
4272 return -1;
4273
4274 *size = val;
4275 return 0;
4276 }
4277
rtw_halmac_read_physical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size)4278 int rtw_halmac_read_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
4279 {
4280 struct halmac_adapter *mac;
4281 struct halmac_api *api;
4282 enum halmac_ret_status status;
4283 enum halmac_feature_id id;
4284 int ret;
4285
4286
4287 mac = dvobj_to_halmac(d);
4288 api = HALMAC_GET_API(mac);
4289 id = HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE;
4290
4291 ret = init_halmac_event(d, id, map, size);
4292 if (ret)
4293 return -1;
4294
4295 status = api->halmac_dump_efuse_map(mac, HALMAC_EFUSE_R_DRV);
4296 if (HALMAC_RET_SUCCESS != status) {
4297 free_halmac_event(d, id);
4298 return -1;
4299 }
4300
4301 ret = wait_halmac_event(d, id);
4302 if (ret)
4303 return -1;
4304
4305 return 0;
4306 }
4307
rtw_halmac_read_physical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4308 int rtw_halmac_read_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4309 {
4310 struct halmac_adapter *mac;
4311 struct halmac_api *api;
4312 enum halmac_ret_status status;
4313 u8 v;
4314 u32 i;
4315 u8 *efuse = NULL;
4316 u32 size = 0;
4317 int err = 0;
4318
4319
4320 mac = dvobj_to_halmac(d);
4321 api = HALMAC_GET_API(mac);
4322
4323 if (api->halmac_read_efuse) {
4324 for (i = 0; i < cnt; i++) {
4325 status = api->halmac_read_efuse(mac, offset + i, &v);
4326 if (HALMAC_RET_SUCCESS != status)
4327 return -1;
4328 data[i] = v;
4329 }
4330 } else {
4331 err = rtw_halmac_get_physical_efuse_size(d, &size);
4332 if (err)
4333 return -1;
4334
4335 efuse = rtw_zmalloc(size);
4336 if (!efuse)
4337 return -1;
4338
4339 err = rtw_halmac_read_physical_efuse_map(d, efuse, size);
4340 if (err)
4341 err = -1;
4342 else
4343 _rtw_memcpy(data, efuse + offset, cnt);
4344
4345 rtw_mfree(efuse, size);
4346 }
4347
4348 return err;
4349 }
4350
rtw_halmac_write_physical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4351 int rtw_halmac_write_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4352 {
4353 struct halmac_adapter *mac;
4354 struct halmac_api *api;
4355 enum halmac_ret_status status;
4356 u32 i;
4357
4358
4359 mac = dvobj_to_halmac(d);
4360 api = HALMAC_GET_API(mac);
4361
4362 if (api->halmac_write_efuse == NULL)
4363 return -1;
4364
4365 for (i = 0; i < cnt; i++) {
4366 status = api->halmac_write_efuse(mac, offset + i, data[i]);
4367 if (HALMAC_RET_SUCCESS != status)
4368 return -1;
4369 }
4370
4371 return 0;
4372 }
4373
rtw_halmac_get_logical_efuse_size(struct dvobj_priv * d,u32 * size)4374 int rtw_halmac_get_logical_efuse_size(struct dvobj_priv *d, u32 *size)
4375 {
4376 struct halmac_adapter *mac;
4377 struct halmac_api *api;
4378 enum halmac_ret_status status;
4379 u32 val;
4380
4381
4382 mac = dvobj_to_halmac(d);
4383 api = HALMAC_GET_API(mac);
4384
4385 status = api->halmac_get_logical_efuse_size(mac, &val);
4386 if (HALMAC_RET_SUCCESS != status)
4387 return -1;
4388
4389 *size = val;
4390 return 0;
4391 }
4392
rtw_halmac_read_logical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size,u8 * maskmap,u32 masksize)4393 int rtw_halmac_read_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
4394 {
4395 struct halmac_adapter *mac;
4396 struct halmac_api *api;
4397 enum halmac_ret_status status;
4398 enum halmac_feature_id id;
4399 int ret;
4400
4401
4402 mac = dvobj_to_halmac(d);
4403 api = HALMAC_GET_API(mac);
4404 id = HALMAC_FEATURE_DUMP_LOGICAL_EFUSE;
4405
4406 ret = init_halmac_event(d, id, map, size);
4407 if (ret)
4408 return -1;
4409
4410 status = api->halmac_dump_logical_efuse_map(mac, HALMAC_EFUSE_R_DRV);
4411 if (HALMAC_RET_SUCCESS != status) {
4412 free_halmac_event(d, id);
4413 return -1;
4414 }
4415
4416 ret = wait_halmac_event(d, id);
4417 if (ret)
4418 return -1;
4419
4420 if (maskmap && masksize) {
4421 struct halmac_pg_efuse_info pginfo;
4422
4423 pginfo.efuse_map = map;
4424 pginfo.efuse_map_size = size;
4425 pginfo.efuse_mask = maskmap;
4426 pginfo.efuse_mask_size = masksize;
4427
4428 status = api->halmac_mask_logical_efuse(mac, &pginfo);
4429 if (status != HALMAC_RET_SUCCESS)
4430 RTW_WARN("%s: mask logical efuse FAIL!\n", __FUNCTION__);
4431 }
4432
4433 return 0;
4434 }
4435
rtw_halmac_write_logical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size,u8 * maskmap,u32 masksize)4436 int rtw_halmac_write_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
4437 {
4438 struct halmac_adapter *mac;
4439 struct halmac_api *api;
4440 struct halmac_pg_efuse_info pginfo;
4441 enum halmac_ret_status status;
4442
4443
4444 mac = dvobj_to_halmac(d);
4445 api = HALMAC_GET_API(mac);
4446
4447 pginfo.efuse_map = map;
4448 pginfo.efuse_map_size = size;
4449 pginfo.efuse_mask = maskmap;
4450 pginfo.efuse_mask_size = masksize;
4451
4452 status = api->halmac_pg_efuse_by_map(mac, &pginfo, HALMAC_EFUSE_R_AUTO);
4453 if (HALMAC_RET_SUCCESS != status)
4454 return -1;
4455
4456 return 0;
4457 }
4458
rtw_halmac_read_logical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4459 int rtw_halmac_read_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4460 {
4461 struct halmac_adapter *mac;
4462 struct halmac_api *api;
4463 enum halmac_ret_status status;
4464 u8 v;
4465 u32 i;
4466
4467
4468 mac = dvobj_to_halmac(d);
4469 api = HALMAC_GET_API(mac);
4470
4471 for (i = 0; i < cnt; i++) {
4472 status = api->halmac_read_logical_efuse(mac, offset + i, &v);
4473 if (HALMAC_RET_SUCCESS != status)
4474 return -1;
4475 data[i] = v;
4476 }
4477
4478 return 0;
4479 }
4480
rtw_halmac_write_logical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4481 int rtw_halmac_write_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4482 {
4483 struct halmac_adapter *mac;
4484 struct halmac_api *api;
4485 enum halmac_ret_status status;
4486 u32 i;
4487
4488
4489 mac = dvobj_to_halmac(d);
4490 api = HALMAC_GET_API(mac);
4491
4492 for (i = 0; i < cnt; i++) {
4493 status = api->halmac_write_logical_efuse(mac, offset + i, data[i]);
4494 if (HALMAC_RET_SUCCESS != status)
4495 return -1;
4496 }
4497
4498 return 0;
4499 }
4500
rtw_halmac_write_bt_physical_efuse(struct dvobj_priv * d,u32 offset,u32 cnt,u8 * data)4501 int rtw_halmac_write_bt_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4502 {
4503 struct halmac_adapter *mac;
4504 struct halmac_api *api;
4505 enum halmac_ret_status status;
4506 u32 i;
4507 u8 bank = 1;
4508
4509
4510 mac = dvobj_to_halmac(d);
4511 api = HALMAC_GET_API(mac);
4512
4513 for (i = 0; i < cnt; i++) {
4514 status = api->halmac_write_efuse_bt(mac, offset + i, data[i], bank);
4515 if (HALMAC_RET_SUCCESS != status) {
4516 printk("%s: halmac_write_efuse_bt status = %d\n", __FUNCTION__, status);
4517 return -1;
4518 }
4519 }
4520 printk("%s: halmac_write_efuse_bt status = HALMAC_RET_SUCCESS %d\n", __FUNCTION__, status);
4521 return 0;
4522 }
4523
4524
rtw_halmac_read_bt_physical_efuse_map(struct dvobj_priv * d,u8 * map,u32 size)4525 int rtw_halmac_read_bt_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
4526 {
4527 struct halmac_adapter *mac;
4528 struct halmac_api *api;
4529 enum halmac_ret_status status;
4530 int bank = 1;
4531
4532
4533 mac = dvobj_to_halmac(d);
4534 api = HALMAC_GET_API(mac);
4535
4536 status = api->halmac_dump_efuse_map_bt(mac, bank, size, map);
4537 if (HALMAC_RET_SUCCESS != status) {
4538 printk("%s: halmac_dump_efuse_map_bt fail!\n", __FUNCTION__);
4539 return -1;
4540 }
4541
4542 printk("%s: OK!\n", __FUNCTION__);
4543
4544 return 0;
4545 }
4546
_fifo_sel_drv2halmac(u8 fifo_sel)4547 static enum hal_fifo_sel _fifo_sel_drv2halmac(u8 fifo_sel)
4548 {
4549 switch (fifo_sel) {
4550 case 0:
4551 return HAL_FIFO_SEL_TX;
4552 case 1:
4553 return HAL_FIFO_SEL_RX;
4554 case 2:
4555 return HAL_FIFO_SEL_RSVD_PAGE;
4556 case 3:
4557 return HAL_FIFO_SEL_REPORT;
4558 case 4:
4559 return HAL_FIFO_SEL_LLT;
4560 case 5:
4561 return HAL_FIFO_SEL_RXBUF_FW;
4562 }
4563
4564 return HAL_FIFO_SEL_RSVD_PAGE;
4565 }
4566
4567 /*#define CONFIG_HALMAC_FIFO_DUMP*/
rtw_halmac_dump_fifo(struct dvobj_priv * d,u8 fifo_sel,u32 addr,u32 size,u8 * buffer)4568 int rtw_halmac_dump_fifo(struct dvobj_priv *d, u8 fifo_sel, u32 addr, u32 size, u8 *buffer)
4569 {
4570 struct halmac_adapter *mac;
4571 struct halmac_api *api;
4572 enum hal_fifo_sel halmac_fifo_sel;
4573 enum halmac_ret_status status;
4574 u8 *pfifo_map = NULL;
4575 u32 fifo_size = 0;
4576 s8 ret = 0;/* 0:success, -1:error */
4577 u8 mem_created = _FALSE;
4578
4579
4580 mac = dvobj_to_halmac(d);
4581 api = HALMAC_GET_API(mac);
4582
4583 if ((size != 0) && (buffer == NULL))
4584 return -1;
4585
4586 halmac_fifo_sel = _fifo_sel_drv2halmac(fifo_sel);
4587
4588 if ((size) && (buffer)) {
4589 pfifo_map = buffer;
4590 fifo_size = size;
4591 } else {
4592 fifo_size = api->halmac_get_fifo_size(mac, halmac_fifo_sel);
4593
4594 if (fifo_size)
4595 pfifo_map = rtw_zvmalloc(fifo_size);
4596 if (pfifo_map == NULL)
4597 return -1;
4598 mem_created = _TRUE;
4599 }
4600
4601 status = api->halmac_dump_fifo(mac, halmac_fifo_sel, addr, fifo_size, pfifo_map);
4602 if (HALMAC_RET_SUCCESS != status) {
4603 ret = -1;
4604 goto _exit;
4605 }
4606
4607 #ifdef CONFIG_HALMAC_FIFO_DUMP
4608 {
4609 static const char * const fifo_sel_str[] = {
4610 "TX", "RX", "RSVD_PAGE", "REPORT", "LLT", "RXBUF_FW"
4611 };
4612
4613 RTW_INFO("%s FIFO DUMP [start_addr:0x%04x , size:%d]\n", fifo_sel_str[halmac_fifo_sel], addr, fifo_size);
4614 RTW_INFO_DUMP("\n", pfifo_map, fifo_size);
4615 RTW_INFO(" ==================================================\n");
4616 }
4617 #endif /* CONFIG_HALMAC_FIFO_DUMP */
4618
4619 _exit:
4620 if ((mem_created == _TRUE) && pfifo_map)
4621 rtw_vmfree(pfifo_map, fifo_size);
4622
4623 return ret;
4624 }
4625
4626 /*
4627 * rtw_halmac_rx_agg_switch() - Switch RX aggregation function and setting
4628 * @d struct dvobj_priv *
4629 * @enable _FALSE/_TRUE for disable/enable RX aggregation function
4630 *
4631 * This function could help to on/off bus RX aggregation function, and is only
4632 * useful for SDIO and USB interface. Although only "enable" flag is brough in,
4633 * some setting would be taken from other places, and they are from:
4634 * [DMA aggregation]
4635 * struct hal_com_data.rxagg_dma_size
4636 * struct hal_com_data.rxagg_dma_timeout
4637 * [USB aggregation] (only use for USB interface)
4638 * struct hal_com_data.rxagg_usb_size
4639 * struct hal_com_data.rxagg_usb_timeout
4640 * If above values of size and timeout are both 0 means driver would not
4641 * control the threshold setting and leave it to HALMAC handle.
4642 *
4643 * From HALMAC V1_04_04, driver force the size threshold be hard limit, and the
4644 * rx size can not exceed the setting.
4645 *
4646 * Return 0 for success, otherwise fail.
4647 */
rtw_halmac_rx_agg_switch(struct dvobj_priv * d,u8 enable)4648 int rtw_halmac_rx_agg_switch(struct dvobj_priv *d, u8 enable)
4649 {
4650 struct _ADAPTER *adapter;
4651 struct hal_com_data *hal;
4652 struct halmac_adapter *halmac;
4653 struct halmac_api *api;
4654 struct halmac_rxagg_cfg rxaggcfg;
4655 enum halmac_ret_status status;
4656
4657
4658 adapter = dvobj_get_primary_adapter(d);
4659 hal = GET_HAL_DATA(adapter);
4660 halmac = dvobj_to_halmac(d);
4661 api = HALMAC_GET_API(halmac);
4662 _rtw_memset((void *)&rxaggcfg, 0, sizeof(rxaggcfg));
4663 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
4664 /*
4665 * Always enable size limit to avoid rx size exceed
4666 * driver defined size.
4667 */
4668 rxaggcfg.threshold.size_limit_en = 1;
4669
4670 #ifdef RTW_RX_AGGREGATION
4671 if (_TRUE == enable) {
4672 #ifdef CONFIG_SDIO_HCI
4673 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
4674 rxaggcfg.threshold.drv_define = 0;
4675 if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
4676 rxaggcfg.threshold.drv_define = 1;
4677 rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
4678 rxaggcfg.threshold.size = hal->rxagg_dma_size;
4679 RTW_INFO("%s: RX aggregation threshold: "
4680 "timeout=%u size=%u\n",
4681 __FUNCTION__,
4682 hal->rxagg_dma_timeout,
4683 hal->rxagg_dma_size);
4684 }
4685 #elif defined(CONFIG_USB_HCI)
4686 switch (hal->rxagg_mode) {
4687 case RX_AGG_DISABLE:
4688 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
4689 break;
4690
4691 case RX_AGG_DMA:
4692 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
4693 if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
4694 rxaggcfg.threshold.drv_define = 1;
4695 rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
4696 rxaggcfg.threshold.size = hal->rxagg_dma_size;
4697 }
4698 break;
4699
4700 case RX_AGG_USB:
4701 case RX_AGG_MIX:
4702 rxaggcfg.mode = HALMAC_RX_AGG_MODE_USB;
4703 if (hal->rxagg_usb_size || hal->rxagg_usb_timeout) {
4704 rxaggcfg.threshold.drv_define = 1;
4705 rxaggcfg.threshold.timeout = hal->rxagg_usb_timeout;
4706 rxaggcfg.threshold.size = hal->rxagg_usb_size;
4707 }
4708 break;
4709 }
4710 #endif /* CONFIG_USB_HCI */
4711 }
4712 #endif /* RTW_RX_AGGREGATION */
4713
4714 status = api->halmac_cfg_rx_aggregation(halmac, &rxaggcfg);
4715 if (status != HALMAC_RET_SUCCESS)
4716 return -1;
4717
4718 return 0;
4719 }
4720
rtw_halmac_download_rsvd_page(struct dvobj_priv * dvobj,u8 pg_offset,u8 * pbuf,u32 size)4721 int rtw_halmac_download_rsvd_page(struct dvobj_priv *dvobj, u8 pg_offset, u8 *pbuf, u32 size)
4722 {
4723 enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4724 struct halmac_adapter *halmac = dvobj_to_halmac(dvobj);
4725 struct halmac_api *api = HALMAC_GET_API(halmac);
4726
4727 status = api->halmac_dl_drv_rsvd_page(halmac, pg_offset, pbuf, size);
4728 if (status != HALMAC_RET_SUCCESS)
4729 return -1;
4730
4731 return 0;
4732 }
4733
4734 /*
4735 * Description
4736 * Fill following spec info from HALMAC API:
4737 * sec_cam_ent_num
4738 *
4739 * Return
4740 * 0 Success
4741 * others Fail
4742 */
rtw_halmac_fill_hal_spec(struct dvobj_priv * dvobj,struct hal_spec_t * spec)4743 int rtw_halmac_fill_hal_spec(struct dvobj_priv *dvobj, struct hal_spec_t *spec)
4744 {
4745 enum halmac_ret_status status;
4746 struct halmac_adapter *halmac;
4747 struct halmac_api *api;
4748 u8 cam = 0; /* Security Cam Entry Number */
4749
4750
4751 halmac = dvobj_to_halmac(dvobj);
4752 api = HALMAC_GET_API(halmac);
4753
4754 /* Prepare data from HALMAC */
4755 status = api->halmac_get_hw_value(halmac, HALMAC_HW_CAM_ENTRY_NUM, &cam);
4756 if (status != HALMAC_RET_SUCCESS)
4757 return -1;
4758
4759 /* Fill data to hal_spec_t */
4760 spec->sec_cam_ent_num = cam;
4761
4762 return 0;
4763 }
4764
rtw_halmac_p2pps(struct dvobj_priv * dvobj,struct hal_p2p_ps_para * pp2p_ps_para)4765 int rtw_halmac_p2pps(struct dvobj_priv *dvobj, struct hal_p2p_ps_para *pp2p_ps_para)
4766 {
4767 enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4768 struct halmac_adapter *halmac = dvobj_to_halmac(dvobj);
4769 struct halmac_api *api = HALMAC_GET_API(halmac);
4770 struct halmac_p2pps halmac_p2p_ps;
4771
4772 (&halmac_p2p_ps)->offload_en = pp2p_ps_para->offload_en;
4773 (&halmac_p2p_ps)->role = pp2p_ps_para->role;
4774 (&halmac_p2p_ps)->ctwindow_en = pp2p_ps_para->ctwindow_en;
4775 (&halmac_p2p_ps)->noa_en = pp2p_ps_para->noa_en;
4776 (&halmac_p2p_ps)->noa_sel = pp2p_ps_para->noa_sel;
4777 (&halmac_p2p_ps)->all_sta_sleep = pp2p_ps_para->all_sta_sleep;
4778 (&halmac_p2p_ps)->discovery = pp2p_ps_para->discovery;
4779 (&halmac_p2p_ps)->disable_close_rf = pp2p_ps_para->disable_close_rf;
4780 (&halmac_p2p_ps)->p2p_port_id = _hw_port_drv2halmac(pp2p_ps_para->p2p_port_id);
4781 (&halmac_p2p_ps)->p2p_group = pp2p_ps_para->p2p_group;
4782 (&halmac_p2p_ps)->p2p_macid = pp2p_ps_para->p2p_macid;
4783 (&halmac_p2p_ps)->ctwindow_length = pp2p_ps_para->ctwindow_length;
4784 (&halmac_p2p_ps)->noa_duration_para = pp2p_ps_para->noa_duration_para;
4785 (&halmac_p2p_ps)->noa_interval_para = pp2p_ps_para->noa_interval_para;
4786 (&halmac_p2p_ps)->noa_start_time_para = pp2p_ps_para->noa_start_time_para;
4787 (&halmac_p2p_ps)->noa_count_para = pp2p_ps_para->noa_count_para;
4788
4789 status = api->halmac_p2pps(halmac, (&halmac_p2p_ps));
4790 if (status != HALMAC_RET_SUCCESS)
4791 return -1;
4792
4793 return 0;
4794
4795 }
4796
4797 /**
4798 * rtw_halmac_iqk() - Run IQ Calibration
4799 * @d: struct dvobj_priv*
4800 * @clear: IQK parameters
4801 * @segment: IQK parameters
4802 *
4803 * Process IQ Calibration(IQK).
4804 *
4805 * Return 0 for OK, otherwise fail.
4806 */
rtw_halmac_iqk(struct dvobj_priv * d,u8 clear,u8 segment)4807 int rtw_halmac_iqk(struct dvobj_priv *d, u8 clear, u8 segment)
4808 {
4809 struct halmac_adapter *mac;
4810 struct halmac_api *api;
4811 enum halmac_ret_status status;
4812 enum halmac_feature_id id;
4813 struct halmac_iqk_para para;
4814 int ret;
4815 u8 retry = 3;
4816 u8 delay = 1; /* ms */
4817
4818
4819 mac = dvobj_to_halmac(d);
4820 api = HALMAC_GET_API(mac);
4821 id = HALMAC_FEATURE_IQK;
4822
4823 ret = init_halmac_event(d, id, NULL, 0);
4824 if (ret)
4825 return -1;
4826
4827 para.clear = clear;
4828 para.segment_iqk = segment;
4829
4830 do {
4831 status = api->halmac_start_iqk(mac, ¶);
4832 if (status != HALMAC_RET_BUSY_STATE)
4833 break;
4834 RTW_WARN("%s: Fail to start IQK, status is BUSY! retry=%d\n", __FUNCTION__, retry);
4835 if (!retry)
4836 break;
4837 retry--;
4838 rtw_msleep_os(delay);
4839 } while (1);
4840 if (status != HALMAC_RET_SUCCESS) {
4841 free_halmac_event(d, id);
4842 return -1;
4843 }
4844
4845 ret = wait_halmac_event(d, id);
4846 if (ret)
4847 return -1;
4848
4849 return 0;
4850 }
4851
4852 /**
4853 * rtw_halmac_dpk() - Run DP Calibration
4854 * @d: struct dvobj_priv*
4855 * @buf: buffer for store return value
4856 * @bufsz: size of buffer
4857 *
4858 * Process DP Calibration(DPK).
4859 *
4860 * Return 0 for OK, otherwise fail.
4861 */
rtw_halmac_dpk(struct dvobj_priv * d,u8 * buf,u32 bufsz)4862 int rtw_halmac_dpk(struct dvobj_priv *d, u8 *buf, u32 bufsz)
4863 {
4864 struct halmac_adapter *mac;
4865 struct halmac_api *api;
4866 enum halmac_ret_status status;
4867 enum halmac_feature_id id;
4868 int ret;
4869
4870
4871 mac = dvobj_to_halmac(d);
4872 api = HALMAC_GET_API(mac);
4873 id = HALMAC_FEATURE_DPK;
4874
4875 ret = init_halmac_event(d, id, buf, bufsz);
4876 if (ret)
4877 return -1;
4878
4879 status = api->halmac_start_dpk(mac);
4880 if (status != HALMAC_RET_SUCCESS) {
4881 free_halmac_event(d, id);
4882 RTW_ERR("%s: Fail to start DPK (0x%x)!\n",
4883 __FUNCTION__, status);
4884 return -1;
4885 }
4886
4887 ret = wait_halmac_event(d, id);
4888 if (ret)
4889 return -1;
4890
4891 return 0;
4892 }
4893
_phy_parameter_val_drv2halmac(u32 val,u8 msk_en,u32 msk)4894 static inline u32 _phy_parameter_val_drv2halmac(u32 val, u8 msk_en, u32 msk)
4895 {
4896 if (!msk_en)
4897 return val;
4898
4899 return (val << bitshift(msk));
4900 }
4901
_phy_parameter_drv2halmac(struct rtw_phy_parameter * para,struct halmac_phy_parameter_info * info)4902 static int _phy_parameter_drv2halmac(struct rtw_phy_parameter *para, struct halmac_phy_parameter_info *info)
4903 {
4904 if (!para || !info)
4905 return -1;
4906
4907 _rtw_memset(info, 0, sizeof(*info));
4908
4909 switch (para->cmd) {
4910 case 0:
4911 /* MAC register */
4912 switch (para->data.mac.size) {
4913 case 1:
4914 info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W8;
4915 break;
4916 case 2:
4917 info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W16;
4918 break;
4919 default:
4920 info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W32;
4921 break;
4922 }
4923 info->content.MAC_REG_W.value = _phy_parameter_val_drv2halmac(
4924 para->data.mac.value,
4925 para->data.mac.msk_en,
4926 para->data.mac.msk);
4927 info->content.MAC_REG_W.msk = para->data.mac.msk;
4928 info->content.MAC_REG_W.offset = para->data.mac.offset;
4929 info->content.MAC_REG_W.msk_en = para->data.mac.msk_en;
4930 break;
4931
4932 case 1:
4933 /* BB register */
4934 switch (para->data.bb.size) {
4935 case 1:
4936 info->cmd_id = HALMAC_PARAMETER_CMD_BB_W8;
4937 break;
4938 case 2:
4939 info->cmd_id = HALMAC_PARAMETER_CMD_BB_W16;
4940 break;
4941 default:
4942 info->cmd_id = HALMAC_PARAMETER_CMD_BB_W32;
4943 break;
4944 }
4945 info->content.BB_REG_W.value = _phy_parameter_val_drv2halmac(
4946 para->data.bb.value,
4947 para->data.bb.msk_en,
4948 para->data.bb.msk);
4949 info->content.BB_REG_W.msk = para->data.bb.msk;
4950 info->content.BB_REG_W.offset = para->data.bb.offset;
4951 info->content.BB_REG_W.msk_en = para->data.bb.msk_en;
4952 break;
4953
4954 case 2:
4955 /* RF register */
4956 info->cmd_id = HALMAC_PARAMETER_CMD_RF_W;
4957 info->content.RF_REG_W.value = _phy_parameter_val_drv2halmac(
4958 para->data.rf.value,
4959 para->data.rf.msk_en,
4960 para->data.rf.msk);
4961 info->content.RF_REG_W.msk = para->data.rf.msk;
4962 info->content.RF_REG_W.offset = para->data.rf.offset;
4963 info->content.RF_REG_W.msk_en = para->data.rf.msk_en;
4964 info->content.RF_REG_W.rf_path = para->data.rf.path;
4965 break;
4966
4967 case 3:
4968 /* Delay register */
4969 if (para->data.delay.unit == 0)
4970 info->cmd_id = HALMAC_PARAMETER_CMD_DELAY_US;
4971 else
4972 info->cmd_id = HALMAC_PARAMETER_CMD_DELAY_MS;
4973 info->content.DELAY_TIME.delay_time = para->data.delay.value;
4974 break;
4975
4976 case 0xFF:
4977 /* Latest(End) command */
4978 info->cmd_id = HALMAC_PARAMETER_CMD_END;
4979 break;
4980
4981 default:
4982 return -1;
4983 }
4984
4985 return 0;
4986 }
4987
4988 /**
4989 * rtw_halmac_cfg_phy_para() - Register(Phy parameter) configuration
4990 * @d: struct dvobj_priv*
4991 * @para: phy parameter
4992 *
4993 * Configure registers by firmware using H2C/C2H mechanism.
4994 * The latest command should be para->cmd==0xFF(End command) to finish all
4995 * processes.
4996 *
4997 * Return: 0 for OK, otherwise fail.
4998 */
rtw_halmac_cfg_phy_para(struct dvobj_priv * d,struct rtw_phy_parameter * para)4999 int rtw_halmac_cfg_phy_para(struct dvobj_priv *d, struct rtw_phy_parameter *para)
5000 {
5001 struct halmac_adapter *mac;
5002 struct halmac_api *api;
5003 enum halmac_ret_status status;
5004 enum halmac_feature_id id;
5005 struct halmac_phy_parameter_info info;
5006 u8 full_fifo;
5007 int err, ret;
5008
5009
5010 mac = dvobj_to_halmac(d);
5011 api = HALMAC_GET_API(mac);
5012 id = HALMAC_FEATURE_CFG_PARA;
5013 full_fifo = 1; /* ToDo: How to deciede? */
5014 ret = 0;
5015
5016 err = _phy_parameter_drv2halmac(para, &info);
5017 if (err)
5018 return -1;
5019
5020 err = init_halmac_event(d, id, NULL, 0);
5021 if (err)
5022 return -1;
5023
5024 status = api->halmac_cfg_parameter(mac, &info, full_fifo);
5025 if (info.cmd_id == HALMAC_PARAMETER_CMD_END) {
5026 if (status == HALMAC_RET_SUCCESS) {
5027 err = wait_halmac_event(d, id);
5028 if (err)
5029 ret = -1;
5030 } else {
5031 free_halmac_event(d, id);
5032 ret = -1;
5033 RTW_ERR("%s: Fail to send END of cfg parameter, status is 0x%x!\n", __FUNCTION__, status);
5034 }
5035 } else {
5036 if (status == HALMAC_RET_PARA_SENDING) {
5037 err = wait_halmac_event(d, id);
5038 if (err)
5039 ret = -1;
5040 } else {
5041 free_halmac_event(d, id);
5042 if (status != HALMAC_RET_SUCCESS) {
5043 ret = -1;
5044 RTW_ERR("%s: Fail to cfg parameter, status is 0x%x!\n", __FUNCTION__, status);
5045 }
5046 }
5047 }
5048
5049 return ret;
5050 }
5051
_led_mode_drv2halmac(u8 drv_mode)5052 static enum halmac_wlled_mode _led_mode_drv2halmac(u8 drv_mode)
5053 {
5054 enum halmac_wlled_mode halmac_mode;
5055
5056
5057 switch (drv_mode) {
5058 case 1:
5059 halmac_mode = HALMAC_WLLED_MODE_TX;
5060 break;
5061 case 2:
5062 halmac_mode = HALMAC_WLLED_MODE_RX;
5063 break;
5064 case 3:
5065 halmac_mode = HALMAC_WLLED_MODE_SW_CTRL;
5066 break;
5067 case 0:
5068 default:
5069 halmac_mode = HALMAC_WLLED_MODE_TRX;
5070 break;
5071 }
5072
5073 return halmac_mode;
5074 }
5075
5076 /**
5077 * rtw_halmac_led_cfg() - Configure Hardware LED Mode
5078 * @d: struct dvobj_priv*
5079 * @enable: enable or disable LED function
5080 * 0: disable
5081 * 1: enable
5082 * @mode: WLan LED mode (valid when enable==1)
5083 * 0: Blink when TX(transmit packet) and RX(receive packet)
5084 * 1: Blink when TX only
5085 * 2: Blink when RX only
5086 * 3: Software control
5087 *
5088 * Configure hardware WLan LED mode.
5089 * If want to change LED mode after enabled, need to disable LED first and
5090 * enable again to set new mode.
5091 *
5092 * Return 0 for OK, otherwise fail.
5093 */
rtw_halmac_led_cfg(struct dvobj_priv * d,u8 enable,u8 mode)5094 int rtw_halmac_led_cfg(struct dvobj_priv *d, u8 enable, u8 mode)
5095 {
5096 struct halmac_adapter *halmac;
5097 struct halmac_api *api;
5098 enum halmac_wlled_mode led_mode;
5099 enum halmac_ret_status status;
5100
5101
5102 halmac = dvobj_to_halmac(d);
5103 api = HALMAC_GET_API(halmac);
5104
5105 if (enable) {
5106 status = api->halmac_pinmux_set_func(halmac,
5107 HALMAC_GPIO_FUNC_WL_LED);
5108 if (status != HALMAC_RET_SUCCESS) {
5109 RTW_ERR("%s: pinmux set fail!(0x%x)\n",
5110 __FUNCTION__, status);
5111 return -1;
5112 }
5113
5114 led_mode = _led_mode_drv2halmac(mode);
5115 status = api->halmac_pinmux_wl_led_mode(halmac, led_mode);
5116 if (status != HALMAC_RET_SUCCESS) {
5117 RTW_ERR("%s: mode set fail!(0x%x)\n",
5118 __FUNCTION__, status);
5119 return -1;
5120 }
5121 } else {
5122 /* Change LED to software control and turn off */
5123 api->halmac_pinmux_wl_led_mode(halmac,
5124 HALMAC_WLLED_MODE_SW_CTRL);
5125 api->halmac_pinmux_wl_led_sw_ctrl(halmac, 0);
5126
5127 status = api->halmac_pinmux_free_func(halmac,
5128 HALMAC_GPIO_FUNC_WL_LED);
5129 if (status != HALMAC_RET_SUCCESS) {
5130 RTW_ERR("%s: pinmux free fail!(0x%x)\n",
5131 __FUNCTION__, status);
5132 return -1;
5133 }
5134 }
5135
5136 return 0;
5137 }
5138
5139 /**
5140 * rtw_halmac_led_switch() - Turn Hardware LED on/off
5141 * @d: struct dvobj_priv*
5142 * @on: LED light or not
5143 * 0: Off
5144 * 1: On(Light)
5145 *
5146 * Turn Hardware WLan LED On/Off.
5147 * Before use this function, user should call rtw_halmac_led_ctrl() to switch
5148 * mode to "software control(3)" first, otherwise control would fail.
5149 * The interval between on and off must be longer than 1 ms, or the LED would
5150 * keep light or dark only.
5151 * Ex. Turn off LED at first, turn on after 0.5ms and turn off again after
5152 * 0.5ms. The LED during this flow will only keep dark, and miss the turn on
5153 * operation between two turn off operations.
5154 */
rtw_halmac_led_switch(struct dvobj_priv * d,u8 on)5155 void rtw_halmac_led_switch(struct dvobj_priv *d, u8 on)
5156 {
5157 struct halmac_adapter *halmac;
5158 struct halmac_api *api;
5159
5160
5161 halmac = dvobj_to_halmac(d);
5162 api = HALMAC_GET_API(halmac);
5163
5164 api->halmac_pinmux_wl_led_sw_ctrl(halmac, on);
5165 }
5166
_gpio_cfg(struct dvobj_priv * d,enum halmac_gpio_func gpio,u8 enable)5167 static int _gpio_cfg(struct dvobj_priv *d, enum halmac_gpio_func gpio, u8 enable)
5168 {
5169 struct halmac_adapter *halmac;
5170 struct halmac_api *api;
5171 enum halmac_ret_status status;
5172
5173
5174 halmac = dvobj_to_halmac(d);
5175 api = HALMAC_GET_API(halmac);
5176
5177 if (enable) {
5178 status = api->halmac_pinmux_set_func(halmac, gpio);
5179 if (status != HALMAC_RET_SUCCESS) {
5180 RTW_ERR("%s: pinmux set GPIO(%d) fail!(0x%x)\n",
5181 __FUNCTION__, gpio, status);
5182 return -1;
5183 }
5184 } else {
5185 status = api->halmac_pinmux_free_func(halmac, gpio);
5186 if (status != HALMAC_RET_SUCCESS) {
5187 RTW_ERR("%s: pinmux free GPIO(%d) fail!(0x%x)\n",
5188 __FUNCTION__, gpio, status);
5189 return -1;
5190 }
5191 }
5192
5193 return 0;
5194 }
5195
5196 /**
5197 * rtw_halmac_bt_wake_cfg() - Configure BT wake host function
5198 * @d: struct dvobj_priv*
5199 * @enable: enable or disable BT wake host function
5200 * 0: disable
5201 * 1: enable
5202 *
5203 * Configure pinmux to allow BT to control BT wake host pin.
5204 *
5205 * Return 0 for OK, otherwise fail.
5206 */
rtw_halmac_bt_wake_cfg(struct dvobj_priv * d,u8 enable)5207 int rtw_halmac_bt_wake_cfg(struct dvobj_priv *d, u8 enable)
5208 {
5209 return _gpio_cfg(d, HALMAC_GPIO_FUNC_BT_HOST_WAKE1, enable);
5210 }
5211
_gpio_to_func_for_rfe_ctrl(u8 gpio)5212 static enum halmac_gpio_func _gpio_to_func_for_rfe_ctrl(u8 gpio)
5213 {
5214 enum halmac_gpio_func f = HALMAC_GPIO_FUNC_UNDEFINE;
5215
5216
5217 #ifdef CONFIG_RTL8822C
5218 switch (gpio) {
5219 case 1:
5220 f = HALMAC_GPIO_FUNC_ANTSWB;
5221 break;
5222 case 2:
5223 f = HALMAC_GPIO_FUNC_S1_TRSW;
5224 break;
5225 case 3:
5226 f = HALMAC_GPIO_FUNC_S0_TRSW;
5227 break;
5228 case 6:
5229 f = HALMAC_GPIO_FUNC_S0_PAPE;
5230 break;
5231 case 7:
5232 f = HALMAC_GPIO_FUNC_S0_TRSWB;
5233 break;
5234 case 13:
5235 f = HALMAC_GPIO_FUNC_ANTSW;
5236 break;
5237 }
5238 #endif /* CONFIG_RTL8822C */
5239
5240 return f;
5241 }
5242
5243 /**
5244 * rtw_halmac_rfe_ctrl_cfg() - Configure RFE control GPIO
5245 * @d: struct dvobj_priv*
5246 * @gpio: gpio number
5247 *
5248 * Configure pinmux to enable RFE control GPIO.
5249 *
5250 * Return 0 for OK, otherwise fail.
5251 */
rtw_halmac_rfe_ctrl_cfg(struct dvobj_priv * d,u8 gpio)5252 int rtw_halmac_rfe_ctrl_cfg(struct dvobj_priv *d, u8 gpio)
5253 {
5254 enum halmac_gpio_func f;
5255
5256
5257 f = _gpio_to_func_for_rfe_ctrl(gpio);
5258 if (f == HALMAC_GPIO_FUNC_UNDEFINE)
5259 return -1;
5260 return _gpio_cfg(d, f, 1);
5261 }
5262
5263 #ifdef CONFIG_PNO_SUPPORT
5264 /**
5265 * _halmac_scanoffload() - Switch channel by firmware during scanning
5266 * @d: struct dvobj_priv*
5267 * @enable: 1: enable, 0: disable
5268 * @nlo: 1: nlo mode (no c2h event), 0: normal mode
5269 * @ssid: ssid of probe request
5270 * @ssid_len: ssid length
5271 *
5272 * Switch Channel and Send Porbe Request Offloaded by FW
5273 *
5274 * Return 0 for OK, otherwise fail.
5275 */
_halmac_scanoffload(struct dvobj_priv * d,u32 enable,u8 nlo,u8 * ssid,u8 ssid_len)5276 static int _halmac_scanoffload(struct dvobj_priv *d, u32 enable, u8 nlo,
5277 u8 *ssid, u8 ssid_len)
5278 {
5279 struct _ADAPTER *adapter;
5280 struct halmac_adapter *mac;
5281 struct halmac_api *api;
5282 enum halmac_ret_status status;
5283 struct halmac_ch_info ch_info;
5284 struct halmac_ch_switch_option cs_option;
5285 struct mlme_ext_priv *pmlmeext;
5286 enum halmac_feature_id id_update, id_ch_sw;
5287 struct halmac_indicator *indicator, *tbl;
5288
5289 int err = 0;
5290 u8 probereq[64];
5291 u32 len = 0;
5292 int i = 0;
5293 struct pno_ssid pnossid;
5294 struct rf_ctl_t *rfctl = NULL;
5295 struct _RT_CHANNEL_INFO *ch_set;
5296
5297
5298 tbl = d->hmpriv.indicator;
5299 adapter = dvobj_get_primary_adapter(d);
5300 mac = dvobj_to_halmac(d);
5301 if (!mac)
5302 return -1;
5303 api = HALMAC_GET_API(mac);
5304 id_update = HALMAC_FEATURE_UPDATE_PACKET;
5305 id_ch_sw = HALMAC_FEATURE_CHANNEL_SWITCH;
5306 pmlmeext = &(adapter->mlmeextpriv);
5307 rfctl = adapter_to_rfctl(adapter);
5308 ch_set = rfctl->channel_set;
5309
5310 RTW_INFO("%s: %s scanoffload, mode: %s\n",
5311 __FUNCTION__, enable?"Enable":"Disable",
5312 nlo?"PNO/NLO":"Normal");
5313
5314 if (enable) {
5315 _rtw_memset(probereq, 0, sizeof(probereq));
5316
5317 _rtw_memset(&pnossid, 0, sizeof(pnossid));
5318 if (ssid) {
5319 if (ssid_len > sizeof(pnossid.SSID)) {
5320 RTW_ERR("%s: SSID length(%d) is too long(>%d)!!\n",
5321 __FUNCTION__, ssid_len, sizeof(pnossid.SSID));
5322 return -1;
5323 }
5324
5325 pnossid.SSID_len = ssid_len;
5326 _rtw_memcpy(pnossid.SSID, ssid, ssid_len);
5327 }
5328
5329 rtw_hal_construct_ProbeReq(adapter, probereq, &len, &pnossid);
5330
5331 if (!nlo) {
5332 err = init_halmac_event(d, id_update, NULL, 0);
5333 if (err)
5334 return -1;
5335 }
5336
5337 status = api->halmac_update_packet(mac, HALMAC_PACKET_PROBE_REQ,
5338 probereq, len);
5339 if (status != HALMAC_RET_SUCCESS) {
5340 if (!nlo)
5341 free_halmac_event(d, id_update);
5342 RTW_ERR("%s: halmac_update_packet FAIL(%d)!!\n",
5343 __FUNCTION__, status);
5344 return -1;
5345 }
5346
5347 if (!nlo) {
5348 err = wait_halmac_event(d, id_update);
5349 if (err)
5350 RTW_ERR("%s: wait update packet FAIL(%d)!!\n",
5351 __FUNCTION__, err);
5352 }
5353
5354 api->halmac_clear_ch_info(mac);
5355
5356 for (i = 0; i < rfctl->max_chan_nums && ch_set[i].ChannelNum != 0; i++) {
5357 _rtw_memset(&ch_info, 0, sizeof(ch_info));
5358 ch_info.extra_info = 0;
5359 ch_info.channel = ch_set[i].ChannelNum;
5360 ch_info.bw = HALMAC_BW_20;
5361 ch_info.pri_ch_idx = HALMAC_CH_IDX_1;
5362 ch_info.action_id = HALMAC_CS_ACTIVE_SCAN;
5363 ch_info.timeout = 1;
5364 status = api->halmac_add_ch_info(mac, &ch_info);
5365 if (status != HALMAC_RET_SUCCESS) {
5366 RTW_ERR("%s: add_ch_info FAIL(%d)!!\n",
5367 __FUNCTION__, status);
5368 return -1;
5369 }
5370 }
5371
5372 /* set channel switch option */
5373 _rtw_memset(&cs_option, 0, sizeof(cs_option));
5374 cs_option.dest_bw = HALMAC_BW_20;
5375 cs_option.periodic_option = HALMAC_CS_PERIODIC_2_PHASE;
5376 cs_option.dest_pri_ch_idx = HALMAC_CH_IDX_UNDEFINE;
5377 cs_option.tsf_low = 0;
5378 cs_option.switch_en = 1;
5379 cs_option.dest_ch_en = 1;
5380 cs_option.absolute_time_en = 0;
5381 cs_option.dest_ch = 1;
5382
5383 cs_option.normal_period = 5;
5384 cs_option.normal_period_sel = 0;
5385 cs_option.normal_cycle = 10;
5386
5387 cs_option.phase_2_period = 1;
5388 cs_option.phase_2_period_sel = 1;
5389
5390 /* nlo is for wow fw, 1: no c2h response */
5391 cs_option.nlo_en = nlo;
5392
5393 if (!nlo) {
5394 err = init_halmac_event(d, id_ch_sw, NULL, 0);
5395 if (err)
5396 return -1;
5397 }
5398
5399 status = api->halmac_ctrl_ch_switch(mac, &cs_option);
5400 if (status != HALMAC_RET_SUCCESS) {
5401 if (!nlo)
5402 free_halmac_event(d, id_ch_sw);
5403 RTW_ERR("%s: halmac_ctrl_ch_switch FAIL(%d)!!\n",
5404 __FUNCTION__, status);
5405 return -1;
5406 }
5407
5408 if (!nlo) {
5409 err = wait_halmac_event(d, id_ch_sw);
5410 if (err)
5411 RTW_ERR("%s: wait ctrl_ch_switch FAIL(%d)!!\n",
5412 __FUNCTION__, err);
5413 }
5414 } else {
5415 api->halmac_clear_ch_info(mac);
5416
5417 _rtw_memset(&cs_option, 0, sizeof(cs_option));
5418 cs_option.switch_en = 0;
5419
5420 if (!nlo) {
5421 err = init_halmac_event(d, id_ch_sw, NULL, 0);
5422 if (err)
5423 return -1;
5424 }
5425
5426 status = api->halmac_ctrl_ch_switch(mac, &cs_option);
5427 if (status != HALMAC_RET_SUCCESS) {
5428 if (!nlo)
5429 free_halmac_event(d, id_ch_sw);
5430 RTW_ERR("%s: halmac_ctrl_ch_switch FAIL(%d)!!\n",
5431 __FUNCTION__, status);
5432 return -1;
5433 }
5434
5435 if (!nlo) {
5436 err = wait_halmac_event(d, id_ch_sw);
5437 if (err)
5438 RTW_ERR("%s: wait ctrl_ch_switch FAIL(%d)!!\n",
5439 __FUNCTION__, err);
5440 }
5441 }
5442
5443 return 0;
5444 }
5445
5446 /**
5447 * rtw_halmac_pno_scanoffload() - Control firmware scan AP function for PNO
5448 * @d: struct dvobj_priv*
5449 * @enable: 1: enable, 0: disable
5450 *
5451 * Switch firmware scan AP function for PNO(prefer network offload) or
5452 * NLO(network list offload).
5453 *
5454 * Return 0 for OK, otherwise fail.
5455 */
rtw_halmac_pno_scanoffload(struct dvobj_priv * d,u32 enable)5456 int rtw_halmac_pno_scanoffload(struct dvobj_priv *d, u32 enable)
5457 {
5458 return _halmac_scanoffload(d, enable, 1, NULL, 0);
5459 }
5460 #endif /* CONFIG_PNO_SUPPORT */
5461
5462 #ifdef CONFIG_SDIO_HCI
5463
5464 /**
5465 * rtw_halmac_preinit_sdio_io_indirect() - Enable indirect I/O or not
5466 * @d: struct dvobj_priv*
5467 * @enable: true: enable, false: disable
5468 *
5469 * Enable register access using direct I/O or indirect. This function should be
5470 * called before rtw_halmac_init_adapter(), and the life cycle is the same as
5471 * driver until removing driver.
5472 *
5473 * Return 0 for OK, otherwise fail.
5474 */
rtw_halmac_preinit_sdio_io_indirect(struct dvobj_priv * d,bool enable)5475 int rtw_halmac_preinit_sdio_io_indirect(struct dvobj_priv *d, bool enable)
5476 {
5477 struct halmac_adapter *halmac;
5478 struct halmacpriv *priv;
5479
5480
5481 halmac = dvobj_to_halmac(d);
5482 if (halmac) {
5483 RTW_WARN("%s: illegal operation! "
5484 "preinit function only could be called before init!\n",
5485 __FUNCTION__);
5486 return -1;
5487 }
5488
5489 priv = &d->hmpriv;
5490 priv->sdio_io_indir = (enable ? 1 : 2);
5491
5492 return 0;
5493 }
5494
5495 /*
5496 * Description:
5497 * Update queue allocated page number to driver
5498 *
5499 * Parameter:
5500 * d pointer to struct dvobj_priv of driver
5501 *
5502 * Return:
5503 * 0 Success, "page" is valid.
5504 * others Fail, "page" is invalid.
5505 */
rtw_halmac_query_tx_page_num(struct dvobj_priv * d)5506 int rtw_halmac_query_tx_page_num(struct dvobj_priv *d)
5507 {
5508 PADAPTER adapter;
5509 struct halmacpriv *hmpriv;
5510 struct halmac_adapter *halmac;
5511 struct halmac_api *api;
5512 struct halmac_rqpn_map rqpn;
5513 enum halmac_dma_mapping dmaqueue;
5514 struct halmac_txff_allocation fifosize;
5515 enum halmac_ret_status status;
5516 u8 i;
5517
5518
5519 adapter = dvobj_get_primary_adapter(d);
5520 hmpriv = &d->hmpriv;
5521 halmac = dvobj_to_halmac(d);
5522 api = HALMAC_GET_API(halmac);
5523 _rtw_memset((void *)&rqpn, 0, sizeof(rqpn));
5524 _rtw_memset((void *)&fifosize, 0, sizeof(fifosize));
5525
5526 status = api->halmac_get_hw_value(halmac, HALMAC_HW_RQPN_MAPPING, &rqpn);
5527 if (status != HALMAC_RET_SUCCESS)
5528 return -1;
5529 status = api->halmac_get_hw_value(halmac, HALMAC_HW_TXFF_ALLOCATION, &fifosize);
5530 if (status != HALMAC_RET_SUCCESS)
5531 return -1;
5532
5533 for (i = 0; i < HW_QUEUE_ENTRY; i++) {
5534 hmpriv->txpage[i] = 0;
5535
5536 /* Driver index mapping to HALMAC DMA queue */
5537 dmaqueue = HALMAC_DMA_MAPPING_UNDEFINE;
5538 switch (i) {
5539 case VO_QUEUE_INX:
5540 dmaqueue = rqpn.dma_map_vo;
5541 break;
5542 case VI_QUEUE_INX:
5543 dmaqueue = rqpn.dma_map_vi;
5544 break;
5545 case BE_QUEUE_INX:
5546 dmaqueue = rqpn.dma_map_be;
5547 break;
5548 case BK_QUEUE_INX:
5549 dmaqueue = rqpn.dma_map_bk;
5550 break;
5551 case MGT_QUEUE_INX:
5552 dmaqueue = rqpn.dma_map_mg;
5553 break;
5554 case HIGH_QUEUE_INX:
5555 dmaqueue = rqpn.dma_map_hi;
5556 break;
5557 case BCN_QUEUE_INX:
5558 case TXCMD_QUEUE_INX:
5559 /* Unlimited */
5560 hmpriv->txpage[i] = 0xFFFF;
5561 continue;
5562 }
5563
5564 switch (dmaqueue) {
5565 case HALMAC_DMA_MAPPING_EXTRA:
5566 hmpriv->txpage[i] = fifosize.extra_queue_pg_num;
5567 break;
5568 case HALMAC_DMA_MAPPING_LOW:
5569 hmpriv->txpage[i] = fifosize.low_queue_pg_num;
5570 break;
5571 case HALMAC_DMA_MAPPING_NORMAL:
5572 hmpriv->txpage[i] = fifosize.normal_queue_pg_num;
5573 break;
5574 case HALMAC_DMA_MAPPING_HIGH:
5575 hmpriv->txpage[i] = fifosize.high_queue_pg_num;
5576 break;
5577 case HALMAC_DMA_MAPPING_UNDEFINE:
5578 break;
5579 }
5580 hmpriv->txpage[i] += fifosize.pub_queue_pg_num;
5581 }
5582
5583 return 0;
5584 }
5585
5586 /*
5587 * Description:
5588 * Get specific queue allocated page number
5589 *
5590 * Parameter:
5591 * d pointer to struct dvobj_priv of driver
5592 * queue target queue to query, VO/VI/BE/BK/.../TXCMD_QUEUE_INX
5593 * page return allocated page number
5594 *
5595 * Return:
5596 * 0 Success, "page" is valid.
5597 * others Fail, "page" is invalid.
5598 */
rtw_halmac_get_tx_queue_page_num(struct dvobj_priv * d,u8 queue,u32 * page)5599 int rtw_halmac_get_tx_queue_page_num(struct dvobj_priv *d, u8 queue, u32 *page)
5600 {
5601 *page = 0;
5602 if (queue < HW_QUEUE_ENTRY)
5603 *page = d->hmpriv.txpage[queue];
5604
5605 return 0;
5606 }
5607
5608 /*
5609 * Return:
5610 * address for SDIO command
5611 */
rtw_halmac_sdio_get_tx_addr(struct dvobj_priv * d,u8 * desc,u32 size)5612 u32 rtw_halmac_sdio_get_tx_addr(struct dvobj_priv *d, u8 *desc, u32 size)
5613 {
5614 struct halmac_adapter *mac;
5615 struct halmac_api *api;
5616 enum halmac_ret_status status;
5617 u32 addr;
5618
5619
5620 mac = dvobj_to_halmac(d);
5621 api = HALMAC_GET_API(mac);
5622
5623 status = api->halmac_get_sdio_tx_addr(mac, desc, size, &addr);
5624 if (HALMAC_RET_SUCCESS != status)
5625 return 0;
5626
5627 return addr;
5628 }
5629
rtw_halmac_sdio_tx_allowed(struct dvobj_priv * d,u8 * buf,u32 size)5630 int rtw_halmac_sdio_tx_allowed(struct dvobj_priv *d, u8 *buf, u32 size)
5631 {
5632 struct halmac_adapter *mac;
5633 struct halmac_api *api;
5634 enum halmac_ret_status status;
5635
5636
5637 mac = dvobj_to_halmac(d);
5638 api = HALMAC_GET_API(mac);
5639
5640 status = api->halmac_tx_allowed_sdio(mac, buf, size);
5641 if (HALMAC_RET_SUCCESS != status)
5642 return -1;
5643
5644 return 0;
5645 }
5646
rtw_halmac_sdio_get_rx_addr(struct dvobj_priv * d,u8 * seq)5647 u32 rtw_halmac_sdio_get_rx_addr(struct dvobj_priv *d, u8 *seq)
5648 {
5649 u8 id;
5650
5651 #define RTW_SDIO_ADDR_RX_RX0FF_PRFIX 0x0E000
5652 #define RTW_SDIO_ADDR_RX_RX0FF_GEN(a) (RTW_SDIO_ADDR_RX_RX0FF_PRFIX|(a&0x3))
5653
5654 id = *seq;
5655 (*seq)++;
5656 return RTW_SDIO_ADDR_RX_RX0FF_GEN(id);
5657 }
5658
rtw_halmac_sdio_set_tx_format(struct dvobj_priv * d,enum halmac_sdio_tx_format format)5659 int rtw_halmac_sdio_set_tx_format(struct dvobj_priv *d, enum halmac_sdio_tx_format format)
5660 {
5661 struct halmac_adapter *mac;
5662 struct halmac_api *api;
5663 enum halmac_ret_status status;
5664
5665 mac = dvobj_to_halmac(d);
5666 api = HALMAC_GET_API(mac);
5667
5668 status = api->halmac_set_hw_value(mac, HALMAC_HW_SDIO_TX_FORMAT, &format);
5669 if (HALMAC_RET_SUCCESS != status)
5670 return -1;
5671
5672 return 0;
5673 }
5674 #endif /* CONFIG_SDIO_HCI */
5675
5676 #ifdef CONFIG_USB_HCI
rtw_halmac_usb_get_bulkout_id(struct dvobj_priv * d,u8 * buf,u32 size)5677 u8 rtw_halmac_usb_get_bulkout_id(struct dvobj_priv *d, u8 *buf, u32 size)
5678 {
5679 struct halmac_adapter *mac;
5680 struct halmac_api *api;
5681 enum halmac_ret_status status;
5682 u8 bulkout_id;
5683
5684
5685 mac = dvobj_to_halmac(d);
5686 api = HALMAC_GET_API(mac);
5687
5688 status = api->halmac_get_usb_bulkout_id(mac, buf, size, &bulkout_id);
5689 if (HALMAC_RET_SUCCESS != status)
5690 return 0;
5691
5692 return bulkout_id;
5693 }
5694
5695 /**
5696 * rtw_halmac_usb_get_txagg_desc_num() - MAX descriptor number in one bulk for TX
5697 * @d: struct dvobj_priv*
5698 * @size: TX FIFO size, unit is byte.
5699 *
5700 * Get MAX descriptor number in one bulk out from HALMAC.
5701 *
5702 * Return 0 for OK, otherwise fail.
5703 */
rtw_halmac_usb_get_txagg_desc_num(struct dvobj_priv * d,u8 * num)5704 int rtw_halmac_usb_get_txagg_desc_num(struct dvobj_priv *d, u8 *num)
5705 {
5706 struct halmac_adapter *halmac;
5707 struct halmac_api *api;
5708 enum halmac_ret_status status;
5709 u8 val = 0;
5710
5711
5712 halmac = dvobj_to_halmac(d);
5713 api = HALMAC_GET_API(halmac);
5714
5715 status = api->halmac_get_hw_value(halmac, HALMAC_HW_USB_TXAGG_DESC_NUM, &val);
5716 if (status != HALMAC_RET_SUCCESS)
5717 return -1;
5718
5719 *num = val;
5720
5721 return 0;
5722 }
5723
_usb_mode_drv2halmac(enum RTW_USB_SPEED usb_mode)5724 static inline enum halmac_usb_mode _usb_mode_drv2halmac(enum RTW_USB_SPEED usb_mode)
5725 {
5726 enum halmac_usb_mode halmac_usb_mode = HALMAC_USB_MODE_U2;
5727
5728 switch (usb_mode) {
5729 case RTW_USB_SPEED_2:
5730 halmac_usb_mode = HALMAC_USB_MODE_U2;
5731 break;
5732 case RTW_USB_SPEED_3:
5733 halmac_usb_mode = HALMAC_USB_MODE_U3;
5734 break;
5735 default:
5736 halmac_usb_mode = HALMAC_USB_MODE_U2;
5737 break;
5738 }
5739
5740 return halmac_usb_mode;
5741 }
5742
rtw_halmac_switch_usb_mode(struct dvobj_priv * d,enum RTW_USB_SPEED usb_mode)5743 u8 rtw_halmac_switch_usb_mode(struct dvobj_priv *d, enum RTW_USB_SPEED usb_mode)
5744 {
5745 PADAPTER adapter;
5746 struct halmac_adapter *mac;
5747 struct halmac_api *api;
5748 enum halmac_ret_status status;
5749 enum halmac_usb_mode halmac_usb_mode;
5750
5751 adapter = dvobj_get_primary_adapter(d);
5752 mac = dvobj_to_halmac(d);
5753 api = HALMAC_GET_API(mac);
5754 halmac_usb_mode = _usb_mode_drv2halmac(usb_mode);
5755 status = api->halmac_set_hw_value(mac, HALMAC_HW_USB_MODE, (void *)&halmac_usb_mode);
5756
5757 if (HALMAC_RET_SUCCESS != status)
5758 return _FAIL;
5759
5760 return _SUCCESS;
5761 }
5762 #endif /* CONFIG_USB_HCI */
5763
5764 #ifdef CONFIG_BEAMFORMING
5765 #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)5766 int rtw_halmac_bf_add_mu_bfer(struct dvobj_priv *d, u16 paid, u16 csi_para,
5767 u16 my_aid, enum halmac_csi_seg_len sel, u8 *addr)
5768 {
5769 struct halmac_adapter *mac;
5770 struct halmac_api *api;
5771 enum halmac_ret_status status;
5772 struct halmac_mu_bfer_init_para param;
5773
5774
5775 mac = dvobj_to_halmac(d);
5776 api = HALMAC_GET_API(mac);
5777
5778 _rtw_memset(¶m, 0, sizeof(param));
5779 param.paid = paid;
5780 param.csi_para = csi_para;
5781 param.my_aid = my_aid;
5782 param.csi_length_sel = sel;
5783 _rtw_memcpy(param.bfer_address.addr, addr, 6);
5784
5785 status = api->halmac_mu_bfer_entry_init(mac, ¶m);
5786 if (status != HALMAC_RET_SUCCESS)
5787 return -1;
5788
5789 return 0;
5790 }
5791
rtw_halmac_bf_del_mu_bfer(struct dvobj_priv * d)5792 int rtw_halmac_bf_del_mu_bfer(struct dvobj_priv *d)
5793 {
5794 struct halmac_adapter *mac;
5795 struct halmac_api *api;
5796 enum halmac_ret_status status;
5797
5798
5799 mac = dvobj_to_halmac(d);
5800 api = HALMAC_GET_API(mac);
5801
5802 status = api->halmac_mu_bfer_entry_del(mac);
5803 if (status != HALMAC_RET_SUCCESS)
5804 return -1;
5805
5806 return 0;
5807 }
5808
5809
rtw_halmac_bf_cfg_sounding(struct dvobj_priv * d,enum halmac_snd_role role,enum halmac_data_rate rate)5810 int rtw_halmac_bf_cfg_sounding(struct dvobj_priv *d,
5811 enum halmac_snd_role role, enum halmac_data_rate rate)
5812 {
5813 struct halmac_adapter *mac;
5814 struct halmac_api *api;
5815 enum halmac_ret_status status;
5816
5817
5818 mac = dvobj_to_halmac(d);
5819 api = HALMAC_GET_API(mac);
5820
5821 status = api->halmac_cfg_sounding(mac, role, rate);
5822 if (status != HALMAC_RET_SUCCESS)
5823 return -1;
5824
5825 return 0;
5826 }
5827
rtw_halmac_bf_del_sounding(struct dvobj_priv * d,enum halmac_snd_role role)5828 int rtw_halmac_bf_del_sounding(struct dvobj_priv *d,
5829 enum halmac_snd_role role)
5830 {
5831 struct halmac_adapter *mac;
5832 struct halmac_api *api;
5833 enum halmac_ret_status status;
5834
5835
5836 mac = dvobj_to_halmac(d);
5837 api = HALMAC_GET_API(mac);
5838
5839 status = api->halmac_del_sounding(mac, role);
5840 if (status != HALMAC_RET_SUCCESS)
5841 return -1;
5842
5843 return 0;
5844 }
5845
5846 /**
5847 * rtw_halmac_bf_cfg_csi_rate() - Config data rate for CSI report frame by RSSI
5848 * @d: struct dvobj_priv*
5849 * @rssi: RSSI vlaue, unit is percentage (0~100).
5850 * @current_rate: Current CSI frame rate
5851 * Valid value example
5852 * 0 CCK 1M
5853 * 3 CCK 11M
5854 * 4 OFDM 6M
5855 * and so on
5856 * @fixrate_en: Enable to fix CSI frame in VHT rate, otherwise legacy OFDM rate.
5857 * The value "0" for disable, otheriwse enable.
5858 * @new_rate: Return new data rate, and value range is the same as
5859 * current_rate
5860 * @bmp_ofdm54: Return to suggest enabling OFDM 54M for CSI report frame or not,
5861 * The valid values and meanings are:
5862 * 0x00 disable
5863 * 0x01 enable
5864 * 0xFF Keep current setting
5865 *
5866 * According RSSI to config data rate for CSI report frame of Beamforming.
5867 *
5868 * Return 0 for OK, otherwise fail.
5869 */
rtw_halmac_bf_cfg_csi_rate(struct dvobj_priv * d,u8 rssi,u8 current_rate,u8 fixrate_en,u8 * new_rate,u8 * bmp_ofdm54)5870 int rtw_halmac_bf_cfg_csi_rate(struct dvobj_priv *d, u8 rssi,
5871 u8 current_rate, u8 fixrate_en, u8 *new_rate,
5872 u8 *bmp_ofdm54)
5873 {
5874 struct halmac_adapter *mac;
5875 struct halmac_api *api;
5876 enum halmac_ret_status status;
5877
5878
5879 mac = dvobj_to_halmac(d);
5880 api = HALMAC_GET_API(mac);
5881
5882 status = api->halmac_cfg_csi_rate(mac,
5883 rssi, current_rate, fixrate_en, new_rate,
5884 bmp_ofdm54);
5885 if (status != HALMAC_RET_SUCCESS)
5886 return -1;
5887
5888 return 0;
5889 }
5890
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)5891 int rtw_halmac_bf_cfg_mu_mimo(struct dvobj_priv *d, enum halmac_snd_role role,
5892 u8 *sounding_sts, u16 grouping_bitmap, u8 mu_tx_en,
5893 u32 *given_gid_tab, u32 *given_user_pos)
5894 {
5895 struct halmac_adapter *mac;
5896 struct halmac_api *api;
5897 enum halmac_ret_status status;
5898 struct halmac_cfg_mumimo_para param;
5899
5900
5901 mac = dvobj_to_halmac(d);
5902 api = HALMAC_GET_API(mac);
5903
5904 _rtw_memset(¶m, 0, sizeof(param));
5905
5906 param.role = role;
5907 param.grouping_bitmap = grouping_bitmap;
5908 param.mu_tx_en = mu_tx_en;
5909
5910 if (sounding_sts)
5911 _rtw_memcpy(param.sounding_sts, sounding_sts, 6);
5912
5913 if (given_gid_tab)
5914 _rtw_memcpy(param.given_gid_tab, given_gid_tab, 8);
5915
5916 if (given_user_pos)
5917 _rtw_memcpy(param.given_user_pos, given_user_pos, 16);
5918
5919 status = api->halmac_cfg_mumimo(mac, ¶m);
5920 if (status != HALMAC_RET_SUCCESS)
5921 return -1;
5922
5923 return 0;
5924 }
5925
5926 #endif /* RTW_BEAMFORMING_VERSION_2 */
5927 #endif /* CONFIG_BEAMFORMING */
5928