Staging: rt28x0: updates from vendor's V2.1.0.0 drivers
[pandora-kernel.git] / drivers / staging / rt2860 / 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
39 #include        "../rt_config.h"
40
41
42
43 // IRQL = PASSIVE_LEVEL
44 static inline VOID RaiseClock(
45     IN  PRTMP_ADAPTER   pAd,
46     IN  UINT32 *x)
47 {
48         *x = *x | EESK;
49         RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
50         RTMPusecDelay(1);                               // Max frequency = 1MHz in Spec. definition
51 }
52
53 // IRQL = PASSIVE_LEVEL
54 static inline VOID LowerClock(
55     IN  PRTMP_ADAPTER   pAd,
56     IN  UINT32 *x)
57 {
58         *x = *x & ~EESK;
59         RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
60         RTMPusecDelay(1);
61 }
62
63 // IRQL = PASSIVE_LEVEL
64 static inline USHORT ShiftInBits(
65         IN PRTMP_ADAPTER        pAd)
66 {
67         UINT32          x,i;
68         USHORT      data=0;
69
70         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
71
72         x &= ~( EEDO | EEDI);
73
74         for(i=0; i<16; i++)
75         {
76                 data = data << 1;
77                 RaiseClock(pAd, &x);
78
79                 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
80                 LowerClock(pAd, &x); //prevent read failed
81
82                 x &= ~(EEDI);
83                 if(x & EEDO)
84                     data |= 1;
85         }
86
87         return data;
88 }
89
90
91 // IRQL = PASSIVE_LEVEL
92 static inline VOID ShiftOutBits(
93         IN PRTMP_ADAPTER        pAd,
94         IN USHORT                       data,
95         IN USHORT                       count)
96 {
97         UINT32       x,mask;
98
99         mask = 0x01 << (count - 1);
100         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
101
102         x &= ~(EEDO | EEDI);
103
104         do
105         {
106             x &= ~EEDI;
107             if(data & mask)             x |= EEDI;
108
109             RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
110
111             RaiseClock(pAd, &x);
112             LowerClock(pAd, &x);
113
114             mask = mask >> 1;
115         } while(mask);
116
117         x &= ~EEDI;
118         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
119 }
120
121
122 // IRQL = PASSIVE_LEVEL
123 static inline VOID EEpromCleanup(
124         IN PRTMP_ADAPTER        pAd)
125 {
126         UINT32 x;
127
128         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
129
130         x &= ~(EECS | EEDI);
131         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
132
133         RaiseClock(pAd, &x);
134         LowerClock(pAd, &x);
135 }
136
137
138 static inline VOID EWEN(
139         IN PRTMP_ADAPTER        pAd)
140 {
141         UINT32  x;
142
143         // reset bits and set EECS
144         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
145         x &= ~(EEDI | EEDO | EESK);
146         x |= EECS;
147         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
148
149         // kick a pulse
150         RaiseClock(pAd, &x);
151         LowerClock(pAd, &x);
152
153         // output the read_opcode and six pulse in that order
154         ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
155         ShiftOutBits(pAd, 0, 6);
156
157         EEpromCleanup(pAd);
158 }
159
160
161 static inline VOID EWDS(
162         IN PRTMP_ADAPTER        pAd)
163 {
164         UINT32  x;
165
166         // reset bits and set EECS
167         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
168         x &= ~(EEDI | EEDO | EESK);
169         x |= EECS;
170         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
171
172         // kick a pulse
173         RaiseClock(pAd, &x);
174         LowerClock(pAd, &x);
175
176         // output the read_opcode and six pulse in that order
177         ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
178         ShiftOutBits(pAd, 0, 6);
179
180         EEpromCleanup(pAd);
181 }
182
183
184 // IRQL = PASSIVE_LEVEL
185 int rtmp_ee_prom_read16(
186         IN PRTMP_ADAPTER        pAd,
187         IN USHORT                       Offset,
188         OUT USHORT                      *pValue)
189 {
190         UINT32          x;
191         USHORT          data;
192
193
194         Offset /= 2;
195         // reset bits and set EECS
196         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
197         x &= ~(EEDI | EEDO | EESK);
198         x |= EECS;
199         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
200
201         // patch can not access e-Fuse issue
202         if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)))
203         {
204                 // kick a pulse
205                 RaiseClock(pAd, &x);
206                 LowerClock(pAd, &x);
207         }
208
209         // output the read_opcode and register number in that order
210         ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
211         ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
212
213         // Now read the data (16 bits) in from the selected EEPROM word
214         data = ShiftInBits(pAd);
215
216         EEpromCleanup(pAd);
217
218
219         *pValue = data;
220
221         return NDIS_STATUS_SUCCESS;
222 }
223
224
225 int rtmp_ee_prom_write16(
226     IN  PRTMP_ADAPTER   pAd,
227     IN  USHORT Offset,
228     IN  USHORT Data)
229 {
230         UINT32 x;
231
232
233         Offset /= 2;
234
235         EWEN(pAd);
236
237         // reset bits and set EECS
238         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
239         x &= ~(EEDI | EEDO | EESK);
240         x |= EECS;
241         RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
242
243         // patch can not access e-Fuse issue
244         if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)))
245         {
246                 // kick a pulse
247                 RaiseClock(pAd, &x);
248                 LowerClock(pAd, &x);
249         }
250
251         // output the read_opcode ,register number and data in that order
252         ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3);
253         ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
254         ShiftOutBits(pAd, Data, 16);            // 16-bit access
255
256         // read DO status
257         RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
258
259         EEpromCleanup(pAd);
260
261         RTMPusecDelay(10000);   //delay for twp(MAX)=10ms
262
263         EWDS(pAd);
264
265         EEpromCleanup(pAd);
266
267
268         return NDIS_STATUS_SUCCESS;
269
270 }