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