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