Commit | Line | Data |
---|---|---|
06a05884 LF |
1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
06a05884 LF |
14 | ******************************************************************************/ |
15 | #define _RTW_EFUSE_C_ | |
16 | ||
17 | #include <osdep_service.h> | |
18 | #include <drv_types.h> | |
19 | #include <rtw_efuse.h> | |
e73fd15e | 20 | #include <usb_ops_linux.h> |
ee5f8a43 | 21 | #include <rtl8188e_hal.h> |
22 | #include <rtw_iol.h> | |
06a05884 | 23 | |
06a05884 LF |
24 | #define REG_EFUSE_CTRL 0x0030 |
25 | #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */ | |
06a05884 | 26 | |
ee5f8a43 | 27 | enum{ |
28 | VOLTAGE_V25 = 0x03, | |
e703f237 | 29 | LDOE25_SHIFT = 28, |
ee5f8a43 | 30 | }; |
31 | ||
32 | /* | |
33 | * Function: Efuse_PowerSwitch | |
34 | * | |
35 | * Overview: When we want to enable write operation, we should change to | |
36 | * pwr on state. When we stop write, we should switch to 500k mode | |
37 | * and disable LDO 2.5V. | |
38 | */ | |
39 | ||
40 | void Efuse_PowerSwitch( | |
41 | struct adapter *pAdapter, | |
42 | u8 bWrite, | |
43 | u8 PwrState) | |
44 | { | |
45 | u8 tempval; | |
46 | u16 tmpV16; | |
47 | ||
48 | if (PwrState) { | |
49 | usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); | |
50 | ||
51 | /* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */ | |
52 | tmpV16 = usb_read16(pAdapter, REG_SYS_ISO_CTRL); | |
53 | if (!(tmpV16 & PWC_EV12V)) { | |
54 | tmpV16 |= PWC_EV12V; | |
55 | usb_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16); | |
56 | } | |
57 | /* Reset: 0x0000h[28], default valid */ | |
58 | tmpV16 = usb_read16(pAdapter, REG_SYS_FUNC_EN); | |
59 | if (!(tmpV16 & FEN_ELDR)) { | |
60 | tmpV16 |= FEN_ELDR; | |
61 | usb_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16); | |
62 | } | |
63 | ||
64 | /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */ | |
65 | tmpV16 = usb_read16(pAdapter, REG_SYS_CLKR); | |
66 | if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) { | |
67 | tmpV16 |= (LOADER_CLK_EN | ANA8M); | |
68 | usb_write16(pAdapter, REG_SYS_CLKR, tmpV16); | |
69 | } | |
70 | ||
71 | if (bWrite) { | |
72 | /* Enable LDO 2.5V before read/write action */ | |
73 | tempval = usb_read8(pAdapter, EFUSE_TEST+3); | |
74 | tempval &= 0x0F; | |
75 | tempval |= (VOLTAGE_V25 << 4); | |
76 | usb_write8(pAdapter, EFUSE_TEST+3, (tempval | 0x80)); | |
77 | } | |
78 | } else { | |
79 | usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); | |
80 | ||
81 | if (bWrite) { | |
82 | /* Disable LDO 2.5V after read/write action */ | |
83 | tempval = usb_read8(pAdapter, EFUSE_TEST+3); | |
84 | usb_write8(pAdapter, EFUSE_TEST+3, (tempval & 0x7F)); | |
85 | } | |
86 | } | |
87 | } | |
88 | ||
89 | static void | |
90 | efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) | |
91 | { | |
92 | u8 *efuseTbl = NULL; | |
93 | u8 rtemp8; | |
94 | u16 eFuse_Addr = 0; | |
95 | u8 offset, wren; | |
96 | u16 i, j; | |
97 | u16 **eFuseWord = NULL; | |
98 | u16 efuse_utilized = 0; | |
99 | u8 u1temp = 0; | |
100 | ||
fadbe0cd | 101 | efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL); |
b08e0fc0 | 102 | if (!efuseTbl) |
3cfab18c | 103 | return; |
ee5f8a43 | 104 | |
bc8201e3 | 105 | eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); |
e59b76cf | 106 | if (!eFuseWord) { |
ee5f8a43 | 107 | DBG_88E("%s: alloc eFuseWord fail!\n", __func__); |
3cfab18c | 108 | goto eFuseWord_failed; |
ee5f8a43 | 109 | } |
110 | ||
111 | /* 0. Refresh efuse init map as all oxFF. */ | |
112 | for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) | |
113 | for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) | |
114 | eFuseWord[i][j] = 0xFFFF; | |
115 | ||
116 | /* */ | |
117 | /* 1. Read the first byte to check if efuse is empty!!! */ | |
118 | /* */ | |
119 | /* */ | |
120 | rtemp8 = *(phymap+eFuse_Addr); | |
121 | if (rtemp8 != 0xFF) { | |
122 | efuse_utilized++; | |
123 | eFuse_Addr++; | |
124 | } else { | |
125 | DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8); | |
126 | goto exit; | |
127 | } | |
128 | ||
129 | /* */ | |
130 | /* 2. Read real efuse content. Filter PG header and every section data. */ | |
131 | /* */ | |
132 | while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { | |
133 | /* Check PG header for section num. */ | |
134 | if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */ | |
07add2d3 | 135 | u1temp = (rtemp8 & 0xE0) >> 5; |
ee5f8a43 | 136 | rtemp8 = *(phymap+eFuse_Addr); |
137 | if ((rtemp8 & 0x0F) == 0x0F) { | |
138 | eFuse_Addr++; | |
139 | rtemp8 = *(phymap+eFuse_Addr); | |
140 | ||
141 | if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) | |
142 | eFuse_Addr++; | |
143 | continue; | |
144 | } else { | |
145 | offset = ((rtemp8 & 0xF0) >> 1) | u1temp; | |
adb3d770 | 146 | wren = rtemp8 & 0x0F; |
ee5f8a43 | 147 | eFuse_Addr++; |
148 | } | |
149 | } else { | |
adb3d770 HM |
150 | offset = (rtemp8 >> 4) & 0x0f; |
151 | wren = rtemp8 & 0x0f; | |
ee5f8a43 | 152 | } |
153 | ||
154 | if (offset < EFUSE_MAX_SECTION_88E) { | |
155 | /* Get word enable value from PG header */ | |
156 | for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { | |
157 | /* Check word enable condition in the section */ | |
158 | if (!(wren & 0x01)) { | |
159 | rtemp8 = *(phymap+eFuse_Addr); | |
160 | eFuse_Addr++; | |
161 | efuse_utilized++; | |
162 | eFuseWord[offset][i] = (rtemp8 & 0xff); | |
163 | if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) | |
164 | break; | |
165 | rtemp8 = *(phymap+eFuse_Addr); | |
166 | eFuse_Addr++; | |
167 | efuse_utilized++; | |
168 | eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00); | |
169 | ||
170 | if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) | |
171 | break; | |
172 | } | |
173 | wren >>= 1; | |
174 | } | |
175 | } | |
176 | /* Read next PG header */ | |
177 | rtemp8 = *(phymap+eFuse_Addr); | |
178 | ||
179 | if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { | |
180 | efuse_utilized++; | |
181 | eFuse_Addr++; | |
182 | } | |
183 | } | |
184 | ||
185 | /* */ | |
186 | /* 3. Collect 16 sections and 4 word unit into Efuse map. */ | |
187 | /* */ | |
188 | for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { | |
189 | for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { | |
190 | efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff); | |
191 | efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff); | |
192 | } | |
193 | } | |
194 | ||
195 | /* */ | |
196 | /* 4. Copy from Efuse map to output pointer memory!!! */ | |
197 | /* */ | |
198 | for (i = 0; i < _size_byte; i++) | |
199 | pbuf[i] = efuseTbl[_offset+i]; | |
200 | ||
201 | /* */ | |
202 | /* 5. Calculate Efuse utilization. */ | |
203 | /* */ | |
204 | ||
205 | exit: | |
3cfab18c | 206 | kfree(eFuseWord); |
ee5f8a43 | 207 | |
3cfab18c TP |
208 | eFuseWord_failed: |
209 | kfree(efuseTbl); | |
ee5f8a43 | 210 | } |
211 | ||
212 | static void efuse_read_phymap_from_txpktbuf( | |
213 | struct adapter *adapter, | |
214 | int bcnhead, /* beacon head, where FW store len(2-byte) and efuse physical map. */ | |
215 | u8 *content, /* buffer to store efuse physical map */ | |
216 | u16 *size /* for efuse content: the max byte to read. will update to byte read */ | |
217 | ) | |
218 | { | |
219 | u16 dbg_addr = 0; | |
ed737494 | 220 | unsigned long start = 0; |
ee5f8a43 | 221 | u8 reg_0x143 = 0; |
222 | u32 lo32 = 0, hi32 = 0; | |
223 | u16 len = 0, count = 0; | |
224 | int i = 0; | |
225 | u16 limit = *size; | |
226 | ||
227 | u8 *pos = content; | |
228 | ||
229 | if (bcnhead < 0) /* if not valid */ | |
230 | bcnhead = usb_read8(adapter, REG_TDECTRL+1); | |
231 | ||
232 | DBG_88E("%s bcnhead:%d\n", __func__, bcnhead); | |
233 | ||
234 | usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); | |
235 | ||
236 | dbg_addr = bcnhead*128/8; /* 8-bytes addressing */ | |
237 | ||
238 | while (1) { | |
239 | usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i); | |
240 | ||
241 | usb_write8(adapter, REG_TXPKTBUF_DBG, 0); | |
242 | start = jiffies; | |
243 | while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) && | |
ed737494 | 244 | jiffies_to_msecs(jiffies - start) < 1000) { |
ee5f8a43 | 245 | DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106)); |
c8cb5f2c | 246 | usleep_range(1000, 2000); |
ee5f8a43 | 247 | } |
248 | ||
249 | lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L); | |
250 | hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H); | |
251 | ||
252 | if (i == 0) { | |
253 | u8 lenc[2]; | |
254 | u16 lenbak, aaabak; | |
255 | u16 aaa; | |
256 | lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L); | |
257 | lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1); | |
258 | ||
259 | aaabak = le16_to_cpup((__le16 *)lenc); | |
260 | lenbak = le16_to_cpu(*((__le16 *)lenc)); | |
261 | aaa = le16_to_cpup((__le16 *)&lo32); | |
262 | len = le16_to_cpu(*((__le16 *)&lo32)); | |
263 | ||
530c9b1b | 264 | limit = min_t(u16, len-2, limit); |
ee5f8a43 | 265 | |
266 | DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak); | |
267 | ||
268 | memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count); | |
269 | count += (limit >= count+2) ? 2 : limit-count; | |
270 | pos = content+count; | |
271 | ||
272 | } else { | |
273 | memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count); | |
274 | count += (limit >= count+4) ? 4 : limit-count; | |
275 | pos = content+count; | |
276 | } | |
277 | ||
278 | if (limit > count && len-2 > count) { | |
279 | memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count); | |
280 | count += (limit >= count+4) ? 4 : limit-count; | |
281 | pos = content+count; | |
282 | } | |
283 | ||
284 | if (limit <= count || len-2 <= count) | |
285 | break; | |
286 | i++; | |
287 | } | |
288 | usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS); | |
289 | DBG_88E("%s read count:%u\n", __func__, count); | |
290 | *size = count; | |
291 | } | |
292 | ||
293 | static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map) | |
294 | { | |
295 | s32 status = _FAIL; | |
296 | u8 physical_map[512]; | |
297 | u16 size = 512; | |
298 | ||
299 | usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy); | |
1ce39848 | 300 | memset(physical_map, 0xFF, 512); |
ee5f8a43 | 301 | usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); |
302 | status = iol_execute(padapter, CMD_READ_EFUSE_MAP); | |
303 | if (status == _SUCCESS) | |
304 | efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size); | |
305 | efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map); | |
306 | return status; | |
307 | } | |
308 | ||
309 | void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf) | |
310 | { | |
311 | ||
312 | if (rtw_IOL_applied(Adapter)) { | |
313 | rtw_hal_power_on(Adapter); | |
314 | iol_mode_enable(Adapter, 1); | |
315 | iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf); | |
316 | iol_mode_enable(Adapter, 0); | |
317 | } | |
ee5f8a43 | 318 | } |
319 | ||
ee5f8a43 | 320 | u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data) |
321 | { | |
322 | u16 tmpaddr = 0; | |
323 | u16 start_addr = efuse_addr; | |
324 | u8 badworden = 0x0F; | |
325 | u8 tmpdata[8]; | |
326 | ||
d0beccb0 | 327 | memset(tmpdata, 0xff, PGPKT_DATA_SIZE); |
ee5f8a43 | 328 | |
9c68ed09 | 329 | if (!(word_en & BIT(0))) { |
ee5f8a43 | 330 | tmpaddr = start_addr; |
331 | efuse_OneByteWrite(pAdapter, start_addr++, data[0]); | |
332 | efuse_OneByteWrite(pAdapter, start_addr++, data[1]); | |
333 | ||
334 | efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]); | |
335 | efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]); | |
336 | if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) | |
9c68ed09 | 337 | badworden &= (~BIT(0)); |
ee5f8a43 | 338 | } |
9c68ed09 | 339 | if (!(word_en & BIT(1))) { |
ee5f8a43 | 340 | tmpaddr = start_addr; |
341 | efuse_OneByteWrite(pAdapter, start_addr++, data[2]); | |
342 | efuse_OneByteWrite(pAdapter, start_addr++, data[3]); | |
343 | ||
344 | efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]); | |
345 | efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]); | |
346 | if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) | |
9c68ed09 | 347 | badworden &= (~BIT(1)); |
ee5f8a43 | 348 | } |
9c68ed09 | 349 | if (!(word_en & BIT(2))) { |
ee5f8a43 | 350 | tmpaddr = start_addr; |
351 | efuse_OneByteWrite(pAdapter, start_addr++, data[4]); | |
352 | efuse_OneByteWrite(pAdapter, start_addr++, data[5]); | |
353 | ||
354 | efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]); | |
355 | efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]); | |
356 | if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) | |
9c68ed09 | 357 | badworden &= (~BIT(2)); |
ee5f8a43 | 358 | } |
9c68ed09 | 359 | if (!(word_en & BIT(3))) { |
ee5f8a43 | 360 | tmpaddr = start_addr; |
361 | efuse_OneByteWrite(pAdapter, start_addr++, data[6]); | |
362 | efuse_OneByteWrite(pAdapter, start_addr++, data[7]); | |
363 | ||
364 | efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]); | |
365 | efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]); | |
366 | if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) | |
9c68ed09 | 367 | badworden &= (~BIT(3)); |
ee5f8a43 | 368 | } |
369 | return badworden; | |
370 | } | |
371 | ||
e7e7068f | 372 | static u16 Efuse_GetCurrentSize(struct adapter *pAdapter) |
ee5f8a43 | 373 | { |
374 | int bContinual = true; | |
375 | u16 efuse_addr = 0; | |
376 | u8 hoffset = 0, hworden = 0; | |
377 | u8 efuse_data, word_cnts = 0; | |
378 | ||
379 | rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr); | |
380 | ||
381 | while (bContinual && | |
382 | efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && | |
383 | AVAILABLE_EFUSE_ADDR(efuse_addr)) { | |
384 | if (efuse_data != 0xFF) { | |
385 | if ((efuse_data&0x1F) == 0x0F) { /* extended header */ | |
386 | hoffset = efuse_data; | |
387 | efuse_addr++; | |
388 | efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data); | |
389 | if ((efuse_data & 0x0F) == 0x0F) { | |
390 | efuse_addr++; | |
391 | continue; | |
392 | } else { | |
393 | hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); | |
394 | hworden = efuse_data & 0x0F; | |
395 | } | |
396 | } else { | |
397 | hoffset = (efuse_data>>4) & 0x0F; | |
398 | hworden = efuse_data & 0x0F; | |
399 | } | |
400 | word_cnts = Efuse_CalculateWordCnts(hworden); | |
401 | /* read next header */ | |
402 | efuse_addr = efuse_addr + (word_cnts*2)+1; | |
403 | } else { | |
404 | bContinual = false; | |
405 | } | |
406 | } | |
407 | ||
408 | rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr); | |
409 | ||
410 | return efuse_addr; | |
411 | } | |
412 | ||
413 | int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) | |
414 | { | |
415 | u8 ReadState = PG_STATE_HEADER; | |
416 | int bContinual = true; | |
417 | int bDataEmpty = true; | |
418 | u8 efuse_data, word_cnts = 0; | |
419 | u16 efuse_addr = 0; | |
420 | u8 hoffset = 0, hworden = 0; | |
421 | u8 tmpidx = 0; | |
422 | u8 tmpdata[8]; | |
ee5f8a43 | 423 | u8 tmp_header = 0; |
424 | ||
e59b76cf | 425 | if (!data) |
ee5f8a43 | 426 | return false; |
f573fed7 | 427 | if (offset > EFUSE_MAX_SECTION_88E) |
ee5f8a43 | 428 | return false; |
429 | ||
d0beccb0 LC |
430 | memset(data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); |
431 | memset(tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); | |
ee5f8a43 | 432 | |
433 | /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ | |
434 | /* Skip dummy parts to prevent unexpected data read from Efuse. */ | |
435 | /* By pass right now. 2009.02.19. */ | |
436 | while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) { | |
437 | /* Header Read ------------- */ | |
438 | if (ReadState & PG_STATE_HEADER) { | |
439 | if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) { | |
440 | if (EXT_HEADER(efuse_data)) { | |
441 | tmp_header = efuse_data; | |
442 | efuse_addr++; | |
443 | efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data); | |
444 | if (!ALL_WORDS_DISABLED(efuse_data)) { | |
445 | hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); | |
446 | hworden = efuse_data & 0x0F; | |
447 | } else { | |
448 | DBG_88E("Error, All words disabled\n"); | |
449 | efuse_addr++; | |
450 | continue; | |
451 | } | |
452 | } else { | |
453 | hoffset = (efuse_data>>4) & 0x0F; | |
454 | hworden = efuse_data & 0x0F; | |
455 | } | |
456 | word_cnts = Efuse_CalculateWordCnts(hworden); | |
457 | bDataEmpty = true; | |
458 | ||
459 | if (hoffset == offset) { | |
460 | for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) { | |
461 | if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) { | |
462 | tmpdata[tmpidx] = efuse_data; | |
463 | if (efuse_data != 0xff) | |
464 | bDataEmpty = false; | |
465 | } | |
466 | } | |
467 | if (bDataEmpty == false) { | |
468 | ReadState = PG_STATE_DATA; | |
469 | } else {/* read next header */ | |
470 | efuse_addr = efuse_addr + (word_cnts*2)+1; | |
471 | ReadState = PG_STATE_HEADER; | |
472 | } | |
473 | } else {/* read next header */ | |
474 | efuse_addr = efuse_addr + (word_cnts*2)+1; | |
475 | ReadState = PG_STATE_HEADER; | |
476 | } | |
477 | } else { | |
478 | bContinual = false; | |
479 | } | |
480 | } else if (ReadState & PG_STATE_DATA) { | |
4e0fa71c | 481 | /* Data section Read ------------- */ |
ee5f8a43 | 482 | efuse_WordEnableDataRead(hworden, tmpdata, data); |
483 | efuse_addr = efuse_addr + (word_cnts*2)+1; | |
484 | ReadState = PG_STATE_HEADER; | |
485 | } | |
486 | ||
487 | } | |
488 | ||
489 | if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff) && (data[3] == 0xff) && | |
490 | (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff) && (data[7] == 0xff)) | |
491 | return false; | |
492 | else | |
493 | return true; | |
494 | } | |
495 | ||
496 | static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr) | |
497 | { | |
498 | u8 originaldata[8], badworden = 0; | |
499 | u16 efuse_addr = *pAddr; | |
500 | u32 PgWriteSuccess = 0; | |
501 | ||
d0beccb0 | 502 | memset(originaldata, 0xff, 8); |
ee5f8a43 | 503 | |
504 | if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) { | |
505 | /* check if data exist */ | |
506 | badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata); | |
507 | ||
508 | if (badworden != 0xf) { /* write fail */ | |
509 | PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata); | |
510 | ||
511 | if (!PgWriteSuccess) | |
512 | return false; | |
513 | else | |
514 | efuse_addr = Efuse_GetCurrentSize(pAdapter); | |
515 | } else { | |
516 | efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; | |
517 | } | |
518 | } else { | |
519 | efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; | |
520 | } | |
521 | *pAddr = efuse_addr; | |
522 | return true; | |
523 | } | |
524 | ||
525 | static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) | |
526 | { | |
527 | bool bRet = false; | |
054bf87c IS |
528 | u16 efuse_addr = *pAddr; |
529 | u16 efuse_max_available_len = | |
530 | EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E; | |
ee5f8a43 | 531 | u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0; |
532 | u8 repeatcnt = 0; | |
533 | ||
ee5f8a43 | 534 | while (efuse_addr < efuse_max_available_len) { |
535 | pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F; | |
536 | efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); | |
537 | efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); | |
538 | ||
539 | while (tmp_header == 0xFF) { | |
540 | if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) | |
541 | return false; | |
542 | ||
543 | efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); | |
544 | efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); | |
545 | } | |
546 | ||
547 | /* to write ext_header */ | |
548 | if (tmp_header == pg_header) { | |
549 | efuse_addr++; | |
550 | pg_header_temp = pg_header; | |
551 | pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en; | |
552 | ||
553 | efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); | |
554 | efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); | |
555 | ||
556 | while (tmp_header == 0xFF) { | |
557 | if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) | |
558 | return false; | |
559 | ||
560 | efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); | |
561 | efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); | |
562 | } | |
563 | ||
564 | if ((tmp_header & 0x0F) == 0x0F) { /* word_en PG fail */ | |
565 | if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) { | |
566 | return false; | |
ee5f8a43 | 567 | } |
b7c12ca4 DU |
568 | efuse_addr++; |
569 | continue; | |
ee5f8a43 | 570 | } else if (pg_header != tmp_header) { /* offset PG fail */ |
571 | struct pgpkt fixPkt; | |
572 | fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1); | |
573 | fixPkt.word_en = tmp_header & 0x0F; | |
574 | fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); | |
575 | if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) | |
576 | return false; | |
577 | } else { | |
578 | bRet = true; | |
579 | break; | |
580 | } | |
581 | } else if ((tmp_header & 0x1F) == 0x0F) { /* wrong extended header */ | |
582 | efuse_addr += 2; | |
583 | continue; | |
584 | } | |
585 | } | |
586 | ||
587 | *pAddr = efuse_addr; | |
588 | return bRet; | |
589 | } | |
590 | ||
591 | static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) | |
592 | { | |
593 | bool bRet = false; | |
594 | u8 pg_header = 0, tmp_header = 0; | |
595 | u16 efuse_addr = *pAddr; | |
596 | u8 repeatcnt = 0; | |
597 | ||
598 | pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en; | |
599 | ||
600 | efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); | |
601 | efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); | |
602 | ||
603 | while (tmp_header == 0xFF) { | |
604 | if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) | |
605 | return false; | |
606 | efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); | |
607 | efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); | |
608 | } | |
609 | ||
610 | if (pg_header == tmp_header) { | |
611 | bRet = true; | |
612 | } else { | |
613 | struct pgpkt fixPkt; | |
614 | fixPkt.offset = (tmp_header>>4) & 0x0F; | |
615 | fixPkt.word_en = tmp_header & 0x0F; | |
616 | fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); | |
617 | if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) | |
618 | return false; | |
619 | } | |
620 | ||
621 | *pAddr = efuse_addr; | |
622 | return bRet; | |
623 | } | |
624 | ||
625 | static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) | |
626 | { | |
627 | u16 efuse_addr = *pAddr; | |
628 | u8 badworden = 0; | |
629 | u32 PgWriteSuccess = 0; | |
630 | ||
631 | badworden = 0x0f; | |
632 | badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data); | |
633 | if (badworden == 0x0F) { | |
634 | /* write ok */ | |
635 | return true; | |
ee5f8a43 | 636 | } |
b7c12ca4 DU |
637 | /* reorganize other pg packet */ |
638 | PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data); | |
639 | if (!PgWriteSuccess) | |
640 | return false; | |
641 | else | |
642 | return true; | |
ee5f8a43 | 643 | } |
644 | ||
645 | static bool | |
646 | hal_EfusePgPacketWriteHeader( | |
647 | struct adapter *pAdapter, | |
648 | u8 efuseType, | |
649 | u16 *pAddr, | |
650 | struct pgpkt *pTargetPkt) | |
651 | { | |
652 | bool bRet = false; | |
653 | ||
654 | if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) | |
655 | bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt); | |
656 | else | |
657 | bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt); | |
658 | ||
659 | return bRet; | |
660 | } | |
661 | ||
662 | static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt, | |
663 | u8 *pWden) | |
664 | { | |
665 | u8 match_word_en = 0x0F; /* default all words are disabled */ | |
666 | ||
667 | /* check if the same words are enabled both target and current PG packet */ | |
9c68ed09 AB |
668 | if (((pTargetPkt->word_en & BIT(0)) == 0) && |
669 | ((pCurPkt->word_en & BIT(0)) == 0)) | |
670 | match_word_en &= ~BIT(0); /* enable word 0 */ | |
671 | if (((pTargetPkt->word_en & BIT(1)) == 0) && | |
672 | ((pCurPkt->word_en & BIT(1)) == 0)) | |
673 | match_word_en &= ~BIT(1); /* enable word 1 */ | |
674 | if (((pTargetPkt->word_en & BIT(2)) == 0) && | |
675 | ((pCurPkt->word_en & BIT(2)) == 0)) | |
676 | match_word_en &= ~BIT(2); /* enable word 2 */ | |
677 | if (((pTargetPkt->word_en & BIT(3)) == 0) && | |
678 | ((pCurPkt->word_en & BIT(3)) == 0)) | |
679 | match_word_en &= ~BIT(3); /* enable word 3 */ | |
ee5f8a43 | 680 | |
681 | *pWden = match_word_en; | |
682 | ||
683 | if (match_word_en != 0xf) | |
684 | return true; | |
685 | else | |
686 | return false; | |
687 | } | |
688 | ||
689 | static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr) | |
690 | { | |
691 | bool bRet = false; | |
692 | u8 i, efuse_data; | |
693 | ||
694 | for (i = 0; i < (word_cnts*2); i++) { | |
695 | if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF)) | |
696 | bRet = true; | |
697 | } | |
698 | return bRet; | |
699 | } | |
700 | ||
701 | static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) | |
702 | { | |
703 | bool bRet = false; | |
704 | u8 i, efuse_data = 0, cur_header = 0; | |
705 | u8 matched_wden = 0, badworden = 0; | |
054bf87c IS |
706 | u16 startAddr = 0; |
707 | u16 efuse_max_available_len = | |
708 | EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E; | |
ee5f8a43 | 709 | struct pgpkt curPkt; |
710 | ||
ee5f8a43 | 711 | rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr); |
712 | startAddr %= EFUSE_REAL_CONTENT_LEN; | |
713 | ||
714 | while (1) { | |
715 | if (startAddr >= efuse_max_available_len) { | |
716 | bRet = false; | |
717 | break; | |
718 | } | |
719 | ||
720 | if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) { | |
721 | if (EXT_HEADER(efuse_data)) { | |
722 | cur_header = efuse_data; | |
723 | startAddr++; | |
724 | efuse_OneByteRead(pAdapter, startAddr, &efuse_data); | |
725 | if (ALL_WORDS_DISABLED(efuse_data)) { | |
726 | bRet = false; | |
727 | break; | |
728 | } else { | |
729 | curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); | |
730 | curPkt.word_en = efuse_data & 0x0F; | |
731 | } | |
732 | } else { | |
733 | cur_header = efuse_data; | |
734 | curPkt.offset = (cur_header>>4) & 0x0F; | |
735 | curPkt.word_en = cur_header & 0x0F; | |
736 | } | |
737 | ||
738 | curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en); | |
739 | /* if same header is found but no data followed */ | |
740 | /* write some part of data followed by the header. */ | |
741 | if ((curPkt.offset == pTargetPkt->offset) && | |
742 | (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) && | |
743 | wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) { | |
744 | /* Here to write partial data */ | |
745 | badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data); | |
746 | if (badworden != 0x0F) { | |
747 | u32 PgWriteSuccess = 0; | |
748 | /* if write fail on some words, write these bad words again */ | |
749 | ||
750 | PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data); | |
751 | ||
752 | if (!PgWriteSuccess) { | |
753 | bRet = false; /* write fail, return */ | |
754 | break; | |
755 | } | |
756 | } | |
757 | /* partial write ok, update the target packet for later use */ | |
758 | for (i = 0; i < 4; i++) { | |
759 | if ((matched_wden & (0x1<<i)) == 0) /* this word has been written */ | |
760 | pTargetPkt->word_en |= (0x1<<i); /* disable the word */ | |
761 | } | |
762 | pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); | |
763 | } | |
764 | /* read from next header */ | |
765 | startAddr = startAddr + (curPkt.word_cnts*2) + 1; | |
766 | } else { | |
767 | /* not used header, 0xff */ | |
768 | *pAddr = startAddr; | |
769 | bRet = true; | |
770 | break; | |
771 | } | |
772 | } | |
773 | return bRet; | |
774 | } | |
775 | ||
776 | static bool | |
777 | hal_EfusePgCheckAvailableAddr( | |
778 | struct adapter *pAdapter, | |
779 | u8 efuseType | |
780 | ) | |
781 | { | |
0cdec5a4 | 782 | if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) |
ee5f8a43 | 783 | return false; |
784 | return true; | |
785 | } | |
786 | ||
787 | static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt) | |
788 | { | |
1ce39848 | 789 | memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8); |
ee5f8a43 | 790 | pTargetPkt->offset = offset; |
791 | pTargetPkt->word_en = word_en; | |
792 | efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data); | |
793 | pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); | |
794 | } | |
795 | ||
796 | bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData) | |
797 | { | |
798 | struct pgpkt targetPkt; | |
799 | u16 startAddr = 0; | |
800 | u8 efuseType = EFUSE_WIFI; | |
801 | ||
802 | if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType)) | |
803 | return false; | |
804 | ||
805 | hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); | |
806 | ||
807 | if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt)) | |
808 | return false; | |
809 | ||
810 | if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt)) | |
811 | return false; | |
812 | ||
813 | if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt)) | |
814 | return false; | |
815 | ||
816 | return true; | |
817 | } | |
818 | ||
756850c6 | 819 | u8 Efuse_CalculateWordCnts(u8 word_en) |
06a05884 LF |
820 | { |
821 | u8 word_cnts = 0; | |
822 | if (!(word_en & BIT(0))) | |
823 | word_cnts++; /* 0 : write enable */ | |
824 | if (!(word_en & BIT(1))) | |
825 | word_cnts++; | |
826 | if (!(word_en & BIT(2))) | |
827 | word_cnts++; | |
828 | if (!(word_en & BIT(3))) | |
829 | word_cnts++; | |
830 | return word_cnts; | |
831 | } | |
832 | ||
78810556 | 833 | u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data) |
06a05884 LF |
834 | { |
835 | u8 tmpidx = 0; | |
836 | u8 result; | |
837 | ||
e76484d0 | 838 | usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff)); |
839 | usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) | | |
c7b2e995 | 840 | (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC)); |
06a05884 | 841 | |
e76484d0 | 842 | usb_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */ |
06a05884 | 843 | |
c7b2e995 | 844 | while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100)) |
06a05884 LF |
845 | tmpidx++; |
846 | if (tmpidx < 100) { | |
c7b2e995 | 847 | *data = usb_read8(pAdapter, EFUSE_CTRL); |
06a05884 LF |
848 | result = true; |
849 | } else { | |
850 | *data = 0xff; | |
851 | result = false; | |
852 | } | |
853 | return result; | |
854 | } | |
855 | ||
20f3b6c8 | 856 | u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data) |
06a05884 LF |
857 | { |
858 | u8 tmpidx = 0; | |
859 | u8 result; | |
860 | ||
e76484d0 | 861 | usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff)); |
862 | usb_write8(pAdapter, EFUSE_CTRL+2, | |
c7b2e995 | 863 | (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) | |
06a05884 | 864 | (u8)((addr>>8) & 0x03)); |
e76484d0 | 865 | usb_write8(pAdapter, EFUSE_CTRL, data);/* data */ |
06a05884 | 866 | |
e76484d0 | 867 | usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */ |
06a05884 | 868 | |
c7b2e995 | 869 | while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100)) |
06a05884 LF |
870 | tmpidx++; |
871 | ||
872 | if (tmpidx < 100) | |
873 | result = true; | |
874 | else | |
875 | result = false; | |
876 | ||
877 | return result; | |
878 | } | |
879 | ||
756850c6 | 880 | /* |
881 | * Overview: Read allowed word in current efuse section data. | |
882 | */ | |
06a05884 LF |
883 | void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata) |
884 | { | |
9c68ed09 | 885 | if (!(word_en & BIT(0))) { |
06a05884 LF |
886 | targetdata[0] = sourdata[0]; |
887 | targetdata[1] = sourdata[1]; | |
888 | } | |
9c68ed09 | 889 | if (!(word_en & BIT(1))) { |
06a05884 LF |
890 | targetdata[2] = sourdata[2]; |
891 | targetdata[3] = sourdata[3]; | |
892 | } | |
9c68ed09 | 893 | if (!(word_en & BIT(2))) { |
06a05884 LF |
894 | targetdata[4] = sourdata[4]; |
895 | targetdata[5] = sourdata[5]; | |
896 | } | |
9c68ed09 | 897 | if (!(word_en & BIT(3))) { |
06a05884 LF |
898 | targetdata[6] = sourdata[6]; |
899 | targetdata[7] = sourdata[7]; | |
900 | } | |
901 | } | |
902 | ||
756850c6 | 903 | /* |
06a05884 | 904 | * Overview: Read All Efuse content |
756850c6 | 905 | */ |
0d1c84d6 | 906 | static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse) |
06a05884 | 907 | { |
06a05884 LF |
908 | Efuse_PowerSwitch(pAdapter, false, true); |
909 | ||
0cdec5a4 | 910 | efuse_ReadEFuse(pAdapter, efuseType, 0, EFUSE_MAP_LEN_88E, Efuse); |
06a05884 LF |
911 | |
912 | Efuse_PowerSwitch(pAdapter, false, false); | |
913 | } | |
914 | ||
756850c6 | 915 | /* |
06a05884 | 916 | * Overview: Transfer current EFUSE content to shadow init and modify map. |
756850c6 | 917 | */ |
06a05884 LF |
918 | void EFUSE_ShadowMapUpdate( |
919 | struct adapter *pAdapter, | |
b0d255c7 | 920 | u8 efuseType) |
06a05884 LF |
921 | { |
922 | struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); | |
06a05884 LF |
923 | |
924 | if (pEEPROM->bautoload_fail_flag) | |
0cdec5a4 | 925 | memset(pEEPROM->efuse_eeprom_data, 0xFF, EFUSE_MAP_LEN_88E); |
06a05884 | 926 | else |
0d1c84d6 | 927 | Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data); |
756850c6 | 928 | } |