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