linux/drivers/net/wireless/realtek/rtlwifi/efuse.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2012  Realtek Corporation.
   4 *
   5 * Tmis 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 * Tmis 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 * Tme full GNU General Public License is included in this distribution in the
  15 * file called LICENSE.
  16 *
  17 * Contact Information:
  18 * wlanfae <wlanfae@realtek.com>
  19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20 * Hsinchu 300, Taiwan.
  21 *
  22 * Larry Finger <Larry.Finger@lwfinger.net>
  23 *
  24 *****************************************************************************/
  25#include "wifi.h"
  26#include "efuse.h"
  27#include <linux/export.h>
  28
  29static const u8 MAX_PGPKT_SIZE = 9;
  30static const u8 PGPKT_DATA_SIZE = 8;
  31static const int EFUSE_MAX_SIZE = 512;
  32
  33static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = {
  34        {0, 0, 0, 2},
  35        {0, 1, 0, 2},
  36        {0, 2, 0, 2},
  37        {1, 0, 0, 1},
  38        {1, 0, 1, 1},
  39        {1, 1, 0, 1},
  40        {1, 1, 1, 3},
  41        {1, 3, 0, 17},
  42        {3, 3, 1, 48},
  43        {10, 0, 0, 6},
  44        {10, 3, 0, 1},
  45        {10, 3, 1, 1},
  46        {11, 0, 0, 28}
  47};
  48
  49static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, u16 offset,
  50                                    u8 *value);
  51static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, u16 offset,
  52                                    u16 *value);
  53static void efuse_shadow_read_4byte(struct ieee80211_hw *hw, u16 offset,
  54                                    u32 *value);
  55static void efuse_shadow_write_1byte(struct ieee80211_hw *hw, u16 offset,
  56                                     u8 value);
  57static void efuse_shadow_write_2byte(struct ieee80211_hw *hw, u16 offset,
  58                                     u16 value);
  59static void efuse_shadow_write_4byte(struct ieee80211_hw *hw, u16 offset,
  60                                     u32 value);
  61static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr,
  62                                u8 data);
  63static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse);
  64static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset,
  65                                u8 *data);
  66static int efuse_pg_packet_write(struct ieee80211_hw *hw, u8 offset,
  67                                 u8 word_en, u8 *data);
  68static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata,
  69                                        u8 *targetdata);
  70static u8 enable_efuse_data_write(struct ieee80211_hw *hw,
  71                                  u16 efuse_addr, u8 word_en, u8 *data);
  72static void efuse_power_switch(struct ieee80211_hw *hw, u8 write,
  73                               u8 pwrstate);
  74static u16 efuse_get_current_size(struct ieee80211_hw *hw);
  75static u8 efuse_calculate_word_cnts(u8 word_en);
  76
  77void efuse_initialize(struct ieee80211_hw *hw)
  78{
  79        struct rtl_priv *rtlpriv = rtl_priv(hw);
  80        u8 bytetemp;
  81        u8 temp;
  82
  83        bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1);
  84        temp = bytetemp | 0x20;
  85        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1, temp);
  86
  87        bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1);
  88        temp = bytetemp & 0xFE;
  89        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1, temp);
  90
  91        bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3);
  92        temp = bytetemp | 0x80;
  93        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3, temp);
  94
  95        rtl_write_byte(rtlpriv, 0x2F8, 0x3);
  96
  97        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72);
  98
  99}
 100
 101u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address)
 102{
 103        struct rtl_priv *rtlpriv = rtl_priv(hw);
 104        u8 data;
 105        u8 bytetemp;
 106        u8 temp;
 107        u32 k = 0;
 108        const u32 efuse_len =
 109                rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE];
 110
 111        if (address < efuse_len) {
 112                temp = address & 0xFF;
 113                rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
 114                               temp);
 115                bytetemp = rtl_read_byte(rtlpriv,
 116                                         rtlpriv->cfg->maps[EFUSE_CTRL] + 2);
 117                temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC);
 118                rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2,
 119                               temp);
 120
 121                bytetemp = rtl_read_byte(rtlpriv,
 122                                         rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
 123                temp = bytetemp & 0x7F;
 124                rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3,
 125                               temp);
 126
 127                bytetemp = rtl_read_byte(rtlpriv,
 128                                         rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
 129                while (!(bytetemp & 0x80)) {
 130                        bytetemp = rtl_read_byte(rtlpriv,
 131                                                 rtlpriv->cfg->
 132                                                 maps[EFUSE_CTRL] + 3);
 133                        k++;
 134                        if (k == 1000) {
 135                                k = 0;
 136                                break;
 137                        }
 138                }
 139                data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
 140                return data;
 141        } else
 142                return 0xFF;
 143
 144}
 145EXPORT_SYMBOL(efuse_read_1byte);
 146
 147void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value)
 148{
 149        struct rtl_priv *rtlpriv = rtl_priv(hw);
 150        u8 bytetemp;
 151        u8 temp;
 152        u32 k = 0;
 153        const u32 efuse_len =
 154                rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE];
 155
 156        RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "Addr=%x Data =%x\n",
 157                 address, value);
 158
 159        if (address < efuse_len) {
 160                rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value);
 161
 162                temp = address & 0xFF;
 163                rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
 164                               temp);
 165                bytetemp = rtl_read_byte(rtlpriv,
 166                                         rtlpriv->cfg->maps[EFUSE_CTRL] + 2);
 167
 168                temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC);
 169                rtl_write_byte(rtlpriv,
 170                               rtlpriv->cfg->maps[EFUSE_CTRL] + 2, temp);
 171
 172                bytetemp = rtl_read_byte(rtlpriv,
 173                                         rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
 174                temp = bytetemp | 0x80;
 175                rtl_write_byte(rtlpriv,
 176                               rtlpriv->cfg->maps[EFUSE_CTRL] + 3, temp);
 177
 178                bytetemp = rtl_read_byte(rtlpriv,
 179                                         rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
 180
 181                while (bytetemp & 0x80) {
 182                        bytetemp = rtl_read_byte(rtlpriv,
 183                                                 rtlpriv->cfg->
 184                                                 maps[EFUSE_CTRL] + 3);
 185                        k++;
 186                        if (k == 100) {
 187                                k = 0;
 188                                break;
 189                        }
 190                }
 191        }
 192
 193}
 194
 195void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf)
 196{
 197        struct rtl_priv *rtlpriv = rtl_priv(hw);
 198        u32 value32;
 199        u8 readbyte;
 200        u16 retry;
 201
 202        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
 203                       (_offset & 0xff));
 204        readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2);
 205        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2,
 206                       ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
 207
 208        readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3);
 209        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3,
 210                       (readbyte & 0x7f));
 211
 212        retry = 0;
 213        value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
 214        while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) {
 215                value32 = rtl_read_dword(rtlpriv,
 216                                         rtlpriv->cfg->maps[EFUSE_CTRL]);
 217                retry++;
 218        }
 219
 220        udelay(50);
 221        value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
 222
 223        *pbuf = (u8) (value32 & 0xff);
 224}
 225EXPORT_SYMBOL_GPL(read_efuse_byte);
 226
 227void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
 228{
 229        struct rtl_priv *rtlpriv = rtl_priv(hw);
 230        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 231        u8 *efuse_tbl;
 232        u8 rtemp8[1];
 233        u16 efuse_addr = 0;
 234        u8 offset, wren;
 235        u8 u1temp = 0;
 236        u16 i;
 237        u16 j;
 238        const u16 efuse_max_section =
 239                rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP];
 240        const u32 efuse_len =
 241                rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE];
 242        u16 **efuse_word;
 243        u16 efuse_utilized = 0;
 244        u8 efuse_usage;
 245
 246        if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) {
 247                RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
 248                         "read_efuse(): Invalid offset(%#x) with read bytes(%#x)!!\n",
 249                         _offset, _size_byte);
 250                return;
 251        }
 252
 253        /* allocate memory for efuse_tbl and efuse_word */
 254        efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE] *
 255                            sizeof(u8), GFP_ATOMIC);
 256        if (!efuse_tbl)
 257                return;
 258        efuse_word = kzalloc(EFUSE_MAX_WORD_UNIT * sizeof(u16 *), GFP_ATOMIC);
 259        if (!efuse_word)
 260                goto out;
 261        for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
 262                efuse_word[i] = kzalloc(efuse_max_section * sizeof(u16),
 263                                        GFP_ATOMIC);
 264                if (!efuse_word[i])
 265                        goto done;
 266        }
 267
 268        for (i = 0; i < efuse_max_section; i++)
 269                for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
 270                        efuse_word[j][i] = 0xFFFF;
 271
 272        read_efuse_byte(hw, efuse_addr, rtemp8);
 273        if (*rtemp8 != 0xFF) {
 274                efuse_utilized++;
 275                RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL,
 276                        "Addr=%d\n", efuse_addr);
 277                efuse_addr++;
 278        }
 279
 280        while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) {
 281                /*  Check PG header for section num.  */
 282                if ((*rtemp8 & 0x1F) == 0x0F) {/* extended header */
 283                        u1temp = ((*rtemp8 & 0xE0) >> 5);
 284                        read_efuse_byte(hw, efuse_addr, rtemp8);
 285
 286                        if ((*rtemp8 & 0x0F) == 0x0F) {
 287                                efuse_addr++;
 288                                read_efuse_byte(hw, efuse_addr, rtemp8);
 289
 290                                if (*rtemp8 != 0xFF &&
 291                                    (efuse_addr < efuse_len)) {
 292                                        efuse_addr++;
 293                                }
 294                                continue;
 295                        } else {
 296                                offset = ((*rtemp8 & 0xF0) >> 1) | u1temp;
 297                                wren = (*rtemp8 & 0x0F);
 298                                efuse_addr++;
 299                        }
 300                } else {
 301                        offset = ((*rtemp8 >> 4) & 0x0f);
 302                        wren = (*rtemp8 & 0x0f);
 303                }
 304
 305                if (offset < efuse_max_section) {
 306                        RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL,
 307                                "offset-%d Worden=%x\n", offset, wren);
 308
 309                        for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
 310                                if (!(wren & 0x01)) {
 311                                        RTPRINT(rtlpriv, FEEPROM,
 312                                                EFUSE_READ_ALL,
 313                                                "Addr=%d\n", efuse_addr);
 314
 315                                        read_efuse_byte(hw, efuse_addr, rtemp8);
 316                                        efuse_addr++;
 317                                        efuse_utilized++;
 318                                        efuse_word[i][offset] =
 319                                                         (*rtemp8 & 0xff);
 320
 321                                        if (efuse_addr >= efuse_len)
 322                                                break;
 323
 324                                        RTPRINT(rtlpriv, FEEPROM,
 325                                                EFUSE_READ_ALL,
 326                                                "Addr=%d\n", efuse_addr);
 327
 328                                        read_efuse_byte(hw, efuse_addr, rtemp8);
 329                                        efuse_addr++;
 330                                        efuse_utilized++;
 331                                        efuse_word[i][offset] |=
 332                                            (((u16)*rtemp8 << 8) & 0xff00);
 333
 334                                        if (efuse_addr >= efuse_len)
 335                                                break;
 336                                }
 337
 338                                wren >>= 1;
 339                        }
 340                }
 341
 342                RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL,
 343                        "Addr=%d\n", efuse_addr);
 344                read_efuse_byte(hw, efuse_addr, rtemp8);
 345                if (*rtemp8 != 0xFF && (efuse_addr < efuse_len)) {
 346                        efuse_utilized++;
 347                        efuse_addr++;
 348                }
 349        }
 350
 351        for (i = 0; i < efuse_max_section; i++) {
 352                for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
 353                        efuse_tbl[(i * 8) + (j * 2)] =
 354                            (efuse_word[j][i] & 0xff);
 355                        efuse_tbl[(i * 8) + ((j * 2) + 1)] =
 356                            ((efuse_word[j][i] >> 8) & 0xff);
 357                }
 358        }
 359
 360        for (i = 0; i < _size_byte; i++)
 361                pbuf[i] = efuse_tbl[_offset + i];
 362
 363        rtlefuse->efuse_usedbytes = efuse_utilized;
 364        efuse_usage = (u8) ((efuse_utilized * 100) / efuse_len);
 365        rtlefuse->efuse_usedpercentage = efuse_usage;
 366        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES,
 367                                      (u8 *)&efuse_utilized);
 368        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_USAGE,
 369                                      &efuse_usage);
 370done:
 371        for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++)
 372                kfree(efuse_word[i]);
 373        kfree(efuse_word);
 374out:
 375        kfree(efuse_tbl);
 376}
 377
 378bool efuse_shadow_update_chk(struct ieee80211_hw *hw)
 379{
 380        struct rtl_priv *rtlpriv = rtl_priv(hw);
 381        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 382        u8 section_idx, i, Base;
 383        u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used;
 384        bool wordchanged, result = true;
 385
 386        for (section_idx = 0; section_idx < 16; section_idx++) {
 387                Base = section_idx * 8;
 388                wordchanged = false;
 389
 390                for (i = 0; i < 8; i = i + 2) {
 391                        if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i] !=
 392                             rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i]) ||
 393                            (rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i + 1] !=
 394                             rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i +
 395                                                                   1])) {
 396                                words_need++;
 397                                wordchanged = true;
 398                        }
 399                }
 400
 401                if (wordchanged)
 402                        hdr_num++;
 403        }
 404
 405        totalbytes = hdr_num + words_need * 2;
 406        efuse_used = rtlefuse->efuse_usedbytes;
 407
 408        if ((totalbytes + efuse_used) >=
 409            (EFUSE_MAX_SIZE - rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))
 410                result = false;
 411
 412        RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
 413                 "efuse_shadow_update_chk(): totalbytes(%#x), hdr_num(%#x), words_need(%#x), efuse_used(%d)\n",
 414                 totalbytes, hdr_num, words_need, efuse_used);
 415
 416        return result;
 417}
 418
 419void efuse_shadow_read(struct ieee80211_hw *hw, u8 type,
 420                       u16 offset, u32 *value)
 421{
 422        if (type == 1)
 423                efuse_shadow_read_1byte(hw, offset, (u8 *)value);
 424        else if (type == 2)
 425                efuse_shadow_read_2byte(hw, offset, (u16 *)value);
 426        else if (type == 4)
 427                efuse_shadow_read_4byte(hw, offset, value);
 428
 429}
 430EXPORT_SYMBOL(efuse_shadow_read);
 431
 432void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, u16 offset,
 433                                u32 value)
 434{
 435        if (type == 1)
 436                efuse_shadow_write_1byte(hw, offset, (u8) value);
 437        else if (type == 2)
 438                efuse_shadow_write_2byte(hw, offset, (u16) value);
 439        else if (type == 4)
 440                efuse_shadow_write_4byte(hw, offset, value);
 441
 442}
 443
 444bool efuse_shadow_update(struct ieee80211_hw *hw)
 445{
 446        struct rtl_priv *rtlpriv = rtl_priv(hw);
 447        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 448        u16 i, offset, base;
 449        u8 word_en = 0x0F;
 450        u8 first_pg = false;
 451
 452        RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n");
 453
 454        if (!efuse_shadow_update_chk(hw)) {
 455                efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
 456                memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
 457                       &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
 458                       rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 459
 460                RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
 461                         "efuse out of capacity!!\n");
 462                return false;
 463        }
 464        efuse_power_switch(hw, true, true);
 465
 466        for (offset = 0; offset < 16; offset++) {
 467
 468                word_en = 0x0F;
 469                base = offset * 8;
 470
 471                for (i = 0; i < 8; i++) {
 472                        if (first_pg) {
 473                                word_en &= ~(BIT(i / 2));
 474
 475                                rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] =
 476                                    rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i];
 477                        } else {
 478
 479                                if (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] !=
 480                                    rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]) {
 481                                        word_en &= ~(BIT(i / 2));
 482
 483                                        rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] =
 484                                            rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i];
 485                                }
 486                        }
 487                }
 488
 489                if (word_en != 0x0F) {
 490                        u8 tmpdata[8];
 491                        memcpy(tmpdata,
 492                               &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base],
 493                               8);
 494                        RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD,
 495                                      "U-efuse\n", tmpdata, 8);
 496
 497                        if (!efuse_pg_packet_write(hw, (u8) offset, word_en,
 498                                                   tmpdata)) {
 499                                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 500                                         "PG section(%#x) fail!!\n", offset);
 501                                break;
 502                        }
 503                }
 504
 505        }
 506
 507        efuse_power_switch(hw, true, false);
 508        efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
 509
 510        memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
 511               &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
 512               rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 513
 514        RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n");
 515        return true;
 516}
 517
 518void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
 519{
 520        struct rtl_priv *rtlpriv = rtl_priv(hw);
 521        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 522
 523        if (rtlefuse->autoload_failflag)
 524                memset((&rtlefuse->efuse_map[EFUSE_INIT_MAP][0]),
 525                       0xFF, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 526        else
 527                efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
 528
 529        memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
 530                        &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
 531                        rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 532
 533}
 534EXPORT_SYMBOL(rtl_efuse_shadow_map_update);
 535
 536void efuse_force_write_vendor_Id(struct ieee80211_hw *hw)
 537{
 538        u8 tmpdata[8] = { 0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF };
 539
 540        efuse_power_switch(hw, true, true);
 541
 542        efuse_pg_packet_write(hw, 1, 0xD, tmpdata);
 543
 544        efuse_power_switch(hw, true, false);
 545
 546}
 547
 548void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx)
 549{
 550}
 551
 552static void efuse_shadow_read_1byte(struct ieee80211_hw *hw,
 553                                    u16 offset, u8 *value)
 554{
 555        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 556        *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset];
 557}
 558
 559static void efuse_shadow_read_2byte(struct ieee80211_hw *hw,
 560                                    u16 offset, u16 *value)
 561{
 562        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 563
 564        *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset];
 565        *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8;
 566
 567}
 568
 569static void efuse_shadow_read_4byte(struct ieee80211_hw *hw,
 570                                    u16 offset, u32 *value)
 571{
 572        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 573
 574        *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset];
 575        *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8;
 576        *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] << 16;
 577        *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] << 24;
 578}
 579
 580static void efuse_shadow_write_1byte(struct ieee80211_hw *hw,
 581                                     u16 offset, u8 value)
 582{
 583        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 584
 585        rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value;
 586}
 587
 588static void efuse_shadow_write_2byte(struct ieee80211_hw *hw,
 589                                     u16 offset, u16 value)
 590{
 591        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 592
 593        rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value & 0x00FF;
 594        rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] = value >> 8;
 595
 596}
 597
 598static void efuse_shadow_write_4byte(struct ieee80211_hw *hw,
 599                                     u16 offset, u32 value)
 600{
 601        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 602
 603        rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] =
 604            (u8) (value & 0x000000FF);
 605        rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] =
 606            (u8) ((value >> 8) & 0x0000FF);
 607        rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] =
 608            (u8) ((value >> 16) & 0x00FF);
 609        rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] =
 610            (u8) ((value >> 24) & 0xFF);
 611
 612}
 613
 614int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data)
 615{
 616        struct rtl_priv *rtlpriv = rtl_priv(hw);
 617        u8 tmpidx = 0;
 618        int result;
 619
 620        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
 621                       (u8) (addr & 0xff));
 622        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2,
 623                       ((u8) ((addr >> 8) & 0x03)) |
 624                       (rtl_read_byte(rtlpriv,
 625                                      rtlpriv->cfg->maps[EFUSE_CTRL] + 2) &
 626                        0xFC));
 627
 628        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72);
 629
 630        while (!(0x80 & rtl_read_byte(rtlpriv,
 631                                      rtlpriv->cfg->maps[EFUSE_CTRL] + 3))
 632               && (tmpidx < 100)) {
 633                tmpidx++;
 634        }
 635
 636        if (tmpidx < 100) {
 637                *data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
 638                result = true;
 639        } else {
 640                *data = 0xff;
 641                result = false;
 642        }
 643        return result;
 644}
 645EXPORT_SYMBOL(efuse_one_byte_read);
 646
 647static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data)
 648{
 649        struct rtl_priv *rtlpriv = rtl_priv(hw);
 650        u8 tmpidx = 0;
 651
 652        RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
 653                 "Addr = %x Data=%x\n", addr, data);
 654
 655        rtl_write_byte(rtlpriv,
 656                       rtlpriv->cfg->maps[EFUSE_CTRL] + 1, (u8) (addr & 0xff));
 657        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2,
 658                       (rtl_read_byte(rtlpriv,
 659                         rtlpriv->cfg->maps[EFUSE_CTRL] +
 660                         2) & 0xFC) | (u8) ((addr >> 8) & 0x03));
 661
 662        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], data);
 663        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0xF2);
 664
 665        while ((0x80 & rtl_read_byte(rtlpriv,
 666                                     rtlpriv->cfg->maps[EFUSE_CTRL] + 3))
 667               && (tmpidx < 100)) {
 668                tmpidx++;
 669        }
 670
 671        if (tmpidx < 100)
 672                return true;
 673        return false;
 674}
 675
 676static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse)
 677{
 678        struct rtl_priv *rtlpriv = rtl_priv(hw);
 679        efuse_power_switch(hw, false, true);
 680        read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse);
 681        efuse_power_switch(hw, false, false);
 682}
 683
 684static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,
 685                                u8 efuse_data, u8 offset, u8 *tmpdata,
 686                                u8 *readstate)
 687{
 688        bool dataempty = true;
 689        u8 hoffset;
 690        u8 tmpidx;
 691        u8 hworden;
 692        u8 word_cnts;
 693
 694        hoffset = (efuse_data >> 4) & 0x0F;
 695        hworden = efuse_data & 0x0F;
 696        word_cnts = efuse_calculate_word_cnts(hworden);
 697
 698        if (hoffset == offset) {
 699                for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) {
 700                        if (efuse_one_byte_read(hw, *efuse_addr + 1 + tmpidx,
 701                                                &efuse_data)) {
 702                                tmpdata[tmpidx] = efuse_data;
 703                                if (efuse_data != 0xff)
 704                                        dataempty = false;
 705                        }
 706                }
 707
 708                if (!dataempty) {
 709                        *readstate = PG_STATE_DATA;
 710                } else {
 711                        *efuse_addr = *efuse_addr + (word_cnts * 2) + 1;
 712                        *readstate = PG_STATE_HEADER;
 713                }
 714
 715        } else {
 716                *efuse_addr = *efuse_addr + (word_cnts * 2) + 1;
 717                *readstate = PG_STATE_HEADER;
 718        }
 719}
 720
 721static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data)
 722{
 723        u8 readstate = PG_STATE_HEADER;
 724
 725        bool continual = true;
 726
 727        u8 efuse_data, word_cnts = 0;
 728        u16 efuse_addr = 0;
 729        u8 tmpdata[8];
 730
 731        if (data == NULL)
 732                return false;
 733        if (offset > 15)
 734                return false;
 735
 736        memset(data, 0xff, PGPKT_DATA_SIZE * sizeof(u8));
 737        memset(tmpdata, 0xff, PGPKT_DATA_SIZE * sizeof(u8));
 738
 739        while (continual && (efuse_addr < EFUSE_MAX_SIZE)) {
 740                if (readstate & PG_STATE_HEADER) {
 741                        if (efuse_one_byte_read(hw, efuse_addr, &efuse_data)
 742                            && (efuse_data != 0xFF))
 743                                efuse_read_data_case1(hw, &efuse_addr,
 744                                                      efuse_data, offset,
 745                                                      tmpdata, &readstate);
 746                        else
 747                                continual = false;
 748                } else if (readstate & PG_STATE_DATA) {
 749                        efuse_word_enable_data_read(0, tmpdata, data);
 750                        efuse_addr = efuse_addr + (word_cnts * 2) + 1;
 751                        readstate = PG_STATE_HEADER;
 752                }
 753
 754        }
 755
 756        if ((data[0] == 0xff) && (data[1] == 0xff) &&
 757            (data[2] == 0xff) && (data[3] == 0xff) &&
 758            (data[4] == 0xff) && (data[5] == 0xff) &&
 759            (data[6] == 0xff) && (data[7] == 0xff))
 760                return false;
 761        else
 762                return true;
 763
 764}
 765
 766static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,
 767                                   u8 efuse_data, u8 offset,
 768                                   int *continual, u8 *write_state,
 769                                   struct pgpkt_struct *target_pkt,
 770                                   int *repeat_times, int *result, u8 word_en)
 771{
 772        struct rtl_priv *rtlpriv = rtl_priv(hw);
 773        struct pgpkt_struct tmp_pkt;
 774        int dataempty = true;
 775        u8 originaldata[8 * sizeof(u8)];
 776        u8 badworden = 0x0F;
 777        u8 match_word_en, tmp_word_en;
 778        u8 tmpindex;
 779        u8 tmp_header = efuse_data;
 780        u8 tmp_word_cnts;
 781
 782        tmp_pkt.offset = (tmp_header >> 4) & 0x0F;
 783        tmp_pkt.word_en = tmp_header & 0x0F;
 784        tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en);
 785
 786        if (tmp_pkt.offset != target_pkt->offset) {
 787                *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1;
 788                *write_state = PG_STATE_HEADER;
 789        } else {
 790                for (tmpindex = 0; tmpindex < (tmp_word_cnts * 2); tmpindex++) {
 791                        if (efuse_one_byte_read(hw,
 792                                                (*efuse_addr + 1 + tmpindex),
 793                                                &efuse_data) &&
 794                            (efuse_data != 0xFF))
 795                                dataempty = false;
 796                }
 797
 798                if (!dataempty) {
 799                        *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1;
 800                        *write_state = PG_STATE_HEADER;
 801                } else {
 802                        match_word_en = 0x0F;
 803                        if (!((target_pkt->word_en & BIT(0)) |
 804                            (tmp_pkt.word_en & BIT(0))))
 805                                match_word_en &= (~BIT(0));
 806
 807                        if (!((target_pkt->word_en & BIT(1)) |
 808                            (tmp_pkt.word_en & BIT(1))))
 809                                match_word_en &= (~BIT(1));
 810
 811                        if (!((target_pkt->word_en & BIT(2)) |
 812                            (tmp_pkt.word_en & BIT(2))))
 813                                match_word_en &= (~BIT(2));
 814
 815                        if (!((target_pkt->word_en & BIT(3)) |
 816                            (tmp_pkt.word_en & BIT(3))))
 817                                match_word_en &= (~BIT(3));
 818
 819                        if ((match_word_en & 0x0F) != 0x0F) {
 820                                badworden =
 821                                  enable_efuse_data_write(hw,
 822                                                          *efuse_addr + 1,
 823                                                          tmp_pkt.word_en,
 824                                                          target_pkt->data);
 825
 826                                if (0x0F != (badworden & 0x0F)) {
 827                                        u8 reorg_offset = offset;
 828                                        u8 reorg_worden = badworden;
 829                                        efuse_pg_packet_write(hw, reorg_offset,
 830                                                              reorg_worden,
 831                                                              originaldata);
 832                                }
 833
 834                                tmp_word_en = 0x0F;
 835                                if ((target_pkt->word_en & BIT(0)) ^
 836                                    (match_word_en & BIT(0)))
 837                                        tmp_word_en &= (~BIT(0));
 838
 839                                if ((target_pkt->word_en & BIT(1)) ^
 840                                    (match_word_en & BIT(1)))
 841                                        tmp_word_en &= (~BIT(1));
 842
 843                                if ((target_pkt->word_en & BIT(2)) ^
 844                                    (match_word_en & BIT(2)))
 845                                        tmp_word_en &= (~BIT(2));
 846
 847                                if ((target_pkt->word_en & BIT(3)) ^
 848                                    (match_word_en & BIT(3)))
 849                                        tmp_word_en &= (~BIT(3));
 850
 851                                if ((tmp_word_en & 0x0F) != 0x0F) {
 852                                        *efuse_addr = efuse_get_current_size(hw);
 853                                        target_pkt->offset = offset;
 854                                        target_pkt->word_en = tmp_word_en;
 855                                } else {
 856                                        *continual = false;
 857                                }
 858                                *write_state = PG_STATE_HEADER;
 859                                *repeat_times += 1;
 860                                if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) {
 861                                        *continual = false;
 862                                        *result = false;
 863                                }
 864                        } else {
 865                                *efuse_addr += (2 * tmp_word_cnts) + 1;
 866                                target_pkt->offset = offset;
 867                                target_pkt->word_en = word_en;
 868                                *write_state = PG_STATE_HEADER;
 869                        }
 870                }
 871        }
 872        RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse PG_STATE_HEADER-1\n");
 873}
 874
 875static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr,
 876                                   int *continual, u8 *write_state,
 877                                   struct pgpkt_struct target_pkt,
 878                                   int *repeat_times, int *result)
 879{
 880        struct rtl_priv *rtlpriv = rtl_priv(hw);
 881        struct pgpkt_struct tmp_pkt;
 882        u8 pg_header;
 883        u8 tmp_header;
 884        u8 originaldata[8 * sizeof(u8)];
 885        u8 tmp_word_cnts;
 886        u8 badworden = 0x0F;
 887
 888        pg_header = ((target_pkt.offset << 4) & 0xf0) | target_pkt.word_en;
 889        efuse_one_byte_write(hw, *efuse_addr, pg_header);
 890        efuse_one_byte_read(hw, *efuse_addr, &tmp_header);
 891
 892        if (tmp_header == pg_header) {
 893                *write_state = PG_STATE_DATA;
 894        } else if (tmp_header == 0xFF) {
 895                *write_state = PG_STATE_HEADER;
 896                *repeat_times += 1;
 897                if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) {
 898                        *continual = false;
 899                        *result = false;
 900                }
 901        } else {
 902                tmp_pkt.offset = (tmp_header >> 4) & 0x0F;
 903                tmp_pkt.word_en = tmp_header & 0x0F;
 904
 905                tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en);
 906
 907                memset(originaldata, 0xff,  8 * sizeof(u8));
 908
 909                if (efuse_pg_packet_read(hw, tmp_pkt.offset, originaldata)) {
 910                        badworden = enable_efuse_data_write(hw,
 911                                                            *efuse_addr + 1,
 912                                                            tmp_pkt.word_en,
 913                                                            originaldata);
 914
 915                        if (0x0F != (badworden & 0x0F)) {
 916                                u8 reorg_offset = tmp_pkt.offset;
 917                                u8 reorg_worden = badworden;
 918                                efuse_pg_packet_write(hw, reorg_offset,
 919                                                      reorg_worden,
 920                                                      originaldata);
 921                                *efuse_addr = efuse_get_current_size(hw);
 922                        } else {
 923                                *efuse_addr = *efuse_addr +
 924                                              (tmp_word_cnts * 2) + 1;
 925                        }
 926                } else {
 927                        *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1;
 928                }
 929
 930                *write_state = PG_STATE_HEADER;
 931                *repeat_times += 1;
 932                if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) {
 933                        *continual = false;
 934                        *result = false;
 935                }
 936
 937                RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
 938                        "efuse PG_STATE_HEADER-2\n");
 939        }
 940}
 941
 942static int efuse_pg_packet_write(struct ieee80211_hw *hw,
 943                                 u8 offset, u8 word_en, u8 *data)
 944{
 945        struct rtl_priv *rtlpriv = rtl_priv(hw);
 946        struct pgpkt_struct target_pkt;
 947        u8 write_state = PG_STATE_HEADER;
 948        int continual = true, dataempty = true, result = true;
 949        u16 efuse_addr = 0;
 950        u8 efuse_data;
 951        u8 target_word_cnts = 0;
 952        u8 badworden = 0x0F;
 953        static int repeat_times;
 954
 955        if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE -
 956                rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) {
 957                RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
 958                        "efuse_pg_packet_write error\n");
 959                return false;
 960        }
 961
 962        target_pkt.offset = offset;
 963        target_pkt.word_en = word_en;
 964
 965        memset(target_pkt.data, 0xFF,  8 * sizeof(u8));
 966
 967        efuse_word_enable_data_read(word_en, data, target_pkt.data);
 968        target_word_cnts = efuse_calculate_word_cnts(target_pkt.word_en);
 969
 970        RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n");
 971
 972        while (continual && (efuse_addr < (EFUSE_MAX_SIZE -
 973                rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) {
 974
 975                if (write_state == PG_STATE_HEADER) {
 976                        dataempty = true;
 977                        badworden = 0x0F;
 978                        RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
 979                                "efuse PG_STATE_HEADER\n");
 980
 981                        if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) &&
 982                            (efuse_data != 0xFF))
 983                                efuse_write_data_case1(hw, &efuse_addr,
 984                                                       efuse_data, offset,
 985                                                       &continual,
 986                                                       &write_state,
 987                                                       &target_pkt,
 988                                                       &repeat_times, &result,
 989                                                       word_en);
 990                        else
 991                                efuse_write_data_case2(hw, &efuse_addr,
 992                                                       &continual,
 993                                                       &write_state,
 994                                                       target_pkt,
 995                                                       &repeat_times,
 996                                                       &result);
 997
 998                } else if (write_state == PG_STATE_DATA) {
 999                        RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
1000                                "efuse PG_STATE_DATA\n");
1001                        badworden = 0x0f;
1002                        badworden =
1003                            enable_efuse_data_write(hw, efuse_addr + 1,
1004                                                    target_pkt.word_en,
1005                                                    target_pkt.data);
1006
1007                        if ((badworden & 0x0F) == 0x0F) {
1008                                continual = false;
1009                        } else {
1010                                efuse_addr =
1011                                    efuse_addr + (2 * target_word_cnts) + 1;
1012
1013                                target_pkt.offset = offset;
1014                                target_pkt.word_en = badworden;
1015                                target_word_cnts =
1016                                    efuse_calculate_word_cnts(target_pkt.
1017                                                              word_en);
1018                                write_state = PG_STATE_HEADER;
1019                                repeat_times++;
1020                                if (repeat_times > EFUSE_REPEAT_THRESHOLD_) {
1021                                        continual = false;
1022                                        result = false;
1023                                }
1024                                RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,
1025                                        "efuse PG_STATE_HEADER-3\n");
1026                        }
1027                }
1028        }
1029
1030        if (efuse_addr >= (EFUSE_MAX_SIZE -
1031                rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) {
1032                RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
1033                         "efuse_addr(%#x) Out of size!!\n", efuse_addr);
1034        }
1035
1036        return true;
1037}
1038
1039static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata,
1040                                        u8 *targetdata)
1041{
1042        if (!(word_en & BIT(0))) {
1043                targetdata[0] = sourdata[0];
1044                targetdata[1] = sourdata[1];
1045        }
1046
1047        if (!(word_en & BIT(1))) {
1048                targetdata[2] = sourdata[2];
1049                targetdata[3] = sourdata[3];
1050        }
1051
1052        if (!(word_en & BIT(2))) {
1053                targetdata[4] = sourdata[4];
1054                targetdata[5] = sourdata[5];
1055        }
1056
1057        if (!(word_en & BIT(3))) {
1058                targetdata[6] = sourdata[6];
1059                targetdata[7] = sourdata[7];
1060        }
1061}
1062
1063static u8 enable_efuse_data_write(struct ieee80211_hw *hw,
1064                                  u16 efuse_addr, u8 word_en, u8 *data)
1065{
1066        struct rtl_priv *rtlpriv = rtl_priv(hw);
1067        u16 tmpaddr;
1068        u16 start_addr = efuse_addr;
1069        u8 badworden = 0x0F;
1070        u8 tmpdata[8];
1071
1072        memset(tmpdata, 0xff, PGPKT_DATA_SIZE);
1073        RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
1074                 "word_en = %x efuse_addr=%x\n", word_en, efuse_addr);
1075
1076        if (!(word_en & BIT(0))) {
1077                tmpaddr = start_addr;
1078                efuse_one_byte_write(hw, start_addr++, data[0]);
1079                efuse_one_byte_write(hw, start_addr++, data[1]);
1080
1081                efuse_one_byte_read(hw, tmpaddr, &tmpdata[0]);
1082                efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[1]);
1083                if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
1084                        badworden &= (~BIT(0));
1085        }
1086
1087        if (!(word_en & BIT(1))) {
1088                tmpaddr = start_addr;
1089                efuse_one_byte_write(hw, start_addr++, data[2]);
1090                efuse_one_byte_write(hw, start_addr++, data[3]);
1091
1092                efuse_one_byte_read(hw, tmpaddr, &tmpdata[2]);
1093                efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[3]);
1094                if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
1095                        badworden &= (~BIT(1));
1096        }
1097
1098        if (!(word_en & BIT(2))) {
1099                tmpaddr = start_addr;
1100                efuse_one_byte_write(hw, start_addr++, data[4]);
1101                efuse_one_byte_write(hw, start_addr++, data[5]);
1102
1103                efuse_one_byte_read(hw, tmpaddr, &tmpdata[4]);
1104                efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[5]);
1105                if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
1106                        badworden &= (~BIT(2));
1107        }
1108
1109        if (!(word_en & BIT(3))) {
1110                tmpaddr = start_addr;
1111                efuse_one_byte_write(hw, start_addr++, data[6]);
1112                efuse_one_byte_write(hw, start_addr++, data[7]);
1113
1114                efuse_one_byte_read(hw, tmpaddr, &tmpdata[6]);
1115                efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[7]);
1116                if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
1117                        badworden &= (~BIT(3));
1118        }
1119
1120        return badworden;
1121}
1122
1123static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate)
1124{
1125        struct rtl_priv *rtlpriv = rtl_priv(hw);
1126        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1127        u8 tempval;
1128        u16 tmpV16;
1129
1130        if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) {
1131
1132                if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE &&
1133                    rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) {
1134                        rtl_write_byte(rtlpriv,
1135                                       rtlpriv->cfg->maps[EFUSE_ACCESS], 0x69);
1136                } else {
1137                        tmpV16 =
1138                          rtl_read_word(rtlpriv,
1139                                        rtlpriv->cfg->maps[SYS_ISO_CTRL]);
1140                        if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) {
1141                                tmpV16 |= rtlpriv->cfg->maps[EFUSE_PWC_EV12V];
1142                                rtl_write_word(rtlpriv,
1143                                               rtlpriv->cfg->maps[SYS_ISO_CTRL],
1144                                               tmpV16);
1145                        }
1146                }
1147                tmpV16 = rtl_read_word(rtlpriv,
1148                                       rtlpriv->cfg->maps[SYS_FUNC_EN]);
1149                if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_FEN_ELDR])) {
1150                        tmpV16 |= rtlpriv->cfg->maps[EFUSE_FEN_ELDR];
1151                        rtl_write_word(rtlpriv,
1152                                       rtlpriv->cfg->maps[SYS_FUNC_EN], tmpV16);
1153                }
1154
1155                tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_CLK]);
1156                if ((!(tmpV16 & rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN])) ||
1157                    (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_ANA8M]))) {
1158                        tmpV16 |= (rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN] |
1159                                   rtlpriv->cfg->maps[EFUSE_ANA8M]);
1160                        rtl_write_word(rtlpriv,
1161                                       rtlpriv->cfg->maps[SYS_CLK], tmpV16);
1162                }
1163        }
1164
1165        if (pwrstate) {
1166                if (write) {
1167                        tempval = rtl_read_byte(rtlpriv,
1168                                                rtlpriv->cfg->maps[EFUSE_TEST] +
1169                                                3);
1170
1171                        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
1172                                tempval &= ~(BIT(3) | BIT(4) | BIT(5) | BIT(6));
1173                                tempval |= (VOLTAGE_V25 << 3);
1174                        } else if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) {
1175                                tempval &= 0x0F;
1176                                tempval |= (VOLTAGE_V25 << 4);
1177                        }
1178
1179                        rtl_write_byte(rtlpriv,
1180                                       rtlpriv->cfg->maps[EFUSE_TEST] + 3,
1181                                       (tempval | 0x80));
1182                }
1183
1184                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) {
1185                        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK],
1186                                       0x03);
1187                }
1188        } else {
1189                if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE &&
1190                    rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE)
1191                        rtl_write_byte(rtlpriv,
1192                                       rtlpriv->cfg->maps[EFUSE_ACCESS], 0);
1193
1194                if (write) {
1195                        tempval = rtl_read_byte(rtlpriv,
1196                                                rtlpriv->cfg->maps[EFUSE_TEST] +
1197                                                3);
1198                        rtl_write_byte(rtlpriv,
1199                                       rtlpriv->cfg->maps[EFUSE_TEST] + 3,
1200                                       (tempval & 0x7F));
1201                }
1202
1203                if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) {
1204                        rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK],
1205                                       0x02);
1206                }
1207        }
1208}
1209
1210static u16 efuse_get_current_size(struct ieee80211_hw *hw)
1211{
1212        int continual = true;
1213        u16 efuse_addr = 0;
1214        u8 hoffset, hworden;
1215        u8 efuse_data, word_cnts;
1216
1217        while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) &&
1218               (efuse_addr < EFUSE_MAX_SIZE)) {
1219                if (efuse_data != 0xFF) {
1220                        hoffset = (efuse_data >> 4) & 0x0F;
1221                        hworden = efuse_data & 0x0F;
1222                        word_cnts = efuse_calculate_word_cnts(hworden);
1223                        efuse_addr = efuse_addr + (word_cnts * 2) + 1;
1224                } else {
1225                        continual = false;
1226                }
1227        }
1228
1229        return efuse_addr;
1230}
1231
1232static u8 efuse_calculate_word_cnts(u8 word_en)
1233{
1234        u8 word_cnts = 0;
1235        if (!(word_en & BIT(0)))
1236                word_cnts++;
1237        if (!(word_en & BIT(1)))
1238                word_cnts++;
1239        if (!(word_en & BIT(2)))
1240                word_cnts++;
1241        if (!(word_en & BIT(3)))
1242                word_cnts++;
1243        return word_cnts;
1244}
1245
1246