- supported.conf: Added sparse_keymap (eeepc_laptop depends on it)
[linux-flexiantxendom0-3.2.10.git] / drivers / staging / rt3090 / common / ee_prom.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         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
41 // IRQL = PASSIVE_LEVEL
42 static inline VOID RaiseClock(
43     IN  PRTMP_ADAPTER   pAd,
44     IN  UINT32 *x)
45 {
46         *x = *x | EESK;
47         RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
48         RTMPusecDelay(1);                               // Max frequency = 1MHz in Spec. definition
49 }
50
51 // IRQL = PASSIVE_LEVEL
52 static inline VOID LowerClock(
53     IN  PRTMP_ADAPTER   pAd,
54     IN  UINT32 *x)
55 {
56         *x = *x & ~EESK;
57         RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
58         RTMPusecDelay(1);
59 }
60
61 // IRQL = PASSIVE_LEVEL
62 static inline USHORT ShiftInBits(
63         IN PRTMP_ADAPTER        pAd)
64 {
65         UINT32          x,i;
66         USHORT      data=0;
67
68         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
69
70         x &= ~( EEDO | EEDI);
71
72         for(i=0; i<16; i++)
73         {
74                 data = data << 1;
75                 RaiseClock(pAd, &x);
76
77                 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
78                 LowerClock(pAd, &x); //prevent read failed
79
80                 x &= ~(EEDI);
81                 if(x & EEDO)
82                     data |= 1;
83         }
84
85         return data;
86 }
87
88
89 // IRQL = PASSIVE_LEVEL
90 static inline VOID ShiftOutBits(
91         IN PRTMP_ADAPTER        pAd,
92         IN USHORT                       data,
93         IN USHORT                       count)
94 {
95         UINT32       x,mask;
96
97         mask = 0x01 << (count - 1);
98         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
99
100         x &= ~(EEDO | EEDI);
101
102         do
103         {
104             x &= ~EEDI;
105             if(data & mask)             x |= EEDI;
106
107             RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
108
109             RaiseClock(pAd, &x);
110             LowerClock(pAd, &x);
111
112             mask = mask >> 1;
113         } while(mask);
114
115         x &= ~EEDI;
116         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
117 }
118
119
120 // IRQL = PASSIVE_LEVEL
121 static inline VOID EEpromCleanup(
122         IN PRTMP_ADAPTER        pAd)
123 {
124         UINT32 x;
125
126         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
127
128         x &= ~(EECS | EEDI);
129         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
130
131         RaiseClock(pAd, &x);
132         LowerClock(pAd, &x);
133 }
134
135
136 static inline VOID EWEN(
137         IN PRTMP_ADAPTER        pAd)
138 {
139         UINT32  x;
140
141         // reset bits and set EECS
142         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
143         x &= ~(EEDI | EEDO | EESK);
144         x |= EECS;
145         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
146
147         // kick a pulse
148         RaiseClock(pAd, &x);
149         LowerClock(pAd, &x);
150
151         // output the read_opcode and six pulse in that order
152         ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
153         ShiftOutBits(pAd, 0, 6);
154
155         EEpromCleanup(pAd);
156 }
157
158
159 static inline VOID EWDS(
160         IN PRTMP_ADAPTER        pAd)
161 {
162         UINT32  x;
163
164         // reset bits and set EECS
165         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
166         x &= ~(EEDI | EEDO | EESK);
167         x |= EECS;
168         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
169
170         // kick a pulse
171         RaiseClock(pAd, &x);
172         LowerClock(pAd, &x);
173
174         // output the read_opcode and six pulse in that order
175         ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
176         ShiftOutBits(pAd, 0, 6);
177
178         EEpromCleanup(pAd);
179 }
180
181
182 // IRQL = PASSIVE_LEVEL
183 int rtmp_ee_prom_read16(
184         IN PRTMP_ADAPTER        pAd,
185         IN USHORT                       Offset,
186         OUT USHORT                      *pValue)
187 {
188         UINT32          x;
189         USHORT          data;
190
191 #ifdef RT30xx
192 #ifdef ANT_DIVERSITY_SUPPORT
193         if (pAd->NicConfig2.field.AntDiversity)
194         {
195                 pAd->EepromAccess = TRUE;
196         }
197 #endif // ANT_DIVERSITY_SUPPORT //
198 #endif // RT30xx //
199
200         Offset /= 2;
201         // reset bits and set EECS
202         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
203         x &= ~(EEDI | EEDO | EESK);
204         x |= EECS;
205         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
206
207         // patch can not access e-Fuse issue
208         if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)))
209         {
210                 // kick a pulse
211                 RaiseClock(pAd, &x);
212                 LowerClock(pAd, &x);
213         }
214
215         // output the read_opcode and register number in that order
216         ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
217         ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
218
219         // Now read the data (16 bits) in from the selected EEPROM word
220         data = ShiftInBits(pAd);
221
222         EEpromCleanup(pAd);
223
224 #ifdef RT30xx
225 #ifdef ANT_DIVERSITY_SUPPORT
226         // Antenna and EEPROM access are both using EESK pin,
227         // Therefor we should avoid accessing EESK at the same time
228         // Then restore antenna after EEPROM access
229         if ((pAd->NicConfig2.field.AntDiversity)/* || (pAd->RfIcType == RFIC_3020)*/)
230         {
231                 pAd->EepromAccess = FALSE;
232                 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
233         }
234 #endif // ANT_DIVERSITY_SUPPORT //
235 #endif // RT30xx //
236
237         *pValue = data;
238
239         return NDIS_STATUS_SUCCESS;
240 }
241
242
243 int rtmp_ee_prom_write16(
244     IN  PRTMP_ADAPTER   pAd,
245     IN  USHORT Offset,
246     IN  USHORT Data)
247 {
248         UINT32 x;
249
250 #ifdef RT30xx
251 #ifdef ANT_DIVERSITY_SUPPORT
252         if (pAd->NicConfig2.field.AntDiversity)
253         {
254                 pAd->EepromAccess = TRUE;
255         }
256 #endif // ANT_DIVERSITY_SUPPORT //
257 #endif // RT30xx //
258
259         Offset /= 2;
260
261         EWEN(pAd);
262
263         // reset bits and set EECS
264         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
265         x &= ~(EEDI | EEDO | EESK);
266         x |= EECS;
267         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
268
269         // patch can not access e-Fuse issue
270         if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)))
271         {
272                 // kick a pulse
273                 RaiseClock(pAd, &x);
274                 LowerClock(pAd, &x);
275         }
276
277         // output the read_opcode ,register number and data in that order
278         ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3);
279         ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
280         ShiftOutBits(pAd, Data, 16);            // 16-bit access
281
282         // read DO status
283         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
284
285         EEpromCleanup(pAd);
286
287         RTMPusecDelay(10000);   //delay for twp(MAX)=10ms
288
289         EWDS(pAd);
290
291         EEpromCleanup(pAd);
292
293 #ifdef RT30xx
294 #ifdef ANT_DIVERSITY_SUPPORT
295         // Antenna and EEPROM access are both using EESK pin,
296         // Therefor we should avoid accessing EESK at the same time
297         // Then restore antenna after EEPROM access
298         if ((pAd->NicConfig2.field.AntDiversity) /*|| (pAd->RfIcType == RFIC_3020)*/)
299         {
300                 pAd->EepromAccess = FALSE;
301                 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
302         }
303 #endif // ANT_DIVERSITY_SUPPORT //
304 #endif // RT30xx //
305
306         return NDIS_STATUS_SUCCESS;
307
308 }