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