diff options
Diffstat (limited to 'drivers/staging/rtl8723bs/core/rtw_eeprom.c')
-rw-r--r-- | drivers/staging/rtl8723bs/core/rtw_eeprom.c | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/drivers/staging/rtl8723bs/core/rtw_eeprom.c b/drivers/staging/rtl8723bs/core/rtw_eeprom.c new file mode 100644 index 0000000..35031a7 --- /dev/null +++ b/drivers/staging/rtl8723bs/core/rtw_eeprom.c @@ -0,0 +1,369 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + ******************************************************************************/ +#define _RTW_EEPROM_C_ + +#include <drv_conf.h> +#include <osdep_service.h> +#include <drv_types.h> + +void up_clk(_adapter *padapter, u16 *x) +{ +_func_enter_; + *x = *x | _EESK; + rtw_write8(padapter, EE_9346CR, (u8)*x); + udelay(CLOCK_RATE); + +_func_exit_; + +} + +void down_clk(_adapter *padapter, u16 *x) +{ +_func_enter_; + *x = *x & ~_EESK; + rtw_write8(padapter, EE_9346CR, (u8)*x); + udelay(CLOCK_RATE); +_func_exit_; +} + +void shift_out_bits(_adapter *padapter, u16 data, u16 count) +{ + u16 x, mask; +_func_enter_; + + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + mask = 0x01 << (count - 1); + x = rtw_read8(padapter, EE_9346CR); + + x &= ~(_EEDO | _EEDI); + + do { + x &= ~_EEDI; + if (data & mask) + x |= _EEDI; + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + rtw_write8(padapter, EE_9346CR, (u8)x); + udelay(CLOCK_RATE); + up_clk(padapter, &x); + down_clk(padapter, &x); + mask = mask >> 1; + } while (mask); + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + x &= ~_EEDI; + rtw_write8(padapter, EE_9346CR, (u8)x); +out: +_func_exit_; +} + +u16 shift_in_bits(_adapter *padapter) +{ + u16 x, d = 0, i; +_func_enter_; + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + x = rtw_read8(padapter, EE_9346CR); + + x &= ~(_EEDO | _EEDI); + d = 0; + + for (i = 0; i < 16; i++) { + d = d << 1; + up_clk(padapter, &x); + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + x = rtw_read8(padapter, EE_9346CR); + + x &= ~(_EEDI); + if (x & _EEDO) + d |= 1; + + down_clk(padapter, &x); + } +out: +_func_exit_; + + return d; +} + +void standby(_adapter *padapter) +{ + u8 x; +_func_enter_; + x = rtw_read8(padapter, EE_9346CR); + + x &= ~(_EECS | _EESK); + rtw_write8(padapter, EE_9346CR, x); + + udelay(CLOCK_RATE); + x |= _EECS; + rtw_write8(padapter, EE_9346CR, x); + udelay(CLOCK_RATE); +_func_exit_; +} + +u16 wait_eeprom_cmd_done(_adapter *padapter) +{ + u8 x; + u16 i, res = false; +_func_enter_; + standby(padapter); + for (i = 0; i < 200; i++) { + x = rtw_read8(padapter, EE_9346CR); + if (x & _EEDO) { + res = true; + goto exit; + } + udelay(CLOCK_RATE); + } +exit: +_func_exit_; + return res; +} + +void eeprom_clean(_adapter *padapter) +{ + u16 x; +_func_enter_; + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + x = rtw_read8(padapter, EE_9346CR); + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + x &= ~(_EECS | _EEDI); + rtw_write8(padapter, EE_9346CR, (u8)x); + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + up_clk(padapter, &x); + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + down_clk(padapter, &x); +out: +_func_exit_; +} + +void eeprom_write16(_adapter *padapter, u16 reg, u16 data) +{ + u8 x; + +_func_enter_; + + x = rtw_read8(padapter, EE_9346CR); + + x &= ~(_EEDI | _EEDO | _EESK | _EEM0); + x |= _EEM1 | _EECS; + rtw_write8(padapter, EE_9346CR, x); + + shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5); + + if (padapter->EepromAddressSize == 8) /*CF+ and SDIO*/ + shift_out_bits(padapter, 0, 6); + else /*USB*/ + shift_out_bits(padapter, 0, 4); + + standby(padapter); + +/* Commented out by rcnjko, 2004.0 +* Erase this particular word. Write the erase opcode and register +* number in that order. The opcode is 3bits in length; reg is 6 bits long. +* shift_out_bits(Adapter, EEPROM_ERASE_OPCODE, 3); +* shift_out_bits(Adapter, reg, Adapter->EepromAddressSize); +* +* if (wait_eeprom_cmd_done(Adapter ) == false) +* { +* return; +* } +*/ + + standby(padapter); + + /* write the new word to the EEPROM*/ + + /* send the write opcode the EEPORM*/ + shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3); + + /* select which word in the EEPROM that we are writing to.*/ + shift_out_bits(padapter, reg, padapter->EepromAddressSize); + + /* write the data to the selected EEPROM word.*/ + shift_out_bits(padapter, data, 16); + + if (wait_eeprom_cmd_done(padapter) == false) { + + goto exit; + } + + standby(padapter); + + shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5); + shift_out_bits(padapter, reg, 4); + + eeprom_clean(padapter); +exit: +_func_exit_; + return; +} + +u16 eeprom_read16(_adapter *padapter, u16 reg) /*ReadEEprom*/ +{ + + u16 x; + u16 data = 0; + +_func_enter_; + + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + /* select EEPROM, reset bits, set _EECS*/ + x = rtw_read8(padapter, EE_9346CR); + + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + + x &= ~(_EEDI | _EEDO | _EESK | _EEM0); + x |= _EEM1 | _EECS; + rtw_write8(padapter, EE_9346CR, (unsigned char)x); + + /* write the read opcode and register number in that order*/ + /* The opcode is 3bits in length, reg is 6 bits long*/ + shift_out_bits(padapter, EEPROM_READ_OPCODE, 3); + shift_out_bits(padapter, reg, padapter->EepromAddressSize); + + /* Now read the data (16 bits) in from the selected EEPROM word*/ + data = shift_in_bits(padapter); + + eeprom_clean(padapter); +out: +_func_exit_; + return data; + + +} + + + + +/*From even offset*/ +void eeprom_read_sz(_adapter *padapter, u16 reg, u8 *data, u32 sz) +{ + + u16 x, data16; + u32 i; +_func_enter_; + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + /* select EEPROM, reset bits, set _EECS*/ + x = rtw_read8(padapter, EE_9346CR); + + if (padapter->bSurpriseRemoved == true) { + RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==true")); + goto out; + } + + x &= ~(_EEDI | _EEDO | _EESK | _EEM0); + x |= _EEM1 | _EECS; + rtw_write8(padapter, EE_9346CR, (unsigned char)x); + + /* write the read opcode and register number in that order*/ + /* The opcode is 3bits in length, reg is 6 bits long*/ + shift_out_bits(padapter, EEPROM_READ_OPCODE, 3); + shift_out_bits(padapter, reg, padapter->EepromAddressSize); + + + for (i = 0; i < sz; i += 2) { + data16 = shift_in_bits(padapter); + data[i] = data16 & 0xff; + data[i+1] = data16 >> 8; + } + + eeprom_clean(padapter); +out: +_func_exit_; + + + +} + + +/*addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg)*/ +u8 eeprom_read(_adapter *padapter, u32 addr_off, u8 sz, u8 *rbuf) +{ + u8 quotient, remainder, addr_2align_odd; + u16 reg, stmp, i = 0, idx = 0; +_func_enter_; + reg = (u16)(addr_off >> 1); + addr_2align_odd = (u8)(addr_off & 0x1); + + /*read that start at high part: e.g 1,3,5,7,9,...*/ + if (addr_2align_odd) { + stmp = eeprom_read16(padapter, reg); + rbuf[idx++] = (u8) ((stmp>>8)&0xff); /*return hogh-part of the short*/ + reg++; sz--; + } + + quotient = sz >> 1; + remainder = sz & 0x1; + + for (i = 0; i < quotient; i++) { + stmp = eeprom_read16(padapter, reg+i); + rbuf[idx++] = (u8) (stmp&0xff); + rbuf[idx++] = (u8) ((stmp>>8)&0xff); + } + + reg = reg+i; + if (remainder) { /*end of read at lower part of short : 0,2,4,6,...*/ + stmp = eeprom_read16(padapter, reg); + rbuf[idx] = (u8)(stmp & 0xff); + } +_func_exit_; + return true; +} + + + +void read_eeprom_content(_adapter *padapter) +{ + +_func_enter_; + + +_func_exit_; +} |