1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
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 *****************************************************************************/
15 #define _RTW_EEPROM_C_
16
17 #include <drv_conf.h>
18 #include <osdep_service.h>
19 #include <drv_types.h>
20
up_clk(_adapter * padapter,u16 * x)21 void up_clk(_adapter *padapter, u16 *x)
22 {
23 *x = *x | _EESK;
24 rtw_write8(padapter, EE_9346CR, (u8)*x);
25 rtw_udelay_os(CLOCK_RATE);
26
27
28 }
29
down_clk(_adapter * padapter,u16 * x)30 void down_clk(_adapter *padapter, u16 *x)
31 {
32 *x = *x & ~_EESK;
33 rtw_write8(padapter, EE_9346CR, (u8)*x);
34 rtw_udelay_os(CLOCK_RATE);
35 }
36
shift_out_bits(_adapter * padapter,u16 data,u16 count)37 void shift_out_bits(_adapter *padapter, u16 data, u16 count)
38 {
39 u16 x, mask;
40
41 if (rtw_is_surprise_removed(padapter)) {
42 goto out;
43 }
44 mask = 0x01 << (count - 1);
45 x = rtw_read8(padapter, EE_9346CR);
46
47 x &= ~(_EEDO | _EEDI);
48
49 do {
50 x &= ~_EEDI;
51 if (data & mask)
52 x |= _EEDI;
53 if (rtw_is_surprise_removed(padapter)) {
54 goto out;
55 }
56 rtw_write8(padapter, EE_9346CR, (u8)x);
57 rtw_udelay_os(CLOCK_RATE);
58 up_clk(padapter, &x);
59 down_clk(padapter, &x);
60 mask = mask >> 1;
61 } while (mask);
62 if (rtw_is_surprise_removed(padapter)) {
63 goto out;
64 }
65 x &= ~_EEDI;
66 rtw_write8(padapter, EE_9346CR, (u8)x);
67 out:
68 return;
69 }
70
shift_in_bits(_adapter * padapter)71 u16 shift_in_bits(_adapter *padapter)
72 {
73 u16 x, d = 0, i;
74 if (rtw_is_surprise_removed(padapter)) {
75 goto out;
76 }
77 x = rtw_read8(padapter, EE_9346CR);
78
79 x &= ~(_EEDO | _EEDI);
80 d = 0;
81
82 for (i = 0; i < 16; i++) {
83 d = d << 1;
84 up_clk(padapter, &x);
85 if (rtw_is_surprise_removed(padapter)) {
86 goto out;
87 }
88 x = rtw_read8(padapter, EE_9346CR);
89
90 x &= ~(_EEDI);
91 if (x & _EEDO)
92 d |= 1;
93
94 down_clk(padapter, &x);
95 }
96 out:
97
98 return d;
99 }
100
standby(_adapter * padapter)101 void standby(_adapter *padapter)
102 {
103 u8 x;
104 x = rtw_read8(padapter, EE_9346CR);
105
106 x &= ~(_EECS | _EESK);
107 rtw_write8(padapter, EE_9346CR, x);
108
109 rtw_udelay_os(CLOCK_RATE);
110 x |= _EECS;
111 rtw_write8(padapter, EE_9346CR, x);
112 rtw_udelay_os(CLOCK_RATE);
113 }
114
wait_eeprom_cmd_done(_adapter * padapter)115 u16 wait_eeprom_cmd_done(_adapter *padapter)
116 {
117 u8 x;
118 u16 i, res = _FALSE;
119 standby(padapter);
120 for (i = 0; i < 200; i++) {
121 x = rtw_read8(padapter, EE_9346CR);
122 if (x & _EEDO) {
123 res = _TRUE;
124 goto exit;
125 }
126 rtw_udelay_os(CLOCK_RATE);
127 }
128 exit:
129 return res;
130 }
131
eeprom_clean(_adapter * padapter)132 void eeprom_clean(_adapter *padapter)
133 {
134 u16 x;
135 if (rtw_is_surprise_removed(padapter)) {
136 goto out;
137 }
138 x = rtw_read8(padapter, EE_9346CR);
139 if (rtw_is_surprise_removed(padapter)) {
140 goto out;
141 }
142 x &= ~(_EECS | _EEDI);
143 rtw_write8(padapter, EE_9346CR, (u8)x);
144 if (rtw_is_surprise_removed(padapter)) {
145 goto out;
146 }
147 up_clk(padapter, &x);
148 if (rtw_is_surprise_removed(padapter)) {
149 goto out;
150 }
151 down_clk(padapter, &x);
152 out:
153 return;
154 }
155
eeprom_write16(_adapter * padapter,u16 reg,u16 data)156 void eeprom_write16(_adapter *padapter, u16 reg, u16 data)
157 {
158 u8 x;
159 x = rtw_read8(padapter, EE_9346CR);
160
161 x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
162 x |= _EEM1 | _EECS;
163 rtw_write8(padapter, EE_9346CR, x);
164
165 shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
166
167 if (padapter->EepromAddressSize == 8) /* CF+ and SDIO */
168 shift_out_bits(padapter, 0, 6);
169 else /* USB */
170 shift_out_bits(padapter, 0, 4);
171
172 standby(padapter);
173
174 /* Commented out by rcnjko, 2004.0
175 * Erase this particular word. Write the erase opcode and register
176 * number in that order. The opcode is 3bits in length; reg is 6 bits long. */
177 /* shift_out_bits(Adapter, EEPROM_ERASE_OPCODE, 3);
178 * shift_out_bits(Adapter, reg, Adapter->EepromAddressSize);
179 *
180 * if (wait_eeprom_cmd_done(Adapter ) == FALSE)
181 * {
182 * return;
183 * } */
184
185
186 standby(padapter);
187
188 /* write the new word to the EEPROM */
189
190 /* send the write opcode the EEPORM */
191 shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
192
193 /* select which word in the EEPROM that we are writing to. */
194 shift_out_bits(padapter, reg, padapter->EepromAddressSize);
195
196 /* write the data to the selected EEPROM word. */
197 shift_out_bits(padapter, data, 16);
198
199 if (wait_eeprom_cmd_done(padapter) == _FALSE)
200
201 goto exit;
202
203 standby(padapter);
204
205 shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
206 shift_out_bits(padapter, reg, 4);
207
208 eeprom_clean(padapter);
209 exit:
210 return;
211 }
212
eeprom_read16(_adapter * padapter,u16 reg)213 u16 eeprom_read16(_adapter *padapter, u16 reg) /* ReadEEprom */
214 {
215
216 u16 x;
217 u16 data = 0;
218
219 if (rtw_is_surprise_removed(padapter)) {
220 goto out;
221 }
222 /* select EEPROM, reset bits, set _EECS */
223 x = rtw_read8(padapter, EE_9346CR);
224
225 if (rtw_is_surprise_removed(padapter)) {
226 goto out;
227 }
228
229 x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
230 x |= _EEM1 | _EECS;
231 rtw_write8(padapter, EE_9346CR, (unsigned char)x);
232
233 /* write the read opcode and register number in that order */
234 /* The opcode is 3bits in length, reg is 6 bits long */
235 shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
236 shift_out_bits(padapter, reg, padapter->EepromAddressSize);
237
238 /* Now read the data (16 bits) in from the selected EEPROM word */
239 data = shift_in_bits(padapter);
240
241 eeprom_clean(padapter);
242 out:
243
244 return data;
245
246
247 }
248
249
250
251
252 /* From even offset */
eeprom_read_sz(_adapter * padapter,u16 reg,u8 * data,u32 sz)253 void eeprom_read_sz(_adapter *padapter, u16 reg, u8 *data, u32 sz)
254 {
255
256 u16 x, data16;
257 u32 i;
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
278 for (i = 0; i < sz; i += 2) {
279 data16 = shift_in_bits(padapter);
280 data[i] = data16 & 0xff;
281 data[i + 1] = data16 >> 8;
282 }
283
284 eeprom_clean(padapter);
285 out:
286 return;
287 }
288
289
290 /* addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg) */
eeprom_read(_adapter * padapter,u32 addr_off,u8 sz,u8 * rbuf)291 u8 eeprom_read(_adapter *padapter, u32 addr_off, u8 sz, u8 *rbuf)
292 {
293 u8 quotient, remainder, addr_2align_odd;
294 u16 reg, stmp , i = 0, idx = 0;
295 reg = (u16)(addr_off >> 1);
296 addr_2align_odd = (u8)(addr_off & 0x1);
297
298 if (addr_2align_odd) { /* read that start at high part: e.g 1,3,5,7,9,... */
299 stmp = eeprom_read16(padapter, reg);
300 rbuf[idx++] = (u8)((stmp >> 8) & 0xff); /* return hogh-part of the short */
301 reg++;
302 sz--;
303 }
304
305 quotient = sz >> 1;
306 remainder = sz & 0x1;
307
308 for (i = 0 ; i < quotient; i++) {
309 stmp = eeprom_read16(padapter, reg + i);
310 rbuf[idx++] = (u8)(stmp & 0xff);
311 rbuf[idx++] = (u8)((stmp >> 8) & 0xff);
312 }
313
314 reg = reg + i;
315 if (remainder) { /* end of read at lower part of short : 0,2,4,6,... */
316 stmp = eeprom_read16(padapter, reg);
317 rbuf[idx] = (u8)(stmp & 0xff);
318 }
319 return _TRUE;
320 }
321
322
323
read_eeprom_content(_adapter * padapter)324 void read_eeprom_content(_adapter *padapter)
325 {
326
327
328
329 }
330