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