]>
Commit | Line | Data |
---|---|---|
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 |
49 | typedef 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 |
76 | u8 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 |
152 | void 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 |
217 | static 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 | 247 | int 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 | 271 | int 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 | 290 | int 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 | 297 | int 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 | 308 | void 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 | 334 | int 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 | } |