/drivers/staging/rtl8712/rtl8712_efuse.c
C | 568 lines | 468 code | 42 blank | 58 comment | 163 complexity | 0c1afe15159dfb25ad94ea5eeb8a7022 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * rtl8712_efuse.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
- #define _RTL8712_EFUSE_C_
- #include "osdep_service.h"
- #include "drv_types.h"
- #include "rtl8712_efuse.h"
- /* reserve 3 bytes for HW stop read */
- static int efuse_available_max_size = EFUSE_MAX_SIZE - 3 /*0x1FD*/;
- static void efuse_reg_ctrl(struct _adapter *padapter, u8 bPowerOn)
- {
- u8 tmpu8 = 0;
- if (true == bPowerOn) {
- /* -----------------e-fuse pwr & clk reg ctrl ---------------
- * Enable LDOE25 Macro Block
- */
- tmpu8 = r8712_read8(padapter, EFUSE_TEST + 3);
- tmpu8 |= 0x80;
- r8712_write8(padapter, EFUSE_TEST + 3, tmpu8);
- msleep(20); /* for some platform , need some delay time */
- /* Change Efuse Clock for write action to 40MHZ */
- r8712_write8(padapter, EFUSE_CLK_CTRL, 0x03);
- msleep(20); /* for some platform , need some delay time */
- } else {
- /* -----------------e-fuse pwr & clk reg ctrl -----------------
- * Disable LDOE25 Macro Block
- */
- tmpu8 = r8712_read8(padapter, EFUSE_TEST + 3);
- tmpu8 &= 0x7F;
- r8712_write8(padapter, EFUSE_TEST + 3, tmpu8);
- /* Change Efuse Clock for write action to 500K */
- r8712_write8(padapter, EFUSE_CLK_CTRL, 0x02);
- }
- }
- /*
- * Before write E-Fuse, this function must be called.
- */
- u8 r8712_efuse_reg_init(struct _adapter *padapter)
- {
- return true;
- }
- void r8712_efuse_reg_uninit(struct _adapter *padapter)
- {
- efuse_reg_ctrl(padapter, false);
- }
- static u8 efuse_one_byte_read(struct _adapter *padapter, u16 addr, u8 *data)
- {
- u8 tmpidx = 0, bResult;
- /* -----------------e-fuse reg ctrl --------------------------------- */
- r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */
- r8712_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8)&0x03)) |
- (r8712_read8(padapter, EFUSE_CTRL+2)&0xFC));
- r8712_write8(padapter, EFUSE_CTRL+3, 0x72); /* read cmd */
- /* wait for complete */
- while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100) {
- *data = r8712_read8(padapter, EFUSE_CTRL);
- bResult = true;
- } else {
- *data = 0xff;
- bResult = false;
- }
- return bResult;
- }
- static u8 efuse_one_byte_write(struct _adapter *padapter, u16 addr, u8 data)
- {
- u8 tmpidx = 0, bResult;
- /* -----------------e-fuse reg ctrl -------------------------------- */
- r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */
- r8712_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8)&0x03)) |
- (r8712_read8(padapter, EFUSE_CTRL+2)&0xFC));
- r8712_write8(padapter, EFUSE_CTRL, data); /* data */
- r8712_write8(padapter, EFUSE_CTRL+3, 0xF2); /* write cmd */
- /* wait for complete */
- while ((0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100)
- bResult = true;
- else
- bResult = false;
- return bResult;
- }
- static u8 efuse_one_byte_rw(struct _adapter *padapter, u8 bRead, u16 addr,
- u8 *data)
- {
- u8 tmpidx = 0, tmpv8 = 0, bResult;
- /* -----------------e-fuse reg ctrl --------------------------------- */
- r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */
- tmpv8 = ((u8)((addr >> 8) & 0x03)) |
- (r8712_read8(padapter, EFUSE_CTRL + 2) & 0xFC);
- r8712_write8(padapter, EFUSE_CTRL+2, tmpv8);
- if (true == bRead) {
- r8712_write8(padapter, EFUSE_CTRL+3, 0x72); /* read cmd */
- while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100) {
- *data = r8712_read8(padapter, EFUSE_CTRL);
- bResult = true;
- } else {
- *data = 0;
- bResult = false;
- }
- } else {
- r8712_write8(padapter, EFUSE_CTRL, *data); /* data */
- r8712_write8(padapter, EFUSE_CTRL+3, 0xF2); /* write cmd */
- while ((0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100)
- bResult = true;
- else
- bResult = false;
- }
- return bResult;
- }
- static u8 efuse_is_empty(struct _adapter *padapter, u8 *empty)
- {
- u8 value, ret = true;
- /* read one byte to check if E-Fuse is empty */
- if (efuse_one_byte_rw(padapter, true, 0, &value) == true) {
- if (0xFF == value)
- *empty = true;
- else
- *empty = false;
- } else
- ret = false;
- return ret;
- }
- void r8712_efuse_change_max_size(struct _adapter *padapter)
- {
- u16 pre_pg_data_saddr = 0x1FB;
- u16 i;
- u16 pre_pg_data_size = 5;
- u8 pre_pg_data[5];
- for (i = 0; i < pre_pg_data_size; i++)
- efuse_one_byte_read(padapter, pre_pg_data_saddr + i,
- &pre_pg_data[i]);
- if ((pre_pg_data[0] == 0x03) && (pre_pg_data[1] == 0x00) &&
- (pre_pg_data[2] == 0x00) && (pre_pg_data[3] == 0x00) &&
- (pre_pg_data[4] == 0x0C))
- efuse_available_max_size -= pre_pg_data_size;
- }
- int r8712_efuse_get_max_size(struct _adapter *padapter)
- {
- return efuse_available_max_size;
- }
- static u8 calculate_word_cnts(const u8 word_en)
- {
- u8 word_cnts = 0;
- u8 word_idx;
- for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++)
- if (!(word_en & BIT(word_idx)))
- word_cnts++; /* 0 : write enable */
- return word_cnts;
- }
- static void pgpacket_copy_data(const u8 word_en, const u8 *sourdata,
- u8 *targetdata)
- {
- u8 tmpindex = 0;
- u8 word_idx, byte_idx;
- for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++) {
- if (!(word_en&BIT(word_idx))) {
- byte_idx = word_idx * 2;
- targetdata[byte_idx] = sourdata[tmpindex++];
- targetdata[byte_idx + 1] = sourdata[tmpindex++];
- }
- }
- }
- u16 r8712_efuse_get_current_size(struct _adapter *padapter)
- {
- int bContinual = true;
- u16 efuse_addr = 0;
- u8 hoffset = 0, hworden = 0;
- u8 efuse_data, word_cnts = 0;
- while (bContinual && efuse_one_byte_read(padapter, efuse_addr,
- &efuse_data) && (efuse_addr < efuse_available_max_size)) {
- if (efuse_data != 0xFF) {
- hoffset = (efuse_data >> 4) & 0x0F;
- hworden = efuse_data & 0x0F;
- word_cnts = calculate_word_cnts(hworden);
- /* read next header */
- efuse_addr = efuse_addr + (word_cnts * 2) + 1;
- } else
- bContinual = false ;
- }
- return efuse_addr;
- }
- u8 r8712_efuse_pg_packet_read(struct _adapter *padapter, u8 offset, u8 *data)
- {
- u8 hoffset = 0, hworden = 0, word_cnts = 0;
- u16 efuse_addr = 0;
- u8 efuse_data;
- u8 tmpidx = 0;
- u8 tmpdata[PGPKT_DATA_SIZE];
- u8 ret = true;
-