4bff473ccf38f108c4f7bfb3102d970d38c23875
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rt2860 / common / ee_efuse.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26
27         Module Name:
28         ee_efuse.c
29
30         Abstract:
31         Miniport generic portion header file
32
33         Revision History:
34         Who         When          What
35         --------    ----------    ----------------------------------------------
36 */
37
38
39 #include        "../rt_config.h"
40
41
42
43 #define EFUSE_USAGE_MAP_START   0x2d0
44 #define EFUSE_USAGE_MAP_END             0x2fc
45 #define EFUSE_USAGE_MAP_SIZE    45
46
47
48
49 #define EFUSE_EEPROM_DEFULT_FILE        "RT30xxEEPROM.bin"
50 #define MAX_EEPROM_BIN_FILE_SIZE        1024
51
52
53
54 #define EFUSE_TAG                               0x2fe
55
56 typedef union   _EFUSE_CTRL_STRUC {
57         struct  {
58                 UINT32            EFSROM_AOUT:6;
59                 UINT32            EFSROM_MODE:2;
60                 UINT32            EFSROM_LDO_OFF_TIME:6;
61                 UINT32            EFSROM_LDO_ON_TIME:2;
62                 UINT32            EFSROM_AIN:10;
63                 UINT32            RESERVED:4;
64                 UINT32            EFSROM_KICK:1;
65                 UINT32            SEL_EFUSE:1;
66         }       field;
67         UINT32                  word;
68 }       EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC;
69
70 /*
71 ========================================================================
72
73         Routine Description:
74
75         Arguments:
76
77         Return Value:
78
79         Note:
80
81 ========================================================================
82 */
83 UCHAR eFuseReadRegisters(
84         IN      PRTMP_ADAPTER   pAd,
85         IN      USHORT Offset,
86         IN      USHORT Length,
87         OUT     USHORT* pData)
88 {
89         EFUSE_CTRL_STRUC                eFuseCtrlStruc;
90         int     i;
91         USHORT  efuseDataOffset;
92         UINT32  data;
93
94         RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
95
96         //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
97         //Use the eeprom logical address and covert to address to block number
98         eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
99
100         //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0.
101         eFuseCtrlStruc.field.EFSROM_MODE = 0;
102
103         //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.
104         eFuseCtrlStruc.field.EFSROM_KICK = 1;
105
106         NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
107         RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
108
109         //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.
110         i = 0;
111         while(i < 500)
112         {
113                 //rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4);
114                 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
115                 if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
116                 {
117                         break;
118                 }
119                 RTMPusecDelay(2);
120                 i++;
121         }
122
123         //if EFSROM_AOUT is not found in physical address, write 0xffff
124         if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f)
125         {
126                 for(i=0; i<Length/2; i++)
127                         *(pData+2*i) = 0xffff;
128         }
129         else
130         {
131                 //Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x590-0x59C)
132                 efuseDataOffset =  EFUSE_DATA3 - (Offset & 0xC);
133                 //data hold 4 bytes data.
134                 //In RTMP_IO_READ32 will automatically execute 32-bytes swapping
135                 RTMP_IO_READ32(pAd, efuseDataOffset, &data);
136                 //Decide the upper 2 bytes or the bottom 2 bytes.
137                 // Little-endian                S       |       S       Big-endian
138                 // addr 3       2       1       0       |       0       1       2       3
139                 // Ori-V        D       C       B       A       |       A       B       C       D
140                 //After swapping
141                 //              D       C       B       A       |       D       C       B       A
142                 //Return 2-bytes
143                 //The return byte statrs from S. Therefore, the little-endian will return BA, the Big-endian will return DC.
144                 //For returning the bottom 2 bytes, the Big-endian should shift right 2-bytes.
145                 data = data >> (8*(Offset & 0x3));
146
147                 NdisMoveMemory(pData, &data, Length);
148         }
149
150         return (UCHAR) eFuseCtrlStruc.field.EFSROM_AOUT;
151
152 }
153
154 /*
155 ========================================================================
156
157         Routine Description:
158
159         Arguments:
160
161         Return Value:
162
163         Note:
164
165 ========================================================================
166 */
167 VOID eFusePhysicalReadRegisters(
168         IN      PRTMP_ADAPTER   pAd,
169         IN      USHORT Offset,
170         IN      USHORT Length,
171         OUT     USHORT* pData)
172 {
173         EFUSE_CTRL_STRUC                eFuseCtrlStruc;
174         int     i;
175         USHORT  efuseDataOffset;
176         UINT32  data;
177
178         RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
179
180         //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
181         eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
182
183         //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.
184         //Read in physical view
185         eFuseCtrlStruc.field.EFSROM_MODE = 1;
186
187         //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.
188         eFuseCtrlStruc.field.EFSROM_KICK = 1;
189
190         NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
191         RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
192
193         //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.
194         i = 0;
195         while(i < 500)
196         {
197                 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
198                 if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
199                         break;
200                 RTMPusecDelay(2);
201                 i++;
202         }
203
204         //Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)
205         //Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits.
206         //The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes
207         //Decide which EFUSE_DATA to read
208         //590:F E D C
209         //594:B A 9 8
210         //598:7 6 5 4
211         //59C:3 2 1 0
212         efuseDataOffset =  EFUSE_DATA3 - (Offset & 0xC)  ;
213
214         RTMP_IO_READ32(pAd, efuseDataOffset, &data);
215
216         data = data >> (8*(Offset & 0x3));
217
218         NdisMoveMemory(pData, &data, Length);
219
220 }
221
222 /*
223 ========================================================================
224
225         Routine Description:
226
227         Arguments:
228
229         Return Value:
230
231         Note:
232
233 ========================================================================
234 */
235 static VOID eFuseReadPhysical(
236         IN      PRTMP_ADAPTER   pAd,
237         IN      PUSHORT lpInBuffer,
238         IN      ULONG nInBufferSize,
239         OUT     PUSHORT lpOutBuffer,
240         IN      ULONG nOutBufferSize
241 )
242 {
243         USHORT* pInBuf = (USHORT*)lpInBuffer;
244         USHORT* pOutBuf = (USHORT*)lpOutBuffer;
245
246         USHORT Offset = pInBuf[0];                                      //addr
247         USHORT Length = pInBuf[1];                                      //length
248         int             i;
249
250         for(i=0; i<Length; i+=2)
251         {
252                 eFusePhysicalReadRegisters(pAd,Offset+i, 2, &pOutBuf[i/2]);
253         }
254 }
255
256 /*
257 ========================================================================
258
259         Routine Description:
260
261         Arguments:
262
263         Return Value:
264
265         Note:
266
267 ========================================================================
268 */
269 INT set_eFuseGetFreeBlockCount_Proc(
270         IN      PRTMP_ADAPTER   pAd,
271         IN      PSTRING                 arg)
272 {
273         USHORT i;
274         USHORT  LogicalAddress;
275         USHORT efusefreenum=0;
276         if(!pAd->bUseEfuse)
277                 return FALSE;
278         for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i+=2)
279         {
280                 eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
281                 if( (LogicalAddress & 0xff) == 0)
282                 {
283                         efusefreenum= (UCHAR) (EFUSE_USAGE_MAP_END-i+1);
284                         break;
285                 }
286                 else if(( (LogicalAddress >> 8) & 0xff) == 0)
287                 {
288                         efusefreenum = (UCHAR) (EFUSE_USAGE_MAP_END-i);
289                         break;
290                 }
291
292                 if(i == EFUSE_USAGE_MAP_END)
293                         efusefreenum = 0;
294         }
295         printk("efuseFreeNumber is %d\n",efusefreenum);
296         return TRUE;
297 }
298
299
300 INT set_eFusedump_Proc(
301         IN      PRTMP_ADAPTER   pAd,
302         IN      PSTRING                 arg)
303 {
304 USHORT InBuf[3];
305         INT i=0;
306         if(!pAd->bUseEfuse)
307                 return FALSE;
308         for(i =0; i<EFUSE_USAGE_MAP_END/2; i++)
309         {
310                 InBuf[0] = 2*i;
311                 InBuf[1] = 2;
312                 InBuf[2] = 0x0;
313
314                 eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
315                 if(i%4==0)
316                 printk("\nBlock %x:",i/8);
317                 printk("%04x ",InBuf[2]);
318         }
319         return TRUE;
320 }
321
322 int rtmp_ee_efuse_read16(
323         IN RTMP_ADAPTER *pAd,
324         IN USHORT Offset,
325         OUT USHORT *pValue)
326 {
327         eFuseReadRegisters(pAd, Offset, 2, pValue);
328         return (*pValue);
329 }
330
331 int RtmpEfuseSupportCheck(
332         IN RTMP_ADAPTER *pAd)
333 {
334         USHORT value;
335
336         if (IS_RT30xx(pAd))
337         {
338                 eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value);
339                 pAd->EFuseTag = (value & 0xff);
340         }
341         return 0;
342 }
343
344 VOID eFuseGetFreeBlockCount(IN PRTMP_ADAPTER pAd,
345         PUINT EfuseFreeBlock)
346 {
347         USHORT i;
348         USHORT  LogicalAddress;
349         if(!pAd->bUseEfuse)
350                 {
351                 DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount Only supports efuse Mode\n"));
352                 return ;
353                 }
354         for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i+=2)
355         {
356                 eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
357                 if( (LogicalAddress & 0xff) == 0)
358                 {
359                         *EfuseFreeBlock= (UCHAR) (EFUSE_USAGE_MAP_END-i+1);
360                         break;
361                 }
362                 else if(( (LogicalAddress >> 8) & 0xff) == 0)
363                 {
364                         *EfuseFreeBlock = (UCHAR) (EFUSE_USAGE_MAP_END-i);
365                         break;
366                 }
367
368                 if(i == EFUSE_USAGE_MAP_END)
369                         *EfuseFreeBlock = 0;
370         }
371         DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount is 0x%x\n",*EfuseFreeBlock));
372 }
373
374 INT eFuse_init(
375         IN PRTMP_ADAPTER pAd)
376 {
377         UINT    EfuseFreeBlock=0;
378         DBGPRINT(RT_DEBUG_ERROR, ("NVM is Efuse and its size =%x[%x-%x] \n",EFUSE_USAGE_MAP_SIZE,EFUSE_USAGE_MAP_START,EFUSE_USAGE_MAP_END));
379         eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock);
380
381         return 0;
382 }