Staging: add rt2860 wireless driver
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / rt2860 / common / eeprom.c
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 eeprom.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 Name Date Modification logs
36 */
37 #include "../rt_config.h"
38
39 // IRQL = PASSIVE_LEVEL
40 VOID RaiseClock(
41 IN PRTMP_ADAPTER pAd,
42 IN UINT32 *x)
43 {
44 *x = *x | EESK;
45 RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
46 RTMPusecDelay(1); // Max frequency = 1MHz in Spec. definition
47 }
48
49 // IRQL = PASSIVE_LEVEL
50 VOID LowerClock(
51 IN PRTMP_ADAPTER pAd,
52 IN UINT32 *x)
53 {
54 *x = *x & ~EESK;
55 RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
56 RTMPusecDelay(1);
57 }
58
59 // IRQL = PASSIVE_LEVEL
60 USHORT ShiftInBits(
61 IN PRTMP_ADAPTER pAd)
62 {
63 UINT32 x,i;
64 USHORT data=0;
65
66 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
67
68 x &= ~( EEDO | EEDI);
69
70 for(i=0; i<16; i++)
71 {
72 data = data << 1;
73 RaiseClock(pAd, &x);
74
75 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
76
77 x &= ~(EEDI);
78 if(x & EEDO)
79 data |= 1;
80
81 LowerClock(pAd, &x);
82 }
83
84 return data;
85 }
86
87 // IRQL = PASSIVE_LEVEL
88 VOID ShiftOutBits(
89 IN PRTMP_ADAPTER pAd,
90 IN USHORT data,
91 IN USHORT count)
92 {
93 UINT32 x,mask;
94
95 mask = 0x01 << (count - 1);
96 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
97
98 x &= ~(EEDO | EEDI);
99
100 do
101 {
102 x &= ~EEDI;
103 if(data & mask) x |= EEDI;
104
105 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
106
107 RaiseClock(pAd, &x);
108 LowerClock(pAd, &x);
109
110 mask = mask >> 1;
111 } while(mask);
112
113 x &= ~EEDI;
114 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
115 }
116
117 // IRQL = PASSIVE_LEVEL
118 VOID EEpromCleanup(
119 IN PRTMP_ADAPTER pAd)
120 {
121 UINT32 x;
122
123 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
124
125 x &= ~(EECS | EEDI);
126 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
127
128 RaiseClock(pAd, &x);
129 LowerClock(pAd, &x);
130 }
131
132 VOID EWEN(
133 IN PRTMP_ADAPTER pAd)
134 {
135 UINT32 x;
136
137 // reset bits and set EECS
138 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
139 x &= ~(EEDI | EEDO | EESK);
140 x |= EECS;
141 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
142
143 // kick a pulse
144 RaiseClock(pAd, &x);
145 LowerClock(pAd, &x);
146
147 // output the read_opcode and six pulse in that order
148 ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
149 ShiftOutBits(pAd, 0, 6);
150
151 EEpromCleanup(pAd);
152 }
153
154 VOID EWDS(
155 IN PRTMP_ADAPTER pAd)
156 {
157 UINT32 x;
158
159 // reset bits and set EECS
160 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
161 x &= ~(EEDI | EEDO | EESK);
162 x |= EECS;
163 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
164
165 // kick a pulse
166 RaiseClock(pAd, &x);
167 LowerClock(pAd, &x);
168
169 // output the read_opcode and six pulse in that order
170 ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
171 ShiftOutBits(pAd, 0, 6);
172
173 EEpromCleanup(pAd);
174 }
175
176 // IRQL = PASSIVE_LEVEL
177 USHORT RTMP_EEPROM_READ16(
178 IN PRTMP_ADAPTER pAd,
179 IN USHORT Offset)
180 {
181 UINT32 x;
182 USHORT data;
183
184 Offset /= 2;
185 // reset bits and set EECS
186 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
187 x &= ~(EEDI | EEDO | EESK);
188 x |= EECS;
189 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
190
191 // kick a pulse
192 RaiseClock(pAd, &x);
193 LowerClock(pAd, &x);
194
195 // output the read_opcode and register number in that order
196 ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
197 ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
198
199 // Now read the data (16 bits) in from the selected EEPROM word
200 data = ShiftInBits(pAd);
201
202 EEpromCleanup(pAd);
203
204 return data;
205 } //ReadEEprom
206
207 VOID RTMP_EEPROM_WRITE16(
208 IN PRTMP_ADAPTER pAd,
209 IN USHORT Offset,
210 IN USHORT Data)
211 {
212 UINT32 x;
213
214 Offset /= 2;
215
216 EWEN(pAd);
217
218 // reset bits and set EECS
219 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
220 x &= ~(EEDI | EEDO | EESK);
221 x |= EECS;
222 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
223
224 // kick a pulse
225 RaiseClock(pAd, &x);
226 LowerClock(pAd, &x);
227
228 // output the read_opcode ,register number and data in that order
229 ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3);
230 ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
231 ShiftOutBits(pAd, Data, 16); // 16-bit access
232
233 // read DO status
234 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
235
236 EEpromCleanup(pAd);
237
238 RTMPusecDelay(10000); //delay for twp(MAX)=10ms
239
240 EWDS(pAd);
241
242 EEpromCleanup(pAd);
243 }
244