]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/common/ee_efuse.c
Staging: rt28x0: remove typedefs (part one)
[net-next-2.6.git] / drivers / staging / rt2860 / common / ee_efuse.c
CommitLineData
ca97b838
BZ
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
ca97b838
BZ
38#include "../rt_config.h"
39
ca97b838
BZ
40#define EFUSE_USAGE_MAP_START 0x2d0
41#define EFUSE_USAGE_MAP_END 0x2fc
42#define EFUSE_USAGE_MAP_SIZE 45
43
ca97b838
BZ
44#define EFUSE_EEPROM_DEFULT_FILE "RT30xxEEPROM.bin"
45#define MAX_EEPROM_BIN_FILE_SIZE 1024
46
ca97b838
BZ
47#define EFUSE_TAG 0x2fe
48
96b3c83d
BZ
49typedef union _EFUSE_CTRL_STRUC {
50 struct {
51126deb
BZ
51 u32 EFSROM_AOUT:6;
52 u32 EFSROM_MODE:2;
53 u32 EFSROM_LDO_OFF_TIME:6;
54 u32 EFSROM_LDO_ON_TIME:2;
55 u32 EFSROM_AIN:10;
56 u32 RESERVED:4;
57 u32 EFSROM_KICK:1;
58 u32 SEL_EFUSE:1;
96b3c83d 59 } field;
51126deb 60 u32 word;
96b3c83d 61} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC;
ca97b838 62
ca97b838
BZ
63/*
64========================================================================
65
66 Routine Description:
67
68 Arguments:
69
70 Return Value:
71
72 Note:
73
74========================================================================
75*/
51126deb
BZ
76u8 eFuseReadRegisters(IN PRTMP_ADAPTER pAd,
77 u16 Offset, u16 Length, u16 * pData)
ca97b838 78{
96b3c83d
BZ
79 EFUSE_CTRL_STRUC eFuseCtrlStruc;
80 int i;
51126deb
BZ
81 u16 efuseDataOffset;
82 u32 data;
ca97b838
BZ
83
84 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
85
ec278fa2
BZ
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 */
ca97b838
BZ
88 eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
89
ec278fa2 90 /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0. */
ca97b838
BZ
91 eFuseCtrlStruc.field.EFSROM_MODE = 0;
92
ec278fa2 93 /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. */
ca97b838
BZ
94 eFuseCtrlStruc.field.EFSROM_KICK = 1;
95
96 NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
97 RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
98
ec278fa2 99 /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. */
ca97b838 100 i = 0;
96b3c83d 101 while (i < 500) {
ec278fa2 102 /*rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4); */
ca97b838 103 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
96b3c83d 104 if (eFuseCtrlStruc.field.EFSROM_KICK == 0) {
ca97b838
BZ
105 break;
106 }
107 RTMPusecDelay(2);
108 i++;
109 }
110
ec278fa2 111 /*if EFSROM_AOUT is not found in physical address, write 0xffff */
96b3c83d
BZ
112 if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) {
113 for (i = 0; i < Length / 2; i++)
114 *(pData + 2 * i) = 0xffff;
115 } else {
ec278fa2 116 /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x590-0x59C) */
96b3c83d 117 efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC);
ec278fa2
BZ
118 /*data hold 4 bytes data. */
119 /*In RTMP_IO_READ32 will automatically execute 32-bytes swapping */
ca97b838 120 RTMP_IO_READ32(pAd, efuseDataOffset, &data);
ec278fa2
BZ
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. */
96b3c83d 130 data = data >> (8 * (Offset & 0x3));
ca97b838
BZ
131
132 NdisMoveMemory(pData, &data, Length);
133 }
134
51126deb 135 return (u8)eFuseCtrlStruc.field.EFSROM_AOUT;
ca97b838
BZ
136
137}
138
139/*
140========================================================================
141
142 Routine Description:
143
144 Arguments:
145
146 Return Value:
147
148 Note:
149
150========================================================================
151*/
51126deb
BZ
152void eFusePhysicalReadRegisters(IN PRTMP_ADAPTER pAd,
153 u16 Offset,
154 u16 Length, u16 * pData)
ca97b838 155{
96b3c83d
BZ
156 EFUSE_CTRL_STRUC eFuseCtrlStruc;
157 int i;
51126deb
BZ
158 u16 efuseDataOffset;
159 u32 data;
ca97b838
BZ
160
161 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
162
ec278fa2 163 /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. */
ca97b838
BZ
164 eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
165
ec278fa2
BZ
166 /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. */
167 /*Read in physical view */
ca97b838
BZ
168 eFuseCtrlStruc.field.EFSROM_MODE = 1;
169
ec278fa2 170 /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. */
ca97b838
BZ
171 eFuseCtrlStruc.field.EFSROM_KICK = 1;
172
173 NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
174 RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
175
ec278fa2 176 /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. */
ca97b838 177 i = 0;
96b3c83d 178 while (i < 500) {
ca97b838 179 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
96b3c83d 180 if (eFuseCtrlStruc.field.EFSROM_KICK == 0)
ca97b838
BZ
181 break;
182 RTMPusecDelay(2);
183 i++;
184 }
185
ec278fa2
BZ
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 */
96b3c83d 194 efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC);
ca97b838
BZ
195
196 RTMP_IO_READ32(pAd, efuseDataOffset, &data);
197
96b3c83d 198 data = data >> (8 * (Offset & 0x3));
ca97b838
BZ
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*/
51126deb
BZ
217static void eFuseReadPhysical(IN PRTMP_ADAPTER pAd,
218 u16 *lpInBuffer,
219 unsigned long nInBufferSize,
220 u16 *lpOutBuffer, unsigned long nOutBufferSize)
ca97b838 221{
51126deb
BZ
222 u16 *pInBuf = (u16 *) lpInBuffer;
223 u16 *pOutBuf = (u16 *) lpOutBuffer;
ca97b838 224
51126deb
BZ
225 u16 Offset = pInBuf[0]; /*addr */
226 u16 Length = pInBuf[1]; /*length */
96b3c83d 227 int i;
ca97b838 228
96b3c83d
BZ
229 for (i = 0; i < Length; i += 2) {
230 eFusePhysicalReadRegisters(pAd, Offset + i, 2, &pOutBuf[i / 2]);
ca97b838
BZ
231 }
232}
233
ca97b838
BZ
234/*
235========================================================================
236
237 Routine Description:
238
239 Arguments:
240
241 Return Value:
242
243 Note:
244
245========================================================================
246*/
51126deb 247int set_eFuseGetFreeBlockCount_Proc(IN PRTMP_ADAPTER pAd, char *arg)
ca97b838 248{
51126deb
BZ
249 u16 i;
250 u16 LogicalAddress;
251 u16 efusefreenum = 0;
96b3c83d 252 if (!pAd->bUseEfuse)
ca97b838 253 return FALSE;
96b3c83d 254 for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) {
ca97b838 255 eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
96b3c83d 256 if ((LogicalAddress & 0xff) == 0) {
51126deb 257 efusefreenum = (u8)(EFUSE_USAGE_MAP_END - i + 1);
ca97b838 258 break;
96b3c83d 259 } else if (((LogicalAddress >> 8) & 0xff) == 0) {
51126deb 260 efusefreenum = (u8)(EFUSE_USAGE_MAP_END - i);
ca97b838
BZ
261 break;
262 }
263
96b3c83d 264 if (i == EFUSE_USAGE_MAP_END)
ca97b838
BZ
265 efusefreenum = 0;
266 }
96b3c83d 267 printk("efuseFreeNumber is %d\n", efusefreenum);
ca97b838
BZ
268 return TRUE;
269}
270
51126deb 271int set_eFusedump_Proc(IN PRTMP_ADAPTER pAd, char *arg)
ca97b838 272{
51126deb
BZ
273 u16 InBuf[3];
274 int i = 0;
96b3c83d 275 if (!pAd->bUseEfuse)
ca97b838 276 return FALSE;
96b3c83d
BZ
277 for (i = 0; i < EFUSE_USAGE_MAP_END / 2; i++) {
278 InBuf[0] = 2 * i;
ca97b838
BZ
279 InBuf[1] = 2;
280 InBuf[2] = 0x0;
281
282 eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
96b3c83d
BZ
283 if (i % 4 == 0)
284 printk("\nBlock %x:", i / 8);
285 printk("%04x ", InBuf[2]);
ca97b838
BZ
286 }
287 return TRUE;
288}
289
96b3c83d 290int rtmp_ee_efuse_read16(IN RTMP_ADAPTER * pAd,
51126deb 291 u16 Offset, u16 * pValue)
ca97b838 292{
44c68c23 293 eFuseReadRegisters(pAd, Offset, 2, pValue);
ca97b838
BZ
294 return (*pValue);
295}
296
96b3c83d 297int RtmpEfuseSupportCheck(IN RTMP_ADAPTER * pAd)
ca97b838 298{
51126deb 299 u16 value;
ca97b838 300
96b3c83d 301 if (IS_RT30xx(pAd)) {
ca97b838
BZ
302 eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value);
303 pAd->EFuseTag = (value & 0xff);
304 }
305 return 0;
306}
307
51126deb 308void eFuseGetFreeBlockCount(IN PRTMP_ADAPTER pAd, u32 *EfuseFreeBlock)
ca97b838 309{
51126deb
BZ
310 u16 i;
311 u16 LogicalAddress;
96b3c83d
BZ
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) {
ca97b838 318 eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
96b3c83d 319 if ((LogicalAddress & 0xff) == 0) {
51126deb 320 *EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i + 1);
ca97b838 321 break;
96b3c83d 322 } else if (((LogicalAddress >> 8) & 0xff) == 0) {
51126deb 323 *EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i);
ca97b838
BZ
324 break;
325 }
326
96b3c83d 327 if (i == EFUSE_USAGE_MAP_END)
ca97b838
BZ
328 *EfuseFreeBlock = 0;
329 }
96b3c83d
BZ
330 DBGPRINT(RT_DEBUG_TRACE,
331 ("eFuseGetFreeBlockCount is 0x%x\n", *EfuseFreeBlock));
ca97b838
BZ
332}
333
51126deb 334int eFuse_init(IN PRTMP_ADAPTER pAd)
ca97b838 335{
51126deb 336 u32 EfuseFreeBlock = 0;
96b3c83d
BZ
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));
ca97b838 341 eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock);
ca97b838
BZ
342
343 return 0;
344}