- patches.suse/slab-handle-memoryless-nodes-v2a.patch: Refresh.
[linux-flexiantxendom0-3.2.10.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 #include        "../rt_config.h"
39
40 /* IRQL = PASSIVE_LEVEL */
41 static 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 */
49 static 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 */
57 static 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 */
82 static 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 */
110 static 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
123 static 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
144 static 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 */
166 int 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 }