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