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