staging: rtl8188eu:Remove rtw_zmalloc(), wrapper for kzalloc()
[deliverable/linux.git] / drivers / staging / rtl8188eu / core / rtw_efuse.c
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 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20 #define _RTW_EFUSE_C_
21
22 #include <osdep_service.h>
23 #include <drv_types.h>
24 #include <rtw_efuse.h>
25 #include <usb_ops_linux.h>
26 #include <rtl8188e_hal.h>
27 #include <rtw_iol.h>
28
29 #define REG_EFUSE_CTRL 0x0030
30 #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
31
32 enum{
33 VOLTAGE_V25 = 0x03,
34 LDOE25_SHIFT = 28 ,
35 };
36
37 /*
38 * Function: Efuse_PowerSwitch
39 *
40 * Overview: When we want to enable write operation, we should change to
41 * pwr on state. When we stop write, we should switch to 500k mode
42 * and disable LDO 2.5V.
43 */
44
45 void Efuse_PowerSwitch(
46 struct adapter *pAdapter,
47 u8 bWrite,
48 u8 PwrState)
49 {
50 u8 tempval;
51 u16 tmpV16;
52
53 if (PwrState) {
54 usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
55
56 /* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */
57 tmpV16 = usb_read16(pAdapter, REG_SYS_ISO_CTRL);
58 if (!(tmpV16 & PWC_EV12V)) {
59 tmpV16 |= PWC_EV12V;
60 usb_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16);
61 }
62 /* Reset: 0x0000h[28], default valid */
63 tmpV16 = usb_read16(pAdapter, REG_SYS_FUNC_EN);
64 if (!(tmpV16 & FEN_ELDR)) {
65 tmpV16 |= FEN_ELDR;
66 usb_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16);
67 }
68
69 /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
70 tmpV16 = usb_read16(pAdapter, REG_SYS_CLKR);
71 if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
72 tmpV16 |= (LOADER_CLK_EN | ANA8M);
73 usb_write16(pAdapter, REG_SYS_CLKR, tmpV16);
74 }
75
76 if (bWrite) {
77 /* Enable LDO 2.5V before read/write action */
78 tempval = usb_read8(pAdapter, EFUSE_TEST+3);
79 tempval &= 0x0F;
80 tempval |= (VOLTAGE_V25 << 4);
81 usb_write8(pAdapter, EFUSE_TEST+3, (tempval | 0x80));
82 }
83 } else {
84 usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
85
86 if (bWrite) {
87 /* Disable LDO 2.5V after read/write action */
88 tempval = usb_read8(pAdapter, EFUSE_TEST+3);
89 usb_write8(pAdapter, EFUSE_TEST+3, (tempval & 0x7F));
90 }
91 }
92 }
93
94 static void
95 efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf)
96 {
97 u8 *efuseTbl = NULL;
98 u8 rtemp8;
99 u16 eFuse_Addr = 0;
100 u8 offset, wren;
101 u16 i, j;
102 u16 **eFuseWord = NULL;
103 u16 efuse_utilized = 0;
104 u8 u1temp = 0;
105
106 efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
107 if (efuseTbl == NULL) {
108 DBG_88E("%s: alloc efuseTbl fail!\n", __func__);
109 goto exit;
110 }
111
112 eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
113 if (eFuseWord == NULL) {
114 DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
115 goto exit;
116 }
117
118 /* 0. Refresh efuse init map as all oxFF. */
119 for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
120 for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
121 eFuseWord[i][j] = 0xFFFF;
122
123 /* */
124 /* 1. Read the first byte to check if efuse is empty!!! */
125 /* */
126 /* */
127 rtemp8 = *(phymap+eFuse_Addr);
128 if (rtemp8 != 0xFF) {
129 efuse_utilized++;
130 eFuse_Addr++;
131 } else {
132 DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8);
133 goto exit;
134 }
135
136 /* */
137 /* 2. Read real efuse content. Filter PG header and every section data. */
138 /* */
139 while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
140 /* Check PG header for section num. */
141 if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */
142 u1temp = ((rtemp8 & 0xE0) >> 5);
143 rtemp8 = *(phymap+eFuse_Addr);
144 if ((rtemp8 & 0x0F) == 0x0F) {
145 eFuse_Addr++;
146 rtemp8 = *(phymap+eFuse_Addr);
147
148 if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
149 eFuse_Addr++;
150 continue;
151 } else {
152 offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
153 wren = (rtemp8 & 0x0F);
154 eFuse_Addr++;
155 }
156 } else {
157 offset = ((rtemp8 >> 4) & 0x0f);
158 wren = (rtemp8 & 0x0f);
159 }
160
161 if (offset < EFUSE_MAX_SECTION_88E) {
162 /* Get word enable value from PG header */
163 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
164 /* Check word enable condition in the section */
165 if (!(wren & 0x01)) {
166 rtemp8 = *(phymap+eFuse_Addr);
167 eFuse_Addr++;
168 efuse_utilized++;
169 eFuseWord[offset][i] = (rtemp8 & 0xff);
170 if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
171 break;
172 rtemp8 = *(phymap+eFuse_Addr);
173 eFuse_Addr++;
174 efuse_utilized++;
175 eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00);
176
177 if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
178 break;
179 }
180 wren >>= 1;
181 }
182 }
183 /* Read next PG header */
184 rtemp8 = *(phymap+eFuse_Addr);
185
186 if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
187 efuse_utilized++;
188 eFuse_Addr++;
189 }
190 }
191
192 /* */
193 /* 3. Collect 16 sections and 4 word unit into Efuse map. */
194 /* */
195 for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
196 for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
197 efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff);
198 efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff);
199 }
200 }
201
202 /* */
203 /* 4. Copy from Efuse map to output pointer memory!!! */
204 /* */
205 for (i = 0; i < _size_byte; i++)
206 pbuf[i] = efuseTbl[_offset+i];
207
208 /* */
209 /* 5. Calculate Efuse utilization. */
210 /* */
211
212 exit:
213 kfree(efuseTbl);
214
215 if (eFuseWord)
216 kfree(eFuseWord);
217 }
218
219 static void efuse_read_phymap_from_txpktbuf(
220 struct adapter *adapter,
221 int bcnhead, /* beacon head, where FW store len(2-byte) and efuse physical map. */
222 u8 *content, /* buffer to store efuse physical map */
223 u16 *size /* for efuse content: the max byte to read. will update to byte read */
224 )
225 {
226 u16 dbg_addr = 0;
227 u32 start = 0, passing_time = 0;
228 u8 reg_0x143 = 0;
229 u32 lo32 = 0, hi32 = 0;
230 u16 len = 0, count = 0;
231 int i = 0;
232 u16 limit = *size;
233
234 u8 *pos = content;
235
236 if (bcnhead < 0) /* if not valid */
237 bcnhead = usb_read8(adapter, REG_TDECTRL+1);
238
239 DBG_88E("%s bcnhead:%d\n", __func__, bcnhead);
240
241 usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
242
243 dbg_addr = bcnhead*128/8; /* 8-bytes addressing */
244
245 while (1) {
246 usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i);
247
248 usb_write8(adapter, REG_TXPKTBUF_DBG, 0);
249 start = jiffies;
250 while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) &&
251 (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
252 DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106));
253 msleep(1);
254 }
255
256 lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L);
257 hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H);
258
259 if (i == 0) {
260 u8 lenc[2];
261 u16 lenbak, aaabak;
262 u16 aaa;
263 lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L);
264 lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1);
265
266 aaabak = le16_to_cpup((__le16 *)lenc);
267 lenbak = le16_to_cpu(*((__le16 *)lenc));
268 aaa = le16_to_cpup((__le16 *)&lo32);
269 len = le16_to_cpu(*((__le16 *)&lo32));
270
271 limit = (len-2 < limit) ? len-2 : limit;
272
273 DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak);
274
275 memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count);
276 count += (limit >= count+2) ? 2 : limit-count;
277 pos = content+count;
278
279 } else {
280 memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count);
281 count += (limit >= count+4) ? 4 : limit-count;
282 pos = content+count;
283 }
284
285 if (limit > count && len-2 > count) {
286 memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count);
287 count += (limit >= count+4) ? 4 : limit-count;
288 pos = content+count;
289 }
290
291 if (limit <= count || len-2 <= count)
292 break;
293 i++;
294 }
295 usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
296 DBG_88E("%s read count:%u\n", __func__, count);
297 *size = count;
298 }
299
300 static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map)
301 {
302 s32 status = _FAIL;
303 u8 physical_map[512];
304 u16 size = 512;
305
306 usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy);
307 memset(physical_map, 0xFF, 512);
308 usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
309 status = iol_execute(padapter, CMD_READ_EFUSE_MAP);
310 if (status == _SUCCESS)
311 efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size);
312 efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map);
313 return status;
314 }
315
316 void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
317 {
318
319 if (rtw_IOL_applied(Adapter)) {
320 rtw_hal_power_on(Adapter);
321 iol_mode_enable(Adapter, 1);
322 iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf);
323 iol_mode_enable(Adapter, 0);
324 }
325 return;
326 }
327
328 /* Do not support BT */
329 void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
330 {
331 switch (type) {
332 case TYPE_EFUSE_MAX_SECTION:
333 {
334 u8 *pMax_section;
335 pMax_section = (u8 *)pOut;
336 *pMax_section = EFUSE_MAX_SECTION_88E;
337 }
338 break;
339 case TYPE_EFUSE_REAL_CONTENT_LEN:
340 {
341 u16 *pu2Tmp;
342 pu2Tmp = (u16 *)pOut;
343 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
344 }
345 break;
346 case TYPE_EFUSE_CONTENT_LEN_BANK:
347 {
348 u16 *pu2Tmp;
349 pu2Tmp = (u16 *)pOut;
350 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
351 }
352 break;
353 case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
354 {
355 u16 *pu2Tmp;
356 pu2Tmp = (u16 *)pOut;
357 *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
358 }
359 break;
360 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
361 {
362 u16 *pu2Tmp;
363 pu2Tmp = (u16 *)pOut;
364 *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
365 }
366 break;
367 case TYPE_EFUSE_MAP_LEN:
368 {
369 u16 *pu2Tmp;
370 pu2Tmp = (u16 *)pOut;
371 *pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
372 }
373 break;
374 case TYPE_EFUSE_PROTECT_BYTES_BANK:
375 {
376 u8 *pu1Tmp;
377 pu1Tmp = (u8 *)pOut;
378 *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
379 }
380 break;
381 default:
382 {
383 u8 *pu1Tmp;
384 pu1Tmp = (u8 *)pOut;
385 *pu1Tmp = 0;
386 }
387 break;
388 }
389 }
390
391 u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data)
392 {
393 u16 tmpaddr = 0;
394 u16 start_addr = efuse_addr;
395 u8 badworden = 0x0F;
396 u8 tmpdata[8];
397
398 memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
399
400 if (!(word_en&BIT0)) {
401 tmpaddr = start_addr;
402 efuse_OneByteWrite(pAdapter, start_addr++, data[0]);
403 efuse_OneByteWrite(pAdapter, start_addr++, data[1]);
404
405 efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]);
406 efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]);
407 if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
408 badworden &= (~BIT0);
409 }
410 if (!(word_en&BIT1)) {
411 tmpaddr = start_addr;
412 efuse_OneByteWrite(pAdapter, start_addr++, data[2]);
413 efuse_OneByteWrite(pAdapter, start_addr++, data[3]);
414
415 efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]);
416 efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]);
417 if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
418 badworden &= (~BIT1);
419 }
420 if (!(word_en&BIT2)) {
421 tmpaddr = start_addr;
422 efuse_OneByteWrite(pAdapter, start_addr++, data[4]);
423 efuse_OneByteWrite(pAdapter, start_addr++, data[5]);
424
425 efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]);
426 efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]);
427 if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
428 badworden &= (~BIT2);
429 }
430 if (!(word_en&BIT3)) {
431 tmpaddr = start_addr;
432 efuse_OneByteWrite(pAdapter, start_addr++, data[6]);
433 efuse_OneByteWrite(pAdapter, start_addr++, data[7]);
434
435 efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]);
436 efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]);
437 if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
438 badworden &= (~BIT3);
439 }
440 return badworden;
441 }
442
443 u16 Efuse_GetCurrentSize(struct adapter *pAdapter)
444 {
445 int bContinual = true;
446 u16 efuse_addr = 0;
447 u8 hoffset = 0, hworden = 0;
448 u8 efuse_data, word_cnts = 0;
449
450 rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
451
452 while (bContinual &&
453 efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) &&
454 AVAILABLE_EFUSE_ADDR(efuse_addr)) {
455 if (efuse_data != 0xFF) {
456 if ((efuse_data&0x1F) == 0x0F) { /* extended header */
457 hoffset = efuse_data;
458 efuse_addr++;
459 efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
460 if ((efuse_data & 0x0F) == 0x0F) {
461 efuse_addr++;
462 continue;
463 } else {
464 hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
465 hworden = efuse_data & 0x0F;
466 }
467 } else {
468 hoffset = (efuse_data>>4) & 0x0F;
469 hworden = efuse_data & 0x0F;
470 }
471 word_cnts = Efuse_CalculateWordCnts(hworden);
472 /* read next header */
473 efuse_addr = efuse_addr + (word_cnts*2)+1;
474 } else {
475 bContinual = false;
476 }
477 }
478
479 rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
480
481 return efuse_addr;
482 }
483
484 int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data)
485 {
486 u8 ReadState = PG_STATE_HEADER;
487 int bContinual = true;
488 int bDataEmpty = true;
489 u8 efuse_data, word_cnts = 0;
490 u16 efuse_addr = 0;
491 u8 hoffset = 0, hworden = 0;
492 u8 tmpidx = 0;
493 u8 tmpdata[8];
494 u8 max_section = 0;
495 u8 tmp_header = 0;
496
497 EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section);
498
499 if (data == NULL)
500 return false;
501 if (offset > max_section)
502 return false;
503
504 memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
505 memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
506
507 /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
508 /* Skip dummy parts to prevent unexpected data read from Efuse. */
509 /* By pass right now. 2009.02.19. */
510 while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) {
511 /* Header Read ------------- */
512 if (ReadState & PG_STATE_HEADER) {
513 if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) {
514 if (EXT_HEADER(efuse_data)) {
515 tmp_header = efuse_data;
516 efuse_addr++;
517 efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
518 if (!ALL_WORDS_DISABLED(efuse_data)) {
519 hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
520 hworden = efuse_data & 0x0F;
521 } else {
522 DBG_88E("Error, All words disabled\n");
523 efuse_addr++;
524 continue;
525 }
526 } else {
527 hoffset = (efuse_data>>4) & 0x0F;
528 hworden = efuse_data & 0x0F;
529 }
530 word_cnts = Efuse_CalculateWordCnts(hworden);
531 bDataEmpty = true;
532
533 if (hoffset == offset) {
534 for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) {
535 if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) {
536 tmpdata[tmpidx] = efuse_data;
537 if (efuse_data != 0xff)
538 bDataEmpty = false;
539 }
540 }
541 if (bDataEmpty == false) {
542 ReadState = PG_STATE_DATA;
543 } else {/* read next header */
544 efuse_addr = efuse_addr + (word_cnts*2)+1;
545 ReadState = PG_STATE_HEADER;
546 }
547 } else {/* read next header */
548 efuse_addr = efuse_addr + (word_cnts*2)+1;
549 ReadState = PG_STATE_HEADER;
550 }
551 } else {
552 bContinual = false;
553 }
554 } else if (ReadState & PG_STATE_DATA) {
555 /* Data section Read ------------- */
556 efuse_WordEnableDataRead(hworden, tmpdata, data);
557 efuse_addr = efuse_addr + (word_cnts*2)+1;
558 ReadState = PG_STATE_HEADER;
559 }
560
561 }
562
563 if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff) && (data[3] == 0xff) &&
564 (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff) && (data[7] == 0xff))
565 return false;
566 else
567 return true;
568 }
569
570 static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr)
571 {
572 u8 originaldata[8], badworden = 0;
573 u16 efuse_addr = *pAddr;
574 u32 PgWriteSuccess = 0;
575
576 memset((void *)originaldata, 0xff, 8);
577
578 if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) {
579 /* check if data exist */
580 badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata);
581
582 if (badworden != 0xf) { /* write fail */
583 PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata);
584
585 if (!PgWriteSuccess)
586 return false;
587 else
588 efuse_addr = Efuse_GetCurrentSize(pAdapter);
589 } else {
590 efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
591 }
592 } else {
593 efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
594 }
595 *pAddr = efuse_addr;
596 return true;
597 }
598
599 static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
600 {
601 bool bRet = false;
602 u16 efuse_addr = *pAddr, efuse_max_available_len = 0;
603 u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
604 u8 repeatcnt = 0;
605
606 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len);
607
608 while (efuse_addr < efuse_max_available_len) {
609 pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
610 efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
611 efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
612
613 while (tmp_header == 0xFF) {
614 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
615 return false;
616
617 efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
618 efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
619 }
620
621 /* to write ext_header */
622 if (tmp_header == pg_header) {
623 efuse_addr++;
624 pg_header_temp = pg_header;
625 pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
626
627 efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
628 efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
629
630 while (tmp_header == 0xFF) {
631 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
632 return false;
633
634 efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
635 efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
636 }
637
638 if ((tmp_header & 0x0F) == 0x0F) { /* word_en PG fail */
639 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
640 return false;
641 } else {
642 efuse_addr++;
643 continue;
644 }
645 } else if (pg_header != tmp_header) { /* offset PG fail */
646 struct pgpkt fixPkt;
647 fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
648 fixPkt.word_en = tmp_header & 0x0F;
649 fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
650 if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
651 return false;
652 } else {
653 bRet = true;
654 break;
655 }
656 } else if ((tmp_header & 0x1F) == 0x0F) { /* wrong extended header */
657 efuse_addr += 2;
658 continue;
659 }
660 }
661
662 *pAddr = efuse_addr;
663 return bRet;
664 }
665
666 static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
667 {
668 bool bRet = false;
669 u8 pg_header = 0, tmp_header = 0;
670 u16 efuse_addr = *pAddr;
671 u8 repeatcnt = 0;
672
673 pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
674
675 efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
676 efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
677
678 while (tmp_header == 0xFF) {
679 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
680 return false;
681 efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
682 efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
683 }
684
685 if (pg_header == tmp_header) {
686 bRet = true;
687 } else {
688 struct pgpkt fixPkt;
689 fixPkt.offset = (tmp_header>>4) & 0x0F;
690 fixPkt.word_en = tmp_header & 0x0F;
691 fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
692 if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
693 return false;
694 }
695
696 *pAddr = efuse_addr;
697 return bRet;
698 }
699
700 static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
701 {
702 u16 efuse_addr = *pAddr;
703 u8 badworden = 0;
704 u32 PgWriteSuccess = 0;
705
706 badworden = 0x0f;
707 badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data);
708 if (badworden == 0x0F) {
709 /* write ok */
710 return true;
711 } else {
712 /* reorganize other pg packet */
713 PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
714 if (!PgWriteSuccess)
715 return false;
716 else
717 return true;
718 }
719 }
720
721 static bool
722 hal_EfusePgPacketWriteHeader(
723 struct adapter *pAdapter,
724 u8 efuseType,
725 u16 *pAddr,
726 struct pgpkt *pTargetPkt)
727 {
728 bool bRet = false;
729
730 if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
731 bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
732 else
733 bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
734
735 return bRet;
736 }
737
738 static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
739 u8 *pWden)
740 {
741 u8 match_word_en = 0x0F; /* default all words are disabled */
742
743 /* check if the same words are enabled both target and current PG packet */
744 if (((pTargetPkt->word_en & BIT0) == 0) &&
745 ((pCurPkt->word_en & BIT0) == 0))
746 match_word_en &= ~BIT0; /* enable word 0 */
747 if (((pTargetPkt->word_en & BIT1) == 0) &&
748 ((pCurPkt->word_en & BIT1) == 0))
749 match_word_en &= ~BIT1; /* enable word 1 */
750 if (((pTargetPkt->word_en & BIT2) == 0) &&
751 ((pCurPkt->word_en & BIT2) == 0))
752 match_word_en &= ~BIT2; /* enable word 2 */
753 if (((pTargetPkt->word_en & BIT3) == 0) &&
754 ((pCurPkt->word_en & BIT3) == 0))
755 match_word_en &= ~BIT3; /* enable word 3 */
756
757 *pWden = match_word_en;
758
759 if (match_word_en != 0xf)
760 return true;
761 else
762 return false;
763 }
764
765 static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr)
766 {
767 bool bRet = false;
768 u8 i, efuse_data;
769
770 for (i = 0; i < (word_cnts*2); i++) {
771 if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF))
772 bRet = true;
773 }
774 return bRet;
775 }
776
777 static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
778 {
779 bool bRet = false;
780 u8 i, efuse_data = 0, cur_header = 0;
781 u8 matched_wden = 0, badworden = 0;
782 u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
783 struct pgpkt curPkt;
784
785 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len);
786 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max);
787
788 rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
789 startAddr %= EFUSE_REAL_CONTENT_LEN;
790
791 while (1) {
792 if (startAddr >= efuse_max_available_len) {
793 bRet = false;
794 break;
795 }
796
797 if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) {
798 if (EXT_HEADER(efuse_data)) {
799 cur_header = efuse_data;
800 startAddr++;
801 efuse_OneByteRead(pAdapter, startAddr, &efuse_data);
802 if (ALL_WORDS_DISABLED(efuse_data)) {
803 bRet = false;
804 break;
805 } else {
806 curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
807 curPkt.word_en = efuse_data & 0x0F;
808 }
809 } else {
810 cur_header = efuse_data;
811 curPkt.offset = (cur_header>>4) & 0x0F;
812 curPkt.word_en = cur_header & 0x0F;
813 }
814
815 curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
816 /* if same header is found but no data followed */
817 /* write some part of data followed by the header. */
818 if ((curPkt.offset == pTargetPkt->offset) &&
819 (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) &&
820 wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
821 /* Here to write partial data */
822 badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data);
823 if (badworden != 0x0F) {
824 u32 PgWriteSuccess = 0;
825 /* if write fail on some words, write these bad words again */
826
827 PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
828
829 if (!PgWriteSuccess) {
830 bRet = false; /* write fail, return */
831 break;
832 }
833 }
834 /* partial write ok, update the target packet for later use */
835 for (i = 0; i < 4; i++) {
836 if ((matched_wden & (0x1<<i)) == 0) /* this word has been written */
837 pTargetPkt->word_en |= (0x1<<i); /* disable the word */
838 }
839 pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
840 }
841 /* read from next header */
842 startAddr = startAddr + (curPkt.word_cnts*2) + 1;
843 } else {
844 /* not used header, 0xff */
845 *pAddr = startAddr;
846 bRet = true;
847 break;
848 }
849 }
850 return bRet;
851 }
852
853 static bool
854 hal_EfusePgCheckAvailableAddr(
855 struct adapter *pAdapter,
856 u8 efuseType
857 )
858 {
859 u16 efuse_max_available_len = 0;
860
861 /* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */
862 EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len);
863
864 if (Efuse_GetCurrentSize(pAdapter) >= efuse_max_available_len)
865 return false;
866 return true;
867 }
868
869 static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
870 {
871 memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8);
872 pTargetPkt->offset = offset;
873 pTargetPkt->word_en = word_en;
874 efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
875 pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
876 }
877
878 bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData)
879 {
880 struct pgpkt targetPkt;
881 u16 startAddr = 0;
882 u8 efuseType = EFUSE_WIFI;
883
884 if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType))
885 return false;
886
887 hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
888
889 if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt))
890 return false;
891
892 if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt))
893 return false;
894
895 if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt))
896 return false;
897
898 return true;
899 }
900
901 u8 Efuse_CalculateWordCnts(u8 word_en)
902 {
903 u8 word_cnts = 0;
904 if (!(word_en & BIT(0)))
905 word_cnts++; /* 0 : write enable */
906 if (!(word_en & BIT(1)))
907 word_cnts++;
908 if (!(word_en & BIT(2)))
909 word_cnts++;
910 if (!(word_en & BIT(3)))
911 word_cnts++;
912 return word_cnts;
913 }
914
915 u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data)
916 {
917 u8 tmpidx = 0;
918 u8 result;
919
920 usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
921 usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
922 (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
923
924 usb_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */
925
926 while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
927 tmpidx++;
928 if (tmpidx < 100) {
929 *data = usb_read8(pAdapter, EFUSE_CTRL);
930 result = true;
931 } else {
932 *data = 0xff;
933 result = false;
934 }
935 return result;
936 }
937
938 u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data)
939 {
940 u8 tmpidx = 0;
941 u8 result;
942
943 usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
944 usb_write8(pAdapter, EFUSE_CTRL+2,
945 (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
946 (u8)((addr>>8) & 0x03));
947 usb_write8(pAdapter, EFUSE_CTRL, data);/* data */
948
949 usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
950
951 while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
952 tmpidx++;
953
954 if (tmpidx < 100)
955 result = true;
956 else
957 result = false;
958
959 return result;
960 }
961
962 /*
963 * Overview: Read allowed word in current efuse section data.
964 */
965 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
966 {
967 if (!(word_en&BIT(0))) {
968 targetdata[0] = sourdata[0];
969 targetdata[1] = sourdata[1];
970 }
971 if (!(word_en&BIT(1))) {
972 targetdata[2] = sourdata[2];
973 targetdata[3] = sourdata[3];
974 }
975 if (!(word_en&BIT(2))) {
976 targetdata[4] = sourdata[4];
977 targetdata[5] = sourdata[5];
978 }
979 if (!(word_en&BIT(3))) {
980 targetdata[6] = sourdata[6];
981 targetdata[7] = sourdata[7];
982 }
983 }
984
985 static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
986 {
987 return efuse_OneByteRead(padapter, address, value);
988 }
989
990 static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
991 {
992 return efuse_OneByteWrite(padapter, address, *value);
993 }
994
995 /*
996 * read/wirte raw efuse data
997 */
998 u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts, u8 *data)
999 {
1000 int i = 0;
1001 u16 real_content_len = 0, max_available_size = 0;
1002 u8 res = _FAIL;
1003 u8 (*rw8)(struct adapter *, u16, u8*);
1004
1005 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len);
1006 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
1007
1008 if (start_addr > real_content_len)
1009 return _FAIL;
1010
1011 if (write) {
1012 if ((start_addr + cnts) > max_available_size)
1013 return _FAIL;
1014 rw8 = &efuse_write8;
1015 } else {
1016 rw8 = &efuse_read8;
1017 }
1018
1019 Efuse_PowerSwitch(padapter, write, true);
1020
1021 /* e-fuse one byte read / write */
1022 for (i = 0; i < cnts; i++) {
1023 if (start_addr >= real_content_len) {
1024 res = _FAIL;
1025 break;
1026 }
1027
1028 res = rw8(padapter, start_addr++, data++);
1029 if (_FAIL == res)
1030 break;
1031 }
1032
1033 Efuse_PowerSwitch(padapter, write, false);
1034
1035 return res;
1036 }
1037
1038 u16 efuse_GetMaxSize(struct adapter *padapter)
1039 {
1040 u16 max_size;
1041 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size);
1042 return max_size;
1043 }
1044
1045 u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
1046 {
1047 Efuse_PowerSwitch(padapter, false, true);
1048 *size = Efuse_GetCurrentSize(padapter);
1049 Efuse_PowerSwitch(padapter, false, false);
1050
1051 return _SUCCESS;
1052 }
1053
1054 u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
1055 {
1056 u16 mapLen = 0;
1057
1058 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
1059
1060 if ((addr + cnts) > mapLen)
1061 return _FAIL;
1062
1063 Efuse_PowerSwitch(padapter, false, true);
1064
1065 efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data);
1066
1067 Efuse_PowerSwitch(padapter, false, false);
1068
1069 return _SUCCESS;
1070 }
1071
1072 u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
1073 {
1074 u8 offset, word_en;
1075 u8 *map;
1076 u8 newdata[PGPKT_DATA_SIZE + 1];
1077 s32 i, idx;
1078 u8 ret = _SUCCESS;
1079 u16 mapLen = 0;
1080
1081 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
1082
1083 if ((addr + cnts) > mapLen)
1084 return _FAIL;
1085
1086 map = kzalloc(mapLen, GFP_KERNEL);
1087 if (map == NULL)
1088 return _FAIL;
1089
1090 ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
1091 if (ret == _FAIL)
1092 goto exit;
1093
1094 Efuse_PowerSwitch(padapter, true, true);
1095
1096 offset = (addr >> 3);
1097 word_en = 0xF;
1098 memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
1099 i = addr & 0x7; /* index of one package */
1100 idx = 0; /* data index */
1101
1102 if (i & 0x1) {
1103 /* odd start */
1104 if (data[idx] != map[addr+idx]) {
1105 word_en &= ~BIT(i >> 1);
1106 newdata[i-1] = map[addr+idx-1];
1107 newdata[i] = data[idx];
1108 }
1109 i++;
1110 idx++;
1111 }
1112 do {
1113 for (; i < PGPKT_DATA_SIZE; i += 2) {
1114 if (cnts == idx)
1115 break;
1116 if ((cnts - idx) == 1) {
1117 if (data[idx] != map[addr+idx]) {
1118 word_en &= ~BIT(i >> 1);
1119 newdata[i] = data[idx];
1120 newdata[i+1] = map[addr+idx+1];
1121 }
1122 idx++;
1123 break;
1124 } else {
1125 if ((data[idx] != map[addr+idx]) ||
1126 (data[idx+1] != map[addr+idx+1])) {
1127 word_en &= ~BIT(i >> 1);
1128 newdata[i] = data[idx];
1129 newdata[i+1] = data[idx + 1];
1130 }
1131 idx += 2;
1132 }
1133 if (idx == cnts)
1134 break;
1135 }
1136
1137 if (word_en != 0xF) {
1138 ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata);
1139 DBG_88E("offset=%x\n", offset);
1140 DBG_88E("word_en=%x\n", word_en);
1141
1142 for (i = 0; i < PGPKT_DATA_SIZE; i++)
1143 DBG_88E("data=%x \t", newdata[i]);
1144 if (ret == _FAIL)
1145 break;
1146 }
1147
1148 if (idx == cnts)
1149 break;
1150
1151 offset++;
1152 i = 0;
1153 word_en = 0xF;
1154 memset(newdata, 0xFF, PGPKT_DATA_SIZE);
1155 } while (1);
1156
1157 Efuse_PowerSwitch(padapter, true, false);
1158 exit:
1159 kfree(map);
1160 return ret;
1161 }
1162
1163 /*
1164 * Function: efuse_ShadowRead1Byte
1165 * efuse_ShadowRead2Byte
1166 * efuse_ShadowRead4Byte
1167 *
1168 * Overview: Read from efuse init map by one/two/four bytes !!!!!
1169 */
1170 static void
1171 efuse_ShadowRead1Byte(
1172 struct adapter *pAdapter,
1173 u16 Offset,
1174 u8 *Value)
1175 {
1176 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
1177
1178 *Value = pEEPROM->efuse_eeprom_data[Offset];
1179
1180 }
1181
1182 static void
1183 efuse_ShadowRead2Byte(
1184 struct adapter *pAdapter,
1185 u16 Offset,
1186 u16 *Value)
1187 {
1188 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
1189
1190 *Value = pEEPROM->efuse_eeprom_data[Offset];
1191 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
1192
1193 }
1194
1195 static void
1196 efuse_ShadowRead4Byte(
1197 struct adapter *pAdapter,
1198 u16 Offset,
1199 u32 *Value)
1200 {
1201 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
1202
1203 *Value = pEEPROM->efuse_eeprom_data[Offset];
1204 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
1205 *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
1206 *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
1207
1208 }
1209
1210 /*
1211 * Overview: Read All Efuse content
1212 */
1213 static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse)
1214 {
1215 u16 mapLen = 0;
1216
1217 Efuse_PowerSwitch(pAdapter, false, true);
1218
1219 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
1220
1221 efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse);
1222
1223 Efuse_PowerSwitch(pAdapter, false, false);
1224 }
1225
1226 /*
1227 * Overview: Transfer current EFUSE content to shadow init and modify map.
1228 */
1229 void EFUSE_ShadowMapUpdate(
1230 struct adapter *pAdapter,
1231 u8 efuseType)
1232 {
1233 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
1234 u16 mapLen = 0;
1235
1236 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
1237
1238 if (pEEPROM->bautoload_fail_flag)
1239 memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
1240 else
1241 Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data);
1242 }
1243
1244 /*
1245 * Overview: Read from efuse init map !!!!!
1246 */
1247 void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
1248 {
1249 if (Type == 1)
1250 efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
1251 else if (Type == 2)
1252 efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
1253 else if (Type == 4)
1254 efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
1255 }
This page took 0.060281 seconds and 5 git commands to generate.