net: wireless: rockchip_wlan: add rtl8723cs support
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723cs / core / rtw_eeprom.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTW_EEPROM_C_
21
22 #include <drv_conf.h>
23 #include <osdep_service.h>
24 #include <drv_types.h>
25
26 void up_clk(_adapter    *padapter,       u16 *x)
27 {
28         *x = *x | _EESK;
29         rtw_write8(padapter, EE_9346CR, (u8)*x);
30         rtw_udelay_os(CLOCK_RATE);
31
32
33 }
34
35 void down_clk(_adapter  *padapter, u16 *x)
36 {
37         *x = *x & ~_EESK;
38         rtw_write8(padapter, EE_9346CR, (u8)*x);
39         rtw_udelay_os(CLOCK_RATE);
40 }
41
42 void shift_out_bits(_adapter *padapter, u16 data, u16 count)
43 {
44         u16 x, mask;
45
46         if (rtw_is_surprise_removed(padapter)) {
47                 goto out;
48         }
49         mask = 0x01 << (count - 1);
50         x = rtw_read8(padapter, EE_9346CR);
51
52         x &= ~(_EEDO | _EEDI);
53
54         do {
55                 x &= ~_EEDI;
56                 if (data & mask)
57                         x |= _EEDI;
58                 if (rtw_is_surprise_removed(padapter)) {
59                         goto out;
60                 }
61                 rtw_write8(padapter, EE_9346CR, (u8)x);
62                 rtw_udelay_os(CLOCK_RATE);
63                 up_clk(padapter, &x);
64                 down_clk(padapter, &x);
65                 mask = mask >> 1;
66         } while (mask);
67         if (rtw_is_surprise_removed(padapter)) {
68                 goto out;
69         }
70         x &= ~_EEDI;
71         rtw_write8(padapter, EE_9346CR, (u8)x);
72 out:
73         return;
74 }
75
76 u16 shift_in_bits(_adapter *padapter)
77 {
78         u16 x, d = 0, i;
79         if (rtw_is_surprise_removed(padapter)) {
80                 goto out;
81         }
82         x = rtw_read8(padapter, EE_9346CR);
83
84         x &= ~(_EEDO | _EEDI);
85         d = 0;
86
87         for (i = 0; i < 16; i++) {
88                 d = d << 1;
89                 up_clk(padapter, &x);
90                 if (rtw_is_surprise_removed(padapter)) {
91                         goto out;
92                 }
93                 x = rtw_read8(padapter, EE_9346CR);
94
95                 x &= ~(_EEDI);
96                 if (x & _EEDO)
97                         d |= 1;
98
99                 down_clk(padapter, &x);
100         }
101 out:
102
103         return d;
104 }
105
106 void standby(_adapter   *padapter)
107 {
108         u8   x;
109         x = rtw_read8(padapter, EE_9346CR);
110
111         x &= ~(_EECS | _EESK);
112         rtw_write8(padapter, EE_9346CR, x);
113
114         rtw_udelay_os(CLOCK_RATE);
115         x |= _EECS;
116         rtw_write8(padapter, EE_9346CR, x);
117         rtw_udelay_os(CLOCK_RATE);
118 }
119
120 u16 wait_eeprom_cmd_done(_adapter *padapter)
121 {
122         u8      x;
123         u16     i, res = _FALSE;
124         standby(padapter);
125         for (i = 0; i < 200; i++) {
126                 x = rtw_read8(padapter, EE_9346CR);
127                 if (x & _EEDO) {
128                         res = _TRUE;
129                         goto exit;
130                 }
131                 rtw_udelay_os(CLOCK_RATE);
132         }
133 exit:
134         return res;
135 }
136
137 void eeprom_clean(_adapter *padapter)
138 {
139         u16 x;
140         if (rtw_is_surprise_removed(padapter)) {
141                 goto out;
142         }
143         x = rtw_read8(padapter, EE_9346CR);
144         if (rtw_is_surprise_removed(padapter)) {
145                 goto out;
146         }
147         x &= ~(_EECS | _EEDI);
148         rtw_write8(padapter, EE_9346CR, (u8)x);
149         if (rtw_is_surprise_removed(padapter)) {
150                 goto out;
151         }
152         up_clk(padapter, &x);
153         if (rtw_is_surprise_removed(padapter)) {
154                 goto out;
155         }
156         down_clk(padapter, &x);
157 out:
158         return;
159 }
160
161 void eeprom_write16(_adapter *padapter, u16 reg, u16 data)
162 {
163         u8 x;
164 #ifdef CONFIG_RTL8712
165         u8      tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
166         tmp8_ori = rtw_read8(padapter, 0x102502f1);
167         tmp8_new = tmp8_ori & 0xf7;
168         if (tmp8_ori != tmp8_new) {
169                 rtw_write8(padapter, 0x102502f1, tmp8_new);
170         }
171         tmp8_clk_ori = rtw_read8(padapter, 0x10250003);
172         tmp8_clk_new = tmp8_clk_ori | 0x20;
173         if (tmp8_clk_new != tmp8_clk_ori) {
174                 rtw_write8(padapter, 0x10250003, tmp8_clk_new);
175         }
176 #endif
177
178         x = rtw_read8(padapter, EE_9346CR);
179
180         x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
181         x |= _EEM1 | _EECS;
182         rtw_write8(padapter, EE_9346CR, x);
183
184         shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
185
186         if (padapter->EepromAddressSize == 8)   /* CF+ and SDIO */
187                 shift_out_bits(padapter, 0, 6);
188         else                                                                    /* USB */
189                 shift_out_bits(padapter, 0, 4);
190
191         standby(padapter);
192
193         /* Commented out by rcnjko, 2004.0
194          *        Erase this particular word.  Write the erase opcode and register
195          *    number in that order. The opcode is 3bits in length; reg is 6 bits long. */
196 /*      shift_out_bits(Adapter, EEPROM_ERASE_OPCODE, 3);
197  *      shift_out_bits(Adapter, reg, Adapter->EepromAddressSize);
198  *
199  *      if (wait_eeprom_cmd_done(Adapter ) == FALSE)
200  *      {
201  *              return;
202  *      } */
203
204
205         standby(padapter);
206
207         /* write the new word to the EEPROM */
208
209         /* send the write opcode the EEPORM */
210         shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
211
212         /* select which word in the EEPROM that we are writing to. */
213         shift_out_bits(padapter, reg, padapter->EepromAddressSize);
214
215         /* write the data to the selected EEPROM word. */
216         shift_out_bits(padapter, data, 16);
217
218         if (wait_eeprom_cmd_done(padapter) == _FALSE)
219
220                 goto exit;
221
222         standby(padapter);
223
224         shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
225         shift_out_bits(padapter, reg, 4);
226
227         eeprom_clean(padapter);
228 exit:
229 #ifdef CONFIG_RTL8712
230         if (tmp8_clk_new != tmp8_clk_ori)
231                 rtw_write8(padapter, 0x10250003, tmp8_clk_ori);
232         if (tmp8_new != tmp8_ori)
233                 rtw_write8(padapter, 0x102502f1, tmp8_ori);
234
235 #endif
236         return;
237 }
238
239 u16 eeprom_read16(_adapter *padapter, u16 reg)  /* ReadEEprom */
240 {
241
242         u16 x;
243         u16 data = 0;
244 #ifdef CONFIG_RTL8712
245         u8      tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
246         tmp8_ori = rtw_read8(padapter, 0x102502f1);
247         tmp8_new = tmp8_ori & 0xf7;
248         if (tmp8_ori != tmp8_new) {
249                 rtw_write8(padapter, 0x102502f1, tmp8_new);
250         }
251         tmp8_clk_ori = rtw_read8(padapter, 0x10250003);
252         tmp8_clk_new = tmp8_clk_ori | 0x20;
253         if (tmp8_clk_new != tmp8_clk_ori) {
254                 rtw_write8(padapter, 0x10250003, tmp8_clk_new);
255         }
256 #endif
257
258         if (rtw_is_surprise_removed(padapter)) {
259                 goto out;
260         }
261         /* select EEPROM, reset bits, set _EECS */
262         x = rtw_read8(padapter, EE_9346CR);
263
264         if (rtw_is_surprise_removed(padapter)) {
265                 goto out;
266         }
267
268         x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
269         x |= _EEM1 | _EECS;
270         rtw_write8(padapter, EE_9346CR, (unsigned char)x);
271
272         /* write the read opcode and register number in that order */
273         /* The opcode is 3bits in length, reg is 6 bits long */
274         shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
275         shift_out_bits(padapter, reg, padapter->EepromAddressSize);
276
277         /* Now read the data (16 bits) in from the selected EEPROM word */
278         data = shift_in_bits(padapter);
279
280         eeprom_clean(padapter);
281 out:
282 #ifdef CONFIG_RTL8712
283         if (tmp8_clk_new != tmp8_clk_ori)
284                 rtw_write8(padapter, 0x10250003, tmp8_clk_ori);
285         if (tmp8_new != tmp8_ori)
286                 rtw_write8(padapter, 0x102502f1, tmp8_ori);
287
288 #endif
289         return data;
290
291
292 }
293
294
295
296
297 /* From even offset */
298 void eeprom_read_sz(_adapter *padapter, u16 reg, u8 *data, u32 sz)
299 {
300
301         u16 x, data16;
302         u32 i;
303         if (rtw_is_surprise_removed(padapter)) {
304                 goto out;
305         }
306         /* select EEPROM, reset bits, set _EECS */
307         x = rtw_read8(padapter, EE_9346CR);
308
309         if (rtw_is_surprise_removed(padapter)) {
310                 goto out;
311         }
312
313         x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
314         x |= _EEM1 | _EECS;
315         rtw_write8(padapter, EE_9346CR, (unsigned char)x);
316
317         /* write the read opcode and register number in that order */
318         /* The opcode is 3bits in length, reg is 6 bits long */
319         shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
320         shift_out_bits(padapter, reg, padapter->EepromAddressSize);
321
322
323         for (i = 0; i < sz; i += 2) {
324                 data16 = shift_in_bits(padapter);
325                 data[i] = data16 & 0xff;
326                 data[i + 1] = data16 >> 8;
327         }
328
329         eeprom_clean(padapter);
330 out:
331         return;
332 }
333
334
335 /* addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg) */
336 u8 eeprom_read(_adapter *padapter, u32 addr_off, u8 sz, u8 *rbuf)
337 {
338         u8 quotient, remainder, addr_2align_odd;
339         u16 reg, stmp , i = 0, idx = 0;
340         reg = (u16)(addr_off >> 1);
341         addr_2align_odd = (u8)(addr_off & 0x1);
342
343         if (addr_2align_odd) { /* read that start at high part: e.g  1,3,5,7,9,... */
344                 stmp = eeprom_read16(padapter, reg);
345                 rbuf[idx++] = (u8)((stmp >> 8) & 0xff); /* return hogh-part of the short */
346                 reg++;
347                 sz--;
348         }
349
350         quotient = sz >> 1;
351         remainder = sz & 0x1;
352
353         for (i = 0 ; i < quotient; i++) {
354                 stmp = eeprom_read16(padapter, reg + i);
355                 rbuf[idx++] = (u8)(stmp & 0xff);
356                 rbuf[idx++] = (u8)((stmp >> 8) & 0xff);
357         }
358
359         reg = reg + i;
360         if (remainder) { /* end of read at lower part of short : 0,2,4,6,... */
361                 stmp = eeprom_read16(padapter, reg);
362                 rbuf[idx] = (u8)(stmp & 0xff);
363         }
364         return _TRUE;
365 }
366
367
368
369 VOID read_eeprom_content(_adapter       *padapter)
370 {
371
372
373
374 }