1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _RTW_EEPROM_C_
8 
9 #include <drv_conf.h>
10 #include <osdep_service.h>
11 #include <drv_types.h>
12 
up_clk(_adapter * padapter,u16 * x)13 void up_clk(_adapter *padapter,	 u16 *x)
14 {
15 _func_enter_;
16 	*x = *x | _EESK;
17 	rtw_write8(padapter, EE_9346CR, (u8)*x);
18 	udelay(CLOCK_RATE);
19 
20 _func_exit_;
21 
22 }
23 
down_clk(_adapter * padapter,u16 * x)24 void down_clk(_adapter *padapter, u16 *x)
25 {
26 _func_enter_;
27 	*x = *x & ~_EESK;
28 	rtw_write8(padapter, EE_9346CR, (u8)*x);
29 	udelay(CLOCK_RATE);
30 _func_exit_;
31 }
32 
shift_out_bits(_adapter * padapter,u16 data,u16 count)33 void shift_out_bits(_adapter *padapter, u16 data, u16 count)
34 {
35 	u16 x, mask;
36 _func_enter_;
37 
38 	if (padapter->bSurpriseRemoved == true) {
39 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
40 		goto out;
41 	}
42 	mask = 0x01 << (count - 1);
43 	x = rtw_read8(padapter, EE_9346CR);
44 
45 	x &= ~(_EEDO | _EEDI);
46 
47 	do {
48 		x &= ~_EEDI;
49 		if (data & mask)
50 			x |= _EEDI;
51 		if (padapter->bSurpriseRemoved == true) {
52 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
53 		goto out;
54 		}
55 		rtw_write8(padapter, EE_9346CR, (u8)x);
56 		udelay(CLOCK_RATE);
57 		up_clk(padapter, &x);
58 		down_clk(padapter, &x);
59 		mask = mask >> 1;
60 	} while (mask);
61 	if (padapter->bSurpriseRemoved == true) {
62 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
63 		goto out;
64 	}
65 	x &= ~_EEDI;
66 	rtw_write8(padapter, EE_9346CR, (u8)x);
67 out:
68 _func_exit_;
69 }
70 
shift_in_bits(_adapter * padapter)71 u16 shift_in_bits(_adapter *padapter)
72 {
73 	u16 x, d = 0, i;
74 _func_enter_;
75 	if (padapter->bSurpriseRemoved == true) {
76 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
77 		goto out;
78 	}
79 	x = rtw_read8(padapter, EE_9346CR);
80 
81 	x &= ~(_EEDO | _EEDI);
82 	d = 0;
83 
84 	for (i = 0; i < 16; i++) {
85 		d = d << 1;
86 		up_clk(padapter, &x);
87 	if (padapter->bSurpriseRemoved == true) {
88 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
89 		goto out;
90 	}
91 		x = rtw_read8(padapter, EE_9346CR);
92 
93 		x &= ~(_EEDI);
94 		if (x & _EEDO)
95 		d |= 1;
96 
97 		down_clk(padapter, &x);
98 	}
99 out:
100 _func_exit_;
101 
102 	return d;
103 }
104 
standby(_adapter * padapter)105 void standby(_adapter *padapter)
106 {
107 	u8   x;
108 _func_enter_;
109 	x = rtw_read8(padapter, EE_9346CR);
110 
111 	x &= ~(_EECS | _EESK);
112 	rtw_write8(padapter, EE_9346CR, x);
113 
114 	udelay(CLOCK_RATE);
115 	x |= _EECS;
116 	rtw_write8(padapter, EE_9346CR, x);
117 	udelay(CLOCK_RATE);
118 _func_exit_;
119 }
120 
eeprom_clean(_adapter * padapter)121 void eeprom_clean(_adapter *padapter)
122 {
123 	u16 x;
124 _func_enter_;
125 	if (padapter->bSurpriseRemoved == true) {
126 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
127 		goto out;
128 	}
129 	x = rtw_read8(padapter, EE_9346CR);
130 	if (padapter->bSurpriseRemoved == true) {
131 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
132 		goto out;
133 	}
134 	x &= ~(_EECS | _EEDI);
135 	rtw_write8(padapter, EE_9346CR, (u8)x);
136 	if (padapter->bSurpriseRemoved == true) {
137 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
138 		goto out;
139 	}
140 	up_clk(padapter, &x);
141 		if (padapter->bSurpriseRemoved == true) {
142 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
143 		goto out;
144 	}
145 	down_clk(padapter, &x);
146 out:
147 _func_exit_;
148 }
149 
eeprom_read16(_adapter * padapter,u16 reg)150 u16 eeprom_read16(_adapter *padapter, u16 reg) /*ReadEEprom*/
151 {
152 
153 	u16 x;
154 	u16 data = 0;
155 
156 _func_enter_;
157 
158 	if (padapter->bSurpriseRemoved == true) {
159 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
160 		goto out;
161 	}
162 	/* select EEPROM, reset bits, set _EECS*/
163 	x = rtw_read8(padapter, EE_9346CR);
164 
165 	if (padapter->bSurpriseRemoved == true) {
166 		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
167 		goto out;
168 	}
169 
170 	x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
171 	x |= _EEM1 | _EECS;
172 	rtw_write8(padapter, EE_9346CR, (unsigned char)x);
173 
174 	/* write the read opcode and register number in that order*/
175 	/* The opcode is 3bits in length, reg is 6 bits long*/
176 	shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
177 	shift_out_bits(padapter, reg, padapter->EepromAddressSize);
178 
179 	/* Now read the data (16 bits) in from the selected EEPROM word*/
180 	data = shift_in_bits(padapter);
181 
182 	eeprom_clean(padapter);
183 out:
184 _func_exit_;
185 	return data;
186 
187 
188 }
189 
190 /*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)191 u8 eeprom_read(_adapter *padapter, u32 addr_off, u8 sz, u8 *rbuf)
192 {
193 	u8 quotient, remainder, addr_2align_odd;
194 	u16 reg, stmp, i = 0, idx = 0;
195 _func_enter_;
196 	reg = (u16)(addr_off >> 1);
197 	addr_2align_odd = (u8)(addr_off & 0x1);
198 
199 	/*read that start at high part: e.g  1,3,5,7,9,...*/
200 	if (addr_2align_odd) {
201 		stmp = eeprom_read16(padapter, reg);
202 		rbuf[idx++] = (u8) ((stmp>>8)&0xff); /*return hogh-part of the short*/
203 		reg++; sz--;
204 	}
205 
206 	quotient = sz >> 1;
207 	remainder = sz & 0x1;
208 
209 	for (i = 0; i < quotient; i++) {
210 		stmp = eeprom_read16(padapter, reg+i);
211 		rbuf[idx++] = (u8) (stmp&0xff);
212 		rbuf[idx++] = (u8) ((stmp>>8)&0xff);
213 	}
214 
215 	reg = reg+i;
216 	if (remainder) { /*end of read at lower part of short : 0,2,4,6,...*/
217 		stmp = eeprom_read16(padapter, reg);
218 		rbuf[idx] = (u8)(stmp & 0xff);
219 	}
220 _func_exit_;
221 	return true;
222 }
223