| // SPDX-License-Identifier: GPL-2.0 |
| /* Copyright(c) 2007 - 2011 Realtek Corporation. */ |
| |
| #define _RTW_EFUSE_C_ |
| |
| #include "../include/osdep_service.h" |
| #include "../include/drv_types.h" |
| #include "../include/rtw_efuse.h" |
| |
| /*------------------------Define local variable------------------------------*/ |
| 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 local variable------------------------------*/ |
| |
| #define REG_EFUSE_CTRL 0x0030 |
| #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */ |
| |
| static bool Efuse_Read1ByteFromFakeContent(u16 Offset, u8 *Value) |
| { |
| if (Offset >= EFUSE_MAX_HW_SIZE) |
| return false; |
| if (fakeEfuseBank == 0) |
| *Value = fakeEfuseContent[Offset]; |
| else |
| *Value = fakeBTEfuseContent[fakeEfuseBank - 1][Offset]; |
| return true; |
| } |
| |
| static 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; |
| } |
| |
| /* 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: */ |
| /* Execute E-Fuse read byte operation. */ |
| /* 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. */ |
| /* */ |
| void |
| ReadEFuseByte( |
| struct adapter *Adapter, |
| u16 _offset, |
| u8 *pbuf, |
| bool pseudo) |
| { |
| u32 value32; |
| u8 readbyte; |
| u16 retry; |
| |
| if (pseudo) { |
| Efuse_Read1ByteFromFakeContent(_offset, pbuf); |
| return; |
| } |
| |
| /* Write Address */ |
| rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff)); |
| readbyte = rtw_read8(Adapter, EFUSE_CTRL + 2); |
| rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); |
| |
| /* Write bit 32 0 */ |
| readbyte = rtw_read8(Adapter, EFUSE_CTRL + 3); |
| rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f)); |
| |
| /* Check bit 32 read-ready */ |
| retry = 0; |
| value32 = rtw_read32(Adapter, EFUSE_CTRL); |
| while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) { |
| value32 = rtw_read32(Adapter, EFUSE_CTRL); |
| retry++; |
| } |
| |
| /* 20100205 Joseph: Add delay suggested by SD1 Victor. */ |
| /* This fix the problem that Efuse read error in high temperature condition. */ |
| /* Designer says that there shall be some delay after ready bit is set, or the */ |
| /* result will always stay on last data we read. */ |
| udelay(50); |
| value32 = rtw_read32(Adapter, EFUSE_CTRL); |
| |
| *pbuf = (u8)(value32 & 0xff); |
| } |
| |
| /* 11/16/2008 MH Read one byte from real Efuse. */ |
| u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo) |
| { |
| u8 tmpidx = 0; |
| u8 result; |
| |
| if (pseudo) { |
| result = Efuse_Read1ByteFromFakeContent(addr, data); |
| return result; |
| } |
| /* -----------------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 */ |
| |
| while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) |
| tmpidx++; |
| if (tmpidx < 100) { |
| *data = rtw_read8(pAdapter, EFUSE_CTRL); |
| result = true; |
| } else { |
| *data = 0xff; |
| result = false; |
| } |
| return result; |
| } |
| |
| /* 11/16/2008 MH Write one byte to reald Efuse. */ |
| u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo) |
| { |
| u8 tmpidx = 0; |
| u8 result; |
| |
| if (pseudo) { |
| result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data); |
| return result; |
| } |
| |
| /* -----------------e-fuse reg ctrl --------------------------------- */ |
| /* address */ |
| rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); |
| rtw_write8(pAdapter, EFUSE_CTRL + 2, |
| (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) | |
| (u8)((addr >> 8) & 0x03)); |
| rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */ |
| |
| rtw_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */ |
| |
| while ((0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) |
| tmpidx++; |
| |
| if (tmpidx < 100) |
| result = true; |
| else |
| result = false; |
| |
| return result; |
| } |
| |
| /*----------------------------------------------------------------------------- |
| * 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]; |
| } |
| } |
| |
| /*----------------------------------------------------------------------------- |
| * 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. |
| * |
| *---------------------------------------------------------------------------*/ |
| static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo) |
| { |
| u16 mapLen = 0; |
| |
| rtl8188e_EfusePowerSwitch(pAdapter, false, true); |
| |
| rtl8188e_EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo); |
| |
| rtl8188e_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo); |
| |
| rtl8188e_EfusePowerSwitch(pAdapter, false, false); |
| } |
| |
| /*----------------------------------------------------------------------------- |
| * 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 pseudo) |
| { |
| struct eeprom_priv *pEEPROM = &pAdapter->eeprompriv; |
| u16 mapLen = 0; |
| |
| rtl8188e_EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo); |
| |
| if (pEEPROM->bautoload_fail_flag) |
| memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen); |
| else |
| Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo); |
| } /* EFUSE_ShadowMapUpdate */ |