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 registers 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 /* because 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 /* Check 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_SetPgAntNum(padapter, pHalData->EEPROMBluetoothAntNum == Ant_x2 ? 2 : 1); 2308 if (pHalData->EEPROMBluetoothAntNum == Ant_x1) 2309 hal_btcoex_SetSingleAntPath(padapter, pHalData->ant_path); 2310 } 2311 2312 void Hal_EfuseParseEEPROMVer_8723B( 2313 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail 2314 ) 2315 { 2316 struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 2317 2318 if (!AutoLoadFail) 2319 pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723B]; 2320 else 2321 pHalData->EEPROMVersion = 1; 2322 } 2323 2324 2325 2326 void Hal_EfuseParsePackageType_8723B( 2327 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail 2328 ) 2329 { 2330 struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 2331 u8 package; 2332 u8 efuseContent; 2333 2334 Efuse_PowerSwitch(padapter, false, true); 2335 efuse_OneByteRead(padapter, 0x1FB, &efuseContent, false); 2336 Efuse_PowerSwitch(padapter, false, false); 2337 2338 package = efuseContent & 0x7; 2339 switch (package) { 2340 case 0x4: 2341 pHalData->PackageType = PACKAGE_TFBGA79; 2342 break; 2343 case 0x5: 2344 pHalData->PackageType = PACKAGE_TFBGA90; 2345 break; 2346 case 0x6: 2347 pHalData->PackageType = PACKAGE_QFN68; 2348 break; 2349 case 0x7: 2350 pHalData->PackageType = PACKAGE_TFBGA80; 2351 break; 2352 2353 default: 2354 pHalData->PackageType = PACKAGE_DEFAULT; 2355 break; 2356 } 2357 } 2358 2359 2360 void Hal_EfuseParseVoltage_8723B( 2361 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail 2362 ) 2363 { 2364 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); 2365 2366 /* memcpy(pEEPROM->adjuseVoltageVal, &hwinfo[EEPROM_Voltage_ADDR_8723B], 1); */ 2367 pEEPROM->adjuseVoltageVal = (hwinfo[EEPROM_Voltage_ADDR_8723B] & 0xf0) >> 4; 2368 } 2369 2370 void Hal_EfuseParseChnlPlan_8723B( 2371 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail 2372 ) 2373 { 2374 padapter->mlmepriv.ChannelPlan = hal_com_config_channel_plan( 2375 padapter, 2376 hwinfo ? hwinfo[EEPROM_ChannelPlan_8723B] : 0xFF, 2377 padapter->registrypriv.channel_plan, 2378 RT_CHANNEL_DOMAIN_WORLD_NULL, 2379 AutoLoadFail 2380 ); 2381 2382 Hal_ChannelPlanToRegulation(padapter, padapter->mlmepriv.ChannelPlan); 2383 } 2384 2385 void Hal_EfuseParseCustomerID_8723B( 2386 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail 2387 ) 2388 { 2389 struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 2390 2391 if (!AutoLoadFail) 2392 pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723B]; 2393 else 2394 pHalData->EEPROMCustomerID = 0; 2395 } 2396 2397 void Hal_EfuseParseAntennaDiversity_8723B( 2398 struct adapter *padapter, 2399 u8 *hwinfo, 2400 bool AutoLoadFail 2401 ) 2402 { 2403 } 2404 2405 void Hal_EfuseParseXtal_8723B( 2406 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail 2407 ) 2408 { 2409 struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 2410 2411 if (!AutoLoadFail) { 2412 pHalData->CrystalCap = hwinfo[EEPROM_XTAL_8723B]; 2413 if (pHalData->CrystalCap == 0xFF) 2414 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B; /* what value should 8812 set? */ 2415 } else 2416 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B; 2417 } 2418 2419 2420 void Hal_EfuseParseThermalMeter_8723B( 2421 struct adapter *padapter, u8 *PROMContent, u8 AutoLoadFail 2422 ) 2423 { 2424 struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 2425 2426 /* */ 2427 /* ThermalMeter from EEPROM */ 2428 /* */ 2429 if (!AutoLoadFail) 2430 pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_8723B]; 2431 else 2432 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B; 2433 2434 if ((pHalData->EEPROMThermalMeter == 0xff) || AutoLoadFail) { 2435 pHalData->bAPKThermalMeterIgnore = true; 2436 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B; 2437 } 2438 } 2439 2440 2441 void Hal_ReadRFGainOffset( 2442 struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail 2443 ) 2444 { 2445 /* */ 2446 /* BB_RF Gain Offset from EEPROM */ 2447 /* */ 2448 2449 if (!AutoloadFail) { 2450 Adapter->eeprompriv.EEPROMRFGainOffset = PROMContent[EEPROM_RF_GAIN_OFFSET]; 2451 Adapter->eeprompriv.EEPROMRFGainVal = EFUSE_Read1Byte(Adapter, EEPROM_RF_GAIN_VAL); 2452 } else { 2453 Adapter->eeprompriv.EEPROMRFGainOffset = 0; 2454 Adapter->eeprompriv.EEPROMRFGainVal = 0xFF; 2455 } 2456 } 2457 2458 u8 BWMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib) 2459 { 2460 u8 BWSettingOfDesc = 0; 2461 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); 2462 2463 if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) { 2464 if (pattrib->bwmode == CHANNEL_WIDTH_40) 2465 BWSettingOfDesc = 1; 2466 else 2467 BWSettingOfDesc = 0; 2468 } else 2469 BWSettingOfDesc = 0; 2470 2471 /* if (pTcb->bBTTxPacket) */ 2472 /* BWSettingOfDesc = 0; */ 2473 2474 return BWSettingOfDesc; 2475 } 2476 2477 u8 SCMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib) 2478 { 2479 u8 SCSettingOfDesc = 0; 2480 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); 2481 2482 if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) { 2483 if (pattrib->bwmode == CHANNEL_WIDTH_40) { 2484 SCSettingOfDesc = HT_DATA_SC_DONOT_CARE; 2485 } else if (pattrib->bwmode == CHANNEL_WIDTH_20) { 2486 if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) { 2487 SCSettingOfDesc = HT_DATA_SC_20_UPPER_OF_40MHZ; 2488 } else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) { 2489 SCSettingOfDesc = HT_DATA_SC_20_LOWER_OF_40MHZ; 2490 } else { 2491 SCSettingOfDesc = HT_DATA_SC_DONOT_CARE; 2492 } 2493 } 2494 } else { 2495 SCSettingOfDesc = HT_DATA_SC_DONOT_CARE; 2496 } 2497 2498 return SCSettingOfDesc; 2499 } 2500 2501 static void rtl8723b_cal_txdesc_chksum(struct tx_desc *ptxdesc) 2502 { 2503 u16 *usPtr = (u16 *)ptxdesc; 2504 u32 count; 2505 u32 index; 2506 u16 checksum = 0; 2507 2508 2509 /* Clear first */ 2510 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000); 2511 2512 /* checksum is always calculated by first 32 bytes, */ 2513 /* and it doesn't depend on TX DESC length. */ 2514 /* Thomas, Lucas@SD4, 20130515 */ 2515 count = 16; 2516 2517 for (index = 0; index < count; index++) { 2518 checksum |= le16_to_cpu(*(__le16 *)(usPtr + index)); 2519 } 2520 2521 ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff); 2522 } 2523 2524 static u8 fill_txdesc_sectype(struct pkt_attrib *pattrib) 2525 { 2526 u8 sectype = 0; 2527 if ((pattrib->encrypt > 0) && !pattrib->bswenc) { 2528 switch (pattrib->encrypt) { 2529 /* SEC_TYPE */ 2530 case _WEP40_: 2531 case _WEP104_: 2532 case _TKIP_: 2533 case _TKIP_WTMIC_: 2534 sectype = 1; 2535 break; 2536 2537 case _AES_: 2538 sectype = 3; 2539 break; 2540 2541 case _NO_PRIVACY_: 2542 default: 2543 break; 2544 } 2545 } 2546 return sectype; 2547 } 2548 2549 static void fill_txdesc_vcs_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc) 2550 { 2551 if (pattrib->vcs_mode) { 2552 switch (pattrib->vcs_mode) { 2553 case RTS_CTS: 2554 ptxdesc->rtsen = 1; 2555 /* ENABLE HW RTS */ 2556 ptxdesc->hw_rts_en = 1; 2557 break; 2558 2559 case CTS_TO_SELF: 2560 ptxdesc->cts2self = 1; 2561 break; 2562 2563 case NONE_VCS: 2564 default: 2565 break; 2566 } 2567 2568 ptxdesc->rtsrate = 8; /* RTS Rate =24M */ 2569 ptxdesc->rts_ratefb_lmt = 0xF; 2570 2571 if (padapter->mlmeextpriv.mlmext_info.preamble_mode == PREAMBLE_SHORT) 2572 ptxdesc->rts_short = 1; 2573 2574 /* Set RTS BW */ 2575 if (pattrib->ht_en) 2576 ptxdesc->rts_sc = SCMapping_8723B(padapter, pattrib); 2577 } 2578 } 2579 2580 static void fill_txdesc_phy_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc) 2581 { 2582 if (pattrib->ht_en) { 2583 ptxdesc->data_bw = BWMapping_8723B(padapter, pattrib); 2584 2585 ptxdesc->data_sc = SCMapping_8723B(padapter, pattrib); 2586 } 2587 } 2588 2589 static void rtl8723b_fill_default_txdesc( 2590 struct xmit_frame *pxmitframe, u8 *pbuf 2591 ) 2592 { 2593 struct adapter *padapter; 2594 struct hal_com_data *pHalData; 2595 struct mlme_ext_priv *pmlmeext; 2596 struct mlme_ext_info *pmlmeinfo; 2597 struct pkt_attrib *pattrib; 2598 struct txdesc_8723b *ptxdesc; 2599 s32 bmcst; 2600 2601 memset(pbuf, 0, TXDESC_SIZE); 2602 2603 padapter = pxmitframe->padapter; 2604 pHalData = GET_HAL_DATA(padapter); 2605 pmlmeext = &padapter->mlmeextpriv; 2606 pmlmeinfo = &(pmlmeext->mlmext_info); 2607 2608 pattrib = &pxmitframe->attrib; 2609 bmcst = IS_MCAST(pattrib->ra); 2610 2611 ptxdesc = (struct txdesc_8723b *)pbuf; 2612 2613 if (pxmitframe->frame_tag == DATA_FRAMETAG) { 2614 u8 drv_userate = 0; 2615 2616 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */ 2617 ptxdesc->rate_id = pattrib->raid; 2618 ptxdesc->qsel = pattrib->qsel; 2619 ptxdesc->seq = pattrib->seqnum; 2620 2621 ptxdesc->sectype = fill_txdesc_sectype(pattrib); 2622 fill_txdesc_vcs_8723b(padapter, pattrib, ptxdesc); 2623 2624 if (pattrib->icmp_pkt == 1 && padapter->registrypriv.wifi_spec == 1) 2625 drv_userate = 1; 2626 2627 if ( 2628 (pattrib->ether_type != 0x888e) && 2629 (pattrib->ether_type != 0x0806) && 2630 (pattrib->ether_type != 0x88B4) && 2631 (pattrib->dhcp_pkt != 1) && 2632 (drv_userate != 1) 2633 ) { 2634 /* Non EAP & ARP & DHCP type data packet */ 2635 2636 if (pattrib->ampdu_en) { 2637 ptxdesc->agg_en = 1; /* AGG EN */ 2638 ptxdesc->max_agg_num = 0x1f; 2639 ptxdesc->ampdu_density = pattrib->ampdu_spacing; 2640 } else 2641 ptxdesc->bk = 1; /* AGG BK */ 2642 2643 fill_txdesc_phy_8723b(padapter, pattrib, ptxdesc); 2644 2645 ptxdesc->data_ratefb_lmt = 0x1F; 2646 2647 if (!pHalData->fw_ractrl) { 2648 ptxdesc->userate = 1; 2649 2650 if (pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & BIT(7)) 2651 ptxdesc->data_short = 1; 2652 2653 ptxdesc->datarate = pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & 0x7F; 2654 } 2655 2656 if (padapter->fix_rate != 0xFF) { /* modify data rate by iwpriv */ 2657 ptxdesc->userate = 1; 2658 if (padapter->fix_rate & BIT(7)) 2659 ptxdesc->data_short = 1; 2660 2661 ptxdesc->datarate = (padapter->fix_rate & 0x7F); 2662 ptxdesc->disdatafb = 1; 2663 } 2664 2665 if (pattrib->ldpc) 2666 ptxdesc->data_ldpc = 1; 2667 if (pattrib->stbc) 2668 ptxdesc->data_stbc = 1; 2669 } else { 2670 /* EAP data packet and ARP packet. */ 2671 /* Use the 1M data rate to send the EAP/ARP packet. */ 2672 /* This will maybe make the handshake smooth. */ 2673 2674 ptxdesc->bk = 1; /* AGG BK */ 2675 ptxdesc->userate = 1; /* driver uses rate */ 2676 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT) 2677 ptxdesc->data_short = 1;/* DATA_SHORT */ 2678 ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate); 2679 } 2680 2681 ptxdesc->usb_txagg_num = pxmitframe->agg_num; 2682 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { 2683 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */ 2684 ptxdesc->qsel = pattrib->qsel; 2685 ptxdesc->rate_id = pattrib->raid; /* Rate ID */ 2686 ptxdesc->seq = pattrib->seqnum; 2687 ptxdesc->userate = 1; /* driver uses rate, 1M */ 2688 2689 ptxdesc->mbssid = pattrib->mbssid & 0xF; 2690 2691 ptxdesc->rty_lmt_en = 1; /* retry limit enable */ 2692 if (pattrib->retry_ctrl) { 2693 ptxdesc->data_rt_lmt = 6; 2694 } else { 2695 ptxdesc->data_rt_lmt = 12; 2696 } 2697 2698 ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate); 2699 2700 /* CCX-TXRPT ack for xmit mgmt frames. */ 2701 if (pxmitframe->ack_report) { 2702 ptxdesc->spe_rpt = 1; 2703 ptxdesc->sw_define = (u8)(GET_PRIMARY_ADAPTER(padapter)->xmitpriv.seq_no); 2704 } 2705 } else { 2706 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */ 2707 ptxdesc->rate_id = pattrib->raid; /* Rate ID */ 2708 ptxdesc->qsel = pattrib->qsel; 2709 ptxdesc->seq = pattrib->seqnum; 2710 ptxdesc->userate = 1; /* driver uses rate */ 2711 ptxdesc->datarate = MRateToHwRate(pmlmeext->tx_rate); 2712 } 2713 2714 ptxdesc->pktlen = pattrib->last_txcmdsz; 2715 ptxdesc->offset = TXDESC_SIZE + OFFSET_SZ; 2716 2717 if (bmcst) 2718 ptxdesc->bmc = 1; 2719 2720 /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. 2721 * (1) The sequence number of each non-Qos frame / broadcast / 2722 * multicast / mgnt frame should be controlled by Hw because Fw 2723 * will also send null data which we cannot control when Fw LPS 2724 * enable. 2725 * --> default enable non-Qos data sequence number. 2010.06.23. 2726 * by tynli. 2727 * (2) Enable HW SEQ control for beacon packet, because we use 2728 * Hw beacon. 2729 * (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos 2730 * packets. 2731 * 2010.06.23. Added by tynli. 2732 */ 2733 if (!pattrib->qos_en) /* Hw set sequence number */ 2734 ptxdesc->en_hwseq = 1; /* HWSEQ_EN */ 2735 } 2736 2737 /* Description: 2738 * 2739 * Parameters: 2740 * pxmitframe xmitframe 2741 * pbuf where to fill tx desc 2742 */ 2743 void rtl8723b_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf) 2744 { 2745 struct tx_desc *pdesc; 2746 2747 rtl8723b_fill_default_txdesc(pxmitframe, pbuf); 2748 pdesc = (struct tx_desc *)pbuf; 2749 rtl8723b_cal_txdesc_chksum(pdesc); 2750 } 2751 2752 /* */ 2753 /* Description: In normal chip, we should send some packet to Hw which will be used by Fw */ 2754 /* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */ 2755 /* Fw can tell Hw to send these packet derectly. */ 2756 /* Added by tynli. 2009.10.15. */ 2757 /* */ 2758 /* type1:pspoll, type2:null */ 2759 void rtl8723b_fill_fake_txdesc( 2760 struct adapter *padapter, 2761 u8 *pDesc, 2762 u32 BufferLen, 2763 u8 IsPsPoll, 2764 u8 IsBTQosNull, 2765 u8 bDataFrame 2766 ) 2767 { 2768 /* Clear all status */ 2769 memset(pDesc, 0, TXDESC_SIZE); 2770 2771 SET_TX_DESC_FIRST_SEG_8723B(pDesc, 1); /* bFirstSeg; */ 2772 SET_TX_DESC_LAST_SEG_8723B(pDesc, 1); /* bLastSeg; */ 2773 2774 SET_TX_DESC_OFFSET_8723B(pDesc, 0x28); /* Offset = 32 */ 2775 2776 SET_TX_DESC_PKT_SIZE_8723B(pDesc, BufferLen); /* Buffer size + command header */ 2777 SET_TX_DESC_QUEUE_SEL_8723B(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */ 2778 2779 /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error value by Hw. */ 2780 if (IsPsPoll) { 2781 SET_TX_DESC_NAV_USE_HDR_8723B(pDesc, 1); 2782 } else { 2783 SET_TX_DESC_HWSEQ_EN_8723B(pDesc, 1); /* Hw set sequence number */ 2784 SET_TX_DESC_HWSEQ_SEL_8723B(pDesc, 0); 2785 } 2786 2787 if (IsBTQosNull) { 2788 SET_TX_DESC_BT_INT_8723B(pDesc, 1); 2789 } 2790 2791 SET_TX_DESC_USE_RATE_8723B(pDesc, 1); /* use data rate which is set by Sw */ 2792 SET_TX_DESC_OWN_8723B((u8 *)pDesc, 1); 2793 2794 SET_TX_DESC_TX_RATE_8723B(pDesc, DESC8723B_RATE1M); 2795 2796 /* */ 2797 /* Encrypt the data frame if under security mode excepct null data. Suggested by CCW. */ 2798 /* */ 2799 if (bDataFrame) { 2800 u32 EncAlg; 2801 2802 EncAlg = padapter->securitypriv.dot11PrivacyAlgrthm; 2803 switch (EncAlg) { 2804 case _NO_PRIVACY_: 2805 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0); 2806 break; 2807 case _WEP40_: 2808 case _WEP104_: 2809 case _TKIP_: 2810 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x1); 2811 break; 2812 case _SMS4_: 2813 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x2); 2814 break; 2815 case _AES_: 2816 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x3); 2817 break; 2818 default: 2819 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0); 2820 break; 2821 } 2822 } 2823 2824 /* USB interface drop packet if the checksum of descriptor isn't correct. */ 2825 /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */ 2826 rtl8723b_cal_txdesc_chksum((struct tx_desc *)pDesc); 2827 } 2828 2829 static void hw_var_set_opmode(struct adapter *padapter, u8 variable, u8 *val) 2830 { 2831 u8 val8; 2832 u8 mode = *((u8 *)val); 2833 2834 { 2835 /* disable Port0 TSF update */ 2836 val8 = rtw_read8(padapter, REG_BCN_CTRL); 2837 val8 |= DIS_TSF_UDT; 2838 rtw_write8(padapter, REG_BCN_CTRL, val8); 2839 2840 /* set net_type */ 2841 Set_MSR(padapter, mode); 2842 2843 if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) { 2844 { 2845 StopTxBeacon(padapter); 2846 } 2847 2848 /* disable atim wnd */ 2849 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_ATIM); 2850 /* rtw_write8(padapter, REG_BCN_CTRL, 0x18); */ 2851 } else if (mode == _HW_STATE_ADHOC_) { 2852 ResumeTxBeacon(padapter); 2853 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_BCNQ_SUB); 2854 } else if (mode == _HW_STATE_AP_) { 2855 2856 ResumeTxBeacon(padapter); 2857 2858 rtw_write8(padapter, REG_BCN_CTRL, DIS_TSF_UDT|DIS_BCNQ_SUB); 2859 2860 /* Set RCR */ 2861 rtw_write32(padapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0, reject ICV_ERR packet */ 2862 /* enable to rx data frame */ 2863 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF); 2864 /* enable to rx ps-poll */ 2865 rtw_write16(padapter, REG_RXFLTMAP1, 0x0400); 2866 2867 /* Beacon Control related register for first time */ 2868 rtw_write8(padapter, REG_BCNDMATIM, 0x02); /* 2ms */ 2869 2870 /* rtw_write8(padapter, REG_BCN_MAX_ERR, 0xFF); */ 2871 rtw_write8(padapter, REG_ATIMWND, 0x0a); /* 10ms */ 2872 rtw_write16(padapter, REG_BCNTCFG, 0x00); 2873 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0xff04); 2874 rtw_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */ 2875 2876 /* reset TSF */ 2877 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0)); 2878 2879 /* enable BCN0 Function for if1 */ 2880 /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */ 2881 rtw_write8(padapter, REG_BCN_CTRL, (DIS_TSF_UDT|EN_BCN_FUNCTION|EN_TXBCN_RPT|DIS_BCNQ_SUB)); 2882 2883 /* SW_BCN_SEL - Port0 */ 2884 /* rtw_write8(Adapter, REG_DWBCN1_CTRL_8192E+2, rtw_read8(Adapter, REG_DWBCN1_CTRL_8192E+2) & ~BIT4); */ 2885 rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL); 2886 2887 /* select BCN on port 0 */ 2888 rtw_write8( 2889 padapter, 2890 REG_CCK_CHECK_8723B, 2891 (rtw_read8(padapter, REG_CCK_CHECK_8723B)&~BIT_BCN_PORT_SEL) 2892 ); 2893 2894 /* dis BCN1 ATIM WND if if2 is station */ 2895 val8 = rtw_read8(padapter, REG_BCN_CTRL_1); 2896 val8 |= DIS_ATIM; 2897 rtw_write8(padapter, REG_BCN_CTRL_1, val8); 2898 } 2899 } 2900 } 2901 2902 static void hw_var_set_macaddr(struct adapter *padapter, u8 variable, u8 *val) 2903 { 2904 u8 idx = 0; 2905 u32 reg_macid; 2906 2907 reg_macid = REG_MACID; 2908 2909 for (idx = 0 ; idx < 6; idx++) 2910 rtw_write8(GET_PRIMARY_ADAPTER(padapter), (reg_macid+idx), val[idx]); 2911 } 2912 2913 static void hw_var_set_bssid(struct adapter *padapter, u8 variable, u8 *val) 2914 { 2915 u8 idx = 0; 2916 u32 reg_bssid; 2917 2918 reg_bssid = REG_BSSID; 2919 2920 for (idx = 0 ; idx < 6; idx++) 2921 rtw_write8(padapter, (reg_bssid+idx), val[idx]); 2922 } 2923 2924 static void hw_var_set_bcn_func(struct adapter *padapter, u8 variable, u8 *val) 2925 { 2926 u32 bcn_ctrl_reg; 2927 2928 bcn_ctrl_reg = REG_BCN_CTRL; 2929 2930 if (*(u8 *)val) 2931 rtw_write8(padapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT)); 2932 else { 2933 u8 val8; 2934 val8 = rtw_read8(padapter, bcn_ctrl_reg); 2935 val8 &= ~(EN_BCN_FUNCTION | EN_TXBCN_RPT); 2936 2937 /* Always enable port0 beacon function for PSTDMA */ 2938 if (REG_BCN_CTRL == bcn_ctrl_reg) 2939 val8 |= EN_BCN_FUNCTION; 2940 2941 rtw_write8(padapter, bcn_ctrl_reg, val8); 2942 } 2943 } 2944 2945 static void hw_var_set_correct_tsf(struct adapter *padapter, u8 variable, u8 *val) 2946 { 2947 u8 val8; 2948 u64 tsf; 2949 struct mlme_ext_priv *pmlmeext; 2950 struct mlme_ext_info *pmlmeinfo; 2951 2952 2953 pmlmeext = &padapter->mlmeextpriv; 2954 pmlmeinfo = &pmlmeext->mlmext_info; 2955 2956 tsf = pmlmeext->TSFValue-do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024))-1024; /* us */ 2957 2958 if ( 2959 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || 2960 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 2961 ) 2962 StopTxBeacon(padapter); 2963 2964 { 2965 /* disable related TSF function */ 2966 val8 = rtw_read8(padapter, REG_BCN_CTRL); 2967 val8 &= ~EN_BCN_FUNCTION; 2968 rtw_write8(padapter, REG_BCN_CTRL, val8); 2969 2970 rtw_write32(padapter, REG_TSFTR, tsf); 2971 rtw_write32(padapter, REG_TSFTR+4, tsf>>32); 2972 2973 /* enable related TSF function */ 2974 val8 = rtw_read8(padapter, REG_BCN_CTRL); 2975 val8 |= EN_BCN_FUNCTION; 2976 rtw_write8(padapter, REG_BCN_CTRL, val8); 2977 } 2978 2979 if ( 2980 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || 2981 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 2982 ) 2983 ResumeTxBeacon(padapter); 2984 } 2985 2986 static void hw_var_set_mlme_disconnect(struct adapter *padapter, u8 variable, u8 *val) 2987 { 2988 u8 val8; 2989 2990 /* Set RCR to not to receive data frame when NO LINK state */ 2991 /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR) & ~RCR_ADF); */ 2992 /* reject all data frames */ 2993 rtw_write16(padapter, REG_RXFLTMAP2, 0); 2994 2995 /* reset TSF */ 2996 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0)); 2997 2998 /* disable update TSF */ 2999 val8 = rtw_read8(padapter, REG_BCN_CTRL); 3000 val8 |= DIS_TSF_UDT; 3001 rtw_write8(padapter, REG_BCN_CTRL, val8); 3002 } 3003 3004 static void hw_var_set_mlme_sitesurvey(struct adapter *padapter, u8 variable, u8 *val) 3005 { 3006 u32 value_rcr, rcr_clear_bit, reg_bcn_ctl; 3007 u16 value_rxfltmap2; 3008 u8 val8; 3009 struct hal_com_data *pHalData; 3010 struct mlme_priv *pmlmepriv; 3011 3012 3013 pHalData = GET_HAL_DATA(padapter); 3014 pmlmepriv = &padapter->mlmepriv; 3015 3016 reg_bcn_ctl = REG_BCN_CTRL; 3017 3018 rcr_clear_bit = RCR_CBSSID_BCN; 3019 3020 /* config RCR to receive different BSSID & not to receive data frame */ 3021 value_rxfltmap2 = 0; 3022 3023 if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)) 3024 rcr_clear_bit = RCR_CBSSID_BCN; 3025 3026 value_rcr = rtw_read32(padapter, REG_RCR); 3027 3028 if (*((u8 *)val)) { 3029 /* under sitesurvey */ 3030 value_rcr &= ~(rcr_clear_bit); 3031 rtw_write32(padapter, REG_RCR, value_rcr); 3032 3033 rtw_write16(padapter, REG_RXFLTMAP2, value_rxfltmap2); 3034 3035 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) { 3036 /* disable update TSF */ 3037 val8 = rtw_read8(padapter, reg_bcn_ctl); 3038 val8 |= DIS_TSF_UDT; 3039 rtw_write8(padapter, reg_bcn_ctl, val8); 3040 } 3041 3042 /* Save original RRSR setting. */ 3043 pHalData->RegRRSR = rtw_read16(padapter, REG_RRSR); 3044 } else { 3045 /* sitesurvey done */ 3046 if (check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE))) 3047 /* enable to rx data frame */ 3048 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF); 3049 3050 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) { 3051 /* enable update TSF */ 3052 val8 = rtw_read8(padapter, reg_bcn_ctl); 3053 val8 &= ~DIS_TSF_UDT; 3054 rtw_write8(padapter, reg_bcn_ctl, val8); 3055 } 3056 3057 value_rcr |= rcr_clear_bit; 3058 rtw_write32(padapter, REG_RCR, value_rcr); 3059 3060 /* Restore original RRSR setting. */ 3061 rtw_write16(padapter, REG_RRSR, pHalData->RegRRSR); 3062 } 3063 } 3064 3065 static void hw_var_set_mlme_join(struct adapter *padapter, u8 variable, u8 *val) 3066 { 3067 u8 val8; 3068 u16 val16; 3069 u32 val32; 3070 u8 RetryLimit; 3071 u8 type; 3072 struct mlme_priv *pmlmepriv; 3073 struct eeprom_priv *pEEPROM; 3074 3075 3076 RetryLimit = 0x30; 3077 type = *(u8 *)val; 3078 pmlmepriv = &padapter->mlmepriv; 3079 pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); 3080 3081 if (type == 0) { /* prepare to join */ 3082 /* enable to rx data frame.Accept all data frame */ 3083 /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF); */ 3084 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF); 3085 3086 val32 = rtw_read32(padapter, REG_RCR); 3087 if (padapter->in_cta_test) 3088 val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */ 3089 else 3090 val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN; 3091 rtw_write32(padapter, REG_RCR, val32); 3092 3093 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) 3094 RetryLimit = (pEEPROM->CustomerID == RT_CID_CCX) ? 7 : 48; 3095 else /* Ad-hoc Mode */ 3096 RetryLimit = 0x7; 3097 } else if (type == 1) /* joinbss_event call back when join res < 0 */ 3098 rtw_write16(padapter, REG_RXFLTMAP2, 0x00); 3099 else if (type == 2) { /* sta add event call back */ 3100 /* enable update TSF */ 3101 val8 = rtw_read8(padapter, REG_BCN_CTRL); 3102 val8 &= ~DIS_TSF_UDT; 3103 rtw_write8(padapter, REG_BCN_CTRL, val8); 3104 3105 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) 3106 RetryLimit = 0x7; 3107 } 3108 3109 val16 = (RetryLimit << RETRY_LIMIT_SHORT_SHIFT) | (RetryLimit << RETRY_LIMIT_LONG_SHIFT); 3110 rtw_write16(padapter, REG_RL, val16); 3111 } 3112 3113 void CCX_FwC2HTxRpt_8723b(struct adapter *padapter, u8 *pdata, u8 len) 3114 { 3115 3116 #define GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 6, 1) 3117 #define GET_8723B_C2H_TX_RPT_RETRY_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 7, 1) 3118 3119 if (GET_8723B_C2H_TX_RPT_RETRY_OVER(pdata) | GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(pdata)) { 3120 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL); 3121 } 3122 /* 3123 else if (seq_no != padapter->xmitpriv.seq_no) { 3124 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL); 3125 } 3126 */ 3127 else 3128 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_SUCCESS); 3129 } 3130 3131 s32 c2h_id_filter_ccx_8723b(u8 *buf) 3132 { 3133 struct c2h_evt_hdr_88xx *c2h_evt = (struct c2h_evt_hdr_88xx *)buf; 3134 s32 ret = false; 3135 if (c2h_evt->id == C2H_CCX_TX_RPT) 3136 ret = true; 3137 3138 return ret; 3139 } 3140 3141 3142 s32 c2h_handler_8723b(struct adapter *padapter, u8 *buf) 3143 { 3144 struct c2h_evt_hdr_88xx *pC2hEvent = (struct c2h_evt_hdr_88xx *)buf; 3145 s32 ret = _SUCCESS; 3146 3147 if (!pC2hEvent) { 3148 ret = _FAIL; 3149 goto exit; 3150 } 3151 3152 switch (pC2hEvent->id) { 3153 case C2H_AP_RPT_RSP: 3154 break; 3155 case C2H_DBG: 3156 { 3157 } 3158 break; 3159 3160 case C2H_CCX_TX_RPT: 3161 /* CCX_FwC2HTxRpt(padapter, QueueID, pC2hEvent->payload); */ 3162 break; 3163 3164 case C2H_EXT_RA_RPT: 3165 /* C2HExtRaRptHandler(padapter, pC2hEvent->payload, C2hEvent.CmdLen); */ 3166 break; 3167 3168 case C2H_HW_INFO_EXCH: 3169 break; 3170 3171 case C2H_8723B_BT_INFO: 3172 hal_btcoex_BtInfoNotify(padapter, pC2hEvent->plen, pC2hEvent->payload); 3173 break; 3174 3175 default: 3176 break; 3177 } 3178 3179 /* Clear event to notify FW we have read the command. */ 3180 /* Note: */ 3181 /* If this field isn't clear, the FW won't update the next command message. */ 3182 /* rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); */ 3183 exit: 3184 return ret; 3185 } 3186 3187 static void process_c2h_event(struct adapter *padapter, struct c2h_evt_hdr_t *pC2hEvent, u8 *c2hBuf) 3188 { 3189 if (!c2hBuf) 3190 return; 3191 3192 switch (pC2hEvent->CmdID) { 3193 case C2H_AP_RPT_RSP: 3194 break; 3195 case C2H_DBG: 3196 { 3197 } 3198 break; 3199 3200 case C2H_CCX_TX_RPT: 3201 /* CCX_FwC2HTxRpt(padapter, QueueID, tmpBuf); */ 3202 break; 3203 3204 case C2H_EXT_RA_RPT: 3205 /* C2HExtRaRptHandler(padapter, tmpBuf, C2hEvent.CmdLen); */ 3206 break; 3207 3208 case C2H_HW_INFO_EXCH: 3209 break; 3210 3211 case C2H_8723B_BT_INFO: 3212 hal_btcoex_BtInfoNotify(padapter, pC2hEvent->CmdLen, c2hBuf); 3213 break; 3214 3215 default: 3216 break; 3217 } 3218 } 3219 3220 void C2HPacketHandler_8723B(struct adapter *padapter, u8 *pbuffer, u16 length) 3221 { 3222 struct c2h_evt_hdr_t C2hEvent; 3223 u8 *tmpBuf = NULL; 3224 C2hEvent.CmdID = pbuffer[0]; 3225 C2hEvent.CmdSeq = pbuffer[1]; 3226 C2hEvent.CmdLen = length-2; 3227 tmpBuf = pbuffer+2; 3228 3229 process_c2h_event(padapter, &C2hEvent, tmpBuf); 3230 /* c2h_handler_8723b(padapter,&C2hEvent); */ 3231 } 3232 3233 void SetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val) 3234 { 3235 struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 3236 u8 val8; 3237 u32 val32; 3238 3239 switch (variable) { 3240 case HW_VAR_MEDIA_STATUS: 3241 val8 = rtw_read8(padapter, MSR) & 0x0c; 3242 val8 |= *val; 3243 rtw_write8(padapter, MSR, val8); 3244 break; 3245 3246 case HW_VAR_MEDIA_STATUS1: 3247 val8 = rtw_read8(padapter, MSR) & 0x03; 3248 val8 |= *val << 2; 3249 rtw_write8(padapter, MSR, val8); 3250 break; 3251 3252 case HW_VAR_SET_OPMODE: 3253 hw_var_set_opmode(padapter, variable, val); 3254 break; 3255 3256 case HW_VAR_MAC_ADDR: 3257 hw_var_set_macaddr(padapter, variable, val); 3258 break; 3259 3260 case HW_VAR_BSSID: 3261 hw_var_set_bssid(padapter, variable, val); 3262 break; 3263 3264 case HW_VAR_BASIC_RATE: 3265 { 3266 struct mlme_ext_info *mlmext_info = &padapter->mlmeextpriv.mlmext_info; 3267 u16 BrateCfg = 0; 3268 u16 rrsr_2g_force_mask = (RRSR_11M|RRSR_5_5M|RRSR_1M); 3269 u16 rrsr_2g_allow_mask = (RRSR_24M|RRSR_12M|RRSR_6M|RRSR_CCK_RATES); 3270 3271 HalSetBrateCfg(padapter, val, &BrateCfg); 3272 3273 /* apply force and allow mask */ 3274 BrateCfg |= rrsr_2g_force_mask; 3275 BrateCfg &= rrsr_2g_allow_mask; 3276 3277 /* IOT consideration */ 3278 if (mlmext_info->assoc_AP_vendor == HT_IOT_PEER_CISCO) { 3279 /* if peer is cisco and didn't use ofdm rate, we enable 6M ack */ 3280 if ((BrateCfg & (RRSR_24M|RRSR_12M|RRSR_6M)) == 0) 3281 BrateCfg |= RRSR_6M; 3282 } 3283 3284 pHalData->BasicRateSet = BrateCfg; 3285 3286 /* Set RRSR rate table. */ 3287 rtw_write16(padapter, REG_RRSR, BrateCfg); 3288 rtw_write8(padapter, REG_RRSR+2, rtw_read8(padapter, REG_RRSR+2)&0xf0); 3289 } 3290 break; 3291 3292 case HW_VAR_TXPAUSE: 3293 rtw_write8(padapter, REG_TXPAUSE, *val); 3294 break; 3295 3296 case HW_VAR_BCN_FUNC: 3297 hw_var_set_bcn_func(padapter, variable, val); 3298 break; 3299 3300 case HW_VAR_CORRECT_TSF: 3301 hw_var_set_correct_tsf(padapter, variable, val); 3302 break; 3303 3304 case HW_VAR_CHECK_BSSID: 3305 { 3306 u32 val32; 3307 val32 = rtw_read32(padapter, REG_RCR); 3308 if (*val) 3309 val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN; 3310 else 3311 val32 &= ~(RCR_CBSSID_DATA|RCR_CBSSID_BCN); 3312 rtw_write32(padapter, REG_RCR, val32); 3313 } 3314 break; 3315 3316 case HW_VAR_MLME_DISCONNECT: 3317 hw_var_set_mlme_disconnect(padapter, variable, val); 3318 break; 3319 3320 case HW_VAR_MLME_SITESURVEY: 3321 hw_var_set_mlme_sitesurvey(padapter, variable, val); 3322 3323 hal_btcoex_ScanNotify(padapter, *val?true:false); 3324 break; 3325 3326 case HW_VAR_MLME_JOIN: 3327 hw_var_set_mlme_join(padapter, variable, val); 3328 3329 switch (*val) { 3330 case 0: 3331 /* prepare to join */ 3332 hal_btcoex_ConnectNotify(padapter, true); 3333 break; 3334 case 1: 3335 /* joinbss_event callback when join res < 0 */ 3336 hal_btcoex_ConnectNotify(padapter, false); 3337 break; 3338 case 2: 3339 /* sta add event callback */ 3340 /* rtw_btcoex_MediaStatusNotify(padapter, RT_MEDIA_CONNECT); */ 3341 break; 3342 } 3343 break; 3344 3345 case HW_VAR_ON_RCR_AM: 3346 val32 = rtw_read32(padapter, REG_RCR); 3347 val32 |= RCR_AM; 3348 rtw_write32(padapter, REG_RCR, val32); 3349 break; 3350 3351 case HW_VAR_OFF_RCR_AM: 3352 val32 = rtw_read32(padapter, REG_RCR); 3353 val32 &= ~RCR_AM; 3354 rtw_write32(padapter, REG_RCR, val32); 3355 break; 3356 3357 case HW_VAR_BEACON_INTERVAL: 3358 rtw_write16(padapter, REG_BCN_INTERVAL, *((u16 *)val)); 3359 break; 3360 3361 case HW_VAR_SLOT_TIME: 3362 rtw_write8(padapter, REG_SLOT, *val); 3363 break; 3364 3365 case HW_VAR_RESP_SIFS: 3366 /* SIFS_Timer = 0x0a0a0808; */ 3367 /* RESP_SIFS for CCK */ 3368 rtw_write8(padapter, REG_RESP_SIFS_CCK, val[0]); /* SIFS_T2T_CCK (0x08) */ 3369 rtw_write8(padapter, REG_RESP_SIFS_CCK+1, val[1]); /* SIFS_R2T_CCK(0x08) */ 3370 /* RESP_SIFS for OFDM */ 3371 rtw_write8(padapter, REG_RESP_SIFS_OFDM, val[2]); /* SIFS_T2T_OFDM (0x0a) */ 3372 rtw_write8(padapter, REG_RESP_SIFS_OFDM+1, val[3]); /* SIFS_R2T_OFDM(0x0a) */ 3373 break; 3374 3375 case HW_VAR_ACK_PREAMBLE: 3376 { 3377 u8 regTmp; 3378 u8 bShortPreamble = *val; 3379 3380 /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */ 3381 /* regTmp = (pHalData->nCur40MhzPrimeSC)<<5; */ 3382 regTmp = 0; 3383 if (bShortPreamble) 3384 regTmp |= 0x80; 3385 rtw_write8(padapter, REG_RRSR+2, regTmp); 3386 } 3387 break; 3388 3389 case HW_VAR_CAM_EMPTY_ENTRY: 3390 { 3391 u8 ucIndex = *val; 3392 u8 i; 3393 u32 ulCommand = 0; 3394 u32 ulContent = 0; 3395 u32 ulEncAlgo = CAM_AES; 3396 3397 for (i = 0; i < CAM_CONTENT_COUNT; i++) { 3398 /* filled id in CAM config 2 byte */ 3399 if (i == 0) { 3400 ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo)<<2); 3401 /* ulContent |= CAM_VALID; */ 3402 } else 3403 ulContent = 0; 3404 3405 /* polling bit, and No Write enable, and address */ 3406 ulCommand = CAM_CONTENT_COUNT*ucIndex+i; 3407 ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE; 3408 /* write content 0 is equal to mark as invalid */ 3409 rtw_write32(padapter, WCAMI, ulContent); /* mdelay(40); */ 3410 rtw_write32(padapter, RWCAM, ulCommand); /* mdelay(40); */ 3411 } 3412 } 3413 break; 3414 3415 case HW_VAR_CAM_INVALID_ALL: 3416 rtw_write32(padapter, RWCAM, BIT(31)|BIT(30)); 3417 break; 3418 3419 case HW_VAR_CAM_WRITE: 3420 { 3421 u32 cmd; 3422 u32 *cam_val = (u32 *)val; 3423 3424 rtw_write32(padapter, WCAMI, cam_val[0]); 3425 3426 cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1]; 3427 rtw_write32(padapter, RWCAM, cmd); 3428 } 3429 break; 3430 3431 case HW_VAR_AC_PARAM_VO: 3432 rtw_write32(padapter, REG_EDCA_VO_PARAM, *((u32 *)val)); 3433 break; 3434 3435 case HW_VAR_AC_PARAM_VI: 3436 rtw_write32(padapter, REG_EDCA_VI_PARAM, *((u32 *)val)); 3437 break; 3438 3439 case HW_VAR_AC_PARAM_BE: 3440 pHalData->AcParam_BE = ((u32 *)(val))[0]; 3441 rtw_write32(padapter, REG_EDCA_BE_PARAM, *((u32 *)val)); 3442 break; 3443 3444 case HW_VAR_AC_PARAM_BK: 3445 rtw_write32(padapter, REG_EDCA_BK_PARAM, *((u32 *)val)); 3446 break; 3447 3448 case HW_VAR_ACM_CTRL: 3449 { 3450 u8 ctrl = *((u8 *)val); 3451 u8 hwctrl = 0; 3452 3453 if (ctrl != 0) { 3454 hwctrl |= AcmHw_HwEn; 3455 3456 if (ctrl & BIT(1)) /* BE */ 3457 hwctrl |= AcmHw_BeqEn; 3458 3459 if (ctrl & BIT(2)) /* VI */ 3460 hwctrl |= AcmHw_ViqEn; 3461 3462 if (ctrl & BIT(3)) /* VO */ 3463 hwctrl |= AcmHw_VoqEn; 3464 } 3465 3466 rtw_write8(padapter, REG_ACMHWCTRL, hwctrl); 3467 } 3468 break; 3469 3470 case HW_VAR_AMPDU_FACTOR: 3471 { 3472 u32 AMPDULen = (*((u8 *)val)); 3473 3474 if (AMPDULen < HT_AGG_SIZE_32K) 3475 AMPDULen = (0x2000 << (*((u8 *)val)))-1; 3476 else 3477 AMPDULen = 0x7fff; 3478 3479 rtw_write32(padapter, REG_AMPDU_MAX_LENGTH_8723B, AMPDULen); 3480 } 3481 break; 3482 3483 case HW_VAR_H2C_FW_PWRMODE: 3484 { 3485 u8 psmode = *val; 3486 3487 /* Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */ 3488 /* saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */ 3489 if (psmode != PS_MODE_ACTIVE) { 3490 ODM_RF_Saving(&pHalData->odmpriv, true); 3491 } 3492 3493 /* if (psmode != PS_MODE_ACTIVE) { */ 3494 /* rtl8723b_set_lowpwr_lps_cmd(padapter, true); */ 3495 /* else { */ 3496 /* rtl8723b_set_lowpwr_lps_cmd(padapter, false); */ 3497 /* */ 3498 rtl8723b_set_FwPwrMode_cmd(padapter, psmode); 3499 } 3500 break; 3501 case HW_VAR_H2C_PS_TUNE_PARAM: 3502 rtl8723b_set_FwPsTuneParam_cmd(padapter); 3503 break; 3504 3505 case HW_VAR_H2C_FW_JOINBSSRPT: 3506 rtl8723b_set_FwJoinBssRpt_cmd(padapter, *val); 3507 break; 3508 3509 case HW_VAR_INITIAL_GAIN: 3510 { 3511 struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable; 3512 u32 rx_gain = *(u32 *)val; 3513 3514 if (rx_gain == 0xff) {/* restore rx gain */ 3515 ODM_Write_DIG(&pHalData->odmpriv, pDigTable->BackupIGValue); 3516 } else { 3517 pDigTable->BackupIGValue = pDigTable->CurIGValue; 3518 ODM_Write_DIG(&pHalData->odmpriv, rx_gain); 3519 } 3520 } 3521 break; 3522 3523 case HW_VAR_EFUSE_USAGE: 3524 pHalData->EfuseUsedPercentage = *val; 3525 break; 3526 3527 case HW_VAR_EFUSE_BYTES: 3528 pHalData->EfuseUsedBytes = *((u16 *)val); 3529 break; 3530 3531 case HW_VAR_EFUSE_BT_USAGE: 3532 #ifdef HAL_EFUSE_MEMORY 3533 pHalData->EfuseHal.BTEfuseUsedPercentage = *val; 3534 #endif 3535 break; 3536 3537 case HW_VAR_EFUSE_BT_BYTES: 3538 #ifdef HAL_EFUSE_MEMORY 3539 pHalData->EfuseHal.BTEfuseUsedBytes = *((u16 *)val); 3540 #else 3541 BTEfuseUsedBytes = *((u16 *)val); 3542 #endif 3543 break; 3544 3545 case HW_VAR_FIFO_CLEARN_UP: 3546 { 3547 #define RW_RELEASE_EN BIT(18) 3548 #define RXDMA_IDLE BIT(17) 3549 3550 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); 3551 u8 trycnt = 100; 3552 3553 /* pause tx */ 3554 rtw_write8(padapter, REG_TXPAUSE, 0xff); 3555 3556 /* keep sn */ 3557 padapter->xmitpriv.nqos_ssn = rtw_read16(padapter, REG_NQOS_SEQ); 3558 3559 if (!pwrpriv->bkeepfwalive) { 3560 /* RX DMA stop */ 3561 val32 = rtw_read32(padapter, REG_RXPKT_NUM); 3562 val32 |= RW_RELEASE_EN; 3563 rtw_write32(padapter, REG_RXPKT_NUM, val32); 3564 do { 3565 val32 = rtw_read32(padapter, REG_RXPKT_NUM); 3566 val32 &= RXDMA_IDLE; 3567 if (val32) 3568 break; 3569 } while (--trycnt); 3570 3571 /* RQPN Load 0 */ 3572 rtw_write16(padapter, REG_RQPN_NPQ, 0); 3573 rtw_write32(padapter, REG_RQPN, 0x80000000); 3574 mdelay(2); 3575 } 3576 } 3577 break; 3578 3579 case HW_VAR_APFM_ON_MAC: 3580 pHalData->bMacPwrCtrlOn = *val; 3581 break; 3582 3583 case HW_VAR_NAV_UPPER: 3584 { 3585 u32 usNavUpper = *((u32 *)val); 3586 3587 if (usNavUpper > HAL_NAV_UPPER_UNIT_8723B * 0xFF) 3588 break; 3589 3590 usNavUpper = DIV_ROUND_UP(usNavUpper, 3591 HAL_NAV_UPPER_UNIT_8723B); 3592 rtw_write8(padapter, REG_NAV_UPPER, (u8)usNavUpper); 3593 } 3594 break; 3595 3596 case HW_VAR_H2C_MEDIA_STATUS_RPT: 3597 { 3598 u16 mstatus_rpt = (*(u16 *)val); 3599 u8 mstatus, macId; 3600 3601 mstatus = (u8) (mstatus_rpt & 0xFF); 3602 macId = (u8)(mstatus_rpt >> 8); 3603 rtl8723b_set_FwMediaStatusRpt_cmd(padapter, mstatus, macId); 3604 } 3605 break; 3606 case HW_VAR_BCN_VALID: 3607 { 3608 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */ 3609 val8 = rtw_read8(padapter, REG_TDECTRL+2); 3610 val8 |= BIT(0); 3611 rtw_write8(padapter, REG_TDECTRL+2, val8); 3612 } 3613 break; 3614 3615 case HW_VAR_DL_BCN_SEL: 3616 { 3617 /* SW_BCN_SEL - Port0 */ 3618 val8 = rtw_read8(padapter, REG_DWBCN1_CTRL_8723B+2); 3619 val8 &= ~BIT(4); 3620 rtw_write8(padapter, REG_DWBCN1_CTRL_8723B+2, val8); 3621 } 3622 break; 3623 3624 case HW_VAR_DO_IQK: 3625 pHalData->bNeedIQK = true; 3626 break; 3627 3628 case HW_VAR_DL_RSVD_PAGE: 3629 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) 3630 rtl8723b_download_BTCoex_AP_mode_rsvd_page(padapter); 3631 else 3632 rtl8723b_download_rsvd_page(padapter, RT_MEDIA_CONNECT); 3633 break; 3634 3635 case HW_VAR_MACID_SLEEP: 3636 /* Input is MACID */ 3637 val32 = *(u32 *)val; 3638 if (val32 > 31) 3639 break; 3640 3641 val8 = (u8)val32; /* macid is between 0~31 */ 3642 3643 val32 = rtw_read32(padapter, REG_MACID_SLEEP); 3644 if (val32 & BIT(val8)) 3645 break; 3646 val32 |= BIT(val8); 3647 rtw_write32(padapter, REG_MACID_SLEEP, val32); 3648 break; 3649 3650 case HW_VAR_MACID_WAKEUP: 3651 /* Input is MACID */ 3652 val32 = *(u32 *)val; 3653 if (val32 > 31) 3654 break; 3655 3656 val8 = (u8)val32; /* macid is between 0~31 */ 3657 3658 val32 = rtw_read32(padapter, REG_MACID_SLEEP); 3659 if (!(val32 & BIT(val8))) 3660 break; 3661 val32 &= ~BIT(val8); 3662 rtw_write32(padapter, REG_MACID_SLEEP, val32); 3663 break; 3664 3665 default: 3666 SetHwReg(padapter, variable, val); 3667 break; 3668 } 3669 } 3670 3671 void GetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val) 3672 { 3673 struct hal_com_data *pHalData = GET_HAL_DATA(padapter); 3674 u8 val8; 3675 u16 val16; 3676 3677 switch (variable) { 3678 case HW_VAR_TXPAUSE: 3679 *val = rtw_read8(padapter, REG_TXPAUSE); 3680 break; 3681 3682 case HW_VAR_BCN_VALID: 3683 { 3684 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */ 3685 val8 = rtw_read8(padapter, REG_TDECTRL+2); 3686 *val = (BIT(0) & val8) ? true : false; 3687 } 3688 break; 3689 3690 case HW_VAR_FWLPS_RF_ON: 3691 { 3692 /* When we halt NIC, we should check if FW LPS is leave. */ 3693 u32 valRCR; 3694 3695 if ( 3696 padapter->bSurpriseRemoved || 3697 (adapter_to_pwrctl(padapter)->rf_pwrstate == rf_off) 3698 ) { 3699 /* If it is in HW/SW Radio OFF or IPS state, we do not check Fw LPS Leave, */ 3700 /* because Fw is unload. */ 3701 *val = true; 3702 } else { 3703 valRCR = rtw_read32(padapter, REG_RCR); 3704 valRCR &= 0x00070000; 3705 if (valRCR) 3706 *val = false; 3707 else 3708 *val = true; 3709 } 3710 } 3711 break; 3712 3713 case HW_VAR_EFUSE_USAGE: 3714 *val = pHalData->EfuseUsedPercentage; 3715 break; 3716 3717 case HW_VAR_EFUSE_BYTES: 3718 *((u16 *)val) = pHalData->EfuseUsedBytes; 3719 break; 3720 3721 case HW_VAR_EFUSE_BT_USAGE: 3722 #ifdef HAL_EFUSE_MEMORY 3723 *val = pHalData->EfuseHal.BTEfuseUsedPercentage; 3724 #endif 3725 break; 3726 3727 case HW_VAR_EFUSE_BT_BYTES: 3728 #ifdef HAL_EFUSE_MEMORY 3729 *((u16 *)val) = pHalData->EfuseHal.BTEfuseUsedBytes; 3730 #else 3731 *((u16 *)val) = BTEfuseUsedBytes; 3732 #endif 3733 break; 3734 3735 case HW_VAR_APFM_ON_MAC: 3736 *val = pHalData->bMacPwrCtrlOn; 3737 break; 3738 case HW_VAR_CHK_HI_QUEUE_EMPTY: 3739 val16 = rtw_read16(padapter, REG_TXPKT_EMPTY); 3740 *val = (val16 & BIT(10)) ? true:false; 3741 break; 3742 default: 3743 GetHwReg(padapter, variable, val); 3744 break; 3745 } 3746 } 3747 3748 /* Description: 3749 * Change default setting of specified variable. 3750 */ 3751 u8 SetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval) 3752 { 3753 u8 bResult; 3754 3755 bResult = _SUCCESS; 3756 3757 switch (variable) { 3758 default: 3759 bResult = SetHalDefVar(padapter, variable, pval); 3760 break; 3761 } 3762 3763 return bResult; 3764 } 3765 3766 /* Description: 3767 * Query setting of specified variable. 3768 */ 3769 u8 GetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval) 3770 { 3771 u8 bResult; 3772 3773 bResult = _SUCCESS; 3774 3775 switch (variable) { 3776 case HAL_DEF_MAX_RECVBUF_SZ: 3777 *((u32 *)pval) = MAX_RECVBUF_SZ; 3778 break; 3779 3780 case HAL_DEF_RX_PACKET_OFFSET: 3781 *((u32 *)pval) = RXDESC_SIZE + DRVINFO_SZ*8; 3782 break; 3783 3784 case HW_VAR_MAX_RX_AMPDU_FACTOR: 3785 /* Stanley@BB.SD3 suggests 16K can get stable performance */ 3786 /* The experiment was done on SDIO interface */ 3787 /* coding by Lucas@20130730 */ 3788 *(u32 *)pval = IEEE80211_HT_MAX_AMPDU_16K; 3789 break; 3790 case HAL_DEF_TX_LDPC: 3791 case HAL_DEF_RX_LDPC: 3792 *((u8 *)pval) = false; 3793 break; 3794 case HAL_DEF_TX_STBC: 3795 *((u8 *)pval) = 0; 3796 break; 3797 case HAL_DEF_RX_STBC: 3798 *((u8 *)pval) = 1; 3799 break; 3800 case HAL_DEF_EXPLICIT_BEAMFORMER: 3801 case HAL_DEF_EXPLICIT_BEAMFORMEE: 3802 *((u8 *)pval) = false; 3803 break; 3804 3805 case HW_DEF_RA_INFO_DUMP: 3806 { 3807 u8 mac_id = *(u8 *)pval; 3808 u32 cmd; 3809 3810 cmd = 0x40000100 | mac_id; 3811 rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd); 3812 msleep(10); 3813 rtw_read32(padapter, 0x2F0); // info 1 3814 3815 cmd = 0x40000400 | mac_id; 3816 rtw_write32(padapter, REG_HMEBOX_DBG_2_8723B, cmd); 3817 msleep(10); 3818 rtw_read32(padapter, 0x2F0); // info 1 3819 rtw_read32(padapter, 0x2F4); // info 2 3820 rtw_read32(padapter, 0x2F8); // rate mask 1 3821 rtw_read32(padapter, 0x2FC); // rate mask 2 3822 } 3823 break; 3824 3825 case HAL_DEF_TX_PAGE_BOUNDARY: 3826 if (!padapter->registrypriv.wifi_spec) { 3827 *(u8 *)pval = TX_PAGE_BOUNDARY_8723B; 3828 } else { 3829 *(u8 *)pval = WMM_NORMAL_TX_PAGE_BOUNDARY_8723B; 3830 } 3831 break; 3832 3833 case HAL_DEF_MACID_SLEEP: 3834 *(u8 *)pval = true; /* support macid sleep */ 3835 break; 3836 3837 default: 3838 bResult = GetHalDefVar(padapter, variable, pval); 3839 break; 3840 } 3841 3842 return bResult; 3843 } 3844 3845 void rtl8723b_start_thread(struct adapter *padapter) 3846 { 3847 struct xmit_priv *xmitpriv = &padapter->xmitpriv; 3848 3849 xmitpriv->SdioXmitThread = kthread_run(rtl8723bs_xmit_thread, padapter, "RTWHALXT"); 3850 } 3851 3852 void rtl8723b_stop_thread(struct adapter *padapter) 3853 { 3854 struct xmit_priv *xmitpriv = &padapter->xmitpriv; 3855 3856 /* stop xmit_buf_thread */ 3857 if (xmitpriv->SdioXmitThread) { 3858 complete(&xmitpriv->SdioXmitStart); 3859 wait_for_completion(&xmitpriv->SdioXmitTerminate); 3860 xmitpriv->SdioXmitThread = NULL; 3861 } 3862 } 3863