1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
3
4 #define _RTW_EFUSE_C_
5
6 #include "../include/osdep_service.h"
7 #include "../include/drv_types.h"
8 #include "../include/rtw_efuse.h"
9
10 /*------------------------Define local variable------------------------------*/
11 u8 fakeEfuseBank;
12 u32 fakeEfuseUsedBytes;
13 u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
14 u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
15 u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
16
17 u32 BTEfuseUsedBytes;
18 u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
19 u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
20 u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
21
22 u32 fakeBTEfuseUsedBytes;
23 u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
24 u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
25 u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
26 /*------------------------Define local variable------------------------------*/
27
28 #define REG_EFUSE_CTRL 0x0030
29 #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
30
Efuse_Read1ByteFromFakeContent(u16 Offset,u8 * Value)31 static bool Efuse_Read1ByteFromFakeContent(u16 Offset, u8 *Value)
32 {
33 if (Offset >= EFUSE_MAX_HW_SIZE)
34 return false;
35 if (fakeEfuseBank == 0)
36 *Value = fakeEfuseContent[Offset];
37 else
38 *Value = fakeBTEfuseContent[fakeEfuseBank - 1][Offset];
39 return true;
40 }
41
42 static bool
Efuse_Write1ByteToFakeContent(struct adapter * pAdapter,u16 Offset,u8 Value)43 Efuse_Write1ByteToFakeContent(
44 struct adapter *pAdapter,
45 u16 Offset,
46 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 }
55 return true;
56 }
57
58 /* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
59 u8
Efuse_CalculateWordCnts(u8 word_en)60 Efuse_CalculateWordCnts(u8 word_en)
61 {
62 u8 word_cnts = 0;
63 if (!(word_en & BIT(0)))
64 word_cnts++; /* 0 : write enable */
65 if (!(word_en & BIT(1)))
66 word_cnts++;
67 if (!(word_en & BIT(2)))
68 word_cnts++;
69 if (!(word_en & BIT(3)))
70 word_cnts++;
71 return word_cnts;
72 }
73
74 /* */
75 /* Description: */
76 /* Execute E-Fuse read byte operation. */
77 /* Referred from SD1 Richard. */
78 /* */
79 /* Assumption: */
80 /* 1. Boot from E-Fuse and successfully auto-load. */
81 /* 2. PASSIVE_LEVEL (USB interface) */
82 /* */
83 /* Created by Roger, 2008.10.21. */
84 /* */
85 void
ReadEFuseByte(struct adapter * Adapter,u16 _offset,u8 * pbuf,bool pseudo)86 ReadEFuseByte(
87 struct adapter *Adapter,
88 u16 _offset,
89 u8 *pbuf,
90 bool pseudo)
91 {
92 u32 value32;
93 u8 readbyte;
94 u16 retry;
95
96 if (pseudo) {
97 Efuse_Read1ByteFromFakeContent(_offset, pbuf);
98 return;
99 }
100
101 /* Write Address */
102 rtw_write8(Adapter, EFUSE_CTRL + 1, (_offset & 0xff));
103 readbyte = rtw_read8(Adapter, EFUSE_CTRL + 2);
104 rtw_write8(Adapter, EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
105
106 /* Write bit 32 0 */
107 readbyte = rtw_read8(Adapter, EFUSE_CTRL + 3);
108 rtw_write8(Adapter, EFUSE_CTRL + 3, (readbyte & 0x7f));
109
110 /* Check bit 32 read-ready */
111 retry = 0;
112 value32 = rtw_read32(Adapter, EFUSE_CTRL);
113 while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) {
114 value32 = rtw_read32(Adapter, EFUSE_CTRL);
115 retry++;
116 }
117
118 /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
119 /* This fix the problem that Efuse read error in high temperature condition. */
120 /* Designer says that there shall be some delay after ready bit is set, or the */
121 /* result will always stay on last data we read. */
122 udelay(50);
123 value32 = rtw_read32(Adapter, EFUSE_CTRL);
124
125 *pbuf = (u8)(value32 & 0xff);
126 }
127
128 /* 11/16/2008 MH Read one byte from real Efuse. */
efuse_OneByteRead(struct adapter * pAdapter,u16 addr,u8 * data,bool pseudo)129 u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
130 {
131 u8 tmpidx = 0;
132 u8 result;
133
134 if (pseudo) {
135 result = Efuse_Read1ByteFromFakeContent(addr, data);
136 return result;
137 }
138 /* -----------------e-fuse reg ctrl --------------------------------- */
139 /* address */
140 rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
141 rtw_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
142 (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
143
144 rtw_write8(pAdapter, EFUSE_CTRL + 3, 0x72);/* read cmd */
145
146 while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
147 tmpidx++;
148 if (tmpidx < 100) {
149 *data = rtw_read8(pAdapter, EFUSE_CTRL);
150 result = true;
151 } else {
152 *data = 0xff;
153 result = false;
154 }
155 return result;
156 }
157
158 /* 11/16/2008 MH Write one byte to reald Efuse. */
efuse_OneByteWrite(struct adapter * pAdapter,u16 addr,u8 data,bool pseudo)159 u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
160 {
161 u8 tmpidx = 0;
162 u8 result;
163
164 if (pseudo) {
165 result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
166 return result;
167 }
168
169 /* -----------------e-fuse reg ctrl --------------------------------- */
170 /* address */
171 rtw_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
172 rtw_write8(pAdapter, EFUSE_CTRL + 2,
173 (rtw_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
174 (u8)((addr >> 8) & 0x03));
175 rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
176
177 rtw_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */
178
179 while ((0x80 & rtw_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
180 tmpidx++;
181
182 if (tmpidx < 100)
183 result = true;
184 else
185 result = false;
186
187 return result;
188 }
189
190 /*-----------------------------------------------------------------------------
191 * Function: efuse_WordEnableDataRead
192 *
193 * Overview: Read allowed word in current efuse section data.
194 *
195 * Input: NONE
196 *
197 * Output: NONE
198 *
199 * Return: NONE
200 *
201 * Revised History:
202 * When Who Remark
203 * 11/16/2008 MHC Create Version 0.
204 * 11/21/2008 MHC Fix Write bug when we only enable late word.
205 *
206 *---------------------------------------------------------------------------*/
efuse_WordEnableDataRead(u8 word_en,u8 * sourdata,u8 * targetdata)207 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
208 {
209 if (!(word_en & BIT(0))) {
210 targetdata[0] = sourdata[0];
211 targetdata[1] = sourdata[1];
212 }
213 if (!(word_en & BIT(1))) {
214 targetdata[2] = sourdata[2];
215 targetdata[3] = sourdata[3];
216 }
217 if (!(word_en & BIT(2))) {
218 targetdata[4] = sourdata[4];
219 targetdata[5] = sourdata[5];
220 }
221 if (!(word_en & BIT(3))) {
222 targetdata[6] = sourdata[6];
223 targetdata[7] = sourdata[7];
224 }
225 }
226
227 /*-----------------------------------------------------------------------------
228 * Function: Efuse_ReadAllMap
229 *
230 * Overview: Read All Efuse content
231 *
232 * Input: NONE
233 *
234 * Output: NONE
235 *
236 * Return: NONE
237 *
238 * Revised History:
239 * When Who Remark
240 * 11/11/2008 MHC Create Version 0.
241 *
242 *---------------------------------------------------------------------------*/
Efuse_ReadAllMap(struct adapter * pAdapter,u8 efuseType,u8 * Efuse,bool pseudo)243 static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
244 {
245 u16 mapLen = 0;
246
247 rtl8188e_EfusePowerSwitch(pAdapter, false, true);
248
249 rtl8188e_EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
250
251 rtl8188e_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
252
253 rtl8188e_EfusePowerSwitch(pAdapter, false, false);
254 }
255
256 /*-----------------------------------------------------------------------------
257 * Function: EFUSE_ShadowMapUpdate
258 *
259 * Overview: Transfer current EFUSE content to shadow init and modify map.
260 *
261 * Input: NONE
262 *
263 * Output: NONE
264 *
265 * Return: NONE
266 *
267 * Revised History:
268 * When Who Remark
269 * 11/13/2008 MHC Create Version 0.
270 *
271 *---------------------------------------------------------------------------*/
EFUSE_ShadowMapUpdate(struct adapter * pAdapter,u8 efuseType,bool pseudo)272 void EFUSE_ShadowMapUpdate(
273 struct adapter *pAdapter,
274 u8 efuseType,
275 bool pseudo)
276 {
277 struct eeprom_priv *pEEPROM = &pAdapter->eeprompriv;
278 u16 mapLen = 0;
279
280 rtl8188e_EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
281
282 if (pEEPROM->bautoload_fail_flag)
283 memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
284 else
285 Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
286 } /* EFUSE_ShadowMapUpdate */
287