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