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