1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #include <drv_types.h>
8 #include <hal_data.h>
9 #include <linux/jiffies.h>
10 
11 
12 /* Define global variables */
13 u8 fakeEfuseBank;
14 u32 fakeEfuseUsedBytes;
15 u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
16 u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
17 u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
18 
19 u32 BTEfuseUsedBytes;
20 u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
21 u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
22 u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
23 
24 u32 fakeBTEfuseUsedBytes;
25 u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
26 u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
27 u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
28 
29 #define REG_EFUSE_CTRL		0x0030
30 #define EFUSE_CTRL			REG_EFUSE_CTRL		/*  E-Fuse Control. */
31 
32 static bool
Efuse_Read1ByteFromFakeContent(u16 Offset,u8 * Value)33 Efuse_Read1ByteFromFakeContent(u16 Offset, u8 *Value)
34 {
35 	if (Offset >= EFUSE_MAX_HW_SIZE)
36 		return false;
37 	if (fakeEfuseBank == 0)
38 		*Value = fakeEfuseContent[Offset];
39 	else
40 		*Value = fakeBTEfuseContent[fakeEfuseBank - 1][Offset];
41 	return true;
42 }
43 
44 static bool
Efuse_Write1ByteToFakeContent(u16 Offset,u8 Value)45 Efuse_Write1ByteToFakeContent(u16 Offset, u8 Value)
46 {
47 	if (Offset >= EFUSE_MAX_HW_SIZE)
48 		return false;
49 	if (fakeEfuseBank == 0)
50 		fakeEfuseContent[Offset] = Value;
51 	else
52 		fakeBTEfuseContent[fakeEfuseBank - 1][Offset] = Value;
53 	return true;
54 }
55 
56 /*-----------------------------------------------------------------------------
57  * Function:	Efuse_PowerSwitch
58  *
59  * Overview:	When we want to enable write operation, we should change to
60  *			pwr on state. When we stop write, we should switch to 500k mode
61  *			and disable LDO 2.5V.
62  *
63  * Input:       NONE
64  *
65  * Output:      NONE
66  *
67  * Return:      NONE
68  *
69  * Revised History:
70  * When			Who		Remark
71  * 11/17/2008	MHC		Create Version 0.
72  *
73  *---------------------------------------------------------------------------*/
74 void
Efuse_PowerSwitch(struct adapter * padapter,u8 bWrite,u8 PwrState)75 Efuse_PowerSwitch(
76 struct adapter *padapter,
77 u8 bWrite,
78 u8 PwrState)
79 {
80 	Hal_EfusePowerSwitch(padapter, bWrite, PwrState);
81 }
82 
83 /*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
84 u8
Efuse_CalculateWordCnts(u8 word_en)85 Efuse_CalculateWordCnts(u8 word_en)
86 {
87 	u8 word_cnts = 0;
88 	if (!(word_en & BIT(0)))
89 		word_cnts++; /*  0 : write enable */
90 	if (!(word_en & BIT(1)))
91 		word_cnts++;
92 	if (!(word_en & BIT(2)))
93 		word_cnts++;
94 	if (!(word_en & BIT(3)))
95 		word_cnts++;
96 	return word_cnts;
97 }
98 
99 /*  */
100 /* Description: */
101 /*		1. Execute E-Fuse read byte operation according as map offset and */
102 /*			save to E-Fuse table. */
103 /*		2. Referred from SD1 Richard. */
104 /*  */
105 /* Assumption: */
106 /*		1. Boot from E-Fuse and successfully auto-load. */
107 /*		2. PASSIVE_LEVEL (USB interface) */
108 /*  */
109 /* Created by Roger, 2008.10.21. */
110 /*  */
111 /* 2008/12/12 MH	1. Reorganize code flow and reserve bytes. and add description. */
112 /*					2. Add efuse utilization collect. */
113 /* 2008/12/22 MH	Read Efuse must check if we write section 1 data again!!! Sec1 */
114 /*					write addr must be after sec5. */
115 /*  */
116 
117 void
118 efuse_ReadEFuse(
119 	struct adapter *Adapter,
120 	u8 efuseType,
121 	u16		_offset,
122 	u16		_size_byte,
123 	u8 *pbuf,
124 bool	bPseudoTest
125 	);
126 void
efuse_ReadEFuse(struct adapter * Adapter,u8 efuseType,u16 _offset,u16 _size_byte,u8 * pbuf,bool bPseudoTest)127 efuse_ReadEFuse(
128 	struct adapter *Adapter,
129 	u8 efuseType,
130 	u16		_offset,
131 	u16		_size_byte,
132 	u8 *pbuf,
133 bool	bPseudoTest
134 	)
135 {
136 	Hal_ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
137 }
138 
139 void
EFUSE_GetEfuseDefinition(struct adapter * padapter,u8 efuseType,u8 type,void * pOut,bool bPseudoTest)140 EFUSE_GetEfuseDefinition(
141 	struct adapter *padapter,
142 	u8 efuseType,
143 	u8 type,
144 	void	*pOut,
145 	bool		bPseudoTest
146 	)
147 {
148 	Hal_GetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest);
149 }
150 
151 /*-----------------------------------------------------------------------------
152  * Function:	EFUSE_Read1Byte
153  *
154  * Overview:	Copy from WMAC fot EFUSE read 1 byte.
155  *
156  * Input:       NONE
157  *
158  * Output:      NONE
159  *
160  * Return:      NONE
161  *
162  * Revised History:
163  * When			Who		Remark
164  * 09/23/2008	MHC		Copy from WMAC.
165  *
166  *---------------------------------------------------------------------------*/
167 u8
EFUSE_Read1Byte(struct adapter * Adapter,u16 Address)168 EFUSE_Read1Byte(
169 struct adapter *Adapter,
170 u16		Address)
171 {
172 	u8 Bytetemp = {0x00};
173 	u8 temp = {0x00};
174 	u32 k = 0;
175 	u16 contentLen = 0;
176 
177 	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
178 
179 	if (Address < contentLen) {/* E-fuse 512Byte */
180 		/* Write E-fuse Register address bit0~7 */
181 		temp = Address & 0xFF;
182 		rtw_write8(Adapter, EFUSE_CTRL + 1, temp);
183 		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 2);
184 		/* Write E-fuse Register address bit8~9 */
185 		temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
186 		rtw_write8(Adapter, EFUSE_CTRL + 2, temp);
187 
188 		/* Write 0x30[31]= 0 */
189 		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
190 		temp = Bytetemp & 0x7F;
191 		rtw_write8(Adapter, EFUSE_CTRL + 3, temp);
192 
193 		/* Wait Write-ready (0x30[31]= 1) */
194 		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
195 		while (!(Bytetemp & 0x80)) {
196 			Bytetemp = rtw_read8(Adapter, EFUSE_CTRL + 3);
197 			k++;
198 			if (k == 1000)
199 				break;
200 		}
201 		return rtw_read8(Adapter, EFUSE_CTRL);
202 	} else
203 		return 0xFF;
204 
205 } /* EFUSE_Read1Byte */
206 
207 /*  11/16/2008 MH Read one byte from real Efuse. */
208 u8
efuse_OneByteRead(struct adapter * padapter,u16 addr,u8 * data,bool bPseudoTest)209 efuse_OneByteRead(
210 struct adapter *padapter,
211 u16	addr,
212 u8	*data,
213 bool		bPseudoTest)
214 {
215 	u32 tmpidx = 0;
216 	u8 bResult;
217 	u8 readbyte;
218 
219 	if (bPseudoTest)
220 		return Efuse_Read1ByteFromFakeContent(addr, data);
221 
222 	/*  <20130121, Kordan> For SMIC EFUSE specificatoin. */
223 	/* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
224 	/* PHY_SetMacReg(padapter, 0x34, BIT11, 0); */
225 	rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) & (~BIT11));
226 
227 	/*  -----------------e-fuse reg ctrl --------------------------------- */
228 	/* address */
229 	rtw_write8(padapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
230 	rtw_write8(padapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
231 	(rtw_read8(padapter, EFUSE_CTRL + 2) & 0xFC));
232 
233 	/* rtw_write8(padapter, EFUSE_CTRL+3,  0x72); read cmd */
234 	/* Write bit 32 0 */
235 	readbyte = rtw_read8(padapter, EFUSE_CTRL + 3);
236 	rtw_write8(padapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
237 
238 	while (!(0x80 & rtw_read8(padapter, EFUSE_CTRL + 3)) && (tmpidx < 1000)) {
239 		mdelay(1);
240 		tmpidx++;
241 	}
242 	if (tmpidx < 100) {
243 		*data = rtw_read8(padapter, EFUSE_CTRL);
244 		bResult = true;
245 	} else {
246 		*data = 0xff;
247 		bResult = false;
248 	}
249 
250 	return bResult;
251 }
252 
253 /*  11/16/2008 MH Write one byte to reald Efuse. */
efuse_OneByteWrite(struct adapter * padapter,u16 addr,u8 data,bool bPseudoTest)254 u8 efuse_OneByteWrite(struct adapter *padapter, u16 addr, u8 data, bool bPseudoTest)
255 {
256 	u8 tmpidx = 0;
257 	u8 bResult = false;
258 
259 	if (bPseudoTest)
260 		return Efuse_Write1ByteToFakeContent(addr, data);
261 
262 	/*  -----------------e-fuse reg ctrl --------------------------------- */
263 	/* address */
264 
265 	/*  <20130227, Kordan> 8192E MP chip A-cut had better not set 0x34[11] until B-Cut. */
266 
267 	/*  <20130121, Kordan> For SMIC EFUSE specificatoin. */
268 	/* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
269 	/* PHY_SetMacReg(padapter, 0x34, BIT11, 1); */
270 	rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) | (BIT11));
271 	rtw_write32(padapter, EFUSE_CTRL, 0x90600000 | ((addr << 8 | data)));
272 
273 	while ((0x80 &  rtw_read8(padapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) {
274 		mdelay(1);
275 		tmpidx++;
276 	}
277 
278 	if (tmpidx < 100)
279 		bResult = true;
280 	else
281 		bResult = false;
282 
283 	/*  disable Efuse program enable */
284 	PHY_SetMacReg(padapter, EFUSE_TEST, BIT(11), 0);
285 
286 	return bResult;
287 }
288 
289 u8
Efuse_WordEnableDataWrite(struct adapter * padapter,u16 efuse_addr,u8 word_en,u8 * data,bool bPseudoTest)290 Efuse_WordEnableDataWrite(struct adapter *padapter,
291 						u16		efuse_addr,
292 						u8 word_en,
293 						u8 *data,
294 						bool		bPseudoTest)
295 {
296 	return padapter->HalFunc.Efuse_WordEnableDataWrite(padapter, efuse_addr,
297 							   word_en, data,
298 							   bPseudoTest);
299 }
300 
301 /*-----------------------------------------------------------------------------
302  * Function:	Efuse_ReadAllMap
303  *
304  * Overview:	Read All Efuse content
305  *
306  * Input:       NONE
307  *
308  * Output:      NONE
309  *
310  * Return:      NONE
311  *
312  * Revised History:
313  * When			Who		Remark
314  * 11/11/2008	MHC		Create Version 0.
315  *
316  *---------------------------------------------------------------------------*/
317 void
318 Efuse_ReadAllMap(
319 	struct adapter *padapter,
320 	u8 efuseType,
321 	u8 *Efuse,
322 	bool		bPseudoTest);
Efuse_ReadAllMap(struct adapter * padapter,u8 efuseType,u8 * Efuse,bool bPseudoTest)323 void Efuse_ReadAllMap(struct adapter *padapter, u8 efuseType, u8 *Efuse, bool bPseudoTest)
324 {
325 	u16 mapLen = 0;
326 
327 	Efuse_PowerSwitch(padapter, false, true);
328 
329 	EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
330 
331 	efuse_ReadEFuse(padapter, efuseType, 0, mapLen, Efuse, bPseudoTest);
332 
333 	Efuse_PowerSwitch(padapter, false, false);
334 }
335 
336 /*-----------------------------------------------------------------------------
337  * Function:	efuse_ShadowRead1Byte
338  *		efuse_ShadowRead2Byte
339  *		efuse_ShadowRead4Byte
340  *
341  * Overview:	Read from efuse init map by one/two/four bytes !!!!!
342  *
343  * Input:       NONE
344  *
345  * Output:      NONE
346  *
347  * Return:      NONE
348  *
349  * Revised History:
350  * When			Who		Remark
351  * 11/12/2008	MHC		Create Version 0.
352  *
353  *---------------------------------------------------------------------------*/
efuse_ShadowRead1Byte(struct adapter * padapter,u16 Offset,u8 * Value)354 static void efuse_ShadowRead1Byte(struct adapter *padapter, u16 Offset, u8 *Value)
355 {
356 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
357 
358 	*Value = pEEPROM->efuse_eeprom_data[Offset];
359 
360 }	/*  EFUSE_ShadowRead1Byte */
361 
362 /* Read Two Bytes */
efuse_ShadowRead2Byte(struct adapter * padapter,u16 Offset,u16 * Value)363 static void efuse_ShadowRead2Byte(struct adapter *padapter, u16 Offset, u16 *Value)
364 {
365 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
366 
367 	*Value = pEEPROM->efuse_eeprom_data[Offset];
368 	*Value |= pEEPROM->efuse_eeprom_data[Offset + 1] << 8;
369 
370 }	/*  EFUSE_ShadowRead2Byte */
371 
372 /* Read Four Bytes */
efuse_ShadowRead4Byte(struct adapter * padapter,u16 Offset,u32 * Value)373 static void efuse_ShadowRead4Byte(struct adapter *padapter, u16 Offset, u32 *Value)
374 {
375 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
376 
377 	*Value = pEEPROM->efuse_eeprom_data[Offset];
378 	*Value |= pEEPROM->efuse_eeprom_data[Offset + 1] << 8;
379 	*Value |= pEEPROM->efuse_eeprom_data[Offset + 2] << 16;
380 	*Value |= pEEPROM->efuse_eeprom_data[Offset + 3] << 24;
381 
382 }	/*  efuse_ShadowRead4Byte */
383 
384 /*-----------------------------------------------------------------------------
385  * Function:	EFUSE_ShadowMapUpdate
386  *
387  * Overview:	Transfer current EFUSE content to shadow init and modify map.
388  *
389  * Input:       NONE
390  *
391  * Output:      NONE
392  *
393  * Return:      NONE
394  *
395  * Revised History:
396  * When			Who		Remark
397  * 11/13/2008	MHC		Create Version 0.
398  *
399  *---------------------------------------------------------------------------*/
EFUSE_ShadowMapUpdate(struct adapter * padapter,u8 efuseType,bool bPseudoTest)400 void EFUSE_ShadowMapUpdate(struct adapter *padapter, u8 efuseType, bool bPseudoTest)
401 {
402 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
403 	u16 mapLen = 0;
404 
405 	EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
406 
407 	if (pEEPROM->bautoload_fail_flag)
408 		memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
409 	else
410 		Efuse_ReadAllMap(padapter, efuseType, pEEPROM->efuse_eeprom_data, bPseudoTest);
411 
412 	/* PlatformMoveMemory((void *)&pHalData->EfuseMap[EFUSE_MODIFY_MAP][0], */
413 	/* void *)&pHalData->EfuseMap[EFUSE_INIT_MAP][0], mapLen); */
414 } /*  EFUSE_ShadowMapUpdate */
415 
416 
417 /*-----------------------------------------------------------------------------
418  * Function:	EFUSE_ShadowRead
419  *
420  * Overview:	Read from efuse init map !!!!!
421  *
422  * Input:       NONE
423  *
424  * Output:      NONE
425  *
426  * Return:      NONE
427  *
428  * Revised History:
429  * When			Who		Remark
430  * 11/12/2008	MHC		Create Version 0.
431  *
432  *---------------------------------------------------------------------------*/
EFUSE_ShadowRead(struct adapter * padapter,u8 Type,u16 Offset,u32 * Value)433 void EFUSE_ShadowRead(struct adapter *padapter, u8 Type, u16 Offset, u32 *Value)
434 {
435 	if (Type == 1)
436 		efuse_ShadowRead1Byte(padapter, Offset, (u8 *)Value);
437 	else if (Type == 2)
438 		efuse_ShadowRead2Byte(padapter, Offset, (u16 *)Value);
439 	else if (Type == 4)
440 		efuse_ShadowRead4Byte(padapter, Offset, (u32 *)Value);
441 
442 }	/* EFUSE_ShadowRead*/
443