1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 ******************************************************************************/
17 #include <linux/firmware.h>
18 #include <drv_types.h>
19 #include <rtw_efuse.h>
21 #include <rtl8723a_hal.h>
23 static void _FWDownloadEnable(struct rtw_adapter *padapter, bool enable)
29 tmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
30 rtw_write8(padapter, REG_SYS_FUNC_EN + 1, tmp | 0x04);
32 /* MCU firmware download enable. */
33 tmp = rtw_read8(padapter, REG_MCUFWDL);
34 rtw_write8(padapter, REG_MCUFWDL, tmp | 0x01);
37 tmp = rtw_read8(padapter, REG_MCUFWDL + 2);
38 rtw_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7);
40 /* MCU firmware download disable. */
41 tmp = rtw_read8(padapter, REG_MCUFWDL);
42 rtw_write8(padapter, REG_MCUFWDL, tmp & 0xfe);
44 /* Reserved for fw extension. */
45 rtw_write8(padapter, REG_MCUFWDL + 1, 0x00);
49 static int _BlockWrite(struct rtw_adapter *padapter, void *buffer, u32 buffSize)
52 /* (Default) Phase #1 : PCI muse use 4-byte write to download FW */
54 /* Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
56 /* Phase #3 : Use 1-byte, the remnant of FW image. */
58 u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
59 u32 remainSize_p1 = 0, remainSize_p2 = 0;
60 u8 *bufferPtr = (u8 *) buffer;
61 u32 i = 0, offset = 0;
66 blockCount_p1 = buffSize / blockSize_p1;
67 remainSize_p1 = buffSize % blockSize_p1;
70 RT_TRACE(_module_hal_init_c_, _drv_notice_,
71 ("_BlockWrite: [P1] buffSize(%d) blockSize_p1(%d) "
72 "blockCount_p1(%d) remainSize_p1(%d)\n",
73 buffSize, blockSize_p1, blockCount_p1,
77 for (i = 0; i < blockCount_p1; i++) {
78 ret = rtw_writeN(padapter,
79 (FW_8723A_START_ADDRESS + i * blockSize_p1),
80 blockSize_p1, (bufferPtr + i * blockSize_p1));
87 offset = blockCount_p1 * blockSize_p1;
89 blockCount_p2 = remainSize_p1 / blockSize_p2;
90 remainSize_p2 = remainSize_p1 % blockSize_p2;
93 RT_TRACE(_module_hal_init_c_, _drv_notice_,
94 ("_BlockWrite: [P2] buffSize_p2(%d) "
95 "blockSize_p2(%d) blockCount_p2(%d) "
96 "remainSize_p2(%d)\n",
97 (buffSize - offset), blockSize_p2,
98 blockCount_p2, remainSize_p2));
101 for (i = 0; i < blockCount_p2; i++) {
102 ret = rtw_writeN(padapter,
103 (FW_8723A_START_ADDRESS + offset +
104 i * blockSize_p2), blockSize_p2,
105 (bufferPtr + offset +
115 offset = (blockCount_p1 * blockSize_p1) +
116 (blockCount_p2 * blockSize_p2);
118 blockCount_p3 = remainSize_p2 / blockSize_p3;
120 RT_TRACE(_module_hal_init_c_, _drv_notice_,
121 ("_BlockWrite: [P3] buffSize_p3(%d) blockSize_p3(%d) "
122 "blockCount_p3(%d)\n",
123 (buffSize - offset), blockSize_p3, blockCount_p3));
125 for (i = 0; i < blockCount_p3; i++) {
126 ret = rtw_write8(padapter,
127 (FW_8723A_START_ADDRESS + offset + i),
128 *(bufferPtr + offset + i));
140 _PageWrite(struct rtw_adapter *padapter, u32 page, void *buffer, u32 size)
143 u8 u8Page = (u8) (page & 0x07);
145 value8 = (rtw_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page;
146 rtw_write8(padapter, REG_MCUFWDL + 2, value8);
148 return _BlockWrite(padapter, buffer, size);
151 static int _WriteFW(struct rtw_adapter *padapter, void *buffer, u32 size)
153 /* Since we need dynamic decide method of dwonload fw, so we
154 call this function to get chip version. */
155 /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
157 u32 pageNums, remainSize;
159 u8 *bufferPtr = (u8 *) buffer;
161 pageNums = size / MAX_PAGE_SIZE;
162 /* RT_ASSERT((pageNums <= 4),
163 ("Page numbers should not greater then 4 \n")); */
164 remainSize = size % MAX_PAGE_SIZE;
166 for (page = 0; page < pageNums; page++) {
167 offset = page * MAX_PAGE_SIZE;
168 ret = _PageWrite(padapter, page, bufferPtr + offset,
175 offset = pageNums * MAX_PAGE_SIZE;
177 ret = _PageWrite(padapter, page, bufferPtr + offset,
183 RT_TRACE(_module_hal_init_c_, _drv_info_,
184 ("_WriteFW Done- for Normal chip.\n"));
190 static s32 _FWFreeToGo(struct rtw_adapter *padapter)
195 /* polling CheckSum report */
197 value32 = rtw_read32(padapter, REG_MCUFWDL);
198 if (value32 & FWDL_ChkSum_rpt)
200 } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
202 if (counter >= POLLING_READY_TIMEOUT_COUNT) {
203 RT_TRACE(_module_hal_init_c_, _drv_err_,
204 ("%s: chksum report fail! REG_MCUFWDL:0x%08x\n",
208 RT_TRACE(_module_hal_init_c_, _drv_info_,
209 ("%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__,
212 value32 = rtw_read32(padapter, REG_MCUFWDL);
213 value32 |= MCUFWDL_RDY;
214 value32 &= ~WINTINI_RDY;
215 rtw_write32(padapter, REG_MCUFWDL, value32);
217 /* polling for FW ready */
220 value32 = rtw_read32(padapter, REG_MCUFWDL);
221 if (value32 & WINTINI_RDY) {
222 RT_TRACE(_module_hal_init_c_, _drv_info_,
223 ("%s: Polling FW ready success!! "
224 "REG_MCUFWDL:0x%08x\n",
229 } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
231 RT_TRACE(_module_hal_init_c_, _drv_err_,
232 ("%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
237 #define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
239 void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter)
241 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
245 if (!(IS_FW_81xxC(padapter) &&
246 ((pHalData->FirmwareVersion < 0x21) ||
247 (pHalData->FirmwareVersion == 0x21 &&
248 pHalData->FirmwareSubVersion < 0x01)))) {
249 /* after 88C Fw v33.1 */
250 /* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */
251 rtw_write8(padapter, REG_HMETFR + 3, 0x20);
253 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
254 while (u1bTmp & BIT2) {
259 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
261 RT_TRACE(_module_hal_init_c_, _drv_info_,
262 ("-%s: 8051 reset success (%d)\n", __func__,
266 /* force firmware reset */
267 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
268 rtw_write8(padapter, REG_SYS_FUNC_EN + 1,
276 /* Download 8192C firmware code. */
279 s32 rtl8723a_FirmwareDownload(struct rtw_adapter *padapter)
281 s32 rtStatus = _SUCCESS;
282 u8 writeFW_retry = 0;
283 unsigned long fwdl_start_time;
284 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
285 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
286 struct device *device = dvobj_to_dev(dvobj);
287 struct rt_8723a_firmware_hdr *pFwHdr = NULL;
288 const struct firmware *fw;
290 u8 *firmware_buf = NULL;
293 static int log_version;
295 RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__));
297 if (IS_8723A_A_CUT(pHalData->VersionID)) {
298 fw_name = "rtlwifi/rtl8723aufw.bin";
299 RT_TRACE(_module_hal_init_c_, _drv_info_,
300 ("rtl8723a_FirmwareDownload: R8723FwImageArray_UMC "
301 "for RTL8723A A CUT\n"));
302 } else if (IS_8723A_B_CUT(pHalData->VersionID)) {
304 if (padapter->registrypriv.wifi_spec == 1) {
305 fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
306 DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithoutBT for "
309 #ifdef CONFIG_8723AU_BT_COEXIST
310 fw_name = "rtlwifi/rtl8723aufw_B.bin";
311 DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithBT for "
314 fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
315 DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithoutBT for "
320 /* <Roger_TODO> We should download proper RAM Code here
321 to match the ROM code. */
322 RT_TRACE(_module_hal_init_c_, _drv_err_,
323 ("%s: unknow version!\n", __func__));
328 pr_info("rtl8723au: Loading firmware %s\n", fw_name);
329 if (request_firmware(&fw, fw_name, device)) {
330 pr_err("rtl8723au: request_firmware load failed\n");
335 pr_err("rtl8723au: Firmware %s not available\n", fw_name);
339 firmware_buf = kzalloc(fw->size, GFP_KERNEL);
344 memcpy(firmware_buf, fw->data, fw->size);
347 release_firmware(fw);
349 /* To Check Fw header. Added by tynli. 2009.12.04. */
350 pFwHdr = (struct rt_8723a_firmware_hdr *)firmware_buf;
352 pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->Version);
353 pHalData->FirmwareSubVersion = pFwHdr->Subversion;
354 pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature);
356 DBG_8723A("%s: fw_ver =%d fw_subver =%d sig = 0x%x\n",
357 __func__, pHalData->FirmwareVersion,
358 pHalData->FirmwareSubVersion, pHalData->FirmwareSignature);
361 pr_info("%sFirmware Version %d, SubVersion %d, Signature "
362 "0x%x\n", DRIVER_PREFIX, pHalData->FirmwareVersion,
363 pHalData->FirmwareSubVersion,
364 pHalData->FirmwareSignature);
366 if (IS_FW_HEADER_EXIST(pFwHdr)) {
367 /* Shift 32 bytes for FW header */
369 fw_size = fw_size - 32;
372 /* Suggested by Filen. If 8051 is running in RAM code, driver should
373 inform Fw to reset by itself, */
374 /* or it will cause download Fw fail. 2010.02.01. by tynli. */
375 if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) {
377 rtl8723a_FirmwareSelfReset(padapter);
378 rtw_write8(padapter, REG_MCUFWDL, 0x00);
381 _FWDownloadEnable(padapter, true);
382 fwdl_start_time = jiffies;
384 /* reset the FWDL chksum */
385 rtw_write8(padapter, REG_MCUFWDL,
386 rtw_read8(padapter, REG_MCUFWDL) | FWDL_ChkSum_rpt);
388 rtStatus = _WriteFW(padapter, buf, fw_size);
390 if (rtStatus == _SUCCESS ||
391 (jiffies_to_msecs(jiffies - fwdl_start_time) > 500 &&
392 writeFW_retry++ >= 3))
395 DBG_8723A("%s writeFW_retry:%u, time after fwdl_start_time:"
396 "%ums\n", __func__, writeFW_retry,
397 jiffies_to_msecs(jiffies - fwdl_start_time));
399 _FWDownloadEnable(padapter, false);
400 if (_SUCCESS != rtStatus) {
401 DBG_8723A("DL Firmware failed!\n");
405 rtStatus = _FWFreeToGo(padapter);
406 if (_SUCCESS != rtStatus) {
407 RT_TRACE(_module_hal_init_c_, _drv_err_,
408 ("DL Firmware failed!\n"));
411 RT_TRACE(_module_hal_init_c_, _drv_info_,
412 ("Firmware is ready to run!\n"));
419 void rtl8723a_InitializeFirmwareVars(struct rtw_adapter *padapter)
421 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
423 /* Init Fw LPS related. */
424 padapter->pwrctrlpriv.bFwCurrentInPSMode = false;
426 /* Init H2C counter. by tynli. 2009.12.09. */
427 pHalData->LastHMEBoxNum = 0;
430 static void rtl8723a_free_hal_data(struct rtw_adapter *padapter)
433 kfree(padapter->HalData);
434 padapter->HalData = NULL;
439 /* Efuse related code */
442 hal_EfuseSwitchToBank(struct rtw_adapter *padapter, u8 bank)
447 DBG_8723A("%s: Efuse switch bank to %d\n", __func__, bank);
448 value32 = rtw_read32(padapter, EFUSE_TEST);
452 value32 = (value32 & ~EFUSE_SEL_MASK) |
453 EFUSE_SEL(EFUSE_WIFI_SEL_0);
456 value32 = (value32 & ~EFUSE_SEL_MASK) |
457 EFUSE_SEL(EFUSE_BT_SEL_0);
460 value32 = (value32 & ~EFUSE_SEL_MASK) |
461 EFUSE_SEL(EFUSE_BT_SEL_1);
464 value32 = (value32 & ~EFUSE_SEL_MASK) |
465 EFUSE_SEL(EFUSE_BT_SEL_2);
468 value32 = (value32 & ~EFUSE_SEL_MASK) |
469 EFUSE_SEL(EFUSE_WIFI_SEL_0);
473 rtw_write32(padapter, EFUSE_TEST, value32);
479 Hal_GetEfuseDefinition(struct rtw_adapter *padapter,
480 u8 efuseType, u8 type, void *pOut)
487 case TYPE_EFUSE_MAX_SECTION:
488 pMax_section = (u8 *) pOut;
490 if (efuseType == EFUSE_WIFI)
491 *pMax_section = EFUSE_MAX_SECTION_8723A;
493 *pMax_section = EFUSE_BT_MAX_SECTION;
496 case TYPE_EFUSE_REAL_CONTENT_LEN:
497 pu2Tmp = (u16 *) pOut;
499 if (efuseType == EFUSE_WIFI)
500 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
502 *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
505 case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
506 pu2Tmp = (u16 *) pOut;
508 if (efuseType == EFUSE_WIFI)
509 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
510 EFUSE_OOB_PROTECT_BYTES);
512 *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN -
513 EFUSE_PROTECT_BYTES_BANK);
516 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
517 pu2Tmp = (u16 *) pOut;
519 if (efuseType == EFUSE_WIFI)
520 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
521 EFUSE_OOB_PROTECT_BYTES);
523 *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN -
524 (EFUSE_PROTECT_BYTES_BANK * 3));
527 case TYPE_EFUSE_MAP_LEN:
528 pu2Tmp = (u16 *) pOut;
530 if (efuseType == EFUSE_WIFI)
531 *pu2Tmp = EFUSE_MAP_LEN_8723A;
533 *pu2Tmp = EFUSE_BT_MAP_LEN;
536 case TYPE_EFUSE_PROTECT_BYTES_BANK:
537 pu1Tmp = (u8 *) pOut;
539 if (efuseType == EFUSE_WIFI)
540 *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
542 *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
545 case TYPE_EFUSE_CONTENT_LEN_BANK:
546 pu2Tmp = (u16 *) pOut;
548 if (efuseType == EFUSE_WIFI)
549 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
551 *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
555 pu1Tmp = (u8 *) pOut;
561 #define VOLTAGE_V25 0x03
562 #define LDOE25_SHIFT 28
565 Hal_EfusePowerSwitch(struct rtw_adapter *padapter, u8 bWrite, u8 PwrState)
570 if (PwrState == true) {
571 rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
573 /* 1.2V Power: From VDDON with Power
574 Cut(0x0000h[15]), defualt valid */
575 tmpV16 = rtw_read16(padapter, REG_SYS_ISO_CTRL);
576 if (!(tmpV16 & PWC_EV12V)) {
578 rtw_write16(padapter, REG_SYS_ISO_CTRL, tmpV16);
580 /* Reset: 0x0000h[28], default valid */
581 tmpV16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
582 if (!(tmpV16 & FEN_ELDR)) {
584 rtw_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
587 /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock
588 from ANA, default valid */
589 tmpV16 = rtw_read16(padapter, REG_SYS_CLKR);
590 if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
591 tmpV16 |= (LOADER_CLK_EN | ANA8M);
592 rtw_write16(padapter, REG_SYS_CLKR, tmpV16);
595 if (bWrite == true) {
596 /* Enable LDO 2.5V before read/write action */
597 tempval = rtw_read8(padapter, EFUSE_TEST + 3);
599 tempval |= (VOLTAGE_V25 << 4);
600 rtw_write8(padapter, EFUSE_TEST + 3, (tempval | 0x80));
603 rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
605 if (bWrite == true) {
606 /* Disable LDO 2.5V after read/write action */
607 tempval = rtw_read8(padapter, EFUSE_TEST + 3);
608 rtw_write8(padapter, EFUSE_TEST + 3, (tempval & 0x7F));
614 hal_ReadEFuse_WiFi(struct rtw_adapter *padapter,
615 u16 _offset, u16 _size_byte, u8 *pbuf)
620 u8 efuseHeader, efuseExtHdr, efuseData;
623 /* Do NOT excess total size of EFuse table.
624 Added by Roger, 2008.11.10. */
625 if ((_offset + _size_byte) > EFUSE_MAP_LEN_8723A) {
626 DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
627 __func__, _offset, _size_byte);
631 efuseTbl = (u8 *) kmalloc(EFUSE_MAP_LEN_8723A, GFP_KERNEL);
632 if (efuseTbl == NULL) {
633 DBG_8723A("%s: alloc efuseTbl fail!\n", __func__);
636 /* 0xff will be efuse default value instead of 0x00. */
637 memset(efuseTbl, 0xFF, EFUSE_MAP_LEN_8723A);
639 /* switch bank back to bank 0 for later BT and wifi use. */
640 hal_EfuseSwitchToBank(padapter, 0);
642 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
643 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
644 if (efuseHeader == 0xFF) {
645 DBG_8723A("%s: data end at address =%#x\n", __func__,
650 /* Check PG header for section num. */
651 if (EXT_HEADER(efuseHeader)) { /* extended header */
652 offset = GET_HDR_OFFSET_2_0(efuseHeader);
654 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseExtHdr);
655 if (ALL_WORDS_DISABLED(efuseExtHdr)) {
659 offset |= ((efuseExtHdr & 0xF0) >> 1);
660 wden = (efuseExtHdr & 0x0F);
662 offset = ((efuseHeader >> 4) & 0x0f);
663 wden = (efuseHeader & 0x0f);
666 if (offset < EFUSE_MAX_SECTION_8723A) {
668 /* Get word enable value from PG header */
670 addr = offset * PGPKT_DATA_SIZE;
671 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
672 /* Check word enable condition in the section */
673 if (!(wden & (0x01 << i))) {
674 ReadEFuseByte23a(padapter, eFuse_Addr++,
676 efuseTbl[addr] = efuseData;
678 ReadEFuseByte23a(padapter, eFuse_Addr++,
680 efuseTbl[addr + 1] = efuseData;
685 DBG_8723A(KERN_ERR "%s: offset(%d) is illegal!!\n",
687 eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
691 /* Copy from Efuse map to output pointer memory!!! */
692 for (i = 0; i < _size_byte; i++)
693 pbuf[i] = efuseTbl[_offset + i];
695 /* Calculate Efuse utilization */
696 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
697 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
698 used = eFuse_Addr - 1;
699 rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&used);
705 hal_ReadEFuse_BT(struct rtw_adapter *padapter,
706 u16 _offset, u16 _size_byte, u8 *pbuf)
711 u8 efuseHeader, efuseExtHdr, efuseData;
715 /* Do NOT excess total size of EFuse table.
716 Added by Roger, 2008.11.10. */
717 if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN) {
718 DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
719 __func__, _offset, _size_byte);
723 efuseTbl = kmalloc(EFUSE_BT_MAP_LEN, GFP_KERNEL);
724 if (efuseTbl == NULL) {
725 DBG_8723A("%s: efuseTbl malloc fail!\n", __func__);
728 /* 0xff will be efuse default value instead of 0x00. */
729 memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
731 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
732 TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total);
734 for (bank = 1; bank < EFUSE_MAX_BANK; bank++) {
735 if (hal_EfuseSwitchToBank(padapter, bank) == false) {
736 DBG_8723A("%s: hal_EfuseSwitchToBank Fail!!\n",
743 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
744 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
745 if (efuseHeader == 0xFF)
748 /* Check PG header for section num. */
749 if (EXT_HEADER(efuseHeader)) { /* extended header */
750 offset = GET_HDR_OFFSET_2_0(efuseHeader);
752 ReadEFuseByte23a(padapter, eFuse_Addr++,
754 if (ALL_WORDS_DISABLED(efuseExtHdr)) {
758 offset |= ((efuseExtHdr & 0xF0) >> 1);
759 wden = (efuseExtHdr & 0x0F);
761 offset = ((efuseHeader >> 4) & 0x0f);
762 wden = (efuseHeader & 0x0f);
765 if (offset < EFUSE_BT_MAX_SECTION) {
768 /* Get word enable value from PG header */
770 addr = offset * PGPKT_DATA_SIZE;
771 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
772 /* Check word enable condition in
774 if (!(wden & (0x01 << i))) {
775 ReadEFuseByte23a(padapter,
778 efuseTbl[addr] = efuseData;
780 ReadEFuseByte23a(padapter,
783 efuseTbl[addr + 1] = efuseData;
789 "%s: offset(%d) is illegal!!\n",
791 eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
795 if ((eFuse_Addr - 1) < total) {
796 DBG_8723A("%s: bank(%d) data end at %#x\n",
797 __func__, bank, eFuse_Addr - 1);
802 /* switch bank back to bank 0 for later BT and wifi use. */
803 hal_EfuseSwitchToBank(padapter, 0);
805 /* Copy from Efuse map to output pointer memory!!! */
806 for (i = 0; i < _size_byte; i++)
807 pbuf[i] = efuseTbl[_offset + i];
810 /* Calculate Efuse utilization. */
812 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
813 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
814 used = (EFUSE_BT_REAL_BANK_CONTENT_LEN * (bank - 1)) + eFuse_Addr - 1;
815 rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *) &used);
822 Hal_ReadEFuse(struct rtw_adapter *padapter,
823 u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
825 if (efuseType == EFUSE_WIFI)
826 hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf);
828 hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf);
832 hal_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter)
835 u8 hoffset = 0, hworden = 0;
836 u8 efuse_data, word_cnts = 0;
838 rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *) &efuse_addr);
840 DBG_8723A("%s: start_efuse_addr = 0x%X\n", __func__, efuse_addr);
842 /* switch bank back to bank 0 for later BT and wifi use. */
843 hal_EfuseSwitchToBank(padapter, 0);
845 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
846 if (efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data) ==
848 DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail! "
849 "addr = 0x%X !!\n", __func__, efuse_addr);
853 if (efuse_data == 0xFF)
856 if (EXT_HEADER(efuse_data)) {
857 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
859 efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data);
860 if (ALL_WORDS_DISABLED(efuse_data)) {
864 hoffset |= ((efuse_data & 0xF0) >> 1);
865 hworden = efuse_data & 0x0F;
867 hoffset = (efuse_data >> 4) & 0x0F;
868 hworden = efuse_data & 0x0F;
871 word_cnts = Efuse_CalculateWordCnts23a(hworden);
872 efuse_addr += (word_cnts * 2) + 1;
875 rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BYTES, (u8 *) &efuse_addr);
877 DBG_8723A("%s: CurrentSize =%d\n", __func__, efuse_addr);
883 hal_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter)
888 u8 hoffset = 0, hworden = 0;
889 u8 efuse_data, word_cnts = 0;
892 rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *) &btusedbytes);
894 efuse_addr = (u16) ((btusedbytes % EFUSE_BT_REAL_BANK_CONTENT_LEN));
895 startBank = (u8) (1 + (btusedbytes / EFUSE_BT_REAL_BANK_CONTENT_LEN));
897 DBG_8723A("%s: start from bank =%d addr = 0x%X\n", __func__, startBank,
900 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
901 TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2);
903 for (bank = startBank; bank < EFUSE_MAX_BANK; bank++) {
904 if (hal_EfuseSwitchToBank(padapter, bank) == false) {
905 DBG_8723A(KERN_ERR "%s: switch bank(%d) Fail!!\n",
907 bank = EFUSE_MAX_BANK;
911 /* only when bank is switched we have to reset
913 if (bank != startBank)
916 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
917 if (efuse_OneByteRead23a(padapter, efuse_addr,
918 &efuse_data) == false) {
919 DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail!"
921 __func__, efuse_addr);
922 bank = EFUSE_MAX_BANK;
926 if (efuse_data == 0xFF)
929 if (EXT_HEADER(efuse_data)) {
930 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
932 efuse_OneByteRead23a(padapter, efuse_addr,
934 if (ALL_WORDS_DISABLED(efuse_data)) {
939 hoffset |= ((efuse_data & 0xF0) >> 1);
940 hworden = efuse_data & 0x0F;
942 hoffset = (efuse_data >> 4) & 0x0F;
943 hworden = efuse_data & 0x0F;
945 word_cnts = Efuse_CalculateWordCnts23a(hworden);
946 /* read next header */
947 efuse_addr += (word_cnts * 2) + 1;
950 /* Check if we need to check next bank efuse */
951 if (efuse_addr < retU2) {
952 break; /* don't need to check next bank. */
956 retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr;
957 rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&retU2);
959 DBG_8723A("%s: CurrentSize =%d\n", __func__, retU2);
964 Hal_EfuseGetCurrentSize(struct rtw_adapter *pAdapter, u8 efuseType)
968 if (efuseType == EFUSE_WIFI)
969 ret = hal_EfuseGetCurrentSize_WiFi(pAdapter);
971 ret = hal_EfuseGetCurrentSize_BT(pAdapter);
977 Hal_EfuseWordEnableDataWrite(struct rtw_adapter *padapter,
978 u16 efuse_addr, u8 word_en, u8 *data)
981 u16 start_addr = efuse_addr;
983 u8 tmpdata[PGPKT_DATA_SIZE];
985 memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
987 if (!(word_en & BIT(0))) {
988 tmpaddr = start_addr;
989 efuse_OneByteWrite23a(padapter, start_addr++, data[0]);
990 efuse_OneByteWrite23a(padapter, start_addr++, data[1]);
992 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[0]);
993 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[1]);
994 if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) {
995 badworden &= (~BIT(0));
998 if (!(word_en & BIT(1))) {
999 tmpaddr = start_addr;
1000 efuse_OneByteWrite23a(padapter, start_addr++, data[2]);
1001 efuse_OneByteWrite23a(padapter, start_addr++, data[3]);
1003 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[2]);
1004 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[3]);
1005 if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) {
1006 badworden &= (~BIT(1));
1009 if (!(word_en & BIT(2))) {
1010 tmpaddr = start_addr;
1011 efuse_OneByteWrite23a(padapter, start_addr++, data[4]);
1012 efuse_OneByteWrite23a(padapter, start_addr++, data[5]);
1014 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[4]);
1015 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[5]);
1016 if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) {
1017 badworden &= (~BIT(2));
1020 if (!(word_en & BIT(3))) {
1021 tmpaddr = start_addr;
1022 efuse_OneByteWrite23a(padapter, start_addr++, data[6]);
1023 efuse_OneByteWrite23a(padapter, start_addr++, data[7]);
1025 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[6]);
1026 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[7]);
1027 if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) {
1028 badworden &= (~BIT(3));
1036 Hal_EfusePgPacketRead(struct rtw_adapter *padapter, u8 offset, u8 *data)
1038 u8 efuse_data, word_cnts = 0;
1040 u8 hoffset = 0, hworden = 0;
1048 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION,
1050 if (offset > max_section) {
1051 DBG_8723A("%s: Packet offset(%d) is illegal(>%d)!\n",
1052 __func__, offset, max_section);
1056 memset(data, 0xFF, PGPKT_DATA_SIZE);
1060 /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the
1061 end of Efuse by CP. */
1062 /* Skip dummy parts to prevent unexpected data read from Efuse. */
1063 /* By pass right now. 2009.02.19. */
1065 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1066 if (efuse_OneByteRead23a(padapter, efuse_addr++, &efuse_data) ==
1072 if (efuse_data == 0xFF)
1075 if (EXT_HEADER(efuse_data)) {
1076 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
1077 efuse_OneByteRead23a(padapter, efuse_addr++, &efuse_data);
1078 if (ALL_WORDS_DISABLED(efuse_data)) {
1079 DBG_8723A("%s: Error!! All words disabled!\n",
1084 hoffset |= ((efuse_data & 0xF0) >> 1);
1085 hworden = efuse_data & 0x0F;
1087 hoffset = (efuse_data >> 4) & 0x0F;
1088 hworden = efuse_data & 0x0F;
1091 if (hoffset == offset) {
1092 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
1093 /* Check word enable condition in the section */
1094 if (!(hworden & (0x01 << i))) {
1095 ReadEFuseByte23a(padapter, efuse_addr++,
1097 data[i * 2] = efuse_data;
1099 ReadEFuseByte23a(padapter, efuse_addr++,
1101 data[(i * 2) + 1] = efuse_data;
1105 word_cnts = Efuse_CalculateWordCnts23a(hworden);
1106 efuse_addr += word_cnts * 2;
1114 hal_EfusePgCheckAvailableAddr(struct rtw_adapter *pAdapter, u8 efuseType)
1116 u16 max_available = 0;
1119 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
1120 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
1123 current_size = Efuse_GetCurrentSize23a(pAdapter, efuseType);
1124 if (current_size >= max_available) {
1125 DBG_8723A("%s: Error!! current_size(%d)>max_available(%d)\n",
1126 __func__, current_size, max_available);
1133 hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData,
1134 struct pg_pkt_struct *pTargetPkt)
1136 memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
1137 pTargetPkt->offset = offset;
1138 pTargetPkt->word_en = word_en;
1139 efuse_WordEnableDataRead23a(word_en, pData, pTargetPkt->data);
1140 pTargetPkt->word_cnts = Efuse_CalculateWordCnts23a(pTargetPkt->word_en);
1144 hal_EfusePartialWriteCheck(struct rtw_adapter *padapter, u8 efuseType,
1145 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1148 u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
1151 EFUSE_GetEfuseDefinition23a(padapter, efuseType,
1152 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
1153 &efuse_max_available_len);
1154 EFUSE_GetEfuseDefinition23a(padapter, efuseType,
1155 TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max);
1157 if (efuseType == EFUSE_WIFI) {
1158 rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES,
1161 rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES,
1164 startAddr %= efuse_max;
1167 if (startAddr >= efuse_max_available_len) {
1169 DBG_8723A("%s: startAddr(%d) >= efuse_max_available_"
1170 "len(%d)\n", __func__, startAddr,
1171 efuse_max_available_len);
1175 if (efuse_OneByteRead23a(padapter, startAddr, &efuse_data) &&
1176 (efuse_data != 0xFF)) {
1178 DBG_8723A("%s: Something Wrong! last bytes(%#X = 0x%02X) "
1179 "is not 0xFF\n", __func__,
1180 startAddr, efuse_data);
1183 /* not used header, 0xff */
1194 hal_EfusePgPacketWrite1ByteHeader(struct rtw_adapter *pAdapter, u8 efuseType,
1195 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1197 u8 pg_header = 0, tmp_header = 0;
1198 u16 efuse_addr = *pAddr;
1201 pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
1204 efuse_OneByteWrite23a(pAdapter, efuse_addr, pg_header);
1205 efuse_OneByteRead23a(pAdapter, efuse_addr, &tmp_header);
1206 if (tmp_header != 0xFF)
1208 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1209 DBG_8723A("%s: Repeat over limit for pg_header!!\n",
1215 if (tmp_header != pg_header) {
1216 DBG_8723A(KERN_ERR "%s: PG Header Fail!!(pg = 0x%02X "
1217 "read = 0x%02X)\n", __func__,
1218 pg_header, tmp_header);
1222 *pAddr = efuse_addr;
1228 hal_EfusePgPacketWrite2ByteHeader(struct rtw_adapter *padapter, u8 efuseType,
1229 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1231 u16 efuse_addr, efuse_max_available_len = 0;
1232 u8 pg_header = 0, tmp_header = 0;
1235 EFUSE_GetEfuseDefinition23a(padapter, efuseType,
1236 TYPE_AVAILABLE_EFUSE_BYTES_BANK,
1237 &efuse_max_available_len);
1239 efuse_addr = *pAddr;
1240 if (efuse_addr >= efuse_max_available_len) {
1241 DBG_8723A("%s: addr(%d) over avaliable(%d)!!\n", __func__,
1242 efuse_addr, efuse_max_available_len);
1246 pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
1249 efuse_OneByteWrite23a(padapter, efuse_addr, pg_header);
1250 efuse_OneByteRead23a(padapter, efuse_addr, &tmp_header);
1251 if (tmp_header != 0xFF)
1253 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1254 DBG_8723A("%s: Repeat over limit for pg_header!!\n",
1260 if (tmp_header != pg_header) {
1262 "%s: PG Header Fail!!(pg = 0x%02X read = 0x%02X)\n",
1263 __func__, pg_header, tmp_header);
1267 /* to write ext_header */
1269 pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
1272 efuse_OneByteWrite23a(padapter, efuse_addr, pg_header);
1273 efuse_OneByteRead23a(padapter, efuse_addr, &tmp_header);
1274 if (tmp_header != 0xFF)
1276 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1277 DBG_8723A("%s: Repeat over limit for ext_header!!\n",
1283 if (tmp_header != pg_header) { /* offset PG fail */
1285 "%s: PG EXT Header Fail!!(pg = 0x%02X read = 0x%02X)\n",
1286 __func__, pg_header, tmp_header);
1290 *pAddr = efuse_addr;
1296 hal_EfusePgPacketWriteHeader(struct rtw_adapter *padapter, u8 efuseType,
1297 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1301 if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) {
1302 bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType,
1305 bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType,
1313 hal_EfusePgPacketWriteData(struct rtw_adapter *pAdapter, u8 efuseType,
1314 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1319 efuse_addr = *pAddr;
1321 Efuse_WordEnableDataWrite23a(pAdapter, efuse_addr + 1,
1322 pTargetPkt->word_en, pTargetPkt->data);
1323 if (badworden != 0x0F) {
1324 DBG_8723A("%s: Fail!!\n", __func__);
1332 Hal_EfusePgPacketWrite(struct rtw_adapter *padapter,
1333 u8 offset, u8 word_en, u8 *pData)
1335 struct pg_pkt_struct targetPkt;
1337 u8 efuseType = EFUSE_WIFI;
1339 if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType))
1342 hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
1344 if (!hal_EfusePartialWriteCheck(padapter, efuseType,
1345 &startAddr, &targetPkt))
1348 if (!hal_EfusePgPacketWriteHeader(padapter, efuseType,
1349 &startAddr, &targetPkt))
1352 if (!hal_EfusePgPacketWriteData(padapter, efuseType,
1353 &startAddr, &targetPkt))
1360 Hal_EfusePgPacketWrite_BT(struct rtw_adapter *pAdapter,
1361 u8 offset, u8 word_en, u8 *pData)
1363 struct pg_pkt_struct targetPkt;
1365 u8 efuseType = EFUSE_BT;
1367 if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType))
1370 hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
1372 if (!hal_EfusePartialWriteCheck(pAdapter, efuseType,
1373 &startAddr, &targetPkt))
1376 if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType,
1377 &startAddr, &targetPkt))
1380 if (!hal_EfusePgPacketWriteData(pAdapter, efuseType,
1381 &startAddr, &targetPkt))
1387 static struct hal_version ReadChipVersion8723A(struct rtw_adapter *padapter)
1390 struct hal_version ChipVersion;
1391 struct hal_data_8723a *pHalData;
1393 pHalData = GET_HAL_DATA(padapter);
1395 value32 = rtw_read32(padapter, REG_SYS_CFG);
1396 ChipVersion.ICType = CHIP_8723A;
1397 ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
1398 ChipVersion.RFType = RF_TYPE_1T1R;
1399 ChipVersion.VendorType =
1400 ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
1401 ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
1403 /* For regulator mode. by tynli. 2011.01.14 */
1404 pHalData->RegulatorMode = ((value32 & SPS_SEL) ?
1405 RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
1407 value32 = rtw_read32(padapter, REG_GPIO_OUTSTS);
1408 /* ROM code version. */
1409 ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20);
1411 /* For multi-function consideration. Added by Roger, 2010.10.06. */
1412 pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
1413 value32 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
1414 pHalData->MultiFunc |=
1415 ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0);
1416 pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
1417 pHalData->MultiFunc |=
1418 ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
1419 pHalData->PolarityCtl =
1420 ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT :
1421 RT_POLARITY_LOW_ACT);
1422 dump_chip_info23a(ChipVersion);
1423 pHalData->VersionID = ChipVersion;
1425 if (IS_1T2R(ChipVersion))
1426 pHalData->rf_type = RF_1T2R;
1427 else if (IS_2T2R(ChipVersion))
1428 pHalData->rf_type = RF_2T2R;
1430 pHalData->rf_type = RF_1T1R;
1432 MSG_8723A("RF_Type is %x!!\n", pHalData->rf_type);
1437 static void rtl8723a_read_chip_version(struct rtw_adapter *padapter)
1439 ReadChipVersion8723A(padapter);
1444 /* 20100209 Joseph: */
1445 /* This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */
1446 /* We just reserve the value of the register in variable
1447 pHalData->RegBcnCtrlVal and then operate */
1448 /* the value of the register via atomic operation. */
1449 /* This prevents from race condition when setting this register. */
1450 /* The value of pHalData->RegBcnCtrlVal is initialized in
1451 HwConfigureRTL8192CE() function. */
1453 void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits)
1455 struct hal_data_8723a *pHalData;
1459 pHalData = GET_HAL_DATA(padapter);
1460 pRegBcnCtrlVal = (u8 *)&pHalData->RegBcnCtrlVal;
1462 addr = REG_BCN_CTRL;
1464 *pRegBcnCtrlVal = rtw_read8(padapter, addr);
1465 *pRegBcnCtrlVal |= SetBits;
1466 *pRegBcnCtrlVal &= ~ClearBits;
1468 rtw_write8(padapter, addr, *pRegBcnCtrlVal);
1471 void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter)
1473 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1475 rtw_write16(padapter, REG_BCN_CTRL, 0x1010);
1476 pHalData->RegBcnCtrlVal = 0x1010;
1478 /* TODO: Remove these magic number */
1479 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0x6404); /* ms */
1480 /* Firmware will control REG_DRVERLYINT when power saving is enable, */
1481 /* so don't set this register on STA mode. */
1482 if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false)
1483 rtw_write8(padapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
1485 rtw_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
1487 /* Suggested by designer timchen. Change beacon AIFS to the
1488 largest number beacause test chip does not contension before
1489 sending beacon. by tynli. 2009.11.03 */
1490 rtw_write16(padapter, REG_BCNTCFG, 0x660F);
1493 static void ResumeTxBeacon(struct rtw_adapter *padapter)
1495 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1497 /* 2010.03.01. Marked by tynli. No need to call workitem beacause
1498 we record the value */
1499 /* which should be read from register to a global variable. */
1501 RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+ResumeTxBeacon\n"));
1503 pHalData->RegFwHwTxQCtrl |= BIT(6);
1504 rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl);
1505 rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0xff);
1506 pHalData->RegReg542 |= BIT(0);
1507 rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
1510 static void StopTxBeacon(struct rtw_adapter *padapter)
1512 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1514 /* 2010.03.01. Marked by tynli. No need to call workitem beacause
1515 we record the value */
1516 /* which should be read from register to a global variable. */
1518 RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+StopTxBeacon\n"));
1520 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
1521 rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl);
1522 rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0x64);
1523 pHalData->RegReg542 &= ~BIT(0);
1524 rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
1526 CheckFwRsvdPageContent23a(padapter); /* 2010.06.23. Added by tynli. */
1529 static void _BeaconFunctionEnable(struct rtw_adapter *padapter, u8 Enable,
1532 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB,
1534 rtw_write8(padapter, REG_RD_CTRL + 1, 0x6F);
1537 static void rtl8723a_SetBeaconRelatedRegisters(struct rtw_adapter *padapter)
1540 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1541 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1543 /* reset TSF, enable update TSF, correcting TSF On Beacon */
1545 /* REG_BCN_INTERVAL */
1548 /* REG_TBTT_PROHIBIT */
1549 /* REG_DRVERLYINT */
1550 /* REG_BCN_MAX_ERR */
1551 /* REG_BCNTCFG (0x510) */
1552 /* REG_DUAL_TSF_RST */
1553 /* REG_BCN_CTRL (0x550) */
1558 rtw_write16(padapter, REG_ATIMWND, 2);
1561 /* Beacon interval (in unit of TU). */
1563 rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
1565 rtl8723a_InitBeaconParameters(padapter);
1567 rtw_write8(padapter, REG_SLOT, 0x09);
1570 /* Reset TSF Timer to zero, added by Roger. 2008.06.24 */
1572 value32 = rtw_read32(padapter, REG_TCR);
1574 rtw_write32(padapter, REG_TCR, value32);
1577 rtw_write32(padapter, REG_TCR, value32);
1579 /* NOTE: Fix test chip's bug (about contention windows's randomness) */
1580 if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE |
1581 WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE) == true) {
1582 rtw_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50);
1583 rtw_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50);
1586 _BeaconFunctionEnable(padapter, true, true);
1588 ResumeTxBeacon(padapter);
1589 SetBcnCtrlReg23a(padapter, DIS_BCNQ_SUB, 0);
1592 static void rtl8723a_GetHalODMVar(struct rtw_adapter *Adapter,
1593 enum hal_odm_variable eVariable,
1594 void *pValue1, bool bSet)
1596 switch (eVariable) {
1597 case HAL_ODM_STA_INFO:
1604 static void rtl8723a_SetHalODMVar(struct rtw_adapter *Adapter,
1605 enum hal_odm_variable eVariable,
1606 void *pValue1, bool bSet)
1608 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1609 struct dm_odm_t *podmpriv = &pHalData->odmpriv;
1610 switch (eVariable) {
1611 case HAL_ODM_STA_INFO:
1613 struct sta_info *psta = (struct sta_info *)pValue1;
1616 DBG_8723A("Set STA_(%d) info\n", psta->mac_id);
1617 ODM_CmnInfoPtrArrayHook23a(podmpriv,
1618 ODM_CMNINFO_STA_STATUS,
1619 psta->mac_id, psta);
1621 DBG_8723A("Clean STA_(%d) info\n", psta->mac_id);
1622 ODM_CmnInfoPtrArrayHook23a(podmpriv,
1623 ODM_CMNINFO_STA_STATUS,
1624 psta->mac_id, NULL);
1628 case HAL_ODM_P2P_STATE:
1629 ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet);
1631 case HAL_ODM_WIFI_DISPLAY_STATE:
1632 ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet);
1639 static void hal_notch_filter_8723a(struct rtw_adapter *adapter, bool enable)
1642 DBG_8723A("Enable notch filter\n");
1643 rtw_write8(adapter, rOFDM0_RxDSP + 1,
1644 rtw_read8(adapter, rOFDM0_RxDSP + 1) | BIT1);
1646 DBG_8723A("Disable notch filter\n");
1647 rtw_write8(adapter, rOFDM0_RxDSP + 1,
1648 rtw_read8(adapter, rOFDM0_RxDSP + 1) & ~BIT1);
1652 s32 c2h_id_filter_ccx_8723a(u8 id)
1655 if (id == C2H_CCX_TX_RPT)
1661 static s32 c2h_handler_8723a(struct rtw_adapter *padapter,
1662 struct c2h_evt_hdr *c2h_evt)
1667 if (c2h_evt == NULL) {
1668 DBG_8723A("%s c2h_evt is NULL\n", __func__);
1673 switch (c2h_evt->id) {
1675 RT_TRACE(_module_hal_init_c_, _drv_info_,
1676 ("C2HCommandHandler: %s\n", c2h_evt->payload));
1679 case C2H_CCX_TX_RPT:
1680 handle_txrpt_ccx_8723a(padapter, c2h_evt->payload);
1682 case C2H_EXT_RA_RPT:
1684 case C2H_HW_INFO_EXCH:
1685 RT_TRACE(_module_hal_init_c_, _drv_info_,
1686 ("[BT], C2H_HW_INFO_EXCH\n"));
1687 for (i = 0; i < c2h_evt->plen; i++) {
1688 RT_TRACE(_module_hal_init_c_, _drv_info_,
1689 ("[BT], tmpBuf[%d]= 0x%x\n", i,
1690 c2h_evt->payload[i]));
1694 case C2H_C2H_H2C_TEST:
1695 RT_TRACE(_module_hal_init_c_, _drv_info_,
1696 ("[BT], C2H_H2C_TEST\n"));
1697 RT_TRACE(_module_hal_init_c_, _drv_info_,
1698 ("[BT], tmpBuf[0]/[1]/[2]/[3]/[4]= 0x%x/ 0x%x/ "
1699 "0x%x/ 0x%x/ 0x%x\n", c2h_evt->payload[0],
1700 c2h_evt->payload[1], c2h_evt->payload[2],
1701 c2h_evt->payload[3], c2h_evt->payload[4]));
1704 #ifdef CONFIG_8723AU_BT_COEXIST
1706 DBG_8723A("%s , Got C2H_BT_INFO \n", __func__);
1707 BT_FwC2hBtInfo(padapter, c2h_evt->payload, c2h_evt->plen);
1720 void rtl8723a_set_hal_ops(struct hal_ops *pHalFunc)
1722 pHalFunc->free_hal_data = &rtl8723a_free_hal_data;
1724 pHalFunc->dm_init = &rtl8723a_init_dm_priv;
1725 pHalFunc->dm_deinit = &rtl8723a_deinit_dm_priv;
1727 pHalFunc->read_chip_version = &rtl8723a_read_chip_version;
1729 pHalFunc->set_bwmode_handler = &PHY_SetBWMode23a8723A;
1730 pHalFunc->set_channel_handler = &PHY_SwChnl8723A;
1732 pHalFunc->hal_dm_watchdog = &rtl8723a_HalDmWatchDog;
1734 pHalFunc->SetBeaconRelatedRegistersHandler =
1735 &rtl8723a_SetBeaconRelatedRegisters;
1737 pHalFunc->Add_RateATid = &rtl8723a_add_rateatid;
1738 pHalFunc->run_thread = &rtl8723a_start_thread;
1739 pHalFunc->cancel_thread = &rtl8723a_stop_thread;
1741 pHalFunc->read_bbreg = &PHY_QueryBBReg;
1742 pHalFunc->write_bbreg = &PHY_SetBBReg;
1743 pHalFunc->read_rfreg = &PHY_QueryRFReg;
1744 pHalFunc->write_rfreg = &PHY_SetRFReg;
1746 /* Efuse related function */
1747 pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch;
1748 pHalFunc->ReadEFuse = &Hal_ReadEFuse;
1749 pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition;
1750 pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize;
1751 pHalFunc->Efuse_PgPacketRead23a = &Hal_EfusePgPacketRead;
1752 pHalFunc->Efuse_PgPacketWrite23a = &Hal_EfusePgPacketWrite;
1753 pHalFunc->Efuse_WordEnableDataWrite23a = &Hal_EfuseWordEnableDataWrite;
1754 pHalFunc->Efuse_PgPacketWrite23a_BT = &Hal_EfusePgPacketWrite_BT;
1756 pHalFunc->sreset_init_value23a = &sreset_init_value23a;
1757 pHalFunc->sreset_reset_value23a = &sreset_reset_value23a;
1758 pHalFunc->silentreset = &sreset_reset;
1759 pHalFunc->sreset_xmit_status_check = &rtl8723a_sreset_xmit_status_check;
1760 pHalFunc->sreset_linked_status_check =
1761 &rtl8723a_sreset_linked_status_check;
1762 pHalFunc->sreset_get_wifi_status23a = &sreset_get_wifi_status23a;
1763 pHalFunc->sreset_inprogress = &sreset_inprogress;
1764 pHalFunc->GetHalODMVarHandler = &rtl8723a_GetHalODMVar;
1765 pHalFunc->SetHalODMVarHandler = &rtl8723a_SetHalODMVar;
1767 pHalFunc->hal_notch_filter = &hal_notch_filter_8723a;
1769 pHalFunc->c2h_handler = c2h_handler_8723a;
1770 pHalFunc->c2h_id_filter_ccx = c2h_id_filter_ccx_8723a;
1773 void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter)
1775 struct hal_data_8723a *pHalData;
1778 pHalData = GET_HAL_DATA(padapter);
1780 val = rtw_read8(padapter, REG_LEDCFG2);
1781 /* Let 8051 take control antenna settting */
1782 val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
1783 rtw_write8(padapter, REG_LEDCFG2, val);
1786 void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter)
1788 struct hal_data_8723a *pHalData;
1791 pHalData = GET_HAL_DATA(padapter);
1793 val = rtw_read8(padapter, REG_LEDCFG2);
1794 /* Let 8051 take control antenna settting */
1795 if (!(val & BIT(7))) {
1796 val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
1797 rtw_write8(padapter, REG_LEDCFG2, val);
1801 void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter)
1803 struct hal_data_8723a *pHalData;
1806 pHalData = GET_HAL_DATA(padapter);
1807 val = rtw_read8(padapter, REG_LEDCFG2);
1808 /* Let 8051 take control antenna settting */
1809 val &= ~BIT(7); /* DPDT_SEL_EN, clear 0x4C[23] */
1810 rtw_write8(padapter, REG_LEDCFG2, val);
1813 void rtl8723a_init_default_value(struct rtw_adapter *padapter)
1815 struct hal_data_8723a *pHalData;
1816 struct dm_priv *pdmpriv;
1819 pHalData = GET_HAL_DATA(padapter);
1820 pdmpriv = &pHalData->dmpriv;
1822 /* init default value */
1823 pHalData->fw_ractrl = false;
1824 pHalData->bIQKInitialized = false;
1825 if (!padapter->pwrctrlpriv.bkeepfwalive)
1826 pHalData->LastHMEBoxNum = 0;
1828 pHalData->bIQKInitialized = false;
1830 /* init dm default value */
1831 pdmpriv->TM_Trigger = 0; /* for IQK */
1832 /* pdmpriv->binitialized = false; */
1833 /* pdmpriv->prv_traffic_idx = 3; */
1834 /* pdmpriv->initialize = 0; */
1836 pdmpriv->ThermalValue_HP_index = 0;
1837 for (i = 0; i < HP_THERMAL_NUM; i++)
1838 pdmpriv->ThermalValue_HP[i] = 0;
1840 /* init Efuse variables */
1841 pHalData->EfuseUsedBytes = 0;
1842 pHalData->BTEfuseUsedBytes = 0;
1845 u8 GetEEPROMSize8723A(struct rtw_adapter *padapter)
1850 cr = rtw_read16(padapter, REG_9346CR);
1851 /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */
1852 size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
1854 MSG_8723A("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46");
1861 /* LLT R/W/Init function */
1864 static s32 _LLTWrite(struct rtw_adapter *padapter, u32 address, u32 data)
1866 s32 status = _SUCCESS;
1868 u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) |
1869 _LLT_OP(_LLT_WRITE_ACCESS);
1870 u16 LLTReg = REG_LLT_INIT;
1872 rtw_write32(padapter, LLTReg, value);
1876 value = rtw_read32(padapter, LLTReg);
1877 if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) {
1881 if (count > POLLING_LLT_THRESHOLD) {
1882 RT_TRACE(_module_hal_init_c_, _drv_err_,
1883 ("Failed to polling write LLT done at "
1884 "address %d!\n", address));
1893 s32 InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary)
1895 s32 status = _SUCCESS;
1897 u32 txpktbuf_bndy = boundary;
1898 u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;
1900 for (i = 0; i < (txpktbuf_bndy - 1); i++) {
1901 status = _LLTWrite(padapter, i, i + 1);
1902 if (_SUCCESS != status) {
1908 status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
1909 if (_SUCCESS != status) {
1913 /* Make the other pages as ring buffer */
1914 /* This ring buffer is used as beacon buffer if we config this
1915 MAC as two MAC transfer. */
1916 /* Otherwise used as local loopback buffer. */
1917 for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
1918 status = _LLTWrite(padapter, i, (i + 1));
1919 if (_SUCCESS != status) {
1924 /* Let last entry point to the start entry of ring buffer */
1925 status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
1926 if (_SUCCESS != status) {
1933 static void _DisableGPIO(struct rtw_adapter *padapter)
1935 /***************************************
1936 j. GPIO_PIN_CTRL 0x44[31:0]= 0x000
1937 k.Value = GPIO_PIN_CTRL[7:0]
1938 l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write external PIN level
1939 m. GPIO_MUXCFG 0x42 [15:0] = 0x0780
1940 n. LEDCFG 0x4C[15:0] = 0x8080
1941 ***************************************/
1945 /* 1. Disable GPIO[7:0] */
1946 rtw_write16(padapter, REG_GPIO_PIN_CTRL + 2, 0x0000);
1947 value32 = rtw_read32(padapter, REG_GPIO_PIN_CTRL) & 0xFFFF00FF;
1948 u4bTmp = value32 & 0x000000FF;
1949 value32 |= ((u4bTmp << 8) | 0x00FF0000);
1950 rtw_write32(padapter, REG_GPIO_PIN_CTRL, value32);
1953 /* <Roger_Notes> For RTL8723u multi-function configuration which
1954 was autoload from Efuse offset 0x0a and 0x0b, */
1955 /* WLAN HW GPIO[9], GPS HW GPIO[10] and BT HW GPIO[11]. */
1956 /* Added by Roger, 2010.10.07. */
1958 /* 2. Disable GPIO[8] and GPIO[12] */
1960 /* Configure all pins as input mode. */
1961 rtw_write16(padapter, REG_GPIO_IO_SEL_2, 0x0000);
1962 value32 = rtw_read32(padapter, REG_GPIO_PIN_CTRL_2) & 0xFFFF001F;
1963 u4bTmp = value32 & 0x0000001F;
1964 /* Set pin 8, 10, 11 and pin 12 to output mode. */
1965 value32 |= ((u4bTmp << 8) | 0x001D0000);
1966 rtw_write32(padapter, REG_GPIO_PIN_CTRL_2, value32);
1968 /* 3. Disable LED0 & 1 */
1969 rtw_write16(padapter, REG_LEDCFG0, 0x8080);
1970 } /* end of _DisableGPIO() */
1972 static void _DisableRFAFEAndResetBB8192C(struct rtw_adapter *padapter)
1974 /**************************************
1975 a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue
1976 b. RF path 0 offset 0x00 = 0x00 disable RF
1977 c. APSD_CTRL 0x600[7:0] = 0x40
1978 d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine
1979 e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine
1980 ***************************************/
1981 u8 eRFPath = 0, value8 = 0;
1983 rtw_write8(padapter, REG_TXPAUSE, 0xFF);
1985 PHY_SetRFReg(padapter, (enum RF_RADIO_PATH) eRFPath, 0x0, bMaskByte0, 0x0);
1988 rtw_write8(padapter, REG_APSD_CTRL, value8); /* 0x40 */
1990 /* Set BB reset at first */
1992 value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn);
1993 rtw_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x16 */
1995 /* Set global reset. */
1996 value8 &= ~FEN_BB_GLB_RSTn;
1997 rtw_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x14 */
1999 /* 2010/08/12 MH We need to set BB/GLBAL reset to save power
2002 /* RT_TRACE(COMP_INIT, DBG_LOUD, ("======> RF off and reset BB.\n")); */
2005 static void _DisableRFAFEAndResetBB(struct rtw_adapter *padapter)
2007 _DisableRFAFEAndResetBB8192C(padapter);
2010 static void _ResetDigitalProcedure1_92C(struct rtw_adapter *padapter,
2013 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2015 if (IS_FW_81xxC(padapter) && (pHalData->FirmwareVersion <= 0x20)) {
2016 /*****************************
2017 f. MCUFWDL 0x80[7:0]= 0 reset MCU ready status
2018 g. SYS_FUNC_EN 0x02[10]= 0 reset MCU register, (8051 reset)
2019 h. SYS_FUNC_EN 0x02[15-12]= 5 reset MAC register, DCORE
2020 i. SYS_FUNC_EN 0x02[10]= 1 enable MCU register,
2022 ******************************/
2024 rtw_write8(padapter, REG_MCUFWDL, 0);
2026 valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
2027 /* reset MCU , 8051 */
2028 rtw_write16(padapter, REG_SYS_FUNC_EN, (valu16 & (~FEN_CPUEN)));
2030 valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN) & 0x0FFF;
2031 rtw_write16(padapter, REG_SYS_FUNC_EN,
2032 (valu16 | (FEN_HWPDN | FEN_ELDR))); /* reset MAC */
2034 valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
2035 /* enable MCU , 8051 */
2036 rtw_write16(padapter, REG_SYS_FUNC_EN, (valu16 | FEN_CPUEN));
2040 /* 2010/08/12 MH For USB SS, we can not stop 8051 when we
2041 are trying to enter IPS/HW&SW radio off. For
2042 S3/S4/S5/Disable, we can stop 8051 because */
2043 /* we will init FW when power on again. */
2044 /* if (!pDevice->RegUsbSS) */
2045 /* If we want to SS mode, we can not reset 8051. */
2046 if (rtw_read8(padapter, REG_MCUFWDL) & BIT1) {
2047 /* IF fw in RAM code, do reset */
2048 if (padapter->bFWReady) {
2049 /* 2010/08/25 MH Accordign to RD alfred's
2050 suggestion, we need to disable other */
2051 /* HRCV INT to influence 8051 reset. */
2052 rtw_write8(padapter, REG_FWIMR, 0x20);
2053 /* 2011/02/15 MH According to Alex's
2054 suggestion, close mask to prevent
2055 incorrect FW write operation. */
2056 rtw_write8(padapter, REG_FTIMR, 0x00);
2057 rtw_write8(padapter, REG_FSIMR, 0x00);
2059 /* 8051 reset by self */
2060 rtw_write8(padapter, REG_HMETFR + 3, 0x20);
2062 while ((retry_cnts++ < 100) &&
2064 rtw_read16(padapter, REG_SYS_FUNC_EN))) {
2065 udelay(50); /* us */
2068 if (retry_cnts >= 100) {
2069 /* Reset MAC and Enable 8051 */
2070 rtw_write8(padapter,
2071 REG_SYS_FUNC_EN + 1, 0x50);
2076 /* Reset MAC and Enable 8051 */
2077 rtw_write8(padapter, REG_SYS_FUNC_EN + 1, 0x54);
2078 rtw_write8(padapter, REG_MCUFWDL, 0);
2082 /*****************************
2083 Without HW auto state machine
2084 g. SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock
2085 h. AFE_PLL_CTRL 0x28[7:0] = 0x80 disable AFE PLL
2086 i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F gated AFE DIG_CLOCK
2087 j. SYS_ISO_CTRL 0x00[7:0] = 0xF9 isolated digital to PON
2088 ******************************/
2089 /* modify to 0x70A3 by Scott. */
2090 rtw_write16(padapter, REG_SYS_CLKR, 0x70A3);
2091 rtw_write8(padapter, REG_AFE_PLL_CTRL, 0x80);
2092 rtw_write16(padapter, REG_AFE_XTAL_CTRL, 0x880F);
2093 rtw_write8(padapter, REG_SYS_ISO_CTRL, 0xF9);
2095 /* Disable all RF/BB power */
2096 rtw_write8(padapter, REG_RF_CTRL, 0x00);
2100 static void _ResetDigitalProcedure1(struct rtw_adapter *padapter,
2103 _ResetDigitalProcedure1_92C(padapter, bWithoutHWSM);
2106 static void _ResetDigitalProcedure2(struct rtw_adapter *padapter)
2108 /*****************************
2109 k. SYS_FUNC_EN 0x03[7:0] = 0x44 disable ELDR runction
2110 l. SYS_CLKR 0x08[15:0] = 0x3083 disable ELDR clock
2111 m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON
2112 ******************************/
2113 /* modify to 0x70a3 by Scott. */
2114 rtw_write16(padapter, REG_SYS_CLKR, 0x70a3);
2115 /* modify to 0x82 by Scott. */
2116 rtw_write8(padapter, REG_SYS_ISO_CTRL + 1, 0x82);
2119 static void _DisableAnalog(struct rtw_adapter *padapter, bool bWithoutHWSM)
2121 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2126 /*****************************
2127 n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power
2128 o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power
2129 r. When driver call disable, the ASIC will turn off remaining
2131 ******************************/
2133 rtw_write8(padapter, REG_LDOA15_CTRL, 0x04);
2134 /* rtw_write8(padapter, REG_LDOV12D_CTRL, 0x54); */
2136 value8 = rtw_read8(padapter, REG_LDOV12D_CTRL);
2137 value8 &= (~LDV12_EN);
2138 rtw_write8(padapter, REG_LDOV12D_CTRL, value8);
2139 /* RT_TRACE(COMP_INIT, DBG_LOUD,
2140 (" REG_LDOV12D_CTRL Reg0x21:0x%02x.\n", value8)); */
2143 /*****************************
2144 h. SPS0_CTRL 0x11[7:0] = 0x23 enter PFM mode
2145 i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend
2146 ******************************/
2148 if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID))
2151 rtw_write8(padapter, REG_SPS0_CTRL, value8);
2154 /* value16 |= (APDM_HOST | FSM_HSUS |/PFM_ALDN); */
2155 /* 2010/08/31 According to Filen description, we need to
2156 use HW to shut down 8051 automatically. */
2157 /* Becasue suspend operatione need the asistance of 8051
2159 value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
2161 value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
2164 rtw_write16(padapter, REG_APS_FSMCO, value16); /* 0x4802 */
2166 rtw_write8(padapter, REG_RSV_CTRL, 0x0e);
2169 /* HW Auto state machine */
2170 s32 CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU)
2172 int rtStatus = _SUCCESS;
2174 if (padapter->bSurpriseRemoved) {
2177 /* RF Off Sequence ==== */
2178 _DisableRFAFEAndResetBB(padapter);
2180 /* ==== Reset digital sequence ====== */
2181 _ResetDigitalProcedure1(padapter, false);
2183 /* ==== Pull GPIO PIN to balance level and LED control ====== */
2184 _DisableGPIO(padapter);
2186 /* ==== Disable analog sequence === */
2187 _DisableAnalog(padapter, false);
2189 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2190 ("======> Card disable finished.\n"));
2195 /* without HW Auto state machine */
2196 s32 CardDisableWithoutHWSM(struct rtw_adapter *padapter)
2198 s32 rtStatus = _SUCCESS;
2200 /* RT_TRACE(COMP_INIT, DBG_LOUD,
2201 ("======> Card Disable Without HWSM .\n")); */
2202 if (padapter->bSurpriseRemoved) {
2206 /* RF Off Sequence ==== */
2207 _DisableRFAFEAndResetBB(padapter);
2209 /* ==== Reset digital sequence ====== */
2210 _ResetDigitalProcedure1(padapter, true);
2212 /* ==== Pull GPIO PIN to balance level and LED control ====== */
2213 _DisableGPIO(padapter);
2215 /* ==== Reset digital sequence ====== */
2216 _ResetDigitalProcedure2(padapter);
2218 /* ==== Disable analog sequence === */
2219 _DisableAnalog(padapter, true);
2221 /* RT_TRACE(COMP_INIT, DBG_LOUD,
2222 ("<====== Card Disable Without HWSM .\n")); */
2226 void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent)
2228 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2230 if (false == pEEPROM->bautoload_fail_flag) { /* autoload OK. */
2231 if (!pEEPROM->EepromOrEfuse) {
2232 /* Read EFUSE real map to shadow. */
2233 EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
2234 memcpy((void *)PROMContent,
2235 (void *)pEEPROM->efuse_eeprom_data,
2238 } else { /* autoload fail */
2239 RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
2240 ("AutoLoad Fail reported from CR9346!!\n"));
2241 /* pHalData->AutoloadFailFlag = true; */
2242 /* update to default value 0xFF */
2243 if (false == pEEPROM->EepromOrEfuse)
2244 EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
2245 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data,
2250 void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo)
2252 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2253 /* struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); */
2256 /* Checl 0x8129 again for making sure autoload status!! */
2257 EEPROMId = le16_to_cpu(*((u16 *) hwinfo));
2258 if (EEPROMId != RTL_EEPROM_ID) {
2259 DBG_8723A("EEPROM ID(%#x) is invalid!!\n", EEPROMId);
2260 pEEPROM->bautoload_fail_flag = true;
2262 pEEPROM->bautoload_fail_flag = false;
2265 RT_TRACE(_module_hal_init_c_, _drv_info_,
2266 ("EEPROM ID = 0x%04x\n", EEPROMId));
2269 static void Hal_EEValueCheck(u8 EEType, void *pInValue, void *pOutValue)
2275 pIn = (u8 *) pInValue;
2276 pOut = (u8 *) pOutValue;
2277 if (*pIn >= 0 && *pIn <= 63) {
2280 RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
2281 ("EETYPE_TX_PWR, value =%d is invalid, set "
2282 "to default = 0x%x\n",
2283 *pIn, EEPROM_Default_TxPowerLevel));
2284 *pOut = EEPROM_Default_TxPowerLevel;
2294 Hal_ReadPowerValueFromPROM_8723A(struct txpowerinfo *pwrInfo,
2295 u8 *PROMContent, bool AutoLoadFail)
2297 u32 rfPath, eeAddr, group, rfPathMax = 1;
2299 memset(pwrInfo, 0, sizeof(*pwrInfo));
2302 for (group = 0; group < MAX_CHNL_GROUP; group++) {
2303 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2304 pwrInfo->CCKIndex[rfPath][group] =
2305 EEPROM_Default_TxPowerLevel;
2306 pwrInfo->HT40_1SIndex[rfPath][group] =
2307 EEPROM_Default_TxPowerLevel;
2308 pwrInfo->HT40_2SIndexDiff[rfPath][group] =
2309 EEPROM_Default_HT40_2SDiff;
2310 pwrInfo->HT20IndexDiff[rfPath][group] =
2311 EEPROM_Default_HT20_Diff;
2312 pwrInfo->OFDMIndexDiff[rfPath][group] =
2313 EEPROM_Default_LegacyHTTxPowerDiff;
2314 pwrInfo->HT40MaxOffset[rfPath][group] =
2315 EEPROM_Default_HT40_PwrMaxOffset;
2316 pwrInfo->HT20MaxOffset[rfPath][group] =
2317 EEPROM_Default_HT20_PwrMaxOffset;
2320 pwrInfo->TSSI_A[0] = EEPROM_Default_TSSI;
2324 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2325 for (group = 0; group < MAX_CHNL_GROUP; group++) {
2327 EEPROM_CCK_TX_PWR_INX_8723A + (rfPath * 3) + group;
2328 /* pwrInfo->CCKIndex[rfPath][group] =
2329 PROMContent[eeAddr]; */
2330 Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
2331 &pwrInfo->CCKIndex[rfPath][group]);
2332 eeAddr = EEPROM_HT40_1S_TX_PWR_INX_8723A +
2333 (rfPath * 3) + group;
2334 /* pwrInfo->HT40_1SIndex[rfPath][group] =
2335 PROMContent[eeAddr]; */
2336 Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
2337 &pwrInfo->HT40_1SIndex[rfPath][group]);
2341 for (group = 0; group < MAX_CHNL_GROUP; group++) {
2342 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2343 pwrInfo->HT40_2SIndexDiff[rfPath][group] = 0;
2344 pwrInfo->HT20IndexDiff[rfPath][group] =
2346 [EEPROM_HT20_TX_PWR_INX_DIFF_8723A +
2347 group] >> (rfPath * 4)) & 0xF;
2348 /* 4bit sign number to 8 bit sign number */
2349 if (pwrInfo->HT20IndexDiff[rfPath][group] & BIT3)
2350 pwrInfo->HT20IndexDiff[rfPath][group] |= 0xF0;
2352 pwrInfo->OFDMIndexDiff[rfPath][group] =
2353 (PROMContent[EEPROM_OFDM_TX_PWR_INX_DIFF_8723A +
2354 group] >> (rfPath * 4)) & 0xF;
2356 pwrInfo->HT40MaxOffset[rfPath][group] =
2357 (PROMContent[EEPROM_HT40_MAX_PWR_OFFSET_8723A +
2358 group] >> (rfPath * 4)) & 0xF;
2360 pwrInfo->HT20MaxOffset[rfPath][group] =
2361 (PROMContent[EEPROM_HT20_MAX_PWR_OFFSET_8723A +
2362 group] >> (rfPath * 4)) & 0xF;
2366 pwrInfo->TSSI_A[0] = PROMContent[EEPROM_TSSI_A_8723A];
2369 static u8 Hal_GetChnlGroup(u8 chnl)
2373 if (chnl < 3) /* Cjanel 1-3 */
2375 else if (chnl < 9) /* Channel 4-9 */
2377 else /* Channel 10-14 */
2384 Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter,
2385 u8 *PROMContent, bool AutoLoadFail)
2387 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2388 struct txpowerinfo pwrInfo;
2389 u8 rfPath, ch, group, rfPathMax = 1;
2392 Hal_ReadPowerValueFromPROM_8723A(&pwrInfo, PROMContent, AutoLoadFail);
2393 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2394 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2395 group = Hal_GetChnlGroup(ch);
2397 pHalData->TxPwrLevelCck[rfPath][ch] =
2398 pwrInfo.CCKIndex[rfPath][group];
2399 pHalData->TxPwrLevelHT40_1S[rfPath][ch] =
2400 pwrInfo.HT40_1SIndex[rfPath][group];
2402 pHalData->TxPwrHt20Diff[rfPath][ch] =
2403 pwrInfo.HT20IndexDiff[rfPath][group];
2404 pHalData->TxPwrLegacyHtDiff[rfPath][ch] =
2405 pwrInfo.OFDMIndexDiff[rfPath][group];
2406 pHalData->PwrGroupHT20[rfPath][ch] =
2407 pwrInfo.HT20MaxOffset[rfPath][group];
2408 pHalData->PwrGroupHT40[rfPath][ch] =
2409 pwrInfo.HT40MaxOffset[rfPath][group];
2411 pwr = pwrInfo.HT40_1SIndex[rfPath][group];
2412 diff = pwrInfo.HT40_2SIndexDiff[rfPath][group];
2414 pHalData->TxPwrLevelHT40_2S[rfPath][ch] =
2415 (pwr > diff) ? (pwr - diff) : 0;
2418 for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
2419 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2420 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2421 ("RF(%u)-Ch(%u) [CCK / HT40_1S / HT40_2S] = "
2422 "[0x%x / 0x%x / 0x%x]\n",
2424 pHalData->TxPwrLevelCck[rfPath][ch],
2425 pHalData->TxPwrLevelHT40_1S[rfPath][ch],
2426 pHalData->TxPwrLevelHT40_2S[rfPath][ch]));
2430 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2431 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2432 ("RF-A Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
2433 pHalData->TxPwrHt20Diff[RF_PATH_A][ch],
2434 pHalData->TxPwrHt20Diff[RF_PATH_A][ch]));
2436 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
2437 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2438 ("RF-A Legacy to Ht40 Diff[%u] = 0x%x\n", ch,
2439 pHalData->TxPwrLegacyHtDiff[RF_PATH_A][ch]));
2440 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2441 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2442 ("RF-B Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
2443 pHalData->TxPwrHt20Diff[RF_PATH_B][ch],
2444 pHalData->TxPwrHt20Diff[RF_PATH_B][ch]));
2446 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
2447 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2448 ("RF-B Legacy to HT40 Diff[%u] = 0x%x\n", ch,
2449 pHalData->TxPwrLegacyHtDiff[RF_PATH_B][ch]));
2450 if (!AutoLoadFail) {
2451 struct registry_priv *registry_par = &padapter->registrypriv;
2452 if (registry_par->regulatory_tid == 0xff) {
2453 if (PROMContent[RF_OPTION1_8723A] == 0xff)
2454 pHalData->EEPROMRegulatory = 0;
2456 pHalData->EEPROMRegulatory =
2457 PROMContent[RF_OPTION1_8723A] & 0x7;
2459 pHalData->EEPROMRegulatory =
2460 registry_par->regulatory_tid;
2463 pHalData->EEPROMRegulatory = 0;
2465 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2466 ("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory));
2469 pHalData->bTXPowerDataReadFromEEPORM = true;
2473 Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter,
2474 u8 *hwinfo, bool AutoLoadFail)
2476 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2480 if (!AutoLoadFail) {
2481 tmpu4 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
2482 if (tmpu4 & BT_FUNC_EN)
2483 pHalData->EEPROMBluetoothCoexist = 1;
2485 pHalData->EEPROMBluetoothCoexist = 0;
2486 pHalData->EEPROMBluetoothType = BT_RTL8723A;
2488 /* The following need to be checked with newer version of */
2490 tempval = hwinfo[RF_OPTION4_8723A];
2491 pHalData->EEPROMBluetoothAntNum = (tempval & 0x1);
2492 pHalData->EEPROMBluetoothAntIsolation = ((tempval & 0x10) >> 4);
2493 pHalData->EEPROMBluetoothRadioShared = ((tempval & 0x20) >> 5);
2495 pHalData->EEPROMBluetoothCoexist = 0;
2496 pHalData->EEPROMBluetoothType = BT_RTL8723A;
2497 pHalData->EEPROMBluetoothAntNum = Ant_x2;
2498 pHalData->EEPROMBluetoothAntIsolation = 0;
2499 pHalData->EEPROMBluetoothRadioShared = BT_Radio_Shared;
2501 #ifdef CONFIG_8723AU_BT_COEXIST
2502 BT_InitHalVars(padapter);
2507 Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter,
2508 u8 *hwinfo, bool AutoLoadFail)
2510 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2513 pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723A];
2515 pHalData->EEPROMVersion = 1;
2516 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2517 ("Hal_EfuseParseEEPROMVer(), EEVer = %d\n",
2518 pHalData->EEPROMVersion));
2522 rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter,
2523 u8 *hwinfo, bool AutoLoadFail)
2525 padapter->mlmepriv.ChannelPlan =
2526 hal_com_get_channel_plan23a(padapter, hwinfo ?
2527 hwinfo[EEPROM_ChannelPlan_8723A]:0xFF,
2528 padapter->registrypriv.channel_plan,
2529 RT_CHANNEL_DOMAIN_WORLD_WIDE_13,
2532 DBG_8723A("mlmepriv.ChannelPlan = 0x%02x\n",
2533 padapter->mlmepriv.ChannelPlan);
2537 Hal_EfuseParseCustomerID(struct rtw_adapter *padapter,
2538 u8 *hwinfo, bool AutoLoadFail)
2540 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2542 if (!AutoLoadFail) {
2543 pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723A];
2544 pHalData->EEPROMSubCustomerID =
2545 hwinfo[EEPROM_SubCustomID_8723A];
2547 pHalData->EEPROMCustomerID = 0;
2548 pHalData->EEPROMSubCustomerID = 0;
2550 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2551 ("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID));
2552 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2553 ("EEPROM SubCustomer ID: 0x%02x\n",
2554 pHalData->EEPROMSubCustomerID));
2558 Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter,
2559 u8 *hwinfo, bool AutoLoadFail)
2564 Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter,
2565 u8 *hwinfo, bool AutoLoadFail)
2570 Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter,
2571 u8 *hwinfo, u8 AutoLoadFail)
2573 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
2575 if (!AutoLoadFail) {
2576 pHalData->CrystalCap = hwinfo[EEPROM_XTAL_K_8723A];
2577 if (pHalData->CrystalCap == 0xFF)
2578 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
2580 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
2582 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2583 ("%s: CrystalCap = 0x%2x\n", __func__,
2584 pHalData->CrystalCap));
2588 Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter,
2589 u8 *PROMContent, u8 AutoloadFail)
2591 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2594 /* ThermalMeter from EEPROM */
2596 if (false == AutoloadFail)
2597 pHalData->EEPROMThermalMeter =
2598 PROMContent[EEPROM_THERMAL_METER_8723A];
2600 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2602 if ((pHalData->EEPROMThermalMeter == 0xff) || (true == AutoloadFail)) {
2603 pHalData->bAPKThermalMeterIgnore = true;
2604 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2607 DBG_8723A("%s: ThermalMeter = 0x%x\n", __func__,
2608 pHalData->EEPROMThermalMeter);
2611 void Hal_InitChannelPlan23a(struct rtw_adapter *padapter)
2615 static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc)
2617 u16 *usPtr = (u16 *) ptxdesc;
2618 u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
2623 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
2625 for (index = 0; index < count; index++) {
2626 checksum ^= le16_to_cpu(*(usPtr + index));
2629 ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
2632 static void fill_txdesc_sectype(struct pkt_attrib *pattrib,
2633 struct txdesc_8723a *ptxdesc)
2635 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
2636 switch (pattrib->encrypt) {
2642 ptxdesc->sectype = 1;
2646 ptxdesc->sectype = 3;
2656 static void fill_txdesc_vcs(struct pkt_attrib *pattrib,
2657 struct txdesc_8723a *ptxdesc)
2659 /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */
2661 switch (pattrib->vcs_mode) {
2667 ptxdesc->cts2self = 1;
2675 if (pattrib->vcs_mode) {
2676 ptxdesc->hw_rts_en = 1; /* ENABLE HW RTS */
2679 if (pattrib->ht_en) {
2680 if (pattrib->bwmode & HT_CHANNEL_WIDTH_40)
2681 ptxdesc->rts_bw = 1;
2683 switch (pattrib->ch_offset) {
2684 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
2685 ptxdesc->rts_sc = 0;
2688 case HAL_PRIME_CHNL_OFFSET_LOWER:
2689 ptxdesc->rts_sc = 1;
2692 case HAL_PRIME_CHNL_OFFSET_UPPER:
2693 ptxdesc->rts_sc = 2;
2697 ptxdesc->rts_sc = 3; /* Duplicate */
2704 static void fill_txdesc_phy(struct pkt_attrib *pattrib,
2705 struct txdesc_8723a *ptxdesc)
2707 if (pattrib->ht_en) {
2708 if (pattrib->bwmode & HT_CHANNEL_WIDTH_40)
2709 ptxdesc->data_bw = 1;
2711 switch (pattrib->ch_offset) {
2712 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
2713 ptxdesc->data_sc = 0;
2716 case HAL_PRIME_CHNL_OFFSET_LOWER:
2717 ptxdesc->data_sc = 1;
2720 case HAL_PRIME_CHNL_OFFSET_UPPER:
2721 ptxdesc->data_sc = 2;
2725 ptxdesc->data_sc = 3; /* Duplicate */
2731 static void rtl8723a_fill_default_txdesc(struct xmit_frame *pxmitframe,
2734 struct rtw_adapter *padapter;
2735 struct hal_data_8723a *pHalData;
2736 struct dm_priv *pdmpriv;
2737 struct mlme_ext_priv *pmlmeext;
2738 struct mlme_ext_info *pmlmeinfo;
2739 struct pkt_attrib *pattrib;
2740 struct txdesc_8723a *ptxdesc;
2743 padapter = pxmitframe->padapter;
2744 pHalData = GET_HAL_DATA(padapter);
2745 pdmpriv = &pHalData->dmpriv;
2746 pmlmeext = &padapter->mlmeextpriv;
2747 pmlmeinfo = &pmlmeext->mlmext_info;
2749 pattrib = &pxmitframe->attrib;
2750 bmcst = is_multicast_ether_addr(pattrib->ra);
2752 ptxdesc = (struct txdesc_8723a *)pbuf;
2754 if (pxmitframe->frame_tag == DATA_FRAMETAG) {
2755 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2757 if (pattrib->ampdu_en == true)
2758 ptxdesc->agg_en = 1; /* AGG EN */
2760 ptxdesc->bk = 1; /* AGG BK */
2762 ptxdesc->qsel = pattrib->qsel;
2763 ptxdesc->rate_id = pattrib->raid;
2765 fill_txdesc_sectype(pattrib, ptxdesc);
2767 ptxdesc->seq = pattrib->seqnum;
2769 if ((pattrib->ether_type != 0x888e) &&
2770 (pattrib->ether_type != 0x0806) &&
2771 (pattrib->dhcp_pkt != 1)) {
2772 /* Non EAP & ARP & DHCP type data packet */
2774 fill_txdesc_vcs(pattrib, ptxdesc);
2775 fill_txdesc_phy(pattrib, ptxdesc);
2777 ptxdesc->rtsrate = 8; /* RTS Rate = 24M */
2778 ptxdesc->data_ratefb_lmt = 0x1F;
2779 ptxdesc->rts_ratefb_lmt = 0xF;
2781 /* use REG_INIDATA_RATE_SEL value */
2783 pdmpriv->INIDATA_RATE[pattrib->mac_id];
2786 /* EAP data packet and ARP packet. */
2787 /* Use the 1M data rate to send the EAP/ARP packet. */
2788 /* This will maybe make the handshake smooth. */
2790 ptxdesc->bk = 1; /* AGG BK */
2791 ptxdesc->userate = 1; /* driver uses rate */
2792 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
2793 ptxdesc->data_short = 1;
2794 ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
2796 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
2797 /* RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
2798 ("%s: MGNT_FRAMETAG\n", __func__)); */
2800 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2801 ptxdesc->qsel = pattrib->qsel;
2802 ptxdesc->rate_id = pattrib->raid; /* Rate ID */
2803 ptxdesc->seq = pattrib->seqnum;
2804 ptxdesc->userate = 1; /* driver uses rate, 1M */
2805 ptxdesc->rty_lmt_en = 1; /* retry limit enable */
2806 ptxdesc->data_rt_lmt = 6; /* retry limit = 6 */
2808 /* CCX-TXRPT ack for xmit mgmt frames. */
2809 if (pxmitframe->ack_report)
2812 ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
2813 } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
2814 RT_TRACE(_module_hal_xmit_c_, _drv_warning_,
2815 ("%s: TXAGG_FRAMETAG\n", __func__));
2817 RT_TRACE(_module_hal_xmit_c_, _drv_warning_,
2818 ("%s: frame_tag = 0x%x\n", __func__,
2819 pxmitframe->frame_tag));
2821 ptxdesc->macid = 4; /* CAM_ID(MAC_ID) */
2822 ptxdesc->rate_id = 6; /* Rate ID */
2823 ptxdesc->seq = pattrib->seqnum;
2824 ptxdesc->userate = 1; /* driver uses rate */
2825 ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
2828 ptxdesc->pktlen = pattrib->last_txcmdsz;
2829 ptxdesc->offset = TXDESC_SIZE + OFFSET_SZ;
2836 /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
2837 /* (1) The sequence number of each non-Qos frame / broadcast /
2838 * multicast / mgnt frame should be controled by Hw because Fw
2839 * will also send null data which we cannot control when Fw LPS enable.
2840 * --> default enable non-Qos data sequense number.
2841 2010.06.23. by tynli. */
2842 /* (2) Enable HW SEQ control for beacon packet,
2843 * because we use Hw beacon. */
2844 /* (3) Use HW Qos SEQ to control the seq num of Ext port
2845 * non-Qos packets. */
2846 /* 2010.06.23. Added by tynli. */
2847 if (!pattrib->qos_en) {
2848 /* Hw set sequence number */
2849 ptxdesc->hwseq_en = 1; /* HWSEQ_EN */
2850 ptxdesc->hwseq_sel = 0; /* HWSEQ_SEL */
2858 * pxmitframe xmitframe
2859 * pbuf where to fill tx desc
2861 void rtl8723a_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf)
2863 struct tx_desc *pdesc;
2865 pdesc = (struct tx_desc *)pbuf;
2866 memset(pdesc, 0, sizeof(struct tx_desc));
2868 rtl8723a_fill_default_txdesc(pxmitframe, pbuf);
2870 pdesc->txdw0 = cpu_to_le32(pdesc->txdw0);
2871 pdesc->txdw1 = cpu_to_le32(pdesc->txdw1);
2872 pdesc->txdw2 = cpu_to_le32(pdesc->txdw2);
2873 pdesc->txdw3 = cpu_to_le32(pdesc->txdw3);
2874 pdesc->txdw4 = cpu_to_le32(pdesc->txdw4);
2875 pdesc->txdw5 = cpu_to_le32(pdesc->txdw5);
2876 pdesc->txdw6 = cpu_to_le32(pdesc->txdw6);
2877 pdesc->txdw7 = cpu_to_le32(pdesc->txdw7);
2878 rtl8723a_cal_txdesc_chksum(pdesc);
2882 * Description: In normal chip, we should send some packet to Hw which
2883 * will be used by Fw in FW LPS mode. The function is to fill the Tx
2884 * descriptor of this packets, then
2886 /* Fw can tell Hw to send these packet derectly. */
2887 /* Added by tynli. 2009.10.15. */
2889 void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc,
2890 u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull)
2892 struct tx_desc *ptxdesc;
2894 /* Clear all status */
2895 ptxdesc = (struct tx_desc *)pDesc;
2896 memset(pDesc, 0, TXDESC_SIZE);
2899 /* own, bFirstSeg, bLastSeg; */
2900 ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
2902 /* 32 bytes for TX Desc */
2903 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) <<
2904 OFFSET_SHT) & 0x00ff0000);
2906 /* Buffer size + command header */
2907 ptxdesc->txdw0 |= cpu_to_le32(BufferLen & 0x0000ffff);
2910 /* Fixed queue of Mgnt queue */
2911 ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT << QSEL_SHT) & 0x00001f00);
2913 /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed
2914 to error vlaue by Hw. */
2916 ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
2918 /* Hw set sequence number */
2919 ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
2920 /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */
2921 ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
2924 if (true == IsBTQosNull) {
2925 ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */
2929 ptxdesc->txdw4 |= cpu_to_le32(BIT(8)); /* driver uses rate */
2931 /* USB interface drop packet if the checksum of descriptor isn't
2933 /* Using this checksum can let hardware recovery from packet bulk
2934 out error (e.g. Cancel URC, Bulk out error.). */
2935 rtl8723a_cal_txdesc_chksum(ptxdesc);
2938 static void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode)
2942 if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
2943 StopTxBeacon(padapter);
2945 /* disable atim wnd */
2946 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_ATIM;
2947 SetBcnCtrlReg23a(padapter, val8, ~val8);
2948 } else if ((mode == _HW_STATE_ADHOC_) /*|| (mode == _HW_STATE_AP_) */) {
2949 ResumeTxBeacon(padapter);
2951 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB;
2952 SetBcnCtrlReg23a(padapter, val8, ~val8);
2953 } else if (mode == _HW_STATE_AP_) {
2954 #ifdef CONFIG_8723AU_BT_COEXIST
2955 /* add NULL Data and BT NULL Data Packets to FW RSVD Page */
2956 rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter);
2959 ResumeTxBeacon(padapter);
2961 val8 = DIS_TSF_UDT | DIS_BCNQ_SUB;
2962 SetBcnCtrlReg23a(padapter, val8, ~val8);
2965 /* rtw_write32(padapter, REG_RCR, 0x70002a8e);
2966 CBSSID_DATA must set to 0 */
2967 /* CBSSID_DATA must set to 0 */
2968 rtw_write32(padapter, REG_RCR, 0x7000228e);
2969 /* enable to rx data frame */
2970 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
2971 /* enable to rx ps-poll */
2972 rtw_write16(padapter, REG_RXFLTMAP1, 0x0400);
2974 /* Beacon Control related register for first time */
2975 rtw_write8(padapter, REG_BCNDMATIM, 0x02); /* 2ms */
2976 rtw_write8(padapter, REG_DRVERLYINT, 0x05); /* 5ms */
2977 rtw_write8(padapter, REG_ATIMWND, 0x0a); /* 10ms for port0 */
2978 rtw_write16(padapter, REG_BCNTCFG, 0x00);
2979 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0xff04);
2980 /* +32767 (~32ms) */
2981 rtw_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff);
2984 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
2986 /* enable BCN Function */
2987 /* don't enable update TSF (due to TSF update when
2988 beacon/probe rsp are received) */
2989 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION |
2990 EN_TXBCN_RPT | DIS_BCNQ_SUB;
2991 SetBcnCtrlReg23a(padapter, val8, ~val8);
2994 val8 = rtw_read8(padapter, MSR);
2995 val8 = (val8 & 0xC) | mode;
2996 rtw_write8(padapter, MSR, val8);
2999 static void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val)
3004 reg_macid = REG_MACID;
3006 for (idx = 0; idx < 6; idx++)
3007 rtw_write8(padapter, (reg_macid + idx), val[idx]);
3010 static void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val)
3015 reg_bssid = REG_BSSID;
3017 for (idx = 0; idx < 6; idx++)
3018 rtw_write8(padapter, (reg_bssid + idx), val[idx]);
3021 static void hw_var_set_correct_tsf(struct rtw_adapter *padapter)
3025 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3026 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3028 /* tsf = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue %
3029 (pmlmeinfo->bcn_interval*1024)) - 1024; us */
3030 tsf = pmlmeext->TSFValue -
3031 rtw_modular6423a(pmlmeext->TSFValue,
3032 (pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */
3034 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
3035 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
3036 /* pHalData->RegTxPause |= STOP_BCNQ;BIT(6) */
3037 /* rtw_write8(padapter, REG_TXPAUSE,
3038 (rtw_read8(Adapter, REG_TXPAUSE)|BIT(6))); */
3039 StopTxBeacon(padapter);
3042 reg_tsftr = REG_TSFTR;
3044 /* disable related TSF function */
3045 SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION);
3047 rtw_write32(padapter, reg_tsftr, tsf);
3048 rtw_write32(padapter, reg_tsftr + 4, tsf >> 32);
3050 /* enable related TSF function */
3051 SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION, 0);
3053 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
3054 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
3055 ResumeTxBeacon(padapter);
3058 static void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter)
3060 /* reject all data frames */
3061 rtw_write16(padapter, REG_RXFLTMAP2, 0);
3064 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
3066 /* disable update TSF */
3067 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
3070 static void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type)
3072 u8 RetryLimit = 0x30;
3074 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
3075 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3077 if (type == 0) { /* prepare to join */
3080 /* enable to rx data frame.Accept all data frame */
3081 /* rtw_write32(padapter, REG_RCR,
3082 rtw_read32(padapter, REG_RCR)|RCR_ADF); */
3083 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
3085 v32 = rtw_read32(padapter, REG_RCR);
3086 v32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
3087 rtw_write32(padapter, REG_RCR, v32);
3089 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
3091 (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48;
3092 else /* Ad-hoc Mode */
3094 } else if (type == 1) { /* joinbss_event callback when join res < 0 */
3095 /* config RCR to receive different BSSID & not to
3096 receive data frame during linking */
3097 rtw_write16(padapter, REG_RXFLTMAP2, 0);
3098 } else if (type == 2) { /* sta add event callback */
3099 /* enable update TSF */
3100 SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
3102 if (check_fwstate(pmlmepriv,
3103 WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
3104 /* fixed beacon issue for 8191su........... */
3105 rtw_write8(padapter, 0x542, 0x02);
3110 rtw_write16(padapter, REG_RL,
3111 RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit <<
3112 RETRY_LIMIT_LONG_SHIFT);
3114 #ifdef CONFIG_8723AU_BT_COEXIST
3117 /* prepare to join */
3118 BT_WifiAssociateNotify(padapter, true);
3121 /* joinbss_event callback when join res < 0 */
3122 BT_WifiAssociateNotify(padapter, false);
3125 /* sta add event callback */
3126 /* BT_WifiMediaStatusNotify(padapter, RT_MEDIA_CONNECT); */
3132 void SetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val)
3134 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
3135 u32 *val32 = (u32 *)val;
3138 case HW_VAR_MEDIA_STATUS:
3139 rtl8723a_set_media_status(padapter, *val);
3142 case HW_VAR_MEDIA_STATUS1:
3143 rtl8723a_set_media_status1(padapter, *val);
3146 case HW_VAR_SET_OPMODE:
3147 hw_var_set_opmode(padapter, *val);
3150 case HW_VAR_MAC_ADDR:
3151 hw_var_set_macaddr(padapter, val);
3155 hw_var_set_bssid(padapter, val);
3158 case HW_VAR_BASIC_RATE:
3159 HalSetBrateCfg23a(padapter, val);
3162 case HW_VAR_TXPAUSE:
3163 rtl8723a_set_tx_pause(padapter, *val);
3166 case HW_VAR_BCN_FUNC:
3167 rtl8723a_set_bcn_func(padapter, *val);
3170 case HW_VAR_CORRECT_TSF:
3171 hw_var_set_correct_tsf(padapter);
3174 case HW_VAR_CHECK_BSSID:
3175 rtl8723a_check_bssid(padapter, *val);
3178 case HW_VAR_MLME_DISCONNECT:
3179 hw_var_set_mlme_disconnect(padapter);
3182 case HW_VAR_MLME_SITESURVEY:
3183 rtl8723a_mlme_sitesurvey(padapter, *val);
3186 case HW_VAR_MLME_JOIN:
3187 hw_var_set_mlme_join(padapter, *val);
3190 case HW_VAR_ON_RCR_AM:
3191 rtl8723a_on_rcr_am(padapter);
3194 case HW_VAR_OFF_RCR_AM:
3195 rtl8723a_off_rcr_am(padapter);
3198 case HW_VAR_BEACON_INTERVAL:
3199 rtl8723a_set_beacon_interval(padapter, *((u16 *) val));
3202 case HW_VAR_SLOT_TIME:
3203 rtl8723a_set_slot_time(padapter, *val);
3206 case HW_VAR_RESP_SIFS:
3207 rtl8723a_set_resp_sifs(padapter, val[0], val[1],
3211 case HW_VAR_ACK_PREAMBLE:
3212 rtl8723a_ack_preamble(padapter, *val);
3215 case HW_VAR_SEC_CFG:
3216 rtl8723a_set_sec_cfg(padapter, *val);
3219 case HW_VAR_DM_FLAG:
3220 rtl8723a_odm_support_ability_write(padapter, *val32);
3222 case HW_VAR_DM_FUNC_OP:
3223 rtl8723a_odm_support_ability_backup(padapter, *val);
3225 case HW_VAR_DM_FUNC_SET:
3226 rtl8723a_odm_support_ability_set(padapter, *val32);
3229 case HW_VAR_DM_FUNC_CLR:
3230 rtl8723a_odm_support_ability_clr(padapter, *val32);
3233 case HW_VAR_CAM_EMPTY_ENTRY:
3234 rtl8723a_cam_empty_entry(padapter, *val);
3237 case HW_VAR_CAM_INVALID_ALL:
3238 rtl8723a_cam_invalid_all(padapter);
3241 case HW_VAR_CAM_WRITE:
3242 rtl8723a_cam_write(padapter, val32[0], val32[1]);
3245 case HW_VAR_AC_PARAM_VO:
3246 rtl8723a_set_ac_param_vo(padapter, *val32);
3249 case HW_VAR_AC_PARAM_VI:
3250 rtl8723a_set_ac_param_vi(padapter, *val32);
3253 case HW_VAR_AC_PARAM_BE:
3254 rtl8723a_set_ac_param_be(padapter, *val32);
3257 case HW_VAR_AC_PARAM_BK:
3258 rtl8723a_set_ac_param_bk(padapter, *val32);
3261 case HW_VAR_ACM_CTRL:
3262 rtl8723a_set_acm_ctrl(padapter, *val);
3265 case HW_VAR_AMPDU_MIN_SPACE:
3266 rtl8723a_set_ampdu_min_space(padapter, *val);
3269 case HW_VAR_AMPDU_FACTOR:
3270 rtl8723a_set_ampdu_factor(padapter, *val);
3273 case HW_VAR_RXDMA_AGG_PG_TH:
3274 rtl8723a_set_rxdma_agg_pg_th(padapter, *val);
3277 case HW_VAR_H2C_FW_PWRMODE:
3278 rtl8723a_set_FwPwrMode_cmd(padapter, *val);
3281 case HW_VAR_H2C_FW_JOINBSSRPT:
3282 rtl8723a_set_FwJoinBssReport_cmd(padapter, *val);
3285 #ifdef CONFIG_8723AU_P2P
3286 case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
3287 rtl8723a_set_p2p_ps_offload_cmd(padapter, *val);
3289 #endif /* CONFIG_8723AU_P2P */
3291 case HW_VAR_INITIAL_GAIN:
3292 rtl8723a_set_initial_gain(padapter, *val32);
3294 case HW_VAR_EFUSE_BYTES:
3295 pHalData->EfuseUsedBytes = *((u16 *) val);
3297 case HW_VAR_EFUSE_BT_BYTES:
3298 pHalData->BTEfuseUsedBytes = *((u16 *) val);
3300 case HW_VAR_FIFO_CLEARN_UP:
3301 rtl8723a_fifo_cleanup(padapter);
3303 case HW_VAR_CHECK_TXBUF:
3305 case HW_VAR_APFM_ON_MAC:
3306 rtl8723a_set_apfm_on_mac(padapter, *val);
3309 case HW_VAR_NAV_UPPER:
3310 rtl8723a_set_nav_upper(padapter, *val32);
3312 case HW_VAR_BCN_VALID:
3313 rtl8723a_bcn_valid(padapter);
3321 void GetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val)
3323 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
3326 case HW_VAR_BASIC_RATE:
3327 *((u16 *) val) = pHalData->BasicRateSet;
3330 case HW_VAR_TXPAUSE:
3331 *val = rtw_read8(padapter, REG_TXPAUSE);
3334 case HW_VAR_BCN_VALID:
3335 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
3336 val[0] = (BIT0 & rtw_read8(padapter, REG_TDECTRL + 2)) ? true :
3340 case HW_VAR_RF_TYPE:
3341 *val = pHalData->rf_type;
3344 case HW_VAR_DM_FLAG:
3346 struct dm_odm_t *podmpriv = &pHalData->odmpriv;
3347 *((u32 *) val) = podmpriv->SupportAbility;
3351 case HW_VAR_FWLPS_RF_ON:
3353 /* When we halt NIC, we should check if FW LPS is leave. */
3356 if ((padapter->bSurpriseRemoved == true) ||
3357 (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) {
3358 /* If it is in HW/SW Radio OFF or IPS state, we do
3359 not check Fw LPS Leave, because Fw is unload. */
3362 valRCR = rtw_read32(padapter, REG_RCR);
3363 valRCR &= 0x00070000;
3371 case HW_VAR_EFUSE_BYTES:
3372 *((u16 *) val) = pHalData->EfuseUsedBytes;
3375 case HW_VAR_EFUSE_BT_BYTES:
3376 *((u16 *) val) = pHalData->BTEfuseUsedBytes;
3379 case HW_VAR_APFM_ON_MAC:
3380 *val = pHalData->bMacPwrCtrlOn;
3382 case HW_VAR_CHK_HI_QUEUE_EMPTY:
3384 ((rtw_read32(padapter, REG_HGQ_INFORMATION) & 0x0000ff00) ==
3390 #ifdef CONFIG_8723AU_BT_COEXIST
3392 void rtl8723a_SingleDualAntennaDetection(struct rtw_adapter *padapter)
3394 struct hal_data_8723a *pHalData;
3395 struct dm_odm_t *pDM_Odm;
3396 struct sw_ant_sw *pDM_SWAT_Table;
3399 pHalData = GET_HAL_DATA(padapter);
3400 pDM_Odm = &pHalData->odmpriv;
3401 pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
3404 /* <Roger_Notes> RTL8723A Single and Dual antenna dynamic detection
3405 mechanism when RF power state is on. */
3406 /* We should take power tracking, IQK, LCK, RCK RF read/write
3407 operation into consideration. */
3410 if (!pHalData->bAntennaDetected) {
3411 u8 btAntNum = BT_GetPGAntNum(padapter);
3413 /* Set default antenna B status */
3414 if (btAntNum == Ant_x2)
3415 pDM_SWAT_Table->ANTB_ON = true;
3416 else if (btAntNum == Ant_x1)
3417 pDM_SWAT_Table->ANTB_ON = false;
3419 pDM_SWAT_Table->ANTB_ON = true;
3421 if (pHalData->CustomerID != RT_CID_TOSHIBA) {
3422 for (i = 0; i < MAX_ANTENNA_DETECTION_CNT; i++) {
3423 if (ODM_SingleDualAntennaDetection
3424 (&pHalData->odmpriv, ANTTESTALL) == true)
3428 /* Set default antenna number for BT coexistence */
3429 if (btAntNum == Ant_x2)
3430 BT_SetBtCoexCurrAntNum(padapter,
3434 pHalData->bAntennaDetected = true;
3437 #endif /* CONFIG_8723AU_BT_COEXIST */
3439 void rtl8723a_clone_haldata(struct rtw_adapter *dst_adapter,
3440 struct rtw_adapter *src_adapter)
3442 memcpy(dst_adapter->HalData, src_adapter->HalData,
3443 dst_adapter->hal_data_sz);
3446 void rtl8723a_start_thread(struct rtw_adapter *padapter)
3450 void rtl8723a_stop_thread(struct rtw_adapter *padapter)