1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
6 #include "../include/osdep_service.h"
7 #include "../include/drv_types.h"
8 #include "../include/rtw_efuse.h"
10 /*------------------------Define local variable------------------------------*/
12 u32 fakeEfuseUsedBytes;
13 u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
14 u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
15 u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
18 u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
19 u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
20 u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
22 u32 fakeBTEfuseUsedBytes;
23 u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
24 u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
25 u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
26 /*------------------------Define local variable------------------------------*/
29 #define REG_EFUSE_CTRL 0x0030
30 #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
34 Efuse_Read1ByteFromFakeContent(
35 struct adapter *pAdapter,
39 Efuse_Read1ByteFromFakeContent(
40 struct adapter *pAdapter,
44 if (Offset >= EFUSE_MAX_HW_SIZE)
46 if (fakeEfuseBank == 0)
47 *Value = fakeEfuseContent[Offset];
49 *Value = fakeBTEfuseContent[fakeEfuseBank - 1][Offset];
54 Efuse_Write1ByteToFakeContent(
55 struct adapter *pAdapter,
59 if (Offset >= EFUSE_MAX_HW_SIZE)
61 if (fakeEfuseBank == 0) {
62 fakeEfuseContent[Offset] = Value;
64 fakeBTEfuseContent[fakeEfuseBank - 1][Offset] = Value;
69 /*-----------------------------------------------------------------------------
70 * Function: Efuse_PowerSwitch
72 * Overview: When we want to enable write operation, we should change to
73 * pwr on state. When we stop write, we should switch to 500k mode
74 * and disable LDO 2.5V.
84 * 11/17/2008 MHC Create Version 0.
86 *---------------------------------------------------------------------------*/
89 struct adapter *pAdapter,
93 pAdapter->HalFunc.EfusePowerSwitch(pAdapter, write, PwrState);
96 /*-----------------------------------------------------------------------------
97 * Function: efuse_GetCurrentSize
99 * Overview: Get current efuse size!!!
109 * 11/16/2008 MHC Create Version 0.
111 *---------------------------------------------------------------------------*/
113 Efuse_GetCurrentSize(
114 struct adapter *pAdapter,
120 ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType, pseudo);
125 /* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
127 Efuse_CalculateWordCnts(u8 word_en)
130 if (!(word_en & BIT(0)))
131 word_cnts++; /* 0 : write enable */
132 if (!(word_en & BIT(1)))
134 if (!(word_en & BIT(2)))
136 if (!(word_en & BIT(3)))
143 /* Execute E-Fuse read byte operation. */
144 /* Referred from SD1 Richard. */
147 /* 1. Boot from E-Fuse and successfully auto-load. */
148 /* 2. PASSIVE_LEVEL (USB interface) */
150 /* Created by Roger, 2008.10.21. */
154 struct adapter *Adapter,
164 Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
169 rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
170 readbyte = rtw_read8(Adapter, EFUSE_CTRL + 2);
171 rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
174 readbyte = rtw_read8(Adapter, EFUSE_CTRL + 3);
175 rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
177 /* Check bit 32 read-ready */
179 value32 = rtw_read32(Adapter, EFUSE_CTRL);
180 while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) {
181 value32 = rtw_read32(Adapter, EFUSE_CTRL);
185 /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
186 /* This fix the problem that Efuse read error in high temperature condition. */
187 /* Designer says that there shall be some delay after ready bit is set, or the */
188 /* result will always stay on last data we read. */
190 value32 = rtw_read32(Adapter, EFUSE_CTRL);
192 *pbuf = (u8)(value32 & 0xff);
197 /* 1. Execute E-Fuse read byte operation according as map offset and */
198 /* save to E-Fuse table. */
199 /* 2. Referred from SD1 Richard. */
202 /* 1. Boot from E-Fuse and successfully auto-load. */
203 /* 2. PASSIVE_LEVEL (USB interface) */
205 /* Created by Roger, 2008.10.21. */
207 /* 2008/12/12 MH 1. Reorganize code flow and reserve bytes. and add description. */
208 /* 2. Add efuse utilization collect. */
209 /* 2008/12/22 MH Read Efuse must check if we write section 1 data again!!! Sec1 */
210 /* write addr must be after sec5. */
213 static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
215 Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
218 void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
221 pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType, type, pOut, pseudo);
224 /*-----------------------------------------------------------------------------
225 * Function: EFUSE_Read1Byte
227 * Overview: Copy from WMAC fot EFUSE read 1 byte.
237 * 09/23/2008 MHC Copy from WMAC.
239 *---------------------------------------------------------------------------*/
240 u8 EFUSE_Read1Byte(struct adapter *Adapter, u16 Address)
243 u8 Bytetemp = {0x00};
248 EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
250 if (Address < contentLen) { /* E-fuse 512Byte */
251 /* Write E-fuse Register address bit0~7 */
252 temp = Address & 0xFF;
253 rtw_write8(Adapter, EFUSE_CTRL + 1, temp);
254 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 2);
255 /* Write E-fuse Register address bit8~9 */
256 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
257 rtw_write8(Adapter, EFUSE_CTRL + 2, temp);
259 /* Write 0x30[31]= 0 */
260 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
261 temp = Bytetemp & 0x7F;
262 rtw_write8(Adapter, EFUSE_CTRL + 3, temp);
264 /* Wait Write-ready (0x30[31]= 1) */
265 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
266 while (!(Bytetemp & 0x80)) {
267 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
274 data = rtw_read8(Adapter, EFUSE_CTRL);
280 } /* EFUSE_Read1Byte */
282 /* 11/16/2008 MH Read one byte from real Efuse. */
283 u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
289 result = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
292 /* -----------------e-fuse reg ctrl --------------------------------- */
294 rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
295 rtw_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
296 (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
298 rtw_write8(pAdapter, EFUSE_CTRL + 3, 0x72);/* read cmd */
300 while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
303 *data = rtw_read8(pAdapter, EFUSE_CTRL);
312 /* 11/16/2008 MH Write one byte to reald Efuse. */
313 u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
319 result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
323 /* -----------------e-fuse reg ctrl --------------------------------- */
325 rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
326 rtw_write8(pAdapter, EFUSE_CTRL + 2,
327 (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
328 (u8)((addr >> 8) & 0x03));
329 rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
331 rtw_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */
333 while ((0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
344 int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool pseudo)
348 ret = pAdapter->HalFunc.Efuse_PgPacketRead(pAdapter, offset, data, pseudo);
353 int Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
357 ret = pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, pseudo);
362 static int Efuse_PgPacketWrite_BT(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
366 ret = pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, pseudo);
371 /*-----------------------------------------------------------------------------
372 * Function: efuse_WordEnableDataRead
374 * Overview: Read allowed word in current efuse section data.
384 * 11/16/2008 MHC Create Version 0.
385 * 11/21/2008 MHC Fix Write bug when we only enable late word.
387 *---------------------------------------------------------------------------*/
388 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
390 if (!(word_en & BIT(0))) {
391 targetdata[0] = sourdata[0];
392 targetdata[1] = sourdata[1];
394 if (!(word_en & BIT(1))) {
395 targetdata[2] = sourdata[2];
396 targetdata[3] = sourdata[3];
398 if (!(word_en & BIT(2))) {
399 targetdata[4] = sourdata[4];
400 targetdata[5] = sourdata[5];
402 if (!(word_en & BIT(3))) {
403 targetdata[6] = sourdata[6];
404 targetdata[7] = sourdata[7];
408 u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool pseudo)
412 ret = pAdapter->HalFunc.Efuse_WordEnableDataWrite(pAdapter, efuse_addr, word_en, data, pseudo);
417 static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
419 return efuse_OneByteRead(padapter, address, value, false);
422 static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
424 return efuse_OneByteWrite(padapter, address, *value, false);
428 * read/wirte raw efuse data
430 u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts, u8 *data)
433 u16 real_content_len = 0, max_available_size = 0;
435 u8 (*rw8)(struct adapter *, u16, u8*);
437 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len, false);
438 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
440 if (start_addr > real_content_len)
444 if ((start_addr + cnts) > max_available_size)
451 Efuse_PowerSwitch(padapter, write, true);
453 /* e-fuse one byte read / write */
454 for (i = 0; i < cnts; i++) {
455 if (start_addr >= real_content_len) {
460 res = rw8(padapter, start_addr++, data++);
465 Efuse_PowerSwitch(padapter, write, false);
470 u16 efuse_GetMaxSize(struct adapter *padapter)
473 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size, false);
477 u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
479 Efuse_PowerSwitch(padapter, false, true);
480 *size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, false);
481 Efuse_PowerSwitch(padapter, false, false);
486 u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
490 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
492 if ((addr + cnts) > mapLen)
495 Efuse_PowerSwitch(padapter, false, true);
497 efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
499 Efuse_PowerSwitch(padapter, false, false);
504 u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
508 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
510 if ((addr + cnts) > mapLen)
513 Efuse_PowerSwitch(padapter, false, true);
515 efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
517 Efuse_PowerSwitch(padapter, false, false);
522 u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
526 u8 newdata[PGPKT_DATA_SIZE + 1];
531 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
533 if ((addr + cnts) > mapLen)
536 map = kzalloc(mapLen, GFP_KERNEL);
540 ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
544 Efuse_PowerSwitch(padapter, true, true);
546 offset = (addr >> 3);
548 memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
549 i = addr & 0x7; /* index of one package */
550 idx = 0; /* data index */
554 if (data[idx] != map[addr + idx]) {
555 word_en &= ~BIT(i >> 1);
556 newdata[i - 1] = map[addr + idx - 1];
557 newdata[i] = data[idx];
563 for (; i < PGPKT_DATA_SIZE; i += 2) {
566 if ((cnts - idx) == 1) {
567 if (data[idx] != map[addr + idx]) {
568 word_en &= ~BIT(i >> 1);
569 newdata[i] = data[idx];
570 newdata[i + 1] = map[addr + idx + 1];
575 if ((data[idx] != map[addr + idx]) ||
576 (data[idx + 1] != map[addr + idx + 1])) {
577 word_en &= ~BIT(i >> 1);
578 newdata[i] = data[idx];
579 newdata[i + 1] = data[idx + 1];
587 if (word_en != 0xF) {
588 ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
589 DBG_88E("offset=%x\n", offset);
590 DBG_88E("word_en=%x\n", word_en);
592 for (i = 0; i < PGPKT_DATA_SIZE; i++)
593 DBG_88E("data=%x \t", newdata[i]);
604 memset(newdata, 0xFF, PGPKT_DATA_SIZE);
607 Efuse_PowerSwitch(padapter, true, false);
614 u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
618 u8 newdata[PGPKT_DATA_SIZE + 1];
623 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
625 if ((addr + cnts) > mapLen)
628 map = kzalloc(mapLen, GFP_KERNEL);
632 ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
636 Efuse_PowerSwitch(padapter, true, true);
638 offset = (addr >> 3);
640 memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
641 i = addr & 0x7; /* index of one package */
642 idx = 0; /* data index */
646 if (data[idx] != map[addr + idx]) {
647 word_en &= ~BIT(i >> 1);
648 newdata[i - 1] = map[addr + idx - 1];
649 newdata[i] = data[idx];
655 for (; i < PGPKT_DATA_SIZE; i += 2) {
658 if ((cnts - idx) == 1) {
659 if (data[idx] != map[addr + idx]) {
660 word_en &= ~BIT(i >> 1);
661 newdata[i] = data[idx];
662 newdata[i + 1] = map[addr + idx + 1];
667 if ((data[idx] != map[addr + idx]) ||
668 (data[idx + 1] != map[addr + idx + 1])) {
669 word_en &= ~BIT(i >> 1);
670 newdata[i] = data[idx];
671 newdata[i + 1] = data[idx + 1];
679 if (word_en != 0xF) {
680 DBG_88E("%s: offset=%#X\n", __func__, offset);
681 DBG_88E("%s: word_en=%#X\n", __func__, word_en);
682 DBG_88E("%s: data=", __func__);
683 for (i = 0; i < PGPKT_DATA_SIZE; i++)
684 DBG_88E("0x%02X ", newdata[i]);
687 ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, false);
698 memset(newdata, 0xFF, PGPKT_DATA_SIZE);
701 Efuse_PowerSwitch(padapter, true, false);
710 /*-----------------------------------------------------------------------------
711 * Function: efuse_ShadowRead1Byte
712 * efuse_ShadowRead2Byte
713 * efuse_ShadowRead4Byte
715 * Overview: Read from efuse init map by one/two/four bytes !!!!!
725 * 11/12/2008 MHC Create Version 0.
727 *---------------------------------------------------------------------------*/
729 efuse_ShadowRead1Byte(
730 struct adapter *pAdapter,
734 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
736 *Value = pEEPROM->efuse_eeprom_data[Offset];
738 } /* EFUSE_ShadowRead1Byte */
742 efuse_ShadowRead2Byte(
743 struct adapter *pAdapter,
747 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
749 *Value = pEEPROM->efuse_eeprom_data[Offset];
750 *Value |= pEEPROM->efuse_eeprom_data[Offset + 1] << 8;
752 } /* EFUSE_ShadowRead2Byte */
754 /* Read Four Bytes */
756 efuse_ShadowRead4Byte(
757 struct adapter *pAdapter,
761 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
763 *Value = pEEPROM->efuse_eeprom_data[Offset];
764 *Value |= pEEPROM->efuse_eeprom_data[Offset + 1] << 8;
765 *Value |= pEEPROM->efuse_eeprom_data[Offset + 2] << 16;
766 *Value |= pEEPROM->efuse_eeprom_data[Offset + 3] << 24;
768 } /* efuse_ShadowRead4Byte */
770 /*-----------------------------------------------------------------------------
771 * Function: Efuse_ReadAllMap
773 * Overview: Read All Efuse content
783 * 11/11/2008 MHC Create Version 0.
785 *---------------------------------------------------------------------------*/
786 static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
790 Efuse_PowerSwitch(pAdapter, false, true);
792 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
794 efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
796 Efuse_PowerSwitch(pAdapter, false, false);
799 /*-----------------------------------------------------------------------------
800 * Function: EFUSE_ShadowMapUpdate
802 * Overview: Transfer current EFUSE content to shadow init and modify map.
812 * 11/13/2008 MHC Create Version 0.
814 *---------------------------------------------------------------------------*/
815 void EFUSE_ShadowMapUpdate(
816 struct adapter *pAdapter,
820 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
823 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
825 if (pEEPROM->bautoload_fail_flag)
826 memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
828 Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
829 } /* EFUSE_ShadowMapUpdate */
831 /*-----------------------------------------------------------------------------
832 * Function: EFUSE_ShadowRead
834 * Overview: Read from efuse init map !!!!!
844 * 11/12/2008 MHC Create Version 0.
846 *---------------------------------------------------------------------------*/
847 void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
850 efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
852 efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
854 efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
856 } /* EFUSE_ShadowRead */