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