1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
15 #define _RTW_EEPROM_C_
18 #include <osdep_service.h>
19 #include <drv_types.h>
21 void up_clk(_adapter *padapter, u16 *x)
25 rtw_write8(padapter, EE_9346CR, (u8)*x);
32 void down_clk(_adapter *padapter, u16 *x)
36 rtw_write8(padapter, EE_9346CR, (u8)*x);
41 void shift_out_bits(_adapter *padapter, u16 data, u16 count)
46 if (padapter->bSurpriseRemoved == true) {
47 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
50 mask = 0x01 << (count - 1);
51 x = rtw_read8(padapter, EE_9346CR);
53 x &= ~(_EEDO | _EEDI);
59 if (padapter->bSurpriseRemoved == true) {
60 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
63 rtw_write8(padapter, EE_9346CR, (u8)x);
66 down_clk(padapter, &x);
69 if (padapter->bSurpriseRemoved == true) {
70 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
74 rtw_write8(padapter, EE_9346CR, (u8)x);
79 u16 shift_in_bits(_adapter *padapter)
83 if (padapter->bSurpriseRemoved == true) {
84 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
87 x = rtw_read8(padapter, EE_9346CR);
89 x &= ~(_EEDO | _EEDI);
92 for (i = 0; i < 16; i++) {
95 if (padapter->bSurpriseRemoved == true) {
96 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
99 x = rtw_read8(padapter, EE_9346CR);
105 down_clk(padapter, &x);
113 void standby(_adapter *padapter)
117 x = rtw_read8(padapter, EE_9346CR);
119 x &= ~(_EECS | _EESK);
120 rtw_write8(padapter, EE_9346CR, x);
124 rtw_write8(padapter, EE_9346CR, x);
129 u16 wait_eeprom_cmd_done(_adapter *padapter)
135 for (i = 0; i < 200; i++) {
136 x = rtw_read8(padapter, EE_9346CR);
148 void eeprom_clean(_adapter *padapter)
152 if (padapter->bSurpriseRemoved == true) {
153 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
156 x = rtw_read8(padapter, EE_9346CR);
157 if (padapter->bSurpriseRemoved == true) {
158 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
161 x &= ~(_EECS | _EEDI);
162 rtw_write8(padapter, EE_9346CR, (u8)x);
163 if (padapter->bSurpriseRemoved == true) {
164 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
167 up_clk(padapter, &x);
168 if (padapter->bSurpriseRemoved == true) {
169 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
172 down_clk(padapter, &x);
177 void eeprom_write16(_adapter *padapter, u16 reg, u16 data)
183 x = rtw_read8(padapter, EE_9346CR);
185 x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
187 rtw_write8(padapter, EE_9346CR, x);
189 shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
191 if (padapter->EepromAddressSize == 8) /*CF+ and SDIO*/
192 shift_out_bits(padapter, 0, 6);
194 shift_out_bits(padapter, 0, 4);
198 /* Commented out by rcnjko, 2004.0
199 * Erase this particular word. Write the erase opcode and register
200 * number in that order. The opcode is 3bits in length; reg is 6 bits long.
201 * shift_out_bits(Adapter, EEPROM_ERASE_OPCODE, 3);
202 * shift_out_bits(Adapter, reg, Adapter->EepromAddressSize);
204 * if (wait_eeprom_cmd_done(Adapter ) == false)
212 /* write the new word to the EEPROM*/
214 /* send the write opcode the EEPORM*/
215 shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
217 /* select which word in the EEPROM that we are writing to.*/
218 shift_out_bits(padapter, reg, padapter->EepromAddressSize);
220 /* write the data to the selected EEPROM word.*/
221 shift_out_bits(padapter, data, 16);
223 if (wait_eeprom_cmd_done(padapter) == false) {
230 shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
231 shift_out_bits(padapter, reg, 4);
233 eeprom_clean(padapter);
239 u16 eeprom_read16(_adapter *padapter, u16 reg) /*ReadEEprom*/
247 if (padapter->bSurpriseRemoved == true) {
248 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
251 /* select EEPROM, reset bits, set _EECS*/
252 x = rtw_read8(padapter, EE_9346CR);
254 if (padapter->bSurpriseRemoved == true) {
255 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
259 x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
261 rtw_write8(padapter, EE_9346CR, (unsigned char)x);
263 /* write the read opcode and register number in that order*/
264 /* The opcode is 3bits in length, reg is 6 bits long*/
265 shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
266 shift_out_bits(padapter, reg, padapter->EepromAddressSize);
268 /* Now read the data (16 bits) in from the selected EEPROM word*/
269 data = shift_in_bits(padapter);
271 eeprom_clean(padapter);
283 void eeprom_read_sz(_adapter *padapter, u16 reg, u8 *data, u32 sz)
289 if (padapter->bSurpriseRemoved == true) {
290 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
293 /* select EEPROM, reset bits, set _EECS*/
294 x = rtw_read8(padapter, EE_9346CR);
296 if (padapter->bSurpriseRemoved == true) {
297 RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true"));
301 x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
303 rtw_write8(padapter, EE_9346CR, (unsigned char)x);
305 /* write the read opcode and register number in that order*/
306 /* The opcode is 3bits in length, reg is 6 bits long*/
307 shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
308 shift_out_bits(padapter, reg, padapter->EepromAddressSize);
311 for (i = 0; i < sz; i += 2) {
312 data16 = shift_in_bits(padapter);
313 data[i] = data16 & 0xff;
314 data[i+1] = data16 >> 8;
317 eeprom_clean(padapter);
326 /*addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg)*/
327 u8 eeprom_read(_adapter *padapter, u32 addr_off, u8 sz, u8 *rbuf)
329 u8 quotient, remainder, addr_2align_odd;
330 u16 reg, stmp, i = 0, idx = 0;
332 reg = (u16)(addr_off >> 1);
333 addr_2align_odd = (u8)(addr_off & 0x1);
335 /*read that start at high part: e.g 1,3,5,7,9,...*/
336 if (addr_2align_odd) {
337 stmp = eeprom_read16(padapter, reg);
338 rbuf[idx++] = (u8) ((stmp>>8)&0xff); /*return hogh-part of the short*/
343 remainder = sz & 0x1;
345 for (i = 0; i < quotient; i++) {
346 stmp = eeprom_read16(padapter, reg+i);
347 rbuf[idx++] = (u8) (stmp&0xff);
348 rbuf[idx++] = (u8) ((stmp>>8)&0xff);
352 if (remainder) { /*end of read at lower part of short : 0,2,4,6,...*/
353 stmp = eeprom_read16(padapter, reg);
354 rbuf[idx] = (u8)(stmp & 0xff);
362 void read_eeprom_content(_adapter *padapter)