diff options
Diffstat (limited to 'drivers/staging/rtl8723bs/core/rtw_efuse.c')
-rw-r--r-- | drivers/staging/rtl8723bs/core/rtw_efuse.c | 623 |
1 files changed, 623 insertions, 0 deletions
diff --git a/drivers/staging/rtl8723bs/core/rtw_efuse.c b/drivers/staging/rtl8723bs/core/rtw_efuse.c new file mode 100644 index 0000000..b3247c9 --- /dev/null +++ b/drivers/staging/rtl8723bs/core/rtw_efuse.c @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: GPL-2.0 +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + ******************************************************************************/ +#define _RTW_EFUSE_C_ + +#include <drv_types.h> +#include <rtw_debug.h> +#include <hal_data.h> +#include <linux/jiffies.h> + + +/* Define global variables */ +u8 fakeEfuseBank; +u32 fakeEfuseUsedBytes; +u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0}; +u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0}; +u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0}; + +u32 BTEfuseUsedBytes; +u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE]; +u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0}; +u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0}; + +u32 fakeBTEfuseUsedBytes; +u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE]; +u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0}; +u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0}; + +#define REG_EFUSE_CTRL 0x0030 +#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */ + +bool +Efuse_Read1ByteFromFakeContent( + struct adapter *padapter, + u16 Offset, + u8 *Value); +bool +Efuse_Read1ByteFromFakeContent( + struct adapter *padapter, + u16 Offset, + u8 *Value) +{ + if (Offset >= EFUSE_MAX_HW_SIZE) { + return false; + } + /* DbgPrint("Read fake content, offset = %d\n", Offset); */ + if (fakeEfuseBank == 0) + *Value = fakeEfuseContent[Offset]; + else + *Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset]; + return true; +} + +bool +Efuse_Write1ByteToFakeContent( + struct adapter *padapter, + u16 Offset, + u8 Value); +bool +Efuse_Write1ByteToFakeContent( + struct adapter *padapter, + u16 Offset, + u8 Value) +{ + if (Offset >= EFUSE_MAX_HW_SIZE) { + return false; + } + if (fakeEfuseBank == 0) + fakeEfuseContent[Offset] = Value; + else{ + fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value; + } + return true; +} + +/*----------------------------------------------------------------------------- + * Function: Efuse_PowerSwitch + * + * Overview: When we want to enable write operation, we should change to + * pwr on state. When we stop write, we should switch to 500k mode + * and disable LDO 2.5V. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/17/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void +Efuse_PowerSwitch( +struct adapter *padapter, +u8 bWrite, +u8 PwrState) +{ + padapter->HalFunc.EfusePowerSwitch(padapter, bWrite, PwrState); +} + +/*----------------------------------------------------------------------------- + * Function: Efuse_GetCurrentSize + * + * Overview: Get current efuse size!!! + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/16/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +u16 +Efuse_GetCurrentSize( + struct adapter *padapter, + u8 efuseType, + bool bPseudoTest) +{ + u16 ret = 0; + + ret = padapter->HalFunc.EfuseGetCurrentSize(padapter, efuseType, bPseudoTest); + + return ret; +} + +/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */ +u8 +Efuse_CalculateWordCnts(u8 word_en) +{ + u8 word_cnts = 0; + if (!(word_en & BIT(0))) + word_cnts++; /* 0 : write enable */ + if (!(word_en & BIT(1))) + word_cnts++; + if (!(word_en & BIT(2))) + word_cnts++; + if (!(word_en & BIT(3))) + word_cnts++; + return word_cnts; +} + +/* */ +/* Description: */ +/* 1. Execute E-Fuse read byte operation according as map offset and */ +/* save to E-Fuse table. */ +/* 2. Referred from SD1 Richard. */ +/* */ +/* Assumption: */ +/* 1. Boot from E-Fuse and successfully auto-load. */ +/* 2. PASSIVE_LEVEL (USB interface) */ +/* */ +/* Created by Roger, 2008.10.21. */ +/* */ +/* 2008/12/12 MH 1. Reorganize code flow and reserve bytes. and add description. */ +/* 2. Add efuse utilization collect. */ +/* 2008/12/22 MH Read Efuse must check if we write section 1 data again!!! Sec1 */ +/* write addr must be after sec5. */ +/* */ + +void +efuse_ReadEFuse( + struct adapter *Adapter, + u8 efuseType, + u16 _offset, + u16 _size_byte, + u8 *pbuf, +bool bPseudoTest + ); +void +efuse_ReadEFuse( + struct adapter *Adapter, + u8 efuseType, + u16 _offset, + u16 _size_byte, + u8 *pbuf, +bool bPseudoTest + ) +{ + Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest); +} + +void +EFUSE_GetEfuseDefinition( + struct adapter *padapter, + u8 efuseType, + u8 type, + void *pOut, + bool bPseudoTest + ) +{ + padapter->HalFunc.EFUSEGetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest); +} + +/*----------------------------------------------------------------------------- + * Function: EFUSE_Read1Byte + * + * Overview: Copy from WMAC fot EFUSE read 1 byte. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 09/23/2008 MHC Copy from WMAC. + * + *---------------------------------------------------------------------------*/ +u8 +EFUSE_Read1Byte( +struct adapter *Adapter, +u16 Address) +{ + u8 data; + u8 Bytetemp = {0x00}; + u8 temp = {0x00}; + u32 k = 0; + u16 contentLen = 0; + + EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false); + + if (Address < contentLen) {/* E-fuse 512Byte */ + /* Write E-fuse Register address bit0~7 */ + temp = Address & 0xFF; + rtw_write8(Adapter, EFUSE_CTRL+1, temp); + Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2); + /* Write E-fuse Register address bit8~9 */ + temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC); + rtw_write8(Adapter, EFUSE_CTRL+2, temp); + + /* Write 0x30[31]= 0 */ + Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3); + temp = Bytetemp & 0x7F; + rtw_write8(Adapter, EFUSE_CTRL+3, temp); + + /* Wait Write-ready (0x30[31]= 1) */ + Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3); + while (!(Bytetemp & 0x80)) { + Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3); + k++; + if (k == 1000) { + k = 0; + break; + } + } + data = rtw_read8(Adapter, EFUSE_CTRL); + return data; + } else + return 0xFF; + +} /* EFUSE_Read1Byte */ + +/* 11/16/2008 MH Read one byte from real Efuse. */ +u8 +efuse_OneByteRead( +struct adapter *padapter, +u16 addr, +u8 *data, +bool bPseudoTest) +{ + u32 tmpidx = 0; + u8 bResult; + u8 readbyte; + + /* DBG_871X("===> EFUSE_OneByteRead(), addr = %x\n", addr); */ + /* DBG_871X("===> EFUSE_OneByteRead() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */ + + if (bPseudoTest) { + bResult = Efuse_Read1ByteFromFakeContent(padapter, addr, data); + return bResult; + } + + /* <20130121, Kordan> For SMIC EFUSE specificatoin. */ + /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */ + /* PHY_SetMacReg(padapter, 0x34, BIT11, 0); */ + rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) & (~BIT11)); + + /* -----------------e-fuse reg ctrl --------------------------------- */ + /* address */ + rtw_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xff)); + rtw_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) | + (rtw_read8(padapter, EFUSE_CTRL+2)&0xFC)); + + /* rtw_write8(padapter, EFUSE_CTRL+3, 0x72); read cmd */ + /* Write bit 32 0 */ + readbyte = rtw_read8(padapter, EFUSE_CTRL+3); + rtw_write8(padapter, EFUSE_CTRL+3, (readbyte & 0x7f)); + + while (!(0x80 & rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 1000)) { + mdelay(1); + tmpidx++; + } + if (tmpidx < 100) { + *data = rtw_read8(padapter, EFUSE_CTRL); + bResult = true; + } else{ + *data = 0xff; + bResult = false; + DBG_871X("%s: [ERROR] addr = 0x%x bResult =%d time out 1s !!!\n", __func__, addr, bResult); + DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL)); + } + + return bResult; +} + +/* 11/16/2008 MH Write one byte to reald Efuse. */ +u8 +efuse_OneByteWrite( +struct adapter *padapter, +u16 addr, +u8 data, +bool bPseudoTest) +{ + u8 tmpidx = 0; + u8 bResult = false; + u32 efuseValue = 0; + + /* DBG_871X("===> EFUSE_OneByteWrite(), addr = %x data =%x\n", addr, data); */ + /* DBG_871X("===> EFUSE_OneByteWrite() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */ + + if (bPseudoTest) { + bResult = Efuse_Write1ByteToFakeContent(padapter, addr, data); + return bResult; + } + + + /* -----------------e-fuse reg ctrl --------------------------------- */ + /* address */ + + + efuseValue = rtw_read32(padapter, EFUSE_CTRL); + efuseValue |= (BIT21|BIT31); + efuseValue &= ~(0x3FFFF); + efuseValue |= ((addr<<8 | data) & 0x3FFFF); + + + /* <20130227, Kordan> 8192E MP chip A-cut had better not set 0x34[11] until B-Cut. */ + + /* <20130121, Kordan> For SMIC EFUSE specificatoin. */ + /* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */ + /* PHY_SetMacReg(padapter, 0x34, BIT11, 1); */ + rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) | (BIT11)); + rtw_write32(padapter, EFUSE_CTRL, 0x90600000|((addr<<8 | data))); + + while ((0x80 & rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100)) { + mdelay(1); + tmpidx++; + } + + if (tmpidx < 100) { + bResult = true; + } else{ + bResult = false; + DBG_871X("%s: [ERROR] addr = 0x%x , efuseValue = 0x%x , bResult =%d time out 1s !!!\n", + __func__, addr, efuseValue, bResult); + DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL)); + } + + /* disable Efuse program enable */ + PHY_SetMacReg(padapter, EFUSE_TEST, BIT(11), 0); + + return bResult; +} + +int +Efuse_PgPacketRead(struct adapter *padapter, + u8 offset, + u8 *data, + bool bPseudoTest) +{ + int ret = 0; + + ret = padapter->HalFunc.Efuse_PgPacketRead(padapter, offset, data, bPseudoTest); + + return ret; +} + +int +Efuse_PgPacketWrite(struct adapter *padapter, + u8 offset, + u8 word_en, + u8 *data, + bool bPseudoTest) +{ + int ret; + + ret = padapter->HalFunc.Efuse_PgPacketWrite(padapter, offset, word_en, data, bPseudoTest); + + return ret; +} + +/*----------------------------------------------------------------------------- + * Function: efuse_WordEnableDataRead + * + * Overview: Read allowed word in current efuse section data. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/16/2008 MHC Create Version 0. + * 11/21/2008 MHC Fix Write bug when we only enable late word. + * + *---------------------------------------------------------------------------*/ +void +efuse_WordEnableDataRead(u8 word_en, + u8 *sourdata, + u8 *targetdata) +{ + if (!(word_en&BIT(0))) { + targetdata[0] = sourdata[0]; + targetdata[1] = sourdata[1]; + } + if (!(word_en&BIT(1))) { + targetdata[2] = sourdata[2]; + targetdata[3] = sourdata[3]; + } + if (!(word_en&BIT(2))) { + targetdata[4] = sourdata[4]; + targetdata[5] = sourdata[5]; + } + if (!(word_en&BIT(3))) { + targetdata[6] = sourdata[6]; + targetdata[7] = sourdata[7]; + } +} + + +u8 +Efuse_WordEnableDataWrite(struct adapter *padapter, + u16 efuse_addr, + u8 word_en, + u8 *data, + bool bPseudoTest) +{ + u8 ret = 0; + + ret = padapter->HalFunc.Efuse_WordEnableDataWrite(padapter, efuse_addr, word_en, data, bPseudoTest); + + return ret; +} + +/*----------------------------------------------------------------------------- + * Function: Efuse_ReadAllMap + * + * Overview: Read All Efuse content + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/11/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void +Efuse_ReadAllMap( + struct adapter *padapter, + u8 efuseType, + u8 *Efuse, + bool bPseudoTest); +void +Efuse_ReadAllMap( + struct adapter *padapter, + u8 efuseType, + u8 *Efuse, + bool bPseudoTest) +{ + u16 mapLen = 0; + + Efuse_PowerSwitch(padapter, false, true); + + EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest); + + efuse_ReadEFuse(padapter, efuseType, 0, mapLen, Efuse, bPseudoTest); + + Efuse_PowerSwitch(padapter, false, false); +} + +/*----------------------------------------------------------------------------- + * Function: efuse_ShadowRead1Byte + * efuse_ShadowRead2Byte + * efuse_ShadowRead4Byte + * + * Overview: Read from efuse init map by one/two/four bytes !!!!! + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/12/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +static void +efuse_ShadowRead1Byte( +struct adapter *padapter, +u16 Offset, + u8 *Value) +{ + struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); + + *Value = pEEPROM->efuse_eeprom_data[Offset]; + +} /* EFUSE_ShadowRead1Byte */ + +/* Read Two Bytes */ +static void +efuse_ShadowRead2Byte( +struct adapter *padapter, +u16 Offset, + u16 *Value) +{ + struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); + + *Value = pEEPROM->efuse_eeprom_data[Offset]; + *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8; + +} /* EFUSE_ShadowRead2Byte */ + +/* Read Four Bytes */ +static void +efuse_ShadowRead4Byte( +struct adapter *padapter, +u16 Offset, + u32 *Value) +{ + struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); + + *Value = pEEPROM->efuse_eeprom_data[Offset]; + *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8; + *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16; + *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24; + +} /* efuse_ShadowRead4Byte */ + +/*----------------------------------------------------------------------------- + * Function: EFUSE_ShadowMapUpdate + * + * Overview: Transfer current EFUSE content to shadow init and modify map. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/13/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void EFUSE_ShadowMapUpdate( + struct adapter *padapter, + u8 efuseType, + bool bPseudoTest) +{ + struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); + u16 mapLen = 0; + + EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest); + + if (pEEPROM->bautoload_fail_flag) + memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen); + else + Efuse_ReadAllMap(padapter, efuseType, pEEPROM->efuse_eeprom_data, bPseudoTest); + + /* PlatformMoveMemory((void *)&pHalData->EfuseMap[EFUSE_MODIFY_MAP][0], */ + /* void *)&pHalData->EfuseMap[EFUSE_INIT_MAP][0], mapLen); */ +} /* EFUSE_ShadowMapUpdate */ + + +/*----------------------------------------------------------------------------- + * Function: EFUSE_ShadowRead + * + * Overview: Read from efuse init map !!!!! + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/12/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void +EFUSE_ShadowRead( + struct adapter *padapter, + u8 Type, + u16 Offset, + u32 *Value) +{ + if (Type == 1) + efuse_ShadowRead1Byte(padapter, Offset, (u8 *)Value); + else if (Type == 2) + efuse_ShadowRead2Byte(padapter, Offset, (u16 *)Value); + else if (Type == 4) + efuse_ShadowRead4Byte(padapter, Offset, (u32 *)Value); + +} /* EFUSE_ShadowRead*/ |