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