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