OSDN Git Service

7f58b34eda4fc91f47d754d2260742d8ec51206e
[android-x86/kernel.git] / drivers / staging / rtl8723bs / core / rtw_efuse.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 #define _RTW_EFUSE_C_
16
17 #include <drv_types.h>
18 #include <rtw_debug.h>
19 #include <hal_data.h>
20 #include <linux/jiffies.h>
21
22
23 /*------------------------Define local variable------------------------------*/
24 u8 fakeEfuseBank = 0;
25 u32 fakeEfuseUsedBytes = 0;
26 u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE]={0};
27 u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN]={0};
28 u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN]={0};
29
30 u32 BTEfuseUsedBytes = 0;
31 u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
32 u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN]={0};
33 u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN]={0};
34
35 u32 fakeBTEfuseUsedBytes = 0;
36 u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
37 u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN]={0};
38 u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN]={0};
39 /*------------------------Define local variable------------------------------*/
40
41 /*  */
42 #define REG_EFUSE_CTRL          0x0030
43 #define EFUSE_CTRL                      REG_EFUSE_CTRL          /*  E-Fuse Control. */
44 /*  */
45
46 bool
47 Efuse_Read1ByteFromFakeContent(
48         struct adapter *padapter,
49         u16     Offset,
50         u8 *Value       );
51 bool
52 Efuse_Read1ByteFromFakeContent(
53         struct adapter *padapter,
54         u16     Offset,
55         u8 *Value       )
56 {
57         if (Offset >= EFUSE_MAX_HW_SIZE)
58         {
59                 return false;
60         }
61         /* DbgPrint("Read fake content, offset = %d\n", Offset); */
62         if (fakeEfuseBank == 0)
63                 *Value = fakeEfuseContent[Offset];
64         else
65                 *Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
66         return true;
67 }
68
69 bool
70 Efuse_Write1ByteToFakeContent(
71         struct adapter *padapter,
72         u16     Offset,
73         u8 Value        );
74 bool
75 Efuse_Write1ByteToFakeContent(
76         struct adapter *padapter,
77         u16     Offset,
78         u8 Value        )
79 {
80         if (Offset >= EFUSE_MAX_HW_SIZE)
81         {
82                 return false;
83         }
84         if (fakeEfuseBank == 0)
85                 fakeEfuseContent[Offset] = Value;
86         else
87         {
88                 fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
89         }
90         return true;
91 }
92
93 /*-----------------------------------------------------------------------------
94  * Function:    Efuse_PowerSwitch
95  *
96  * Overview:    When we want to enable write operation, we should change to
97  *                      pwr on state. When we stop write, we should switch to 500k mode
98  *                      and disable LDO 2.5V.
99  *
100  * Input:       NONE
101  *
102  * Output:      NONE
103  *
104  * Return:      NONE
105  *
106  * Revised History:
107  * When                 Who             Remark
108  * 11/17/2008   MHC             Create Version 0.
109  *
110  *---------------------------------------------------------------------------*/
111 void
112 Efuse_PowerSwitch(
113 struct adapter *padapter,
114 u8 bWrite,
115 u8 PwrState)
116 {
117         padapter->HalFunc.EfusePowerSwitch(padapter, bWrite, PwrState);
118 }
119
120 /*-----------------------------------------------------------------------------
121  * Function:    Efuse_GetCurrentSize
122  *
123  * Overview:    Get current efuse size!!!
124  *
125  * Input:       NONE
126  *
127  * Output:      NONE
128  *
129  * Return:      NONE
130  *
131  * Revised History:
132  * When                 Who             Remark
133  * 11/16/2008   MHC             Create Version 0.
134  *
135  *---------------------------------------------------------------------------*/
136 u16
137 Efuse_GetCurrentSize(
138         struct adapter *        padapter,
139         u8      efuseType,
140         bool            bPseudoTest)
141 {
142         u16 ret = 0;
143
144         ret = padapter->HalFunc.EfuseGetCurrentSize(padapter, efuseType, bPseudoTest);
145
146         return ret;
147 }
148
149 /*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
150 u8
151 Efuse_CalculateWordCnts(u8 word_en)
152 {
153         u8 word_cnts = 0;
154         if (!(word_en & BIT(0)))        word_cnts++; /*  0 : write enable */
155         if (!(word_en & BIT(1)))        word_cnts++;
156         if (!(word_en & BIT(2)))        word_cnts++;
157         if (!(word_en & BIT(3)))        word_cnts++;
158         return word_cnts;
159 }
160
161 /*  */
162 /*      Description: */
163 /*              1. Execute E-Fuse read byte operation according as map offset and */
164 /*                  save to E-Fuse table. */
165 /*              2. Refered from SD1 Richard. */
166 /*  */
167 /*      Assumption: */
168 /*              1. Boot from E-Fuse and successfully auto-load. */
169 /*              2. PASSIVE_LEVEL (USB interface) */
170 /*  */
171 /*      Created by Roger, 2008.10.21. */
172 /*  */
173 /*      2008/12/12 MH   1. Reorganize code flow and reserve bytes. and add description. */
174 /*                                      2. Add efuse utilization collect. */
175 /*      2008/12/22 MH   Read Efuse must check if we write section 1 data again!!! Sec1 */
176 /*                                      write addr must be after sec5. */
177 /*  */
178
179 void
180 efuse_ReadEFuse(
181         struct adapter *Adapter,
182         u8 efuseType,
183         u16     _offset,
184         u16     _size_byte,
185         u8 *pbuf,
186 bool    bPseudoTest
187         );
188 void
189 efuse_ReadEFuse(
190         struct adapter *Adapter,
191         u8 efuseType,
192         u16     _offset,
193         u16     _size_byte,
194         u8 *pbuf,
195 bool    bPseudoTest
196         )
197 {
198         Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
199 }
200
201 void
202 EFUSE_GetEfuseDefinition(
203         struct adapter *padapter,
204         u8 efuseType,
205         u8 type,
206         void    *pOut,
207         bool            bPseudoTest
208         )
209 {
210         padapter->HalFunc.EFUSEGetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest);
211 }
212
213 /*-----------------------------------------------------------------------------
214  * Function:    EFUSE_Read1Byte
215  *
216  * Overview:    Copy from WMAC fot EFUSE read 1 byte.
217  *
218  * Input:       NONE
219  *
220  * Output:      NONE
221  *
222  * Return:      NONE
223  *
224  * Revised History:
225  * When                 Who             Remark
226  * 09/23/2008   MHC             Copy from WMAC.
227  *
228  *---------------------------------------------------------------------------*/
229 u8
230 EFUSE_Read1Byte(
231 struct adapter *Adapter,
232 u16     Address)
233 {
234         u8 data;
235         u8 Bytetemp = {0x00};
236         u8 temp = {0x00};
237         u32 k = 0;
238         u16 contentLen = 0;
239
240         EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
241
242         if (Address < contentLen)       /* E-fuse 512Byte */
243         {
244                 /* Write E-fuse Register address bit0~7 */
245                 temp = Address & 0xFF;
246                 rtw_write8(Adapter, EFUSE_CTRL+1, temp);
247                 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
248                 /* Write E-fuse Register address bit8~9 */
249                 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
250                 rtw_write8(Adapter, EFUSE_CTRL+2, temp);
251
252                 /* Write 0x30[31]= 0 */
253                 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
254                 temp = Bytetemp & 0x7F;
255                 rtw_write8(Adapter, EFUSE_CTRL+3, temp);
256
257                 /* Wait Write-ready (0x30[31]= 1) */
258                 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
259                 while (!(Bytetemp & 0x80))
260                 {
261                         Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
262                         k++;
263                         if (k == 1000)
264                         {
265                                 k = 0;
266                                 break;
267                         }
268                 }
269                 data =rtw_read8(Adapter, EFUSE_CTRL);
270                 return data;
271         }
272         else
273                 return 0xFF;
274
275 }/* EFUSE_Read1Byte */
276
277 /*  11/16/2008 MH Read one byte from real Efuse. */
278 u8
279 efuse_OneByteRead(
280 struct adapter *padapter,
281 u16             addr,
282 u8      *data,
283 bool            bPseudoTest)
284 {
285         u32 tmpidx = 0;
286         u8 bResult;
287         u8 readbyte;
288
289         /* DBG_871X("===> EFUSE_OneByteRead(), addr = %x\n", addr); */
290         /* DBG_871X("===> EFUSE_OneByteRead() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */
291
292         if (bPseudoTest)
293         {
294                 bResult = Efuse_Read1ByteFromFakeContent(padapter, addr, data);
295                 return bResult;
296         }
297
298         /*  <20130121, Kordan> For SMIC EFUSE specificatoin. */
299         /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
300         /* PHY_SetMacReg(padapter, 0x34, BIT11, 0); */
301         rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34)& (~BIT11));
302
303         /*  -----------------e-fuse reg ctrl --------------------------------- */
304         /* address */
305         rtw_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xff));
306         rtw_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03)) |
307         (rtw_read8(padapter, EFUSE_CTRL+2)&0xFC));
308
309         /* rtw_write8(padapter, EFUSE_CTRL+3,  0x72); read cmd */
310         /* Write bit 32 0 */
311         readbyte = rtw_read8(padapter, EFUSE_CTRL+3);
312         rtw_write8(padapter, EFUSE_CTRL+3, (readbyte & 0x7f));
313
314         while (!(0x80 &rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx<1000))
315         {
316                 mdelay(1);
317                 tmpidx++;
318         }
319         if (tmpidx<100)
320         {
321                 *data =rtw_read8(padapter, EFUSE_CTRL);
322                 bResult = true;
323         }
324         else
325         {
326                 *data = 0xff;
327                 bResult = false;
328                 DBG_871X("%s: [ERROR] addr = 0x%x bResult =%d time out 1s !!!\n", __func__, addr, bResult);
329                 DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL));
330         }
331
332         return bResult;
333 }
334
335 /*  11/16/2008 MH Write one byte to reald Efuse. */
336 u8
337 efuse_OneByteWrite(
338 struct adapter *padapter,
339 u16             addr,
340 u8      data,
341 bool            bPseudoTest)
342 {
343         u8 tmpidx = 0;
344         u8 bResult =false;
345         u32 efuseValue = 0;
346
347         /* DBG_871X("===> EFUSE_OneByteWrite(), addr = %x data =%x\n", addr, data); */
348         /* DBG_871X("===> EFUSE_OneByteWrite() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */
349
350         if (bPseudoTest)
351         {
352                 bResult = Efuse_Write1ByteToFakeContent(padapter, addr, data);
353                 return bResult;
354         }
355
356
357         /*  -----------------e-fuse reg ctrl --------------------------------- */
358         /* address */
359
360
361         efuseValue = rtw_read32(padapter, EFUSE_CTRL);
362         efuseValue |= (BIT21|BIT31);
363         efuseValue &= ~(0x3FFFF);
364         efuseValue |= ((addr<<8 | data) & 0x3FFFF);
365
366
367         /*  <20130227, Kordan> 8192E MP chip A-cut had better not set 0x34[11] until B-Cut. */
368
369         /*  <20130121, Kordan> For SMIC EFUSE specificatoin. */
370         /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
371         /* PHY_SetMacReg(padapter, 0x34, BIT11, 1); */
372         rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34)| (BIT11));
373         rtw_write32(padapter, EFUSE_CTRL, 0x90600000|((addr<<8 | data)));
374
375         while ((0x80 &  rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx<100)) {
376                 mdelay(1);
377                 tmpidx++;
378         }
379
380         if (tmpidx<100)
381         {
382                 bResult = true;
383         }
384         else
385         {
386                 bResult = false;
387                 DBG_871X("%s: [ERROR] addr = 0x%x , efuseValue = 0x%x , bResult =%d time out 1s !!!\n",
388                                         __func__, addr, efuseValue, bResult);
389                 DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL));
390         }
391
392         /*  disable Efuse program enable */
393         PHY_SetMacReg(padapter, EFUSE_TEST, BIT(11), 0);
394
395         return bResult;
396 }
397
398 int
399 Efuse_PgPacketRead(struct adapter *padapter,
400                                 u8      offset,
401                                 u8      *data,
402                                 bool            bPseudoTest)
403 {
404         int     ret = 0;
405
406         ret =  padapter->HalFunc.Efuse_PgPacketRead(padapter, offset, data, bPseudoTest);
407
408         return ret;
409 }
410
411 int
412 Efuse_PgPacketWrite(struct adapter *padapter,
413                                 u8      offset,
414                                 u8      word_en,
415                                 u8      *data,
416                                 bool            bPseudoTest)
417 {
418         int ret;
419
420         ret =  padapter->HalFunc.Efuse_PgPacketWrite(padapter, offset, word_en, data, bPseudoTest);
421
422         return ret;
423 }
424
425 /*-----------------------------------------------------------------------------
426  * Function:    efuse_WordEnableDataRead
427  *
428  * Overview:    Read allowed word in current efuse section data.
429  *
430  * Input:       NONE
431  *
432  * Output:      NONE
433  *
434  * Return:      NONE
435  *
436  * Revised History:
437  * When                 Who             Remark
438  * 11/16/2008   MHC             Create Version 0.
439  * 11/21/2008   MHC             Fix Write bug when we only enable late word.
440  *
441  *---------------------------------------------------------------------------*/
442 void
443 efuse_WordEnableDataRead(u8 word_en,
444                                                 u8 *sourdata,
445                                                 u8 *targetdata)
446 {
447         if (!(word_en&BIT(0)))
448         {
449                 targetdata[0] = sourdata[0];
450                 targetdata[1] = sourdata[1];
451         }
452         if (!(word_en&BIT(1)))
453         {
454                 targetdata[2] = sourdata[2];
455                 targetdata[3] = sourdata[3];
456         }
457         if (!(word_en&BIT(2)))
458         {
459                 targetdata[4] = sourdata[4];
460                 targetdata[5] = sourdata[5];
461         }
462         if (!(word_en&BIT(3)))
463         {
464                 targetdata[6] = sourdata[6];
465                 targetdata[7] = sourdata[7];
466         }
467 }
468
469
470 u8
471 Efuse_WordEnableDataWrite(struct adapter *padapter,
472                                                 u16     efuse_addr,
473                                                 u8 word_en,
474                                                 u8 *data,
475                                                 bool            bPseudoTest)
476 {
477         u8 ret = 0;
478
479         ret =  padapter->HalFunc.Efuse_WordEnableDataWrite(padapter, efuse_addr, word_en, data, bPseudoTest);
480
481         return ret;
482 }
483
484 /*-----------------------------------------------------------------------------
485  * Function:    Efuse_ReadAllMap
486  *
487  * Overview:    Read All Efuse content
488  *
489  * Input:       NONE
490  *
491  * Output:      NONE
492  *
493  * Return:      NONE
494  *
495  * Revised History:
496  * When                 Who             Remark
497  * 11/11/2008   MHC             Create Version 0.
498  *
499  *---------------------------------------------------------------------------*/
500 void
501 Efuse_ReadAllMap(
502         struct adapter *padapter,
503         u8 efuseType,
504         u8 *Efuse,
505         bool            bPseudoTest);
506 void
507 Efuse_ReadAllMap(
508         struct adapter *padapter,
509         u8 efuseType,
510         u8 *Efuse,
511         bool            bPseudoTest)
512 {
513         u16 mapLen = 0;
514
515         Efuse_PowerSwitch(padapter, false, true);
516
517         EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
518
519         efuse_ReadEFuse(padapter, efuseType, 0, mapLen, Efuse, bPseudoTest);
520
521         Efuse_PowerSwitch(padapter, false, false);
522 }
523
524 /*-----------------------------------------------------------------------------
525  * Function:    efuse_ShadowRead1Byte
526  *              efuse_ShadowRead2Byte
527  *              efuse_ShadowRead4Byte
528  *
529  * Overview:    Read from efuse init map by one/two/four bytes !!!!!
530  *
531  * Input:       NONE
532  *
533  * Output:      NONE
534  *
535  * Return:      NONE
536  *
537  * Revised History:
538  * When                 Who             Remark
539  * 11/12/2008   MHC             Create Version 0.
540  *
541  *---------------------------------------------------------------------------*/
542 static void
543 efuse_ShadowRead1Byte(
544 struct adapter *padapter,
545 u16     Offset,
546         u8 *Value)
547 {
548         struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
549
550         *Value = pEEPROM->efuse_eeprom_data[Offset];
551
552 }       /*  EFUSE_ShadowRead1Byte */
553
554 /* Read Two Bytes */
555 static void
556 efuse_ShadowRead2Byte(
557 struct adapter *padapter,
558 u16     Offset,
559         u16     *Value)
560 {
561         struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
562
563         *Value = pEEPROM->efuse_eeprom_data[Offset];
564         *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
565
566 }       /*  EFUSE_ShadowRead2Byte */
567
568 /* Read Four Bytes */
569 static void
570 efuse_ShadowRead4Byte(
571 struct adapter *padapter,
572 u16     Offset,
573         u32     *Value)
574 {
575         struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
576
577         *Value = pEEPROM->efuse_eeprom_data[Offset];
578         *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
579         *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
580         *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
581
582 }       /*  efuse_ShadowRead4Byte */
583
584 /*-----------------------------------------------------------------------------
585  * Function:    EFUSE_ShadowMapUpdate
586  *
587  * Overview:    Transfer current EFUSE content to shadow init and modify map.
588  *
589  * Input:       NONE
590  *
591  * Output:      NONE
592  *
593  * Return:      NONE
594  *
595  * Revised History:
596  * When                 Who             Remark
597  * 11/13/2008   MHC             Create Version 0.
598  *
599  *---------------------------------------------------------------------------*/
600 void EFUSE_ShadowMapUpdate(
601         struct adapter *padapter,
602         u8 efuseType,
603         bool    bPseudoTest)
604 {
605         struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
606         u16 mapLen = 0;
607
608         EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
609
610         if (pEEPROM->bautoload_fail_flag == true)
611         {
612                 memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
613         }
614         else
615         {
616                 Efuse_ReadAllMap(padapter, efuseType, pEEPROM->efuse_eeprom_data, bPseudoTest);
617         }
618
619         /* PlatformMoveMemory((void *)&pHalData->EfuseMap[EFUSE_MODIFY_MAP][0], */
620         /* void *)&pHalData->EfuseMap[EFUSE_INIT_MAP][0], mapLen); */
621 }/*  EFUSE_ShadowMapUpdate */
622
623
624 /*-----------------------------------------------------------------------------
625  * Function:    EFUSE_ShadowRead
626  *
627  * Overview:    Read from efuse init map !!!!!
628  *
629  * Input:       NONE
630  *
631  * Output:      NONE
632  *
633  * Return:      NONE
634  *
635  * Revised History:
636  * When                 Who             Remark
637  * 11/12/2008   MHC             Create Version 0.
638  *
639  *---------------------------------------------------------------------------*/
640 void
641 EFUSE_ShadowRead(
642         struct adapter *padapter,
643         u8 Type,
644         u16     Offset,
645         u32     *Value  )
646 {
647         if (Type == 1)
648                 efuse_ShadowRead1Byte(padapter, Offset, (u8 *)Value);
649         else if (Type == 2)
650                 efuse_ShadowRead2Byte(padapter, Offset, (u16 *)Value);
651         else if (Type == 4)
652                 efuse_ShadowRead4Byte(padapter, Offset, (u32 *)Value);
653
654 }       // EFUSE_ShadowRead