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