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