• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/rt2860/common/
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
49typedef 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*/
76u8 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*/
152void 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*/
217static 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*/
247int 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("efuseFreeNumber is %d\n", efusefreenum);
268	return TRUE;
269}
270
271int 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	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
290int rtmp_ee_efuse_read16(struct rt_rtmp_adapter *pAd,
291			 u16 Offset, u16 * pValue)
292{
293	eFuseReadRegisters(pAd, Offset, 2, pValue);
294	return (*pValue);
295}
296
297int RtmpEfuseSupportCheck(struct rt_rtmp_adapter *pAd)
298{
299	u16 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
308void eFuseGetFreeBlockCount(struct rt_rtmp_adapter *pAd, u32 *EfuseFreeBlock)
309{
310	u16 i;
311	u16 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 = (u8)(EFUSE_USAGE_MAP_END - i + 1);
321			break;
322		} else if (((LogicalAddress >> 8) & 0xff) == 0) {
323			*EfuseFreeBlock = (u8)(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
334int eFuse_init(struct rt_rtmp_adapter *pAd)
335{
336	u32 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}
345