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 		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;
59 	} field;
60 	u32 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 */
eFuseReadRegisters(struct rt_rtmp_adapter * pAd,u16 Offset,u16 Length,u16 * pData)76 u8 eFuseReadRegisters(struct rt_rtmp_adapter *pAd,
77 			 u16 Offset, u16 Length, u16 * pData)
78 {
79 	EFUSE_CTRL_STRUC eFuseCtrlStruc;
80 	int i;
81 	u16 efuseDataOffset;
82 	u32 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 (u8)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 */
eFusePhysicalReadRegisters(struct rt_rtmp_adapter * pAd,u16 Offset,u16 Length,u16 * pData)152 void eFusePhysicalReadRegisters(struct rt_rtmp_adapter *pAd,
153 				u16 Offset,
154 				u16 Length, u16 * pData)
155 {
156 	EFUSE_CTRL_STRUC eFuseCtrlStruc;
157 	int i;
158 	u16 efuseDataOffset;
159 	u32 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 */
eFuseReadPhysical(struct rt_rtmp_adapter * pAd,u16 * lpInBuffer,unsigned long nInBufferSize,u16 * lpOutBuffer,unsigned long nOutBufferSize)217 static void eFuseReadPhysical(struct rt_rtmp_adapter *pAd,
218 			      u16 *lpInBuffer,
219 			      unsigned long nInBufferSize,
220 			      u16 *lpOutBuffer, unsigned long nOutBufferSize)
221 {
222 	u16 *pInBuf = (u16 *) lpInBuffer;
223 	u16 *pOutBuf = (u16 *) lpOutBuffer;
224 
225 	u16 Offset = pInBuf[0];	/*addr */
226 	u16 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 */
set_eFuseGetFreeBlockCount_Proc(struct rt_rtmp_adapter * pAd,char * arg)247 int set_eFuseGetFreeBlockCount_Proc(struct rt_rtmp_adapter *pAd, char *arg)
248 {
249 	u16 i;
250 	u16 LogicalAddress;
251 	u16 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 = (u8)(EFUSE_USAGE_MAP_END - i + 1);
258 			break;
259 		} else if (((LogicalAddress >> 8) & 0xff) == 0) {
260 			efusefreenum = (u8)(EFUSE_USAGE_MAP_END - i);
261 			break;
262 		}
263 
264 		if (i == EFUSE_USAGE_MAP_END)
265 			efusefreenum = 0;
266 	}
267 	printk(KERN_DEBUG "efuseFreeNumber is %d\n", efusefreenum);
268 	return TRUE;
269 }
270 
set_eFusedump_Proc(struct rt_rtmp_adapter * pAd,char * arg)271 int set_eFusedump_Proc(struct rt_rtmp_adapter *pAd, char *arg)
272 {
273 	u16 InBuf[3];
274 	int i = 0;
275 	if (!pAd->bUseEfuse)
276 		return FALSE;
277 
278 	printk(KERN_DEBUG "Block 0: ");
279 
280 	for (i = 0; i < EFUSE_USAGE_MAP_END / 2; i++) {
281 		InBuf[0] = 2 * i;
282 		InBuf[1] = 2;
283 		InBuf[2] = 0x0;
284 
285 		eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
286 		if (i && i % 4 == 0) {
287 			printk(KERN_CONT "\n");
288 			printk(KERN_DEBUG "Block %x:", i / 8);
289 		}
290 		printk(KERN_CONT "%04x ", InBuf[2]);
291 	}
292 	printk(KERN_CONT "\n");
293 
294 	return TRUE;
295 }
296 
rtmp_ee_efuse_read16(struct rt_rtmp_adapter * pAd,u16 Offset,u16 * pValue)297 int rtmp_ee_efuse_read16(struct rt_rtmp_adapter *pAd,
298 			 u16 Offset, u16 * pValue)
299 {
300 	eFuseReadRegisters(pAd, Offset, 2, pValue);
301 	return (*pValue);
302 }
303 
RtmpEfuseSupportCheck(struct rt_rtmp_adapter * pAd)304 int RtmpEfuseSupportCheck(struct rt_rtmp_adapter *pAd)
305 {
306 	u16 value;
307 
308 	if (IS_RT30xx(pAd)) {
309 		eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value);
310 		pAd->EFuseTag = (value & 0xff);
311 	}
312 	return 0;
313 }
314 
eFuseGetFreeBlockCount(struct rt_rtmp_adapter * pAd,u32 * EfuseFreeBlock)315 void eFuseGetFreeBlockCount(struct rt_rtmp_adapter *pAd, u32 *EfuseFreeBlock)
316 {
317 	u16 i;
318 	u16 LogicalAddress;
319 	if (!pAd->bUseEfuse) {
320 		DBGPRINT(RT_DEBUG_TRACE,
321 			 ("eFuseGetFreeBlockCount Only supports efuse Mode\n"));
322 		return;
323 	}
324 	for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) {
325 		eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
326 		if ((LogicalAddress & 0xff) == 0) {
327 			*EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i + 1);
328 			break;
329 		} else if (((LogicalAddress >> 8) & 0xff) == 0) {
330 			*EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i);
331 			break;
332 		}
333 
334 		if (i == EFUSE_USAGE_MAP_END)
335 			*EfuseFreeBlock = 0;
336 	}
337 	DBGPRINT(RT_DEBUG_TRACE,
338 		 ("eFuseGetFreeBlockCount is 0x%x\n", *EfuseFreeBlock));
339 }
340 
eFuse_init(struct rt_rtmp_adapter * pAd)341 int eFuse_init(struct rt_rtmp_adapter *pAd)
342 {
343 	u32 EfuseFreeBlock = 0;
344 	DBGPRINT(RT_DEBUG_ERROR,
345 		 ("NVM is Efuse and its size =%x[%x-%x] \n",
346 		  EFUSE_USAGE_MAP_SIZE, EFUSE_USAGE_MAP_START,
347 		  EFUSE_USAGE_MAP_END));
348 	eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock);
349 
350 	return 0;
351 }
352