xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8822cs/core/rtw_eeprom.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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