1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
3 
4 #define _RTW_EFUSE_C_
5 
6 #include "../include/osdep_service.h"
7 #include "../include/drv_types.h"
8 #include "../include/rtw_efuse.h"
9 
10 /*------------------------Define local variable------------------------------*/
11 u8 fakeEfuseBank;
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};
16 
17 u32 BTEfuseUsedBytes;
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};
21 
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------------------------------*/
27 
28 #define REG_EFUSE_CTRL		0x0030
29 #define EFUSE_CTRL			REG_EFUSE_CTRL		/*  E-Fuse Control. */
30 
Efuse_Read1ByteFromFakeContent(u16 Offset,u8 * Value)31 static bool Efuse_Read1ByteFromFakeContent(u16 Offset, u8 *Value)
32 {
33 	if (Offset >= EFUSE_MAX_HW_SIZE)
34 		return false;
35 	if (fakeEfuseBank == 0)
36 		*Value = fakeEfuseContent[Offset];
37 	else
38 		*Value = fakeBTEfuseContent[fakeEfuseBank - 1][Offset];
39 	return true;
40 }
41 
42 static bool
Efuse_Write1ByteToFakeContent(struct adapter * pAdapter,u16 Offset,u8 Value)43 Efuse_Write1ByteToFakeContent(
44 			struct adapter *pAdapter,
45 			u16 Offset,
46 			u8 Value)
47 {
48 	if (Offset >= EFUSE_MAX_HW_SIZE)
49 		return false;
50 	if (fakeEfuseBank == 0) {
51 		fakeEfuseContent[Offset] = Value;
52 	} else {
53 		fakeBTEfuseContent[fakeEfuseBank - 1][Offset] = Value;
54 	}
55 	return true;
56 }
57 
58 /*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
59 u8
Efuse_CalculateWordCnts(u8 word_en)60 Efuse_CalculateWordCnts(u8 word_en)
61 {
62 	u8 word_cnts = 0;
63 	if (!(word_en & BIT(0)))
64 		word_cnts++; /*  0 : write enable */
65 	if (!(word_en & BIT(1)))
66 		word_cnts++;
67 	if (!(word_en & BIT(2)))
68 		word_cnts++;
69 	if (!(word_en & BIT(3)))
70 		word_cnts++;
71 	return word_cnts;
72 }
73 
74 /*  */
75 /* 	Description: */
76 /* 		Execute E-Fuse read byte operation. */
77 /* 		Referred from SD1 Richard. */
78 /*  */
79 /* 	Assumption: */
80 /* 		1. Boot from E-Fuse and successfully auto-load. */
81 /* 		2. PASSIVE_LEVEL (USB interface) */
82 /*  */
83 /* 	Created by Roger, 2008.10.21. */
84 /*  */
85 void
ReadEFuseByte(struct adapter * Adapter,u16 _offset,u8 * pbuf,bool pseudo)86 ReadEFuseByte(
87 		struct adapter *Adapter,
88 		u16 _offset,
89 		u8 *pbuf,
90 		bool pseudo)
91 {
92 	u32 value32;
93 	u8 readbyte;
94 	u16 retry;
95 
96 	if (pseudo) {
97 		Efuse_Read1ByteFromFakeContent(_offset, pbuf);
98 		return;
99 	}
100 
101 	/* Write Address */
102 	rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
103 	readbyte = rtw_read8(Adapter, EFUSE_CTRL + 2);
104 	rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
105 
106 	/* Write bit 32 0 */
107 	readbyte = rtw_read8(Adapter, EFUSE_CTRL + 3);
108 	rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
109 
110 	/* Check bit 32 read-ready */
111 	retry = 0;
112 	value32 = rtw_read32(Adapter, EFUSE_CTRL);
113 	while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
114 		value32 = rtw_read32(Adapter, EFUSE_CTRL);
115 		retry++;
116 	}
117 
118 	/*  20100205 Joseph: Add delay suggested by SD1 Victor. */
119 	/*  This fix the problem that Efuse read error in high temperature condition. */
120 	/*  Designer says that there shall be some delay after ready bit is set, or the */
121 	/*  result will always stay on last data we read. */
122 	udelay(50);
123 	value32 = rtw_read32(Adapter, EFUSE_CTRL);
124 
125 	*pbuf = (u8)(value32 & 0xff);
126 }
127 
128 /*  11/16/2008 MH Read one byte from real Efuse. */
efuse_OneByteRead(struct adapter * pAdapter,u16 addr,u8 * data,bool pseudo)129 u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
130 {
131 	u8 tmpidx = 0;
132 	u8 result;
133 
134 	if (pseudo) {
135 		result = Efuse_Read1ByteFromFakeContent(addr, data);
136 		return result;
137 	}
138 	/*  -----------------e-fuse reg ctrl --------------------------------- */
139 	/* address */
140 	rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
141 	rtw_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
142 		   (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
143 
144 	rtw_write8(pAdapter, EFUSE_CTRL + 3,  0x72);/* read cmd */
145 
146 	while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
147 		tmpidx++;
148 	if (tmpidx < 100) {
149 		*data = rtw_read8(pAdapter, EFUSE_CTRL);
150 		result = true;
151 	} else {
152 		*data = 0xff;
153 		result = false;
154 	}
155 	return result;
156 }
157 
158 /*  11/16/2008 MH Write one byte to reald Efuse. */
efuse_OneByteWrite(struct adapter * pAdapter,u16 addr,u8 data,bool pseudo)159 u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
160 {
161 	u8 tmpidx = 0;
162 	u8 result;
163 
164 	if (pseudo) {
165 		result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
166 		return result;
167 	}
168 
169 	/*  -----------------e-fuse reg ctrl --------------------------------- */
170 	/* address */
171 	rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
172 	rtw_write8(pAdapter, EFUSE_CTRL + 2,
173 		   (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
174 		   (u8)((addr >> 8) & 0x03));
175 	rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
176 
177 	rtw_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */
178 
179 	while ((0x80 &  rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
180 		tmpidx++;
181 
182 	if (tmpidx < 100)
183 		result = true;
184 	else
185 		result = false;
186 
187 	return result;
188 }
189 
190 /*-----------------------------------------------------------------------------
191  * Function:	efuse_WordEnableDataRead
192  *
193  * Overview:	Read allowed word in current efuse section data.
194  *
195  * Input:       NONE
196  *
197  * Output:      NONE
198  *
199  * Return:      NONE
200  *
201  * Revised History:
202  * When			Who		Remark
203  * 11/16/2008	MHC		Create Version 0.
204  * 11/21/2008	MHC		Fix Write bug when we only enable late word.
205  *
206  *---------------------------------------------------------------------------*/
efuse_WordEnableDataRead(u8 word_en,u8 * sourdata,u8 * targetdata)207 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
208 {
209 	if (!(word_en & BIT(0))) {
210 		targetdata[0] = sourdata[0];
211 		targetdata[1] = sourdata[1];
212 	}
213 	if (!(word_en & BIT(1))) {
214 		targetdata[2] = sourdata[2];
215 		targetdata[3] = sourdata[3];
216 	}
217 	if (!(word_en & BIT(2))) {
218 		targetdata[4] = sourdata[4];
219 		targetdata[5] = sourdata[5];
220 	}
221 	if (!(word_en & BIT(3))) {
222 		targetdata[6] = sourdata[6];
223 		targetdata[7] = sourdata[7];
224 	}
225 }
226 
227 /*-----------------------------------------------------------------------------
228  * Function:	Efuse_ReadAllMap
229  *
230  * Overview:	Read All Efuse content
231  *
232  * Input:       NONE
233  *
234  * Output:      NONE
235  *
236  * Return:      NONE
237  *
238  * Revised History:
239  * When			Who		Remark
240  * 11/11/2008	MHC		Create Version 0.
241  *
242  *---------------------------------------------------------------------------*/
Efuse_ReadAllMap(struct adapter * pAdapter,u8 efuseType,u8 * Efuse,bool pseudo)243 static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
244 {
245 	u16 mapLen = 0;
246 
247 	rtl8188e_EfusePowerSwitch(pAdapter, false, true);
248 
249 	rtl8188e_EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
250 
251 	rtl8188e_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
252 
253 	rtl8188e_EfusePowerSwitch(pAdapter, false, false);
254 }
255 
256 /*-----------------------------------------------------------------------------
257  * Function:	EFUSE_ShadowMapUpdate
258  *
259  * Overview:	Transfer current EFUSE content to shadow init and modify map.
260  *
261  * Input:       NONE
262  *
263  * Output:      NONE
264  *
265  * Return:      NONE
266  *
267  * Revised History:
268  * When			Who		Remark
269  * 11/13/2008	MHC		Create Version 0.
270  *
271  *---------------------------------------------------------------------------*/
EFUSE_ShadowMapUpdate(struct adapter * pAdapter,u8 efuseType,bool pseudo)272 void EFUSE_ShadowMapUpdate(
273 	struct adapter *pAdapter,
274 	u8 efuseType,
275 	bool pseudo)
276 {
277 	struct eeprom_priv *pEEPROM = &pAdapter->eeprompriv;
278 	u16 mapLen = 0;
279 
280 	rtl8188e_EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
281 
282 	if (pEEPROM->bautoload_fail_flag)
283 		memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
284 	else
285 		Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
286 } /*  EFUSE_ShadowMapUpdate */
287