linux/drivers/staging/rtl8723bs/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 ******************************************************************************/
  15#define _RTW_EFUSE_C_
  16
  17#include <drv_types.h>
  18#include <rtw_debug.h>
  19#include <hal_data.h>
  20#include <linux/jiffies.h>
  21
  22
  23/*------------------------Define local variable------------------------------*/
  24u8 fakeEfuseBank = 0;
  25u32 fakeEfuseUsedBytes = 0;
  26u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
  27u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
  28u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
  29
  30u32 BTEfuseUsedBytes = 0;
  31u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
  32u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
  33u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
  34
  35u32 fakeBTEfuseUsedBytes = 0;
  36u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
  37u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
  38u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
  39/*------------------------Define local variable------------------------------*/
  40
  41/*  */
  42#define REG_EFUSE_CTRL          0x0030
  43#define EFUSE_CTRL                      REG_EFUSE_CTRL          /*  E-Fuse Control. */
  44/*  */
  45
  46bool
  47Efuse_Read1ByteFromFakeContent(
  48        struct adapter *padapter,
  49        u16     Offset,
  50        u8 *Value);
  51bool
  52Efuse_Read1ByteFromFakeContent(
  53        struct adapter *padapter,
  54        u16     Offset,
  55        u8 *Value)
  56{
  57        if (Offset >= EFUSE_MAX_HW_SIZE) {
  58                return false;
  59        }
  60        /* DbgPrint("Read fake content, offset = %d\n", Offset); */
  61        if (fakeEfuseBank == 0)
  62                *Value = fakeEfuseContent[Offset];
  63        else
  64                *Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
  65        return true;
  66}
  67
  68bool
  69Efuse_Write1ByteToFakeContent(
  70        struct adapter *padapter,
  71        u16     Offset,
  72        u8 Value);
  73bool
  74Efuse_Write1ByteToFakeContent(
  75        struct adapter *padapter,
  76        u16     Offset,
  77        u8 Value)
  78{
  79        if (Offset >= EFUSE_MAX_HW_SIZE) {
  80                return false;
  81        }
  82        if (fakeEfuseBank == 0)
  83                fakeEfuseContent[Offset] = Value;
  84        else{
  85                fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
  86        }
  87        return true;
  88}
  89
  90/*-----------------------------------------------------------------------------
  91 * Function:    Efuse_PowerSwitch
  92 *
  93 * Overview:    When we want to enable write operation, we should change to
  94 *                      pwr on state. When we stop write, we should switch to 500k mode
  95 *                      and disable LDO 2.5V.
  96 *
  97 * Input:       NONE
  98 *
  99 * Output:      NONE
 100 *
 101 * Return:      NONE
 102 *
 103 * Revised History:
 104 * When                 Who             Remark
 105 * 11/17/2008   MHC             Create Version 0.
 106 *
 107 *---------------------------------------------------------------------------*/
 108void
 109Efuse_PowerSwitch(
 110struct adapter *padapter,
 111u8 bWrite,
 112u8 PwrState)
 113{
 114        padapter->HalFunc.EfusePowerSwitch(padapter, bWrite, PwrState);
 115}
 116
 117/*-----------------------------------------------------------------------------
 118 * Function:    Efuse_GetCurrentSize
 119 *
 120 * Overview:    Get current efuse size!!!
 121 *
 122 * Input:       NONE
 123 *
 124 * Output:      NONE
 125 *
 126 * Return:      NONE
 127 *
 128 * Revised History:
 129 * When                 Who             Remark
 130 * 11/16/2008   MHC             Create Version 0.
 131 *
 132 *---------------------------------------------------------------------------*/
 133u16
 134Efuse_GetCurrentSize(
 135        struct adapter *padapter,
 136        u8      efuseType,
 137        bool            bPseudoTest)
 138{
 139        u16 ret = 0;
 140
 141        ret = padapter->HalFunc.EfuseGetCurrentSize(padapter, efuseType, bPseudoTest);
 142
 143        return ret;
 144}
 145
 146/*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
 147u8
 148Efuse_CalculateWordCnts(u8 word_en)
 149{
 150        u8 word_cnts = 0;
 151        if (!(word_en & BIT(0)))
 152                word_cnts++; /*  0 : write enable */
 153        if (!(word_en & BIT(1)))
 154                word_cnts++;
 155        if (!(word_en & BIT(2)))
 156                word_cnts++;
 157        if (!(word_en & BIT(3)))
 158                word_cnts++;
 159        return word_cnts;
 160}
 161
 162/*  */
 163/*      Description: */
 164/*              1. Execute E-Fuse read byte operation according as map offset and */
 165/*                  save to E-Fuse table. */
 166/*              2. Referred from SD1 Richard. */
 167/*  */
 168/*      Assumption: */
 169/*              1. Boot from E-Fuse and successfully auto-load. */
 170/*              2. PASSIVE_LEVEL (USB interface) */
 171/*  */
 172/*      Created by Roger, 2008.10.21. */
 173/*  */
 174/*      2008/12/12 MH   1. Reorganize code flow and reserve bytes. and add description. */
 175/*                                      2. Add efuse utilization collect. */
 176/*      2008/12/22 MH   Read Efuse must check if we write section 1 data again!!! Sec1 */
 177/*                                      write addr must be after sec5. */
 178/*  */
 179
 180void
 181efuse_ReadEFuse(
 182        struct adapter *Adapter,
 183        u8 efuseType,
 184        u16     _offset,
 185        u16     _size_byte,
 186        u8 *pbuf,
 187bool    bPseudoTest
 188        );
 189void
 190efuse_ReadEFuse(
 191        struct adapter *Adapter,
 192        u8 efuseType,
 193        u16     _offset,
 194        u16     _size_byte,
 195        u8 *pbuf,
 196bool    bPseudoTest
 197        )
 198{
 199        Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
 200}
 201
 202void
 203EFUSE_GetEfuseDefinition(
 204        struct adapter *padapter,
 205        u8 efuseType,
 206        u8 type,
 207        void    *pOut,
 208        bool            bPseudoTest
 209        )
 210{
 211        padapter->HalFunc.EFUSEGetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest);
 212}
 213
 214/*-----------------------------------------------------------------------------
 215 * Function:    EFUSE_Read1Byte
 216 *
 217 * Overview:    Copy from WMAC fot EFUSE read 1 byte.
 218 *
 219 * Input:       NONE
 220 *
 221 * Output:      NONE
 222 *
 223 * Return:      NONE
 224 *
 225 * Revised History:
 226 * When                 Who             Remark
 227 * 09/23/2008   MHC             Copy from WMAC.
 228 *
 229 *---------------------------------------------------------------------------*/
 230u8
 231EFUSE_Read1Byte(
 232struct adapter *Adapter,
 233u16     Address)
 234{
 235        u8 data;
 236        u8 Bytetemp = {0x00};
 237        u8 temp = {0x00};
 238        u32 k = 0;
 239        u16 contentLen = 0;
 240
 241        EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
 242
 243        if (Address < contentLen) {/* E-fuse 512Byte */
 244                /* Write E-fuse Register address bit0~7 */
 245                temp = Address & 0xFF;
 246                rtw_write8(Adapter, EFUSE_CTRL+1, temp);
 247                Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
 248                /* Write E-fuse Register address bit8~9 */
 249                temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
 250                rtw_write8(Adapter, EFUSE_CTRL+2, temp);
 251
 252                /* Write 0x30[31]= 0 */
 253                Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
 254                temp = Bytetemp & 0x7F;
 255                rtw_write8(Adapter, EFUSE_CTRL+3, temp);
 256
 257                /* Wait Write-ready (0x30[31]= 1) */
 258                Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
 259                while (!(Bytetemp & 0x80)) {
 260                        Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
 261                        k++;
 262                        if (k == 1000) {
 263                                k = 0;
 264                                break;
 265                        }
 266                }
 267                data = rtw_read8(Adapter, EFUSE_CTRL);
 268                return data;
 269        } else
 270                return 0xFF;
 271
 272} /* EFUSE_Read1Byte */
 273
 274/*  11/16/2008 MH Read one byte from real Efuse. */
 275u8
 276efuse_OneByteRead(
 277struct adapter *padapter,
 278u16             addr,
 279u8      *data,
 280bool            bPseudoTest)
 281{
 282        u32 tmpidx = 0;
 283        u8 bResult;
 284        u8 readbyte;
 285
 286        /* DBG_871X("===> EFUSE_OneByteRead(), addr = %x\n", addr); */
 287        /* DBG_871X("===> EFUSE_OneByteRead() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */
 288
 289        if (bPseudoTest) {
 290                bResult = Efuse_Read1ByteFromFakeContent(padapter, addr, data);
 291                return bResult;
 292        }
 293
 294        /*  <20130121, Kordan> For SMIC EFUSE specificatoin. */
 295        /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
 296        /* PHY_SetMacReg(padapter, 0x34, BIT11, 0); */
 297        rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) & (~BIT11));
 298
 299        /*  -----------------e-fuse reg ctrl --------------------------------- */
 300        /* address */
 301        rtw_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xff));
 302        rtw_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
 303        (rtw_read8(padapter, EFUSE_CTRL+2)&0xFC));
 304
 305        /* rtw_write8(padapter, EFUSE_CTRL+3,  0x72); read cmd */
 306        /* Write bit 32 0 */
 307        readbyte = rtw_read8(padapter, EFUSE_CTRL+3);
 308        rtw_write8(padapter, EFUSE_CTRL+3, (readbyte & 0x7f));
 309
 310        while (!(0x80 & rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 1000)) {
 311                mdelay(1);
 312                tmpidx++;
 313        }
 314        if (tmpidx < 100) {
 315                *data = rtw_read8(padapter, EFUSE_CTRL);
 316                bResult = true;
 317        } else{
 318                *data = 0xff;
 319                bResult = false;
 320                DBG_871X("%s: [ERROR] addr = 0x%x bResult =%d time out 1s !!!\n", __func__, addr, bResult);
 321                DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL));
 322        }
 323
 324        return bResult;
 325}
 326
 327/*  11/16/2008 MH Write one byte to reald Efuse. */
 328u8
 329efuse_OneByteWrite(
 330struct adapter *padapter,
 331u16             addr,
 332u8      data,
 333bool            bPseudoTest)
 334{
 335        u8 tmpidx = 0;
 336        u8 bResult = false;
 337        u32 efuseValue = 0;
 338
 339        /* DBG_871X("===> EFUSE_OneByteWrite(), addr = %x data =%x\n", addr, data); */
 340        /* DBG_871X("===> EFUSE_OneByteWrite() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */
 341
 342        if (bPseudoTest) {
 343                bResult = Efuse_Write1ByteToFakeContent(padapter, addr, data);
 344                return bResult;
 345        }
 346
 347
 348        /*  -----------------e-fuse reg ctrl --------------------------------- */
 349        /* address */
 350
 351
 352        efuseValue = rtw_read32(padapter, EFUSE_CTRL);
 353        efuseValue |= (BIT21|BIT31);
 354        efuseValue &= ~(0x3FFFF);
 355        efuseValue |= ((addr<<8 | data) & 0x3FFFF);
 356
 357
 358        /*  <20130227, Kordan> 8192E MP chip A-cut had better not set 0x34[11] until B-Cut. */
 359
 360        /*  <20130121, Kordan> For SMIC EFUSE specificatoin. */
 361        /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
 362        /* PHY_SetMacReg(padapter, 0x34, BIT11, 1); */
 363        rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) | (BIT11));
 364        rtw_write32(padapter, EFUSE_CTRL, 0x90600000|((addr<<8 | data)));
 365
 366        while ((0x80 &  rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100)) {
 367                mdelay(1);
 368                tmpidx++;
 369        }
 370
 371        if (tmpidx < 100) {
 372                bResult = true;
 373        } else{
 374                bResult = false;
 375                DBG_871X("%s: [ERROR] addr = 0x%x , efuseValue = 0x%x , bResult =%d time out 1s !!!\n",
 376                                        __func__, addr, efuseValue, bResult);
 377                DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL));
 378        }
 379
 380        /*  disable Efuse program enable */
 381        PHY_SetMacReg(padapter, EFUSE_TEST, BIT(11), 0);
 382
 383        return bResult;
 384}
 385
 386int
 387Efuse_PgPacketRead(struct adapter *padapter,
 388                                u8      offset,
 389                                u8      *data,
 390                                bool            bPseudoTest)
 391{
 392        int     ret = 0;
 393
 394        ret =  padapter->HalFunc.Efuse_PgPacketRead(padapter, offset, data, bPseudoTest);
 395
 396        return ret;
 397}
 398
 399int
 400Efuse_PgPacketWrite(struct adapter *padapter,
 401                                u8      offset,
 402                                u8      word_en,
 403                                u8      *data,
 404                                bool            bPseudoTest)
 405{
 406        int ret;
 407
 408        ret =  padapter->HalFunc.Efuse_PgPacketWrite(padapter, offset, word_en, data, bPseudoTest);
 409
 410        return ret;
 411}
 412
 413/*-----------------------------------------------------------------------------
 414 * Function:    efuse_WordEnableDataRead
 415 *
 416 * Overview:    Read allowed word in current efuse section data.
 417 *
 418 * Input:       NONE
 419 *
 420 * Output:      NONE
 421 *
 422 * Return:      NONE
 423 *
 424 * Revised History:
 425 * When                 Who             Remark
 426 * 11/16/2008   MHC             Create Version 0.
 427 * 11/21/2008   MHC             Fix Write bug when we only enable late word.
 428 *
 429 *---------------------------------------------------------------------------*/
 430void
 431efuse_WordEnableDataRead(u8 word_en,
 432                                                u8 *sourdata,
 433                                                u8 *targetdata)
 434{
 435        if (!(word_en&BIT(0))) {
 436                targetdata[0] = sourdata[0];
 437                targetdata[1] = sourdata[1];
 438        }
 439        if (!(word_en&BIT(1))) {
 440                targetdata[2] = sourdata[2];
 441                targetdata[3] = sourdata[3];
 442        }
 443        if (!(word_en&BIT(2))) {
 444                targetdata[4] = sourdata[4];
 445                targetdata[5] = sourdata[5];
 446        }
 447        if (!(word_en&BIT(3))) {
 448                targetdata[6] = sourdata[6];
 449                targetdata[7] = sourdata[7];
 450        }
 451}
 452
 453
 454u8
 455Efuse_WordEnableDataWrite(struct adapter *padapter,
 456                                                u16     efuse_addr,
 457                                                u8 word_en,
 458                                                u8 *data,
 459                                                bool            bPseudoTest)
 460{
 461        u8 ret = 0;
 462
 463        ret =  padapter->HalFunc.Efuse_WordEnableDataWrite(padapter, efuse_addr, word_en, data, bPseudoTest);
 464
 465        return ret;
 466}
 467
 468/*-----------------------------------------------------------------------------
 469 * Function:    Efuse_ReadAllMap
 470 *
 471 * Overview:    Read All Efuse content
 472 *
 473 * Input:       NONE
 474 *
 475 * Output:      NONE
 476 *
 477 * Return:      NONE
 478 *
 479 * Revised History:
 480 * When                 Who             Remark
 481 * 11/11/2008   MHC             Create Version 0.
 482 *
 483 *---------------------------------------------------------------------------*/
 484void
 485Efuse_ReadAllMap(
 486        struct adapter *padapter,
 487        u8 efuseType,
 488        u8 *Efuse,
 489        bool            bPseudoTest);
 490void
 491Efuse_ReadAllMap(
 492        struct adapter *padapter,
 493        u8 efuseType,
 494        u8 *Efuse,
 495        bool            bPseudoTest)
 496{
 497        u16 mapLen = 0;
 498
 499        Efuse_PowerSwitch(padapter, false, true);
 500
 501        EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
 502
 503        efuse_ReadEFuse(padapter, efuseType, 0, mapLen, Efuse, bPseudoTest);
 504
 505        Efuse_PowerSwitch(padapter, false, false);
 506}
 507
 508/*-----------------------------------------------------------------------------
 509 * Function:    efuse_ShadowRead1Byte
 510 *              efuse_ShadowRead2Byte
 511 *              efuse_ShadowRead4Byte
 512 *
 513 * Overview:    Read from efuse init map by one/two/four bytes !!!!!
 514 *
 515 * Input:       NONE
 516 *
 517 * Output:      NONE
 518 *
 519 * Return:      NONE
 520 *
 521 * Revised History:
 522 * When                 Who             Remark
 523 * 11/12/2008   MHC             Create Version 0.
 524 *
 525 *---------------------------------------------------------------------------*/
 526static void
 527efuse_ShadowRead1Byte(
 528struct adapter *padapter,
 529u16     Offset,
 530        u8 *Value)
 531{
 532        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
 533
 534        *Value = pEEPROM->efuse_eeprom_data[Offset];
 535
 536}       /*  EFUSE_ShadowRead1Byte */
 537
 538/* Read Two Bytes */
 539static void
 540efuse_ShadowRead2Byte(
 541struct adapter *padapter,
 542u16     Offset,
 543        u16     *Value)
 544{
 545        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
 546
 547        *Value = pEEPROM->efuse_eeprom_data[Offset];
 548        *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
 549
 550}       /*  EFUSE_ShadowRead2Byte */
 551
 552/* Read Four Bytes */
 553static void
 554efuse_ShadowRead4Byte(
 555struct adapter *padapter,
 556u16     Offset,
 557        u32     *Value)
 558{
 559        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
 560
 561        *Value = pEEPROM->efuse_eeprom_data[Offset];
 562        *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
 563        *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
 564        *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
 565
 566}       /*  efuse_ShadowRead4Byte */
 567
 568/*-----------------------------------------------------------------------------
 569 * Function:    EFUSE_ShadowMapUpdate
 570 *
 571 * Overview:    Transfer current EFUSE content to shadow init and modify map.
 572 *
 573 * Input:       NONE
 574 *
 575 * Output:      NONE
 576 *
 577 * Return:      NONE
 578 *
 579 * Revised History:
 580 * When                 Who             Remark
 581 * 11/13/2008   MHC             Create Version 0.
 582 *
 583 *---------------------------------------------------------------------------*/
 584void EFUSE_ShadowMapUpdate(
 585        struct adapter *padapter,
 586        u8 efuseType,
 587        bool    bPseudoTest)
 588{
 589        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
 590        u16 mapLen = 0;
 591
 592        EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
 593
 594        if (pEEPROM->bautoload_fail_flag == true) {
 595                memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
 596        } else{
 597                Efuse_ReadAllMap(padapter, efuseType, pEEPROM->efuse_eeprom_data, bPseudoTest);
 598        }
 599
 600        /* PlatformMoveMemory((void *)&pHalData->EfuseMap[EFUSE_MODIFY_MAP][0], */
 601        /* void *)&pHalData->EfuseMap[EFUSE_INIT_MAP][0], mapLen); */
 602} /*  EFUSE_ShadowMapUpdate */
 603
 604
 605/*-----------------------------------------------------------------------------
 606 * Function:    EFUSE_ShadowRead
 607 *
 608 * Overview:    Read from efuse init map !!!!!
 609 *
 610 * Input:       NONE
 611 *
 612 * Output:      NONE
 613 *
 614 * Return:      NONE
 615 *
 616 * Revised History:
 617 * When                 Who             Remark
 618 * 11/12/2008   MHC             Create Version 0.
 619 *
 620 *---------------------------------------------------------------------------*/
 621void
 622EFUSE_ShadowRead(
 623        struct adapter *padapter,
 624        u8 Type,
 625        u16     Offset,
 626        u32     *Value)
 627{
 628        if (Type == 1)
 629                efuse_ShadowRead1Byte(padapter, Offset, (u8 *)Value);
 630        else if (Type == 2)
 631                efuse_ShadowRead2Byte(padapter, Offset, (u16 *)Value);
 632        else if (Type == 4)
 633                efuse_ShadowRead4Byte(padapter, Offset, (u32 *)Value);
 634
 635}       /* EFUSE_ShadowRead*/
 636