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