GNU Linux-libre 5.10.215-gnu1
[releases.git] / drivers / staging / rtl8723bs / core / rtw_efuse.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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  *---------------------------------------------------------------------------*/
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
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*/