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;
622 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
624 /* Do NOT excess total size of EFuse table.
625 Added by Roger, 2008.11.10. */
626 if ((_offset + _size_byte) > EFUSE_MAP_LEN_8723A) {
627 DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
628 __func__, _offset, _size_byte);
632 efuseTbl = (u8 *) kmalloc(EFUSE_MAP_LEN_8723A, GFP_KERNEL);
633 if (efuseTbl == NULL) {
634 DBG_8723A("%s: alloc efuseTbl fail!\n", __func__);
637 /* 0xff will be efuse default value instead of 0x00. */
638 memset(efuseTbl, 0xFF, EFUSE_MAP_LEN_8723A);
640 /* switch bank back to bank 0 for later BT and wifi use. */
641 hal_EfuseSwitchToBank(padapter, 0);
643 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
644 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
645 if (efuseHeader == 0xFF) {
646 DBG_8723A("%s: data end at address =%#x\n", __func__,
651 /* Check PG header for section num. */
652 if (EXT_HEADER(efuseHeader)) { /* extended header */
653 offset = GET_HDR_OFFSET_2_0(efuseHeader);
655 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseExtHdr);
656 if (ALL_WORDS_DISABLED(efuseExtHdr)) {
660 offset |= ((efuseExtHdr & 0xF0) >> 1);
661 wden = (efuseExtHdr & 0x0F);
663 offset = ((efuseHeader >> 4) & 0x0f);
664 wden = (efuseHeader & 0x0f);
667 if (offset < EFUSE_MAX_SECTION_8723A) {
669 /* Get word enable value from PG header */
671 addr = offset * PGPKT_DATA_SIZE;
672 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
673 /* Check word enable condition in the section */
674 if (!(wden & (0x01 << i))) {
675 ReadEFuseByte23a(padapter, eFuse_Addr++,
677 efuseTbl[addr] = efuseData;
679 ReadEFuseByte23a(padapter, eFuse_Addr++,
681 efuseTbl[addr + 1] = efuseData;
686 DBG_8723A(KERN_ERR "%s: offset(%d) is illegal!!\n",
688 eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
692 /* Copy from Efuse map to output pointer memory!!! */
693 for (i = 0; i < _size_byte; i++)
694 pbuf[i] = efuseTbl[_offset + i];
696 /* Calculate Efuse utilization */
697 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
698 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
699 used = eFuse_Addr - 1;
700 pHalData->EfuseUsedBytes = used;
706 hal_ReadEFuse_BT(struct rtw_adapter *padapter,
707 u16 _offset, u16 _size_byte, u8 *pbuf)
712 u8 efuseHeader, efuseExtHdr, efuseData;
715 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
717 /* Do NOT excess total size of EFuse table.
718 Added by Roger, 2008.11.10. */
719 if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN) {
720 DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
721 __func__, _offset, _size_byte);
725 efuseTbl = kmalloc(EFUSE_BT_MAP_LEN, GFP_KERNEL);
726 if (efuseTbl == NULL) {
727 DBG_8723A("%s: efuseTbl malloc fail!\n", __func__);
730 /* 0xff will be efuse default value instead of 0x00. */
731 memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
733 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
734 TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total);
736 for (bank = 1; bank < EFUSE_MAX_BANK; bank++) {
737 if (hal_EfuseSwitchToBank(padapter, bank) == false) {
738 DBG_8723A("%s: hal_EfuseSwitchToBank Fail!!\n",
745 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
746 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
747 if (efuseHeader == 0xFF)
750 /* Check PG header for section num. */
751 if (EXT_HEADER(efuseHeader)) { /* extended header */
752 offset = GET_HDR_OFFSET_2_0(efuseHeader);
754 ReadEFuseByte23a(padapter, eFuse_Addr++,
756 if (ALL_WORDS_DISABLED(efuseExtHdr)) {
760 offset |= ((efuseExtHdr & 0xF0) >> 1);
761 wden = (efuseExtHdr & 0x0F);
763 offset = ((efuseHeader >> 4) & 0x0f);
764 wden = (efuseHeader & 0x0f);
767 if (offset < EFUSE_BT_MAX_SECTION) {
770 /* Get word enable value from PG header */
772 addr = offset * PGPKT_DATA_SIZE;
773 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
774 /* Check word enable condition in
776 if (!(wden & (0x01 << i))) {
777 ReadEFuseByte23a(padapter,
780 efuseTbl[addr] = efuseData;
782 ReadEFuseByte23a(padapter,
785 efuseTbl[addr + 1] = efuseData;
791 "%s: offset(%d) is illegal!!\n",
793 eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
797 if ((eFuse_Addr - 1) < total) {
798 DBG_8723A("%s: bank(%d) data end at %#x\n",
799 __func__, bank, eFuse_Addr - 1);
804 /* switch bank back to bank 0 for later BT and wifi use. */
805 hal_EfuseSwitchToBank(padapter, 0);
807 /* Copy from Efuse map to output pointer memory!!! */
808 for (i = 0; i < _size_byte; i++)
809 pbuf[i] = efuseTbl[_offset + i];
812 /* Calculate Efuse utilization. */
814 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
815 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
816 used = (EFUSE_BT_REAL_BANK_CONTENT_LEN * (bank - 1)) + eFuse_Addr - 1;
817 pHalData->BTEfuseUsedBytes = used;
824 Hal_ReadEFuse(struct rtw_adapter *padapter,
825 u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
827 if (efuseType == EFUSE_WIFI)
828 hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf);
830 hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf);
834 hal_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter)
837 u8 hoffset = 0, hworden = 0;
838 u8 efuse_data, word_cnts = 0;
839 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
841 efuse_addr = pHalData->EfuseUsedBytes;
843 DBG_8723A("%s: start_efuse_addr = 0x%X\n", __func__, efuse_addr);
845 /* switch bank back to bank 0 for later BT and wifi use. */
846 hal_EfuseSwitchToBank(padapter, 0);
848 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
849 if (efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data) ==
851 DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail! "
852 "addr = 0x%X !!\n", __func__, efuse_addr);
856 if (efuse_data == 0xFF)
859 if (EXT_HEADER(efuse_data)) {
860 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
862 efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data);
863 if (ALL_WORDS_DISABLED(efuse_data)) {
867 hoffset |= ((efuse_data & 0xF0) >> 1);
868 hworden = efuse_data & 0x0F;
870 hoffset = (efuse_data >> 4) & 0x0F;
871 hworden = efuse_data & 0x0F;
874 word_cnts = Efuse_CalculateWordCnts23a(hworden);
875 efuse_addr += (word_cnts * 2) + 1;
878 pHalData->EfuseUsedBytes = efuse_addr;
880 DBG_8723A("%s: CurrentSize =%d\n", __func__, efuse_addr);
886 hal_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter)
891 u8 hoffset = 0, hworden = 0;
892 u8 efuse_data, word_cnts = 0;
894 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
896 btusedbytes = pHalData->BTEfuseUsedBytes;
898 efuse_addr = (u16) ((btusedbytes % EFUSE_BT_REAL_BANK_CONTENT_LEN));
899 startBank = (u8) (1 + (btusedbytes / EFUSE_BT_REAL_BANK_CONTENT_LEN));
901 DBG_8723A("%s: start from bank =%d addr = 0x%X\n", __func__, startBank,
904 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
905 TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2);
907 for (bank = startBank; bank < EFUSE_MAX_BANK; bank++) {
908 if (hal_EfuseSwitchToBank(padapter, bank) == false) {
909 DBG_8723A(KERN_ERR "%s: switch bank(%d) Fail!!\n",
911 bank = EFUSE_MAX_BANK;
915 /* only when bank is switched we have to reset
917 if (bank != startBank)
920 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
921 if (efuse_OneByteRead23a(padapter, efuse_addr,
922 &efuse_data) == false) {
923 DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail!"
925 __func__, efuse_addr);
926 bank = EFUSE_MAX_BANK;
930 if (efuse_data == 0xFF)
933 if (EXT_HEADER(efuse_data)) {
934 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
936 efuse_OneByteRead23a(padapter, efuse_addr,
938 if (ALL_WORDS_DISABLED(efuse_data)) {
943 hoffset |= ((efuse_data & 0xF0) >> 1);
944 hworden = efuse_data & 0x0F;
946 hoffset = (efuse_data >> 4) & 0x0F;
947 hworden = efuse_data & 0x0F;
949 word_cnts = Efuse_CalculateWordCnts23a(hworden);
950 /* read next header */
951 efuse_addr += (word_cnts * 2) + 1;
954 /* Check if we need to check next bank efuse */
955 if (efuse_addr < retU2) {
956 break; /* don't need to check next bank. */
960 retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr;
961 pHalData->BTEfuseUsedBytes = retU2;
963 DBG_8723A("%s: CurrentSize =%d\n", __func__, retU2);
968 Hal_EfuseGetCurrentSize(struct rtw_adapter *pAdapter, u8 efuseType)
972 if (efuseType == EFUSE_WIFI)
973 ret = hal_EfuseGetCurrentSize_WiFi(pAdapter);
975 ret = hal_EfuseGetCurrentSize_BT(pAdapter);
981 Hal_EfuseWordEnableDataWrite(struct rtw_adapter *padapter,
982 u16 efuse_addr, u8 word_en, u8 *data)
985 u16 start_addr = efuse_addr;
987 u8 tmpdata[PGPKT_DATA_SIZE];
989 memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
991 if (!(word_en & BIT(0))) {
992 tmpaddr = start_addr;
993 efuse_OneByteWrite23a(padapter, start_addr++, data[0]);
994 efuse_OneByteWrite23a(padapter, start_addr++, data[1]);
996 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[0]);
997 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[1]);
998 if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) {
999 badworden &= (~BIT(0));
1002 if (!(word_en & BIT(1))) {
1003 tmpaddr = start_addr;
1004 efuse_OneByteWrite23a(padapter, start_addr++, data[2]);
1005 efuse_OneByteWrite23a(padapter, start_addr++, data[3]);
1007 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[2]);
1008 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[3]);
1009 if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) {
1010 badworden &= (~BIT(1));
1013 if (!(word_en & BIT(2))) {
1014 tmpaddr = start_addr;
1015 efuse_OneByteWrite23a(padapter, start_addr++, data[4]);
1016 efuse_OneByteWrite23a(padapter, start_addr++, data[5]);
1018 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[4]);
1019 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[5]);
1020 if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) {
1021 badworden &= (~BIT(2));
1024 if (!(word_en & BIT(3))) {
1025 tmpaddr = start_addr;
1026 efuse_OneByteWrite23a(padapter, start_addr++, data[6]);
1027 efuse_OneByteWrite23a(padapter, start_addr++, data[7]);
1029 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[6]);
1030 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[7]);
1031 if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) {
1032 badworden &= (~BIT(3));
1040 Hal_EfusePgPacketRead(struct rtw_adapter *padapter, u8 offset, u8 *data)
1042 u8 efuse_data, word_cnts = 0;
1044 u8 hoffset = 0, hworden = 0;
1052 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION,
1054 if (offset > max_section) {
1055 DBG_8723A("%s: Packet offset(%d) is illegal(>%d)!\n",
1056 __func__, offset, max_section);
1060 memset(data, 0xFF, PGPKT_DATA_SIZE);
1064 /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the
1065 end of Efuse by CP. */
1066 /* Skip dummy parts to prevent unexpected data read from Efuse. */
1067 /* By pass right now. 2009.02.19. */
1069 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1070 if (efuse_OneByteRead23a(padapter, efuse_addr++, &efuse_data) ==
1076 if (efuse_data == 0xFF)
1079 if (EXT_HEADER(efuse_data)) {
1080 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
1081 efuse_OneByteRead23a(padapter, efuse_addr++, &efuse_data);
1082 if (ALL_WORDS_DISABLED(efuse_data)) {
1083 DBG_8723A("%s: Error!! All words disabled!\n",
1088 hoffset |= ((efuse_data & 0xF0) >> 1);
1089 hworden = efuse_data & 0x0F;
1091 hoffset = (efuse_data >> 4) & 0x0F;
1092 hworden = efuse_data & 0x0F;
1095 if (hoffset == offset) {
1096 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
1097 /* Check word enable condition in the section */
1098 if (!(hworden & (0x01 << i))) {
1099 ReadEFuseByte23a(padapter, efuse_addr++,
1101 data[i * 2] = efuse_data;
1103 ReadEFuseByte23a(padapter, efuse_addr++,
1105 data[(i * 2) + 1] = efuse_data;
1109 word_cnts = Efuse_CalculateWordCnts23a(hworden);
1110 efuse_addr += word_cnts * 2;
1118 hal_EfusePgCheckAvailableAddr(struct rtw_adapter *pAdapter, u8 efuseType)
1120 u16 max_available = 0;
1123 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
1124 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
1127 current_size = Efuse_GetCurrentSize23a(pAdapter, efuseType);
1128 if (current_size >= max_available) {
1129 DBG_8723A("%s: Error!! current_size(%d)>max_available(%d)\n",
1130 __func__, current_size, max_available);
1137 hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData,
1138 struct pg_pkt_struct *pTargetPkt)
1140 memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
1141 pTargetPkt->offset = offset;
1142 pTargetPkt->word_en = word_en;
1143 efuse_WordEnableDataRead23a(word_en, pData, pTargetPkt->data);
1144 pTargetPkt->word_cnts = Efuse_CalculateWordCnts23a(pTargetPkt->word_en);
1148 hal_EfusePartialWriteCheck(struct rtw_adapter *padapter, u8 efuseType,
1149 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1151 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1153 u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
1156 EFUSE_GetEfuseDefinition23a(padapter, efuseType,
1157 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
1158 &efuse_max_available_len);
1159 EFUSE_GetEfuseDefinition23a(padapter, efuseType,
1160 TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max);
1162 if (efuseType == EFUSE_WIFI)
1163 startAddr = pHalData->EfuseUsedBytes;
1165 startAddr = pHalData->BTEfuseUsedBytes;
1167 startAddr %= efuse_max;
1170 if (startAddr >= efuse_max_available_len) {
1172 DBG_8723A("%s: startAddr(%d) >= efuse_max_available_"
1173 "len(%d)\n", __func__, startAddr,
1174 efuse_max_available_len);
1178 if (efuse_OneByteRead23a(padapter, startAddr, &efuse_data) &&
1179 (efuse_data != 0xFF)) {
1181 DBG_8723A("%s: Something Wrong! last bytes(%#X = 0x%02X) "
1182 "is not 0xFF\n", __func__,
1183 startAddr, efuse_data);
1186 /* not used header, 0xff */
1197 hal_EfusePgPacketWrite1ByteHeader(struct rtw_adapter *pAdapter, u8 efuseType,
1198 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1200 u8 pg_header = 0, tmp_header = 0;
1201 u16 efuse_addr = *pAddr;
1204 pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
1207 efuse_OneByteWrite23a(pAdapter, efuse_addr, pg_header);
1208 efuse_OneByteRead23a(pAdapter, efuse_addr, &tmp_header);
1209 if (tmp_header != 0xFF)
1211 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1212 DBG_8723A("%s: Repeat over limit for pg_header!!\n",
1218 if (tmp_header != pg_header) {
1219 DBG_8723A(KERN_ERR "%s: PG Header Fail!!(pg = 0x%02X "
1220 "read = 0x%02X)\n", __func__,
1221 pg_header, tmp_header);
1225 *pAddr = efuse_addr;
1231 hal_EfusePgPacketWrite2ByteHeader(struct rtw_adapter *padapter, u8 efuseType,
1232 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1234 u16 efuse_addr, efuse_max_available_len = 0;
1235 u8 pg_header = 0, tmp_header = 0;
1238 EFUSE_GetEfuseDefinition23a(padapter, efuseType,
1239 TYPE_AVAILABLE_EFUSE_BYTES_BANK,
1240 &efuse_max_available_len);
1242 efuse_addr = *pAddr;
1243 if (efuse_addr >= efuse_max_available_len) {
1244 DBG_8723A("%s: addr(%d) over avaliable(%d)!!\n", __func__,
1245 efuse_addr, efuse_max_available_len);
1249 pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
1252 efuse_OneByteWrite23a(padapter, efuse_addr, pg_header);
1253 efuse_OneByteRead23a(padapter, efuse_addr, &tmp_header);
1254 if (tmp_header != 0xFF)
1256 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1257 DBG_8723A("%s: Repeat over limit for pg_header!!\n",
1263 if (tmp_header != pg_header) {
1265 "%s: PG Header Fail!!(pg = 0x%02X read = 0x%02X)\n",
1266 __func__, pg_header, tmp_header);
1270 /* to write ext_header */
1272 pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
1275 efuse_OneByteWrite23a(padapter, efuse_addr, pg_header);
1276 efuse_OneByteRead23a(padapter, efuse_addr, &tmp_header);
1277 if (tmp_header != 0xFF)
1279 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1280 DBG_8723A("%s: Repeat over limit for ext_header!!\n",
1286 if (tmp_header != pg_header) { /* offset PG fail */
1288 "%s: PG EXT Header Fail!!(pg = 0x%02X read = 0x%02X)\n",
1289 __func__, pg_header, tmp_header);
1293 *pAddr = efuse_addr;
1299 hal_EfusePgPacketWriteHeader(struct rtw_adapter *padapter, u8 efuseType,
1300 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1304 if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) {
1305 bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType,
1308 bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType,
1316 hal_EfusePgPacketWriteData(struct rtw_adapter *pAdapter, u8 efuseType,
1317 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1322 efuse_addr = *pAddr;
1324 Efuse_WordEnableDataWrite23a(pAdapter, efuse_addr + 1,
1325 pTargetPkt->word_en, pTargetPkt->data);
1326 if (badworden != 0x0F) {
1327 DBG_8723A("%s: Fail!!\n", __func__);
1335 Hal_EfusePgPacketWrite(struct rtw_adapter *padapter,
1336 u8 offset, u8 word_en, u8 *pData)
1338 struct pg_pkt_struct targetPkt;
1340 u8 efuseType = EFUSE_WIFI;
1342 if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType))
1345 hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
1347 if (!hal_EfusePartialWriteCheck(padapter, efuseType,
1348 &startAddr, &targetPkt))
1351 if (!hal_EfusePgPacketWriteHeader(padapter, efuseType,
1352 &startAddr, &targetPkt))
1355 if (!hal_EfusePgPacketWriteData(padapter, efuseType,
1356 &startAddr, &targetPkt))
1363 Hal_EfusePgPacketWrite_BT(struct rtw_adapter *pAdapter,
1364 u8 offset, u8 word_en, u8 *pData)
1366 struct pg_pkt_struct targetPkt;
1368 u8 efuseType = EFUSE_BT;
1370 if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType))
1373 hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
1375 if (!hal_EfusePartialWriteCheck(pAdapter, efuseType,
1376 &startAddr, &targetPkt))
1379 if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType,
1380 &startAddr, &targetPkt))
1383 if (!hal_EfusePgPacketWriteData(pAdapter, efuseType,
1384 &startAddr, &targetPkt))
1390 static struct hal_version ReadChipVersion8723A(struct rtw_adapter *padapter)
1393 struct hal_version ChipVersion;
1394 struct hal_data_8723a *pHalData;
1396 pHalData = GET_HAL_DATA(padapter);
1398 value32 = rtw_read32(padapter, REG_SYS_CFG);
1399 ChipVersion.ICType = CHIP_8723A;
1400 ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
1401 ChipVersion.RFType = RF_TYPE_1T1R;
1402 ChipVersion.VendorType =
1403 ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
1404 ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
1406 /* For regulator mode. by tynli. 2011.01.14 */
1407 pHalData->RegulatorMode = ((value32 & SPS_SEL) ?
1408 RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
1410 value32 = rtw_read32(padapter, REG_GPIO_OUTSTS);
1411 /* ROM code version. */
1412 ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20);
1414 /* For multi-function consideration. Added by Roger, 2010.10.06. */
1415 pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
1416 value32 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
1417 pHalData->MultiFunc |=
1418 ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0);
1419 pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
1420 pHalData->MultiFunc |=
1421 ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
1422 pHalData->PolarityCtl =
1423 ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT :
1424 RT_POLARITY_LOW_ACT);
1425 dump_chip_info23a(ChipVersion);
1426 pHalData->VersionID = ChipVersion;
1428 if (IS_1T2R(ChipVersion))
1429 pHalData->rf_type = RF_1T2R;
1430 else if (IS_2T2R(ChipVersion))
1431 pHalData->rf_type = RF_2T2R;
1433 pHalData->rf_type = RF_1T1R;
1435 MSG_8723A("RF_Type is %x!!\n", pHalData->rf_type);
1440 static void rtl8723a_read_chip_version(struct rtw_adapter *padapter)
1442 ReadChipVersion8723A(padapter);
1447 /* 20100209 Joseph: */
1448 /* This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */
1449 /* We just reserve the value of the register in variable
1450 pHalData->RegBcnCtrlVal and then operate */
1451 /* the value of the register via atomic operation. */
1452 /* This prevents from race condition when setting this register. */
1453 /* The value of pHalData->RegBcnCtrlVal is initialized in
1454 HwConfigureRTL8192CE() function. */
1456 void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits)
1458 struct hal_data_8723a *pHalData;
1462 pHalData = GET_HAL_DATA(padapter);
1463 pRegBcnCtrlVal = (u8 *)&pHalData->RegBcnCtrlVal;
1465 addr = REG_BCN_CTRL;
1467 *pRegBcnCtrlVal = rtw_read8(padapter, addr);
1468 *pRegBcnCtrlVal |= SetBits;
1469 *pRegBcnCtrlVal &= ~ClearBits;
1471 rtw_write8(padapter, addr, *pRegBcnCtrlVal);
1474 void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter)
1476 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1478 rtw_write16(padapter, REG_BCN_CTRL, 0x1010);
1479 pHalData->RegBcnCtrlVal = 0x1010;
1481 /* TODO: Remove these magic number */
1482 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0x6404); /* ms */
1483 /* Firmware will control REG_DRVERLYINT when power saving is enable, */
1484 /* so don't set this register on STA mode. */
1485 if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false)
1486 rtw_write8(padapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
1488 rtw_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
1490 /* Suggested by designer timchen. Change beacon AIFS to the
1491 largest number beacause test chip does not contension before
1492 sending beacon. by tynli. 2009.11.03 */
1493 rtw_write16(padapter, REG_BCNTCFG, 0x660F);
1496 static void ResumeTxBeacon(struct rtw_adapter *padapter)
1498 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1500 /* 2010.03.01. Marked by tynli. No need to call workitem beacause
1501 we record the value */
1502 /* which should be read from register to a global variable. */
1504 RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+ResumeTxBeacon\n"));
1506 pHalData->RegFwHwTxQCtrl |= BIT(6);
1507 rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl);
1508 rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0xff);
1509 pHalData->RegReg542 |= BIT(0);
1510 rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
1513 static void StopTxBeacon(struct rtw_adapter *padapter)
1515 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1517 /* 2010.03.01. Marked by tynli. No need to call workitem beacause
1518 we record the value */
1519 /* which should be read from register to a global variable. */
1521 RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+StopTxBeacon\n"));
1523 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
1524 rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl);
1525 rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0x64);
1526 pHalData->RegReg542 &= ~BIT(0);
1527 rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
1529 CheckFwRsvdPageContent23a(padapter); /* 2010.06.23. Added by tynli. */
1532 static void _BeaconFunctionEnable(struct rtw_adapter *padapter, u8 Enable,
1535 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB,
1537 rtw_write8(padapter, REG_RD_CTRL + 1, 0x6F);
1540 static void rtl8723a_SetBeaconRelatedRegisters(struct rtw_adapter *padapter)
1543 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1544 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1546 /* reset TSF, enable update TSF, correcting TSF On Beacon */
1548 /* REG_BCN_INTERVAL */
1551 /* REG_TBTT_PROHIBIT */
1552 /* REG_DRVERLYINT */
1553 /* REG_BCN_MAX_ERR */
1554 /* REG_BCNTCFG (0x510) */
1555 /* REG_DUAL_TSF_RST */
1556 /* REG_BCN_CTRL (0x550) */
1561 rtw_write16(padapter, REG_ATIMWND, 2);
1564 /* Beacon interval (in unit of TU). */
1566 rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
1568 rtl8723a_InitBeaconParameters(padapter);
1570 rtw_write8(padapter, REG_SLOT, 0x09);
1573 /* Reset TSF Timer to zero, added by Roger. 2008.06.24 */
1575 value32 = rtw_read32(padapter, REG_TCR);
1577 rtw_write32(padapter, REG_TCR, value32);
1580 rtw_write32(padapter, REG_TCR, value32);
1582 /* NOTE: Fix test chip's bug (about contention windows's randomness) */
1583 if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE |
1584 WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE) == true) {
1585 rtw_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50);
1586 rtw_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50);
1589 _BeaconFunctionEnable(padapter, true, true);
1591 ResumeTxBeacon(padapter);
1592 SetBcnCtrlReg23a(padapter, DIS_BCNQ_SUB, 0);
1595 static void rtl8723a_GetHalODMVar(struct rtw_adapter *Adapter,
1596 enum hal_odm_variable eVariable,
1597 void *pValue1, bool bSet)
1599 switch (eVariable) {
1600 case HAL_ODM_STA_INFO:
1607 static void rtl8723a_SetHalODMVar(struct rtw_adapter *Adapter,
1608 enum hal_odm_variable eVariable,
1609 void *pValue1, bool bSet)
1611 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1612 struct dm_odm_t *podmpriv = &pHalData->odmpriv;
1613 switch (eVariable) {
1614 case HAL_ODM_STA_INFO:
1616 struct sta_info *psta = (struct sta_info *)pValue1;
1619 DBG_8723A("Set STA_(%d) info\n", psta->mac_id);
1620 ODM_CmnInfoPtrArrayHook23a(podmpriv,
1621 ODM_CMNINFO_STA_STATUS,
1622 psta->mac_id, psta);
1624 DBG_8723A("Clean STA_(%d) info\n", psta->mac_id);
1625 ODM_CmnInfoPtrArrayHook23a(podmpriv,
1626 ODM_CMNINFO_STA_STATUS,
1627 psta->mac_id, NULL);
1631 case HAL_ODM_P2P_STATE:
1632 ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet);
1634 case HAL_ODM_WIFI_DISPLAY_STATE:
1635 ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet);
1642 static void hal_notch_filter_8723a(struct rtw_adapter *adapter, bool enable)
1645 DBG_8723A("Enable notch filter\n");
1646 rtw_write8(adapter, rOFDM0_RxDSP + 1,
1647 rtw_read8(adapter, rOFDM0_RxDSP + 1) | BIT1);
1649 DBG_8723A("Disable notch filter\n");
1650 rtw_write8(adapter, rOFDM0_RxDSP + 1,
1651 rtw_read8(adapter, rOFDM0_RxDSP + 1) & ~BIT1);
1655 s32 c2h_id_filter_ccx_8723a(u8 id)
1658 if (id == C2H_CCX_TX_RPT)
1664 static s32 c2h_handler_8723a(struct rtw_adapter *padapter,
1665 struct c2h_evt_hdr *c2h_evt)
1670 if (c2h_evt == NULL) {
1671 DBG_8723A("%s c2h_evt is NULL\n", __func__);
1676 switch (c2h_evt->id) {
1678 RT_TRACE(_module_hal_init_c_, _drv_info_,
1679 ("C2HCommandHandler: %s\n", c2h_evt->payload));
1682 case C2H_CCX_TX_RPT:
1683 handle_txrpt_ccx_8723a(padapter, c2h_evt->payload);
1685 case C2H_EXT_RA_RPT:
1687 case C2H_HW_INFO_EXCH:
1688 RT_TRACE(_module_hal_init_c_, _drv_info_,
1689 ("[BT], C2H_HW_INFO_EXCH\n"));
1690 for (i = 0; i < c2h_evt->plen; i++) {
1691 RT_TRACE(_module_hal_init_c_, _drv_info_,
1692 ("[BT], tmpBuf[%d]= 0x%x\n", i,
1693 c2h_evt->payload[i]));
1697 case C2H_C2H_H2C_TEST:
1698 RT_TRACE(_module_hal_init_c_, _drv_info_,
1699 ("[BT], C2H_H2C_TEST\n"));
1700 RT_TRACE(_module_hal_init_c_, _drv_info_,
1701 ("[BT], tmpBuf[0]/[1]/[2]/[3]/[4]= 0x%x/ 0x%x/ "
1702 "0x%x/ 0x%x/ 0x%x\n", c2h_evt->payload[0],
1703 c2h_evt->payload[1], c2h_evt->payload[2],
1704 c2h_evt->payload[3], c2h_evt->payload[4]));
1707 #ifdef CONFIG_8723AU_BT_COEXIST
1709 DBG_8723A("%s , Got C2H_BT_INFO \n", __func__);
1710 BT_FwC2hBtInfo(padapter, c2h_evt->payload, c2h_evt->plen);
1723 void rtl8723a_set_hal_ops(struct hal_ops *pHalFunc)
1725 pHalFunc->free_hal_data = &rtl8723a_free_hal_data;
1727 pHalFunc->dm_init = &rtl8723a_init_dm_priv;
1728 pHalFunc->dm_deinit = &rtl8723a_deinit_dm_priv;
1730 pHalFunc->read_chip_version = &rtl8723a_read_chip_version;
1732 pHalFunc->set_bwmode_handler = &PHY_SetBWMode23a8723A;
1733 pHalFunc->set_channel_handler = &PHY_SwChnl8723A;
1735 pHalFunc->hal_dm_watchdog = &rtl8723a_HalDmWatchDog;
1737 pHalFunc->SetBeaconRelatedRegistersHandler =
1738 &rtl8723a_SetBeaconRelatedRegisters;
1740 pHalFunc->Add_RateATid = &rtl8723a_add_rateatid;
1741 pHalFunc->run_thread = &rtl8723a_start_thread;
1742 pHalFunc->cancel_thread = &rtl8723a_stop_thread;
1744 pHalFunc->read_bbreg = &PHY_QueryBBReg;
1745 pHalFunc->write_bbreg = &PHY_SetBBReg;
1746 pHalFunc->read_rfreg = &PHY_QueryRFReg;
1747 pHalFunc->write_rfreg = &PHY_SetRFReg;
1749 /* Efuse related function */
1750 pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch;
1751 pHalFunc->ReadEFuse = &Hal_ReadEFuse;
1752 pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition;
1753 pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize;
1754 pHalFunc->Efuse_PgPacketRead23a = &Hal_EfusePgPacketRead;
1755 pHalFunc->Efuse_PgPacketWrite23a = &Hal_EfusePgPacketWrite;
1756 pHalFunc->Efuse_WordEnableDataWrite23a = &Hal_EfuseWordEnableDataWrite;
1757 pHalFunc->Efuse_PgPacketWrite23a_BT = &Hal_EfusePgPacketWrite_BT;
1759 pHalFunc->sreset_init_value23a = &sreset_init_value23a;
1760 pHalFunc->sreset_reset_value23a = &sreset_reset_value23a;
1761 pHalFunc->silentreset = &sreset_reset;
1762 pHalFunc->sreset_xmit_status_check = &rtl8723a_sreset_xmit_status_check;
1763 pHalFunc->sreset_linked_status_check =
1764 &rtl8723a_sreset_linked_status_check;
1765 pHalFunc->sreset_get_wifi_status23a = &sreset_get_wifi_status23a;
1766 pHalFunc->sreset_inprogress = &sreset_inprogress;
1767 pHalFunc->GetHalODMVarHandler = &rtl8723a_GetHalODMVar;
1768 pHalFunc->SetHalODMVarHandler = &rtl8723a_SetHalODMVar;
1770 pHalFunc->hal_notch_filter = &hal_notch_filter_8723a;
1772 pHalFunc->c2h_handler = c2h_handler_8723a;
1773 pHalFunc->c2h_id_filter_ccx = c2h_id_filter_ccx_8723a;
1776 void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter)
1778 struct hal_data_8723a *pHalData;
1781 pHalData = GET_HAL_DATA(padapter);
1783 val = rtw_read8(padapter, REG_LEDCFG2);
1784 /* Let 8051 take control antenna settting */
1785 val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
1786 rtw_write8(padapter, REG_LEDCFG2, val);
1789 void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter)
1791 struct hal_data_8723a *pHalData;
1794 pHalData = GET_HAL_DATA(padapter);
1796 val = rtw_read8(padapter, REG_LEDCFG2);
1797 /* Let 8051 take control antenna settting */
1798 if (!(val & BIT(7))) {
1799 val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
1800 rtw_write8(padapter, REG_LEDCFG2, val);
1804 void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter)
1806 struct hal_data_8723a *pHalData;
1809 pHalData = GET_HAL_DATA(padapter);
1810 val = rtw_read8(padapter, REG_LEDCFG2);
1811 /* Let 8051 take control antenna settting */
1812 val &= ~BIT(7); /* DPDT_SEL_EN, clear 0x4C[23] */
1813 rtw_write8(padapter, REG_LEDCFG2, val);
1816 void rtl8723a_init_default_value(struct rtw_adapter *padapter)
1818 struct hal_data_8723a *pHalData;
1819 struct dm_priv *pdmpriv;
1822 pHalData = GET_HAL_DATA(padapter);
1823 pdmpriv = &pHalData->dmpriv;
1825 /* init default value */
1826 pHalData->fw_ractrl = false;
1827 pHalData->bIQKInitialized = false;
1828 if (!padapter->pwrctrlpriv.bkeepfwalive)
1829 pHalData->LastHMEBoxNum = 0;
1831 pHalData->bIQKInitialized = false;
1833 /* init dm default value */
1834 pdmpriv->TM_Trigger = 0; /* for IQK */
1835 /* pdmpriv->binitialized = false; */
1836 /* pdmpriv->prv_traffic_idx = 3; */
1837 /* pdmpriv->initialize = 0; */
1839 pdmpriv->ThermalValue_HP_index = 0;
1840 for (i = 0; i < HP_THERMAL_NUM; i++)
1841 pdmpriv->ThermalValue_HP[i] = 0;
1843 /* init Efuse variables */
1844 pHalData->EfuseUsedBytes = 0;
1845 pHalData->BTEfuseUsedBytes = 0;
1848 u8 GetEEPROMSize8723A(struct rtw_adapter *padapter)
1853 cr = rtw_read16(padapter, REG_9346CR);
1854 /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */
1855 size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
1857 MSG_8723A("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46");
1864 /* LLT R/W/Init function */
1867 static s32 _LLTWrite(struct rtw_adapter *padapter, u32 address, u32 data)
1869 s32 status = _SUCCESS;
1871 u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) |
1872 _LLT_OP(_LLT_WRITE_ACCESS);
1873 u16 LLTReg = REG_LLT_INIT;
1875 rtw_write32(padapter, LLTReg, value);
1879 value = rtw_read32(padapter, LLTReg);
1880 if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) {
1884 if (count > POLLING_LLT_THRESHOLD) {
1885 RT_TRACE(_module_hal_init_c_, _drv_err_,
1886 ("Failed to polling write LLT done at "
1887 "address %d!\n", address));
1896 s32 InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary)
1898 s32 status = _SUCCESS;
1900 u32 txpktbuf_bndy = boundary;
1901 u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;
1903 for (i = 0; i < (txpktbuf_bndy - 1); i++) {
1904 status = _LLTWrite(padapter, i, i + 1);
1905 if (_SUCCESS != status) {
1911 status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
1912 if (_SUCCESS != status) {
1916 /* Make the other pages as ring buffer */
1917 /* This ring buffer is used as beacon buffer if we config this
1918 MAC as two MAC transfer. */
1919 /* Otherwise used as local loopback buffer. */
1920 for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
1921 status = _LLTWrite(padapter, i, (i + 1));
1922 if (_SUCCESS != status) {
1927 /* Let last entry point to the start entry of ring buffer */
1928 status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
1929 if (_SUCCESS != status) {
1936 static void _DisableGPIO(struct rtw_adapter *padapter)
1938 /***************************************
1939 j. GPIO_PIN_CTRL 0x44[31:0]= 0x000
1940 k.Value = GPIO_PIN_CTRL[7:0]
1941 l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write external PIN level
1942 m. GPIO_MUXCFG 0x42 [15:0] = 0x0780
1943 n. LEDCFG 0x4C[15:0] = 0x8080
1944 ***************************************/
1948 /* 1. Disable GPIO[7:0] */
1949 rtw_write16(padapter, REG_GPIO_PIN_CTRL + 2, 0x0000);
1950 value32 = rtw_read32(padapter, REG_GPIO_PIN_CTRL) & 0xFFFF00FF;
1951 u4bTmp = value32 & 0x000000FF;
1952 value32 |= ((u4bTmp << 8) | 0x00FF0000);
1953 rtw_write32(padapter, REG_GPIO_PIN_CTRL, value32);
1956 /* <Roger_Notes> For RTL8723u multi-function configuration which
1957 was autoload from Efuse offset 0x0a and 0x0b, */
1958 /* WLAN HW GPIO[9], GPS HW GPIO[10] and BT HW GPIO[11]. */
1959 /* Added by Roger, 2010.10.07. */
1961 /* 2. Disable GPIO[8] and GPIO[12] */
1963 /* Configure all pins as input mode. */
1964 rtw_write16(padapter, REG_GPIO_IO_SEL_2, 0x0000);
1965 value32 = rtw_read32(padapter, REG_GPIO_PIN_CTRL_2) & 0xFFFF001F;
1966 u4bTmp = value32 & 0x0000001F;
1967 /* Set pin 8, 10, 11 and pin 12 to output mode. */
1968 value32 |= ((u4bTmp << 8) | 0x001D0000);
1969 rtw_write32(padapter, REG_GPIO_PIN_CTRL_2, value32);
1971 /* 3. Disable LED0 & 1 */
1972 rtw_write16(padapter, REG_LEDCFG0, 0x8080);
1973 } /* end of _DisableGPIO() */
1975 static void _DisableRFAFEAndResetBB8192C(struct rtw_adapter *padapter)
1977 /**************************************
1978 a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue
1979 b. RF path 0 offset 0x00 = 0x00 disable RF
1980 c. APSD_CTRL 0x600[7:0] = 0x40
1981 d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine
1982 e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine
1983 ***************************************/
1984 u8 eRFPath = 0, value8 = 0;
1986 rtw_write8(padapter, REG_TXPAUSE, 0xFF);
1988 PHY_SetRFReg(padapter, (enum RF_RADIO_PATH) eRFPath, 0x0, bMaskByte0, 0x0);
1991 rtw_write8(padapter, REG_APSD_CTRL, value8); /* 0x40 */
1993 /* Set BB reset at first */
1995 value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn);
1996 rtw_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x16 */
1998 /* Set global reset. */
1999 value8 &= ~FEN_BB_GLB_RSTn;
2000 rtw_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x14 */
2002 /* 2010/08/12 MH We need to set BB/GLBAL reset to save power
2005 /* RT_TRACE(COMP_INIT, DBG_LOUD, ("======> RF off and reset BB.\n")); */
2008 static void _DisableRFAFEAndResetBB(struct rtw_adapter *padapter)
2010 _DisableRFAFEAndResetBB8192C(padapter);
2013 static void _ResetDigitalProcedure1_92C(struct rtw_adapter *padapter,
2016 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2018 if (IS_FW_81xxC(padapter) && (pHalData->FirmwareVersion <= 0x20)) {
2019 /*****************************
2020 f. MCUFWDL 0x80[7:0]= 0 reset MCU ready status
2021 g. SYS_FUNC_EN 0x02[10]= 0 reset MCU register, (8051 reset)
2022 h. SYS_FUNC_EN 0x02[15-12]= 5 reset MAC register, DCORE
2023 i. SYS_FUNC_EN 0x02[10]= 1 enable MCU register,
2025 ******************************/
2027 rtw_write8(padapter, REG_MCUFWDL, 0);
2029 valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
2030 /* reset MCU , 8051 */
2031 rtw_write16(padapter, REG_SYS_FUNC_EN, (valu16 & (~FEN_CPUEN)));
2033 valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN) & 0x0FFF;
2034 rtw_write16(padapter, REG_SYS_FUNC_EN,
2035 (valu16 | (FEN_HWPDN | FEN_ELDR))); /* reset MAC */
2037 valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
2038 /* enable MCU , 8051 */
2039 rtw_write16(padapter, REG_SYS_FUNC_EN, (valu16 | FEN_CPUEN));
2043 /* 2010/08/12 MH For USB SS, we can not stop 8051 when we
2044 are trying to enter IPS/HW&SW radio off. For
2045 S3/S4/S5/Disable, we can stop 8051 because */
2046 /* we will init FW when power on again. */
2047 /* if (!pDevice->RegUsbSS) */
2048 /* If we want to SS mode, we can not reset 8051. */
2049 if (rtw_read8(padapter, REG_MCUFWDL) & BIT1) {
2050 /* IF fw in RAM code, do reset */
2051 if (padapter->bFWReady) {
2052 /* 2010/08/25 MH Accordign to RD alfred's
2053 suggestion, we need to disable other */
2054 /* HRCV INT to influence 8051 reset. */
2055 rtw_write8(padapter, REG_FWIMR, 0x20);
2056 /* 2011/02/15 MH According to Alex's
2057 suggestion, close mask to prevent
2058 incorrect FW write operation. */
2059 rtw_write8(padapter, REG_FTIMR, 0x00);
2060 rtw_write8(padapter, REG_FSIMR, 0x00);
2062 /* 8051 reset by self */
2063 rtw_write8(padapter, REG_HMETFR + 3, 0x20);
2065 while ((retry_cnts++ < 100) &&
2067 rtw_read16(padapter, REG_SYS_FUNC_EN))) {
2068 udelay(50); /* us */
2071 if (retry_cnts >= 100) {
2072 /* Reset MAC and Enable 8051 */
2073 rtw_write8(padapter,
2074 REG_SYS_FUNC_EN + 1, 0x50);
2079 /* Reset MAC and Enable 8051 */
2080 rtw_write8(padapter, REG_SYS_FUNC_EN + 1, 0x54);
2081 rtw_write8(padapter, REG_MCUFWDL, 0);
2085 /*****************************
2086 Without HW auto state machine
2087 g. SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock
2088 h. AFE_PLL_CTRL 0x28[7:0] = 0x80 disable AFE PLL
2089 i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F gated AFE DIG_CLOCK
2090 j. SYS_ISO_CTRL 0x00[7:0] = 0xF9 isolated digital to PON
2091 ******************************/
2092 /* modify to 0x70A3 by Scott. */
2093 rtw_write16(padapter, REG_SYS_CLKR, 0x70A3);
2094 rtw_write8(padapter, REG_AFE_PLL_CTRL, 0x80);
2095 rtw_write16(padapter, REG_AFE_XTAL_CTRL, 0x880F);
2096 rtw_write8(padapter, REG_SYS_ISO_CTRL, 0xF9);
2098 /* Disable all RF/BB power */
2099 rtw_write8(padapter, REG_RF_CTRL, 0x00);
2103 static void _ResetDigitalProcedure1(struct rtw_adapter *padapter,
2106 _ResetDigitalProcedure1_92C(padapter, bWithoutHWSM);
2109 static void _ResetDigitalProcedure2(struct rtw_adapter *padapter)
2111 /*****************************
2112 k. SYS_FUNC_EN 0x03[7:0] = 0x44 disable ELDR runction
2113 l. SYS_CLKR 0x08[15:0] = 0x3083 disable ELDR clock
2114 m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON
2115 ******************************/
2116 /* modify to 0x70a3 by Scott. */
2117 rtw_write16(padapter, REG_SYS_CLKR, 0x70a3);
2118 /* modify to 0x82 by Scott. */
2119 rtw_write8(padapter, REG_SYS_ISO_CTRL + 1, 0x82);
2122 static void _DisableAnalog(struct rtw_adapter *padapter, bool bWithoutHWSM)
2124 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2129 /*****************************
2130 n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power
2131 o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power
2132 r. When driver call disable, the ASIC will turn off remaining
2134 ******************************/
2136 rtw_write8(padapter, REG_LDOA15_CTRL, 0x04);
2137 /* rtw_write8(padapter, REG_LDOV12D_CTRL, 0x54); */
2139 value8 = rtw_read8(padapter, REG_LDOV12D_CTRL);
2140 value8 &= (~LDV12_EN);
2141 rtw_write8(padapter, REG_LDOV12D_CTRL, value8);
2142 /* RT_TRACE(COMP_INIT, DBG_LOUD,
2143 (" REG_LDOV12D_CTRL Reg0x21:0x%02x.\n", value8)); */
2146 /*****************************
2147 h. SPS0_CTRL 0x11[7:0] = 0x23 enter PFM mode
2148 i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend
2149 ******************************/
2151 if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID))
2154 rtw_write8(padapter, REG_SPS0_CTRL, value8);
2157 /* value16 |= (APDM_HOST | FSM_HSUS |/PFM_ALDN); */
2158 /* 2010/08/31 According to Filen description, we need to
2159 use HW to shut down 8051 automatically. */
2160 /* Becasue suspend operatione need the asistance of 8051
2162 value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
2164 value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
2167 rtw_write16(padapter, REG_APS_FSMCO, value16); /* 0x4802 */
2169 rtw_write8(padapter, REG_RSV_CTRL, 0x0e);
2172 /* HW Auto state machine */
2173 s32 CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU)
2175 int rtStatus = _SUCCESS;
2177 if (padapter->bSurpriseRemoved) {
2180 /* RF Off Sequence ==== */
2181 _DisableRFAFEAndResetBB(padapter);
2183 /* ==== Reset digital sequence ====== */
2184 _ResetDigitalProcedure1(padapter, false);
2186 /* ==== Pull GPIO PIN to balance level and LED control ====== */
2187 _DisableGPIO(padapter);
2189 /* ==== Disable analog sequence === */
2190 _DisableAnalog(padapter, false);
2192 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2193 ("======> Card disable finished.\n"));
2198 /* without HW Auto state machine */
2199 s32 CardDisableWithoutHWSM(struct rtw_adapter *padapter)
2201 s32 rtStatus = _SUCCESS;
2203 /* RT_TRACE(COMP_INIT, DBG_LOUD,
2204 ("======> Card Disable Without HWSM .\n")); */
2205 if (padapter->bSurpriseRemoved) {
2209 /* RF Off Sequence ==== */
2210 _DisableRFAFEAndResetBB(padapter);
2212 /* ==== Reset digital sequence ====== */
2213 _ResetDigitalProcedure1(padapter, true);
2215 /* ==== Pull GPIO PIN to balance level and LED control ====== */
2216 _DisableGPIO(padapter);
2218 /* ==== Reset digital sequence ====== */
2219 _ResetDigitalProcedure2(padapter);
2221 /* ==== Disable analog sequence === */
2222 _DisableAnalog(padapter, true);
2224 /* RT_TRACE(COMP_INIT, DBG_LOUD,
2225 ("<====== Card Disable Without HWSM .\n")); */
2229 void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent)
2231 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2233 if (false == pEEPROM->bautoload_fail_flag) { /* autoload OK. */
2234 if (!pEEPROM->EepromOrEfuse) {
2235 /* Read EFUSE real map to shadow. */
2236 EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
2237 memcpy((void *)PROMContent,
2238 (void *)pEEPROM->efuse_eeprom_data,
2241 } else { /* autoload fail */
2242 RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
2243 ("AutoLoad Fail reported from CR9346!!\n"));
2244 /* pHalData->AutoloadFailFlag = true; */
2245 /* update to default value 0xFF */
2246 if (false == pEEPROM->EepromOrEfuse)
2247 EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
2248 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data,
2253 void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo)
2255 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2256 /* struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); */
2259 /* Checl 0x8129 again for making sure autoload status!! */
2260 EEPROMId = le16_to_cpu(*((u16 *) hwinfo));
2261 if (EEPROMId != RTL_EEPROM_ID) {
2262 DBG_8723A("EEPROM ID(%#x) is invalid!!\n", EEPROMId);
2263 pEEPROM->bautoload_fail_flag = true;
2265 pEEPROM->bautoload_fail_flag = false;
2268 RT_TRACE(_module_hal_init_c_, _drv_info_,
2269 ("EEPROM ID = 0x%04x\n", EEPROMId));
2272 static void Hal_EEValueCheck(u8 EEType, void *pInValue, void *pOutValue)
2278 pIn = (u8 *) pInValue;
2279 pOut = (u8 *) pOutValue;
2280 if (*pIn >= 0 && *pIn <= 63) {
2283 RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
2284 ("EETYPE_TX_PWR, value =%d is invalid, set "
2285 "to default = 0x%x\n",
2286 *pIn, EEPROM_Default_TxPowerLevel));
2287 *pOut = EEPROM_Default_TxPowerLevel;
2297 Hal_ReadPowerValueFromPROM_8723A(struct txpowerinfo *pwrInfo,
2298 u8 *PROMContent, bool AutoLoadFail)
2300 u32 rfPath, eeAddr, group, rfPathMax = 1;
2302 memset(pwrInfo, 0, sizeof(*pwrInfo));
2305 for (group = 0; group < MAX_CHNL_GROUP; group++) {
2306 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2307 pwrInfo->CCKIndex[rfPath][group] =
2308 EEPROM_Default_TxPowerLevel;
2309 pwrInfo->HT40_1SIndex[rfPath][group] =
2310 EEPROM_Default_TxPowerLevel;
2311 pwrInfo->HT40_2SIndexDiff[rfPath][group] =
2312 EEPROM_Default_HT40_2SDiff;
2313 pwrInfo->HT20IndexDiff[rfPath][group] =
2314 EEPROM_Default_HT20_Diff;
2315 pwrInfo->OFDMIndexDiff[rfPath][group] =
2316 EEPROM_Default_LegacyHTTxPowerDiff;
2317 pwrInfo->HT40MaxOffset[rfPath][group] =
2318 EEPROM_Default_HT40_PwrMaxOffset;
2319 pwrInfo->HT20MaxOffset[rfPath][group] =
2320 EEPROM_Default_HT20_PwrMaxOffset;
2323 pwrInfo->TSSI_A[0] = EEPROM_Default_TSSI;
2327 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2328 for (group = 0; group < MAX_CHNL_GROUP; group++) {
2330 EEPROM_CCK_TX_PWR_INX_8723A + (rfPath * 3) + group;
2331 /* pwrInfo->CCKIndex[rfPath][group] =
2332 PROMContent[eeAddr]; */
2333 Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
2334 &pwrInfo->CCKIndex[rfPath][group]);
2335 eeAddr = EEPROM_HT40_1S_TX_PWR_INX_8723A +
2336 (rfPath * 3) + group;
2337 /* pwrInfo->HT40_1SIndex[rfPath][group] =
2338 PROMContent[eeAddr]; */
2339 Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
2340 &pwrInfo->HT40_1SIndex[rfPath][group]);
2344 for (group = 0; group < MAX_CHNL_GROUP; group++) {
2345 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2346 pwrInfo->HT40_2SIndexDiff[rfPath][group] = 0;
2347 pwrInfo->HT20IndexDiff[rfPath][group] =
2349 [EEPROM_HT20_TX_PWR_INX_DIFF_8723A +
2350 group] >> (rfPath * 4)) & 0xF;
2351 /* 4bit sign number to 8 bit sign number */
2352 if (pwrInfo->HT20IndexDiff[rfPath][group] & BIT3)
2353 pwrInfo->HT20IndexDiff[rfPath][group] |= 0xF0;
2355 pwrInfo->OFDMIndexDiff[rfPath][group] =
2356 (PROMContent[EEPROM_OFDM_TX_PWR_INX_DIFF_8723A +
2357 group] >> (rfPath * 4)) & 0xF;
2359 pwrInfo->HT40MaxOffset[rfPath][group] =
2360 (PROMContent[EEPROM_HT40_MAX_PWR_OFFSET_8723A +
2361 group] >> (rfPath * 4)) & 0xF;
2363 pwrInfo->HT20MaxOffset[rfPath][group] =
2364 (PROMContent[EEPROM_HT20_MAX_PWR_OFFSET_8723A +
2365 group] >> (rfPath * 4)) & 0xF;
2369 pwrInfo->TSSI_A[0] = PROMContent[EEPROM_TSSI_A_8723A];
2372 static u8 Hal_GetChnlGroup(u8 chnl)
2376 if (chnl < 3) /* Cjanel 1-3 */
2378 else if (chnl < 9) /* Channel 4-9 */
2380 else /* Channel 10-14 */
2387 Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter,
2388 u8 *PROMContent, bool AutoLoadFail)
2390 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2391 struct txpowerinfo pwrInfo;
2392 u8 rfPath, ch, group, rfPathMax = 1;
2395 Hal_ReadPowerValueFromPROM_8723A(&pwrInfo, PROMContent, AutoLoadFail);
2396 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2397 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2398 group = Hal_GetChnlGroup(ch);
2400 pHalData->TxPwrLevelCck[rfPath][ch] =
2401 pwrInfo.CCKIndex[rfPath][group];
2402 pHalData->TxPwrLevelHT40_1S[rfPath][ch] =
2403 pwrInfo.HT40_1SIndex[rfPath][group];
2405 pHalData->TxPwrHt20Diff[rfPath][ch] =
2406 pwrInfo.HT20IndexDiff[rfPath][group];
2407 pHalData->TxPwrLegacyHtDiff[rfPath][ch] =
2408 pwrInfo.OFDMIndexDiff[rfPath][group];
2409 pHalData->PwrGroupHT20[rfPath][ch] =
2410 pwrInfo.HT20MaxOffset[rfPath][group];
2411 pHalData->PwrGroupHT40[rfPath][ch] =
2412 pwrInfo.HT40MaxOffset[rfPath][group];
2414 pwr = pwrInfo.HT40_1SIndex[rfPath][group];
2415 diff = pwrInfo.HT40_2SIndexDiff[rfPath][group];
2417 pHalData->TxPwrLevelHT40_2S[rfPath][ch] =
2418 (pwr > diff) ? (pwr - diff) : 0;
2421 for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
2422 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2423 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2424 ("RF(%u)-Ch(%u) [CCK / HT40_1S / HT40_2S] = "
2425 "[0x%x / 0x%x / 0x%x]\n",
2427 pHalData->TxPwrLevelCck[rfPath][ch],
2428 pHalData->TxPwrLevelHT40_1S[rfPath][ch],
2429 pHalData->TxPwrLevelHT40_2S[rfPath][ch]));
2433 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2434 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2435 ("RF-A Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
2436 pHalData->TxPwrHt20Diff[RF_PATH_A][ch],
2437 pHalData->TxPwrHt20Diff[RF_PATH_A][ch]));
2439 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
2440 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2441 ("RF-A Legacy to Ht40 Diff[%u] = 0x%x\n", ch,
2442 pHalData->TxPwrLegacyHtDiff[RF_PATH_A][ch]));
2443 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2444 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2445 ("RF-B Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
2446 pHalData->TxPwrHt20Diff[RF_PATH_B][ch],
2447 pHalData->TxPwrHt20Diff[RF_PATH_B][ch]));
2449 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
2450 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2451 ("RF-B Legacy to HT40 Diff[%u] = 0x%x\n", ch,
2452 pHalData->TxPwrLegacyHtDiff[RF_PATH_B][ch]));
2453 if (!AutoLoadFail) {
2454 struct registry_priv *registry_par = &padapter->registrypriv;
2455 if (registry_par->regulatory_tid == 0xff) {
2456 if (PROMContent[RF_OPTION1_8723A] == 0xff)
2457 pHalData->EEPROMRegulatory = 0;
2459 pHalData->EEPROMRegulatory =
2460 PROMContent[RF_OPTION1_8723A] & 0x7;
2462 pHalData->EEPROMRegulatory =
2463 registry_par->regulatory_tid;
2466 pHalData->EEPROMRegulatory = 0;
2468 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2469 ("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory));
2472 pHalData->bTXPowerDataReadFromEEPORM = true;
2476 Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter,
2477 u8 *hwinfo, bool AutoLoadFail)
2479 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2483 if (!AutoLoadFail) {
2484 tmpu4 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
2485 if (tmpu4 & BT_FUNC_EN)
2486 pHalData->EEPROMBluetoothCoexist = 1;
2488 pHalData->EEPROMBluetoothCoexist = 0;
2489 pHalData->EEPROMBluetoothType = BT_RTL8723A;
2491 /* The following need to be checked with newer version of */
2493 tempval = hwinfo[RF_OPTION4_8723A];
2494 pHalData->EEPROMBluetoothAntNum = (tempval & 0x1);
2495 pHalData->EEPROMBluetoothAntIsolation = ((tempval & 0x10) >> 4);
2496 pHalData->EEPROMBluetoothRadioShared = ((tempval & 0x20) >> 5);
2498 pHalData->EEPROMBluetoothCoexist = 0;
2499 pHalData->EEPROMBluetoothType = BT_RTL8723A;
2500 pHalData->EEPROMBluetoothAntNum = Ant_x2;
2501 pHalData->EEPROMBluetoothAntIsolation = 0;
2502 pHalData->EEPROMBluetoothRadioShared = BT_Radio_Shared;
2504 #ifdef CONFIG_8723AU_BT_COEXIST
2505 BT_InitHalVars(padapter);
2510 Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter,
2511 u8 *hwinfo, bool AutoLoadFail)
2513 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2516 pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723A];
2518 pHalData->EEPROMVersion = 1;
2519 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2520 ("Hal_EfuseParseEEPROMVer(), EEVer = %d\n",
2521 pHalData->EEPROMVersion));
2525 rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter,
2526 u8 *hwinfo, bool AutoLoadFail)
2528 padapter->mlmepriv.ChannelPlan =
2529 hal_com_get_channel_plan23a(padapter, hwinfo ?
2530 hwinfo[EEPROM_ChannelPlan_8723A]:0xFF,
2531 padapter->registrypriv.channel_plan,
2532 RT_CHANNEL_DOMAIN_WORLD_WIDE_13,
2535 DBG_8723A("mlmepriv.ChannelPlan = 0x%02x\n",
2536 padapter->mlmepriv.ChannelPlan);
2540 Hal_EfuseParseCustomerID(struct rtw_adapter *padapter,
2541 u8 *hwinfo, bool AutoLoadFail)
2543 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2545 if (!AutoLoadFail) {
2546 pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723A];
2547 pHalData->EEPROMSubCustomerID =
2548 hwinfo[EEPROM_SubCustomID_8723A];
2550 pHalData->EEPROMCustomerID = 0;
2551 pHalData->EEPROMSubCustomerID = 0;
2553 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2554 ("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID));
2555 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2556 ("EEPROM SubCustomer ID: 0x%02x\n",
2557 pHalData->EEPROMSubCustomerID));
2561 Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter,
2562 u8 *hwinfo, bool AutoLoadFail)
2567 Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter,
2568 u8 *hwinfo, bool AutoLoadFail)
2573 Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter,
2574 u8 *hwinfo, u8 AutoLoadFail)
2576 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
2578 if (!AutoLoadFail) {
2579 pHalData->CrystalCap = hwinfo[EEPROM_XTAL_K_8723A];
2580 if (pHalData->CrystalCap == 0xFF)
2581 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
2583 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
2585 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2586 ("%s: CrystalCap = 0x%2x\n", __func__,
2587 pHalData->CrystalCap));
2591 Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter,
2592 u8 *PROMContent, u8 AutoloadFail)
2594 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2597 /* ThermalMeter from EEPROM */
2599 if (false == AutoloadFail)
2600 pHalData->EEPROMThermalMeter =
2601 PROMContent[EEPROM_THERMAL_METER_8723A];
2603 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2605 if ((pHalData->EEPROMThermalMeter == 0xff) || (true == AutoloadFail)) {
2606 pHalData->bAPKThermalMeterIgnore = true;
2607 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2610 DBG_8723A("%s: ThermalMeter = 0x%x\n", __func__,
2611 pHalData->EEPROMThermalMeter);
2614 void Hal_InitChannelPlan23a(struct rtw_adapter *padapter)
2618 static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc)
2620 u16 *usPtr = (u16 *) ptxdesc;
2621 u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
2626 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
2628 for (index = 0; index < count; index++) {
2629 checksum ^= le16_to_cpu(*(usPtr + index));
2632 ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
2635 static void fill_txdesc_sectype(struct pkt_attrib *pattrib,
2636 struct txdesc_8723a *ptxdesc)
2638 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
2639 switch (pattrib->encrypt) {
2645 ptxdesc->sectype = 1;
2649 ptxdesc->sectype = 3;
2659 static void fill_txdesc_vcs(struct pkt_attrib *pattrib,
2660 struct txdesc_8723a *ptxdesc)
2662 /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */
2664 switch (pattrib->vcs_mode) {
2670 ptxdesc->cts2self = 1;
2678 if (pattrib->vcs_mode) {
2679 ptxdesc->hw_rts_en = 1; /* ENABLE HW RTS */
2682 if (pattrib->ht_en) {
2683 if (pattrib->bwmode & HT_CHANNEL_WIDTH_40)
2684 ptxdesc->rts_bw = 1;
2686 switch (pattrib->ch_offset) {
2687 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
2688 ptxdesc->rts_sc = 0;
2691 case HAL_PRIME_CHNL_OFFSET_LOWER:
2692 ptxdesc->rts_sc = 1;
2695 case HAL_PRIME_CHNL_OFFSET_UPPER:
2696 ptxdesc->rts_sc = 2;
2700 ptxdesc->rts_sc = 3; /* Duplicate */
2707 static void fill_txdesc_phy(struct pkt_attrib *pattrib,
2708 struct txdesc_8723a *ptxdesc)
2710 if (pattrib->ht_en) {
2711 if (pattrib->bwmode & HT_CHANNEL_WIDTH_40)
2712 ptxdesc->data_bw = 1;
2714 switch (pattrib->ch_offset) {
2715 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
2716 ptxdesc->data_sc = 0;
2719 case HAL_PRIME_CHNL_OFFSET_LOWER:
2720 ptxdesc->data_sc = 1;
2723 case HAL_PRIME_CHNL_OFFSET_UPPER:
2724 ptxdesc->data_sc = 2;
2728 ptxdesc->data_sc = 3; /* Duplicate */
2734 static void rtl8723a_fill_default_txdesc(struct xmit_frame *pxmitframe,
2737 struct rtw_adapter *padapter;
2738 struct hal_data_8723a *pHalData;
2739 struct dm_priv *pdmpriv;
2740 struct mlme_ext_priv *pmlmeext;
2741 struct mlme_ext_info *pmlmeinfo;
2742 struct pkt_attrib *pattrib;
2743 struct txdesc_8723a *ptxdesc;
2746 padapter = pxmitframe->padapter;
2747 pHalData = GET_HAL_DATA(padapter);
2748 pdmpriv = &pHalData->dmpriv;
2749 pmlmeext = &padapter->mlmeextpriv;
2750 pmlmeinfo = &pmlmeext->mlmext_info;
2752 pattrib = &pxmitframe->attrib;
2753 bmcst = is_multicast_ether_addr(pattrib->ra);
2755 ptxdesc = (struct txdesc_8723a *)pbuf;
2757 if (pxmitframe->frame_tag == DATA_FRAMETAG) {
2758 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2760 if (pattrib->ampdu_en == true)
2761 ptxdesc->agg_en = 1; /* AGG EN */
2763 ptxdesc->bk = 1; /* AGG BK */
2765 ptxdesc->qsel = pattrib->qsel;
2766 ptxdesc->rate_id = pattrib->raid;
2768 fill_txdesc_sectype(pattrib, ptxdesc);
2770 ptxdesc->seq = pattrib->seqnum;
2772 if ((pattrib->ether_type != 0x888e) &&
2773 (pattrib->ether_type != 0x0806) &&
2774 (pattrib->dhcp_pkt != 1)) {
2775 /* Non EAP & ARP & DHCP type data packet */
2777 fill_txdesc_vcs(pattrib, ptxdesc);
2778 fill_txdesc_phy(pattrib, ptxdesc);
2780 ptxdesc->rtsrate = 8; /* RTS Rate = 24M */
2781 ptxdesc->data_ratefb_lmt = 0x1F;
2782 ptxdesc->rts_ratefb_lmt = 0xF;
2784 /* use REG_INIDATA_RATE_SEL value */
2786 pdmpriv->INIDATA_RATE[pattrib->mac_id];
2789 /* EAP data packet and ARP packet. */
2790 /* Use the 1M data rate to send the EAP/ARP packet. */
2791 /* This will maybe make the handshake smooth. */
2793 ptxdesc->bk = 1; /* AGG BK */
2794 ptxdesc->userate = 1; /* driver uses rate */
2795 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
2796 ptxdesc->data_short = 1;
2797 ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
2799 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
2800 /* RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
2801 ("%s: MGNT_FRAMETAG\n", __func__)); */
2803 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2804 ptxdesc->qsel = pattrib->qsel;
2805 ptxdesc->rate_id = pattrib->raid; /* Rate ID */
2806 ptxdesc->seq = pattrib->seqnum;
2807 ptxdesc->userate = 1; /* driver uses rate, 1M */
2808 ptxdesc->rty_lmt_en = 1; /* retry limit enable */
2809 ptxdesc->data_rt_lmt = 6; /* retry limit = 6 */
2811 /* CCX-TXRPT ack for xmit mgmt frames. */
2812 if (pxmitframe->ack_report)
2815 ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
2816 } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
2817 RT_TRACE(_module_hal_xmit_c_, _drv_warning_,
2818 ("%s: TXAGG_FRAMETAG\n", __func__));
2820 RT_TRACE(_module_hal_xmit_c_, _drv_warning_,
2821 ("%s: frame_tag = 0x%x\n", __func__,
2822 pxmitframe->frame_tag));
2824 ptxdesc->macid = 4; /* CAM_ID(MAC_ID) */
2825 ptxdesc->rate_id = 6; /* Rate ID */
2826 ptxdesc->seq = pattrib->seqnum;
2827 ptxdesc->userate = 1; /* driver uses rate */
2828 ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
2831 ptxdesc->pktlen = pattrib->last_txcmdsz;
2832 ptxdesc->offset = TXDESC_SIZE + OFFSET_SZ;
2839 /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
2840 /* (1) The sequence number of each non-Qos frame / broadcast /
2841 * multicast / mgnt frame should be controled by Hw because Fw
2842 * will also send null data which we cannot control when Fw LPS enable.
2843 * --> default enable non-Qos data sequense number.
2844 2010.06.23. by tynli. */
2845 /* (2) Enable HW SEQ control for beacon packet,
2846 * because we use Hw beacon. */
2847 /* (3) Use HW Qos SEQ to control the seq num of Ext port
2848 * non-Qos packets. */
2849 /* 2010.06.23. Added by tynli. */
2850 if (!pattrib->qos_en) {
2851 /* Hw set sequence number */
2852 ptxdesc->hwseq_en = 1; /* HWSEQ_EN */
2853 ptxdesc->hwseq_sel = 0; /* HWSEQ_SEL */
2861 * pxmitframe xmitframe
2862 * pbuf where to fill tx desc
2864 void rtl8723a_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf)
2866 struct tx_desc *pdesc;
2868 pdesc = (struct tx_desc *)pbuf;
2869 memset(pdesc, 0, sizeof(struct tx_desc));
2871 rtl8723a_fill_default_txdesc(pxmitframe, pbuf);
2873 pdesc->txdw0 = cpu_to_le32(pdesc->txdw0);
2874 pdesc->txdw1 = cpu_to_le32(pdesc->txdw1);
2875 pdesc->txdw2 = cpu_to_le32(pdesc->txdw2);
2876 pdesc->txdw3 = cpu_to_le32(pdesc->txdw3);
2877 pdesc->txdw4 = cpu_to_le32(pdesc->txdw4);
2878 pdesc->txdw5 = cpu_to_le32(pdesc->txdw5);
2879 pdesc->txdw6 = cpu_to_le32(pdesc->txdw6);
2880 pdesc->txdw7 = cpu_to_le32(pdesc->txdw7);
2881 rtl8723a_cal_txdesc_chksum(pdesc);
2885 * Description: In normal chip, we should send some packet to Hw which
2886 * will be used by Fw in FW LPS mode. The function is to fill the Tx
2887 * descriptor of this packets, then
2889 /* Fw can tell Hw to send these packet derectly. */
2890 /* Added by tynli. 2009.10.15. */
2892 void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc,
2893 u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull)
2895 struct tx_desc *ptxdesc;
2897 /* Clear all status */
2898 ptxdesc = (struct tx_desc *)pDesc;
2899 memset(pDesc, 0, TXDESC_SIZE);
2902 /* own, bFirstSeg, bLastSeg; */
2903 ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
2905 /* 32 bytes for TX Desc */
2906 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) <<
2907 OFFSET_SHT) & 0x00ff0000);
2909 /* Buffer size + command header */
2910 ptxdesc->txdw0 |= cpu_to_le32(BufferLen & 0x0000ffff);
2913 /* Fixed queue of Mgnt queue */
2914 ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT << QSEL_SHT) & 0x00001f00);
2916 /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed
2917 to error vlaue by Hw. */
2919 ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
2921 /* Hw set sequence number */
2922 ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
2923 /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */
2924 ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
2927 if (true == IsBTQosNull) {
2928 ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */
2932 ptxdesc->txdw4 |= cpu_to_le32(BIT(8)); /* driver uses rate */
2934 /* USB interface drop packet if the checksum of descriptor isn't
2936 /* Using this checksum can let hardware recovery from packet bulk
2937 out error (e.g. Cancel URC, Bulk out error.). */
2938 rtl8723a_cal_txdesc_chksum(ptxdesc);
2941 void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode)
2945 if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
2946 StopTxBeacon(padapter);
2948 /* disable atim wnd */
2949 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_ATIM;
2950 SetBcnCtrlReg23a(padapter, val8, ~val8);
2951 } else if ((mode == _HW_STATE_ADHOC_) /*|| (mode == _HW_STATE_AP_) */) {
2952 ResumeTxBeacon(padapter);
2954 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB;
2955 SetBcnCtrlReg23a(padapter, val8, ~val8);
2956 } else if (mode == _HW_STATE_AP_) {
2957 #ifdef CONFIG_8723AU_BT_COEXIST
2958 /* add NULL Data and BT NULL Data Packets to FW RSVD Page */
2959 rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter);
2962 ResumeTxBeacon(padapter);
2964 val8 = DIS_TSF_UDT | DIS_BCNQ_SUB;
2965 SetBcnCtrlReg23a(padapter, val8, ~val8);
2968 /* rtw_write32(padapter, REG_RCR, 0x70002a8e);
2969 CBSSID_DATA must set to 0 */
2970 /* CBSSID_DATA must set to 0 */
2971 rtw_write32(padapter, REG_RCR, 0x7000228e);
2972 /* enable to rx data frame */
2973 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
2974 /* enable to rx ps-poll */
2975 rtw_write16(padapter, REG_RXFLTMAP1, 0x0400);
2977 /* Beacon Control related register for first time */
2978 rtw_write8(padapter, REG_BCNDMATIM, 0x02); /* 2ms */
2979 rtw_write8(padapter, REG_DRVERLYINT, 0x05); /* 5ms */
2980 rtw_write8(padapter, REG_ATIMWND, 0x0a); /* 10ms for port0 */
2981 rtw_write16(padapter, REG_BCNTCFG, 0x00);
2982 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0xff04);
2983 /* +32767 (~32ms) */
2984 rtw_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff);
2987 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
2989 /* enable BCN Function */
2990 /* don't enable update TSF (due to TSF update when
2991 beacon/probe rsp are received) */
2992 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION |
2993 EN_TXBCN_RPT | DIS_BCNQ_SUB;
2994 SetBcnCtrlReg23a(padapter, val8, ~val8);
2997 val8 = rtw_read8(padapter, MSR);
2998 val8 = (val8 & 0xC) | mode;
2999 rtw_write8(padapter, MSR, val8);
3002 void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val)
3007 reg_macid = REG_MACID;
3009 for (idx = 0; idx < 6; idx++)
3010 rtw_write8(padapter, (reg_macid + idx), val[idx]);
3013 void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val)
3018 reg_bssid = REG_BSSID;
3020 for (idx = 0; idx < 6; idx++)
3021 rtw_write8(padapter, (reg_bssid + idx), val[idx]);
3024 void hw_var_set_correct_tsf(struct rtw_adapter *padapter)
3028 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3029 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3031 /* tsf = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue %
3032 (pmlmeinfo->bcn_interval*1024)) - 1024; us */
3033 tsf = pmlmeext->TSFValue -
3034 do_div(pmlmeext->TSFValue,
3035 (pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */
3037 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
3038 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
3039 /* pHalData->RegTxPause |= STOP_BCNQ;BIT(6) */
3040 /* rtw_write8(padapter, REG_TXPAUSE,
3041 (rtw_read8(Adapter, REG_TXPAUSE)|BIT(6))); */
3042 StopTxBeacon(padapter);
3045 reg_tsftr = REG_TSFTR;
3047 /* disable related TSF function */
3048 SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION);
3050 rtw_write32(padapter, reg_tsftr, tsf);
3051 rtw_write32(padapter, reg_tsftr + 4, tsf >> 32);
3053 /* enable related TSF function */
3054 SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION, 0);
3056 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
3057 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
3058 ResumeTxBeacon(padapter);
3061 void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter)
3063 /* reject all data frames */
3064 rtw_write16(padapter, REG_RXFLTMAP2, 0);
3067 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
3069 /* disable update TSF */
3070 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
3073 void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type)
3075 u8 RetryLimit = 0x30;
3077 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
3078 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3080 if (type == 0) { /* prepare to join */
3083 /* enable to rx data frame.Accept all data frame */
3084 /* rtw_write32(padapter, REG_RCR,
3085 rtw_read32(padapter, REG_RCR)|RCR_ADF); */
3086 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
3088 v32 = rtw_read32(padapter, REG_RCR);
3089 v32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
3090 rtw_write32(padapter, REG_RCR, v32);
3092 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
3094 (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48;
3095 else /* Ad-hoc Mode */
3097 } else if (type == 1) { /* joinbss_event callback when join res < 0 */
3098 /* config RCR to receive different BSSID & not to
3099 receive data frame during linking */
3100 rtw_write16(padapter, REG_RXFLTMAP2, 0);
3101 } else if (type == 2) { /* sta add event callback */
3102 /* enable update TSF */
3103 SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
3105 if (check_fwstate(pmlmepriv,
3106 WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
3107 /* fixed beacon issue for 8191su........... */
3108 rtw_write8(padapter, 0x542, 0x02);
3113 rtw_write16(padapter, REG_RL,
3114 RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit <<
3115 RETRY_LIMIT_LONG_SHIFT);
3117 #ifdef CONFIG_8723AU_BT_COEXIST
3120 /* prepare to join */
3121 BT_WifiAssociateNotify(padapter, true);
3124 /* joinbss_event callback when join res < 0 */
3125 BT_WifiAssociateNotify(padapter, false);
3128 /* sta add event callback */
3129 /* BT_WifiMediaStatusNotify(padapter, RT_MEDIA_CONNECT); */
3135 #ifdef CONFIG_8723AU_BT_COEXIST
3137 void rtl8723a_SingleDualAntennaDetection(struct rtw_adapter *padapter)
3139 struct hal_data_8723a *pHalData;
3140 struct dm_odm_t *pDM_Odm;
3141 struct sw_ant_sw *pDM_SWAT_Table;
3144 pHalData = GET_HAL_DATA(padapter);
3145 pDM_Odm = &pHalData->odmpriv;
3146 pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
3149 /* <Roger_Notes> RTL8723A Single and Dual antenna dynamic detection
3150 mechanism when RF power state is on. */
3151 /* We should take power tracking, IQK, LCK, RCK RF read/write
3152 operation into consideration. */
3155 if (!pHalData->bAntennaDetected) {
3156 u8 btAntNum = BT_GetPGAntNum(padapter);
3158 /* Set default antenna B status */
3159 if (btAntNum == Ant_x2)
3160 pDM_SWAT_Table->ANTB_ON = true;
3161 else if (btAntNum == Ant_x1)
3162 pDM_SWAT_Table->ANTB_ON = false;
3164 pDM_SWAT_Table->ANTB_ON = true;
3166 if (pHalData->CustomerID != RT_CID_TOSHIBA) {
3167 for (i = 0; i < MAX_ANTENNA_DETECTION_CNT; i++) {
3168 if (ODM_SingleDualAntennaDetection
3169 (&pHalData->odmpriv, ANTTESTALL) == true)
3173 /* Set default antenna number for BT coexistence */
3174 if (btAntNum == Ant_x2)
3175 BT_SetBtCoexCurrAntNum(padapter,
3179 pHalData->bAntennaDetected = true;
3182 #endif /* CONFIG_8723AU_BT_COEXIST */
3184 void rtl8723a_clone_haldata(struct rtw_adapter *dst_adapter,
3185 struct rtw_adapter *src_adapter)
3187 memcpy(dst_adapter->HalData, src_adapter->HalData,
3188 dst_adapter->hal_data_sz);
3191 void rtl8723a_start_thread(struct rtw_adapter *padapter)
3195 void rtl8723a_stop_thread(struct rtw_adapter *padapter)