GNU Linux-libre 4.19.207-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         }
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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  *---------------------------------------------------------------------------*/
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
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*/