linux/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2007 - 2011 Realtek Corporation. */
   3
   4#define _HAL_INIT_C_
   5
   6#include "../include/linux/firmware.h"
   7#include "../include/drv_types.h"
   8#include "../include/rtw_efuse.h"
   9#include "../include/rtl8188e_hal.h"
  10#include "../include/rtw_iol.h"
  11#include "../include/usb_ops.h"
  12
  13static void iol_mode_enable(struct adapter *padapter, u8 enable)
  14{
  15        u8 reg_0xf0 = 0;
  16
  17        if (enable) {
  18                /* Enable initial offload */
  19                reg_0xf0 = rtw_read8(padapter, REG_SYS_CFG);
  20                rtw_write8(padapter, REG_SYS_CFG, reg_0xf0 | SW_OFFLOAD_EN);
  21
  22                if (!padapter->bFWReady) {
  23                        DBG_88E("bFWReady == false call reset 8051...\n");
  24                        _8051Reset88E(padapter);
  25                }
  26
  27        } else {
  28                /* disable initial offload */
  29                reg_0xf0 = rtw_read8(padapter, REG_SYS_CFG);
  30                rtw_write8(padapter, REG_SYS_CFG, reg_0xf0 & ~SW_OFFLOAD_EN);
  31        }
  32}
  33
  34static s32 iol_execute(struct adapter *padapter, u8 control)
  35{
  36        s32 status = _FAIL;
  37        u8 reg_0x88 = 0;
  38        u32 start = 0, passing_time = 0;
  39
  40        control = control & 0x0f;
  41        reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0);
  42        rtw_write8(padapter, REG_HMEBOX_E0,  reg_0x88 | control);
  43
  44        start = jiffies;
  45        while ((reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0)) & control &&
  46               (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
  47                ;
  48        }
  49
  50        reg_0x88 = rtw_read8(padapter, REG_HMEBOX_E0);
  51        status = (reg_0x88 & control) ? _FAIL : _SUCCESS;
  52        if (reg_0x88 & control << 4)
  53                status = _FAIL;
  54        return status;
  55}
  56
  57static s32 iol_InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy)
  58{
  59        s32 rst = _SUCCESS;
  60        iol_mode_enable(padapter, 1);
  61        rtw_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy);
  62        rst = iol_execute(padapter, CMD_INIT_LLT);
  63        iol_mode_enable(padapter, 0);
  64        return rst;
  65}
  66
  67static void
  68efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8  *pbuf)
  69{
  70        u8 *efuseTbl = NULL;
  71        u8 rtemp8;
  72        u16     eFuse_Addr = 0;
  73        u8 offset, wren;
  74        u16     i, j;
  75        u16     **eFuseWord = NULL;
  76        u16     efuse_utilized = 0;
  77        u8 u1temp = 0;
  78
  79        efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
  80        if (!efuseTbl) {
  81                DBG_88E("%s: alloc efuseTbl fail!\n", __func__);
  82                goto exit;
  83        }
  84
  85        eFuseWord = rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
  86        if (!eFuseWord) {
  87                DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
  88                goto exit;
  89        }
  90
  91        /*  0. Refresh efuse init map as all oxFF. */
  92        for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
  93                for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
  94                        eFuseWord[i][j] = 0xFFFF;
  95
  96        /*  */
  97        /*  1. Read the first byte to check if efuse is empty!!! */
  98        /*  */
  99        /*  */
 100        rtemp8 = *(phymap + eFuse_Addr);
 101        if (rtemp8 != 0xFF) {
 102                efuse_utilized++;
 103                eFuse_Addr++;
 104        } else {
 105                DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8);
 106                goto exit;
 107        }
 108
 109        /*  */
 110        /*  2. Read real efuse content. Filter PG header and every section data. */
 111        /*  */
 112        while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
 113                /*  Check PG header for section num. */
 114                if ((rtemp8 & 0x1F) == 0x0F) {          /* extended header */
 115                        u1temp = ((rtemp8 & 0xE0) >> 5);
 116                        rtemp8 = *(phymap + eFuse_Addr);
 117                        if ((rtemp8 & 0x0F) == 0x0F) {
 118                                eFuse_Addr++;
 119                                rtemp8 = *(phymap + eFuse_Addr);
 120
 121                                if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
 122                                        eFuse_Addr++;
 123                                continue;
 124                        } else {
 125                                offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
 126                                wren = (rtemp8 & 0x0F);
 127                                eFuse_Addr++;
 128                        }
 129                } else {
 130                        offset = ((rtemp8 >> 4) & 0x0f);
 131                        wren = (rtemp8 & 0x0f);
 132                }
 133
 134                if (offset < EFUSE_MAX_SECTION_88E) {
 135                        /*  Get word enable value from PG header */
 136                        for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
 137                                /*  Check word enable condition in the section */
 138                                if (!(wren & 0x01)) {
 139                                        rtemp8 = *(phymap + eFuse_Addr);
 140                                        eFuse_Addr++;
 141                                        efuse_utilized++;
 142                                        eFuseWord[offset][i] = (rtemp8 & 0xff);
 143                                        if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
 144                                                break;
 145                                        rtemp8 = *(phymap + eFuse_Addr);
 146                                        eFuse_Addr++;
 147                                        efuse_utilized++;
 148                                        eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00);
 149
 150                                        if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
 151                                                break;
 152                                }
 153                                wren >>= 1;
 154                        }
 155                }
 156                /*  Read next PG header */
 157                rtemp8 = *(phymap + eFuse_Addr);
 158
 159                if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
 160                        efuse_utilized++;
 161                        eFuse_Addr++;
 162                }
 163        }
 164
 165        /*  */
 166        /*  3. Collect 16 sections and 4 word unit into Efuse map. */
 167        /*  */
 168        for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
 169                for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
 170                        efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff);
 171                        efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff);
 172                }
 173        }
 174
 175        /*  */
 176        /*  4. Copy from Efuse map to output pointer memory!!! */
 177        /*  */
 178        for (i = 0; i < _size_byte; i++)
 179                pbuf[i] = efuseTbl[_offset + i];
 180
 181        /*  */
 182        /*  5. Calculate Efuse utilization. */
 183        /*  */
 184
 185exit:
 186        kfree(efuseTbl);
 187        kfree(eFuseWord);
 188}
 189
 190static void efuse_read_phymap_from_txpktbuf(
 191        struct adapter  *adapter,
 192        int bcnhead,    /* beacon head, where FW store len(2-byte) and efuse physical map. */
 193        u8 *content,    /* buffer to store efuse physical map */
 194        u16 *size       /* for efuse content: the max byte to read. will update to byte read */
 195        )
 196{
 197        u16 dbg_addr = 0;
 198        u32 start  = 0, passing_time = 0;
 199        u8 reg_0x143 = 0;
 200        __le32 lo32 = 0, hi32 = 0;
 201        u16 len = 0, count = 0;
 202        int i = 0;
 203        u16 limit = *size;
 204
 205        u8 *pos = content;
 206
 207        if (bcnhead < 0) /* if not valid */
 208                bcnhead = rtw_read8(adapter, REG_TDECTRL + 1);
 209
 210        DBG_88E("%s bcnhead:%d\n", __func__, bcnhead);
 211
 212        rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
 213
 214        dbg_addr = bcnhead * 128 / 8; /* 8-bytes addressing */
 215
 216        while (1) {
 217                rtw_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr + i);
 218
 219                rtw_write8(adapter, REG_TXPKTBUF_DBG, 0);
 220                start = jiffies;
 221                while (!(reg_0x143 = rtw_read8(adapter, REG_TXPKTBUF_DBG)) &&
 222                       (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
 223                        DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, rtw_read8(adapter, 0x106));
 224                        rtw_usleep_os(100);
 225                }
 226
 227                /* data from EEPROM needs to be in LE */
 228                lo32 = cpu_to_le32(rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L));
 229                hi32 = cpu_to_le32(rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H));
 230
 231                if (i == 0) {
 232                        /* Although lenc is only used in a debug statement,
 233                         * do not remove it as the rtw_read16() call consumes
 234                         * 2 bytes from the EEPROM source.
 235                         */
 236                        u16 lenc = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L);
 237
 238                        len = le32_to_cpu(lo32) & 0x0000ffff;
 239
 240                        limit = (len - 2 < limit) ? len - 2 : limit;
 241
 242                        DBG_88E("%s len:%u, lenc:%u\n", __func__, len, lenc);
 243
 244                        memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count);
 245                        count += (limit >= count + 2) ? 2 : limit - count;
 246                        pos = content + count;
 247                } else {
 248                        memcpy(pos, ((u8 *)&lo32), (limit >= count + 4) ? 4 : limit - count);
 249                        count += (limit >= count + 4) ? 4 : limit - count;
 250                        pos = content + count;
 251                }
 252
 253                if (limit > count && len - 2 > count) {
 254                        memcpy(pos, (u8 *)&hi32, (limit >= count + 4) ? 4 : limit - count);
 255                        count += (limit >= count + 4) ? 4 : limit - count;
 256                        pos = content + count;
 257                }
 258
 259                if (limit <= count || len - 2 <= count)
 260                        break;
 261                i++;
 262        }
 263        rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
 264        DBG_88E("%s read count:%u\n", __func__, count);
 265        *size = count;
 266}
 267
 268static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map)
 269{
 270        s32 status = _FAIL;
 271        u8 physical_map[512];
 272        u16 size = 512;
 273
 274        rtw_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy);
 275        memset(physical_map, 0xFF, 512);
 276        rtw_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
 277        status = iol_execute(padapter, CMD_READ_EFUSE_MAP);
 278        if (status == _SUCCESS)
 279                efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size);
 280        efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map);
 281        return status;
 282}
 283
 284s32 rtl8188e_iol_efuse_patch(struct adapter *padapter)
 285{
 286        s32     result = _SUCCESS;
 287
 288        DBG_88E("==> %s\n", __func__);
 289        if (rtw_IOL_applied(padapter)) {
 290                iol_mode_enable(padapter, 1);
 291                result = iol_execute(padapter, CMD_READ_EFUSE_MAP);
 292                if (result == _SUCCESS)
 293                        result = iol_execute(padapter, CMD_EFUSE_PATCH);
 294
 295                iol_mode_enable(padapter, 0);
 296        }
 297        return result;
 298}
 299
 300static s32 iol_ioconfig(struct adapter *padapter, u8 iocfg_bndy)
 301{
 302        s32 rst = _SUCCESS;
 303
 304        rtw_write8(padapter, REG_TDECTRL + 1, iocfg_bndy);
 305        rst = iol_execute(padapter, CMD_IOCONFIG);
 306        return rst;
 307}
 308
 309static int rtl8188e_IOL_exec_cmds_sync(struct adapter *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt)
 310{
 311        struct pkt_attrib *pattrib = &xmit_frame->attrib;
 312        u8 i;
 313        int ret = _FAIL;
 314
 315        if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS)
 316                goto exit;
 317        if (rtw_usb_bulk_size_boundary(adapter, TXDESC_SIZE + pattrib->last_txcmdsz)) {
 318                if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS)
 319                        goto exit;
 320        }
 321
 322        dump_mgntframe_and_wait(adapter, xmit_frame, max_wating_ms);
 323
 324        iol_mode_enable(adapter, 1);
 325        for (i = 0; i < bndy_cnt; i++) {
 326                u8 page_no = 0;
 327                page_no = i * 2;
 328                ret = iol_ioconfig(adapter, page_no);
 329                if (ret != _SUCCESS)
 330                        break;
 331        }
 332        iol_mode_enable(adapter, 0);
 333exit:
 334        /* restore BCN_HEAD */
 335        rtw_write8(adapter, REG_TDECTRL + 1, 0);
 336        return ret;
 337}
 338
 339void rtw_IOL_cmd_tx_pkt_buf_dump(struct adapter *Adapter, int data_len)
 340{
 341        u32 fifo_data, reg_140;
 342        u32 addr, rstatus, loop = 0;
 343        u16 data_cnts = (data_len / 8) + 1;
 344        u8 *pbuf = vzalloc(data_len + 10);
 345        DBG_88E("###### %s ######\n", __func__);
 346
 347        rtw_write8(Adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
 348        if (pbuf) {
 349                for (addr = 0; addr < data_cnts; addr++) {
 350                        rtw_write32(Adapter, 0x140, addr);
 351                        rtw_usleep_os(2);
 352                        loop = 0;
 353                        do {
 354                                rstatus = (reg_140 = rtw_read32(Adapter, REG_PKTBUF_DBG_CTRL) & BIT(24));
 355                                if (rstatus) {
 356                                        fifo_data = rtw_read32(Adapter, REG_PKTBUF_DBG_DATA_L);
 357                                        memcpy(pbuf + (addr * 8), &fifo_data, 4);
 358
 359                                        fifo_data = rtw_read32(Adapter, REG_PKTBUF_DBG_DATA_H);
 360                                        memcpy(pbuf + (addr * 8 + 4), &fifo_data, 4);
 361                                }
 362                                rtw_usleep_os(2);
 363                        } while (!rstatus && (loop++ < 10));
 364                }
 365                rtw_IOL_cmd_buf_dump(Adapter, data_len, pbuf);
 366                vfree(pbuf);
 367        }
 368        DBG_88E("###### %s ######\n", __func__);
 369}
 370
 371static void _FWDownloadEnable(struct adapter *padapter, bool enable)
 372{
 373        u8 tmp;
 374
 375        if (enable) {
 376                /*  MCU firmware download enable. */
 377                tmp = rtw_read8(padapter, REG_MCUFWDL);
 378                rtw_write8(padapter, REG_MCUFWDL, tmp | 0x01);
 379
 380                /*  8051 reset */
 381                tmp = rtw_read8(padapter, REG_MCUFWDL + 2);
 382                rtw_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7);
 383        } else {
 384                /*  MCU firmware download disable. */
 385                tmp = rtw_read8(padapter, REG_MCUFWDL);
 386                rtw_write8(padapter, REG_MCUFWDL, tmp & 0xfe);
 387
 388                /*  Reserved for fw extension. */
 389                rtw_write8(padapter, REG_MCUFWDL + 1, 0x00);
 390        }
 391}
 392
 393#define MAX_REG_BOLCK_SIZE      196
 394
 395static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
 396{
 397        int ret = _SUCCESS;
 398        u32     blockSize_p1 = 4;       /*  (Default) Phase #1 : PCI muse use 4-byte write to download FW */
 399        u32     blockSize_p2 = 8;       /*  Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
 400        u32     blockSize_p3 = 1;       /*  Phase #3 : Use 1-byte, the remnant of FW image. */
 401        u32     blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
 402        u32     remainSize_p1 = 0, remainSize_p2 = 0;
 403        u8 *bufferPtr   = (u8 *)buffer;
 404        u32     i = 0, offset = 0;
 405
 406        blockSize_p1 = MAX_REG_BOLCK_SIZE;
 407
 408        /* 3 Phase #1 */
 409        blockCount_p1 = buffSize / blockSize_p1;
 410        remainSize_p1 = buffSize % blockSize_p1;
 411
 412        for (i = 0; i < blockCount_p1; i++) {
 413                ret = rtw_writeN(padapter, (FW_8188E_START_ADDRESS + i * blockSize_p1), blockSize_p1, (bufferPtr + i * blockSize_p1));
 414                if (ret == _FAIL)
 415                        goto exit;
 416        }
 417
 418        /* 3 Phase #2 */
 419        if (remainSize_p1) {
 420                offset = blockCount_p1 * blockSize_p1;
 421
 422                blockCount_p2 = remainSize_p1 / blockSize_p2;
 423                remainSize_p2 = remainSize_p1 % blockSize_p2;
 424
 425                for (i = 0; i < blockCount_p2; i++) {
 426                        ret = rtw_writeN(padapter, (FW_8188E_START_ADDRESS + offset + i * blockSize_p2), blockSize_p2, (bufferPtr + offset + i * blockSize_p2));
 427
 428                        if (ret == _FAIL)
 429                                goto exit;
 430                }
 431        }
 432
 433        /* 3 Phase #3 */
 434        if (remainSize_p2) {
 435                offset = (blockCount_p1 * blockSize_p1) + (blockCount_p2 * blockSize_p2);
 436
 437                blockCount_p3 = remainSize_p2 / blockSize_p3;
 438
 439                for (i = 0; i < blockCount_p3; i++) {
 440                        ret = rtw_write8(padapter, (FW_8188E_START_ADDRESS + offset + i), *(bufferPtr + offset + i));
 441
 442                        if (ret == _FAIL)
 443                                goto exit;
 444                }
 445        }
 446
 447exit:
 448        return ret;
 449}
 450
 451static int _PageWrite(struct adapter *padapter, u32 page, void *buffer, u32 size)
 452{
 453        u8 value8;
 454        u8 u8Page = (u8)(page & 0x07);
 455
 456        value8 = (rtw_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page;
 457        rtw_write8(padapter, REG_MCUFWDL + 2, value8);
 458
 459        return _BlockWrite(padapter, buffer, size);
 460}
 461
 462static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
 463{
 464        /*  Since we need dynamic decide method of dwonload fw, so we call this function to get chip version. */
 465        /*  We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
 466        int ret = _SUCCESS;
 467        u32     pageNums, remainSize;
 468        u32     page, offset;
 469        u8 *bufferPtr = (u8 *)buffer;
 470
 471        pageNums = size / MAX_PAGE_SIZE;
 472        remainSize = size % MAX_PAGE_SIZE;
 473
 474        for (page = 0; page < pageNums; page++) {
 475                offset = page * MAX_PAGE_SIZE;
 476                ret = _PageWrite(padapter, page, bufferPtr + offset, MAX_PAGE_SIZE);
 477
 478                if (ret == _FAIL)
 479                        goto exit;
 480        }
 481        if (remainSize) {
 482                offset = pageNums * MAX_PAGE_SIZE;
 483                page = pageNums;
 484                ret = _PageWrite(padapter, page, bufferPtr + offset, remainSize);
 485
 486                if (ret == _FAIL)
 487                        goto exit;
 488        }
 489exit:
 490        return ret;
 491}
 492
 493void _8051Reset88E(struct adapter *padapter)
 494{
 495        u8 u1bTmp;
 496
 497        u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
 498        rtw_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp & (~BIT(2)));
 499        rtw_write8(padapter, REG_SYS_FUNC_EN + 1, u1bTmp | (BIT(2)));
 500        DBG_88E("=====> _8051Reset88E(): 8051 reset success .\n");
 501}
 502
 503static s32 _FWFreeToGo(struct adapter *padapter)
 504{
 505        u32     counter = 0;
 506        u32     value32;
 507
 508        /*  polling CheckSum report */
 509        do {
 510                value32 = rtw_read32(padapter, REG_MCUFWDL);
 511                if (value32 & FWDL_ChkSum_rpt)
 512                        break;
 513        } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
 514
 515        if (counter >= POLLING_READY_TIMEOUT_COUNT) {
 516                DBG_88E("%s: chksum report fail! REG_MCUFWDL:0x%08x\n", __func__, value32);
 517                return _FAIL;
 518        }
 519        DBG_88E("%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__, value32);
 520
 521        value32 = rtw_read32(padapter, REG_MCUFWDL);
 522        value32 |= MCUFWDL_RDY;
 523        value32 &= ~WINTINI_RDY;
 524        rtw_write32(padapter, REG_MCUFWDL, value32);
 525
 526        _8051Reset88E(padapter);
 527
 528        /*  polling for FW ready */
 529        counter = 0;
 530        do {
 531                value32 = rtw_read32(padapter, REG_MCUFWDL);
 532                if (value32 & WINTINI_RDY) {
 533                        DBG_88E("%s: Polling FW ready success!! REG_MCUFWDL:0x%08x\n", __func__, value32);
 534                        return _SUCCESS;
 535                }
 536                udelay(5);
 537        } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
 538
 539        DBG_88E("%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n", __func__, value32);
 540        return _FAIL;
 541}
 542
 543#define IS_FW_81xxC(padapter)   (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
 544
 545static int load_firmware(struct rt_firmware *pFirmware, struct device *device)
 546{
 547        s32     rtStatus = _SUCCESS;
 548        const struct firmware *fw;
 549        const char *fw_name = "rtlwifi/rtl8188eufw.bin";
 550        int err = request_firmware(&fw, fw_name, device);
 551
 552        if (err) {
 553                pr_err("Request firmware failed with error 0x%x\n", err);
 554                rtStatus = _FAIL;
 555                goto Exit;
 556        }
 557        if (!fw) {
 558                pr_err("Firmware %s not available\n", fw_name);
 559                rtStatus = _FAIL;
 560                goto Exit;
 561        }
 562        if (fw->size > FW_8188E_SIZE) {
 563                rtStatus = _FAIL;
 564                goto Exit;
 565        }
 566
 567        pFirmware->szFwBuffer = kzalloc(FW_8188E_SIZE, GFP_KERNEL);
 568        if (!pFirmware->szFwBuffer) {
 569                pr_err("Failed to allocate pFirmware->szFwBuffer\n");
 570                rtStatus = _FAIL;
 571                goto Exit;
 572        }
 573        memcpy(pFirmware->szFwBuffer, fw->data, fw->size);
 574        pFirmware->ulFwLength = fw->size;
 575        release_firmware(fw);
 576        DBG_88E_LEVEL(_drv_info_, "+%s: !bUsedWoWLANFw, FmrmwareLen:%d+\n", __func__, pFirmware->ulFwLength);
 577
 578Exit:
 579        return rtStatus;
 580}
 581
 582s32 rtl8188e_FirmwareDownload(struct adapter *padapter)
 583{
 584        s32     rtStatus = _SUCCESS;
 585        u8 writeFW_retry = 0;
 586        u32 fwdl_start_time;
 587        struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
 588        struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
 589        struct device *device = dvobj_to_dev(dvobj);
 590        struct rt_firmware_hdr *pFwHdr = NULL;
 591        u8 *pFirmwareBuf;
 592        u32 FirmwareLen;
 593        static int log_version;
 594
 595        if (!dvobj->firmware.szFwBuffer)
 596                rtStatus = load_firmware(&dvobj->firmware, device);
 597        if (rtStatus == _FAIL) {
 598                dvobj->firmware.szFwBuffer = NULL;
 599                goto Exit;
 600        }
 601        pFirmwareBuf = dvobj->firmware.szFwBuffer;
 602        FirmwareLen = dvobj->firmware.ulFwLength;
 603
 604        /*  To Check Fw header. Added by tynli. 2009.12.04. */
 605        pFwHdr = (struct rt_firmware_hdr *)dvobj->firmware.szFwBuffer;
 606
 607        pHalData->FirmwareVersion =  le16_to_cpu(pFwHdr->Version);
 608        pHalData->FirmwareSubVersion = pFwHdr->Subversion;
 609        pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature);
 610
 611        if (!log_version++)
 612                pr_info("%sFirmware Version %d, SubVersion %d, Signature 0x%x\n",
 613                        DRIVER_PREFIX, pHalData->FirmwareVersion,
 614                        pHalData->FirmwareSubVersion, pHalData->FirmwareSignature);
 615
 616        if (IS_FW_HEADER_EXIST(pFwHdr)) {
 617                /*  Shift 32 bytes for FW header */
 618                pFirmwareBuf = pFirmwareBuf + 32;
 619                FirmwareLen = FirmwareLen - 32;
 620        }
 621
 622        /*  Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */
 623        /*  or it will cause download Fw fail. 2010.02.01. by tynli. */
 624        if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */
 625                rtw_write8(padapter, REG_MCUFWDL, 0x00);
 626                _8051Reset88E(padapter);
 627        }
 628
 629        _FWDownloadEnable(padapter, true);
 630        fwdl_start_time = jiffies;
 631        while (1) {
 632                /* reset the FWDL chksum */
 633                rtw_write8(padapter, REG_MCUFWDL, rtw_read8(padapter, REG_MCUFWDL) | FWDL_ChkSum_rpt);
 634
 635                rtStatus = _WriteFW(padapter, pFirmwareBuf, FirmwareLen);
 636
 637                if (rtStatus == _SUCCESS ||
 638                    (rtw_get_passing_time_ms(fwdl_start_time) > 500 && writeFW_retry++ >= 3))
 639                        break;
 640
 641                DBG_88E("%s writeFW_retry:%u, time after fwdl_start_time:%ums\n",
 642                        __func__, writeFW_retry, rtw_get_passing_time_ms(fwdl_start_time)
 643                );
 644        }
 645        _FWDownloadEnable(padapter, false);
 646        if (_SUCCESS != rtStatus) {
 647                DBG_88E("DL Firmware failed!\n");
 648                goto Exit;
 649        }
 650
 651        rtStatus = _FWFreeToGo(padapter);
 652        if (_SUCCESS != rtStatus) {
 653                DBG_88E("DL Firmware failed!\n");
 654                goto Exit;
 655        }
 656
 657Exit:
 658        return rtStatus;
 659}
 660
 661void rtl8188e_InitializeFirmwareVars(struct adapter *padapter)
 662{
 663        struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
 664
 665        /*  Init Fw LPS related. */
 666        padapter->pwrctrlpriv.bFwCurrentInPSMode = false;
 667
 668        /*  Init H2C counter. by tynli. 2009.12.09. */
 669        pHalData->LastHMEBoxNum = 0;
 670}
 671
 672static void rtl8188e_free_hal_data(struct adapter *padapter)
 673{
 674
 675        kfree(padapter->HalData);
 676        padapter->HalData = NULL;
 677
 678}
 679
 680/*  */
 681/*                      Efuse related code */
 682/*  */
 683enum{
 684                VOLTAGE_V25                                             = 0x03,
 685                LDOE25_SHIFT                                            = 28,
 686        };
 687
 688static bool
 689hal_EfusePgPacketWrite2ByteHeader(
 690                struct adapter *pAdapter,
 691                u8 efuseType,
 692                u16                             *pAddr,
 693                struct pgpkt *pTargetPkt,
 694                bool bPseudoTest);
 695static bool
 696hal_EfusePgPacketWrite1ByteHeader(
 697                struct adapter *pAdapter,
 698                u8 efuseType,
 699                u16                             *pAddr,
 700                struct pgpkt *pTargetPkt,
 701                bool bPseudoTest);
 702static bool
 703hal_EfusePgPacketWriteData(
 704                struct adapter *pAdapter,
 705                u8 efuseType,
 706                u16                             *pAddr,
 707                struct pgpkt *pTargetPkt,
 708                bool bPseudoTest);
 709
 710static void
 711hal_EfusePowerSwitch_RTL8188E(
 712                struct adapter *pAdapter,
 713                u8 bWrite,
 714                u8 PwrState)
 715{
 716        u8 tempval;
 717        u16     tmpV16;
 718
 719        if (PwrState) {
 720                rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
 721
 722                /*  1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */
 723                tmpV16 = rtw_read16(pAdapter, REG_SYS_ISO_CTRL);
 724                if (!(tmpV16 & PWC_EV12V)) {
 725                        tmpV16 |= PWC_EV12V;
 726                        rtw_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16);
 727                }
 728                /*  Reset: 0x0000h[28], default valid */
 729                tmpV16 =  rtw_read16(pAdapter, REG_SYS_FUNC_EN);
 730                if (!(tmpV16 & FEN_ELDR)) {
 731                        tmpV16 |= FEN_ELDR;
 732                        rtw_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16);
 733                }
 734
 735                /*  Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
 736                tmpV16 = rtw_read16(pAdapter, REG_SYS_CLKR);
 737                if ((!(tmpV16 & LOADER_CLK_EN))  || (!(tmpV16 & ANA8M))) {
 738                        tmpV16 |= (LOADER_CLK_EN | ANA8M);
 739                        rtw_write16(pAdapter, REG_SYS_CLKR, tmpV16);
 740                }
 741
 742                if (bWrite) {
 743                        /*  Enable LDO 2.5V before read/write action */
 744                        tempval = rtw_read8(pAdapter, EFUSE_TEST + 3);
 745                        tempval &= 0x0F;
 746                        tempval |= (VOLTAGE_V25 << 4);
 747                        rtw_write8(pAdapter, EFUSE_TEST + 3, (tempval | 0x80));
 748                }
 749        } else {
 750                rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
 751
 752                if (bWrite) {
 753                        /*  Disable LDO 2.5V after read/write action */
 754                        tempval = rtw_read8(pAdapter, EFUSE_TEST + 3);
 755                        rtw_write8(pAdapter, EFUSE_TEST + 3, (tempval & 0x7F));
 756                }
 757        }
 758}
 759
 760static void
 761rtl8188e_EfusePowerSwitch(
 762                struct adapter *pAdapter,
 763                u8 bWrite,
 764                u8 PwrState)
 765{
 766        hal_EfusePowerSwitch_RTL8188E(pAdapter, bWrite, PwrState);
 767}
 768
 769static void Hal_EfuseReadEFuse88E(struct adapter *Adapter,
 770        u16                     _offset,
 771        u16                     _size_byte,
 772        u8 *pbuf,
 773                bool bPseudoTest
 774        )
 775{
 776        u8 *efuseTbl = NULL;
 777        u8 rtemp8[1];
 778        u16     eFuse_Addr = 0;
 779        u8 offset, wren;
 780        u16     i, j;
 781        u16     **eFuseWord = NULL;
 782        u16     efuse_utilized = 0;
 783        u8 u1temp = 0;
 784
 785        /*  */
 786        /*  Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
 787        /*  */
 788        if ((_offset + _size_byte) > EFUSE_MAP_LEN_88E) {/*  total E-Fuse table is 512bytes */
 789                DBG_88E("Hal_EfuseReadEFuse88E(): Invalid offset(%#x) with read bytes(%#x)!!\n", _offset, _size_byte);
 790                goto exit;
 791        }
 792
 793        efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
 794        if (!efuseTbl) {
 795                DBG_88E("%s: alloc efuseTbl fail!\n", __func__);
 796                goto exit;
 797        }
 798
 799        eFuseWord = rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
 800        if (!eFuseWord) {
 801                DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
 802                goto exit;
 803        }
 804
 805        /*  0. Refresh efuse init map as all oxFF. */
 806        for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
 807                for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
 808                        eFuseWord[i][j] = 0xFFFF;
 809
 810        /*  */
 811        /*  1. Read the first byte to check if efuse is empty!!! */
 812        /*  */
 813        /*  */
 814        ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
 815        if (*rtemp8 != 0xFF) {
 816                efuse_utilized++;
 817                eFuse_Addr++;
 818        } else {
 819                DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, *rtemp8);
 820                goto exit;
 821        }
 822
 823        /*  */
 824        /*  2. Read real efuse content. Filter PG header and every section data. */
 825        /*  */
 826        while ((*rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
 827                /*  Check PG header for section num. */
 828                if ((*rtemp8 & 0x1F) == 0x0F) {         /* extended header */
 829                        u1temp = ((*rtemp8 & 0xE0) >> 5);
 830
 831                        ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
 832
 833                        if ((*rtemp8 & 0x0F) == 0x0F) {
 834                                eFuse_Addr++;
 835                                ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
 836
 837                                if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
 838                                        eFuse_Addr++;
 839                                continue;
 840                        } else {
 841                                offset = ((*rtemp8 & 0xF0) >> 1) | u1temp;
 842                                wren = (*rtemp8 & 0x0F);
 843                                eFuse_Addr++;
 844                        }
 845                } else {
 846                        offset = ((*rtemp8 >> 4) & 0x0f);
 847                        wren = (*rtemp8 & 0x0f);
 848                }
 849
 850                if (offset < EFUSE_MAX_SECTION_88E) {
 851                        /*  Get word enable value from PG header */
 852
 853                        for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
 854                                /*  Check word enable condition in the section */
 855                                if (!(wren & 0x01)) {
 856                                        ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
 857                                        eFuse_Addr++;
 858                                        efuse_utilized++;
 859                                        eFuseWord[offset][i] = (*rtemp8 & 0xff);
 860                                        if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
 861                                                break;
 862                                        ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
 863                                        eFuse_Addr++;
 864                                        efuse_utilized++;
 865                                        eFuseWord[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00);
 866                                        if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
 867                                                break;
 868                                }
 869                                wren >>= 1;
 870                        }
 871                }
 872
 873                /*  Read next PG header */
 874                ReadEFuseByte(Adapter, eFuse_Addr, rtemp8, bPseudoTest);
 875
 876                if (*rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
 877                        efuse_utilized++;
 878                        eFuse_Addr++;
 879                }
 880        }
 881
 882        /*  3. Collect 16 sections and 4 word unit into Efuse map. */
 883        for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
 884                for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
 885                        efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff);
 886                        efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff);
 887                }
 888        }
 889
 890        /*  4. Copy from Efuse map to output pointer memory!!! */
 891        for (i = 0; i < _size_byte; i++)
 892                pbuf[i] = efuseTbl[_offset + i];
 893
 894        /*  5. Calculate Efuse utilization. */
 895        rtw_hal_set_hwreg(Adapter, HW_VAR_EFUSE_BYTES, (u8 *)&eFuse_Addr);
 896
 897exit:
 898        kfree(efuseTbl);
 899        kfree(eFuseWord);
 900}
 901
 902static void ReadEFuseByIC(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool bPseudoTest)
 903{
 904        if (!bPseudoTest) {
 905                int ret = _FAIL;
 906                if (rtw_IOL_applied(Adapter)) {
 907                        rtw_hal_power_on(Adapter);
 908
 909                        iol_mode_enable(Adapter, 1);
 910                        ret = iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf);
 911                        iol_mode_enable(Adapter, 0);
 912
 913                        if (_SUCCESS == ret)
 914                                goto exit;
 915                }
 916        }
 917        Hal_EfuseReadEFuse88E(Adapter, _offset, _size_byte, pbuf, bPseudoTest);
 918
 919exit:
 920        return;
 921}
 922
 923static void ReadEFuse_Pseudo(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool bPseudoTest)
 924{
 925        Hal_EfuseReadEFuse88E(Adapter, _offset, _size_byte, pbuf, bPseudoTest);
 926}
 927
 928static void rtl8188e_ReadEFuse(struct adapter *Adapter, u8 efuseType,
 929                               u16 _offset, u16 _size_byte, u8 *pbuf,
 930                               bool bPseudoTest)
 931{
 932        if (bPseudoTest)
 933                ReadEFuse_Pseudo(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
 934        else
 935                ReadEFuseByIC(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
 936}
 937
 938/* Do not support BT */
 939static void Hal_EFUSEGetEfuseDefinition88E(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
 940{
 941        switch (type) {
 942        case TYPE_EFUSE_MAX_SECTION:
 943                {
 944                        u8 *pMax_section;
 945                        pMax_section = (u8 *)pOut;
 946                        *pMax_section = EFUSE_MAX_SECTION_88E;
 947                }
 948                break;
 949        case TYPE_EFUSE_REAL_CONTENT_LEN:
 950                {
 951                        u16 *pu2Tmp;
 952                        pu2Tmp = (u16 *)pOut;
 953                        *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
 954                }
 955                break;
 956        case TYPE_EFUSE_CONTENT_LEN_BANK:
 957                {
 958                        u16 *pu2Tmp;
 959                        pu2Tmp = (u16 *)pOut;
 960                        *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
 961                }
 962                break;
 963        case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
 964                {
 965                        u16 *pu2Tmp;
 966                        pu2Tmp = (u16 *)pOut;
 967                        *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E);
 968                }
 969                break;
 970        case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
 971                {
 972                        u16 *pu2Tmp;
 973                        pu2Tmp = (u16 *)pOut;
 974                        *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E);
 975                }
 976                break;
 977        case TYPE_EFUSE_MAP_LEN:
 978                {
 979                        u16 *pu2Tmp;
 980                        pu2Tmp = (u16 *)pOut;
 981                        *pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
 982                }
 983                break;
 984        case TYPE_EFUSE_PROTECT_BYTES_BANK:
 985                {
 986                        u8 *pu1Tmp;
 987                        pu1Tmp = (u8 *)pOut;
 988                        *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
 989                }
 990                break;
 991        default:
 992                {
 993                        u8 *pu1Tmp;
 994                        pu1Tmp = (u8 *)pOut;
 995                        *pu1Tmp = 0;
 996                }
 997                break;
 998        }
 999}
1000
1001static void Hal_EFUSEGetEfuseDefinition_Pseudo88E(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
1002{
1003        switch (type) {
1004        case TYPE_EFUSE_MAX_SECTION:
1005                {
1006                        u8 *pMax_section;
1007                        pMax_section = (u8 *)pOut;
1008                        *pMax_section = EFUSE_MAX_SECTION_88E;
1009                }
1010                break;
1011        case TYPE_EFUSE_REAL_CONTENT_LEN:
1012                {
1013                        u16 *pu2Tmp;
1014                        pu2Tmp = (u16 *)pOut;
1015                        *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
1016                }
1017                break;
1018        case TYPE_EFUSE_CONTENT_LEN_BANK:
1019                {
1020                        u16 *pu2Tmp;
1021                        pu2Tmp = (u16 *)pOut;
1022                        *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
1023                }
1024                break;
1025        case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
1026                {
1027                        u16 *pu2Tmp;
1028                        pu2Tmp = (u16 *)pOut;
1029                        *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E);
1030                }
1031                break;
1032        case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
1033                {
1034                        u16 *pu2Tmp;
1035                        pu2Tmp = (u16 *)pOut;
1036                        *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E);
1037                }
1038                break;
1039        case TYPE_EFUSE_MAP_LEN:
1040                {
1041                        u16 *pu2Tmp;
1042                        pu2Tmp = (u16 *)pOut;
1043                        *pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
1044                }
1045                break;
1046        case TYPE_EFUSE_PROTECT_BYTES_BANK:
1047                {
1048                        u8 *pu1Tmp;
1049                        pu1Tmp = (u8 *)pOut;
1050                        *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
1051                }
1052                break;
1053        default:
1054                {
1055                        u8 *pu1Tmp;
1056                        pu1Tmp = (u8 *)pOut;
1057                        *pu1Tmp = 0;
1058                }
1059                break;
1060        }
1061}
1062
1063static void rtl8188e_EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool bPseudoTest)
1064{
1065        if (bPseudoTest)
1066                Hal_EFUSEGetEfuseDefinition_Pseudo88E(pAdapter, efuseType, type, pOut);
1067        else
1068                Hal_EFUSEGetEfuseDefinition88E(pAdapter, efuseType, type, pOut);
1069}
1070
1071static u8 Hal_EfuseWordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest)
1072{
1073        u16     tmpaddr = 0;
1074        u16     start_addr = efuse_addr;
1075        u8 badworden = 0x0F;
1076        u8 tmpdata[8];
1077
1078        memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
1079
1080        if (!(word_en & BIT(0))) {
1081                tmpaddr = start_addr;
1082                efuse_OneByteWrite(pAdapter, start_addr++, data[0], bPseudoTest);
1083                efuse_OneByteWrite(pAdapter, start_addr++, data[1], bPseudoTest);
1084
1085                efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0], bPseudoTest);
1086                efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[1], bPseudoTest);
1087                if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
1088                        badworden &= (~BIT(0));
1089        }
1090        if (!(word_en & BIT(1))) {
1091                tmpaddr = start_addr;
1092                efuse_OneByteWrite(pAdapter, start_addr++, data[2], bPseudoTest);
1093                efuse_OneByteWrite(pAdapter, start_addr++, data[3], bPseudoTest);
1094
1095                efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2], bPseudoTest);
1096                efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[3], bPseudoTest);
1097                if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
1098                        badworden &= (~BIT(1));
1099        }
1100        if (!(word_en & BIT(2))) {
1101                tmpaddr = start_addr;
1102                efuse_OneByteWrite(pAdapter, start_addr++, data[4], bPseudoTest);
1103                efuse_OneByteWrite(pAdapter, start_addr++, data[5], bPseudoTest);
1104
1105                efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4], bPseudoTest);
1106                efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[5], bPseudoTest);
1107                if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
1108                        badworden &= (~BIT(2));
1109        }
1110        if (!(word_en & BIT(3))) {
1111                tmpaddr = start_addr;
1112                efuse_OneByteWrite(pAdapter, start_addr++, data[6], bPseudoTest);
1113                efuse_OneByteWrite(pAdapter, start_addr++, data[7], bPseudoTest);
1114
1115                efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6], bPseudoTest);
1116                efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[7], bPseudoTest);
1117                if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
1118                        badworden &= (~BIT(3));
1119        }
1120        return badworden;
1121}
1122
1123static u8 Hal_EfuseWordEnableDataWrite_Pseudo(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest)
1124{
1125        u8 ret;
1126
1127        ret = Hal_EfuseWordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest);
1128        return ret;
1129}
1130
1131static u8 rtl8188e_Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest)
1132{
1133        u8 ret = 0;
1134
1135        if (bPseudoTest)
1136                ret = Hal_EfuseWordEnableDataWrite_Pseudo(pAdapter, efuse_addr, word_en, data, bPseudoTest);
1137        else
1138                ret = Hal_EfuseWordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest);
1139        return ret;
1140}
1141
1142static u16 hal_EfuseGetCurrentSize_8188e(struct adapter *pAdapter, bool bPseudoTest)
1143{
1144        int     bContinual = true;
1145        u16     efuse_addr = 0;
1146        u8 hoffset = 0, hworden = 0;
1147        u8 efuse_data, word_cnts = 0;
1148
1149        if (bPseudoTest)
1150                efuse_addr = (u16)(fakeEfuseUsedBytes);
1151        else
1152                rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
1153
1154        while (bContinual &&
1155               efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest) &&
1156               AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1157                if (efuse_data != 0xFF) {
1158                        if ((efuse_data & 0x1F) == 0x0F) {              /* extended header */
1159                                hoffset = efuse_data;
1160                                efuse_addr++;
1161                                efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest);
1162                                if ((efuse_data & 0x0F) == 0x0F) {
1163                                        efuse_addr++;
1164                                        continue;
1165                                } else {
1166                                        hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
1167                                        hworden = efuse_data & 0x0F;
1168                                }
1169                        } else {
1170                                hoffset = (efuse_data >> 4) & 0x0F;
1171                                hworden =  efuse_data & 0x0F;
1172                        }
1173                        word_cnts = Efuse_CalculateWordCnts(hworden);
1174                        /* read next header */
1175                        efuse_addr = efuse_addr + (word_cnts * 2) + 1;
1176                } else {
1177                        bContinual = false;
1178                }
1179        }
1180
1181        if (bPseudoTest)
1182                fakeEfuseUsedBytes = efuse_addr;
1183        else
1184                rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
1185
1186        return efuse_addr;
1187}
1188
1189static u16 Hal_EfuseGetCurrentSize_Pseudo(struct adapter *pAdapter, bool bPseudoTest)
1190{
1191        u16     ret = 0;
1192
1193        ret = hal_EfuseGetCurrentSize_8188e(pAdapter, bPseudoTest);
1194        return ret;
1195}
1196
1197static u16 rtl8188e_EfuseGetCurrentSize(struct adapter *pAdapter, u8 efuseType, bool bPseudoTest)
1198{
1199        u16     ret = 0;
1200
1201        if (bPseudoTest)
1202                ret = Hal_EfuseGetCurrentSize_Pseudo(pAdapter, bPseudoTest);
1203        else
1204                ret = hal_EfuseGetCurrentSize_8188e(pAdapter, bPseudoTest);
1205        return ret;
1206}
1207
1208static int hal_EfusePgPacketRead_8188e(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
1209{
1210        u8 ReadState = PG_STATE_HEADER;
1211        int     bContinual = true;
1212        int     bDataEmpty = true;
1213        u8 efuse_data, word_cnts = 0;
1214        u16     efuse_addr = 0;
1215        u8 hoffset = 0, hworden = 0;
1216        u8 tmpidx = 0;
1217        u8 tmpdata[8];
1218        u8 max_section = 0;
1219        u8 tmp_header = 0;
1220
1221        EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section, bPseudoTest);
1222
1223        if (!data)
1224                return false;
1225        if (offset > max_section)
1226                return false;
1227
1228        memset((void *)data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
1229        memset((void *)tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
1230
1231        /*  <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
1232        /*  Skip dummy parts to prevent unexpected data read from Efuse. */
1233        /*  By pass right now. 2009.02.19. */
1234        while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1235                /*   Header Read ------------- */
1236                if (ReadState & PG_STATE_HEADER) {
1237                        if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
1238                                if (EXT_HEADER(efuse_data)) {
1239                                        tmp_header = efuse_data;
1240                                        efuse_addr++;
1241                                        efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data, bPseudoTest);
1242                                        if (!ALL_WORDS_DISABLED(efuse_data)) {
1243                                                hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
1244                                                hworden = efuse_data & 0x0F;
1245                                        } else {
1246                                                DBG_88E("Error, All words disabled\n");
1247                                                efuse_addr++;
1248                                                continue;
1249                                        }
1250                                } else {
1251                                        hoffset = (efuse_data >> 4) & 0x0F;
1252                                        hworden =  efuse_data & 0x0F;
1253                                }
1254                                word_cnts = Efuse_CalculateWordCnts(hworden);
1255                                bDataEmpty = true;
1256
1257                                if (hoffset == offset) {
1258                                        for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) {
1259                                                if (efuse_OneByteRead(pAdapter, efuse_addr + 1 + tmpidx, &efuse_data, bPseudoTest)) {
1260                                                        tmpdata[tmpidx] = efuse_data;
1261                                                        if (efuse_data != 0xff)
1262                                                                bDataEmpty = false;
1263                                                }
1264                                        }
1265                                        if (!bDataEmpty) {
1266                                                ReadState = PG_STATE_DATA;
1267                                        } else {/* read next header */
1268                                                efuse_addr = efuse_addr + (word_cnts * 2) + 1;
1269                                                ReadState = PG_STATE_HEADER;
1270                                        }
1271                                } else {/* read next header */
1272                                        efuse_addr = efuse_addr + (word_cnts * 2) + 1;
1273                                        ReadState = PG_STATE_HEADER;
1274                                }
1275                        } else {
1276                                bContinual = false;
1277                        }
1278                } else if (ReadState & PG_STATE_DATA) {
1279                /*   Data section Read ------------- */
1280                        efuse_WordEnableDataRead(hworden, tmpdata, data);
1281                        efuse_addr = efuse_addr + (word_cnts * 2) + 1;
1282                        ReadState = PG_STATE_HEADER;
1283                }
1284
1285        }
1286
1287        if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff)  && (data[3] == 0xff) &&
1288            (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff)  && (data[7] == 0xff))
1289                return false;
1290        else
1291                return true;
1292}
1293
1294static int Hal_EfusePgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
1295{
1296        int     ret;
1297
1298        ret = hal_EfusePgPacketRead_8188e(pAdapter, offset, data, bPseudoTest);
1299        return ret;
1300}
1301
1302static int Hal_EfusePgPacketRead_Pseudo(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
1303{
1304        int     ret;
1305
1306        ret = hal_EfusePgPacketRead_8188e(pAdapter, offset, data, bPseudoTest);
1307        return ret;
1308}
1309
1310static int rtl8188e_Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool bPseudoTest)
1311{
1312        int     ret;
1313
1314        if (bPseudoTest)
1315                ret = Hal_EfusePgPacketRead_Pseudo(pAdapter, offset, data, bPseudoTest);
1316        else
1317                ret = Hal_EfusePgPacketRead(pAdapter, offset, data, bPseudoTest);
1318        return ret;
1319}
1320
1321static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr, bool bPseudoTest)
1322{
1323        u8 originaldata[8], badworden = 0;
1324        u16     efuse_addr = *pAddr;
1325        u32     PgWriteSuccess = 0;
1326
1327        memset((void *)originaldata, 0xff, 8);
1328
1329        if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata, bPseudoTest)) {
1330                /* check if data exist */
1331                badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pFixPkt->word_en, originaldata, bPseudoTest);
1332
1333                if (badworden != 0xf) { /*  write fail */
1334                        PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata, bPseudoTest);
1335
1336                        if (!PgWriteSuccess)
1337                                return false;
1338                        else
1339                                efuse_addr = Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest);
1340                } else {
1341                        efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1;
1342                }
1343        } else {
1344                efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1;
1345        }
1346        *pAddr = efuse_addr;
1347        return true;
1348}
1349
1350static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
1351{
1352        bool bRet = false;
1353        u16     efuse_addr = *pAddr, efuse_max_available_len = 0;
1354        u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
1355        u8 repeatcnt = 0;
1356
1357        EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len, bPseudoTest);
1358
1359        while (efuse_addr < efuse_max_available_len) {
1360                pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
1361                efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
1362                efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
1363
1364                while (tmp_header == 0xFF) {
1365                        if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
1366                                return false;
1367
1368                        efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
1369                        efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
1370                }
1371
1372                /* to write ext_header */
1373                if (tmp_header == pg_header) {
1374                        efuse_addr++;
1375                        pg_header_temp = pg_header;
1376                        pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
1377
1378                        efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
1379                        efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
1380
1381                        while (tmp_header == 0xFF) {
1382                                if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
1383                                        return false;
1384
1385                                efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
1386                                efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
1387                        }
1388
1389                        if ((tmp_header & 0x0F) == 0x0F) {      /* word_en PG fail */
1390                                if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1391                                        return false;
1392                                } else {
1393                                        efuse_addr++;
1394                                        continue;
1395                                }
1396                        } else if (pg_header != tmp_header) {   /* offset PG fail */
1397                                struct pgpkt    fixPkt;
1398                                fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
1399                                fixPkt.word_en = tmp_header & 0x0F;
1400                                fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
1401                                if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr, bPseudoTest))
1402                                        return false;
1403                        } else {
1404                                bRet = true;
1405                                break;
1406                        }
1407                } else if ((tmp_header & 0x1F) == 0x0F) {               /* wrong extended header */
1408                        efuse_addr += 2;
1409                        continue;
1410                }
1411        }
1412
1413        *pAddr = efuse_addr;
1414        return bRet;
1415}
1416
1417static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
1418{
1419        bool bRet = false;
1420        u8 pg_header = 0, tmp_header = 0;
1421        u16     efuse_addr = *pAddr;
1422        u8 repeatcnt = 0;
1423
1424        pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
1425
1426        efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
1427        efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
1428
1429        while (tmp_header == 0xFF) {
1430                if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
1431                        return false;
1432                efuse_OneByteWrite(pAdapter, efuse_addr, pg_header, bPseudoTest);
1433                efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header, bPseudoTest);
1434        }
1435
1436        if (pg_header == tmp_header) {
1437                bRet = true;
1438        } else {
1439                struct pgpkt    fixPkt;
1440                fixPkt.offset = (tmp_header >> 4) & 0x0F;
1441                fixPkt.word_en = tmp_header & 0x0F;
1442                fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
1443                if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr, bPseudoTest))
1444                        return false;
1445        }
1446
1447        *pAddr = efuse_addr;
1448        return bRet;
1449}
1450
1451static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
1452{
1453        u16     efuse_addr = *pAddr;
1454        u8 badworden = 0;
1455        u32     PgWriteSuccess = 0;
1456
1457        badworden = 0x0f;
1458        badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest);
1459        if (badworden == 0x0F) {
1460                /*  write ok */
1461                return true;
1462        } else {
1463                /* reorganize other pg packet */
1464                PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
1465                if (!PgWriteSuccess)
1466                        return false;
1467                else
1468                        return true;
1469        }
1470}
1471
1472static bool
1473hal_EfusePgPacketWriteHeader(
1474                                struct adapter *pAdapter,
1475                                u8 efuseType,
1476                                u16                             *pAddr,
1477                                struct pgpkt *pTargetPkt,
1478                                bool bPseudoTest)
1479{
1480        bool bRet = false;
1481
1482        if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
1483                bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
1484        else
1485                bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
1486
1487        return bRet;
1488}
1489
1490static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
1491                          u8 *pWden)
1492{
1493        u8 match_word_en = 0x0F;        /*  default all words are disabled */
1494
1495        /*  check if the same words are enabled both target and current PG packet */
1496        if (((pTargetPkt->word_en & BIT(0)) == 0) &&
1497            ((pCurPkt->word_en & BIT(0)) == 0))
1498                match_word_en &= ~BIT(0);                               /*  enable word 0 */
1499        if (((pTargetPkt->word_en & BIT(1)) == 0) &&
1500            ((pCurPkt->word_en & BIT(1)) == 0))
1501                match_word_en &= ~BIT(1);                               /*  enable word 1 */
1502        if (((pTargetPkt->word_en & BIT(2)) == 0) &&
1503            ((pCurPkt->word_en & BIT(2)) == 0))
1504                match_word_en &= ~BIT(2);                               /*  enable word 2 */
1505        if (((pTargetPkt->word_en & BIT(3)) == 0) &&
1506            ((pCurPkt->word_en & BIT(3)) == 0))
1507                match_word_en &= ~BIT(3);                               /*  enable word 3 */
1508
1509        *pWden = match_word_en;
1510
1511        if (match_word_en != 0xf)
1512                return true;
1513        else
1514                return false;
1515}
1516
1517static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr, bool bPseudoTest)
1518{
1519        bool bRet = false;
1520        u8 i, efuse_data;
1521
1522        for (i = 0; i < (word_cnts * 2); i++) {
1523                if (efuse_OneByteRead(pAdapter, (startAddr + i), &efuse_data, bPseudoTest) && (efuse_data != 0xFF))
1524                        bRet = true;
1525        }
1526        return bRet;
1527}
1528
1529static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
1530{
1531        bool bRet = false;
1532        u8 i, efuse_data = 0, cur_header = 0;
1533        u8 matched_wden = 0, badworden = 0;
1534        u16     startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
1535        struct pgpkt curPkt;
1536
1537        EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len, bPseudoTest);
1538        EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max, bPseudoTest);
1539
1540        if (efuseType == EFUSE_WIFI) {
1541                if (bPseudoTest) {
1542                        startAddr = (u16)(fakeEfuseUsedBytes % EFUSE_REAL_CONTENT_LEN);
1543                } else {
1544                        rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
1545                        startAddr %= EFUSE_REAL_CONTENT_LEN;
1546                }
1547        } else {
1548                if (bPseudoTest)
1549                        startAddr = (u16)(fakeBTEfuseUsedBytes % EFUSE_REAL_CONTENT_LEN);
1550                else
1551                        startAddr = (u16)(BTEfuseUsedBytes % EFUSE_REAL_CONTENT_LEN);
1552        }
1553
1554        while (1) {
1555                if (startAddr >= efuse_max_available_len) {
1556                        bRet = false;
1557                        break;
1558                }
1559
1560                if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
1561                        if (EXT_HEADER(efuse_data)) {
1562                                cur_header = efuse_data;
1563                                startAddr++;
1564                                efuse_OneByteRead(pAdapter, startAddr, &efuse_data, bPseudoTest);
1565                                if (ALL_WORDS_DISABLED(efuse_data)) {
1566                                        bRet = false;
1567                                        break;
1568                                } else {
1569                                        curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
1570                                        curPkt.word_en = efuse_data & 0x0F;
1571                                }
1572                        } else {
1573                                cur_header  =  efuse_data;
1574                                curPkt.offset = (cur_header >> 4) & 0x0F;
1575                                curPkt.word_en = cur_header & 0x0F;
1576                        }
1577
1578                        curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
1579                        /*  if same header is found but no data followed */
1580                        /*  write some part of data followed by the header. */
1581                        if ((curPkt.offset == pTargetPkt->offset) &&
1582                            (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr + 1, bPseudoTest)) &&
1583                            wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
1584                                /*  Here to write partial data */
1585                                badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr + 1, matched_wden, pTargetPkt->data, bPseudoTest);
1586                                if (badworden != 0x0F) {
1587                                        u32     PgWriteSuccess = 0;
1588                                        /*  if write fail on some words, write these bad words again */
1589
1590                                        PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
1591
1592                                        if (!PgWriteSuccess) {
1593                                                bRet = false;   /*  write fail, return */
1594                                                break;
1595                                        }
1596                                }
1597                                /*  partial write ok, update the target packet for later use */
1598                                for (i = 0; i < 4; i++) {
1599                                        if ((matched_wden & (0x1 << i)) == 0)   /*  this word has been written */
1600                                                pTargetPkt->word_en |= (0x1 << i);      /*  disable the word */
1601                                }
1602                                pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
1603                        }
1604                        /*  read from next header */
1605                        startAddr = startAddr + (curPkt.word_cnts * 2) + 1;
1606                } else {
1607                        /*  not used header, 0xff */
1608                        *pAddr = startAddr;
1609                        bRet = true;
1610                        break;
1611                }
1612        }
1613        return bRet;
1614}
1615
1616static bool
1617hal_EfusePgCheckAvailableAddr(
1618                struct adapter *pAdapter,
1619                u8 efuseType,
1620                bool bPseudoTest
1621        )
1622{
1623        u16     efuse_max_available_len = 0;
1624
1625        /* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */
1626        EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len, false);
1627
1628        if (Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest) >= efuse_max_available_len)
1629                return false;
1630        return true;
1631}
1632
1633static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
1634{
1635        memset((void *)pTargetPkt->data, 0xFF, sizeof(u8) * 8);
1636        pTargetPkt->offset = offset;
1637        pTargetPkt->word_en = word_en;
1638        efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
1639        pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
1640}
1641
1642static bool hal_EfusePgPacketWrite_8188e(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData, bool bPseudoTest)
1643{
1644        struct pgpkt    targetPkt;
1645        u16                     startAddr = 0;
1646        u8 efuseType = EFUSE_WIFI;
1647
1648        if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType, bPseudoTest))
1649                return false;
1650
1651        hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
1652
1653        if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
1654                return false;
1655
1656        if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
1657                return false;
1658
1659        if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
1660                return false;
1661
1662        return true;
1663}
1664
1665static int Hal_EfusePgPacketWrite_Pseudo(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest)
1666{
1667        int ret;
1668
1669        ret = hal_EfusePgPacketWrite_8188e(pAdapter, offset, word_en, data, bPseudoTest);
1670        return ret;
1671}
1672
1673static int Hal_EfusePgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest)
1674{
1675        int     ret = 0;
1676        ret = hal_EfusePgPacketWrite_8188e(pAdapter, offset, word_en, data, bPseudoTest);
1677
1678        return ret;
1679}
1680
1681static int rtl8188e_Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest)
1682{
1683        int     ret;
1684
1685        if (bPseudoTest)
1686                ret = Hal_EfusePgPacketWrite_Pseudo(pAdapter, offset, word_en, data, bPseudoTest);
1687        else
1688                ret = Hal_EfusePgPacketWrite(pAdapter, offset, word_en, data, bPseudoTest);
1689        return ret;
1690}
1691
1692static struct HAL_VERSION ReadChipVersion8188E(struct adapter *padapter)
1693{
1694        u32                             value32;
1695        struct HAL_VERSION              ChipVersion;
1696        struct hal_data_8188e   *pHalData;
1697
1698        pHalData = GET_HAL_DATA(padapter);
1699
1700        value32 = rtw_read32(padapter, REG_SYS_CFG);
1701        ChipVersion.ICType = CHIP_8188E;
1702        ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
1703
1704        ChipVersion.RFType = RF_TYPE_1T1R;
1705        ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
1706        ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /*  IC version (CUT) */
1707
1708        /*  For regulator mode. by tynli. 2011.01.14 */
1709        pHalData->RegulatorMode = ((value32 & TRP_BT_EN) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
1710
1711        ChipVersion.ROMVer = 0; /*  ROM code version. */
1712        pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
1713
1714        dump_chip_info(ChipVersion);
1715
1716        pHalData->VersionID = ChipVersion;
1717
1718        if (IS_1T2R(ChipVersion)) {
1719                pHalData->rf_type = RF_1T2R;
1720                pHalData->NumTotalRFPath = 2;
1721        } else if (IS_2T2R(ChipVersion)) {
1722                pHalData->rf_type = RF_2T2R;
1723                pHalData->NumTotalRFPath = 2;
1724        } else {
1725                pHalData->rf_type = RF_1T1R;
1726                pHalData->NumTotalRFPath = 1;
1727        }
1728
1729        MSG_88E("RF_Type is %x!!\n", pHalData->rf_type);
1730
1731        return ChipVersion;
1732}
1733
1734static void rtl8188e_read_chip_version(struct adapter *padapter)
1735{
1736        ReadChipVersion8188E(padapter);
1737}
1738
1739static void rtl8188e_GetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
1740{
1741}
1742
1743static void rtl8188e_SetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
1744{
1745        struct hal_data_8188e   *pHalData = GET_HAL_DATA(Adapter);
1746        struct odm_dm_struct *podmpriv = &pHalData->odmpriv;
1747        switch (eVariable) {
1748        case HAL_ODM_STA_INFO:
1749                {
1750                        struct sta_info *psta = (struct sta_info *)pValue1;
1751                        if (bSet) {
1752                                DBG_88E("### Set STA_(%d) info\n", psta->mac_id);
1753                                ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, psta);
1754                                ODM_RAInfo_Init(podmpriv, psta->mac_id);
1755                        } else {
1756                                DBG_88E("### Clean STA_(%d) info\n", psta->mac_id);
1757                                ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, NULL);
1758                       }
1759                }
1760                break;
1761        case HAL_ODM_P2P_STATE:
1762                        ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet);
1763                break;
1764        case HAL_ODM_WIFI_DISPLAY_STATE:
1765                        ODM_CmnInfoUpdate(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet);
1766                break;
1767        default:
1768                break;
1769        }
1770}
1771
1772void rtl8188e_clone_haldata(struct adapter *dst_adapter, struct adapter *src_adapter)
1773{
1774        memcpy(dst_adapter->HalData, src_adapter->HalData, dst_adapter->hal_data_sz);
1775}
1776
1777void rtl8188e_start_thread(struct adapter *padapter)
1778{
1779}
1780
1781void rtl8188e_stop_thread(struct adapter *padapter)
1782{
1783}
1784
1785static void hal_notch_filter_8188e(struct adapter *adapter, bool enable)
1786{
1787        if (enable) {
1788                DBG_88E("Enable notch filter\n");
1789                rtw_write8(adapter, rOFDM0_RxDSP + 1, rtw_read8(adapter, rOFDM0_RxDSP + 1) | BIT(1));
1790        } else {
1791                DBG_88E("Disable notch filter\n");
1792                rtw_write8(adapter, rOFDM0_RxDSP + 1, rtw_read8(adapter, rOFDM0_RxDSP + 1) & ~BIT(1));
1793        }
1794}
1795void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc)
1796{
1797        pHalFunc->free_hal_data = &rtl8188e_free_hal_data;
1798
1799        pHalFunc->dm_init = &rtl8188e_init_dm_priv;
1800        pHalFunc->dm_deinit = &rtl8188e_deinit_dm_priv;
1801
1802        pHalFunc->read_chip_version = &rtl8188e_read_chip_version;
1803
1804        pHalFunc->set_bwmode_handler = &PHY_SetBWMode8188E;
1805        pHalFunc->set_channel_handler = &PHY_SwChnl8188E;
1806
1807        pHalFunc->hal_dm_watchdog = &rtl8188e_HalDmWatchDog;
1808
1809        pHalFunc->Add_RateATid = &rtl8188e_Add_RateATid;
1810        pHalFunc->run_thread = &rtl8188e_start_thread;
1811        pHalFunc->cancel_thread = &rtl8188e_stop_thread;
1812
1813        pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E;
1814        pHalFunc->AntDivCompareHandler = &AntDivCompare8188E;
1815        pHalFunc->read_bbreg = &rtl8188e_PHY_QueryBBReg;
1816        pHalFunc->write_bbreg = &rtl8188e_PHY_SetBBReg;
1817        pHalFunc->read_rfreg = &rtl8188e_PHY_QueryRFReg;
1818        pHalFunc->write_rfreg = &rtl8188e_PHY_SetRFReg;
1819
1820        /*  Efuse related function */
1821        pHalFunc->EfusePowerSwitch = &rtl8188e_EfusePowerSwitch;
1822        pHalFunc->ReadEFuse = &rtl8188e_ReadEFuse;
1823        pHalFunc->EFUSEGetEfuseDefinition = &rtl8188e_EFUSE_GetEfuseDefinition;
1824        pHalFunc->EfuseGetCurrentSize = &rtl8188e_EfuseGetCurrentSize;
1825        pHalFunc->Efuse_PgPacketRead = &rtl8188e_Efuse_PgPacketRead;
1826        pHalFunc->Efuse_PgPacketWrite = &rtl8188e_Efuse_PgPacketWrite;
1827        pHalFunc->Efuse_WordEnableDataWrite = &rtl8188e_Efuse_WordEnableDataWrite;
1828
1829        pHalFunc->sreset_init_value = &sreset_init_value;
1830        pHalFunc->sreset_reset_value = &sreset_reset_value;
1831        pHalFunc->silentreset = &rtl8188e_silentreset_for_specific_platform;
1832        pHalFunc->sreset_xmit_status_check = &rtl8188e_sreset_xmit_status_check;
1833        pHalFunc->sreset_linked_status_check  = &rtl8188e_sreset_linked_status_check;
1834        pHalFunc->sreset_get_wifi_status  = &sreset_get_wifi_status;
1835
1836        pHalFunc->GetHalODMVarHandler = &rtl8188e_GetHalODMVar;
1837        pHalFunc->SetHalODMVarHandler = &rtl8188e_SetHalODMVar;
1838
1839        pHalFunc->IOL_exec_cmds_sync = &rtl8188e_IOL_exec_cmds_sync;
1840
1841        pHalFunc->hal_notch_filter = &hal_notch_filter_8188e;
1842}
1843
1844u8 GetEEPROMSize8188E(struct adapter *padapter)
1845{
1846        u8 size = 0;
1847        u32     cr;
1848
1849        cr = rtw_read16(padapter, REG_9346CR);
1850        /*  6: EEPROM used is 93C46, 4: boot from E-Fuse. */
1851        size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
1852
1853        MSG_88E("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46");
1854
1855        return size;
1856}
1857
1858/*  */
1859/*  */
1860/*  LLT R/W/Init function */
1861/*  */
1862/*  */
1863static s32 _LLTWrite(struct adapter *padapter, u32 address, u32 data)
1864{
1865        s32     status = _SUCCESS;
1866        s32     count = 0;
1867        u32     value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
1868        u16     LLTReg = REG_LLT_INIT;
1869
1870        rtw_write32(padapter, LLTReg, value);
1871
1872        /* polling */
1873        do {
1874                value = rtw_read32(padapter, LLTReg);
1875                if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
1876                        break;
1877
1878                if (count > POLLING_LLT_THRESHOLD) {
1879                        status = _FAIL;
1880                        break;
1881                }
1882        } while (count++);
1883
1884        return status;
1885}
1886
1887s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy)
1888{
1889        s32     status = _FAIL;
1890        u32     i;
1891        u32     Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;/*  176, 22k */
1892
1893        if (rtw_IOL_applied(padapter)) {
1894                status = iol_InitLLTTable(padapter, txpktbuf_bndy);
1895        } else {
1896                for (i = 0; i < (txpktbuf_bndy - 1); i++) {
1897                        status = _LLTWrite(padapter, i, i + 1);
1898                        if (_SUCCESS != status)
1899                                return status;
1900                }
1901
1902                /*  end of list */
1903                status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
1904                if (_SUCCESS != status)
1905                        return status;
1906
1907                /*  Make the other pages as ring buffer */
1908                /*  This ring buffer is used as beacon buffer if we config this MAC as two MAC transfer. */
1909                /*  Otherwise used as local loopback buffer. */
1910                for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
1911                        status = _LLTWrite(padapter, i, (i + 1));
1912                        if (_SUCCESS != status)
1913                                return status;
1914                }
1915
1916                /*  Let last entry point to the start entry of ring buffer */
1917                status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
1918                if (_SUCCESS != status) {
1919                        return status;
1920                }
1921        }
1922
1923        return status;
1924}
1925
1926void
1927Hal_InitPGData88E(struct adapter *padapter)
1928{
1929        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
1930
1931        if (!pEEPROM->bautoload_fail_flag) { /*  autoload OK. */
1932                if (!is_boot_from_eeprom(padapter)) {
1933                        /*  Read EFUSE real map to shadow. */
1934                        EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
1935                }
1936        } else {/* autoload fail */
1937                /* update to default value 0xFF */
1938                if (!is_boot_from_eeprom(padapter))
1939                        EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, false);
1940        }
1941}
1942
1943void
1944Hal_EfuseParseIDCode88E(
1945                struct adapter *padapter,
1946                u8 *hwinfo
1947        )
1948{
1949        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
1950        u16                     EEPROMId;
1951
1952        /*  Check 0x8129 again for making sure autoload status!! */
1953        EEPROMId = le16_to_cpu(*((__le16 *)hwinfo));
1954        if (EEPROMId != RTL_EEPROM_ID) {
1955                pr_err("EEPROM ID(%#x) is invalid!!\n", EEPROMId);
1956                pEEPROM->bautoload_fail_flag = true;
1957        } else {
1958                pEEPROM->bautoload_fail_flag = false;
1959        }
1960
1961        pr_info("EEPROM ID = 0x%04x\n", EEPROMId);
1962}
1963
1964static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G, u8 *PROMContent, bool AutoLoadFail)
1965{
1966        u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_88E, group, TxCount = 0;
1967
1968        memset(pwrInfo24G, 0, sizeof(struct txpowerinfo24g));
1969
1970        if (AutoLoadFail) {
1971                for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
1972                        /* 2.4G default value */
1973                        for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
1974                                pwrInfo24G->IndexCCK_Base[rfPath][group] =      EEPROM_DEFAULT_24G_INDEX;
1975                                pwrInfo24G->IndexBW40_Base[rfPath][group] =     EEPROM_DEFAULT_24G_INDEX;
1976                        }
1977                        for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
1978                                if (TxCount == 0) {
1979                                        pwrInfo24G->BW20_Diff[rfPath][0] = EEPROM_DEFAULT_24G_HT20_DIFF;
1980                                        pwrInfo24G->OFDM_Diff[rfPath][0] = EEPROM_DEFAULT_24G_OFDM_DIFF;
1981                                } else {
1982                                        pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1983                                        pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1984                                        pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1985                                        pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
1986                                }
1987                        }
1988                }
1989                return;
1990        }
1991
1992        for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
1993                /* 2.4G default value */
1994                for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
1995                        pwrInfo24G->IndexCCK_Base[rfPath][group] =      PROMContent[eeAddr++];
1996                        if (pwrInfo24G->IndexCCK_Base[rfPath][group] == 0xFF)
1997                                pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
1998                }
1999                for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) {
2000                        pwrInfo24G->IndexBW40_Base[rfPath][group] =     PROMContent[eeAddr++];
2001                        if (pwrInfo24G->IndexBW40_Base[rfPath][group] == 0xFF)
2002                                pwrInfo24G->IndexBW40_Base[rfPath][group] =     EEPROM_DEFAULT_24G_INDEX;
2003                }
2004                for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
2005                        if (TxCount == 0) {
2006                                pwrInfo24G->BW40_Diff[rfPath][TxCount] = 0;
2007                                if (PROMContent[eeAddr] == 0xFF) {
2008                                        pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
2009                                } else {
2010                                        pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0xf0) >> 4;
2011                                        if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3))            /* 4bit sign number to 8 bit sign number */
2012                                                pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
2013                                }
2014
2015                                if (PROMContent[eeAddr] == 0xFF) {
2016                                        pwrInfo24G->OFDM_Diff[rfPath][TxCount] =        EEPROM_DEFAULT_24G_OFDM_DIFF;
2017                                } else {
2018                                        pwrInfo24G->OFDM_Diff[rfPath][TxCount] =        (PROMContent[eeAddr] & 0x0f);
2019                                        if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3))            /* 4bit sign number to 8 bit sign number */
2020                                                pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
2021                                }
2022                                pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
2023                                eeAddr++;
2024                        } else {
2025                                if (PROMContent[eeAddr] == 0xFF) {
2026                                        pwrInfo24G->BW40_Diff[rfPath][TxCount] =        EEPROM_DEFAULT_DIFF;
2027                                } else {
2028                                        pwrInfo24G->BW40_Diff[rfPath][TxCount] =        (PROMContent[eeAddr] & 0xf0) >> 4;
2029                                        if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT(3))            /* 4bit sign number to 8 bit sign number */
2030                                                pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
2031                                }
2032
2033                                if (PROMContent[eeAddr] == 0xFF) {
2034                                        pwrInfo24G->BW20_Diff[rfPath][TxCount] =        EEPROM_DEFAULT_DIFF;
2035                                } else {
2036                                        pwrInfo24G->BW20_Diff[rfPath][TxCount] =        (PROMContent[eeAddr] & 0x0f);
2037                                        if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3))            /* 4bit sign number to 8 bit sign number */
2038                                                pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
2039                                }
2040                                eeAddr++;
2041
2042                                if (PROMContent[eeAddr] == 0xFF) {
2043                                        pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2044                                } else {
2045                                        pwrInfo24G->OFDM_Diff[rfPath][TxCount] =        (PROMContent[eeAddr] & 0xf0) >> 4;
2046                                        if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3))            /* 4bit sign number to 8 bit sign number */
2047                                                pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
2048                                }
2049
2050                                if (PROMContent[eeAddr] == 0xFF) {
2051                                        pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2052                                } else {
2053                                        pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr] & 0x0f);
2054                                        if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT(3))             /* 4bit sign number to 8 bit sign number */
2055                                                pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
2056                                }
2057                                eeAddr++;
2058                        }
2059                }
2060        }
2061}
2062
2063static void hal_get_chnl_group_88e(u8 chnl, u8 *group)
2064{
2065        if (chnl < 3)                   /*  Channel 1-2 */
2066                *group = 0;
2067        else if (chnl < 6)              /*  Channel 3-5 */
2068                *group = 1;
2069        else if (chnl < 9)              /*  Channel 6-8 */
2070                *group = 2;
2071        else if (chnl < 12)             /*  Channel 9-11 */
2072                *group = 3;
2073        else if (chnl < 14)             /*  Channel 12-13 */
2074                *group = 4;
2075        else if (chnl == 14)            /*  Channel 14 */
2076                *group = 5;
2077}
2078
2079void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
2080{
2081        if (AutoLoadFail) {
2082                padapter->pwrctrlpriv.bHWPowerdown = false;
2083                padapter->pwrctrlpriv.bSupportRemoteWakeup = false;
2084        } else {
2085                /* hw power down mode selection , 0:rf-off / 1:power down */
2086
2087                if (padapter->registrypriv.hwpdn_mode == 2)
2088                        padapter->pwrctrlpriv.bHWPowerdown = (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & BIT(4));
2089                else
2090                        padapter->pwrctrlpriv.bHWPowerdown = padapter->registrypriv.hwpdn_mode;
2091
2092                /*  decide hw if support remote wakeup function */
2093                /*  if hw supported, 8051 (SIE) will generate WeakUP signal(D+/D- toggle) when autoresume */
2094                padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT(1)) ? true : false;
2095
2096                DBG_88E("%s...bHWPwrPindetect(%x)-bHWPowerdown(%x) , bSupportRemoteWakeup(%x)\n", __func__,
2097                padapter->pwrctrlpriv.bHWPwrPindetect, padapter->pwrctrlpriv.bHWPowerdown, padapter->pwrctrlpriv.bSupportRemoteWakeup);
2098
2099                DBG_88E("### PS params =>  power_mgnt(%x), usbss_enable(%x) ###\n", padapter->registrypriv.power_mgnt, padapter->registrypriv.usbss_enable);
2100        }
2101}
2102
2103void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail)
2104{
2105        struct hal_data_8188e   *pHalData = GET_HAL_DATA(padapter);
2106        struct txpowerinfo24g pwrInfo24G;
2107        u8 rfPath, ch, group;
2108        u8 TxCount;
2109
2110        Hal_ReadPowerValueFromPROM_8188E(&pwrInfo24G, PROMContent, AutoLoadFail);
2111
2112        if (!AutoLoadFail)
2113                pHalData->bTXPowerDataReadFromEEPORM = true;
2114
2115        for (rfPath = 0; rfPath < pHalData->NumTotalRFPath; rfPath++) {
2116                for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2117                        hal_get_chnl_group_88e(ch, &group);
2118
2119                        pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][group];
2120                        if (ch == 14)
2121                                pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][4];
2122                        else
2123                                pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
2124
2125                        DBG_88E("======= Path %d, Channel %d =======\n", rfPath, ch);
2126                        DBG_88E("Index24G_CCK_Base[%d][%d] = 0x%x\n", rfPath, ch, pHalData->Index24G_CCK_Base[rfPath][ch]);
2127                        DBG_88E("Index24G_BW40_Base[%d][%d] = 0x%x\n", rfPath, ch, pHalData->Index24G_BW40_Base[rfPath][ch]);
2128                }
2129                for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
2130                        pHalData->CCK_24G_Diff[rfPath][TxCount] = pwrInfo24G.CCK_Diff[rfPath][TxCount];
2131                        pHalData->OFDM_24G_Diff[rfPath][TxCount] = pwrInfo24G.OFDM_Diff[rfPath][TxCount];
2132                        pHalData->BW20_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW20_Diff[rfPath][TxCount];
2133                        pHalData->BW40_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW40_Diff[rfPath][TxCount];
2134                        DBG_88E("======= TxCount %d =======\n", TxCount);
2135                        DBG_88E("CCK_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->CCK_24G_Diff[rfPath][TxCount]);
2136                        DBG_88E("OFDM_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->OFDM_24G_Diff[rfPath][TxCount]);
2137                        DBG_88E("BW20_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->BW20_24G_Diff[rfPath][TxCount]);
2138                        DBG_88E("BW40_24G_Diff[%d][%d] = %d\n", rfPath, TxCount, pHalData->BW40_24G_Diff[rfPath][TxCount]);
2139                }
2140        }
2141
2142        /*  2010/10/19 MH Add Regulator recognize for CU. */
2143        if (!AutoLoadFail) {
2144                pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x7);   /* bit0~2 */
2145                if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF)
2146                        pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION & 0x7);       /* bit0~2 */
2147        } else {
2148                pHalData->EEPROMRegulatory = 0;
2149        }
2150        DBG_88E("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory);
2151}
2152
2153void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail)
2154{
2155        struct hal_data_8188e   *pHalData = GET_HAL_DATA(pAdapter);
2156
2157        if (!AutoLoadFail) {
2158                pHalData->CrystalCap = hwinfo[EEPROM_XTAL_88E];
2159                if (pHalData->CrystalCap == 0xFF)
2160                        pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E;
2161        } else {
2162                pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E;
2163        }
2164        DBG_88E("CrystalCap: 0x%2x\n", pHalData->CrystalCap);
2165}
2166
2167void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail)
2168{
2169        struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter);
2170
2171        if (!AutoLoadFail)
2172                pHalData->BoardType = ((hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0xE0) >> 5);
2173        else
2174                pHalData->BoardType = 0;
2175        DBG_88E("Board Type: 0x%2x\n", pHalData->BoardType);
2176}
2177
2178void Hal_EfuseParseEEPROMVer88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
2179{
2180        struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
2181
2182        if (!AutoLoadFail) {
2183                pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_88E];
2184                if (pHalData->EEPROMVersion == 0xFF)
2185                        pHalData->EEPROMVersion = EEPROM_Default_Version;
2186        } else {
2187                pHalData->EEPROMVersion = 1;
2188        }
2189}
2190
2191void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
2192{
2193        padapter->mlmepriv.ChannelPlan =
2194                 hal_com_get_channel_plan(padapter,
2195                                          hwinfo ? hwinfo[EEPROM_ChannelPlan_88E] : 0xFF,
2196                                          padapter->registrypriv.channel_plan,
2197                                          RT_CHANNEL_DOMAIN_WORLD_WIDE_13, AutoLoadFail);
2198
2199        DBG_88E("mlmepriv.ChannelPlan = 0x%02x\n", padapter->mlmepriv.ChannelPlan);
2200}
2201
2202void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
2203{
2204        struct hal_data_8188e   *pHalData = GET_HAL_DATA(padapter);
2205
2206        if (!AutoLoadFail) {
2207                pHalData->EEPROMCustomerID = hwinfo[EEPROM_CUSTOMERID_88E];
2208        } else {
2209                pHalData->EEPROMCustomerID = 0;
2210                pHalData->EEPROMSubCustomerID = 0;
2211        }
2212        DBG_88E("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID);
2213}
2214
2215void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool AutoLoadFail)
2216{
2217        struct hal_data_8188e   *pHalData = GET_HAL_DATA(pAdapter);
2218        struct registry_priv    *registry_par = &pAdapter->registrypriv;
2219
2220        if (!AutoLoadFail) {
2221                /*  Antenna Diversity setting. */
2222                if (registry_par->antdiv_cfg == 2) { /*  2:By EFUSE */
2223                        pHalData->AntDivCfg = (PROMContent[EEPROM_RF_BOARD_OPTION_88E] & 0x18) >> 3;
2224                        if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF)
2225                                pHalData->AntDivCfg = (EEPROM_DEFAULT_BOARD_OPTION & 0x18) >> 3;
2226                } else {
2227                        pHalData->AntDivCfg = registry_par->antdiv_cfg;  /*  0:OFF , 1:ON, 2:By EFUSE */
2228                }
2229
2230                if (registry_par->antdiv_type == 0) {
2231                        /* If TRxAntDivType is AUTO in advanced setting, use EFUSE value instead. */
2232                        pHalData->TRxAntDivType = PROMContent[EEPROM_RF_ANTENNA_OPT_88E];
2233                        if (pHalData->TRxAntDivType == 0xFF)
2234                                pHalData->TRxAntDivType = CG_TRX_HW_ANTDIV; /*  For 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */
2235                } else {
2236                        pHalData->TRxAntDivType = registry_par->antdiv_type;
2237                }
2238
2239                if (pHalData->TRxAntDivType == CG_TRX_HW_ANTDIV || pHalData->TRxAntDivType == CGCS_RX_HW_ANTDIV)
2240                        pHalData->AntDivCfg = 1; /*  0xC1[3] is ignored. */
2241        } else {
2242                pHalData->AntDivCfg = 0;
2243                pHalData->TRxAntDivType = pHalData->TRxAntDivType; /*  The value in the driver setting of device manager. */
2244        }
2245        DBG_88E("EEPROM : AntDivCfg = %x, TRxAntDivType = %x\n", pHalData->AntDivCfg, pHalData->TRxAntDivType);
2246}
2247
2248void Hal_ReadThermalMeter_88E(struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail)
2249{
2250        struct hal_data_8188e   *pHalData = GET_HAL_DATA(Adapter);
2251
2252        /*  ThermalMeter from EEPROM */
2253        if (!AutoloadFail)
2254                pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_88E];
2255        else
2256                pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E;
2257
2258        if (pHalData->EEPROMThermalMeter == 0xff || AutoloadFail) {
2259                pHalData->bAPKThermalMeterIgnore = true;
2260                pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E;
2261        }
2262        DBG_88E("ThermalMeter = 0x%x\n", pHalData->EEPROMThermalMeter);
2263}
2264
2265void Hal_InitChannelPlan(struct adapter *padapter)
2266{
2267}
2268
2269bool HalDetectPwrDownMode88E(struct adapter *Adapter)
2270{
2271        u8 tmpvalue = 0;
2272        struct hal_data_8188e *pHalData = GET_HAL_DATA(Adapter);
2273        struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
2274
2275        EFUSE_ShadowRead(Adapter, 1, EEPROM_RF_FEATURE_OPTION_88E, (u32 *)&tmpvalue);
2276
2277        /*  2010/08/25 MH INF priority > PDN Efuse value. */
2278        if (tmpvalue & BIT(4) && pwrctrlpriv->reg_pdnmode)
2279                pHalData->pwrdown = true;
2280        else
2281                pHalData->pwrdown = false;
2282
2283        DBG_88E("HalDetectPwrDownMode(): PDN =%d\n", pHalData->pwrdown);
2284
2285        return pHalData->pwrdown;
2286}       /*  HalDetectPwrDownMode */
2287
2288/*  This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */
2289/*  We just reserve the value of the register in variable pHalData->RegBcnCtrlVal and then operate */
2290/*  the value of the register via atomic operation. */
2291/*  This prevents from race condition when setting this register. */
2292/*  The value of pHalData->RegBcnCtrlVal is initialized in HwConfigureRTL8192CE() function. */
2293
2294void SetBcnCtrlReg(struct adapter *padapter, u8 SetBits, u8 ClearBits)
2295{
2296        struct hal_data_8188e *pHalData;
2297
2298        pHalData = GET_HAL_DATA(padapter);
2299
2300        pHalData->RegBcnCtrlVal |= SetBits;
2301        pHalData->RegBcnCtrlVal &= ~ClearBits;
2302
2303        rtw_write8(padapter, REG_BCN_CTRL, (u8)pHalData->RegBcnCtrlVal);
2304}
2305