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