1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3 *
4 * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved.
5 *
6 ******************************************************************************/
7 #define _HAL_INIT_C_
8
9 #include <linux/firmware.h>
10 #include <linux/slab.h>
11 #include <drv_types.h>
12 #include <rtw_debug.h>
13 #include <rtl8723b_hal.h>
14 #include "hal_com_h2c.h"
15
_FWDownloadEnable(struct adapter * padapter,bool enable)16 static void _FWDownloadEnable(struct adapter *padapter, bool enable)
17 {
18 u8 tmp, count = 0;
19
20 if (enable) {
21 /* 8051 enable */
22 tmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
23 rtw_write8(padapter, REG_SYS_FUNC_EN+1, tmp|0x04);
24
25 tmp = rtw_read8(padapter, REG_MCUFWDL);
26 rtw_write8(padapter, REG_MCUFWDL, tmp|0x01);
27
28 do {
29 tmp = rtw_read8(padapter, REG_MCUFWDL);
30 if (tmp & 0x01)
31 break;
32 rtw_write8(padapter, REG_MCUFWDL, tmp|0x01);
33 msleep(1);
34 } while (count++ < 100);
35
36 /* 8051 reset */
37 tmp = rtw_read8(padapter, REG_MCUFWDL+2);
38 rtw_write8(padapter, REG_MCUFWDL+2, tmp&0xf7);
39 } else {
40 /* MCU firmware download disable. */
41 tmp = rtw_read8(padapter, REG_MCUFWDL);
42 rtw_write8(padapter, REG_MCUFWDL, tmp&0xfe);
43 }
44 }
45
_BlockWrite(struct adapter * padapter,void * buffer,u32 buffSize)46 static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
47 {
48 int ret = _SUCCESS;
49
50 u32 blockSize_p1 = 4; /* (Default) Phase #1 : PCI muse use 4-byte write to download FW */
51 u32 blockSize_p2 = 8; /* Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
52 u32 blockSize_p3 = 1; /* Phase #3 : Use 1-byte, the remnant of FW image. */
53 u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
54 u32 remainSize_p1 = 0, remainSize_p2 = 0;
55 u8 *bufferPtr = buffer;
56 u32 i = 0, offset = 0;
57
58 /* printk("====>%s %d\n", __func__, __LINE__); */
59
60 /* 3 Phase #1 */
61 blockCount_p1 = buffSize / blockSize_p1;
62 remainSize_p1 = buffSize % blockSize_p1;
63
64 for (i = 0; i < blockCount_p1; i++) {
65 ret = rtw_write32(padapter, (FW_8723B_START_ADDRESS + i * blockSize_p1), *((u32 *)(bufferPtr + i * blockSize_p1)));
66 if (ret == _FAIL) {
67 printk("====>%s %d i:%d\n", __func__, __LINE__, i);
68 goto exit;
69 }
70 }
71
72 /* 3 Phase #2 */
73 if (remainSize_p1) {
74 offset = blockCount_p1 * blockSize_p1;
75
76 blockCount_p2 = remainSize_p1/blockSize_p2;
77 remainSize_p2 = remainSize_p1%blockSize_p2;
78 }
79
80 /* 3 Phase #3 */
81 if (remainSize_p2) {
82 offset = (blockCount_p1 * blockSize_p1) + (blockCount_p2 * blockSize_p2);
83
84 blockCount_p3 = remainSize_p2 / blockSize_p3;
85
86 for (i = 0; i < blockCount_p3; i++) {
87 ret = rtw_write8(padapter, (FW_8723B_START_ADDRESS + offset + i), *(bufferPtr + offset + i));
88
89 if (ret == _FAIL) {
90 printk("====>%s %d i:%d\n", __func__, __LINE__, i);
91 goto exit;
92 }
93 }
94 }
95 exit:
96 return ret;
97 }
98
_PageWrite(struct adapter * padapter,u32 page,void * buffer,u32 size)99 static int _PageWrite(
100 struct adapter *padapter,
101 u32 page,
102 void *buffer,
103 u32 size
104 )
105 {
106 u8 value8;
107 u8 u8Page = (u8) (page & 0x07);
108
109 value8 = (rtw_read8(padapter, REG_MCUFWDL+2) & 0xF8) | u8Page;
110 rtw_write8(padapter, REG_MCUFWDL+2, value8);
111
112 return _BlockWrite(padapter, buffer, size);
113 }
114
_WriteFW(struct adapter * padapter,void * buffer,u32 size)115 static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
116 {
117 /* Since we need dynamic decide method of dwonload fw, so we call this function to get chip version. */
118 /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
119 int ret = _SUCCESS;
120 u32 pageNums, remainSize;
121 u32 page, offset;
122 u8 *bufferPtr = buffer;
123
124 pageNums = size / MAX_DLFW_PAGE_SIZE;
125 /* RT_ASSERT((pageNums <= 4), ("Page numbers should not greater then 4\n")); */
126 remainSize = size % MAX_DLFW_PAGE_SIZE;
127
128 for (page = 0; page < pageNums; page++) {
129 offset = page * MAX_DLFW_PAGE_SIZE;
130 ret = _PageWrite(padapter, page, bufferPtr+offset, MAX_DLFW_PAGE_SIZE);
131
132 if (ret == _FAIL) {
133 printk("====>%s %d\n", __func__, __LINE__);
134 goto exit;
135 }
136 }
137
138 if (remainSize) {
139 offset = pageNums * MAX_DLFW_PAGE_SIZE;
140 page = pageNums;
141 ret = _PageWrite(padapter, page, bufferPtr+offset, remainSize);
142
143 if (ret == _FAIL) {
144 printk("====>%s %d\n", __func__, __LINE__);
145 goto exit;
146 }
147 }
148
149 exit:
150 return ret;
151 }
152
_8051Reset8723(struct adapter * padapter)153 void _8051Reset8723(struct adapter *padapter)
154 {
155 u8 cpu_rst;
156 u8 io_rst;
157
158
159 /* Reset 8051(WLMCU) IO wrapper */
160 /* 0x1c[8] = 0 */
161 /* Suggested by Isaac@SD1 and Gimmy@SD1, coding by Lucas@20130624 */
162 io_rst = rtw_read8(padapter, REG_RSV_CTRL+1);
163 io_rst &= ~BIT(0);
164 rtw_write8(padapter, REG_RSV_CTRL+1, io_rst);
165
166 cpu_rst = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
167 cpu_rst &= ~BIT(2);
168 rtw_write8(padapter, REG_SYS_FUNC_EN+1, cpu_rst);
169
170 /* Enable 8051 IO wrapper */
171 /* 0x1c[8] = 1 */
172 io_rst = rtw_read8(padapter, REG_RSV_CTRL+1);
173 io_rst |= BIT(0);
174 rtw_write8(padapter, REG_RSV_CTRL+1, io_rst);
175
176 cpu_rst = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
177 cpu_rst |= BIT(2);
178 rtw_write8(padapter, REG_SYS_FUNC_EN+1, cpu_rst);
179 }
180
181 u8 g_fwdl_chksum_fail;
182
polling_fwdl_chksum(struct adapter * adapter,u32 min_cnt,u32 timeout_ms)183 static s32 polling_fwdl_chksum(
184 struct adapter *adapter, u32 min_cnt, u32 timeout_ms
185 )
186 {
187 s32 ret = _FAIL;
188 u32 value32;
189 unsigned long start = jiffies;
190 u32 cnt = 0;
191
192 /* polling CheckSum report */
193 do {
194 cnt++;
195 value32 = rtw_read32(adapter, REG_MCUFWDL);
196 if (value32 & FWDL_ChkSum_rpt || adapter->bSurpriseRemoved || adapter->bDriverStopped)
197 break;
198 yield();
199 } while (jiffies_to_msecs(jiffies-start) < timeout_ms || cnt < min_cnt);
200
201 if (!(value32 & FWDL_ChkSum_rpt)) {
202 goto exit;
203 }
204
205 if (g_fwdl_chksum_fail) {
206 g_fwdl_chksum_fail--;
207 goto exit;
208 }
209
210 ret = _SUCCESS;
211
212 exit:
213
214 return ret;
215 }
216
217 u8 g_fwdl_wintint_rdy_fail;
218
_FWFreeToGo(struct adapter * adapter,u32 min_cnt,u32 timeout_ms)219 static s32 _FWFreeToGo(struct adapter *adapter, u32 min_cnt, u32 timeout_ms)
220 {
221 s32 ret = _FAIL;
222 u32 value32;
223 unsigned long start = jiffies;
224 u32 cnt = 0;
225
226 value32 = rtw_read32(adapter, REG_MCUFWDL);
227 value32 |= MCUFWDL_RDY;
228 value32 &= ~WINTINI_RDY;
229 rtw_write32(adapter, REG_MCUFWDL, value32);
230
231 _8051Reset8723(adapter);
232
233 /* polling for FW ready */
234 do {
235 cnt++;
236 value32 = rtw_read32(adapter, REG_MCUFWDL);
237 if (value32 & WINTINI_RDY || adapter->bSurpriseRemoved || adapter->bDriverStopped)
238 break;
239 yield();
240 } while (jiffies_to_msecs(jiffies - start) < timeout_ms || cnt < min_cnt);
241
242 if (!(value32 & WINTINI_RDY)) {
243 goto exit;
244 }
245
246 if (g_fwdl_wintint_rdy_fail) {
247 g_fwdl_wintint_rdy_fail--;
248 goto exit;
249 }
250
251 ret = _SUCCESS;
252
253 exit:
254
255 return ret;
256 }
257
258 #define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
259
rtl8723b_FirmwareSelfReset(struct adapter * padapter)260 void rtl8723b_FirmwareSelfReset(struct adapter *padapter)
261 {
262 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
263 u8 u1bTmp;
264 u8 Delay = 100;
265
266 if (
267 !(IS_FW_81xxC(padapter) && ((pHalData->FirmwareVersion < 0x21) || (pHalData->FirmwareVersion == 0x21 && pHalData->FirmwareSubVersion < 0x01)))
268 ) { /* after 88C Fw v33.1 */
269 /* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */
270 rtw_write8(padapter, REG_HMETFR+3, 0x20);
271
272 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
273 while (u1bTmp & BIT2) {
274 Delay--;
275 if (Delay == 0)
276 break;
277 udelay(50);
278 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
279 }
280
281 if (Delay == 0) {
282 /* force firmware reset */
283 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN+1);
284 rtw_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT2));
285 }
286 }
287 }
288
289 /* */
290 /* Description: */
291 /* Download 8192C firmware code. */
292 /* */
293 /* */
rtl8723b_FirmwareDownload(struct adapter * padapter,bool bUsedWoWLANFw)294 s32 rtl8723b_FirmwareDownload(struct adapter *padapter, bool bUsedWoWLANFw)
295 {
296 s32 rtStatus = _SUCCESS;
297 u8 write_fw = 0;
298 unsigned long fwdl_start_time;
299 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
300 struct rt_firmware *pFirmware;
301 struct rt_firmware *pBTFirmware;
302 struct rt_firmware_hdr *pFwHdr = NULL;
303 u8 *pFirmwareBuf;
304 u32 FirmwareLen;
305 const struct firmware *fw;
306 struct device *device = dvobj_to_dev(padapter->dvobj);
307 u8 *fwfilepath;
308 struct dvobj_priv *psdpriv = padapter->dvobj;
309 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
310 u8 tmp_ps;
311
312 pFirmware = kzalloc(sizeof(struct rt_firmware), GFP_KERNEL);
313 if (!pFirmware)
314 return _FAIL;
315 pBTFirmware = kzalloc(sizeof(struct rt_firmware), GFP_KERNEL);
316 if (!pBTFirmware) {
317 kfree(pFirmware);
318 return _FAIL;
319 }
320 tmp_ps = rtw_read8(padapter, 0xa3);
321 tmp_ps &= 0xf8;
322 tmp_ps |= 0x02;
323 /* 1. write 0xA3[:2:0] = 3b'010 */
324 rtw_write8(padapter, 0xa3, tmp_ps);
325 /* 2. read power_state = 0xA0[1:0] */
326 tmp_ps = rtw_read8(padapter, 0xa0);
327 tmp_ps &= 0x03;
328 if (tmp_ps != 0x01)
329 pdbgpriv->dbg_downloadfw_pwr_state_cnt++;
330
331 fwfilepath = "rtlwifi/rtl8723bs_nic.bin";
332
333 pr_info("rtl8723bs: acquire FW from file:%s\n", fwfilepath);
334
335 rtStatus = request_firmware(&fw, fwfilepath, device);
336 if (rtStatus) {
337 pr_err("Request firmware failed with error 0x%x\n", rtStatus);
338 rtStatus = _FAIL;
339 goto exit;
340 }
341
342 if (!fw) {
343 pr_err("Firmware %s not available\n", fwfilepath);
344 rtStatus = _FAIL;
345 goto exit;
346 }
347
348 if (fw->size > FW_8723B_SIZE) {
349 rtStatus = _FAIL;
350 goto exit;
351 }
352
353 pFirmware->fw_buffer_sz = kmemdup(fw->data, fw->size, GFP_KERNEL);
354 if (!pFirmware->fw_buffer_sz) {
355 rtStatus = _FAIL;
356 goto exit;
357 }
358
359 pFirmware->fw_length = fw->size;
360 release_firmware(fw);
361 if (pFirmware->fw_length > FW_8723B_SIZE) {
362 rtStatus = _FAIL;
363 netdev_emerg(padapter->pnetdev,
364 "Firmware size:%u exceed %u\n",
365 pFirmware->fw_length, FW_8723B_SIZE);
366 goto release_fw1;
367 }
368
369 pFirmwareBuf = pFirmware->fw_buffer_sz;
370 FirmwareLen = pFirmware->fw_length;
371
372 /* To Check Fw header. Added by tynli. 2009.12.04. */
373 pFwHdr = (struct rt_firmware_hdr *)pFirmwareBuf;
374
375 pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->version);
376 pHalData->FirmwareSubVersion = le16_to_cpu(pFwHdr->subversion);
377 pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->signature);
378
379 if (IS_FW_HEADER_EXIST_8723B(pFwHdr)) {
380 /* Shift 32 bytes for FW header */
381 pFirmwareBuf = pFirmwareBuf + 32;
382 FirmwareLen = FirmwareLen - 32;
383 }
384
385 /* Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */
386 /* or it will cause download Fw fail. 2010.02.01. by tynli. */
387 if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */
388 rtw_write8(padapter, REG_MCUFWDL, 0x00);
389 rtl8723b_FirmwareSelfReset(padapter);
390 }
391
392 _FWDownloadEnable(padapter, true);
393 fwdl_start_time = jiffies;
394 while (
395 !padapter->bDriverStopped &&
396 !padapter->bSurpriseRemoved &&
397 (write_fw++ < 3 || jiffies_to_msecs(jiffies - fwdl_start_time) < 500)
398 ) {
399 /* reset FWDL chksum */
400 rtw_write8(padapter, REG_MCUFWDL, rtw_read8(padapter, REG_MCUFWDL)|FWDL_ChkSum_rpt);
401
402 rtStatus = _WriteFW(padapter, pFirmwareBuf, FirmwareLen);
403 if (rtStatus != _SUCCESS)
404 continue;
405
406 rtStatus = polling_fwdl_chksum(padapter, 5, 50);
407 if (rtStatus == _SUCCESS)
408 break;
409 }
410 _FWDownloadEnable(padapter, false);
411 if (_SUCCESS != rtStatus)
412 goto fwdl_stat;
413
414 rtStatus = _FWFreeToGo(padapter, 10, 200);
415 if (_SUCCESS != rtStatus)
416 goto fwdl_stat;
417
418 fwdl_stat:
419
420 exit:
421 kfree(pFirmware->fw_buffer_sz);
422 kfree(pFirmware);
423 release_fw1:
424 kfree(pBTFirmware);
425 return rtStatus;
426 }
427
rtl8723b_InitializeFirmwareVars(struct adapter * padapter)428 void rtl8723b_InitializeFirmwareVars(struct adapter *padapter)
429 {
430 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
431
432 /* Init Fw LPS related. */
433 adapter_to_pwrctl(padapter)->fw_current_in_ps_mode = false;
434
435 /* Init H2C cmd. */
436 rtw_write8(padapter, REG_HMETFR, 0x0f);
437
438 /* Init H2C counter. by tynli. 2009.12.09. */
439 pHalData->LastHMEBoxNum = 0;
440 /* pHalData->H2CQueueHead = 0; */
441 /* pHalData->H2CQueueTail = 0; */
442 /* pHalData->H2CStopInsertQueue = false; */
443 }
444
rtl8723b_free_hal_data(struct adapter * padapter)445 static void rtl8723b_free_hal_data(struct adapter *padapter)
446 {
447 }
448
449 /* */
450 /* Efuse related code */
451 /* */
hal_EfuseSwitchToBank(struct adapter * padapter,u8 bank,bool bPseudoTest)452 static u8 hal_EfuseSwitchToBank(
453 struct adapter *padapter, u8 bank, bool bPseudoTest
454 )
455 {
456 u8 bRet = false;
457 u32 value32 = 0;
458 #ifdef HAL_EFUSE_MEMORY
459 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
460 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
461 #endif
462
463
464 if (bPseudoTest) {
465 #ifdef HAL_EFUSE_MEMORY
466 pEfuseHal->fakeEfuseBank = bank;
467 #else
468 fakeEfuseBank = bank;
469 #endif
470 bRet = true;
471 } else {
472 value32 = rtw_read32(padapter, EFUSE_TEST);
473 bRet = true;
474 switch (bank) {
475 case 0:
476 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
477 break;
478 case 1:
479 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_0);
480 break;
481 case 2:
482 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_1);
483 break;
484 case 3:
485 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_2);
486 break;
487 default:
488 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
489 bRet = false;
490 break;
491 }
492 rtw_write32(padapter, EFUSE_TEST, value32);
493 }
494
495 return bRet;
496 }
497
Hal_GetEfuseDefinition(struct adapter * padapter,u8 efuseType,u8 type,void * pOut,bool bPseudoTest)498 static void Hal_GetEfuseDefinition(
499 struct adapter *padapter,
500 u8 efuseType,
501 u8 type,
502 void *pOut,
503 bool bPseudoTest
504 )
505 {
506 switch (type) {
507 case TYPE_EFUSE_MAX_SECTION:
508 {
509 u8 *pMax_section;
510 pMax_section = pOut;
511
512 if (efuseType == EFUSE_WIFI)
513 *pMax_section = EFUSE_MAX_SECTION_8723B;
514 else
515 *pMax_section = EFUSE_BT_MAX_SECTION;
516 }
517 break;
518
519 case TYPE_EFUSE_REAL_CONTENT_LEN:
520 {
521 u16 *pu2Tmp;
522 pu2Tmp = pOut;
523
524 if (efuseType == EFUSE_WIFI)
525 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723B;
526 else
527 *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
528 }
529 break;
530
531 case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
532 {
533 u16 *pu2Tmp;
534 pu2Tmp = pOut;
535
536 if (efuseType == EFUSE_WIFI)
537 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723B-EFUSE_OOB_PROTECT_BYTES);
538 else
539 *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN-EFUSE_PROTECT_BYTES_BANK);
540 }
541 break;
542
543 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
544 {
545 u16 *pu2Tmp;
546 pu2Tmp = pOut;
547
548 if (efuseType == EFUSE_WIFI)
549 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723B-EFUSE_OOB_PROTECT_BYTES);
550 else
551 *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN-(EFUSE_PROTECT_BYTES_BANK*3));
552 }
553 break;
554
555 case TYPE_EFUSE_MAP_LEN:
556 {
557 u16 *pu2Tmp;
558 pu2Tmp = pOut;
559
560 if (efuseType == EFUSE_WIFI)
561 *pu2Tmp = EFUSE_MAX_MAP_LEN;
562 else
563 *pu2Tmp = EFUSE_BT_MAP_LEN;
564 }
565 break;
566
567 case TYPE_EFUSE_PROTECT_BYTES_BANK:
568 {
569 u8 *pu1Tmp;
570 pu1Tmp = pOut;
571
572 if (efuseType == EFUSE_WIFI)
573 *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
574 else
575 *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
576 }
577 break;
578
579 case TYPE_EFUSE_CONTENT_LEN_BANK:
580 {
581 u16 *pu2Tmp;
582 pu2Tmp = pOut;
583
584 if (efuseType == EFUSE_WIFI)
585 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723B;
586 else
587 *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
588 }
589 break;
590
591 default:
592 {
593 u8 *pu1Tmp;
594 pu1Tmp = pOut;
595 *pu1Tmp = 0;
596 }
597 break;
598 }
599 }
600
601 #define VOLTAGE_V25 0x03
602 #define LDOE25_SHIFT 28
603
604 /* */
605 /* The following is for compile ok */
606 /* That should be merged with the original in the future */
607 /* */
608 #define EFUSE_ACCESS_ON_8723 0x69 /* For RTL8723 only. */
609 #define EFUSE_ACCESS_OFF_8723 0x00 /* For RTL8723 only. */
610 #define REG_EFUSE_ACCESS_8723 0x00CF /* Efuse access protection for RTL8723 */
611
612 /* */
Hal_BT_EfusePowerSwitch(struct adapter * padapter,u8 bWrite,u8 PwrState)613 static void Hal_BT_EfusePowerSwitch(
614 struct adapter *padapter, u8 bWrite, u8 PwrState
615 )
616 {
617 u8 tempval;
618 if (PwrState) {
619 /* enable BT power cut */
620 /* 0x6A[14] = 1 */
621 tempval = rtw_read8(padapter, 0x6B);
622 tempval |= BIT(6);
623 rtw_write8(padapter, 0x6B, tempval);
624
625 /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
626 /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
627 msleep(1);
628 /* disable BT output isolation */
629 /* 0x6A[15] = 0 */
630 tempval = rtw_read8(padapter, 0x6B);
631 tempval &= ~BIT(7);
632 rtw_write8(padapter, 0x6B, tempval);
633 } else {
634 /* enable BT output isolation */
635 /* 0x6A[15] = 1 */
636 tempval = rtw_read8(padapter, 0x6B);
637 tempval |= BIT(7);
638 rtw_write8(padapter, 0x6B, tempval);
639
640 /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
641 /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
642
643 /* disable BT power cut */
644 /* 0x6A[14] = 1 */
645 tempval = rtw_read8(padapter, 0x6B);
646 tempval &= ~BIT(6);
647 rtw_write8(padapter, 0x6B, tempval);
648 }
649
650 }
Hal_EfusePowerSwitch(struct adapter * padapter,u8 bWrite,u8 PwrState)651 static void Hal_EfusePowerSwitch(
652 struct adapter *padapter, u8 bWrite, u8 PwrState
653 )
654 {
655 u8 tempval;
656 u16 tmpV16;
657
658
659 if (PwrState) {
660 /* To avoid cannot access efuse regsiters after disable/enable several times during DTM test. */
661 /* Suggested by SD1 IsaacHsu. 2013.07.08, added by tynli. */
662 tempval = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL);
663 if (tempval & BIT(0)) { /* SDIO local register is suspend */
664 u8 count = 0;
665
666
667 tempval &= ~BIT(0);
668 rtw_write8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL, tempval);
669
670 /* check 0x86[1:0]= 10'2h, wait power state to leave suspend */
671 do {
672 tempval = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL);
673 tempval &= 0x3;
674 if (tempval == 0x02)
675 break;
676
677 count++;
678 if (count >= 100)
679 break;
680
681 mdelay(10);
682 } while (1);
683 }
684
685 rtw_write8(padapter, REG_EFUSE_ACCESS_8723, EFUSE_ACCESS_ON_8723);
686
687 /* Reset: 0x0000h[28], default valid */
688 tmpV16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
689 if (!(tmpV16 & FEN_ELDR)) {
690 tmpV16 |= FEN_ELDR;
691 rtw_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
692 }
693
694 /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
695 tmpV16 = rtw_read16(padapter, REG_SYS_CLKR);
696 if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
697 tmpV16 |= (LOADER_CLK_EN | ANA8M);
698 rtw_write16(padapter, REG_SYS_CLKR, tmpV16);
699 }
700
701 if (bWrite) {
702 /* Enable LDO 2.5V before read/write action */
703 tempval = rtw_read8(padapter, EFUSE_TEST+3);
704 tempval &= 0x0F;
705 tempval |= (VOLTAGE_V25 << 4);
706 rtw_write8(padapter, EFUSE_TEST+3, (tempval | 0x80));
707
708 /* rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); */
709 }
710 } else {
711 rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
712
713 if (bWrite) {
714 /* Disable LDO 2.5V after read/write action */
715 tempval = rtw_read8(padapter, EFUSE_TEST+3);
716 rtw_write8(padapter, EFUSE_TEST+3, (tempval & 0x7F));
717 }
718
719 }
720 }
721
hal_ReadEFuse_WiFi(struct adapter * padapter,u16 _offset,u16 _size_byte,u8 * pbuf,bool bPseudoTest)722 static void hal_ReadEFuse_WiFi(
723 struct adapter *padapter,
724 u16 _offset,
725 u16 _size_byte,
726 u8 *pbuf,
727 bool bPseudoTest
728 )
729 {
730 #ifdef HAL_EFUSE_MEMORY
731 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
732 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
733 #endif
734 u8 *efuseTbl = NULL;
735 u16 eFuse_Addr = 0;
736 u8 offset, wden;
737 u8 efuseHeader, efuseExtHdr, efuseData;
738 u16 i, total, used;
739 u8 efuse_usage = 0;
740
741 /* */
742 /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
743 /* */
744 if ((_offset + _size_byte) > EFUSE_MAX_MAP_LEN)
745 return;
746
747 efuseTbl = rtw_malloc(EFUSE_MAX_MAP_LEN);
748 if (!efuseTbl)
749 return;
750
751 /* 0xff will be efuse default value instead of 0x00. */
752 memset(efuseTbl, 0xFF, EFUSE_MAX_MAP_LEN);
753
754 /* switch bank back to bank 0 for later BT and wifi use. */
755 hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
756
757 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
758 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseHeader, bPseudoTest);
759 if (efuseHeader == 0xFF)
760 break;
761
762 /* Check PG header for section num. */
763 if (EXT_HEADER(efuseHeader)) { /* extended header */
764 offset = GET_HDR_OFFSET_2_0(efuseHeader);
765
766 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseExtHdr, bPseudoTest);
767 if (ALL_WORDS_DISABLED(efuseExtHdr))
768 continue;
769
770 offset |= ((efuseExtHdr & 0xF0) >> 1);
771 wden = (efuseExtHdr & 0x0F);
772 } else {
773 offset = ((efuseHeader >> 4) & 0x0f);
774 wden = (efuseHeader & 0x0f);
775 }
776
777 if (offset < EFUSE_MAX_SECTION_8723B) {
778 u16 addr;
779 /* Get word enable value from PG header */
780
781 addr = offset * PGPKT_DATA_SIZE;
782 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
783 /* Check word enable condition in the section */
784 if (!(wden & (0x01<<i))) {
785 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
786 efuseTbl[addr] = efuseData;
787
788 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
789 efuseTbl[addr+1] = efuseData;
790 }
791 addr += 2;
792 }
793 } else {
794 eFuse_Addr += Efuse_CalculateWordCnts(wden)*2;
795 }
796 }
797
798 /* Copy from Efuse map to output pointer memory!!! */
799 for (i = 0; i < _size_byte; i++)
800 pbuf[i] = efuseTbl[_offset+i];
801
802 /* Calculate Efuse utilization */
803 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total, bPseudoTest);
804 used = eFuse_Addr - 1;
805 efuse_usage = (u8)((used*100)/total);
806 if (bPseudoTest) {
807 #ifdef HAL_EFUSE_MEMORY
808 pEfuseHal->fakeEfuseUsedBytes = used;
809 #else
810 fakeEfuseUsedBytes = used;
811 #endif
812 } else {
813 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&used);
814 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_USAGE, (u8 *)&efuse_usage);
815 }
816
817 kfree(efuseTbl);
818 }
819
hal_ReadEFuse_BT(struct adapter * padapter,u16 _offset,u16 _size_byte,u8 * pbuf,bool bPseudoTest)820 static void hal_ReadEFuse_BT(
821 struct adapter *padapter,
822 u16 _offset,
823 u16 _size_byte,
824 u8 *pbuf,
825 bool bPseudoTest
826 )
827 {
828 #ifdef HAL_EFUSE_MEMORY
829 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
830 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
831 #endif
832 u8 *efuseTbl;
833 u8 bank;
834 u16 eFuse_Addr;
835 u8 efuseHeader, efuseExtHdr, efuseData;
836 u8 offset, wden;
837 u16 i, total, used;
838 u8 efuse_usage;
839
840
841 /* */
842 /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
843 /* */
844 if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN)
845 return;
846
847 efuseTbl = rtw_malloc(EFUSE_BT_MAP_LEN);
848 if (!efuseTbl)
849 return;
850
851 /* 0xff will be efuse default value instead of 0x00. */
852 memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
853
854 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total, bPseudoTest);
855
856 for (bank = 1; bank < 3; bank++) { /* 8723b Max bake 0~2 */
857 if (hal_EfuseSwitchToBank(padapter, bank, bPseudoTest) == false)
858 goto exit;
859
860 eFuse_Addr = 0;
861
862 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
863 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseHeader, bPseudoTest);
864 if (efuseHeader == 0xFF)
865 break;
866
867 /* Check PG header for section num. */
868 if (EXT_HEADER(efuseHeader)) { /* extended header */
869 offset = GET_HDR_OFFSET_2_0(efuseHeader);
870
871 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseExtHdr, bPseudoTest);
872 if (ALL_WORDS_DISABLED(efuseExtHdr))
873 continue;
874
875
876 offset |= ((efuseExtHdr & 0xF0) >> 1);
877 wden = (efuseExtHdr & 0x0F);
878 } else {
879 offset = ((efuseHeader >> 4) & 0x0f);
880 wden = (efuseHeader & 0x0f);
881 }
882
883 if (offset < EFUSE_BT_MAX_SECTION) {
884 u16 addr;
885
886 addr = offset * PGPKT_DATA_SIZE;
887 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
888 /* Check word enable condition in the section */
889 if (!(wden & (0x01<<i))) {
890 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
891 efuseTbl[addr] = efuseData;
892
893 efuse_OneByteRead(padapter, eFuse_Addr++, &efuseData, bPseudoTest);
894 efuseTbl[addr+1] = efuseData;
895 }
896 addr += 2;
897 }
898 } else {
899 eFuse_Addr += Efuse_CalculateWordCnts(wden)*2;
900 }
901 }
902
903 if ((eFuse_Addr - 1) < total)
904 break;
905
906 }
907
908 /* switch bank back to bank 0 for later BT and wifi use. */
909 hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
910
911 /* Copy from Efuse map to output pointer memory!!! */
912 for (i = 0; i < _size_byte; i++)
913 pbuf[i] = efuseTbl[_offset+i];
914
915 /* */
916 /* Calculate Efuse utilization. */
917 /* */
918 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total, bPseudoTest);
919 used = (EFUSE_BT_REAL_BANK_CONTENT_LEN*(bank-1)) + eFuse_Addr - 1;
920 efuse_usage = (u8)((used*100)/total);
921 if (bPseudoTest) {
922 #ifdef HAL_EFUSE_MEMORY
923 pEfuseHal->fakeBTEfuseUsedBytes = used;
924 #else
925 fakeBTEfuseUsedBytes = used;
926 #endif
927 } else {
928 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&used);
929 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BT_USAGE, (u8 *)&efuse_usage);
930 }
931
932 exit:
933 kfree(efuseTbl);
934 }
935
Hal_ReadEFuse(struct adapter * padapter,u8 efuseType,u16 _offset,u16 _size_byte,u8 * pbuf,bool bPseudoTest)936 static void Hal_ReadEFuse(
937 struct adapter *padapter,
938 u8 efuseType,
939 u16 _offset,
940 u16 _size_byte,
941 u8 *pbuf,
942 bool bPseudoTest
943 )
944 {
945 if (efuseType == EFUSE_WIFI)
946 hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf, bPseudoTest);
947 else
948 hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf, bPseudoTest);
949 }
950
hal_EfuseGetCurrentSize_WiFi(struct adapter * padapter,bool bPseudoTest)951 static u16 hal_EfuseGetCurrentSize_WiFi(
952 struct adapter *padapter, bool bPseudoTest
953 )
954 {
955 #ifdef HAL_EFUSE_MEMORY
956 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
957 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
958 #endif
959 u16 efuse_addr = 0;
960 u16 start_addr = 0; /* for debug */
961 u8 hoffset = 0, hworden = 0;
962 u8 efuse_data, word_cnts = 0;
963 u32 count = 0; /* for debug */
964
965
966 if (bPseudoTest) {
967 #ifdef HAL_EFUSE_MEMORY
968 efuse_addr = (u16)pEfuseHal->fakeEfuseUsedBytes;
969 #else
970 efuse_addr = (u16)fakeEfuseUsedBytes;
971 #endif
972 } else
973 rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
974
975 start_addr = efuse_addr;
976
977 /* switch bank back to bank 0 for later BT and wifi use. */
978 hal_EfuseSwitchToBank(padapter, 0, bPseudoTest);
979
980 count = 0;
981 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
982 if (efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest) == false)
983 goto error;
984
985 if (efuse_data == 0xFF)
986 break;
987
988 if ((start_addr != 0) && (efuse_addr == start_addr)) {
989 count++;
990
991 efuse_data = 0xFF;
992 if (count < 4) {
993 /* try again! */
994
995 if (count > 2) {
996 /* try again form address 0 */
997 efuse_addr = 0;
998 start_addr = 0;
999 }
1000
1001 continue;
1002 }
1003
1004 goto error;
1005 }
1006
1007 if (EXT_HEADER(efuse_data)) {
1008 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
1009 efuse_addr++;
1010 efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
1011 if (ALL_WORDS_DISABLED(efuse_data))
1012 continue;
1013
1014 hoffset |= ((efuse_data & 0xF0) >> 1);
1015 hworden = efuse_data & 0x0F;
1016 } else {
1017 hoffset = (efuse_data>>4) & 0x0F;
1018 hworden = efuse_data & 0x0F;
1019 }
1020
1021 word_cnts = Efuse_CalculateWordCnts(hworden);
1022 efuse_addr += (word_cnts*2)+1;
1023 }
1024
1025 if (bPseudoTest) {
1026 #ifdef HAL_EFUSE_MEMORY
1027 pEfuseHal->fakeEfuseUsedBytes = efuse_addr;
1028 #else
1029 fakeEfuseUsedBytes = efuse_addr;
1030 #endif
1031 } else
1032 rtw_hal_set_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
1033
1034 goto exit;
1035
1036 error:
1037 /* report max size to prevent write efuse */
1038 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_addr, bPseudoTest);
1039
1040 exit:
1041
1042 return efuse_addr;
1043 }
1044
hal_EfuseGetCurrentSize_BT(struct adapter * padapter,u8 bPseudoTest)1045 static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
1046 {
1047 #ifdef HAL_EFUSE_MEMORY
1048 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1049 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
1050 #endif
1051 u16 btusedbytes;
1052 u16 efuse_addr;
1053 u8 bank, startBank;
1054 u8 hoffset = 0, hworden = 0;
1055 u8 efuse_data, word_cnts = 0;
1056 u16 retU2 = 0;
1057
1058 if (bPseudoTest) {
1059 #ifdef HAL_EFUSE_MEMORY
1060 btusedbytes = pEfuseHal->fakeBTEfuseUsedBytes;
1061 #else
1062 btusedbytes = fakeBTEfuseUsedBytes;
1063 #endif
1064 } else
1065 rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&btusedbytes);
1066
1067 efuse_addr = (u16)((btusedbytes%EFUSE_BT_REAL_BANK_CONTENT_LEN));
1068 startBank = (u8)(1+(btusedbytes/EFUSE_BT_REAL_BANK_CONTENT_LEN));
1069
1070 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2, bPseudoTest);
1071
1072 for (bank = startBank; bank < 3; bank++) {
1073 if (hal_EfuseSwitchToBank(padapter, bank, bPseudoTest) == false)
1074 /* bank = EFUSE_MAX_BANK; */
1075 break;
1076
1077 /* only when bank is switched we have to reset the efuse_addr. */
1078 if (bank != startBank)
1079 efuse_addr = 0;
1080 #if 1
1081
1082 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1083 if (efuse_OneByteRead(padapter, efuse_addr,
1084 &efuse_data, bPseudoTest) == false)
1085 /* bank = EFUSE_MAX_BANK; */
1086 break;
1087
1088 if (efuse_data == 0xFF)
1089 break;
1090
1091 if (EXT_HEADER(efuse_data)) {
1092 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
1093 efuse_addr++;
1094 efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
1095
1096 if (ALL_WORDS_DISABLED(efuse_data)) {
1097 efuse_addr++;
1098 continue;
1099 }
1100
1101 /* hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); */
1102 hoffset |= ((efuse_data & 0xF0) >> 1);
1103 hworden = efuse_data & 0x0F;
1104 } else {
1105 hoffset = (efuse_data>>4) & 0x0F;
1106 hworden = efuse_data & 0x0F;
1107 }
1108
1109 word_cnts = Efuse_CalculateWordCnts(hworden);
1110 /* read next header */
1111 efuse_addr += (word_cnts*2)+1;
1112 }
1113 #else
1114 while (
1115 bContinual &&
1116 efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest) &&
1117 AVAILABLE_EFUSE_ADDR(efuse_addr)
1118 ) {
1119 if (efuse_data != 0xFF) {
1120 if ((efuse_data&0x1F) == 0x0F) { /* extended header */
1121 hoffset = efuse_data;
1122 efuse_addr++;
1123 efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
1124 if ((efuse_data & 0x0F) == 0x0F) {
1125 efuse_addr++;
1126 continue;
1127 } else {
1128 hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
1129 hworden = efuse_data & 0x0F;
1130 }
1131 } else {
1132 hoffset = (efuse_data>>4) & 0x0F;
1133 hworden = efuse_data & 0x0F;
1134 }
1135 word_cnts = Efuse_CalculateWordCnts(hworden);
1136 /* read next header */
1137 efuse_addr = efuse_addr + (word_cnts*2)+1;
1138 } else
1139 bContinual = false;
1140 }
1141 #endif
1142
1143
1144 /* Check if we need to check next bank efuse */
1145 if (efuse_addr < retU2)
1146 break; /* don't need to check next bank. */
1147 }
1148
1149 retU2 = ((bank-1)*EFUSE_BT_REAL_BANK_CONTENT_LEN)+efuse_addr;
1150 if (bPseudoTest) {
1151 pEfuseHal->fakeBTEfuseUsedBytes = retU2;
1152 /* RT_DISP(FEEPROM, EFUSE_PG, ("Hal_EfuseGetCurrentSize_BT92C(), already use %u bytes\n", pEfuseHal->fakeBTEfuseUsedBytes)); */
1153 } else {
1154 pEfuseHal->BTEfuseUsedBytes = retU2;
1155 /* RT_DISP(FEEPROM, EFUSE_PG, ("Hal_EfuseGetCurrentSize_BT92C(), already use %u bytes\n", pEfuseHal->BTEfuseUsedBytes)); */
1156 }
1157
1158 return retU2;
1159 }
1160
Hal_EfuseGetCurrentSize(struct adapter * padapter,u8 efuseType,bool bPseudoTest)1161 static u16 Hal_EfuseGetCurrentSize(
1162 struct adapter *padapter, u8 efuseType, bool bPseudoTest
1163 )
1164 {
1165 u16 ret = 0;
1166
1167 if (efuseType == EFUSE_WIFI)
1168 ret = hal_EfuseGetCurrentSize_WiFi(padapter, bPseudoTest);
1169 else
1170 ret = hal_EfuseGetCurrentSize_BT(padapter, bPseudoTest);
1171
1172 return ret;
1173 }
1174
Hal_EfuseWordEnableDataWrite(struct adapter * padapter,u16 efuse_addr,u8 word_en,u8 * data,bool bPseudoTest)1175 static u8 Hal_EfuseWordEnableDataWrite(
1176 struct adapter *padapter,
1177 u16 efuse_addr,
1178 u8 word_en,
1179 u8 *data,
1180 bool bPseudoTest
1181 )
1182 {
1183 u16 tmpaddr = 0;
1184 u16 start_addr = efuse_addr;
1185 u8 badworden = 0x0F;
1186 u8 tmpdata[PGPKT_DATA_SIZE];
1187
1188 memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
1189
1190 if (!(word_en & BIT(0))) {
1191 tmpaddr = start_addr;
1192 efuse_OneByteWrite(padapter, start_addr++, data[0], bPseudoTest);
1193 efuse_OneByteWrite(padapter, start_addr++, data[1], bPseudoTest);
1194
1195 efuse_OneByteRead(padapter, tmpaddr, &tmpdata[0], bPseudoTest);
1196 efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[1], bPseudoTest);
1197 if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) {
1198 badworden &= (~BIT(0));
1199 }
1200 }
1201 if (!(word_en & BIT(1))) {
1202 tmpaddr = start_addr;
1203 efuse_OneByteWrite(padapter, start_addr++, data[2], bPseudoTest);
1204 efuse_OneByteWrite(padapter, start_addr++, data[3], bPseudoTest);
1205
1206 efuse_OneByteRead(padapter, tmpaddr, &tmpdata[2], bPseudoTest);
1207 efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[3], bPseudoTest);
1208 if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) {
1209 badworden &= (~BIT(1));
1210 }
1211 }
1212
1213 if (!(word_en & BIT(2))) {
1214 tmpaddr = start_addr;
1215 efuse_OneByteWrite(padapter, start_addr++, data[4], bPseudoTest);
1216 efuse_OneByteWrite(padapter, start_addr++, data[5], bPseudoTest);
1217
1218 efuse_OneByteRead(padapter, tmpaddr, &tmpdata[4], bPseudoTest);
1219 efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[5], bPseudoTest);
1220 if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) {
1221 badworden &= (~BIT(2));
1222 }
1223 }
1224
1225 if (!(word_en & BIT(3))) {
1226 tmpaddr = start_addr;
1227 efuse_OneByteWrite(padapter, start_addr++, data[6], bPseudoTest);
1228 efuse_OneByteWrite(padapter, start_addr++, data[7], bPseudoTest);
1229
1230 efuse_OneByteRead(padapter, tmpaddr, &tmpdata[6], bPseudoTest);
1231 efuse_OneByteRead(padapter, tmpaddr+1, &tmpdata[7], bPseudoTest);
1232 if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) {
1233 badworden &= (~BIT(3));
1234 }
1235 }
1236
1237 return badworden;
1238 }
1239
Hal_EfusePgPacketRead(struct adapter * padapter,u8 offset,u8 * data,bool bPseudoTest)1240 static s32 Hal_EfusePgPacketRead(
1241 struct adapter *padapter,
1242 u8 offset,
1243 u8 *data,
1244 bool bPseudoTest
1245 )
1246 {
1247 u8 efuse_data, word_cnts = 0;
1248 u16 efuse_addr = 0;
1249 u8 hoffset = 0, hworden = 0;
1250 u8 i;
1251 u8 max_section = 0;
1252 s32 ret;
1253
1254
1255 if (!data)
1256 return false;
1257
1258 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, &max_section, bPseudoTest);
1259 if (offset > max_section)
1260 return false;
1261
1262 memset(data, 0xFF, PGPKT_DATA_SIZE);
1263 ret = true;
1264
1265 /* */
1266 /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
1267 /* Skip dummy parts to prevent unexpected data read from Efuse. */
1268 /* By pass right now. 2009.02.19. */
1269 /* */
1270 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1271 if (efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest) == false) {
1272 ret = false;
1273 break;
1274 }
1275
1276 if (efuse_data == 0xFF)
1277 break;
1278
1279 if (EXT_HEADER(efuse_data)) {
1280 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
1281 efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
1282 if (ALL_WORDS_DISABLED(efuse_data))
1283 continue;
1284
1285 hoffset |= ((efuse_data & 0xF0) >> 1);
1286 hworden = efuse_data & 0x0F;
1287 } else {
1288 hoffset = (efuse_data>>4) & 0x0F;
1289 hworden = efuse_data & 0x0F;
1290 }
1291
1292 if (hoffset == offset) {
1293 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
1294 /* Check word enable condition in the section */
1295 if (!(hworden & (0x01<<i))) {
1296 efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
1297 data[i*2] = efuse_data;
1298
1299 efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
1300 data[(i*2)+1] = efuse_data;
1301 }
1302 }
1303 } else {
1304 word_cnts = Efuse_CalculateWordCnts(hworden);
1305 efuse_addr += word_cnts*2;
1306 }
1307 }
1308
1309 return ret;
1310 }
1311
hal_EfusePgCheckAvailableAddr(struct adapter * padapter,u8 efuseType,u8 bPseudoTest)1312 static u8 hal_EfusePgCheckAvailableAddr(
1313 struct adapter *padapter, u8 efuseType, u8 bPseudoTest
1314 )
1315 {
1316 u16 max_available = 0;
1317 u16 current_size;
1318
1319
1320 EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &max_available, bPseudoTest);
1321
1322 current_size = Efuse_GetCurrentSize(padapter, efuseType, bPseudoTest);
1323 if (current_size >= max_available)
1324 return false;
1325
1326 return true;
1327 }
1328
hal_EfuseConstructPGPkt(u8 offset,u8 word_en,u8 * pData,struct pgpkt_struct * pTargetPkt)1329 static void hal_EfuseConstructPGPkt(
1330 u8 offset,
1331 u8 word_en,
1332 u8 *pData,
1333 struct pgpkt_struct *pTargetPkt
1334 )
1335 {
1336 memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
1337 pTargetPkt->offset = offset;
1338 pTargetPkt->word_en = word_en;
1339 efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
1340 pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
1341 }
1342
hal_EfusePartialWriteCheck(struct adapter * padapter,u8 efuseType,u16 * pAddr,struct pgpkt_struct * pTargetPkt,u8 bPseudoTest)1343 static u8 hal_EfusePartialWriteCheck(
1344 struct adapter *padapter,
1345 u8 efuseType,
1346 u16 *pAddr,
1347 struct pgpkt_struct *pTargetPkt,
1348 u8 bPseudoTest
1349 )
1350 {
1351 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1352 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
1353 u8 bRet = false;
1354 u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
1355 u8 efuse_data = 0;
1356
1357 EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_max_available_len, bPseudoTest);
1358 EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max, bPseudoTest);
1359
1360 if (efuseType == EFUSE_WIFI) {
1361 if (bPseudoTest) {
1362 #ifdef HAL_EFUSE_MEMORY
1363 startAddr = (u16)pEfuseHal->fakeEfuseUsedBytes;
1364 #else
1365 startAddr = (u16)fakeEfuseUsedBytes;
1366 #endif
1367 } else
1368 rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
1369 } else {
1370 if (bPseudoTest) {
1371 #ifdef HAL_EFUSE_MEMORY
1372 startAddr = (u16)pEfuseHal->fakeBTEfuseUsedBytes;
1373 #else
1374 startAddr = (u16)fakeBTEfuseUsedBytes;
1375 #endif
1376 } else
1377 rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&startAddr);
1378 }
1379 startAddr %= efuse_max;
1380
1381 while (1) {
1382 if (startAddr >= efuse_max_available_len) {
1383 bRet = false;
1384 break;
1385 }
1386
1387 if (efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
1388 #if 1
1389 bRet = false;
1390 break;
1391 #else
1392 if (EXT_HEADER(efuse_data)) {
1393 cur_header = efuse_data;
1394 startAddr++;
1395 efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest);
1396 if (ALL_WORDS_DISABLED(efuse_data)) {
1397 bRet = false;
1398 break;
1399 } else {
1400 curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
1401 curPkt.word_en = efuse_data & 0x0F;
1402 }
1403 } else {
1404 cur_header = efuse_data;
1405 curPkt.offset = (cur_header>>4) & 0x0F;
1406 curPkt.word_en = cur_header & 0x0F;
1407 }
1408
1409 curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
1410 /* if same header is found but no data followed */
1411 /* write some part of data followed by the header. */
1412 if (
1413 (curPkt.offset == pTargetPkt->offset) &&
1414 (hal_EfuseCheckIfDatafollowed(padapter, curPkt.word_cnts, startAddr+1, bPseudoTest) == false) &&
1415 wordEnMatched(pTargetPkt, &curPkt, &matched_wden) == true
1416 ) {
1417 /* Here to write partial data */
1418 badworden = Efuse_WordEnableDataWrite(padapter, startAddr+1, matched_wden, pTargetPkt->data, bPseudoTest);
1419 if (badworden != 0x0F) {
1420 u32 PgWriteSuccess = 0;
1421 /* if write fail on some words, write these bad words again */
1422 if (efuseType == EFUSE_WIFI)
1423 PgWriteSuccess = Efuse_PgPacketWrite(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
1424 else
1425 PgWriteSuccess = Efuse_PgPacketWrite_BT(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
1426
1427 if (!PgWriteSuccess) {
1428 bRet = false; /* write fail, return */
1429 break;
1430 }
1431 }
1432 /* partial write ok, update the target packet for later use */
1433 for (i = 0; i < 4; i++) {
1434 if ((matched_wden & (0x1<<i)) == 0) { /* this word has been written */
1435 pTargetPkt->word_en |= (0x1<<i); /* disable the word */
1436 }
1437 }
1438 pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
1439 }
1440 /* read from next header */
1441 startAddr = startAddr + (curPkt.word_cnts*2) + 1;
1442 #endif
1443 } else {
1444 /* not used header, 0xff */
1445 *pAddr = startAddr;
1446 bRet = true;
1447 break;
1448 }
1449 }
1450
1451 return bRet;
1452 }
1453
hal_EfusePgPacketWrite1ByteHeader(struct adapter * padapter,u8 efuseType,u16 * pAddr,struct pgpkt_struct * pTargetPkt,u8 bPseudoTest)1454 static u8 hal_EfusePgPacketWrite1ByteHeader(
1455 struct adapter *padapter,
1456 u8 efuseType,
1457 u16 *pAddr,
1458 struct pgpkt_struct *pTargetPkt,
1459 u8 bPseudoTest
1460 )
1461 {
1462 u8 pg_header = 0, tmp_header = 0;
1463 u16 efuse_addr = *pAddr;
1464 u8 repeatcnt = 0;
1465
1466 pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
1467
1468 do {
1469 efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
1470 efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
1471 if (tmp_header != 0xFF)
1472 break;
1473 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
1474 return false;
1475
1476 } while (1);
1477
1478 if (tmp_header != pg_header)
1479 return false;
1480
1481 *pAddr = efuse_addr;
1482
1483 return true;
1484 }
1485
hal_EfusePgPacketWrite2ByteHeader(struct adapter * padapter,u8 efuseType,u16 * pAddr,struct pgpkt_struct * pTargetPkt,u8 bPseudoTest)1486 static u8 hal_EfusePgPacketWrite2ByteHeader(
1487 struct adapter *padapter,
1488 u8 efuseType,
1489 u16 *pAddr,
1490 struct pgpkt_struct *pTargetPkt,
1491 u8 bPseudoTest
1492 )
1493 {
1494 u16 efuse_addr, efuse_max_available_len = 0;
1495 u8 pg_header = 0, tmp_header = 0;
1496 u8 repeatcnt = 0;
1497
1498 EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &efuse_max_available_len, bPseudoTest);
1499
1500 efuse_addr = *pAddr;
1501 if (efuse_addr >= efuse_max_available_len)
1502 return false;
1503
1504 pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
1505
1506 do {
1507 efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
1508 efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
1509 if (tmp_header != 0xFF)
1510 break;
1511 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
1512 return false;
1513
1514 } while (1);
1515
1516 if (tmp_header != pg_header)
1517 return false;
1518
1519 /* to write ext_header */
1520 efuse_addr++;
1521 pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
1522
1523 do {
1524 efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
1525 efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
1526 if (tmp_header != 0xFF)
1527 break;
1528 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
1529 return false;
1530
1531 } while (1);
1532
1533 if (tmp_header != pg_header) /* offset PG fail */
1534 return false;
1535
1536 *pAddr = efuse_addr;
1537
1538 return true;
1539 }
1540
hal_EfusePgPacketWriteHeader(struct adapter * padapter,u8 efuseType,u16 * pAddr,struct pgpkt_struct * pTargetPkt,u8 bPseudoTest)1541 static u8 hal_EfusePgPacketWriteHeader(
1542 struct adapter *padapter,
1543 u8 efuseType,
1544 u16 *pAddr,
1545 struct pgpkt_struct *pTargetPkt,
1546 u8 bPseudoTest
1547 )
1548 {
1549 u8 bRet = false;
1550
1551 if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
1552 bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
1553 else
1554 bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
1555
1556 return bRet;
1557 }
1558
hal_EfusePgPacketWriteData(struct adapter * padapter,u8 efuseType,u16 * pAddr,struct pgpkt_struct * pTargetPkt,u8 bPseudoTest)1559 static u8 hal_EfusePgPacketWriteData(
1560 struct adapter *padapter,
1561 u8 efuseType,
1562 u16 *pAddr,
1563 struct pgpkt_struct *pTargetPkt,
1564 u8 bPseudoTest
1565 )
1566 {
1567 u16 efuse_addr;
1568 u8 badworden;
1569
1570
1571 efuse_addr = *pAddr;
1572 badworden = Efuse_WordEnableDataWrite(padapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest);
1573 if (badworden != 0x0F)
1574 return false;
1575
1576 return true;
1577 }
1578
Hal_EfusePgPacketWrite(struct adapter * padapter,u8 offset,u8 word_en,u8 * pData,bool bPseudoTest)1579 static s32 Hal_EfusePgPacketWrite(
1580 struct adapter *padapter,
1581 u8 offset,
1582 u8 word_en,
1583 u8 *pData,
1584 bool bPseudoTest
1585 )
1586 {
1587 struct pgpkt_struct targetPkt;
1588 u16 startAddr = 0;
1589 u8 efuseType = EFUSE_WIFI;
1590
1591 if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
1592 return false;
1593
1594 hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
1595
1596 if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
1597 return false;
1598
1599 if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
1600 return false;
1601
1602 if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
1603 return false;
1604
1605 return true;
1606 }
1607
Hal_EfusePgPacketWrite_BT(struct adapter * padapter,u8 offset,u8 word_en,u8 * pData,bool bPseudoTest)1608 static bool Hal_EfusePgPacketWrite_BT(
1609 struct adapter *padapter,
1610 u8 offset,
1611 u8 word_en,
1612 u8 *pData,
1613 bool bPseudoTest
1614 )
1615 {
1616 struct pgpkt_struct targetPkt;
1617 u16 startAddr = 0;
1618 u8 efuseType = EFUSE_BT;
1619
1620 if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
1621 return false;
1622
1623 hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
1624
1625 if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
1626 return false;
1627
1628 if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
1629 return false;
1630
1631 if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
1632 return false;
1633
1634 return true;
1635 }
1636
ReadChipVersion8723B(struct adapter * padapter)1637 static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
1638 {
1639 u32 value32;
1640 struct hal_version ChipVersion;
1641 struct hal_com_data *pHalData;
1642
1643 /* YJ, TODO, move read chip type here */
1644 pHalData = GET_HAL_DATA(padapter);
1645
1646 value32 = rtw_read32(padapter, REG_SYS_CFG);
1647 ChipVersion.ICType = CHIP_8723B;
1648 ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
1649 ChipVersion.RFType = RF_TYPE_1T1R;
1650 ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
1651 ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
1652
1653 /* For regulator mode. by tynli. 2011.01.14 */
1654 pHalData->RegulatorMode = ((value32 & SPS_SEL) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
1655
1656 value32 = rtw_read32(padapter, REG_GPIO_OUTSTS);
1657 ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20); /* ROM code version. */
1658
1659 /* For multi-function consideration. Added by Roger, 2010.10.06. */
1660 pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
1661 value32 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
1662 pHalData->MultiFunc |= ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0);
1663 pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
1664 pHalData->MultiFunc |= ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
1665 pHalData->PolarityCtl = ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT : RT_POLARITY_LOW_ACT);
1666 #if 1
1667 dump_chip_info(ChipVersion);
1668 #endif
1669 pHalData->VersionID = ChipVersion;
1670 if (IS_1T2R(ChipVersion))
1671 pHalData->rf_type = RF_1T2R;
1672 else if (IS_2T2R(ChipVersion))
1673 pHalData->rf_type = RF_2T2R;
1674 else
1675 pHalData->rf_type = RF_1T1R;
1676
1677 return ChipVersion;
1678 }
1679
rtl8723b_read_chip_version(struct adapter * padapter)1680 static void rtl8723b_read_chip_version(struct adapter *padapter)
1681 {
1682 ReadChipVersion8723B(padapter);
1683 }
1684
rtl8723b_InitBeaconParameters(struct adapter * padapter)1685 void rtl8723b_InitBeaconParameters(struct adapter *padapter)
1686 {
1687 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1688 u16 val16;
1689 u8 val8;
1690
1691
1692 val8 = DIS_TSF_UDT;
1693 val16 = val8 | (val8 << 8); /* port0 and port1 */
1694
1695 /* Enable prot0 beacon function for PSTDMA */
1696 val16 |= EN_BCN_FUNCTION;
1697
1698 rtw_write16(padapter, REG_BCN_CTRL, val16);
1699
1700 /* TODO: Remove these magic number */
1701 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0x6404);/* ms */
1702 /* Firmware will control REG_DRVERLYINT when power saving is enable, */
1703 /* so don't set this register on STA mode. */
1704 if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false)
1705 rtw_write8(padapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME_8723B); /* 5ms */
1706 rtw_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME_8723B); /* 2ms */
1707
1708 /* Suggested by designer timchen. Change beacon AIFS to the largest number */
1709 /* beacause test chip does not contension before sending beacon. by tynli. 2009.11.03 */
1710 rtw_write16(padapter, REG_BCNTCFG, 0x660F);
1711
1712 pHalData->RegBcnCtrlVal = rtw_read8(padapter, REG_BCN_CTRL);
1713 pHalData->RegTxPause = rtw_read8(padapter, REG_TXPAUSE);
1714 pHalData->RegFwHwTxQCtrl = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2);
1715 pHalData->RegReg542 = rtw_read8(padapter, REG_TBTT_PROHIBIT+2);
1716 pHalData->RegCR_1 = rtw_read8(padapter, REG_CR+1);
1717 }
1718
_InitBurstPktLen_8723BS(struct adapter * Adapter)1719 void _InitBurstPktLen_8723BS(struct adapter *Adapter)
1720 {
1721 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
1722
1723 rtw_write8(Adapter, 0x4c7, rtw_read8(Adapter, 0x4c7)|BIT(7)); /* enable single pkt ampdu */
1724 rtw_write8(Adapter, REG_RX_PKT_LIMIT_8723B, 0x18); /* for VHT packet length 11K */
1725 rtw_write8(Adapter, REG_MAX_AGGR_NUM_8723B, 0x1F);
1726 rtw_write8(Adapter, REG_PIFS_8723B, 0x00);
1727 rtw_write8(Adapter, REG_FWHW_TXQ_CTRL_8723B, rtw_read8(Adapter, REG_FWHW_TXQ_CTRL)&(~BIT(7)));
1728 if (pHalData->AMPDUBurstMode)
1729 rtw_write8(Adapter, REG_AMPDU_BURST_MODE_8723B, 0x5F);
1730 rtw_write8(Adapter, REG_AMPDU_MAX_TIME_8723B, 0x70);
1731
1732 /* ARFB table 9 for 11ac 5G 2SS */
1733 rtw_write32(Adapter, REG_ARFR0_8723B, 0x00000010);
1734 if (IS_NORMAL_CHIP(pHalData->VersionID))
1735 rtw_write32(Adapter, REG_ARFR0_8723B+4, 0xfffff000);
1736 else
1737 rtw_write32(Adapter, REG_ARFR0_8723B+4, 0x3e0ff000);
1738
1739 /* ARFB table 10 for 11ac 5G 1SS */
1740 rtw_write32(Adapter, REG_ARFR1_8723B, 0x00000010);
1741 rtw_write32(Adapter, REG_ARFR1_8723B+4, 0x003ff000);
1742 }
1743
ResumeTxBeacon(struct adapter * padapter)1744 static void ResumeTxBeacon(struct adapter *padapter)
1745 {
1746 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1747
1748 pHalData->RegFwHwTxQCtrl |= BIT(6);
1749 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
1750 rtw_write8(padapter, REG_TBTT_PROHIBIT+1, 0xff);
1751 pHalData->RegReg542 |= BIT(0);
1752 rtw_write8(padapter, REG_TBTT_PROHIBIT+2, pHalData->RegReg542);
1753 }
1754
StopTxBeacon(struct adapter * padapter)1755 static void StopTxBeacon(struct adapter *padapter)
1756 {
1757 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1758
1759 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
1760 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
1761 rtw_write8(padapter, REG_TBTT_PROHIBIT+1, 0x64);
1762 pHalData->RegReg542 &= ~BIT(0);
1763 rtw_write8(padapter, REG_TBTT_PROHIBIT+2, pHalData->RegReg542);
1764
1765 CheckFwRsvdPageContent(padapter); /* 2010.06.23. Added by tynli. */
1766 }
1767
_BeaconFunctionEnable(struct adapter * padapter,u8 Enable,u8 Linked)1768 static void _BeaconFunctionEnable(struct adapter *padapter, u8 Enable, u8 Linked)
1769 {
1770 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB);
1771 rtw_write8(padapter, REG_RD_CTRL+1, 0x6F);
1772 }
1773
rtl8723b_SetBeaconRelatedRegisters(struct adapter * padapter)1774 static void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
1775 {
1776 u8 val8;
1777 u32 value32;
1778 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1779 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1780 u32 bcn_ctrl_reg;
1781
1782 /* reset TSF, enable update TSF, correcting TSF On Beacon */
1783
1784 /* REG_BCN_INTERVAL */
1785 /* REG_BCNDMATIM */
1786 /* REG_ATIMWND */
1787 /* REG_TBTT_PROHIBIT */
1788 /* REG_DRVERLYINT */
1789 /* REG_BCN_MAX_ERR */
1790 /* REG_BCNTCFG (0x510) */
1791 /* REG_DUAL_TSF_RST */
1792 /* REG_BCN_CTRL (0x550) */
1793
1794
1795 bcn_ctrl_reg = REG_BCN_CTRL;
1796
1797 /* */
1798 /* ATIM window */
1799 /* */
1800 rtw_write16(padapter, REG_ATIMWND, 2);
1801
1802 /* */
1803 /* Beacon interval (in unit of TU). */
1804 /* */
1805 rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
1806
1807 rtl8723b_InitBeaconParameters(padapter);
1808
1809 rtw_write8(padapter, REG_SLOT, 0x09);
1810
1811 /* */
1812 /* Reset TSF Timer to zero, added by Roger. 2008.06.24 */
1813 /* */
1814 value32 = rtw_read32(padapter, REG_TCR);
1815 value32 &= ~TSFRST;
1816 rtw_write32(padapter, REG_TCR, value32);
1817
1818 value32 |= TSFRST;
1819 rtw_write32(padapter, REG_TCR, value32);
1820
1821 /* NOTE: Fix test chip's bug (about contention windows's randomness) */
1822 if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == true) {
1823 rtw_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50);
1824 rtw_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50);
1825 }
1826
1827 _BeaconFunctionEnable(padapter, true, true);
1828
1829 ResumeTxBeacon(padapter);
1830 val8 = rtw_read8(padapter, bcn_ctrl_reg);
1831 val8 |= DIS_BCNQ_SUB;
1832 rtw_write8(padapter, bcn_ctrl_reg, val8);
1833 }
1834
rtl8723b_GetHalODMVar(struct adapter * Adapter,enum hal_odm_variable eVariable,void * pValue1,void * pValue2)1835 static void rtl8723b_GetHalODMVar(
1836 struct adapter *Adapter,
1837 enum hal_odm_variable eVariable,
1838 void *pValue1,
1839 void *pValue2
1840 )
1841 {
1842 GetHalODMVar(Adapter, eVariable, pValue1, pValue2);
1843 }
1844
rtl8723b_SetHalODMVar(struct adapter * Adapter,enum hal_odm_variable eVariable,void * pValue1,bool bSet)1845 static void rtl8723b_SetHalODMVar(
1846 struct adapter *Adapter,
1847 enum hal_odm_variable eVariable,
1848 void *pValue1,
1849 bool bSet
1850 )
1851 {
1852 SetHalODMVar(Adapter, eVariable, pValue1, bSet);
1853 }
1854
hal_notch_filter_8723b(struct adapter * adapter,bool enable)1855 static void hal_notch_filter_8723b(struct adapter *adapter, bool enable)
1856 {
1857 if (enable)
1858 rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) | BIT1);
1859 else
1860 rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
1861 }
1862
UpdateHalRAMask8723B(struct adapter * padapter,u32 mac_id,u8 rssi_level)1863 static void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level)
1864 {
1865 u32 mask, rate_bitmap;
1866 u8 shortGIrate = false;
1867 struct sta_info *psta;
1868 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1869 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1870 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1871 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1872
1873 if (mac_id >= NUM_STA) /* CAM_SIZE */
1874 return;
1875
1876 psta = pmlmeinfo->FW_sta_info[mac_id].psta;
1877 if (!psta)
1878 return;
1879
1880 shortGIrate = query_ra_short_GI(psta);
1881
1882 mask = psta->ra_mask;
1883
1884 rate_bitmap = 0xffffffff;
1885 rate_bitmap = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, mac_id, mask, rssi_level);
1886
1887 mask &= rate_bitmap;
1888
1889 rate_bitmap = hal_btcoex_GetRaMask(padapter);
1890 mask &= ~rate_bitmap;
1891
1892 if (pHalData->fw_ractrl) {
1893 rtl8723b_set_FwMacIdConfig_cmd(padapter, mac_id, psta->raid, psta->bw_mode, shortGIrate, mask);
1894 }
1895
1896 /* set correct initial date rate for each mac_id */
1897 pdmpriv->INIDATA_RATE[mac_id] = psta->init_rate;
1898 }
1899
1900
rtl8723b_set_hal_ops(struct hal_ops * pHalFunc)1901 void rtl8723b_set_hal_ops(struct hal_ops *pHalFunc)
1902 {
1903 pHalFunc->free_hal_data = &rtl8723b_free_hal_data;
1904
1905 pHalFunc->dm_init = &rtl8723b_init_dm_priv;
1906
1907 pHalFunc->read_chip_version = &rtl8723b_read_chip_version;
1908
1909 pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8723B;
1910
1911 pHalFunc->set_bwmode_handler = &PHY_SetBWMode8723B;
1912 pHalFunc->set_channel_handler = &PHY_SwChnl8723B;
1913 pHalFunc->set_chnl_bw_handler = &PHY_SetSwChnlBWMode8723B;
1914
1915 pHalFunc->set_tx_power_level_handler = &PHY_SetTxPowerLevel8723B;
1916 pHalFunc->get_tx_power_level_handler = &PHY_GetTxPowerLevel8723B;
1917
1918 pHalFunc->hal_dm_watchdog = &rtl8723b_HalDmWatchDog;
1919 pHalFunc->hal_dm_watchdog_in_lps = &rtl8723b_HalDmWatchDog_in_LPS;
1920
1921
1922 pHalFunc->SetBeaconRelatedRegistersHandler = &rtl8723b_SetBeaconRelatedRegisters;
1923
1924 pHalFunc->Add_RateATid = &rtl8723b_Add_RateATid;
1925
1926 pHalFunc->run_thread = &rtl8723b_start_thread;
1927 pHalFunc->cancel_thread = &rtl8723b_stop_thread;
1928
1929 pHalFunc->read_bbreg = &PHY_QueryBBReg_8723B;
1930 pHalFunc->write_bbreg = &PHY_SetBBReg_8723B;
1931 pHalFunc->read_rfreg = &PHY_QueryRFReg_8723B;
1932 pHalFunc->write_rfreg = &PHY_SetRFReg_8723B;
1933
1934 /* Efuse related function */
1935 pHalFunc->BTEfusePowerSwitch = &Hal_BT_EfusePowerSwitch;
1936 pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch;
1937 pHalFunc->ReadEFuse = &Hal_ReadEFuse;
1938 pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition;
1939 pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize;
1940 pHalFunc->Efuse_PgPacketRead = &Hal_EfusePgPacketRead;
1941 pHalFunc->Efuse_PgPacketWrite = &Hal_EfusePgPacketWrite;
1942 pHalFunc->Efuse_WordEnableDataWrite = &Hal_EfuseWordEnableDataWrite;
1943 pHalFunc->Efuse_PgPacketWrite_BT = &Hal_EfusePgPacketWrite_BT;
1944
1945 pHalFunc->GetHalODMVarHandler = &rtl8723b_GetHalODMVar;
1946 pHalFunc->SetHalODMVarHandler = &rtl8723b_SetHalODMVar;
1947
1948 pHalFunc->xmit_thread_handler = &hal_xmit_handler;
1949 pHalFunc->hal_notch_filter = &hal_notch_filter_8723b;
1950
1951 pHalFunc->c2h_handler = c2h_handler_8723b;
1952 pHalFunc->c2h_id_filter_ccx = c2h_id_filter_ccx_8723b;
1953
1954 pHalFunc->fill_h2c_cmd = &FillH2CCmd8723B;
1955 }
1956
rtl8723b_InitAntenna_Selection(struct adapter * padapter)1957 void rtl8723b_InitAntenna_Selection(struct adapter *padapter)
1958 {
1959 u8 val;
1960
1961 val = rtw_read8(padapter, REG_LEDCFG2);
1962 /* Let 8051 take control antenna setting */
1963 val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
1964 rtw_write8(padapter, REG_LEDCFG2, val);
1965 }
1966
rtl8723b_init_default_value(struct adapter * padapter)1967 void rtl8723b_init_default_value(struct adapter *padapter)
1968 {
1969 struct hal_com_data *pHalData;
1970 struct dm_priv *pdmpriv;
1971 u8 i;
1972
1973
1974 pHalData = GET_HAL_DATA(padapter);
1975 pdmpriv = &pHalData->dmpriv;
1976
1977 padapter->registrypriv.wireless_mode = WIRELESS_11BG_24N;
1978
1979 /* init default value */
1980 pHalData->fw_ractrl = false;
1981 pHalData->bIQKInitialized = false;
1982 if (!adapter_to_pwrctl(padapter)->bkeepfwalive)
1983 pHalData->LastHMEBoxNum = 0;
1984
1985 pHalData->bIQKInitialized = false;
1986
1987 /* init dm default value */
1988 pdmpriv->TM_Trigger = 0;/* for IQK */
1989 /* pdmpriv->binitialized = false; */
1990 /* pdmpriv->prv_traffic_idx = 3; */
1991 /* pdmpriv->initialize = 0; */
1992
1993 pdmpriv->ThermalValue_HP_index = 0;
1994 for (i = 0; i < HP_THERMAL_NUM; i++)
1995 pdmpriv->ThermalValue_HP[i] = 0;
1996
1997 /* init Efuse variables */
1998 pHalData->EfuseUsedBytes = 0;
1999 pHalData->EfuseUsedPercentage = 0;
2000 #ifdef HAL_EFUSE_MEMORY
2001 pHalData->EfuseHal.fakeEfuseBank = 0;
2002 pHalData->EfuseHal.fakeEfuseUsedBytes = 0;
2003 memset(pHalData->EfuseHal.fakeEfuseContent, 0xFF, EFUSE_MAX_HW_SIZE);
2004 memset(pHalData->EfuseHal.fakeEfuseInitMap, 0xFF, EFUSE_MAX_MAP_LEN);
2005 memset(pHalData->EfuseHal.fakeEfuseModifiedMap, 0xFF, EFUSE_MAX_MAP_LEN);
2006 pHalData->EfuseHal.BTEfuseUsedBytes = 0;
2007 pHalData->EfuseHal.BTEfuseUsedPercentage = 0;
2008 memset(pHalData->EfuseHal.BTEfuseContent, 0xFF, EFUSE_MAX_BT_BANK*EFUSE_MAX_HW_SIZE);
2009 memset(pHalData->EfuseHal.BTEfuseInitMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
2010 memset(pHalData->EfuseHal.BTEfuseModifiedMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
2011 pHalData->EfuseHal.fakeBTEfuseUsedBytes = 0;
2012 memset(pHalData->EfuseHal.fakeBTEfuseContent, 0xFF, EFUSE_MAX_BT_BANK*EFUSE_MAX_HW_SIZE);
2013 memset(pHalData->EfuseHal.fakeBTEfuseInitMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
2014 memset(pHalData->EfuseHal.fakeBTEfuseModifiedMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
2015 #endif
2016 }
2017
GetEEPROMSize8723B(struct adapter * padapter)2018 u8 GetEEPROMSize8723B(struct adapter *padapter)
2019 {
2020 u8 size = 0;
2021 u32 cr;
2022
2023 cr = rtw_read16(padapter, REG_9346CR);
2024 /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */
2025 size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
2026
2027 return size;
2028 }
2029
2030 /* */
2031 /* */
2032 /* LLT R/W/Init function */
2033 /* */
2034 /* */
rtl8723b_InitLLTTable(struct adapter * padapter)2035 s32 rtl8723b_InitLLTTable(struct adapter *padapter)
2036 {
2037 unsigned long start, passing_time;
2038 u32 val32;
2039 s32 ret;
2040
2041
2042 ret = _FAIL;
2043
2044 val32 = rtw_read32(padapter, REG_AUTO_LLT);
2045 val32 |= BIT_AUTO_INIT_LLT;
2046 rtw_write32(padapter, REG_AUTO_LLT, val32);
2047
2048 start = jiffies;
2049
2050 do {
2051 val32 = rtw_read32(padapter, REG_AUTO_LLT);
2052 if (!(val32 & BIT_AUTO_INIT_LLT)) {
2053 ret = _SUCCESS;
2054 break;
2055 }
2056
2057 passing_time = jiffies_to_msecs(jiffies - start);
2058 if (passing_time > 1000)
2059 break;
2060
2061 msleep(1);
2062 } while (1);
2063
2064 return ret;
2065 }
2066
Hal_GetChnlGroup8723B(u8 Channel,u8 * pGroup)2067 static bool Hal_GetChnlGroup8723B(u8 Channel, u8 *pGroup)
2068 {
2069 bool bIn24G = true;
2070
2071 if (Channel <= 14) {
2072 bIn24G = true;
2073
2074 if (1 <= Channel && Channel <= 2)
2075 *pGroup = 0;
2076 else if (3 <= Channel && Channel <= 5)
2077 *pGroup = 1;
2078 else if (6 <= Channel && Channel <= 8)
2079 *pGroup = 2;
2080 else if (9 <= Channel && Channel <= 11)
2081 *pGroup = 3;
2082 else if (12 <= Channel && Channel <= 14)
2083 *pGroup = 4;
2084 } else {
2085 bIn24G = false;
2086
2087 if (36 <= Channel && Channel <= 42)
2088 *pGroup = 0;
2089 else if (44 <= Channel && Channel <= 48)
2090 *pGroup = 1;
2091 else if (50 <= Channel && Channel <= 58)
2092 *pGroup = 2;
2093 else if (60 <= Channel && Channel <= 64)
2094 *pGroup = 3;
2095 else if (100 <= Channel && Channel <= 106)
2096 *pGroup = 4;
2097 else if (108 <= Channel && Channel <= 114)
2098 *pGroup = 5;
2099 else if (116 <= Channel && Channel <= 122)
2100 *pGroup = 6;
2101 else if (124 <= Channel && Channel <= 130)
2102 *pGroup = 7;
2103 else if (132 <= Channel && Channel <= 138)
2104 *pGroup = 8;
2105 else if (140 <= Channel && Channel <= 144)
2106 *pGroup = 9;
2107 else if (149 <= Channel && Channel <= 155)
2108 *pGroup = 10;
2109 else if (157 <= Channel && Channel <= 161)
2110 *pGroup = 11;
2111 else if (165 <= Channel && Channel <= 171)
2112 *pGroup = 12;
2113 else if (173 <= Channel && Channel <= 177)
2114 *pGroup = 13;
2115 }
2116 return bIn24G;
2117 }
2118
Hal_InitPGData(struct adapter * padapter,u8 * PROMContent)2119 void Hal_InitPGData(struct adapter *padapter, u8 *PROMContent)
2120 {
2121 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2122
2123 if (!pEEPROM->bautoload_fail_flag) { /* autoload OK. */
2124 if (!pEEPROM->EepromOrEfuse) {
2125 /* Read EFUSE real map to shadow. */
2126 EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
2127 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data, HWSET_MAX_SIZE_8723B);
2128 }
2129 } else {/* autoload fail */
2130 if (!pEEPROM->EepromOrEfuse)
2131 EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
2132 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data, HWSET_MAX_SIZE_8723B);
2133 }
2134 }
2135
Hal_EfuseParseIDCode(struct adapter * padapter,u8 * hwinfo)2136 void Hal_EfuseParseIDCode(struct adapter *padapter, u8 *hwinfo)
2137 {
2138 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2139 /* struct hal_com_data *pHalData = GET_HAL_DATA(padapter); */
2140 u16 EEPROMId;
2141
2142
2143 /* Checl 0x8129 again for making sure autoload status!! */
2144 EEPROMId = le16_to_cpu(*((__le16 *)hwinfo));
2145 if (EEPROMId != RTL_EEPROM_ID) {
2146 pEEPROM->bautoload_fail_flag = true;
2147 } else
2148 pEEPROM->bautoload_fail_flag = false;
2149 }
2150
Hal_ReadPowerValueFromPROM_8723B(struct adapter * Adapter,struct TxPowerInfo24G * pwrInfo24G,u8 * PROMContent,bool AutoLoadFail)2151 static void Hal_ReadPowerValueFromPROM_8723B(
2152 struct adapter *Adapter,
2153 struct TxPowerInfo24G *pwrInfo24G,
2154 u8 *PROMContent,
2155 bool AutoLoadFail
2156 )
2157 {
2158 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
2159 u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_8723B, group, TxCount = 0;
2160
2161 memset(pwrInfo24G, 0, sizeof(struct TxPowerInfo24G));
2162
2163 if (0xFF == PROMContent[eeAddr+1])
2164 AutoLoadFail = true;
2165
2166 if (AutoLoadFail) {
2167 for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
2168 /* 2.4G default value */
2169 for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
2170 pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
2171 pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
2172 }
2173
2174 for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
2175 if (TxCount == 0) {
2176 pwrInfo24G->BW20_Diff[rfPath][0] = EEPROM_DEFAULT_24G_HT20_DIFF;
2177 pwrInfo24G->OFDM_Diff[rfPath][0] = EEPROM_DEFAULT_24G_OFDM_DIFF;
2178 } else {
2179 pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2180 pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2181 pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2182 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2183 }
2184 }
2185 }
2186
2187 return;
2188 }
2189
2190 pHalData->bTXPowerDataReadFromEEPORM = true; /* YJ, move, 120316 */
2191
2192 for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
2193 /* 2 2.4G default value */
2194 for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
2195 pwrInfo24G->IndexCCK_Base[rfPath][group] = PROMContent[eeAddr++];
2196 if (pwrInfo24G->IndexCCK_Base[rfPath][group] == 0xFF)
2197 pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
2198 }
2199
2200 for (group = 0; group < MAX_CHNL_GROUP_24G-1; group++) {
2201 pwrInfo24G->IndexBW40_Base[rfPath][group] = PROMContent[eeAddr++];
2202 if (pwrInfo24G->IndexBW40_Base[rfPath][group] == 0xFF)
2203 pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
2204 }
2205
2206 for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
2207 if (TxCount == 0) {
2208 pwrInfo24G->BW40_Diff[rfPath][TxCount] = 0;
2209 if (PROMContent[eeAddr] == 0xFF)
2210 pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
2211 else {
2212 pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
2213 if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2214 pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
2215 }
2216
2217 if (PROMContent[eeAddr] == 0xFF)
2218 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_OFDM_DIFF;
2219 else {
2220 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
2221 if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2222 pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
2223 }
2224 pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
2225 eeAddr++;
2226 } else {
2227 if (PROMContent[eeAddr] == 0xFF)
2228 pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2229 else {
2230 pwrInfo24G->BW40_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
2231 if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2232 pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
2233 }
2234
2235 if (PROMContent[eeAddr] == 0xFF)
2236 pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2237 else {
2238 pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
2239 if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2240 pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
2241 }
2242 eeAddr++;
2243
2244 if (PROMContent[eeAddr] == 0xFF)
2245 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2246 else {
2247 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
2248 if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2249 pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
2250 }
2251
2252 if (PROMContent[eeAddr] == 0xFF)
2253 pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2254 else {
2255 pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
2256 if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2257 pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
2258 }
2259 eeAddr++;
2260 }
2261 }
2262 }
2263 }
2264
2265
Hal_EfuseParseTxPowerInfo_8723B(struct adapter * padapter,u8 * PROMContent,bool AutoLoadFail)2266 void Hal_EfuseParseTxPowerInfo_8723B(
2267 struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail
2268 )
2269 {
2270 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2271 struct TxPowerInfo24G pwrInfo24G;
2272 u8 rfPath, ch, TxCount = 1;
2273
2274 Hal_ReadPowerValueFromPROM_8723B(padapter, &pwrInfo24G, PROMContent, AutoLoadFail);
2275 for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) {
2276 for (ch = 0 ; ch < CHANNEL_MAX_NUMBER; ch++) {
2277 u8 group = 0;
2278
2279 Hal_GetChnlGroup8723B(ch+1, &group);
2280
2281 if (ch == 14-1) {
2282 pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][5];
2283 pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
2284 } else {
2285 pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][group];
2286 pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
2287 }
2288 }
2289
2290 for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
2291 pHalData->CCK_24G_Diff[rfPath][TxCount] = pwrInfo24G.CCK_Diff[rfPath][TxCount];
2292 pHalData->OFDM_24G_Diff[rfPath][TxCount] = pwrInfo24G.OFDM_Diff[rfPath][TxCount];
2293 pHalData->BW20_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW20_Diff[rfPath][TxCount];
2294 pHalData->BW40_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW40_Diff[rfPath][TxCount];
2295 }
2296 }
2297
2298 /* 2010/10/19 MH Add Regulator recognize for CU. */
2299 if (!AutoLoadFail) {
2300 pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_8723B]&0x7); /* bit0~2 */
2301 if (PROMContent[EEPROM_RF_BOARD_OPTION_8723B] == 0xFF)
2302 pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION&0x7); /* bit0~2 */
2303 } else
2304 pHalData->EEPROMRegulatory = 0;
2305 }
2306
Hal_EfuseParseBTCoexistInfo_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)2307 void Hal_EfuseParseBTCoexistInfo_8723B(
2308 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2309 )
2310 {
2311 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2312 u8 tempval;
2313 u32 tmpu4;
2314
2315 if (!AutoLoadFail) {
2316 tmpu4 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
2317 if (tmpu4 & BT_FUNC_EN)
2318 pHalData->EEPROMBluetoothCoexist = true;
2319 else
2320 pHalData->EEPROMBluetoothCoexist = false;
2321
2322 pHalData->EEPROMBluetoothType = BT_RTL8723B;
2323
2324 tempval = hwinfo[EEPROM_RF_BT_SETTING_8723B];
2325 if (tempval != 0xFF) {
2326 pHalData->EEPROMBluetoothAntNum = tempval & BIT(0);
2327 /* EFUSE_0xC3[6] == 0, S1(Main)-ODM_RF_PATH_A; */
2328 /* EFUSE_0xC3[6] == 1, S0(Aux)-ODM_RF_PATH_B */
2329 pHalData->ant_path = (tempval & BIT(6))?ODM_RF_PATH_B:ODM_RF_PATH_A;
2330 } else {
2331 pHalData->EEPROMBluetoothAntNum = Ant_x1;
2332 if (pHalData->PackageType == PACKAGE_QFN68)
2333 pHalData->ant_path = ODM_RF_PATH_B;
2334 else
2335 pHalData->ant_path = ODM_RF_PATH_A;
2336 }
2337 } else {
2338 pHalData->EEPROMBluetoothCoexist = false;
2339 pHalData->EEPROMBluetoothType = BT_RTL8723B;
2340 pHalData->EEPROMBluetoothAntNum = Ant_x1;
2341 pHalData->ant_path = ODM_RF_PATH_A;
2342 }
2343
2344 if (padapter->registrypriv.ant_num > 0) {
2345 switch (padapter->registrypriv.ant_num) {
2346 case 1:
2347 pHalData->EEPROMBluetoothAntNum = Ant_x1;
2348 break;
2349 case 2:
2350 pHalData->EEPROMBluetoothAntNum = Ant_x2;
2351 break;
2352 default:
2353 break;
2354 }
2355 }
2356
2357 hal_btcoex_SetBTCoexist(padapter, pHalData->EEPROMBluetoothCoexist);
2358 hal_btcoex_SetChipType(padapter, pHalData->EEPROMBluetoothType);
2359 hal_btcoex_SetPgAntNum(padapter, pHalData->EEPROMBluetoothAntNum == Ant_x2 ? 2 : 1);
2360 if (pHalData->EEPROMBluetoothAntNum == Ant_x1)
2361 hal_btcoex_SetSingleAntPath(padapter, pHalData->ant_path);
2362 }
2363
Hal_EfuseParseEEPROMVer_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)2364 void Hal_EfuseParseEEPROMVer_8723B(
2365 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2366 )
2367 {
2368 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2369
2370 if (!AutoLoadFail)
2371 pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723B];
2372 else
2373 pHalData->EEPROMVersion = 1;
2374 }
2375
2376
2377
Hal_EfuseParsePackageType_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)2378 void Hal_EfuseParsePackageType_8723B(
2379 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2380 )
2381 {
2382 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2383 u8 package;
2384 u8 efuseContent;
2385
2386 Efuse_PowerSwitch(padapter, false, true);
2387 efuse_OneByteRead(padapter, 0x1FB, &efuseContent, false);
2388 Efuse_PowerSwitch(padapter, false, false);
2389
2390 package = efuseContent & 0x7;
2391 switch (package) {
2392 case 0x4:
2393 pHalData->PackageType = PACKAGE_TFBGA79;
2394 break;
2395 case 0x5:
2396 pHalData->PackageType = PACKAGE_TFBGA90;
2397 break;
2398 case 0x6:
2399 pHalData->PackageType = PACKAGE_QFN68;
2400 break;
2401 case 0x7:
2402 pHalData->PackageType = PACKAGE_TFBGA80;
2403 break;
2404
2405 default:
2406 pHalData->PackageType = PACKAGE_DEFAULT;
2407 break;
2408 }
2409 }
2410
2411
Hal_EfuseParseVoltage_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)2412 void Hal_EfuseParseVoltage_8723B(
2413 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2414 )
2415 {
2416 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2417
2418 /* memcpy(pEEPROM->adjuseVoltageVal, &hwinfo[EEPROM_Voltage_ADDR_8723B], 1); */
2419 pEEPROM->adjuseVoltageVal = (hwinfo[EEPROM_Voltage_ADDR_8723B] & 0xf0) >> 4;
2420 }
2421
Hal_EfuseParseChnlPlan_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)2422 void Hal_EfuseParseChnlPlan_8723B(
2423 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2424 )
2425 {
2426 padapter->mlmepriv.ChannelPlan = hal_com_config_channel_plan(
2427 padapter,
2428 hwinfo ? hwinfo[EEPROM_ChannelPlan_8723B] : 0xFF,
2429 padapter->registrypriv.channel_plan,
2430 RT_CHANNEL_DOMAIN_WORLD_NULL,
2431 AutoLoadFail
2432 );
2433
2434 Hal_ChannelPlanToRegulation(padapter, padapter->mlmepriv.ChannelPlan);
2435 }
2436
Hal_EfuseParseCustomerID_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)2437 void Hal_EfuseParseCustomerID_8723B(
2438 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2439 )
2440 {
2441 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2442
2443 if (!AutoLoadFail)
2444 pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723B];
2445 else
2446 pHalData->EEPROMCustomerID = 0;
2447 }
2448
Hal_EfuseParseAntennaDiversity_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)2449 void Hal_EfuseParseAntennaDiversity_8723B(
2450 struct adapter *padapter,
2451 u8 *hwinfo,
2452 bool AutoLoadFail
2453 )
2454 {
2455 }
2456
Hal_EfuseParseXtal_8723B(struct adapter * padapter,u8 * hwinfo,bool AutoLoadFail)2457 void Hal_EfuseParseXtal_8723B(
2458 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2459 )
2460 {
2461 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2462
2463 if (!AutoLoadFail) {
2464 pHalData->CrystalCap = hwinfo[EEPROM_XTAL_8723B];
2465 if (pHalData->CrystalCap == 0xFF)
2466 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B; /* what value should 8812 set? */
2467 } else
2468 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B;
2469 }
2470
2471
Hal_EfuseParseThermalMeter_8723B(struct adapter * padapter,u8 * PROMContent,u8 AutoLoadFail)2472 void Hal_EfuseParseThermalMeter_8723B(
2473 struct adapter *padapter, u8 *PROMContent, u8 AutoLoadFail
2474 )
2475 {
2476 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2477
2478 /* */
2479 /* ThermalMeter from EEPROM */
2480 /* */
2481 if (!AutoLoadFail)
2482 pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_8723B];
2483 else
2484 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B;
2485
2486 if ((pHalData->EEPROMThermalMeter == 0xff) || AutoLoadFail) {
2487 pHalData->bAPKThermalMeterIgnore = true;
2488 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B;
2489 }
2490 }
2491
2492
Hal_ReadRFGainOffset(struct adapter * Adapter,u8 * PROMContent,bool AutoloadFail)2493 void Hal_ReadRFGainOffset(
2494 struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail
2495 )
2496 {
2497 /* */
2498 /* BB_RF Gain Offset from EEPROM */
2499 /* */
2500
2501 if (!AutoloadFail) {
2502 Adapter->eeprompriv.EEPROMRFGainOffset = PROMContent[EEPROM_RF_GAIN_OFFSET];
2503 Adapter->eeprompriv.EEPROMRFGainVal = EFUSE_Read1Byte(Adapter, EEPROM_RF_GAIN_VAL);
2504 } else {
2505 Adapter->eeprompriv.EEPROMRFGainOffset = 0;
2506 Adapter->eeprompriv.EEPROMRFGainVal = 0xFF;
2507 }
2508 }
2509
BWMapping_8723B(struct adapter * Adapter,struct pkt_attrib * pattrib)2510 u8 BWMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib)
2511 {
2512 u8 BWSettingOfDesc = 0;
2513 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
2514
2515 if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_80) {
2516 if (pattrib->bwmode == CHANNEL_WIDTH_80)
2517 BWSettingOfDesc = 2;
2518 else if (pattrib->bwmode == CHANNEL_WIDTH_40)
2519 BWSettingOfDesc = 1;
2520 else
2521 BWSettingOfDesc = 0;
2522 } else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
2523 if ((pattrib->bwmode == CHANNEL_WIDTH_40) || (pattrib->bwmode == CHANNEL_WIDTH_80))
2524 BWSettingOfDesc = 1;
2525 else
2526 BWSettingOfDesc = 0;
2527 } else
2528 BWSettingOfDesc = 0;
2529
2530 /* if (pTcb->bBTTxPacket) */
2531 /* BWSettingOfDesc = 0; */
2532
2533 return BWSettingOfDesc;
2534 }
2535
SCMapping_8723B(struct adapter * Adapter,struct pkt_attrib * pattrib)2536 u8 SCMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib)
2537 {
2538 u8 SCSettingOfDesc = 0;
2539 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
2540
2541 if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_80) {
2542 if (pattrib->bwmode == CHANNEL_WIDTH_80) {
2543 SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;
2544 } else if (pattrib->bwmode == CHANNEL_WIDTH_40) {
2545 if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)
2546 SCSettingOfDesc = VHT_DATA_SC_40_LOWER_OF_80MHZ;
2547 else if (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)
2548 SCSettingOfDesc = VHT_DATA_SC_40_UPPER_OF_80MHZ;
2549 } else {
2550 if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER))
2551 SCSettingOfDesc = VHT_DATA_SC_20_LOWEST_OF_80MHZ;
2552 else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER))
2553 SCSettingOfDesc = VHT_DATA_SC_20_LOWER_OF_80MHZ;
2554 else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER))
2555 SCSettingOfDesc = VHT_DATA_SC_20_UPPER_OF_80MHZ;
2556 else if ((pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) && (pHalData->nCur80MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER))
2557 SCSettingOfDesc = VHT_DATA_SC_20_UPPERST_OF_80MHZ;
2558 }
2559 } else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
2560 if (pattrib->bwmode == CHANNEL_WIDTH_40) {
2561 SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;
2562 } else if (pattrib->bwmode == CHANNEL_WIDTH_20) {
2563 if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) {
2564 SCSettingOfDesc = VHT_DATA_SC_20_UPPER_OF_80MHZ;
2565 } else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) {
2566 SCSettingOfDesc = VHT_DATA_SC_20_LOWER_OF_80MHZ;
2567 } else {
2568 SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;
2569 }
2570 }
2571 } else {
2572 SCSettingOfDesc = VHT_DATA_SC_DONOT_CARE;
2573 }
2574
2575 return SCSettingOfDesc;
2576 }
2577
rtl8723b_cal_txdesc_chksum(struct tx_desc * ptxdesc)2578 static void rtl8723b_cal_txdesc_chksum(struct tx_desc *ptxdesc)
2579 {
2580 u16 *usPtr = (u16 *)ptxdesc;
2581 u32 count;
2582 u32 index;
2583 u16 checksum = 0;
2584
2585
2586 /* Clear first */
2587 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
2588
2589 /* checksume is always calculated by first 32 bytes, */
2590 /* and it doesn't depend on TX DESC length. */
2591 /* Thomas, Lucas@SD4, 20130515 */
2592 count = 16;
2593
2594 for (index = 0; index < count; index++) {
2595 checksum |= le16_to_cpu(*(__le16 *)(usPtr + index));
2596 }
2597
2598 ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
2599 }
2600
fill_txdesc_sectype(struct pkt_attrib * pattrib)2601 static u8 fill_txdesc_sectype(struct pkt_attrib *pattrib)
2602 {
2603 u8 sectype = 0;
2604 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
2605 switch (pattrib->encrypt) {
2606 /* SEC_TYPE */
2607 case _WEP40_:
2608 case _WEP104_:
2609 case _TKIP_:
2610 case _TKIP_WTMIC_:
2611 sectype = 1;
2612 break;
2613
2614 case _AES_:
2615 sectype = 3;
2616 break;
2617
2618 case _NO_PRIVACY_:
2619 default:
2620 break;
2621 }
2622 }
2623 return sectype;
2624 }
2625
fill_txdesc_vcs_8723b(struct adapter * padapter,struct pkt_attrib * pattrib,struct txdesc_8723b * ptxdesc)2626 static void fill_txdesc_vcs_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc)
2627 {
2628 if (pattrib->vcs_mode) {
2629 switch (pattrib->vcs_mode) {
2630 case RTS_CTS:
2631 ptxdesc->rtsen = 1;
2632 /* ENABLE HW RTS */
2633 ptxdesc->hw_rts_en = 1;
2634 break;
2635
2636 case CTS_TO_SELF:
2637 ptxdesc->cts2self = 1;
2638 break;
2639
2640 case NONE_VCS:
2641 default:
2642 break;
2643 }
2644
2645 ptxdesc->rtsrate = 8; /* RTS Rate =24M */
2646 ptxdesc->rts_ratefb_lmt = 0xF;
2647
2648 if (padapter->mlmeextpriv.mlmext_info.preamble_mode == PREAMBLE_SHORT)
2649 ptxdesc->rts_short = 1;
2650
2651 /* Set RTS BW */
2652 if (pattrib->ht_en)
2653 ptxdesc->rts_sc = SCMapping_8723B(padapter, pattrib);
2654 }
2655 }
2656
fill_txdesc_phy_8723b(struct adapter * padapter,struct pkt_attrib * pattrib,struct txdesc_8723b * ptxdesc)2657 static void fill_txdesc_phy_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc)
2658 {
2659 if (pattrib->ht_en) {
2660 ptxdesc->data_bw = BWMapping_8723B(padapter, pattrib);
2661
2662 ptxdesc->data_sc = SCMapping_8723B(padapter, pattrib);
2663 }
2664 }
2665
rtl8723b_fill_default_txdesc(struct xmit_frame * pxmitframe,u8 * pbuf)2666 static void rtl8723b_fill_default_txdesc(
2667 struct xmit_frame *pxmitframe, u8 *pbuf
2668 )
2669 {
2670 struct adapter *padapter;
2671 struct hal_com_data *pHalData;
2672 struct mlme_ext_priv *pmlmeext;
2673 struct mlme_ext_info *pmlmeinfo;
2674 struct pkt_attrib *pattrib;
2675 struct txdesc_8723b *ptxdesc;
2676 s32 bmcst;
2677
2678 memset(pbuf, 0, TXDESC_SIZE);
2679
2680 padapter = pxmitframe->padapter;
2681 pHalData = GET_HAL_DATA(padapter);
2682 pmlmeext = &padapter->mlmeextpriv;
2683 pmlmeinfo = &(pmlmeext->mlmext_info);
2684
2685 pattrib = &pxmitframe->attrib;
2686 bmcst = IS_MCAST(pattrib->ra);
2687
2688 ptxdesc = (struct txdesc_8723b *)pbuf;
2689
2690 if (pxmitframe->frame_tag == DATA_FRAMETAG) {
2691 u8 drv_userate = 0;
2692
2693 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2694 ptxdesc->rate_id = pattrib->raid;
2695 ptxdesc->qsel = pattrib->qsel;
2696 ptxdesc->seq = pattrib->seqnum;
2697
2698 ptxdesc->sectype = fill_txdesc_sectype(pattrib);
2699 fill_txdesc_vcs_8723b(padapter, pattrib, ptxdesc);
2700
2701 if (pattrib->icmp_pkt == 1 && padapter->registrypriv.wifi_spec == 1)
2702 drv_userate = 1;
2703
2704 if (
2705 (pattrib->ether_type != 0x888e) &&
2706 (pattrib->ether_type != 0x0806) &&
2707 (pattrib->ether_type != 0x88B4) &&
2708 (pattrib->dhcp_pkt != 1) &&
2709 (drv_userate != 1)
2710 ) {
2711 /* Non EAP & ARP & DHCP type data packet */
2712
2713 if (pattrib->ampdu_en) {
2714 ptxdesc->agg_en = 1; /* AGG EN */
2715 ptxdesc->max_agg_num = 0x1f;
2716 ptxdesc->ampdu_density = pattrib->ampdu_spacing;
2717 } else
2718 ptxdesc->bk = 1; /* AGG BK */
2719
2720 fill_txdesc_phy_8723b(padapter, pattrib, ptxdesc);
2721
2722 ptxdesc->data_ratefb_lmt = 0x1F;
2723
2724 if (!pHalData->fw_ractrl) {
2725 ptxdesc->userate = 1;
2726
2727 if (pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & BIT(7))
2728 ptxdesc->data_short = 1;
2729
2730 ptxdesc->datarate = pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & 0x7F;
2731 }
2732
2733 if (padapter->fix_rate != 0xFF) { /* modify data rate by iwpriv */
2734 ptxdesc->userate = 1;
2735 if (padapter->fix_rate & BIT(7))
2736 ptxdesc->data_short = 1;
2737
2738 ptxdesc->datarate = (padapter->fix_rate & 0x7F);
2739 ptxdesc->disdatafb = 1;
2740 }
2741
2742 if (pattrib->ldpc)
2743 ptxdesc->data_ldpc = 1;
2744 if (pattrib->stbc)
2745 ptxdesc->data_stbc = 1;
2746 } else {
2747 /* EAP data packet and ARP packet. */
2748 /* Use the 1M data rate to send the EAP/ARP packet. */
2749 /* This will maybe make the handshake smooth. */
2750
2751 ptxdesc->bk = 1; /* AGG BK */
2752 ptxdesc->userate = 1; /* driver uses rate */
2753 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
2754 ptxdesc->data_short = 1;/* DATA_SHORT */
2755 ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate);
2756 }
2757
2758 ptxdesc->usb_txagg_num = pxmitframe->agg_num;
2759 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
2760 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2761 ptxdesc->qsel = pattrib->qsel;
2762 ptxdesc->rate_id = pattrib->raid; /* Rate ID */
2763 ptxdesc->seq = pattrib->seqnum;
2764 ptxdesc->userate = 1; /* driver uses rate, 1M */
2765
2766 ptxdesc->mbssid = pattrib->mbssid & 0xF;
2767
2768 ptxdesc->rty_lmt_en = 1; /* retry limit enable */
2769 if (pattrib->retry_ctrl) {
2770 ptxdesc->data_rt_lmt = 6;
2771 } else {
2772 ptxdesc->data_rt_lmt = 12;
2773 }
2774
2775 ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate);
2776
2777 /* CCX-TXRPT ack for xmit mgmt frames. */
2778 if (pxmitframe->ack_report) {
2779 ptxdesc->spe_rpt = 1;
2780 ptxdesc->sw_define = (u8)(GET_PRIMARY_ADAPTER(padapter)->xmitpriv.seq_no);
2781 }
2782 } else {
2783 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2784 ptxdesc->rate_id = pattrib->raid; /* Rate ID */
2785 ptxdesc->qsel = pattrib->qsel;
2786 ptxdesc->seq = pattrib->seqnum;
2787 ptxdesc->userate = 1; /* driver uses rate */
2788 ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate);
2789 }
2790
2791 ptxdesc->pktlen = pattrib->last_txcmdsz;
2792 ptxdesc->offset = TXDESC_SIZE + OFFSET_SZ;
2793
2794 if (bmcst)
2795 ptxdesc->bmc = 1;
2796
2797 /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS.
2798 * (1) The sequence number of each non-Qos frame / broadcast /
2799 * multicast / mgnt frame should be controlled by Hw because Fw
2800 * will also send null data which we cannot control when Fw LPS
2801 * enable.
2802 * --> default enable non-Qos data sequense number. 2010.06.23.
2803 * by tynli.
2804 * (2) Enable HW SEQ control for beacon packet, because we use
2805 * Hw beacon.
2806 * (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos
2807 * packets.
2808 * 2010.06.23. Added by tynli.
2809 */
2810 if (!pattrib->qos_en) /* Hw set sequence number */
2811 ptxdesc->en_hwseq = 1; /* HWSEQ_EN */
2812 }
2813
2814 /* Description:
2815 *
2816 * Parameters:
2817 * pxmitframe xmitframe
2818 * pbuf where to fill tx desc
2819 */
rtl8723b_update_txdesc(struct xmit_frame * pxmitframe,u8 * pbuf)2820 void rtl8723b_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf)
2821 {
2822 struct tx_desc *pdesc;
2823
2824 rtl8723b_fill_default_txdesc(pxmitframe, pbuf);
2825
2826 pdesc = (struct tx_desc *)pbuf;
2827 pdesc->txdw0 = pdesc->txdw0;
2828 pdesc->txdw1 = pdesc->txdw1;
2829 pdesc->txdw2 = pdesc->txdw2;
2830 pdesc->txdw3 = pdesc->txdw3;
2831 pdesc->txdw4 = pdesc->txdw4;
2832 pdesc->txdw5 = pdesc->txdw5;
2833 pdesc->txdw6 = pdesc->txdw6;
2834 pdesc->txdw7 = pdesc->txdw7;
2835 pdesc->txdw8 = pdesc->txdw8;
2836 pdesc->txdw9 = pdesc->txdw9;
2837
2838 rtl8723b_cal_txdesc_chksum(pdesc);
2839 }
2840
2841 /* */
2842 /* Description: In normal chip, we should send some packet to Hw which will be used by Fw */
2843 /* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */
2844 /* Fw can tell Hw to send these packet derectly. */
2845 /* Added by tynli. 2009.10.15. */
2846 /* */
2847 /* type1:pspoll, type2:null */
rtl8723b_fill_fake_txdesc(struct adapter * padapter,u8 * pDesc,u32 BufferLen,u8 IsPsPoll,u8 IsBTQosNull,u8 bDataFrame)2848 void rtl8723b_fill_fake_txdesc(
2849 struct adapter *padapter,
2850 u8 *pDesc,
2851 u32 BufferLen,
2852 u8 IsPsPoll,
2853 u8 IsBTQosNull,
2854 u8 bDataFrame
2855 )
2856 {
2857 /* Clear all status */
2858 memset(pDesc, 0, TXDESC_SIZE);
2859
2860 SET_TX_DESC_FIRST_SEG_8723B(pDesc, 1); /* bFirstSeg; */
2861 SET_TX_DESC_LAST_SEG_8723B(pDesc, 1); /* bLastSeg; */
2862
2863 SET_TX_DESC_OFFSET_8723B(pDesc, 0x28); /* Offset = 32 */
2864
2865 SET_TX_DESC_PKT_SIZE_8723B(pDesc, BufferLen); /* Buffer size + command header */
2866 SET_TX_DESC_QUEUE_SEL_8723B(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
2867
2868 /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */
2869 if (IsPsPoll) {
2870 SET_TX_DESC_NAV_USE_HDR_8723B(pDesc, 1);
2871 } else {
2872 SET_TX_DESC_HWSEQ_EN_8723B(pDesc, 1); /* Hw set sequence number */
2873 SET_TX_DESC_HWSEQ_SEL_8723B(pDesc, 0);
2874 }
2875
2876 if (IsBTQosNull) {
2877 SET_TX_DESC_BT_INT_8723B(pDesc, 1);
2878 }
2879
2880 SET_TX_DESC_USE_RATE_8723B(pDesc, 1); /* use data rate which is set by Sw */
2881 SET_TX_DESC_OWN_8723B((u8 *)pDesc, 1);
2882
2883 SET_TX_DESC_TX_RATE_8723B(pDesc, DESC8723B_RATE1M);
2884
2885 /* */
2886 /* Encrypt the data frame if under security mode excepct null data. Suggested by CCW. */
2887 /* */
2888 if (bDataFrame) {
2889 u32 EncAlg;
2890
2891 EncAlg = padapter->securitypriv.dot11PrivacyAlgrthm;
2892 switch (EncAlg) {
2893 case _NO_PRIVACY_:
2894 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0);
2895 break;
2896 case _WEP40_:
2897 case _WEP104_:
2898 case _TKIP_:
2899 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x1);
2900 break;
2901 case _SMS4_:
2902 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x2);
2903 break;
2904 case _AES_:
2905 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x3);
2906 break;
2907 default:
2908 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0);
2909 break;
2910 }
2911 }
2912
2913 /* USB interface drop packet if the checksum of descriptor isn't correct. */
2914 /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */
2915 rtl8723b_cal_txdesc_chksum((struct tx_desc *)pDesc);
2916 }
2917
hw_var_set_opmode(struct adapter * padapter,u8 variable,u8 * val)2918 static void hw_var_set_opmode(struct adapter *padapter, u8 variable, u8 *val)
2919 {
2920 u8 val8;
2921 u8 mode = *((u8 *)val);
2922
2923 {
2924 /* disable Port0 TSF update */
2925 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2926 val8 |= DIS_TSF_UDT;
2927 rtw_write8(padapter, REG_BCN_CTRL, val8);
2928
2929 /* set net_type */
2930 Set_MSR(padapter, mode);
2931
2932 if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
2933 {
2934 StopTxBeacon(padapter);
2935 }
2936
2937 /* disable atim wnd */
2938 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_ATIM);
2939 /* rtw_write8(padapter, REG_BCN_CTRL, 0x18); */
2940 } else if (mode == _HW_STATE_ADHOC_) {
2941 ResumeTxBeacon(padapter);
2942 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_BCNQ_SUB);
2943 } else if (mode == _HW_STATE_AP_) {
2944
2945 ResumeTxBeacon(padapter);
2946
2947 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|DIS_BCNQ_SUB);
2948
2949 /* Set RCR */
2950 rtw_write32(padapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0, reject ICV_ERR packet */
2951 /* enable to rx data frame */
2952 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
2953 /* enable to rx ps-poll */
2954 rtw_write16(padapter, REG_RXFLTMAP1, 0x0400);
2955
2956 /* Beacon Control related register for first time */
2957 rtw_write8(padapter, REG_BCNDMATIM, 0x02); /* 2ms */
2958
2959 /* rtw_write8(padapter, REG_BCN_MAX_ERR, 0xFF); */
2960 rtw_write8(padapter, REG_ATIMWND, 0x0a); /* 10ms */
2961 rtw_write16(padapter, REG_BCNTCFG, 0x00);
2962 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0xff04);
2963 rtw_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */
2964
2965 /* reset TSF */
2966 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
2967
2968 /* enable BCN0 Function for if1 */
2969 /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */
2970 rtw_write8(padapter, REG_BCN_CTRL, (DIS_TSF_UDT|EN_BCN_FUNCTION|EN_TXBCN_RPT|DIS_BCNQ_SUB));
2971
2972 /* SW_BCN_SEL - Port0 */
2973 /* rtw_write8(Adapter, REG_DWBCN1_CTRL_8192E+2, rtw_read8(Adapter, REG_DWBCN1_CTRL_8192E+2) & ~BIT4); */
2974 rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
2975
2976 /* select BCN on port 0 */
2977 rtw_write8(
2978 padapter,
2979 REG_CCK_CHECK_8723B,
2980 (rtw_read8(padapter, REG_CCK_CHECK_8723B)&~BIT_BCN_PORT_SEL)
2981 );
2982
2983 /* dis BCN1 ATIM WND if if2 is station */
2984 val8 = rtw_read8(padapter, REG_BCN_CTRL_1);
2985 val8 |= DIS_ATIM;
2986 rtw_write8(padapter, REG_BCN_CTRL_1, val8);
2987 }
2988 }
2989 }
2990
hw_var_set_macaddr(struct adapter * padapter,u8 variable,u8 * val)2991 static void hw_var_set_macaddr(struct adapter *padapter, u8 variable, u8 *val)
2992 {
2993 u8 idx = 0;
2994 u32 reg_macid;
2995
2996 reg_macid = REG_MACID;
2997
2998 for (idx = 0 ; idx < 6; idx++)
2999 rtw_write8(GET_PRIMARY_ADAPTER(padapter), (reg_macid+idx), val[idx]);
3000 }
3001
hw_var_set_bssid(struct adapter * padapter,u8 variable,u8 * val)3002 static void hw_var_set_bssid(struct adapter *padapter, u8 variable, u8 *val)
3003 {
3004 u8 idx = 0;
3005 u32 reg_bssid;
3006
3007 reg_bssid = REG_BSSID;
3008
3009 for (idx = 0 ; idx < 6; idx++)
3010 rtw_write8(padapter, (reg_bssid+idx), val[idx]);
3011 }
3012
hw_var_set_bcn_func(struct adapter * padapter,u8 variable,u8 * val)3013 static void hw_var_set_bcn_func(struct adapter *padapter, u8 variable, u8 *val)
3014 {
3015 u32 bcn_ctrl_reg;
3016
3017 bcn_ctrl_reg = REG_BCN_CTRL;
3018
3019 if (*(u8 *)val)
3020 rtw_write8(padapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT));
3021 else {
3022 u8 val8;
3023 val8 = rtw_read8(padapter, bcn_ctrl_reg);
3024 val8 &= ~(EN_BCN_FUNCTION | EN_TXBCN_RPT);
3025
3026 /* Always enable port0 beacon function for PSTDMA */
3027 if (REG_BCN_CTRL == bcn_ctrl_reg)
3028 val8 |= EN_BCN_FUNCTION;
3029
3030 rtw_write8(padapter, bcn_ctrl_reg, val8);
3031 }
3032 }
3033
hw_var_set_correct_tsf(struct adapter * padapter,u8 variable,u8 * val)3034 static void hw_var_set_correct_tsf(struct adapter *padapter, u8 variable, u8 *val)
3035 {
3036 u8 val8;
3037 u64 tsf;
3038 struct mlme_ext_priv *pmlmeext;
3039 struct mlme_ext_info *pmlmeinfo;
3040
3041
3042 pmlmeext = &padapter->mlmeextpriv;
3043 pmlmeinfo = &pmlmeext->mlmext_info;
3044
3045 tsf = pmlmeext->TSFValue-do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024))-1024; /* us */
3046
3047 if (
3048 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) ||
3049 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3050 )
3051 StopTxBeacon(padapter);
3052
3053 {
3054 /* disable related TSF function */
3055 val8 = rtw_read8(padapter, REG_BCN_CTRL);
3056 val8 &= ~EN_BCN_FUNCTION;
3057 rtw_write8(padapter, REG_BCN_CTRL, val8);
3058
3059 rtw_write32(padapter, REG_TSFTR, tsf);
3060 rtw_write32(padapter, REG_TSFTR+4, tsf>>32);
3061
3062 /* enable related TSF function */
3063 val8 = rtw_read8(padapter, REG_BCN_CTRL);
3064 val8 |= EN_BCN_FUNCTION;
3065 rtw_write8(padapter, REG_BCN_CTRL, val8);
3066 }
3067
3068 if (
3069 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) ||
3070 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3071 )
3072 ResumeTxBeacon(padapter);
3073 }
3074
hw_var_set_mlme_disconnect(struct adapter * padapter,u8 variable,u8 * val)3075 static void hw_var_set_mlme_disconnect(struct adapter *padapter, u8 variable, u8 *val)
3076 {
3077 u8 val8;
3078
3079 /* Set RCR to not to receive data frame when NO LINK state */
3080 /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR) & ~RCR_ADF); */
3081 /* reject all data frames */
3082 rtw_write16(padapter, REG_RXFLTMAP2, 0);
3083
3084 /* reset TSF */
3085 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
3086
3087 /* disable update TSF */
3088 val8 = rtw_read8(padapter, REG_BCN_CTRL);
3089 val8 |= DIS_TSF_UDT;
3090 rtw_write8(padapter, REG_BCN_CTRL, val8);
3091 }
3092
hw_var_set_mlme_sitesurvey(struct adapter * padapter,u8 variable,u8 * val)3093 static void hw_var_set_mlme_sitesurvey(struct adapter *padapter, u8 variable, u8 *val)
3094 {
3095 u32 value_rcr, rcr_clear_bit, reg_bcn_ctl;
3096 u16 value_rxfltmap2;
3097 u8 val8;
3098 struct hal_com_data *pHalData;
3099 struct mlme_priv *pmlmepriv;
3100
3101
3102 pHalData = GET_HAL_DATA(padapter);
3103 pmlmepriv = &padapter->mlmepriv;
3104
3105 reg_bcn_ctl = REG_BCN_CTRL;
3106
3107 rcr_clear_bit = RCR_CBSSID_BCN;
3108
3109 /* config RCR to receive different BSSID & not to receive data frame */
3110 value_rxfltmap2 = 0;
3111
3112 if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true))
3113 rcr_clear_bit = RCR_CBSSID_BCN;
3114
3115 value_rcr = rtw_read32(padapter, REG_RCR);
3116
3117 if (*((u8 *)val)) {
3118 /* under sitesurvey */
3119 value_rcr &= ~(rcr_clear_bit);
3120 rtw_write32(padapter, REG_RCR, value_rcr);
3121
3122 rtw_write16(padapter, REG_RXFLTMAP2, value_rxfltmap2);
3123
3124 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
3125 /* disable update TSF */
3126 val8 = rtw_read8(padapter, reg_bcn_ctl);
3127 val8 |= DIS_TSF_UDT;
3128 rtw_write8(padapter, reg_bcn_ctl, val8);
3129 }
3130
3131 /* Save original RRSR setting. */
3132 pHalData->RegRRSR = rtw_read16(padapter, REG_RRSR);
3133 } else {
3134 /* sitesurvey done */
3135 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
3136 /* enable to rx data frame */
3137 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
3138
3139 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
3140 /* enable update TSF */
3141 val8 = rtw_read8(padapter, reg_bcn_ctl);
3142 val8 &= ~DIS_TSF_UDT;
3143 rtw_write8(padapter, reg_bcn_ctl, val8);
3144 }
3145
3146 value_rcr |= rcr_clear_bit;
3147 rtw_write32(padapter, REG_RCR, value_rcr);
3148
3149 /* Restore original RRSR setting. */
3150 rtw_write16(padapter, REG_RRSR, pHalData->RegRRSR);
3151 }
3152 }
3153
hw_var_set_mlme_join(struct adapter * padapter,u8 variable,u8 * val)3154 static void hw_var_set_mlme_join(struct adapter *padapter, u8 variable, u8 *val)
3155 {
3156 u8 val8;
3157 u16 val16;
3158 u32 val32;
3159 u8 RetryLimit;
3160 u8 type;
3161 struct mlme_priv *pmlmepriv;
3162 struct eeprom_priv *pEEPROM;
3163
3164
3165 RetryLimit = 0x30;
3166 type = *(u8 *)val;
3167 pmlmepriv = &padapter->mlmepriv;
3168 pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
3169
3170 if (type == 0) { /* prepare to join */
3171 /* enable to rx data frame.Accept all data frame */
3172 /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF); */
3173 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
3174
3175 val32 = rtw_read32(padapter, REG_RCR);
3176 if (padapter->in_cta_test)
3177 val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */
3178 else
3179 val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN;
3180 rtw_write32(padapter, REG_RCR, val32);
3181
3182 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
3183 RetryLimit = (pEEPROM->CustomerID == RT_CID_CCX) ? 7 : 48;
3184 else /* Ad-hoc Mode */
3185 RetryLimit = 0x7;
3186 } else if (type == 1) /* joinbss_event call back when join res < 0 */
3187 rtw_write16(padapter, REG_RXFLTMAP2, 0x00);
3188 else if (type == 2) { /* sta add event call back */
3189 /* enable update TSF */
3190 val8 = rtw_read8(padapter, REG_BCN_CTRL);
3191 val8 &= ~DIS_TSF_UDT;
3192 rtw_write8(padapter, REG_BCN_CTRL, val8);
3193
3194 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))
3195 RetryLimit = 0x7;
3196 }
3197
3198 val16 = (RetryLimit << RETRY_LIMIT_SHORT_SHIFT) | (RetryLimit << RETRY_LIMIT_LONG_SHIFT);
3199 rtw_write16(padapter, REG_RL, val16);
3200 }
3201
CCX_FwC2HTxRpt_8723b(struct adapter * padapter,u8 * pdata,u8 len)3202 void CCX_FwC2HTxRpt_8723b(struct adapter *padapter, u8 *pdata, u8 len)
3203 {
3204
3205 #define GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 6, 1)
3206 #define GET_8723B_C2H_TX_RPT_RETRY_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 7, 1)
3207
3208 if (GET_8723B_C2H_TX_RPT_RETRY_OVER(pdata) | GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(pdata)) {
3209 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
3210 }
3211 /*
3212 else if (seq_no != padapter->xmitpriv.seq_no) {
3213 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
3214 }
3215 */
3216 else
3217 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_SUCCESS);
3218 }
3219
c2h_id_filter_ccx_8723b(u8 * buf)3220 s32 c2h_id_filter_ccx_8723b(u8 *buf)
3221 {
3222 struct c2h_evt_hdr_88xx *c2h_evt = (struct c2h_evt_hdr_88xx *)buf;
3223 s32 ret = false;
3224 if (c2h_evt->id == C2H_CCX_TX_RPT)
3225 ret = true;
3226
3227 return ret;
3228 }
3229
3230
c2h_handler_8723b(struct adapter * padapter,u8 * buf)3231 s32 c2h_handler_8723b(struct adapter *padapter, u8 *buf)
3232 {
3233 struct c2h_evt_hdr_88xx *pC2hEvent = (struct c2h_evt_hdr_88xx *)buf;
3234 s32 ret = _SUCCESS;
3235
3236 if (!pC2hEvent) {
3237 ret = _FAIL;
3238 goto exit;
3239 }
3240
3241 switch (pC2hEvent->id) {
3242 case C2H_AP_RPT_RSP:
3243 break;
3244 case C2H_DBG:
3245 {
3246 }
3247 break;
3248
3249 case C2H_CCX_TX_RPT:
3250 /* CCX_FwC2HTxRpt(padapter, QueueID, pC2hEvent->payload); */
3251 break;
3252
3253 case C2H_EXT_RA_RPT:
3254 /* C2HExtRaRptHandler(padapter, pC2hEvent->payload, C2hEvent.CmdLen); */
3255 break;
3256
3257 case C2H_HW_INFO_EXCH:
3258 break;
3259
3260 case C2H_8723B_BT_INFO:
3261 hal_btcoex_BtInfoNotify(padapter, pC2hEvent->plen, pC2hEvent->payload);
3262 break;
3263
3264 default:
3265 break;
3266 }
3267
3268 /* Clear event to notify FW we have read the command. */
3269 /* Note: */
3270 /* If this field isn't clear, the FW won't update the next command message. */
3271 /* rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); */
3272 exit:
3273 return ret;
3274 }
3275
process_c2h_event(struct adapter * padapter,struct c2h_evt_hdr_t * pC2hEvent,u8 * c2hBuf)3276 static void process_c2h_event(struct adapter *padapter, struct c2h_evt_hdr_t *pC2hEvent, u8 *c2hBuf)
3277 {
3278 if (!c2hBuf)
3279 return;
3280
3281 switch (pC2hEvent->CmdID) {
3282 case C2H_AP_RPT_RSP:
3283 break;
3284 case C2H_DBG:
3285 {
3286 }
3287 break;
3288
3289 case C2H_CCX_TX_RPT:
3290 /* CCX_FwC2HTxRpt(padapter, QueueID, tmpBuf); */
3291 break;
3292
3293 case C2H_EXT_RA_RPT:
3294 /* C2HExtRaRptHandler(padapter, tmpBuf, C2hEvent.CmdLen); */
3295 break;
3296
3297 case C2H_HW_INFO_EXCH:
3298 break;
3299
3300 case C2H_8723B_BT_INFO:
3301 hal_btcoex_BtInfoNotify(padapter, pC2hEvent->CmdLen, c2hBuf);
3302 break;
3303
3304 default:
3305 break;
3306 }
3307 }
3308
C2HPacketHandler_8723B(struct adapter * padapter,u8 * pbuffer,u16 length)3309 void C2HPacketHandler_8723B(struct adapter *padapter, u8 *pbuffer, u16 length)
3310 {
3311 struct c2h_evt_hdr_t C2hEvent;
3312 u8 *tmpBuf = NULL;
3313 C2hEvent.CmdID = pbuffer[0];
3314 C2hEvent.CmdSeq = pbuffer[1];
3315 C2hEvent.CmdLen = length-2;
3316 tmpBuf = pbuffer+2;
3317
3318 print_hex_dump_debug(DRIVER_PREFIX ": C2HPacketHandler_8723B(): Command Content:\n",
3319 DUMP_PREFIX_NONE, 16, 1, tmpBuf, C2hEvent.CmdLen, false);
3320
3321 process_c2h_event(padapter, &C2hEvent, tmpBuf);
3322 /* c2h_handler_8723b(padapter,&C2hEvent); */
3323 }
3324
SetHwReg8723B(struct adapter * padapter,u8 variable,u8 * val)3325 void SetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
3326 {
3327 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
3328 u8 val8;
3329 u32 val32;
3330
3331 switch (variable) {
3332 case HW_VAR_MEDIA_STATUS:
3333 val8 = rtw_read8(padapter, MSR) & 0x0c;
3334 val8 |= *val;
3335 rtw_write8(padapter, MSR, val8);
3336 break;
3337
3338 case HW_VAR_MEDIA_STATUS1:
3339 val8 = rtw_read8(padapter, MSR) & 0x03;
3340 val8 |= *val << 2;
3341 rtw_write8(padapter, MSR, val8);
3342 break;
3343
3344 case HW_VAR_SET_OPMODE:
3345 hw_var_set_opmode(padapter, variable, val);
3346 break;
3347
3348 case HW_VAR_MAC_ADDR:
3349 hw_var_set_macaddr(padapter, variable, val);
3350 break;
3351
3352 case HW_VAR_BSSID:
3353 hw_var_set_bssid(padapter, variable, val);
3354 break;
3355
3356 case HW_VAR_BASIC_RATE:
3357 {
3358 struct mlme_ext_info *mlmext_info = &padapter->mlmeextpriv.mlmext_info;
3359 u16 BrateCfg = 0;
3360 u16 rrsr_2g_force_mask = (RRSR_11M|RRSR_5_5M|RRSR_1M);
3361 u16 rrsr_2g_allow_mask = (RRSR_24M|RRSR_12M|RRSR_6M|RRSR_CCK_RATES);
3362
3363 HalSetBrateCfg(padapter, val, &BrateCfg);
3364
3365 /* apply force and allow mask */
3366 BrateCfg |= rrsr_2g_force_mask;
3367 BrateCfg &= rrsr_2g_allow_mask;
3368
3369 /* IOT consideration */
3370 if (mlmext_info->assoc_AP_vendor == HT_IOT_PEER_CISCO) {
3371 /* if peer is cisco and didn't use ofdm rate, we enable 6M ack */
3372 if ((BrateCfg & (RRSR_24M|RRSR_12M|RRSR_6M)) == 0)
3373 BrateCfg |= RRSR_6M;
3374 }
3375
3376 pHalData->BasicRateSet = BrateCfg;
3377
3378 /* Set RRSR rate table. */
3379 rtw_write16(padapter, REG_RRSR, BrateCfg);
3380 rtw_write8(padapter, REG_RRSR+2, rtw_read8(padapter, REG_RRSR+2)&0xf0);
3381 }
3382 break;
3383
3384 case HW_VAR_TXPAUSE:
3385 rtw_write8(padapter, REG_TXPAUSE, *val);
3386 break;
3387
3388 case HW_VAR_BCN_FUNC:
3389 hw_var_set_bcn_func(padapter, variable, val);
3390 break;
3391
3392 case HW_VAR_CORRECT_TSF:
3393 hw_var_set_correct_tsf(padapter, variable, val);
3394 break;
3395
3396 case HW_VAR_CHECK_BSSID:
3397 {
3398 u32 val32;
3399 val32 = rtw_read32(padapter, REG_RCR);
3400 if (*val)
3401 val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN;
3402 else
3403 val32 &= ~(RCR_CBSSID_DATA|RCR_CBSSID_BCN);
3404 rtw_write32(padapter, REG_RCR, val32);
3405 }
3406 break;
3407
3408 case HW_VAR_MLME_DISCONNECT:
3409 hw_var_set_mlme_disconnect(padapter, variable, val);
3410 break;
3411
3412 case HW_VAR_MLME_SITESURVEY:
3413 hw_var_set_mlme_sitesurvey(padapter, variable, val);
3414
3415 hal_btcoex_ScanNotify(padapter, *val?true:false);
3416 break;
3417
3418 case HW_VAR_MLME_JOIN:
3419 hw_var_set_mlme_join(padapter, variable, val);
3420
3421 switch (*val) {
3422 case 0:
3423 /* prepare to join */
3424 hal_btcoex_ConnectNotify(padapter, true);
3425 break;
3426 case 1:
3427 /* joinbss_event callback when join res < 0 */
3428 hal_btcoex_ConnectNotify(padapter, false);
3429 break;
3430 case 2:
3431 /* sta add event callback */
3432 /* rtw_btcoex_MediaStatusNotify(padapter, RT_MEDIA_CONNECT); */
3433 break;
3434 }
3435 break;
3436
3437 case HW_VAR_ON_RCR_AM:
3438 val32 = rtw_read32(padapter, REG_RCR);
3439 val32 |= RCR_AM;
3440 rtw_write32(padapter, REG_RCR, val32);
3441 break;
3442
3443 case HW_VAR_OFF_RCR_AM:
3444 val32 = rtw_read32(padapter, REG_RCR);
3445 val32 &= ~RCR_AM;
3446 rtw_write32(padapter, REG_RCR, val32);
3447 break;
3448
3449 case HW_VAR_BEACON_INTERVAL:
3450 rtw_write16(padapter, REG_BCN_INTERVAL, *((u16 *)val));
3451 break;
3452
3453 case HW_VAR_SLOT_TIME:
3454 rtw_write8(padapter, REG_SLOT, *val);
3455 break;
3456
3457 case HW_VAR_RESP_SIFS:
3458 /* SIFS_Timer = 0x0a0a0808; */
3459 /* RESP_SIFS for CCK */
3460 rtw_write8(padapter, REG_RESP_SIFS_CCK, val[0]); /* SIFS_T2T_CCK (0x08) */
3461 rtw_write8(padapter, REG_RESP_SIFS_CCK+1, val[1]); /* SIFS_R2T_CCK(0x08) */
3462 /* RESP_SIFS for OFDM */
3463 rtw_write8(padapter, REG_RESP_SIFS_OFDM, val[2]); /* SIFS_T2T_OFDM (0x0a) */
3464 rtw_write8(padapter, REG_RESP_SIFS_OFDM+1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
3465 break;
3466
3467 case HW_VAR_ACK_PREAMBLE:
3468 {
3469 u8 regTmp;
3470 u8 bShortPreamble = *val;
3471
3472 /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */
3473 /* regTmp = (pHalData->nCur40MhzPrimeSC)<<5; */
3474 regTmp = 0;
3475 if (bShortPreamble)
3476 regTmp |= 0x80;
3477 rtw_write8(padapter, REG_RRSR+2, regTmp);
3478 }
3479 break;
3480
3481 case HW_VAR_CAM_EMPTY_ENTRY:
3482 {
3483 u8 ucIndex = *val;
3484 u8 i;
3485 u32 ulCommand = 0;
3486 u32 ulContent = 0;
3487 u32 ulEncAlgo = CAM_AES;
3488
3489 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
3490 /* filled id in CAM config 2 byte */
3491 if (i == 0) {
3492 ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo)<<2);
3493 /* ulContent |= CAM_VALID; */
3494 } else
3495 ulContent = 0;
3496
3497 /* polling bit, and No Write enable, and address */
3498 ulCommand = CAM_CONTENT_COUNT*ucIndex+i;
3499 ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
3500 /* write content 0 is equall to mark invalid */
3501 rtw_write32(padapter, WCAMI, ulContent); /* mdelay(40); */
3502 rtw_write32(padapter, RWCAM, ulCommand); /* mdelay(40); */
3503 }
3504 }
3505 break;
3506
3507 case HW_VAR_CAM_INVALID_ALL:
3508 rtw_write32(padapter, RWCAM, BIT(31)|BIT(30));
3509 break;
3510
3511 case HW_VAR_CAM_WRITE:
3512 {
3513 u32 cmd;
3514 u32 *cam_val = (u32 *)val;
3515
3516 rtw_write32(padapter, WCAMI, cam_val[0]);
3517
3518 cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1];
3519 rtw_write32(padapter, RWCAM, cmd);
3520 }
3521 break;
3522
3523 case HW_VAR_AC_PARAM_VO:
3524 rtw_write32(padapter, REG_EDCA_VO_PARAM, *((u32 *)val));
3525 break;
3526
3527 case HW_VAR_AC_PARAM_VI:
3528 rtw_write32(padapter, REG_EDCA_VI_PARAM, *((u32 *)val));
3529 break;
3530
3531 case HW_VAR_AC_PARAM_BE:
3532 pHalData->AcParam_BE = ((u32 *)(val))[0];
3533 rtw_write32(padapter, REG_EDCA_BE_PARAM, *((u32 *)val));
3534 break;
3535
3536 case HW_VAR_AC_PARAM_BK:
3537 rtw_write32(padapter, REG_EDCA_BK_PARAM, *((u32 *)val));
3538 break;
3539
3540 case HW_VAR_ACM_CTRL:
3541 {
3542 u8 ctrl = *((u8 *)val);
3543 u8 hwctrl = 0;
3544
3545 if (ctrl != 0) {
3546 hwctrl |= AcmHw_HwEn;
3547
3548 if (ctrl & BIT(1)) /* BE */
3549 hwctrl |= AcmHw_BeqEn;
3550
3551 if (ctrl & BIT(2)) /* VI */
3552 hwctrl |= AcmHw_ViqEn;
3553
3554 if (ctrl & BIT(3)) /* VO */
3555 hwctrl |= AcmHw_VoqEn;
3556 }
3557
3558 rtw_write8(padapter, REG_ACMHWCTRL, hwctrl);
3559 }
3560 break;
3561
3562 case HW_VAR_AMPDU_FACTOR:
3563 {
3564 u32 AMPDULen = (*((u8 *)val));
3565
3566 if (AMPDULen < HT_AGG_SIZE_32K)
3567 AMPDULen = (0x2000 << (*((u8 *)val)))-1;
3568 else
3569 AMPDULen = 0x7fff;
3570
3571 rtw_write32(padapter, REG_AMPDU_MAX_LENGTH_8723B, AMPDULen);
3572 }
3573 break;
3574
3575 case HW_VAR_H2C_FW_PWRMODE:
3576 {
3577 u8 psmode = *val;
3578
3579 /* Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
3580 /* saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
3581 if (psmode != PS_MODE_ACTIVE) {
3582 ODM_RF_Saving(&pHalData->odmpriv, true);
3583 }
3584
3585 /* if (psmode != PS_MODE_ACTIVE) { */
3586 /* rtl8723b_set_lowpwr_lps_cmd(padapter, true); */
3587 /* else { */
3588 /* rtl8723b_set_lowpwr_lps_cmd(padapter, false); */
3589 /* */
3590 rtl8723b_set_FwPwrMode_cmd(padapter, psmode);
3591 }
3592 break;
3593 case HW_VAR_H2C_PS_TUNE_PARAM:
3594 rtl8723b_set_FwPsTuneParam_cmd(padapter);
3595 break;
3596
3597 case HW_VAR_H2C_FW_JOINBSSRPT:
3598 rtl8723b_set_FwJoinBssRpt_cmd(padapter, *val);
3599 break;
3600
3601 case HW_VAR_INITIAL_GAIN:
3602 {
3603 struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
3604 u32 rx_gain = *(u32 *)val;
3605
3606 if (rx_gain == 0xff) {/* restore rx gain */
3607 ODM_Write_DIG(&pHalData->odmpriv, pDigTable->BackupIGValue);
3608 } else {
3609 pDigTable->BackupIGValue = pDigTable->CurIGValue;
3610 ODM_Write_DIG(&pHalData->odmpriv, rx_gain);
3611 }
3612 }
3613 break;
3614
3615 case HW_VAR_EFUSE_USAGE:
3616 pHalData->EfuseUsedPercentage = *val;
3617 break;
3618
3619 case HW_VAR_EFUSE_BYTES:
3620 pHalData->EfuseUsedBytes = *((u16 *)val);
3621 break;
3622
3623 case HW_VAR_EFUSE_BT_USAGE:
3624 #ifdef HAL_EFUSE_MEMORY
3625 pHalData->EfuseHal.BTEfuseUsedPercentage = *val;
3626 #endif
3627 break;
3628
3629 case HW_VAR_EFUSE_BT_BYTES:
3630 #ifdef HAL_EFUSE_MEMORY
3631 pHalData->EfuseHal.BTEfuseUsedBytes = *((u16 *)val);
3632 #else
3633 BTEfuseUsedBytes = *((u16 *)val);
3634 #endif
3635 break;
3636
3637 case HW_VAR_FIFO_CLEARN_UP:
3638 {
3639 #define RW_RELEASE_EN BIT(18)
3640 #define RXDMA_IDLE BIT(17)
3641
3642 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3643 u8 trycnt = 100;
3644
3645 /* pause tx */
3646 rtw_write8(padapter, REG_TXPAUSE, 0xff);
3647
3648 /* keep sn */
3649 padapter->xmitpriv.nqos_ssn = rtw_read16(padapter, REG_NQOS_SEQ);
3650
3651 if (!pwrpriv->bkeepfwalive) {
3652 /* RX DMA stop */
3653 val32 = rtw_read32(padapter, REG_RXPKT_NUM);
3654 val32 |= RW_RELEASE_EN;
3655 rtw_write32(padapter, REG_RXPKT_NUM, val32);
3656 do {
3657 val32 = rtw_read32(padapter, REG_RXPKT_NUM);
3658 val32 &= RXDMA_IDLE;
3659 if (val32)
3660 break;
3661 } while (--trycnt);
3662
3663 /* RQPN Load 0 */
3664 rtw_write16(padapter, REG_RQPN_NPQ, 0);
3665 rtw_write32(padapter, REG_RQPN, 0x80000000);
3666 mdelay(2);
3667 }
3668 }
3669 break;
3670
3671 case HW_VAR_APFM_ON_MAC:
3672 pHalData->bMacPwrCtrlOn = *val;
3673 break;
3674
3675 case HW_VAR_NAV_UPPER:
3676 {
3677 u32 usNavUpper = *((u32 *)val);
3678
3679 if (usNavUpper > HAL_NAV_UPPER_UNIT_8723B * 0xFF)
3680 break;
3681
3682 usNavUpper = DIV_ROUND_UP(usNavUpper,
3683 HAL_NAV_UPPER_UNIT_8723B);
3684 rtw_write8(padapter, REG_NAV_UPPER, (u8)usNavUpper);
3685 }
3686 break;
3687
3688 case HW_VAR_H2C_MEDIA_STATUS_RPT:
3689 {
3690 u16 mstatus_rpt = (*(u16 *)val);
3691 u8 mstatus, macId;
3692
3693 mstatus = (u8) (mstatus_rpt & 0xFF);
3694 macId = (u8)(mstatus_rpt >> 8);
3695 rtl8723b_set_FwMediaStatusRpt_cmd(padapter, mstatus, macId);
3696 }
3697 break;
3698 case HW_VAR_BCN_VALID:
3699 {
3700 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */
3701 val8 = rtw_read8(padapter, REG_TDECTRL+2);
3702 val8 |= BIT(0);
3703 rtw_write8(padapter, REG_TDECTRL+2, val8);
3704 }
3705 break;
3706
3707 case HW_VAR_DL_BCN_SEL:
3708 {
3709 /* SW_BCN_SEL - Port0 */
3710 val8 = rtw_read8(padapter, REG_DWBCN1_CTRL_8723B+2);
3711 val8 &= ~BIT(4);
3712 rtw_write8(padapter, REG_DWBCN1_CTRL_8723B+2, val8);
3713 }
3714 break;
3715
3716 case HW_VAR_DO_IQK:
3717 pHalData->bNeedIQK = true;
3718 break;
3719
3720 case HW_VAR_DL_RSVD_PAGE:
3721 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)
3722 rtl8723b_download_BTCoex_AP_mode_rsvd_page(padapter);
3723 else
3724 rtl8723b_download_rsvd_page(padapter, RT_MEDIA_CONNECT);
3725 break;
3726
3727 case HW_VAR_MACID_SLEEP:
3728 /* Input is MACID */
3729 val32 = *(u32 *)val;
3730 if (val32 > 31)
3731 break;
3732
3733 val8 = (u8)val32; /* macid is between 0~31 */
3734
3735 val32 = rtw_read32(padapter, REG_MACID_SLEEP);
3736 if (val32 & BIT(val8))
3737 break;
3738 val32 |= BIT(val8);
3739 rtw_write32(padapter, REG_MACID_SLEEP, val32);
3740 break;
3741
3742 case HW_VAR_MACID_WAKEUP:
3743 /* Input is MACID */
3744 val32 = *(u32 *)val;
3745 if (val32 > 31)
3746 break;
3747
3748 val8 = (u8)val32; /* macid is between 0~31 */
3749
3750 val32 = rtw_read32(padapter, REG_MACID_SLEEP);
3751 if (!(val32 & BIT(val8)))
3752 break;
3753 val32 &= ~BIT(val8);
3754 rtw_write32(padapter, REG_MACID_SLEEP, val32);
3755 break;
3756
3757 default:
3758 SetHwReg(padapter, variable, val);
3759 break;
3760 }
3761 }
3762
GetHwReg8723B(struct adapter * padapter,u8 variable,u8 * val)3763 void GetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
3764 {
3765 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
3766 u8 val8;
3767 u16 val16;
3768
3769 switch (variable) {
3770 case HW_VAR_TXPAUSE:
3771 *val = rtw_read8(padapter, REG_TXPAUSE);
3772 break;
3773
3774 case HW_VAR_BCN_VALID:
3775 {
3776 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
3777 val8 = rtw_read8(padapter, REG_TDECTRL+2);
3778 *val = (BIT(0) & val8) ? true : false;
3779 }
3780 break;
3781
3782 case HW_VAR_FWLPS_RF_ON:
3783 {
3784 /* When we halt NIC, we should check if FW LPS is leave. */
3785 u32 valRCR;
3786
3787 if (
3788 padapter->bSurpriseRemoved ||
3789 (adapter_to_pwrctl(padapter)->rf_pwrstate == rf_off)
3790 ) {
3791 /* If it is in HW/SW Radio OFF or IPS state, we do not check Fw LPS Leave, */
3792 /* because Fw is unload. */
3793 *val = true;
3794 } else {
3795 valRCR = rtw_read32(padapter, REG_RCR);
3796 valRCR &= 0x00070000;
3797 if (valRCR)
3798 *val = false;
3799 else
3800 *val = true;
3801 }
3802 }
3803 break;
3804
3805 case HW_VAR_EFUSE_USAGE:
3806 *val = pHalData->EfuseUsedPercentage;
3807 break;
3808
3809 case HW_VAR_EFUSE_BYTES:
3810 *((u16 *)val) = pHalData->EfuseUsedBytes;
3811 break;
3812
3813 case HW_VAR_EFUSE_BT_USAGE:
3814 #ifdef HAL_EFUSE_MEMORY
3815 *val = pHalData->EfuseHal.BTEfuseUsedPercentage;
3816 #endif
3817 break;
3818
3819 case HW_VAR_EFUSE_BT_BYTES:
3820 #ifdef HAL_EFUSE_MEMORY
3821 *((u16 *)val) = pHalData->EfuseHal.BTEfuseUsedBytes;
3822 #else
3823 *((u16 *)val) = BTEfuseUsedBytes;
3824 #endif
3825 break;
3826
3827 case HW_VAR_APFM_ON_MAC:
3828 *val = pHalData->bMacPwrCtrlOn;
3829 break;
3830 case HW_VAR_CHK_HI_QUEUE_EMPTY:
3831 val16 = rtw_read16(padapter, REG_TXPKT_EMPTY);
3832 *val = (val16 & BIT(10)) ? true:false;
3833 break;
3834 default:
3835 GetHwReg(padapter, variable, val);
3836 break;
3837 }
3838 }
3839
3840 /* Description:
3841 * Change default setting of specified variable.
3842 */
SetHalDefVar8723B(struct adapter * padapter,enum hal_def_variable variable,void * pval)3843 u8 SetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval)
3844 {
3845 u8 bResult;
3846
3847 bResult = _SUCCESS;
3848
3849 switch (variable) {
3850 default:
3851 bResult = SetHalDefVar(padapter, variable, pval);
3852 break;
3853 }
3854
3855 return bResult;
3856 }
3857
3858 /* Description:
3859 * Query setting of specified variable.
3860 */
GetHalDefVar8723B(struct adapter * padapter,enum hal_def_variable variable,void * pval)3861 u8 GetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval)
3862 {
3863 u8 bResult;
3864
3865 bResult = _SUCCESS;
3866
3867 switch (variable) {
3868 case HAL_DEF_MAX_RECVBUF_SZ:
3869 *((u32 *)pval) = MAX_RECVBUF_SZ;
3870 break;
3871
3872 case HAL_DEF_RX_PACKET_OFFSET:
3873 *((u32 *)pval) = RXDESC_SIZE + DRVINFO_SZ*8;
3874 break;
3875
3876 case HW_VAR_MAX_RX_AMPDU_FACTOR:
3877 /* Stanley@BB.SD3 suggests 16K can get stable performance */
3878 /* The experiment was done on SDIO interface */
3879 /* coding by Lucas@20130730 */
3880 *(u32 *)pval = IEEE80211_HT_MAX_AMPDU_16K;
3881 break;
3882 case HAL_DEF_TX_LDPC:
3883 case HAL_DEF_RX_LDPC:
3884 *((u8 *)pval) = false;
3885 break;
3886 case HAL_DEF_TX_STBC:
3887 *((u8 *)pval) = 0;
3888 break;
3889 case HAL_DEF_RX_STBC:
3890 *((u8 *)pval) = 1;
3891 break;
3892 case HAL_DEF_EXPLICIT_BEAMFORMER:
3893 case HAL_DEF_EXPLICIT_BEAMFORMEE:
3894 *((u8 *)pval) = false;
3895 break;
3896
3897 case HW_DEF_RA_INFO_DUMP:
3898 {
3899 u8 mac_id = *(u8 *)pval;
3900 u32 cmd;
3901 u32 ra_info1, ra_info2;
3902 u32 rate_mask1, rate_mask2;
3903 u8 curr_tx_rate, curr_tx_sgi, hight_rate, lowest_rate;
3904
3905 cmd = 0x40000100 | mac_id;
3906 rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd);
3907 msleep(10);
3908 ra_info1 = rtw_read32(padapter, 0x2F0);
3909 curr_tx_rate = ra_info1&0x7F;
3910 curr_tx_sgi = (ra_info1>>7)&0x01;
3911
3912 cmd = 0x40000400 | mac_id;
3913 rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd);
3914 msleep(10);
3915 ra_info1 = rtw_read32(padapter, 0x2F0);
3916 ra_info2 = rtw_read32(padapter, 0x2F4);
3917 rate_mask1 = rtw_read32(padapter, 0x2F8);
3918 rate_mask2 = rtw_read32(padapter, 0x2FC);
3919 hight_rate = ra_info2&0xFF;
3920 lowest_rate = (ra_info2>>8) & 0xFF;
3921
3922 }
3923 break;
3924
3925 case HAL_DEF_TX_PAGE_BOUNDARY:
3926 if (!padapter->registrypriv.wifi_spec) {
3927 *(u8 *)pval = TX_PAGE_BOUNDARY_8723B;
3928 } else {
3929 *(u8 *)pval = WMM_NORMAL_TX_PAGE_BOUNDARY_8723B;
3930 }
3931 break;
3932
3933 case HAL_DEF_MACID_SLEEP:
3934 *(u8 *)pval = true; /* support macid sleep */
3935 break;
3936
3937 default:
3938 bResult = GetHalDefVar(padapter, variable, pval);
3939 break;
3940 }
3941
3942 return bResult;
3943 }
3944
rtl8723b_start_thread(struct adapter * padapter)3945 void rtl8723b_start_thread(struct adapter *padapter)
3946 {
3947 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
3948
3949 xmitpriv->SdioXmitThread = kthread_run(rtl8723bs_xmit_thread, padapter, "RTWHALXT");
3950 }
3951
rtl8723b_stop_thread(struct adapter * padapter)3952 void rtl8723b_stop_thread(struct adapter *padapter)
3953 {
3954 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
3955
3956 /* stop xmit_buf_thread */
3957 if (xmitpriv->SdioXmitThread) {
3958 complete(&xmitpriv->SdioXmitStart);
3959 wait_for_completion(&xmitpriv->SdioXmitTerminate);
3960 xmitpriv->SdioXmitThread = NULL;
3961 }
3962 }
3963