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