GNU Linux-libre 6.8.7-gnu
[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 #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
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
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
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
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
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
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
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
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
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. */
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
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
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
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
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);
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  *---------------------------------------------------------------------------*/
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 */
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 */
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  *---------------------------------------------------------------------------*/
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  *---------------------------------------------------------------------------*/
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*/