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