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