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