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