]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rt2860/common/ee_efuse.c
Staging: rt28x0: run common/*.c files through Lindent
[net-next-2.6.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 #include        "../rt_config.h"
39
40 #define EFUSE_USAGE_MAP_START   0x2d0
41 #define EFUSE_USAGE_MAP_END             0x2fc
42 #define EFUSE_USAGE_MAP_SIZE    45
43
44 #define EFUSE_EEPROM_DEFULT_FILE        "RT30xxEEPROM.bin"
45 #define MAX_EEPROM_BIN_FILE_SIZE        1024
46
47 #define EFUSE_TAG                               0x2fe
48
49 typedef union _EFUSE_CTRL_STRUC {
50         struct {
51                 UINT32 EFSROM_AOUT:6;
52                 UINT32 EFSROM_MODE:2;
53                 UINT32 EFSROM_LDO_OFF_TIME:6;
54                 UINT32 EFSROM_LDO_ON_TIME:2;
55                 UINT32 EFSROM_AIN:10;
56                 UINT32 RESERVED:4;
57                 UINT32 EFSROM_KICK:1;
58                 UINT32 SEL_EFUSE:1;
59         } field;
60         UINT32 word;
61 } EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC;
62
63 /*
64 ========================================================================
65
66         Routine Description:
67
68         Arguments:
69
70         Return Value:
71
72         Note:
73
74 ========================================================================
75 */
76 UCHAR eFuseReadRegisters(IN PRTMP_ADAPTER pAd,
77                          IN USHORT Offset, IN USHORT Length, OUT USHORT * pData)
78 {
79         EFUSE_CTRL_STRUC eFuseCtrlStruc;
80         int i;
81         USHORT efuseDataOffset;
82         UINT32 data;
83
84         RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
85
86         //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
87         //Use the eeprom logical address and covert to address to block number
88         eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
89
90         //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0.
91         eFuseCtrlStruc.field.EFSROM_MODE = 0;
92
93         //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.
94         eFuseCtrlStruc.field.EFSROM_KICK = 1;
95
96         NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
97         RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
98
99         //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.
100         i = 0;
101         while (i < 500) {
102                 //rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4);
103                 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
104                 if (eFuseCtrlStruc.field.EFSROM_KICK == 0) {
105                         break;
106                 }
107                 RTMPusecDelay(2);
108                 i++;
109         }
110
111         //if EFSROM_AOUT is not found in physical address, write 0xffff
112         if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) {
113                 for (i = 0; i < Length / 2; i++)
114                         *(pData + 2 * i) = 0xffff;
115         } else {
116                 //Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x590-0x59C)
117                 efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC);
118                 //data hold 4 bytes data.
119                 //In RTMP_IO_READ32 will automatically execute 32-bytes swapping
120                 RTMP_IO_READ32(pAd, efuseDataOffset, &data);
121                 //Decide the upper 2 bytes or the bottom 2 bytes.
122                 // Little-endian                S       |       S       Big-endian
123                 // addr 3       2       1       0       |       0       1       2       3
124                 // Ori-V        D       C       B       A       |       A       B       C       D
125                 //After swapping
126                 //              D       C       B       A       |       D       C       B       A
127                 //Return 2-bytes
128                 //The return byte statrs from S. Therefore, the little-endian will return BA, the Big-endian will return DC.
129                 //For returning the bottom 2 bytes, the Big-endian should shift right 2-bytes.
130                 data = data >> (8 * (Offset & 0x3));
131
132                 NdisMoveMemory(pData, &data, Length);
133         }
134
135         return (UCHAR) eFuseCtrlStruc.field.EFSROM_AOUT;
136
137 }
138
139 /*
140 ========================================================================
141
142         Routine Description:
143
144         Arguments:
145
146         Return Value:
147
148         Note:
149
150 ========================================================================
151 */
152 VOID eFusePhysicalReadRegisters(IN PRTMP_ADAPTER pAd,
153                                 IN USHORT Offset,
154                                 IN USHORT Length, OUT USHORT * pData)
155 {
156         EFUSE_CTRL_STRUC eFuseCtrlStruc;
157         int i;
158         USHORT efuseDataOffset;
159         UINT32 data;
160
161         RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
162
163         //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.
164         eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
165
166         //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.
167         //Read in physical view
168         eFuseCtrlStruc.field.EFSROM_MODE = 1;
169
170         //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.
171         eFuseCtrlStruc.field.EFSROM_KICK = 1;
172
173         NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
174         RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
175
176         //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.
177         i = 0;
178         while (i < 500) {
179                 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
180                 if (eFuseCtrlStruc.field.EFSROM_KICK == 0)
181                         break;
182                 RTMPusecDelay(2);
183                 i++;
184         }
185
186         //Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)
187         //Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits.
188         //The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes
189         //Decide which EFUSE_DATA to read
190         //590:F E D C
191         //594:B A 9 8
192         //598:7 6 5 4
193         //59C:3 2 1 0
194         efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC);
195
196         RTMP_IO_READ32(pAd, efuseDataOffset, &data);
197
198         data = data >> (8 * (Offset & 0x3));
199
200         NdisMoveMemory(pData, &data, Length);
201
202 }
203
204 /*
205 ========================================================================
206
207         Routine Description:
208
209         Arguments:
210
211         Return Value:
212
213         Note:
214
215 ========================================================================
216 */
217 static VOID eFuseReadPhysical(IN PRTMP_ADAPTER pAd,
218                               IN PUSHORT lpInBuffer,
219                               IN ULONG nInBufferSize,
220                               OUT PUSHORT lpOutBuffer, IN ULONG nOutBufferSize)
221 {
222         USHORT *pInBuf = (USHORT *) lpInBuffer;
223         USHORT *pOutBuf = (USHORT *) lpOutBuffer;
224
225         USHORT Offset = pInBuf[0];      //addr
226         USHORT Length = pInBuf[1];      //length
227         int i;
228
229         for (i = 0; i < Length; i += 2) {
230                 eFusePhysicalReadRegisters(pAd, Offset + i, 2, &pOutBuf[i / 2]);
231         }
232 }
233
234 /*
235 ========================================================================
236
237         Routine Description:
238
239         Arguments:
240
241         Return Value:
242
243         Note:
244
245 ========================================================================
246 */
247 INT set_eFuseGetFreeBlockCount_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg)
248 {
249         USHORT i;
250         USHORT LogicalAddress;
251         USHORT efusefreenum = 0;
252         if (!pAd->bUseEfuse)
253                 return FALSE;
254         for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) {
255                 eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
256                 if ((LogicalAddress & 0xff) == 0) {
257                         efusefreenum = (UCHAR) (EFUSE_USAGE_MAP_END - i + 1);
258                         break;
259                 } else if (((LogicalAddress >> 8) & 0xff) == 0) {
260                         efusefreenum = (UCHAR) (EFUSE_USAGE_MAP_END - i);
261                         break;
262                 }
263
264                 if (i == EFUSE_USAGE_MAP_END)
265                         efusefreenum = 0;
266         }
267         printk("efuseFreeNumber is %d\n", efusefreenum);
268         return TRUE;
269 }
270
271 INT set_eFusedump_Proc(IN PRTMP_ADAPTER pAd, IN PSTRING arg)
272 {
273         USHORT InBuf[3];
274         INT i = 0;
275         if (!pAd->bUseEfuse)
276                 return FALSE;
277         for (i = 0; i < EFUSE_USAGE_MAP_END / 2; i++) {
278                 InBuf[0] = 2 * i;
279                 InBuf[1] = 2;
280                 InBuf[2] = 0x0;
281
282                 eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
283                 if (i % 4 == 0)
284                         printk("\nBlock %x:", i / 8);
285                 printk("%04x ", InBuf[2]);
286         }
287         return TRUE;
288 }
289
290 int rtmp_ee_efuse_read16(IN RTMP_ADAPTER * pAd,
291                          IN USHORT Offset, OUT USHORT * pValue)
292 {
293         eFuseReadRegisters(pAd, Offset, 2, pValue);
294         return (*pValue);
295 }
296
297 int RtmpEfuseSupportCheck(IN RTMP_ADAPTER * pAd)
298 {
299         USHORT value;
300
301         if (IS_RT30xx(pAd)) {
302                 eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value);
303                 pAd->EFuseTag = (value & 0xff);
304         }
305         return 0;
306 }
307
308 VOID eFuseGetFreeBlockCount(IN PRTMP_ADAPTER pAd, PUINT EfuseFreeBlock)
309 {
310         USHORT i;
311         USHORT LogicalAddress;
312         if (!pAd->bUseEfuse) {
313                 DBGPRINT(RT_DEBUG_TRACE,
314                          ("eFuseGetFreeBlockCount Only supports efuse Mode\n"));
315                 return;
316         }
317         for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) {
318                 eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
319                 if ((LogicalAddress & 0xff) == 0) {
320                         *EfuseFreeBlock = (UCHAR) (EFUSE_USAGE_MAP_END - i + 1);
321                         break;
322                 } else if (((LogicalAddress >> 8) & 0xff) == 0) {
323                         *EfuseFreeBlock = (UCHAR) (EFUSE_USAGE_MAP_END - i);
324                         break;
325                 }
326
327                 if (i == EFUSE_USAGE_MAP_END)
328                         *EfuseFreeBlock = 0;
329         }
330         DBGPRINT(RT_DEBUG_TRACE,
331                  ("eFuseGetFreeBlockCount is 0x%x\n", *EfuseFreeBlock));
332 }
333
334 INT eFuse_init(IN PRTMP_ADAPTER pAd)
335 {
336         UINT EfuseFreeBlock = 0;
337         DBGPRINT(RT_DEBUG_ERROR,
338                  ("NVM is Efuse and its size =%x[%x-%x] \n",
339                   EFUSE_USAGE_MAP_SIZE, EFUSE_USAGE_MAP_START,
340                   EFUSE_USAGE_MAP_END));
341         eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock);
342
343         return 0;
344 }