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