• 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_prom.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/* IRQL = PASSIVE_LEVEL */
41static inline void RaiseClock(struct rt_rtmp_adapter *pAd, u32 * x)
42{
43	*x = *x | EESK;
44	RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
45	RTMPusecDelay(1);	/* Max frequency = 1MHz in Spec. definition */
46}
47
48/* IRQL = PASSIVE_LEVEL */
49static inline void LowerClock(struct rt_rtmp_adapter *pAd, u32 * x)
50{
51	*x = *x & ~EESK;
52	RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
53	RTMPusecDelay(1);
54}
55
56/* IRQL = PASSIVE_LEVEL */
57static inline u16 ShiftInBits(struct rt_rtmp_adapter *pAd)
58{
59	u32 x, i;
60	u16 data = 0;
61
62	RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
63
64	x &= ~(EEDO | EEDI);
65
66	for (i = 0; i < 16; i++) {
67		data = data << 1;
68		RaiseClock(pAd, &x);
69
70		RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
71		LowerClock(pAd, &x);	/*prevent read failed */
72
73		x &= ~(EEDI);
74		if (x & EEDO)
75			data |= 1;
76	}
77
78	return data;
79}
80
81/* IRQL = PASSIVE_LEVEL */
82static inline void ShiftOutBits(struct rt_rtmp_adapter *pAd,
83				u16 data, u16 count)
84{
85	u32 x, mask;
86
87	mask = 0x01 << (count - 1);
88	RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
89
90	x &= ~(EEDO | EEDI);
91
92	do {
93		x &= ~EEDI;
94		if (data & mask)
95			x |= EEDI;
96
97		RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
98
99		RaiseClock(pAd, &x);
100		LowerClock(pAd, &x);
101
102		mask = mask >> 1;
103	} while (mask);
104
105	x &= ~EEDI;
106	RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
107}
108
109/* IRQL = PASSIVE_LEVEL */
110static inline void EEpromCleanup(struct rt_rtmp_adapter *pAd)
111{
112	u32 x;
113
114	RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
115
116	x &= ~(EECS | EEDI);
117	RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
118
119	RaiseClock(pAd, &x);
120	LowerClock(pAd, &x);
121}
122
123static inline void EWEN(struct rt_rtmp_adapter *pAd)
124{
125	u32 x;
126
127	/* reset bits and set EECS */
128	RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
129	x &= ~(EEDI | EEDO | EESK);
130	x |= EECS;
131	RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
132
133	/* kick a pulse */
134	RaiseClock(pAd, &x);
135	LowerClock(pAd, &x);
136
137	/* output the read_opcode and six pulse in that order */
138	ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
139	ShiftOutBits(pAd, 0, 6);
140
141	EEpromCleanup(pAd);
142}
143
144static inline void EWDS(struct rt_rtmp_adapter *pAd)
145{
146	u32 x;
147
148	/* reset bits and set EECS */
149	RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
150	x &= ~(EEDI | EEDO | EESK);
151	x |= EECS;
152	RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
153
154	/* kick a pulse */
155	RaiseClock(pAd, &x);
156	LowerClock(pAd, &x);
157
158	/* output the read_opcode and six pulse in that order */
159	ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
160	ShiftOutBits(pAd, 0, 6);
161
162	EEpromCleanup(pAd);
163}
164
165/* IRQL = PASSIVE_LEVEL */
166int rtmp_ee_prom_read16(struct rt_rtmp_adapter *pAd,
167			u16 Offset, u16 * pValue)
168{
169	u32 x;
170	u16 data;
171
172	Offset /= 2;
173	/* reset bits and set EECS */
174	RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
175	x &= ~(EEDI | EEDO | EESK);
176	x |= EECS;
177	RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
178
179	/* patch can not access e-Fuse issue */
180	if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) {
181		/* kick a pulse */
182		RaiseClock(pAd, &x);
183		LowerClock(pAd, &x);
184	}
185	/* output the read_opcode and register number in that order */
186	ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
187	ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
188
189	/* Now read the data (16 bits) in from the selected EEPROM word */
190	data = ShiftInBits(pAd);
191
192	EEpromCleanup(pAd);
193
194	*pValue = data;
195
196	return NDIS_STATUS_SUCCESS;
197}
198