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