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