Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_eeprom.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _RTW_EEPROM_C_1516#include <drv_conf.h>17#include <osdep_service.h>18#include <drv_types.h>1920void up_clk(_adapter *padapter, u16 *x)21{22*x = *x | _EESK;23rtw_write8(padapter, EE_9346CR, (u8)*x);24rtw_udelay_os(CLOCK_RATE);252627}2829void down_clk(_adapter *padapter, u16 *x)30{31*x = *x & ~_EESK;32rtw_write8(padapter, EE_9346CR, (u8)*x);33rtw_udelay_os(CLOCK_RATE);34}3536void shift_out_bits(_adapter *padapter, u16 data, u16 count)37{38u16 x, mask;3940if (rtw_is_surprise_removed(padapter)) {41goto out;42}43mask = 0x01 << (count - 1);44x = rtw_read8(padapter, EE_9346CR);4546x &= ~(_EEDO | _EEDI);4748do {49x &= ~_EEDI;50if (data & mask)51x |= _EEDI;52if (rtw_is_surprise_removed(padapter)) {53goto out;54}55rtw_write8(padapter, EE_9346CR, (u8)x);56rtw_udelay_os(CLOCK_RATE);57up_clk(padapter, &x);58down_clk(padapter, &x);59mask = mask >> 1;60} while (mask);61if (rtw_is_surprise_removed(padapter)) {62goto out;63}64x &= ~_EEDI;65rtw_write8(padapter, EE_9346CR, (u8)x);66out:67return;68}6970u16 shift_in_bits(_adapter *padapter)71{72u16 x, d = 0, i;73if (rtw_is_surprise_removed(padapter)) {74goto out;75}76x = rtw_read8(padapter, EE_9346CR);7778x &= ~(_EEDO | _EEDI);79d = 0;8081for (i = 0; i < 16; i++) {82d = d << 1;83up_clk(padapter, &x);84if (rtw_is_surprise_removed(padapter)) {85goto out;86}87x = rtw_read8(padapter, EE_9346CR);8889x &= ~(_EEDI);90if (x & _EEDO)91d |= 1;9293down_clk(padapter, &x);94}95out:9697return d;98}99100void standby(_adapter *padapter)101{102u8 x;103x = rtw_read8(padapter, EE_9346CR);104105x &= ~(_EECS | _EESK);106rtw_write8(padapter, EE_9346CR, x);107108rtw_udelay_os(CLOCK_RATE);109x |= _EECS;110rtw_write8(padapter, EE_9346CR, x);111rtw_udelay_os(CLOCK_RATE);112}113114u16 wait_eeprom_cmd_done(_adapter *padapter)115{116u8 x;117u16 i, res = _FALSE;118standby(padapter);119for (i = 0; i < 200; i++) {120x = rtw_read8(padapter, EE_9346CR);121if (x & _EEDO) {122res = _TRUE;123goto exit;124}125rtw_udelay_os(CLOCK_RATE);126}127exit:128return res;129}130131void eeprom_clean(_adapter *padapter)132{133u16 x;134if (rtw_is_surprise_removed(padapter)) {135goto out;136}137x = rtw_read8(padapter, EE_9346CR);138if (rtw_is_surprise_removed(padapter)) {139goto out;140}141x &= ~(_EECS | _EEDI);142rtw_write8(padapter, EE_9346CR, (u8)x);143if (rtw_is_surprise_removed(padapter)) {144goto out;145}146up_clk(padapter, &x);147if (rtw_is_surprise_removed(padapter)) {148goto out;149}150down_clk(padapter, &x);151out:152return;153}154155void eeprom_write16(_adapter *padapter, u16 reg, u16 data)156{157u8 x;158x = rtw_read8(padapter, EE_9346CR);159160x &= ~(_EEDI | _EEDO | _EESK | _EEM0);161x |= _EEM1 | _EECS;162rtw_write8(padapter, EE_9346CR, x);163164shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);165166if (padapter->EepromAddressSize == 8) /* CF+ and SDIO */167shift_out_bits(padapter, 0, 6);168else /* USB */169shift_out_bits(padapter, 0, 4);170171standby(padapter);172173/* Commented out by rcnjko, 2004.0174* Erase this particular word. Write the erase opcode and register175* number in that order. The opcode is 3bits in length; reg is 6 bits long. */176/* shift_out_bits(Adapter, EEPROM_ERASE_OPCODE, 3);177* shift_out_bits(Adapter, reg, Adapter->EepromAddressSize);178*179* if (wait_eeprom_cmd_done(Adapter ) == FALSE)180* {181* return;182* } */183184185standby(padapter);186187/* write the new word to the EEPROM */188189/* send the write opcode the EEPORM */190shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);191192/* select which word in the EEPROM that we are writing to. */193shift_out_bits(padapter, reg, padapter->EepromAddressSize);194195/* write the data to the selected EEPROM word. */196shift_out_bits(padapter, data, 16);197198if (wait_eeprom_cmd_done(padapter) == _FALSE)199200goto exit;201202standby(padapter);203204shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);205shift_out_bits(padapter, reg, 4);206207eeprom_clean(padapter);208exit:209return;210}211212u16 eeprom_read16(_adapter *padapter, u16 reg) /* ReadEEprom */213{214215u16 x;216u16 data = 0;217218if (rtw_is_surprise_removed(padapter)) {219goto out;220}221/* select EEPROM, reset bits, set _EECS */222x = rtw_read8(padapter, EE_9346CR);223224if (rtw_is_surprise_removed(padapter)) {225goto out;226}227228x &= ~(_EEDI | _EEDO | _EESK | _EEM0);229x |= _EEM1 | _EECS;230rtw_write8(padapter, EE_9346CR, (unsigned char)x);231232/* write the read opcode and register number in that order */233/* The opcode is 3bits in length, reg is 6 bits long */234shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);235shift_out_bits(padapter, reg, padapter->EepromAddressSize);236237/* Now read the data (16 bits) in from the selected EEPROM word */238data = shift_in_bits(padapter);239240eeprom_clean(padapter);241out:242243return data;244245246}247248249250251/* From even offset */252void eeprom_read_sz(_adapter *padapter, u16 reg, u8 *data, u32 sz)253{254255u16 x, data16;256u32 i;257if (rtw_is_surprise_removed(padapter)) {258goto out;259}260/* select EEPROM, reset bits, set _EECS */261x = rtw_read8(padapter, EE_9346CR);262263if (rtw_is_surprise_removed(padapter)) {264goto out;265}266267x &= ~(_EEDI | _EEDO | _EESK | _EEM0);268x |= _EEM1 | _EECS;269rtw_write8(padapter, EE_9346CR, (unsigned char)x);270271/* write the read opcode and register number in that order */272/* The opcode is 3bits in length, reg is 6 bits long */273shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);274shift_out_bits(padapter, reg, padapter->EepromAddressSize);275276277for (i = 0; i < sz; i += 2) {278data16 = shift_in_bits(padapter);279data[i] = data16 & 0xff;280data[i + 1] = data16 >> 8;281}282283eeprom_clean(padapter);284out:285return;286}287288289/* addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg) */290u8 eeprom_read(_adapter *padapter, u32 addr_off, u8 sz, u8 *rbuf)291{292u8 quotient, remainder, addr_2align_odd;293u16 reg, stmp , i = 0, idx = 0;294reg = (u16)(addr_off >> 1);295addr_2align_odd = (u8)(addr_off & 0x1);296297if (addr_2align_odd) { /* read that start at high part: e.g 1,3,5,7,9,... */298stmp = eeprom_read16(padapter, reg);299rbuf[idx++] = (u8)((stmp >> 8) & 0xff); /* return hogh-part of the short */300reg++;301sz--;302}303304quotient = sz >> 1;305remainder = sz & 0x1;306307for (i = 0 ; i < quotient; i++) {308stmp = eeprom_read16(padapter, reg + i);309rbuf[idx++] = (u8)(stmp & 0xff);310rbuf[idx++] = (u8)((stmp >> 8) & 0xff);311}312313reg = reg + i;314if (remainder) { /* end of read at lower part of short : 0,2,4,6,... */315stmp = eeprom_read16(padapter, reg);316rbuf[idx] = (u8)(stmp & 0xff);317}318return _TRUE;319}320321322323void read_eeprom_content(_adapter *padapter)324{325326327328}329330331