158391efdSNathan Chancellor // SPDX-License-Identifier: GPL-2.0
2554c0a3aSHans de Goede /******************************************************************************
3554c0a3aSHans de Goede  *
4554c0a3aSHans de Goede  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5554c0a3aSHans de Goede  *
6554c0a3aSHans de Goede  ******************************************************************************/
7554c0a3aSHans de Goede #define _RTW_EFUSE_C_
8554c0a3aSHans de Goede 
9554c0a3aSHans de Goede #include <drv_types.h>
10554c0a3aSHans de Goede #include <rtw_debug.h>
11554c0a3aSHans de Goede #include <hal_data.h>
12554c0a3aSHans de Goede #include <linux/jiffies.h>
13554c0a3aSHans de Goede 
14554c0a3aSHans de Goede 
15e8466ea7SHenriette Hofmeier /* Define global variables */
16cbb2cb50SHenriette Hofmeier u8 fakeEfuseBank;
17cbb2cb50SHenriette Hofmeier u32 fakeEfuseUsedBytes;
18554c0a3aSHans de Goede u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
19554c0a3aSHans de Goede u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
20554c0a3aSHans de Goede u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
21554c0a3aSHans de Goede 
22cbb2cb50SHenriette Hofmeier u32 BTEfuseUsedBytes;
23554c0a3aSHans de Goede u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
24554c0a3aSHans de Goede u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
25554c0a3aSHans de Goede u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
26554c0a3aSHans de Goede 
27cbb2cb50SHenriette Hofmeier u32 fakeBTEfuseUsedBytes;
28554c0a3aSHans de Goede u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
29554c0a3aSHans de Goede u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
30554c0a3aSHans de Goede u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
31554c0a3aSHans de Goede 
32554c0a3aSHans de Goede #define REG_EFUSE_CTRL		0x0030
33554c0a3aSHans de Goede #define EFUSE_CTRL			REG_EFUSE_CTRL		/*  E-Fuse Control. */
34554c0a3aSHans de Goede 
35554c0a3aSHans de Goede bool
36554c0a3aSHans de Goede Efuse_Read1ByteFromFakeContent(
37554c0a3aSHans de Goede 	struct adapter *padapter,
38554c0a3aSHans de Goede 	u16 	Offset,
39554c0a3aSHans de Goede 	u8 *Value);
40554c0a3aSHans de Goede bool
41554c0a3aSHans de Goede Efuse_Read1ByteFromFakeContent(
42554c0a3aSHans de Goede 	struct adapter *padapter,
43554c0a3aSHans de Goede 	u16 	Offset,
44554c0a3aSHans de Goede 	u8 *Value)
45554c0a3aSHans de Goede {
46554c0a3aSHans de Goede 	if (Offset >= EFUSE_MAX_HW_SIZE) {
47554c0a3aSHans de Goede 		return false;
48554c0a3aSHans de Goede 	}
49554c0a3aSHans de Goede 	/* DbgPrint("Read fake content, offset = %d\n", Offset); */
50554c0a3aSHans de Goede 	if (fakeEfuseBank == 0)
51554c0a3aSHans de Goede 		*Value = fakeEfuseContent[Offset];
52554c0a3aSHans de Goede 	else
53554c0a3aSHans de Goede 		*Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
54554c0a3aSHans de Goede 	return true;
55554c0a3aSHans de Goede }
56554c0a3aSHans de Goede 
57554c0a3aSHans de Goede bool
58554c0a3aSHans de Goede Efuse_Write1ByteToFakeContent(
59554c0a3aSHans de Goede 	struct adapter *padapter,
60554c0a3aSHans de Goede 	u16 	Offset,
61554c0a3aSHans de Goede 	u8 Value);
62554c0a3aSHans de Goede bool
63554c0a3aSHans de Goede Efuse_Write1ByteToFakeContent(
64554c0a3aSHans de Goede 	struct adapter *padapter,
65554c0a3aSHans de Goede 	u16 	Offset,
66554c0a3aSHans de Goede 	u8 Value)
67554c0a3aSHans de Goede {
68554c0a3aSHans de Goede 	if (Offset >= EFUSE_MAX_HW_SIZE) {
69554c0a3aSHans de Goede 		return false;
70554c0a3aSHans de Goede 	}
71554c0a3aSHans de Goede 	if (fakeEfuseBank == 0)
72554c0a3aSHans de Goede 		fakeEfuseContent[Offset] = Value;
73554c0a3aSHans de Goede 	else{
74554c0a3aSHans de Goede 		fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
75554c0a3aSHans de Goede 	}
76554c0a3aSHans de Goede 	return true;
77554c0a3aSHans de Goede }
78554c0a3aSHans de Goede 
79554c0a3aSHans de Goede /*-----------------------------------------------------------------------------
80554c0a3aSHans de Goede  * Function:	Efuse_PowerSwitch
81554c0a3aSHans de Goede  *
82554c0a3aSHans de Goede  * Overview:	When we want to enable write operation, we should change to
83554c0a3aSHans de Goede  *			pwr on state. When we stop write, we should switch to 500k mode
84554c0a3aSHans de Goede  *			and disable LDO 2.5V.
85554c0a3aSHans de Goede  *
86554c0a3aSHans de Goede  * Input:       NONE
87554c0a3aSHans de Goede  *
88554c0a3aSHans de Goede  * Output:      NONE
89554c0a3aSHans de Goede  *
90554c0a3aSHans de Goede  * Return:      NONE
91554c0a3aSHans de Goede  *
92554c0a3aSHans de Goede  * Revised History:
93554c0a3aSHans de Goede  * When			Who		Remark
94554c0a3aSHans de Goede  * 11/17/2008	MHC		Create Version 0.
95554c0a3aSHans de Goede  *
96554c0a3aSHans de Goede  *---------------------------------------------------------------------------*/
97554c0a3aSHans de Goede void
98554c0a3aSHans de Goede Efuse_PowerSwitch(
99554c0a3aSHans de Goede struct adapter *padapter,
100554c0a3aSHans de Goede u8 bWrite,
101554c0a3aSHans de Goede u8 PwrState)
102554c0a3aSHans de Goede {
103554c0a3aSHans de Goede 	padapter->HalFunc.EfusePowerSwitch(padapter, bWrite, PwrState);
104554c0a3aSHans de Goede }
105554c0a3aSHans de Goede 
106554c0a3aSHans de Goede /*-----------------------------------------------------------------------------
107554c0a3aSHans de Goede  * Function:	Efuse_GetCurrentSize
108554c0a3aSHans de Goede  *
109554c0a3aSHans de Goede  * Overview:	Get current efuse size!!!
110554c0a3aSHans de Goede  *
111554c0a3aSHans de Goede  * Input:       NONE
112554c0a3aSHans de Goede  *
113554c0a3aSHans de Goede  * Output:      NONE
114554c0a3aSHans de Goede  *
115554c0a3aSHans de Goede  * Return:      NONE
116554c0a3aSHans de Goede  *
117554c0a3aSHans de Goede  * Revised History:
118554c0a3aSHans de Goede  * When			Who		Remark
119554c0a3aSHans de Goede  * 11/16/2008	MHC		Create Version 0.
120554c0a3aSHans de Goede  *
121554c0a3aSHans de Goede  *---------------------------------------------------------------------------*/
122554c0a3aSHans de Goede u16
123554c0a3aSHans de Goede Efuse_GetCurrentSize(
124554c0a3aSHans de Goede 	struct adapter *padapter,
125554c0a3aSHans de Goede 	u8 	efuseType,
126554c0a3aSHans de Goede 	bool		bPseudoTest)
127554c0a3aSHans de Goede {
128554c0a3aSHans de Goede 	u16 ret = 0;
129554c0a3aSHans de Goede 
130554c0a3aSHans de Goede 	ret = padapter->HalFunc.EfuseGetCurrentSize(padapter, efuseType, bPseudoTest);
131554c0a3aSHans de Goede 
132554c0a3aSHans de Goede 	return ret;
133554c0a3aSHans de Goede }
134554c0a3aSHans de Goede 
135554c0a3aSHans de Goede /*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
136554c0a3aSHans de Goede u8
137554c0a3aSHans de Goede Efuse_CalculateWordCnts(u8 word_en)
138554c0a3aSHans de Goede {
139554c0a3aSHans de Goede 	u8 word_cnts = 0;
140554c0a3aSHans de Goede 	if (!(word_en & BIT(0)))
141554c0a3aSHans de Goede 		word_cnts++; /*  0 : write enable */
142554c0a3aSHans de Goede 	if (!(word_en & BIT(1)))
143554c0a3aSHans de Goede 		word_cnts++;
144554c0a3aSHans de Goede 	if (!(word_en & BIT(2)))
145554c0a3aSHans de Goede 		word_cnts++;
146554c0a3aSHans de Goede 	if (!(word_en & BIT(3)))
147554c0a3aSHans de Goede 		word_cnts++;
148554c0a3aSHans de Goede 	return word_cnts;
149554c0a3aSHans de Goede }
150554c0a3aSHans de Goede 
151554c0a3aSHans de Goede /*  */
152554c0a3aSHans de Goede /* 	Description: */
153554c0a3aSHans de Goede /* 		1. Execute E-Fuse read byte operation according as map offset and */
154554c0a3aSHans de Goede /* 		    save to E-Fuse table. */
155a4b99f3dSXaralampos Mainas /* 		2. Referred from SD1 Richard. */
156554c0a3aSHans de Goede /*  */
157554c0a3aSHans de Goede /* 	Assumption: */
158554c0a3aSHans de Goede /* 		1. Boot from E-Fuse and successfully auto-load. */
159554c0a3aSHans de Goede /* 		2. PASSIVE_LEVEL (USB interface) */
160554c0a3aSHans de Goede /*  */
161554c0a3aSHans de Goede /* 	Created by Roger, 2008.10.21. */
162554c0a3aSHans de Goede /*  */
163554c0a3aSHans de Goede /* 	2008/12/12 MH	1. Reorganize code flow and reserve bytes. and add description. */
164554c0a3aSHans de Goede /* 					2. Add efuse utilization collect. */
165554c0a3aSHans de Goede /* 	2008/12/22 MH	Read Efuse must check if we write section 1 data again!!! Sec1 */
166554c0a3aSHans de Goede /* 					write addr must be after sec5. */
167554c0a3aSHans de Goede /*  */
168554c0a3aSHans de Goede 
169554c0a3aSHans de Goede void
170554c0a3aSHans de Goede efuse_ReadEFuse(
171554c0a3aSHans de Goede 	struct adapter *Adapter,
172554c0a3aSHans de Goede 	u8 efuseType,
173554c0a3aSHans de Goede 	u16 	_offset,
174554c0a3aSHans de Goede 	u16 	_size_byte,
175554c0a3aSHans de Goede 	u8 *pbuf,
176554c0a3aSHans de Goede bool	bPseudoTest
177554c0a3aSHans de Goede 	);
178554c0a3aSHans de Goede void
179554c0a3aSHans de Goede efuse_ReadEFuse(
180554c0a3aSHans de Goede 	struct adapter *Adapter,
181554c0a3aSHans de Goede 	u8 efuseType,
182554c0a3aSHans de Goede 	u16 	_offset,
183554c0a3aSHans de Goede 	u16 	_size_byte,
184554c0a3aSHans de Goede 	u8 *pbuf,
185554c0a3aSHans de Goede bool	bPseudoTest
186554c0a3aSHans de Goede 	)
187554c0a3aSHans de Goede {
188554c0a3aSHans de Goede 	Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
189554c0a3aSHans de Goede }
190554c0a3aSHans de Goede 
191554c0a3aSHans de Goede void
192554c0a3aSHans de Goede EFUSE_GetEfuseDefinition(
193554c0a3aSHans de Goede 	struct adapter *padapter,
194554c0a3aSHans de Goede 	u8 efuseType,
195554c0a3aSHans de Goede 	u8 type,
196554c0a3aSHans de Goede 	void 	*pOut,
197554c0a3aSHans de Goede 	bool		bPseudoTest
198554c0a3aSHans de Goede 	)
199554c0a3aSHans de Goede {
200554c0a3aSHans de Goede 	padapter->HalFunc.EFUSEGetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest);
201554c0a3aSHans de Goede }
202554c0a3aSHans de Goede 
203554c0a3aSHans de Goede /*-----------------------------------------------------------------------------
204554c0a3aSHans de Goede  * Function:	EFUSE_Read1Byte
205554c0a3aSHans de Goede  *
206554c0a3aSHans de Goede  * Overview:	Copy from WMAC fot EFUSE read 1 byte.
207554c0a3aSHans de Goede  *
208554c0a3aSHans de Goede  * Input:       NONE
209554c0a3aSHans de Goede  *
210554c0a3aSHans de Goede  * Output:      NONE
211554c0a3aSHans de Goede  *
212554c0a3aSHans de Goede  * Return:      NONE
213554c0a3aSHans de Goede  *
214554c0a3aSHans de Goede  * Revised History:
215554c0a3aSHans de Goede  * When			Who		Remark
216554c0a3aSHans de Goede  * 09/23/2008	MHC		Copy from WMAC.
217554c0a3aSHans de Goede  *
218554c0a3aSHans de Goede  *---------------------------------------------------------------------------*/
219554c0a3aSHans de Goede u8
220554c0a3aSHans de Goede EFUSE_Read1Byte(
221554c0a3aSHans de Goede struct adapter *Adapter,
222554c0a3aSHans de Goede u16 	Address)
223554c0a3aSHans de Goede {
224554c0a3aSHans de Goede 	u8 data;
225554c0a3aSHans de Goede 	u8 Bytetemp = {0x00};
226554c0a3aSHans de Goede 	u8 temp = {0x00};
227554c0a3aSHans de Goede 	u32 k = 0;
228554c0a3aSHans de Goede 	u16 contentLen = 0;
229554c0a3aSHans de Goede 
230554c0a3aSHans de Goede 	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
231554c0a3aSHans de Goede 
232554c0a3aSHans de Goede 	if (Address < contentLen) {/* E-fuse 512Byte */
233554c0a3aSHans de Goede 		/* Write E-fuse Register address bit0~7 */
234554c0a3aSHans de Goede 		temp = Address & 0xFF;
235554c0a3aSHans de Goede 		rtw_write8(Adapter, EFUSE_CTRL+1, temp);
236554c0a3aSHans de Goede 		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
237554c0a3aSHans de Goede 		/* Write E-fuse Register address bit8~9 */
238554c0a3aSHans de Goede 		temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
239554c0a3aSHans de Goede 		rtw_write8(Adapter, EFUSE_CTRL+2, temp);
240554c0a3aSHans de Goede 
241554c0a3aSHans de Goede 		/* Write 0x30[31]= 0 */
242554c0a3aSHans de Goede 		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
243554c0a3aSHans de Goede 		temp = Bytetemp & 0x7F;
244554c0a3aSHans de Goede 		rtw_write8(Adapter, EFUSE_CTRL+3, temp);
245554c0a3aSHans de Goede 
246554c0a3aSHans de Goede 		/* Wait Write-ready (0x30[31]= 1) */
247554c0a3aSHans de Goede 		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
248554c0a3aSHans de Goede 		while (!(Bytetemp & 0x80)) {
249554c0a3aSHans de Goede 			Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
250554c0a3aSHans de Goede 			k++;
251554c0a3aSHans de Goede 			if (k == 1000) {
252554c0a3aSHans de Goede 				k = 0;
253554c0a3aSHans de Goede 				break;
254554c0a3aSHans de Goede 			}
255554c0a3aSHans de Goede 		}
256554c0a3aSHans de Goede 		data = rtw_read8(Adapter, EFUSE_CTRL);
257554c0a3aSHans de Goede 		return data;
258554c0a3aSHans de Goede 	} else
259554c0a3aSHans de Goede 		return 0xFF;
260554c0a3aSHans de Goede 
261554c0a3aSHans de Goede } /* EFUSE_Read1Byte */
262554c0a3aSHans de Goede 
263554c0a3aSHans de Goede /*  11/16/2008 MH Read one byte from real Efuse. */
264554c0a3aSHans de Goede u8
265554c0a3aSHans de Goede efuse_OneByteRead(
266554c0a3aSHans de Goede struct adapter *padapter,
267554c0a3aSHans de Goede u16 		addr,
268554c0a3aSHans de Goede u8 	*data,
269554c0a3aSHans de Goede bool		bPseudoTest)
270554c0a3aSHans de Goede {
271554c0a3aSHans de Goede 	u32 tmpidx = 0;
272554c0a3aSHans de Goede 	u8 bResult;
273554c0a3aSHans de Goede 	u8 readbyte;
274554c0a3aSHans de Goede 
275554c0a3aSHans de Goede 	/* DBG_871X("===> EFUSE_OneByteRead(), addr = %x\n", addr); */
276554c0a3aSHans de Goede 	/* DBG_871X("===> EFUSE_OneByteRead() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */
277554c0a3aSHans de Goede 
278554c0a3aSHans de Goede 	if (bPseudoTest) {
279554c0a3aSHans de Goede 		bResult = Efuse_Read1ByteFromFakeContent(padapter, addr, data);
280554c0a3aSHans de Goede 		return bResult;
281554c0a3aSHans de Goede 	}
282554c0a3aSHans de Goede 
283554c0a3aSHans de Goede 	/*  <20130121, Kordan> For SMIC EFUSE specificatoin. */
284554c0a3aSHans de Goede 	/* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
285554c0a3aSHans de Goede 	/* PHY_SetMacReg(padapter, 0x34, BIT11, 0); */
286554c0a3aSHans de Goede 	rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) & (~BIT11));
287554c0a3aSHans de Goede 
288554c0a3aSHans de Goede 	/*  -----------------e-fuse reg ctrl --------------------------------- */
289554c0a3aSHans de Goede 	/* address */
290554c0a3aSHans de Goede 	rtw_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xff));
291554c0a3aSHans de Goede 	rtw_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
292554c0a3aSHans de Goede 	(rtw_read8(padapter, EFUSE_CTRL+2)&0xFC));
293554c0a3aSHans de Goede 
294554c0a3aSHans de Goede 	/* rtw_write8(padapter, EFUSE_CTRL+3,  0x72); read cmd */
295554c0a3aSHans de Goede 	/* Write bit 32 0 */
296554c0a3aSHans de Goede 	readbyte = rtw_read8(padapter, EFUSE_CTRL+3);
297554c0a3aSHans de Goede 	rtw_write8(padapter, EFUSE_CTRL+3, (readbyte & 0x7f));
298554c0a3aSHans de Goede 
299554c0a3aSHans de Goede 	while (!(0x80 & rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 1000)) {
300554c0a3aSHans de Goede 		mdelay(1);
301554c0a3aSHans de Goede 		tmpidx++;
302554c0a3aSHans de Goede 	}
303554c0a3aSHans de Goede 	if (tmpidx < 100) {
304554c0a3aSHans de Goede 		*data = rtw_read8(padapter, EFUSE_CTRL);
305554c0a3aSHans de Goede 		bResult = true;
306554c0a3aSHans de Goede 	} else{
307554c0a3aSHans de Goede 		*data = 0xff;
308554c0a3aSHans de Goede 		bResult = false;
309554c0a3aSHans de Goede 		DBG_871X("%s: [ERROR] addr = 0x%x bResult =%d time out 1s !!!\n", __func__, addr, bResult);
310554c0a3aSHans de Goede 		DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL));
311554c0a3aSHans de Goede 	}
312554c0a3aSHans de Goede 
313554c0a3aSHans de Goede 	return bResult;
314554c0a3aSHans de Goede }
315554c0a3aSHans de Goede 
316554c0a3aSHans de Goede /*  11/16/2008 MH Write one byte to reald Efuse. */
317554c0a3aSHans de Goede u8
318554c0a3aSHans de Goede efuse_OneByteWrite(
319554c0a3aSHans de Goede struct adapter *padapter,
320554c0a3aSHans de Goede u16 		addr,
321554c0a3aSHans de Goede u8 	data,
322554c0a3aSHans de Goede bool		bPseudoTest)
323554c0a3aSHans de Goede {
324554c0a3aSHans de Goede 	u8 tmpidx = 0;
325554c0a3aSHans de Goede 	u8 bResult = false;
326554c0a3aSHans de Goede 	u32 efuseValue = 0;
327554c0a3aSHans de Goede 
328554c0a3aSHans de Goede 	/* DBG_871X("===> EFUSE_OneByteWrite(), addr = %x data =%x\n", addr, data); */
329554c0a3aSHans de Goede 	/* DBG_871X("===> EFUSE_OneByteWrite() start, 0x34 = 0x%X\n", rtw_read32(padapter, EFUSE_TEST)); */
330554c0a3aSHans de Goede 
331554c0a3aSHans de Goede 	if (bPseudoTest) {
332554c0a3aSHans de Goede 		bResult = Efuse_Write1ByteToFakeContent(padapter, addr, data);
333554c0a3aSHans de Goede 		return bResult;
334554c0a3aSHans de Goede 	}
335554c0a3aSHans de Goede 
336554c0a3aSHans de Goede 
337554c0a3aSHans de Goede 	/*  -----------------e-fuse reg ctrl --------------------------------- */
338554c0a3aSHans de Goede 	/* address */
339554c0a3aSHans de Goede 
340554c0a3aSHans de Goede 
341554c0a3aSHans de Goede 	efuseValue = rtw_read32(padapter, EFUSE_CTRL);
342554c0a3aSHans de Goede 	efuseValue |= (BIT21|BIT31);
343554c0a3aSHans de Goede 	efuseValue &= ~(0x3FFFF);
344554c0a3aSHans de Goede 	efuseValue |= ((addr<<8 | data) & 0x3FFFF);
345554c0a3aSHans de Goede 
346554c0a3aSHans de Goede 
347554c0a3aSHans de Goede 	/*  <20130227, Kordan> 8192E MP chip A-cut had better not set 0x34[11] until B-Cut. */
348554c0a3aSHans de Goede 
349554c0a3aSHans de Goede 	/*  <20130121, Kordan> For SMIC EFUSE specificatoin. */
350554c0a3aSHans de Goede 	/* 0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) */
351554c0a3aSHans de Goede 	/* PHY_SetMacReg(padapter, 0x34, BIT11, 1); */
352554c0a3aSHans de Goede 	rtw_write16(padapter, 0x34, rtw_read16(padapter, 0x34) | (BIT11));
353554c0a3aSHans de Goede 	rtw_write32(padapter, EFUSE_CTRL, 0x90600000|((addr<<8 | data)));
354554c0a3aSHans de Goede 
355554c0a3aSHans de Goede 	while ((0x80 &  rtw_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100)) {
356554c0a3aSHans de Goede 		mdelay(1);
357554c0a3aSHans de Goede 		tmpidx++;
358554c0a3aSHans de Goede 	}
359554c0a3aSHans de Goede 
360554c0a3aSHans de Goede 	if (tmpidx < 100) {
361554c0a3aSHans de Goede 		bResult = true;
362554c0a3aSHans de Goede 	} else{
363554c0a3aSHans de Goede 		bResult = false;
364554c0a3aSHans de Goede 		DBG_871X("%s: [ERROR] addr = 0x%x , efuseValue = 0x%x , bResult =%d time out 1s !!!\n",
365554c0a3aSHans de Goede 					__func__, addr, efuseValue, bResult);
366554c0a3aSHans de Goede 		DBG_871X("%s: [ERROR] EFUSE_CTRL = 0x%08x !!!\n", __func__, rtw_read32(padapter, EFUSE_CTRL));
367554c0a3aSHans de Goede 	}
368554c0a3aSHans de Goede 
369554c0a3aSHans de Goede 	/*  disable Efuse program enable */
370554c0a3aSHans de Goede 	PHY_SetMacReg(padapter, EFUSE_TEST, BIT(11), 0);
371554c0a3aSHans de Goede 
372554c0a3aSHans de Goede 	return bResult;
373554c0a3aSHans de Goede }
374554c0a3aSHans de Goede 
375554c0a3aSHans de Goede int
376554c0a3aSHans de Goede Efuse_PgPacketRead(struct adapter *padapter,
377554c0a3aSHans de Goede 				u8 	offset,
378554c0a3aSHans de Goede 				u8 	*data,
379554c0a3aSHans de Goede 				bool		bPseudoTest)
380554c0a3aSHans de Goede {
381554c0a3aSHans de Goede 	int	ret = 0;
382554c0a3aSHans de Goede 
383554c0a3aSHans de Goede 	ret =  padapter->HalFunc.Efuse_PgPacketRead(padapter, offset, data, bPseudoTest);
384554c0a3aSHans de Goede 
385554c0a3aSHans de Goede 	return ret;
386554c0a3aSHans de Goede }
387554c0a3aSHans de Goede 
388554c0a3aSHans de Goede int
389554c0a3aSHans de Goede Efuse_PgPacketWrite(struct adapter *padapter,
390554c0a3aSHans de Goede 				u8 	offset,
391554c0a3aSHans de Goede 				u8 	word_en,
392554c0a3aSHans de Goede 				u8 	*data,
393554c0a3aSHans de Goede 				bool		bPseudoTest)
394554c0a3aSHans de Goede {
395554c0a3aSHans de Goede 	int ret;
396554c0a3aSHans de Goede 
397554c0a3aSHans de Goede 	ret =  padapter->HalFunc.Efuse_PgPacketWrite(padapter, offset, word_en, data, bPseudoTest);
398554c0a3aSHans de Goede 
399554c0a3aSHans de Goede 	return ret;
400554c0a3aSHans de Goede }
401554c0a3aSHans de Goede 
402554c0a3aSHans de Goede /*-----------------------------------------------------------------------------
403554c0a3aSHans de Goede  * Function:	efuse_WordEnableDataRead
404554c0a3aSHans de Goede  *
405554c0a3aSHans de Goede  * Overview:	Read allowed word in current efuse section data.
406554c0a3aSHans de Goede  *
407554c0a3aSHans de Goede  * Input:       NONE
408554c0a3aSHans de Goede  *
409554c0a3aSHans de Goede  * Output:      NONE
410554c0a3aSHans de Goede  *
411554c0a3aSHans de Goede  * Return:      NONE
412554c0a3aSHans de Goede  *
413554c0a3aSHans de Goede  * Revised History:
414554c0a3aSHans de Goede  * When			Who		Remark
415554c0a3aSHans de Goede  * 11/16/2008	MHC		Create Version 0.
416554c0a3aSHans de Goede  * 11/21/2008	MHC		Fix Write bug when we only enable late word.
417554c0a3aSHans de Goede  *
418554c0a3aSHans de Goede  *---------------------------------------------------------------------------*/
419554c0a3aSHans de Goede void
420554c0a3aSHans de Goede efuse_WordEnableDataRead(u8 word_en,
421554c0a3aSHans de Goede 						u8 *sourdata,
422554c0a3aSHans de Goede 						u8 *targetdata)
423554c0a3aSHans de Goede {
424554c0a3aSHans de Goede 	if (!(word_en&BIT(0))) {
425554c0a3aSHans de Goede 		targetdata[0] = sourdata[0];
426554c0a3aSHans de Goede 		targetdata[1] = sourdata[1];
427554c0a3aSHans de Goede 	}
428554c0a3aSHans de Goede 	if (!(word_en&BIT(1))) {
429554c0a3aSHans de Goede 		targetdata[2] = sourdata[2];
430554c0a3aSHans de Goede 		targetdata[3] = sourdata[3];
431554c0a3aSHans de Goede 	}
432554c0a3aSHans de Goede 	if (!(word_en&BIT(2))) {
433554c0a3aSHans de Goede 		targetdata[4] = sourdata[4];
434554c0a3aSHans de Goede 		targetdata[5] = sourdata[5];
435554c0a3aSHans de Goede 	}
436554c0a3aSHans de Goede 	if (!(word_en&BIT(3))) {
437554c0a3aSHans de Goede 		targetdata[6] = sourdata[6];
438554c0a3aSHans de Goede 		targetdata[7] = sourdata[7];
439554c0a3aSHans de Goede 	}
440554c0a3aSHans de Goede }
441554c0a3aSHans de Goede 
442554c0a3aSHans de Goede 
443554c0a3aSHans de Goede u8
444554c0a3aSHans de Goede Efuse_WordEnableDataWrite(struct adapter *padapter,
445554c0a3aSHans de Goede 						u16 	efuse_addr,
446554c0a3aSHans de Goede 						u8 word_en,
447554c0a3aSHans de Goede 						u8 *data,
448554c0a3aSHans de Goede 						bool		bPseudoTest)
449554c0a3aSHans de Goede {
450554c0a3aSHans de Goede 	u8 ret = 0;
451554c0a3aSHans de Goede 
452554c0a3aSHans de Goede 	ret =  padapter->HalFunc.Efuse_WordEnableDataWrite(padapter, efuse_addr, word_en, data, bPseudoTest);
453554c0a3aSHans de Goede 
454554c0a3aSHans de Goede 	return ret;
455554c0a3aSHans de Goede }
456554c0a3aSHans de Goede 
457554c0a3aSHans de Goede /*-----------------------------------------------------------------------------
458554c0a3aSHans de Goede  * Function:	Efuse_ReadAllMap
459554c0a3aSHans de Goede  *
460554c0a3aSHans de Goede  * Overview:	Read All Efuse content
461554c0a3aSHans de Goede  *
462554c0a3aSHans de Goede  * Input:       NONE
463554c0a3aSHans de Goede  *
464554c0a3aSHans de Goede  * Output:      NONE
465554c0a3aSHans de Goede  *
466554c0a3aSHans de Goede  * Return:      NONE
467554c0a3aSHans de Goede  *
468554c0a3aSHans de Goede  * Revised History:
469554c0a3aSHans de Goede  * When			Who		Remark
470554c0a3aSHans de Goede  * 11/11/2008	MHC		Create Version 0.
471554c0a3aSHans de Goede  *
472554c0a3aSHans de Goede  *---------------------------------------------------------------------------*/
473554c0a3aSHans de Goede void
474554c0a3aSHans de Goede Efuse_ReadAllMap(
475554c0a3aSHans de Goede 	struct adapter *padapter,
476554c0a3aSHans de Goede 	u8 efuseType,
477554c0a3aSHans de Goede 	u8 *Efuse,
478554c0a3aSHans de Goede 	bool		bPseudoTest);
479554c0a3aSHans de Goede void
480554c0a3aSHans de Goede Efuse_ReadAllMap(
481554c0a3aSHans de Goede 	struct adapter *padapter,
482554c0a3aSHans de Goede 	u8 efuseType,
483554c0a3aSHans de Goede 	u8 *Efuse,
484554c0a3aSHans de Goede 	bool		bPseudoTest)
485554c0a3aSHans de Goede {
486554c0a3aSHans de Goede 	u16 mapLen = 0;
487554c0a3aSHans de Goede 
488554c0a3aSHans de Goede 	Efuse_PowerSwitch(padapter, false, true);
489554c0a3aSHans de Goede 
490554c0a3aSHans de Goede 	EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
491554c0a3aSHans de Goede 
492554c0a3aSHans de Goede 	efuse_ReadEFuse(padapter, efuseType, 0, mapLen, Efuse, bPseudoTest);
493554c0a3aSHans de Goede 
494554c0a3aSHans de Goede 	Efuse_PowerSwitch(padapter, false, false);
495554c0a3aSHans de Goede }
496554c0a3aSHans de Goede 
497554c0a3aSHans de Goede /*-----------------------------------------------------------------------------
498554c0a3aSHans de Goede  * Function:	efuse_ShadowRead1Byte
499554c0a3aSHans de Goede  *		efuse_ShadowRead2Byte
500554c0a3aSHans de Goede  *		efuse_ShadowRead4Byte
501554c0a3aSHans de Goede  *
502554c0a3aSHans de Goede  * Overview:	Read from efuse init map by one/two/four bytes !!!!!
503554c0a3aSHans de Goede  *
504554c0a3aSHans de Goede  * Input:       NONE
505554c0a3aSHans de Goede  *
506554c0a3aSHans de Goede  * Output:      NONE
507554c0a3aSHans de Goede  *
508554c0a3aSHans de Goede  * Return:      NONE
509554c0a3aSHans de Goede  *
510554c0a3aSHans de Goede  * Revised History:
511554c0a3aSHans de Goede  * When			Who		Remark
512554c0a3aSHans de Goede  * 11/12/2008	MHC		Create Version 0.
513554c0a3aSHans de Goede  *
514554c0a3aSHans de Goede  *---------------------------------------------------------------------------*/
515554c0a3aSHans de Goede static void
516554c0a3aSHans de Goede efuse_ShadowRead1Byte(
517554c0a3aSHans de Goede struct adapter *padapter,
518554c0a3aSHans de Goede u16 	Offset,
519554c0a3aSHans de Goede 	u8 *Value)
520554c0a3aSHans de Goede {
521554c0a3aSHans de Goede 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
522554c0a3aSHans de Goede 
523554c0a3aSHans de Goede 	*Value = pEEPROM->efuse_eeprom_data[Offset];
524554c0a3aSHans de Goede 
525554c0a3aSHans de Goede }	/*  EFUSE_ShadowRead1Byte */
526554c0a3aSHans de Goede 
527554c0a3aSHans de Goede /* Read Two Bytes */
528554c0a3aSHans de Goede static void
529554c0a3aSHans de Goede efuse_ShadowRead2Byte(
530554c0a3aSHans de Goede struct adapter *padapter,
531554c0a3aSHans de Goede u16 	Offset,
532554c0a3aSHans de Goede 	u16 	*Value)
533554c0a3aSHans de Goede {
534554c0a3aSHans de Goede 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
535554c0a3aSHans de Goede 
536554c0a3aSHans de Goede 	*Value = pEEPROM->efuse_eeprom_data[Offset];
537554c0a3aSHans de Goede 	*Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
538554c0a3aSHans de Goede 
539554c0a3aSHans de Goede }	/*  EFUSE_ShadowRead2Byte */
540554c0a3aSHans de Goede 
541554c0a3aSHans de Goede /* Read Four Bytes */
542554c0a3aSHans de Goede static void
543554c0a3aSHans de Goede efuse_ShadowRead4Byte(
544554c0a3aSHans de Goede struct adapter *padapter,
545554c0a3aSHans de Goede u16 	Offset,
546554c0a3aSHans de Goede 	u32 	*Value)
547554c0a3aSHans de Goede {
548554c0a3aSHans de Goede 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
549554c0a3aSHans de Goede 
550554c0a3aSHans de Goede 	*Value = pEEPROM->efuse_eeprom_data[Offset];
551554c0a3aSHans de Goede 	*Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
552554c0a3aSHans de Goede 	*Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
553554c0a3aSHans de Goede 	*Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
554554c0a3aSHans de Goede 
555554c0a3aSHans de Goede }	/*  efuse_ShadowRead4Byte */
556554c0a3aSHans de Goede 
557554c0a3aSHans de Goede /*-----------------------------------------------------------------------------
558554c0a3aSHans de Goede  * Function:	EFUSE_ShadowMapUpdate
559554c0a3aSHans de Goede  *
560554c0a3aSHans de Goede  * Overview:	Transfer current EFUSE content to shadow init and modify map.
561554c0a3aSHans de Goede  *
562554c0a3aSHans de Goede  * Input:       NONE
563554c0a3aSHans de Goede  *
564554c0a3aSHans de Goede  * Output:      NONE
565554c0a3aSHans de Goede  *
566554c0a3aSHans de Goede  * Return:      NONE
567554c0a3aSHans de Goede  *
568554c0a3aSHans de Goede  * Revised History:
569554c0a3aSHans de Goede  * When			Who		Remark
570554c0a3aSHans de Goede  * 11/13/2008	MHC		Create Version 0.
571554c0a3aSHans de Goede  *
572554c0a3aSHans de Goede  *---------------------------------------------------------------------------*/
573554c0a3aSHans de Goede void EFUSE_ShadowMapUpdate(
574554c0a3aSHans de Goede 	struct adapter *padapter,
575554c0a3aSHans de Goede 	u8 efuseType,
576554c0a3aSHans de Goede 	bool	bPseudoTest)
577554c0a3aSHans de Goede {
578554c0a3aSHans de Goede 	struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
579554c0a3aSHans de Goede 	u16 mapLen = 0;
580554c0a3aSHans de Goede 
581554c0a3aSHans de Goede 	EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, bPseudoTest);
582554c0a3aSHans de Goede 
583554c0a3aSHans de Goede 	if (pEEPROM->bautoload_fail_flag == true) {
584554c0a3aSHans de Goede 		memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
585554c0a3aSHans de Goede 	} else{
586554c0a3aSHans de Goede 		Efuse_ReadAllMap(padapter, efuseType, pEEPROM->efuse_eeprom_data, bPseudoTest);
587554c0a3aSHans de Goede 	}
588554c0a3aSHans de Goede 
589554c0a3aSHans de Goede 	/* PlatformMoveMemory((void *)&pHalData->EfuseMap[EFUSE_MODIFY_MAP][0], */
590554c0a3aSHans de Goede 	/* void *)&pHalData->EfuseMap[EFUSE_INIT_MAP][0], mapLen); */
591554c0a3aSHans de Goede } /*  EFUSE_ShadowMapUpdate */
592554c0a3aSHans de Goede 
593554c0a3aSHans de Goede 
594554c0a3aSHans de Goede /*-----------------------------------------------------------------------------
595554c0a3aSHans de Goede  * Function:	EFUSE_ShadowRead
596554c0a3aSHans de Goede  *
597554c0a3aSHans de Goede  * Overview:	Read from efuse init map !!!!!
598554c0a3aSHans de Goede  *
599554c0a3aSHans de Goede  * Input:       NONE
600554c0a3aSHans de Goede  *
601554c0a3aSHans de Goede  * Output:      NONE
602554c0a3aSHans de Goede  *
603554c0a3aSHans de Goede  * Return:      NONE
604554c0a3aSHans de Goede  *
605554c0a3aSHans de Goede  * Revised History:
606554c0a3aSHans de Goede  * When			Who		Remark
607554c0a3aSHans de Goede  * 11/12/2008	MHC		Create Version 0.
608554c0a3aSHans de Goede  *
609554c0a3aSHans de Goede  *---------------------------------------------------------------------------*/
610554c0a3aSHans de Goede void
611554c0a3aSHans de Goede EFUSE_ShadowRead(
612554c0a3aSHans de Goede 	struct adapter *padapter,
613554c0a3aSHans de Goede 	u8 Type,
614554c0a3aSHans de Goede 	u16 	Offset,
615554c0a3aSHans de Goede 	u32 	*Value)
616554c0a3aSHans de Goede {
617554c0a3aSHans de Goede 	if (Type == 1)
618554c0a3aSHans de Goede 		efuse_ShadowRead1Byte(padapter, Offset, (u8 *)Value);
619554c0a3aSHans de Goede 	else if (Type == 2)
620554c0a3aSHans de Goede 		efuse_ShadowRead2Byte(padapter, Offset, (u16 *)Value);
621554c0a3aSHans de Goede 	else if (Type == 4)
622554c0a3aSHans de Goede 		efuse_ShadowRead4Byte(padapter, Offset, (u32 *)Value);
623554c0a3aSHans de Goede 
624554c0a3aSHans de Goede }	/* EFUSE_ShadowRead*/
625