linux/drivers/staging/rtl8723au/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 <osdep_service.h>
  18#include <drv_types.h>
  19
  20#include <rtw_efuse.h>
  21#include <rtl8723a_hal.h>
  22#include <usb_ops_linux.h>
  23
  24#define REG_EFUSE_CTRL          0x0030
  25#define EFUSE_CTRL              REG_EFUSE_CTRL  /* E-Fuse Control */
  26
  27#define VOLTAGE_V25             0x03
  28#define LDOE25_SHIFT            28
  29
  30/*
  31 * When we want to enable write operation, we should change to
  32 * pwr on state. When we stop write, we should switch to 500k mode
  33 * and disable LDO 2.5V.
  34 */
  35static void Efuse_PowerSwitch(struct rtw_adapter *padapter,
  36                              u8 bWrite, u8 PwrState)
  37{
  38        u8 tempval;
  39        u16 tmpV16;
  40
  41        if (PwrState == true) {
  42                rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
  43
  44                /*
  45                 * 1.2V Power: From VDDON with Power
  46                 * Cut(0x0000h[15]), default valid
  47                 */
  48                tmpV16 = rtl8723au_read16(padapter, REG_SYS_ISO_CTRL);
  49                if (!(tmpV16 & PWC_EV12V)) {
  50                        tmpV16 |= PWC_EV12V;
  51                        rtl8723au_write16(padapter, REG_SYS_ISO_CTRL, tmpV16);
  52                }
  53                /* Reset: 0x0000h[28], default valid */
  54                tmpV16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN);
  55                if (!(tmpV16 & FEN_ELDR)) {
  56                        tmpV16 |= FEN_ELDR;
  57                        rtl8723au_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
  58                }
  59
  60                /*
  61                 * Clock: Gated(0x0008h[5]) 8M(0x0008h[1])
  62                 * clock from ANA, default valid
  63                 */
  64                tmpV16 = rtl8723au_read16(padapter, REG_SYS_CLKR);
  65                if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
  66                        tmpV16 |= (LOADER_CLK_EN | ANA8M);
  67                        rtl8723au_write16(padapter, REG_SYS_CLKR, tmpV16);
  68                }
  69
  70                if (bWrite == true) {
  71                        /*  Enable LDO 2.5V before read/write action */
  72                        tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3);
  73                        tempval &= 0x0F;
  74                        tempval |= (VOLTAGE_V25 << 4);
  75                        rtl8723au_write8(padapter, EFUSE_TEST + 3,
  76                                         tempval | 0x80);
  77                }
  78        } else {
  79                rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
  80
  81                if (bWrite == true) {
  82                        /*  Disable LDO 2.5V after read/write action */
  83                        tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3);
  84                        rtl8723au_write8(padapter, EFUSE_TEST + 3,
  85                                         tempval & 0x7F);
  86                }
  87        }
  88}
  89
  90u16 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
  91{
  92        u16 ret = 0;
  93
  94        if (efuseType == EFUSE_WIFI)
  95                ret = rtl8723a_EfuseGetCurrentSize_WiFi(pAdapter);
  96        else
  97                ret = rtl8723a_EfuseGetCurrentSize_BT(pAdapter);
  98
  99        return ret;
 100}
 101
 102/* Get current efuse area enabled word */
 103u8 Efuse_CalculateWordCnts23a(u8 word_en)
 104{
 105        return hweight8((~word_en) & 0xf);
 106}
 107
 108/*
 109 * Description: Execute E-Fuse read byte operation.
 110 *
 111 * Assumptions: 1. Boot from E-Fuse and successfully auto-load.
 112 *              2. PASSIVE_LEVEL (USB interface)
 113 */
 114void ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
 115{
 116        u32     value32;
 117        u8      readbyte;
 118        u16     retry;
 119
 120        /* Write Address */
 121        rtl8723au_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
 122        readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
 123        rtl8723au_write8(Adapter, EFUSE_CTRL+2,
 124                         ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
 125
 126        /* Write bit 32 0 */
 127        readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
 128        rtl8723au_write8(Adapter, EFUSE_CTRL+3, readbyte & 0x7f);
 129
 130        /* Check bit 32 read-ready */
 131        retry = 0;
 132        value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
 133        while (!((value32 >> 24) & 0x80) && retry < 10000) {
 134                value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
 135                retry++;
 136        }
 137
 138        /*
 139         * Added suggested delay. This fixes the problem that
 140         * Efuse read error in high temperature condition.
 141         * Designer says that there shall be some delay after
 142         * ready bit is set, or the result will always stay
 143         * on last data we read.
 144         */
 145        udelay(50);
 146        value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
 147
 148        *pbuf = (u8)(value32 & 0xff);
 149}
 150
 151void EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
 152                                 u8 type, void *pOut)
 153{
 154        u8 *pu1Tmp;
 155        u16 *pu2Tmp;
 156        u8 *pMax_section;
 157
 158        switch (type) {
 159        case TYPE_EFUSE_MAX_SECTION:
 160                pMax_section = pOut;
 161
 162                if (efuseType == EFUSE_WIFI)
 163                        *pMax_section = EFUSE_MAX_SECTION_8723A;
 164                else
 165                        *pMax_section = EFUSE_BT_MAX_SECTION;
 166                break;
 167
 168        case TYPE_EFUSE_REAL_CONTENT_LEN:
 169                pu2Tmp = pOut;
 170
 171                if (efuseType == EFUSE_WIFI)
 172                        *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
 173                else
 174                        *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
 175                break;
 176
 177        case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
 178                pu2Tmp = pOut;
 179
 180                if (efuseType == EFUSE_WIFI)
 181                        *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
 182                                   EFUSE_OOB_PROTECT_BYTES);
 183                else
 184                        *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN -
 185                                   EFUSE_PROTECT_BYTES_BANK);
 186                break;
 187
 188        case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
 189                pu2Tmp = pOut;
 190
 191                if (efuseType == EFUSE_WIFI)
 192                        *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
 193                                   EFUSE_OOB_PROTECT_BYTES);
 194                else
 195                        *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN -
 196                                   (EFUSE_PROTECT_BYTES_BANK * 3));
 197                break;
 198
 199        case TYPE_EFUSE_MAP_LEN:
 200                pu2Tmp = pOut;
 201
 202                if (efuseType == EFUSE_WIFI)
 203                        *pu2Tmp = EFUSE_MAP_LEN_8723A;
 204                else
 205                        *pu2Tmp = EFUSE_BT_MAP_LEN;
 206                break;
 207
 208        case TYPE_EFUSE_PROTECT_BYTES_BANK:
 209                pu1Tmp = pOut;
 210
 211                if (efuseType == EFUSE_WIFI)
 212                        *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
 213                else
 214                        *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
 215                break;
 216
 217        case TYPE_EFUSE_CONTENT_LEN_BANK:
 218                pu2Tmp = pOut;
 219
 220                if (efuseType == EFUSE_WIFI)
 221                        *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
 222                else
 223                        *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
 224                break;
 225
 226        default:
 227                pu1Tmp = pOut;
 228                *pu1Tmp = 0;
 229                break;
 230        }
 231}
 232
 233/* Copy from WMAC for EFUSE read 1 byte. */
 234u8 EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
 235{
 236        u8      data;
 237        u8      Bytetemp = {0x00};
 238        u8      temp = {0x00};
 239        u32     k = 0;
 240        u16     contentLen = 0;
 241
 242        EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
 243                                 TYPE_EFUSE_REAL_CONTENT_LEN,
 244                                 (void *)&contentLen);
 245
 246        if (Address < contentLen) { /* E-fuse 512Byte */
 247                /* Write E-fuse Register address bit0~7 */
 248                temp = Address & 0xFF;
 249                rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp);
 250                Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
 251                /* Write E-fuse Register address bit8~9 */
 252                temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
 253                rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp);
 254
 255                /* Write 0x30[31]= 0 */
 256                Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
 257                temp = Bytetemp & 0x7F;
 258                rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp);
 259
 260                /* Wait Write-ready (0x30[31]= 1) */
 261                Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
 262                while (!(Bytetemp & 0x80)) {
 263                        Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
 264                        k++;
 265                        if (k == 1000) {
 266                                k = 0;
 267                                break;
 268                        }
 269                }
 270                data = rtl8723au_read8(Adapter, EFUSE_CTRL);
 271                return data;
 272        }
 273        return 0xFF;
 274}
 275
 276/* Read one byte from real Efuse. */
 277int efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
 278{
 279        u8      tmpidx = 0;
 280        int     bResult;
 281
 282        /*  -----------------e-fuse reg ctrl ---------------------------- */
 283        /* address */
 284        rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
 285        rtl8723au_write8(pAdapter, EFUSE_CTRL + 2,
 286                         ((u8)((addr >> 8) & 0x03)) |
 287                         (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
 288
 289        rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0x72); /* read cmd */
 290
 291        while (!(0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) &&
 292               (tmpidx < 100))
 293                tmpidx++;
 294        if (tmpidx < 100) {
 295                *data = rtl8723au_read8(pAdapter, EFUSE_CTRL);
 296                bResult = _SUCCESS;
 297        } else {
 298                *data = 0xff;
 299                bResult = _FAIL;
 300        }
 301        return bResult;
 302}
 303
 304/* Write one byte to reald Efuse. */
 305int efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
 306{
 307        u8      tmpidx = 0;
 308        int     bResult;
 309
 310        /* return       0; */
 311
 312        /*  -----------------e-fuse reg ctrl ------------------------- */
 313        /* address */
 314        rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
 315        rtl8723au_write8(pAdapter, EFUSE_CTRL + 2,
 316                         (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
 317                         (u8)((addr >> 8) & 0x03));
 318        rtl8723au_write8(pAdapter, EFUSE_CTRL, data); /* data */
 319
 320        rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */
 321
 322        while ((0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) &&
 323               (tmpidx < 100)) {
 324                tmpidx++;
 325        }
 326
 327        if (tmpidx < 100)
 328                bResult = _SUCCESS;
 329        else
 330                bResult = _FAIL;
 331
 332        return bResult;
 333}
 334
 335/* Read allowed word in current efuse section data. */
 336void efuse_WordEnableDataRead23a(u8 word_en, u8 *sourdata, u8 *targetdata)
 337{
 338        if (!(word_en&BIT(0))) {
 339                targetdata[0] = sourdata[0];
 340                targetdata[1] = sourdata[1];
 341        }
 342        if (!(word_en&BIT(1))) {
 343                targetdata[2] = sourdata[2];
 344                targetdata[3] = sourdata[3];
 345        }
 346        if (!(word_en&BIT(2))) {
 347                targetdata[4] = sourdata[4];
 348                targetdata[5] = sourdata[5];
 349        }
 350        if (!(word_en&BIT(3))) {
 351                targetdata[6] = sourdata[6];
 352                targetdata[7] = sourdata[7];
 353        }
 354}
 355
 356static int efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value)
 357{
 358        return efuse_OneByteRead23a(padapter, address, value);
 359}
 360
 361static int efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value)
 362{
 363        return efuse_OneByteWrite23a(padapter, address, *value);
 364}
 365
 366/* read/write raw efuse data */
 367int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
 368                        u16 cnts, u8 *data)
 369{
 370        int i = 0;
 371        u16 real_content_len = 0, max_available_size = 0;
 372        int res = _FAIL;
 373        int (*rw8)(struct rtw_adapter *, u16, u8*);
 374
 375        EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
 376                                 TYPE_EFUSE_REAL_CONTENT_LEN,
 377                                 (void *)&real_content_len);
 378        EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
 379                                 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
 380                                 (void *)&max_available_size);
 381
 382        if (start_addr > real_content_len)
 383                return _FAIL;
 384
 385        if (true == bWrite) {
 386                if ((start_addr + cnts) > max_available_size)
 387                        return _FAIL;
 388                rw8 = &efuse_write8;
 389        } else
 390                rw8 = &efuse_read8;
 391
 392        Efuse_PowerSwitch(padapter, bWrite, true);
 393
 394        /* e-fuse one byte read/write */
 395        for (i = 0; i < cnts; i++) {
 396                if (start_addr >= real_content_len) {
 397                        res = _FAIL;
 398                        break;
 399                }
 400
 401                res = rw8(padapter, start_addr++, data++);
 402                if (res == _FAIL)
 403                        break;
 404        }
 405
 406        Efuse_PowerSwitch(padapter, bWrite, false);
 407
 408        return res;
 409}
 410
 411u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter)
 412{
 413        u16 max_size;
 414
 415        EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
 416                                 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
 417                                 (void *)&max_size);
 418        return max_size;
 419}
 420
 421int rtw_efuse_map_read23a(struct rtw_adapter *padapter,
 422                          u16 addr, u16 cnts, u8 *data)
 423{
 424        u16 mapLen = 0;
 425
 426        EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
 427                                 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
 428
 429        if ((addr + cnts) > mapLen)
 430                return _FAIL;
 431
 432        Efuse_PowerSwitch(padapter, false, true);
 433
 434        rtl8723a_readefuse(padapter, EFUSE_WIFI, addr, cnts, data);
 435
 436        Efuse_PowerSwitch(padapter, false, false);
 437
 438        return _SUCCESS;
 439}
 440
 441int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter,
 442                             u16 addr, u16 cnts, u8 *data)
 443{
 444        u16 mapLen = 0;
 445
 446        EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
 447                                 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
 448
 449        if ((addr + cnts) > mapLen)
 450                return _FAIL;
 451
 452        Efuse_PowerSwitch(padapter, false, true);
 453
 454        rtl8723a_readefuse(padapter, EFUSE_BT, addr, cnts, data);
 455
 456        Efuse_PowerSwitch(padapter, false, false);
 457
 458        return _SUCCESS;
 459}
 460
 461/* Read All Efuse content */
 462static void Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType,
 463                             u8 *Efuse)
 464{
 465        u16     mapLen = 0;
 466
 467        Efuse_PowerSwitch(pAdapter, false, true);
 468
 469        EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN,
 470                                 (void *)&mapLen);
 471
 472        rtl8723a_readefuse(pAdapter, efuseType, 0, mapLen, Efuse);
 473
 474        Efuse_PowerSwitch(pAdapter, false, false);
 475}
 476
 477/*
 478 * Functions:   efuse_ShadowRead1Byte
 479 *              efuse_ShadowRead2Byte
 480 *              efuse_ShadowRead4Byte
 481 *
 482 * Read from efuse init map by one/two/four bytes
 483 */
 484static void efuse_ShadowRead1Byte(struct rtw_adapter *pAdapter, u16 Offset,
 485                                  u8 *Value)
 486{
 487        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 488
 489        *Value = pEEPROM->efuse_eeprom_data[Offset];
 490}
 491
 492static void efuse_ShadowRead2Byte(struct rtw_adapter *pAdapter, u16 Offset,
 493                                  u16 *Value)
 494{
 495        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 496
 497        *Value = pEEPROM->efuse_eeprom_data[Offset];
 498        *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
 499}
 500
 501static void efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset,
 502                                  u32 *Value)
 503{
 504        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 505
 506        *Value = pEEPROM->efuse_eeprom_data[Offset];
 507        *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
 508        *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
 509        *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
 510}
 511
 512/* Transfer current EFUSE content to shadow init and modify map. */
 513void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType)
 514{
 515        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
 516        u16     mapLen = 0;
 517
 518        EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
 519                                 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
 520
 521        if (pEEPROM->bautoload_fail_flag == true)
 522                memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
 523        else
 524                Efuse_ReadAllMap(pAdapter, efuseType,
 525                                 pEEPROM->efuse_eeprom_data);
 526}
 527
 528/* Read from efuse init map */
 529void EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, u8 Type,
 530                         u16 Offset, u32 *Value)
 531{
 532        if (Type == 1)
 533                efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
 534        else if (Type == 2)
 535                efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
 536        else if (Type == 4)
 537                efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
 538}
 539