linux/drivers/staging/rtl8188eu/core/rtw_efuse.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program; if not, write to the Free Software Foundation, Inc.,
  16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17 *
  18 *
  19 ******************************************************************************/
  20#define _RTW_EFUSE_C_
  21
  22#include <osdep_service.h>
  23#include <drv_types.h>
  24#include <rtw_efuse.h>
  25
  26
  27
  28/*------------------------Define local variable------------------------------*/
  29u8 fakeEfuseBank;
  30u32 fakeEfuseUsedBytes;
  31u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
  32u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
  33u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
  34
  35u32 BTEfuseUsedBytes;
  36u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
  37u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
  38u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
  39
  40u32 fakeBTEfuseUsedBytes;
  41u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
  42u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
  43u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
  44/*------------------------Define local variable------------------------------*/
  45
  46/*  */
  47#define REG_EFUSE_CTRL          0x0030
  48#define EFUSE_CTRL                      REG_EFUSE_CTRL          /*  E-Fuse Control. */
  49/*  */
  50
  51bool
  52Efuse_Read1ByteFromFakeContent(
  53                        struct adapter *pAdapter,
  54                        u16 Offset,
  55                u8 *Value);
  56bool
  57Efuse_Read1ByteFromFakeContent(
  58                        struct adapter *pAdapter,
  59                        u16 Offset,
  60                u8 *Value)
  61{
  62        if (Offset >= EFUSE_MAX_HW_SIZE)
  63                return false;
  64        if (fakeEfuseBank == 0)
  65                *Value = fakeEfuseContent[Offset];
  66        else
  67                *Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
  68        return true;
  69}
  70
  71static bool
  72Efuse_Write1ByteToFakeContent(
  73                        struct adapter *pAdapter,
  74                        u16 Offset,
  75                        u8 Value)
  76{
  77        if (Offset >= EFUSE_MAX_HW_SIZE)
  78                return false;
  79        if (fakeEfuseBank == 0)
  80                fakeEfuseContent[Offset] = Value;
  81        else
  82                fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
  83        return true;
  84}
  85
  86/*-----------------------------------------------------------------------------
  87 * Function:    Efuse_PowerSwitch
  88 *
  89 * Overview:    When we want to enable write operation, we should change to
  90 *                              pwr on state. When we stop write, we should switch to 500k mode
  91 *                              and disable LDO 2.5V.
  92 *
  93 * Input:       NONE
  94 *
  95 * Output:      NONE
  96 *
  97 * Return:      NONE
  98 *
  99 * Revised History:
 100 * When                 Who             Remark
 101 * 11/17/2008   MHC             Create Version 0.
 102 *
 103 *---------------------------------------------------------------------------*/
 104void
 105Efuse_PowerSwitch(
 106                struct adapter *pAdapter,
 107                u8 write,
 108                u8 PwrState)
 109{
 110        pAdapter->HalFunc.EfusePowerSwitch(pAdapter, write, PwrState);
 111}
 112
 113/*-----------------------------------------------------------------------------
 114 * Function:    efuse_GetCurrentSize
 115 *
 116 * Overview:    Get current efuse size!!!
 117 *
 118 * Input:       NONE
 119 *
 120 * Output:      NONE
 121 *
 122 * Return:      NONE
 123 *
 124 * Revised History:
 125 * When                 Who             Remark
 126 * 11/16/2008   MHC             Create Version 0.
 127 *
 128 *---------------------------------------------------------------------------*/
 129u16
 130Efuse_GetCurrentSize(
 131        struct adapter *pAdapter,
 132        u8 efuseType,
 133        bool pseudo)
 134{
 135        u16 ret = 0;
 136
 137        ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType, pseudo);
 138
 139        return ret;
 140}
 141
 142/*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
 143u8
 144Efuse_CalculateWordCnts(u8 word_en)
 145{
 146        u8 word_cnts = 0;
 147        if (!(word_en & BIT(0)))
 148                word_cnts++; /*  0 : write enable */
 149        if (!(word_en & BIT(1)))
 150                word_cnts++;
 151        if (!(word_en & BIT(2)))
 152                word_cnts++;
 153        if (!(word_en & BIT(3)))
 154                word_cnts++;
 155        return word_cnts;
 156}
 157
 158/*
 159 * Description:
 160 * Execute E-Fuse read byte operation.
 161 * Referred from SD1 Richard.
 162 * Assumption:
 163 *              1. Boot from E-Fuse and successfully auto-load.
 164 *              2. PASSIVE_LEVEL (USB interface)
 165 * Created by Roger, 2008.10.21.
 166 */
 167void
 168ReadEFuseByte(
 169                struct adapter *Adapter,
 170                u16 _offset,
 171                u8 *pbuf,
 172                bool pseudo)
 173{
 174        u32 value32;
 175        u8 readbyte;
 176        u16 retry;
 177
 178        if (pseudo) {
 179                Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
 180                return;
 181        }
 182
 183        /* Write Address */
 184        rtw_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
 185        readbyte = rtw_read8(Adapter, EFUSE_CTRL+2);
 186        rtw_write8(Adapter, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
 187
 188        /* Write bit 32 0 */
 189        readbyte = rtw_read8(Adapter, EFUSE_CTRL+3);
 190        rtw_write8(Adapter, EFUSE_CTRL+3, (readbyte & 0x7f));
 191
 192        /* Check bit 32 read-ready */
 193        retry = 0;
 194        value32 = rtw_read32(Adapter, EFUSE_CTRL);
 195        while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
 196                value32 = rtw_read32(Adapter, EFUSE_CTRL);
 197                retry++;
 198        }
 199
 200        /*  20100205 Joseph: Add delay suggested by SD1 Victor. */
 201        /*  This fix the problem that Efuse read error in high temperature condition. */
 202        /*  Designer says that there shall be some delay after ready bit is set, or the */
 203        /*  result will always stay on last data we read. */
 204        udelay(50);
 205        value32 = rtw_read32(Adapter, EFUSE_CTRL);
 206
 207        *pbuf = (u8)(value32 & 0xff);
 208}
 209
 210/* Description:
 211 *      1. Execute E-Fuse read byte operation according as map offset and
 212 *      save to E-Fuse table.
 213 *      2. Referred from SD1 Richard.
 214 * Assumption:
 215 *      1. Boot from E-Fuse and successfully auto-load.
 216 *      2. PASSIVE_LEVEL (USB interface)
 217 *      Created by Roger, 2008.10.21.
 218 * 2008/12/12 MH
 219 *      1. Reorganize code flow and reserve bytes. and add description.
 220 *      2. Add efuse utilization collect.
 221 * 2008/12/22 MH
 222 *      Read Efuse must check if we write section 1 data again!!!
 223 *      Sec1 write addr must be after sec5.
 224 */
 225
 226static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
 227{
 228        Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
 229}
 230
 231void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
 232        )
 233{
 234        pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType, type, pOut, pseudo);
 235}
 236
 237/*-----------------------------------------------------------------------------
 238 * Function:    EFUSE_Read1Byte
 239 *
 240 * Overview:    Copy from WMAC fot EFUSE read 1 byte.
 241 *
 242 * Input:       NONE
 243 *
 244 * Output:      NONE
 245 *
 246 * Return:      NONE
 247 *
 248 * Revised History:
 249 * When                 Who             Remark
 250 * 09/23/2008   MHC             Copy from WMAC.
 251 *
 252 *---------------------------------------------------------------------------*/
 253u8 EFUSE_Read1Byte(struct adapter *Adapter, u16 Address)
 254{
 255        u8 data;
 256        u8 Bytetemp = {0x00};
 257        u8 temp = {0x00};
 258        u32 k = 0;
 259        u16 contentLen = 0;
 260
 261        EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
 262
 263        if (Address < contentLen) {     /* E-fuse 512Byte */
 264                /* Write E-fuse Register address bit0~7 */
 265                temp = Address & 0xFF;
 266                rtw_write8(Adapter, EFUSE_CTRL+1, temp);
 267                Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
 268                /* Write E-fuse Register address bit8~9 */
 269                temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
 270                rtw_write8(Adapter, EFUSE_CTRL+2, temp);
 271
 272                /* Write 0x30[31]= 0 */
 273                Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
 274                temp = Bytetemp & 0x7F;
 275                rtw_write8(Adapter, EFUSE_CTRL+3, temp);
 276
 277                /* Wait Write-ready (0x30[31]= 1) */
 278                Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
 279                while (!(Bytetemp & 0x80)) {
 280                        Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
 281                        k++;
 282                        if (k == 1000) {
 283                                k = 0;
 284                                break;
 285                        }
 286                }
 287                data = rtw_read8(Adapter, EFUSE_CTRL);
 288                return data;
 289        } else {
 290                return 0xFF;
 291        }
 292
 293} /* EFUSE_Read1Byte */
 294
 295/*  11/16/2008 MH Read one byte from real Efuse. */
 296u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
 297{
 298        u8 tmpidx = 0;
 299        u8 result;
 300
 301        if (pseudo) {
 302                result = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
 303                return result;
 304        }
 305        /*  -----------------e-fuse reg ctrl --------------------------------- */
 306        /* address */
 307        rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
 308        rtw_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
 309                   (rtw_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
 310
 311        rtw_write8(pAdapter, EFUSE_CTRL+3,  0x72);/* read cmd */
 312
 313        while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
 314                tmpidx++;
 315        if (tmpidx < 100) {
 316                *data = rtw_read8(pAdapter, EFUSE_CTRL);
 317                result = true;
 318        } else {
 319                *data = 0xff;
 320                result = false;
 321        }
 322        return result;
 323}
 324
 325/*  11/16/2008 MH Write one byte to reald Efuse. */
 326u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
 327{
 328        u8 tmpidx = 0;
 329        u8 result;
 330
 331        if (pseudo) {
 332                result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
 333                return result;
 334        }
 335
 336        /*  -----------------e-fuse reg ctrl --------------------------------- */
 337        /* address */
 338        rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
 339        rtw_write8(pAdapter, EFUSE_CTRL+2,
 340                   (rtw_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
 341                   (u8)((addr>>8) & 0x03));
 342        rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
 343
 344        rtw_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
 345
 346        while ((0x80 &  rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
 347                tmpidx++;
 348
 349        if (tmpidx < 100)
 350                result = true;
 351        else
 352                result = false;
 353
 354        return result;
 355}
 356
 357int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool pseudo)
 358{
 359        int     ret = 0;
 360
 361        ret =  pAdapter->HalFunc.Efuse_PgPacketRead(pAdapter, offset, data, pseudo);
 362
 363        return ret;
 364}
 365
 366int Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
 367{
 368        int ret;
 369
 370        ret =  pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, pseudo);
 371
 372        return ret;
 373}
 374
 375
 376static int Efuse_PgPacketWrite_BT(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
 377{
 378        int ret;
 379
 380        ret =  pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, pseudo);
 381
 382        return ret;
 383}
 384
 385/*-----------------------------------------------------------------------------
 386 * Function:    efuse_WordEnableDataRead
 387 *
 388 * Overview:    Read allowed word in current efuse section data.
 389 *
 390 * Input:       NONE
 391 *
 392 * Output:      NONE
 393 *
 394 * Return:      NONE
 395 *
 396 * Revised History:
 397 * When                 Who             Remark
 398 * 11/16/2008   MHC             Create Version 0.
 399 * 11/21/2008   MHC             Fix Write bug when we only enable late word.
 400 *
 401 *---------------------------------------------------------------------------*/
 402void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
 403{
 404        if (!(word_en&BIT(0))) {
 405                targetdata[0] = sourdata[0];
 406                targetdata[1] = sourdata[1];
 407        }
 408        if (!(word_en&BIT(1))) {
 409                targetdata[2] = sourdata[2];
 410                targetdata[3] = sourdata[3];
 411        }
 412        if (!(word_en&BIT(2))) {
 413                targetdata[4] = sourdata[4];
 414                targetdata[5] = sourdata[5];
 415        }
 416        if (!(word_en&BIT(3))) {
 417                targetdata[6] = sourdata[6];
 418                targetdata[7] = sourdata[7];
 419        }
 420}
 421
 422u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool pseudo)
 423{
 424        u8 ret = 0;
 425
 426        ret =  pAdapter->HalFunc.Efuse_WordEnableDataWrite(pAdapter, efuse_addr, word_en, data, pseudo);
 427
 428        return ret;
 429}
 430
 431static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
 432{
 433        return efuse_OneByteRead(padapter, address, value, false);
 434}
 435
 436static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
 437{
 438        return efuse_OneByteWrite(padapter, address, *value, false);
 439}
 440
 441/*
 442 * read/wirte raw efuse data
 443 */
 444u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts, u8 *data)
 445{
 446        int i = 0;
 447        u16 real_content_len = 0, max_available_size = 0;
 448        u8 res = _FAIL;
 449        u8 (*rw8)(struct adapter *, u16, u8*);
 450
 451        EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len, false);
 452        EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
 453
 454        if (start_addr > real_content_len)
 455                return _FAIL;
 456
 457        if (write) {
 458                if ((start_addr + cnts) > max_available_size)
 459                        return _FAIL;
 460                rw8 = &efuse_write8;
 461        } else {
 462                rw8 = &efuse_read8;
 463        }
 464
 465        Efuse_PowerSwitch(padapter, write, true);
 466
 467        /*  e-fuse one byte read / write */
 468        for (i = 0; i < cnts; i++) {
 469                if (start_addr >= real_content_len) {
 470                        res = _FAIL;
 471                        break;
 472                }
 473
 474                res = rw8(padapter, start_addr++, data++);
 475                if (_FAIL == res)
 476                        break;
 477        }
 478
 479        Efuse_PowerSwitch(padapter, write, false);
 480
 481        return res;
 482}
 483/*  */
 484u16 efuse_GetMaxSize(struct adapter *padapter)
 485{
 486        u16 max_size;
 487        EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size, false);
 488        return max_size;
 489}
 490/*  */
 491u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
 492{
 493        Efuse_PowerSwitch(padapter, false, true);
 494        *size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, false);
 495        Efuse_PowerSwitch(padapter, false, false);
 496
 497        return _SUCCESS;
 498}
 499/*  */
 500u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 501{
 502        u16 mapLen = 0;
 503
 504        EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 505
 506        if ((addr + cnts) > mapLen)
 507                return _FAIL;
 508
 509        Efuse_PowerSwitch(padapter, false, true);
 510
 511        efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
 512
 513        Efuse_PowerSwitch(padapter, false, false);
 514
 515        return _SUCCESS;
 516}
 517
 518u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 519{
 520        u16 mapLen = 0;
 521
 522        EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 523
 524        if ((addr + cnts) > mapLen)
 525                return _FAIL;
 526
 527        Efuse_PowerSwitch(padapter, false, true);
 528
 529        efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
 530
 531        Efuse_PowerSwitch(padapter, false, false);
 532
 533        return _SUCCESS;
 534}
 535/*  */
 536u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 537{
 538        u8 offset, word_en;
 539        u8 *map;
 540        u8 newdata[PGPKT_DATA_SIZE + 1];
 541        s32     i, idx;
 542        u8 ret = _SUCCESS;
 543        u16 mapLen = 0;
 544
 545        EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 546
 547        if ((addr + cnts) > mapLen)
 548                return _FAIL;
 549
 550        map = rtw_zmalloc(mapLen);
 551        if (map == NULL)
 552                return _FAIL;
 553
 554        ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
 555        if (ret == _FAIL)
 556                goto exit;
 557
 558        Efuse_PowerSwitch(padapter, true, true);
 559
 560        offset = (addr >> 3);
 561        word_en = 0xF;
 562        _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
 563        i = addr & 0x7; /*  index of one package */
 564        idx = 0;        /*  data index */
 565
 566        if (i & 0x1) {
 567                /*  odd start */
 568                if (data[idx] != map[addr+idx]) {
 569                        word_en &= ~BIT(i >> 1);
 570                        newdata[i-1] = map[addr+idx-1];
 571                        newdata[i] = data[idx];
 572                }
 573                i++;
 574                idx++;
 575        }
 576        do {
 577                for (; i < PGPKT_DATA_SIZE; i += 2) {
 578                        if (cnts == idx)
 579                                break;
 580                        if ((cnts - idx) == 1) {
 581                                if (data[idx] != map[addr+idx]) {
 582                                        word_en &= ~BIT(i >> 1);
 583                                        newdata[i] = data[idx];
 584                                        newdata[i+1] = map[addr+idx+1];
 585                                }
 586                                idx++;
 587                                break;
 588                        } else {
 589                                if ((data[idx] != map[addr+idx]) ||
 590                                    (data[idx+1] != map[addr+idx+1])) {
 591                                        word_en &= ~BIT(i >> 1);
 592                                        newdata[i] = data[idx];
 593                                        newdata[i+1] = data[idx + 1];
 594                                }
 595                                idx += 2;
 596                        }
 597                        if (idx == cnts)
 598                                break;
 599                }
 600
 601                if (word_en != 0xF) {
 602                        ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
 603                        DBG_88E("offset=%x\n", offset);
 604                        DBG_88E("word_en=%x\n", word_en);
 605
 606                        for (i = 0; i < PGPKT_DATA_SIZE; i++)
 607                                DBG_88E("data=%x \t", newdata[i]);
 608                        if (ret == _FAIL)
 609                                break;
 610                }
 611
 612                if (idx == cnts)
 613                        break;
 614
 615                offset++;
 616                i = 0;
 617                word_en = 0xF;
 618                _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
 619        } while (1);
 620
 621        Efuse_PowerSwitch(padapter, true, false);
 622exit:
 623        kfree(map);
 624        return ret;
 625}
 626
 627/*  */
 628u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 629{
 630        u8 offset, word_en;
 631        u8 *map;
 632        u8 newdata[PGPKT_DATA_SIZE + 1];
 633        s32     i, idx;
 634        u8 ret = _SUCCESS;
 635        u16 mapLen = 0;
 636
 637        EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
 638
 639        if ((addr + cnts) > mapLen)
 640                return _FAIL;
 641
 642        map = rtw_zmalloc(mapLen);
 643        if (map == NULL)
 644                return _FAIL;
 645
 646        ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
 647        if (ret == _FAIL)
 648                goto exit;
 649
 650        Efuse_PowerSwitch(padapter, true, true);
 651
 652        offset = (addr >> 3);
 653        word_en = 0xF;
 654        _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
 655        i = addr & 0x7; /*  index of one package */
 656        idx = 0;        /*  data index */
 657
 658        if (i & 0x1) {
 659                /*  odd start */
 660                if (data[idx] != map[addr+idx]) {
 661                        word_en &= ~BIT(i >> 1);
 662                        newdata[i-1] = map[addr+idx-1];
 663                        newdata[i] = data[idx];
 664                }
 665                i++;
 666                idx++;
 667        }
 668        do {
 669                for (; i < PGPKT_DATA_SIZE; i += 2) {
 670                        if (cnts == idx)
 671                                break;
 672                        if ((cnts - idx) == 1) {
 673                                if (data[idx] != map[addr+idx]) {
 674                                        word_en &= ~BIT(i >> 1);
 675                                        newdata[i] = data[idx];
 676                                        newdata[i+1] = map[addr+idx+1];
 677                                }
 678                                idx++;
 679                                break;
 680                        } else {
 681                                if ((data[idx] != map[addr+idx]) ||
 682                                    (data[idx+1] != map[addr+idx+1])) {
 683                                        word_en &= ~BIT(i >> 1);
 684                                        newdata[i] = data[idx];
 685                                        newdata[i+1] = data[idx + 1];
 686                                }
 687                                idx += 2;
 688                        }
 689                        if (idx == cnts)
 690                                break;
 691                }
 692
 693                if (word_en != 0xF) {
 694                        DBG_88E("%s: offset=%#X\n", __func__, offset);
 695                        DBG_88E("%s: word_en=%#X\n", __func__, word_en);
 696                        DBG_88E("%s: data=", __func__);
 697                        for (i = 0; i < PGPKT_DATA_SIZE; i++)
 698                                DBG_88E("0x%02X ", newdata[i]);
 699                        DBG_88E("\n");
 700
 701                        ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, false);
 702                        if (ret == _FAIL)
 703                                break;
 704                }
 705
 706                if (idx == cnts)
 707                        break;
 708
 709                offset++;
 710                i = 0;
 711                word_en = 0xF;
 712                _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
 713        } while (1);
 714
 715        Efuse_PowerSwitch(padapter, true, false);
 716
 717exit:
 718
 719        kfree(map);
 720
 721        return ret;
 722}
 723
 724/*-----------------------------------------------------------------------------
 725 * Function:    efuse_ShadowRead1Byte
 726 *                      efuse_ShadowRead2Byte
 727 *                      efuse_ShadowRead4Byte
 728 *
 729 * Overview:    Read from efuse init map by one/two/four bytes !!!!!
 730 *
 731 * Input:       NONE
 732 *
 733 * Output:      NONE
 734 *
 735 * Return:      NONE
 736 *
 737 * Revised History:
 738 * When                 Who             Remark
 739 * 11/12/2008   MHC             Create Version 0.
 740 *
 741 *---------------------------------------------------------------------------*/
 742static void
 743efuse_ShadowRead1Byte(
 744                struct adapter *pAdapter,
 745                u16 Offset,
 746                u8 *Value)
 747{
 748        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 749
 750        *Value = pEEPROM->efuse_eeprom_data[Offset];
 751
 752}       /*  EFUSE_ShadowRead1Byte */
 753
 754/* Read Two Bytes */
 755static void
 756efuse_ShadowRead2Byte(
 757                struct adapter *pAdapter,
 758                u16 Offset,
 759                u16 *Value)
 760{
 761        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 762
 763        *Value = pEEPROM->efuse_eeprom_data[Offset];
 764        *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
 765
 766}       /*  EFUSE_ShadowRead2Byte */
 767
 768/* Read Four Bytes */
 769static void
 770efuse_ShadowRead4Byte(
 771                struct adapter *pAdapter,
 772                u16 Offset,
 773                u32 *Value)
 774{
 775        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 776
 777        *Value = pEEPROM->efuse_eeprom_data[Offset];
 778        *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
 779        *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
 780        *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
 781
 782}       /*  efuse_ShadowRead4Byte */
 783
 784/*-----------------------------------------------------------------------------
 785 * Function:    Efuse_ReadAllMap
 786 *
 787 * Overview:    Read All Efuse content
 788 *
 789 * Input:       NONE
 790 *
 791 * Output:      NONE
 792 *
 793 * Return:      NONE
 794 *
 795 * Revised History:
 796 * When                 Who             Remark
 797 * 11/11/2008   MHC             Create Version 0.
 798 *
 799 *---------------------------------------------------------------------------*/
 800static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
 801{
 802        u16 mapLen = 0;
 803
 804        Efuse_PowerSwitch(pAdapter, false, true);
 805
 806        EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
 807
 808        efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
 809
 810        Efuse_PowerSwitch(pAdapter, false, false);
 811}
 812
 813/*-----------------------------------------------------------------------------
 814 * Function:    EFUSE_ShadowMapUpdate
 815 *
 816 * Overview:    Transfer current EFUSE content to shadow init and modify map.
 817 *
 818 * Input:       NONE
 819 *
 820 * Output:      NONE
 821 *
 822 * Return:      NONE
 823 *
 824 * Revised History:
 825 * When                 Who             Remark
 826 * 11/13/2008   MHC             Create Version 0.
 827 *
 828 *---------------------------------------------------------------------------*/
 829void EFUSE_ShadowMapUpdate(
 830        struct adapter *pAdapter,
 831        u8 efuseType,
 832        bool pseudo)
 833{
 834        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 835        u16 mapLen = 0;
 836
 837        EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
 838
 839        if (pEEPROM->bautoload_fail_flag)
 840                _rtw_memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
 841        else
 842                Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
 843} /*  EFUSE_ShadowMapUpdate */
 844
 845/*-----------------------------------------------------------------------------
 846 * Function:    EFUSE_ShadowRead
 847 *
 848 * Overview:    Read from efuse init map !!!!!
 849 *
 850 * Input:       NONE
 851 *
 852 * Output:      NONE
 853 *
 854 * Return:      NONE
 855 *
 856 * Revised History:
 857 * When                 Who             Remark
 858 * 11/12/2008   MHC             Create Version 0.
 859 *
 860 *---------------------------------------------------------------------------*/
 861void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
 862{
 863        if (Type == 1)
 864                efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
 865        else if (Type == 2)
 866                efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
 867        else if (Type == 4)
 868                efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
 869
 870}       /*  EFUSE_ShadowRead */
 871