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