1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
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
19 ******************************************************************************/
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>
29 #define REG_EFUSE_CTRL 0x0030
30 #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
38 * Function: Efuse_PowerSwitch
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.
45 void Efuse_PowerSwitch(
46 struct adapter
*pAdapter
,
54 usb_write8(pAdapter
, REG_EFUSE_ACCESS
, EFUSE_ACCESS_ON
);
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
)) {
60 usb_write16(pAdapter
, REG_SYS_ISO_CTRL
, tmpV16
);
62 /* Reset: 0x0000h[28], default valid */
63 tmpV16
= usb_read16(pAdapter
, REG_SYS_FUNC_EN
);
64 if (!(tmpV16
& FEN_ELDR
)) {
66 usb_write16(pAdapter
, REG_SYS_FUNC_EN
, tmpV16
);
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
);
77 /* Enable LDO 2.5V before read/write action */
78 tempval
= usb_read8(pAdapter
, EFUSE_TEST
+3);
80 tempval
|= (VOLTAGE_V25
<< 4);
81 usb_write8(pAdapter
, EFUSE_TEST
+3, (tempval
| 0x80));
84 usb_write8(pAdapter
, REG_EFUSE_ACCESS
, EFUSE_ACCESS_OFF
);
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));
95 efuse_phymap_to_logical(u8
*phymap
, u16 _offset
, u16 _size_byte
, u8
*pbuf
)
102 u16
**eFuseWord
= NULL
;
103 u16 efuse_utilized
= 0;
106 efuseTbl
= kzalloc(EFUSE_MAP_LEN_88E
, GFP_KERNEL
);
107 if (efuseTbl
== NULL
) {
108 DBG_88E("%s: alloc efuseTbl fail!\n", __func__
);
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__
);
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;
124 /* 1. Read the first byte to check if efuse is empty!!! */
127 rtemp8
= *(phymap
+eFuse_Addr
);
128 if (rtemp8
!= 0xFF) {
132 DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr
, rtemp8
);
137 /* 2. Read real efuse content. Filter PG header and every section data. */
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) {
146 rtemp8
= *(phymap
+eFuse_Addr
);
148 if (rtemp8
!= 0xFF && (eFuse_Addr
< EFUSE_REAL_CONTENT_LEN_88E
))
152 offset
= ((rtemp8
& 0xF0) >> 1) | u1temp
;
153 wren
= (rtemp8
& 0x0F);
157 offset
= ((rtemp8
>> 4) & 0x0f);
158 wren
= (rtemp8
& 0x0f);
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
);
169 eFuseWord
[offset
][i
] = (rtemp8
& 0xff);
170 if (eFuse_Addr
>= EFUSE_REAL_CONTENT_LEN_88E
)
172 rtemp8
= *(phymap
+eFuse_Addr
);
175 eFuseWord
[offset
][i
] |= (((u16
)rtemp8
<< 8) & 0xff00);
177 if (eFuse_Addr
>= EFUSE_REAL_CONTENT_LEN_88E
)
183 /* Read next PG header */
184 rtemp8
= *(phymap
+eFuse_Addr
);
186 if (rtemp8
!= 0xFF && (eFuse_Addr
< EFUSE_REAL_CONTENT_LEN_88E
)) {
193 /* 3. Collect 16 sections and 4 word unit into Efuse map. */
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);
203 /* 4. Copy from Efuse map to output pointer memory!!! */
205 for (i
= 0; i
< _size_byte
; i
++)
206 pbuf
[i
] = efuseTbl
[_offset
+i
];
209 /* 5. Calculate Efuse utilization. */
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 */
227 u32 start
= 0, passing_time
= 0;
229 u32 lo32
= 0, hi32
= 0;
230 u16 len
= 0, count
= 0;
236 if (bcnhead
< 0) /* if not valid */
237 bcnhead
= usb_read8(adapter
, REG_TDECTRL
+1);
239 DBG_88E("%s bcnhead:%d\n", __func__
, bcnhead
);
241 usb_write8(adapter
, REG_PKT_BUFF_ACCESS_CTRL
, TXPKT_BUF_SELECT
);
243 dbg_addr
= bcnhead
*128/8; /* 8-bytes addressing */
246 usb_write16(adapter
, REG_PKTBUF_DBG_ADDR
, dbg_addr
+i
);
248 usb_write8(adapter
, REG_TXPKTBUF_DBG
, 0);
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));
256 lo32
= usb_read32(adapter
, REG_PKTBUF_DBG_DATA_L
);
257 hi32
= usb_read32(adapter
, REG_PKTBUF_DBG_DATA_H
);
263 lenc
[0] = usb_read8(adapter
, REG_PKTBUF_DBG_DATA_L
);
264 lenc
[1] = usb_read8(adapter
, REG_PKTBUF_DBG_DATA_L
+1);
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
));
271 limit
= (len
-2 < limit
) ? len
-2 : limit
;
273 DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__
, len
, lenbak
, aaa
, aaabak
);
275 memcpy(pos
, ((u8
*)&lo32
)+2, (limit
>= count
+2) ? 2 : limit
-count
);
276 count
+= (limit
>= count
+2) ? 2 : limit
-count
;
280 memcpy(pos
, ((u8
*)&lo32
), (limit
>= count
+4) ? 4 : limit
-count
);
281 count
+= (limit
>= count
+4) ? 4 : limit
-count
;
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
;
291 if (limit
<= count
|| len
-2 <= count
)
295 usb_write8(adapter
, REG_PKT_BUFF_ACCESS_CTRL
, DISABLE_TRXPKT_BUF_ACCESS
);
296 DBG_88E("%s read count:%u\n", __func__
, count
);
300 static s32
iol_read_efuse(struct adapter
*padapter
, u8 txpktbuf_bndy
, u16 offset
, u16 size_byte
, u8
*logical_map
)
303 u8 physical_map
[512];
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
);
316 void efuse_ReadEFuse(struct adapter
*Adapter
, u8 efuseType
, u16 _offset
, u16 _size_byte
, u8
*pbuf
)
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);
328 /* Do not support BT */
329 void EFUSE_GetEfuseDefinition(struct adapter
*pAdapter
, u8 efuseType
, u8 type
, void *pOut
)
332 case TYPE_EFUSE_MAX_SECTION
:
335 pMax_section
= (u8
*)pOut
;
336 *pMax_section
= EFUSE_MAX_SECTION_88E
;
339 case TYPE_EFUSE_REAL_CONTENT_LEN
:
342 pu2Tmp
= (u16
*)pOut
;
343 *pu2Tmp
= EFUSE_REAL_CONTENT_LEN_88E
;
346 case TYPE_EFUSE_CONTENT_LEN_BANK
:
349 pu2Tmp
= (u16
*)pOut
;
350 *pu2Tmp
= EFUSE_REAL_CONTENT_LEN_88E
;
353 case TYPE_AVAILABLE_EFUSE_BYTES_BANK
:
356 pu2Tmp
= (u16
*)pOut
;
357 *pu2Tmp
= (u16
)(EFUSE_REAL_CONTENT_LEN_88E
-EFUSE_OOB_PROTECT_BYTES_88E
);
360 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL
:
363 pu2Tmp
= (u16
*)pOut
;
364 *pu2Tmp
= (u16
)(EFUSE_REAL_CONTENT_LEN_88E
-EFUSE_OOB_PROTECT_BYTES_88E
);
367 case TYPE_EFUSE_MAP_LEN
:
370 pu2Tmp
= (u16
*)pOut
;
371 *pu2Tmp
= (u16
)EFUSE_MAP_LEN_88E
;
374 case TYPE_EFUSE_PROTECT_BYTES_BANK
:
378 *pu1Tmp
= (u8
)(EFUSE_OOB_PROTECT_BYTES_88E
);
391 u8
Efuse_WordEnableDataWrite(struct adapter
*pAdapter
, u16 efuse_addr
, u8 word_en
, u8
*data
)
394 u16 start_addr
= efuse_addr
;
398 memset((void *)tmpdata
, 0xff, PGPKT_DATA_SIZE
);
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]);
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
);
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]);
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
);
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]);
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
);
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]);
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
);
443 u16
Efuse_GetCurrentSize(struct adapter
*pAdapter
)
445 int bContinual
= true;
447 u8 hoffset
= 0, hworden
= 0;
448 u8 efuse_data
, word_cnts
= 0;
450 rtw_hal_get_hwreg(pAdapter
, HW_VAR_EFUSE_BYTES
, (u8
*)&efuse_addr
);
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
;
459 efuse_OneByteRead(pAdapter
, efuse_addr
, &efuse_data
);
460 if ((efuse_data
& 0x0F) == 0x0F) {
464 hoffset
= ((hoffset
& 0xE0) >> 5) | ((efuse_data
& 0xF0) >> 1);
465 hworden
= efuse_data
& 0x0F;
468 hoffset
= (efuse_data
>>4) & 0x0F;
469 hworden
= efuse_data
& 0x0F;
471 word_cnts
= Efuse_CalculateWordCnts(hworden
);
472 /* read next header */
473 efuse_addr
= efuse_addr
+ (word_cnts
*2)+1;
479 rtw_hal_set_hwreg(pAdapter
, HW_VAR_EFUSE_BYTES
, (u8
*)&efuse_addr
);
484 int Efuse_PgPacketRead(struct adapter
*pAdapter
, u8 offset
, u8
*data
)
486 u8 ReadState
= PG_STATE_HEADER
;
487 int bContinual
= true;
488 int bDataEmpty
= true;
489 u8 efuse_data
, word_cnts
= 0;
491 u8 hoffset
= 0, hworden
= 0;
497 EFUSE_GetEfuseDefinition(pAdapter
, EFUSE_WIFI
, TYPE_EFUSE_MAX_SECTION
, (void *)&max_section
);
501 if (offset
> max_section
)
504 memset((void *)data
, 0xff, sizeof(u8
)*PGPKT_DATA_SIZE
);
505 memset((void *)tmpdata
, 0xff, sizeof(u8
)*PGPKT_DATA_SIZE
);
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
;
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;
522 DBG_88E("Error, All words disabled\n");
527 hoffset
= (efuse_data
>>4) & 0x0F;
528 hworden
= efuse_data
& 0x0F;
530 word_cnts
= Efuse_CalculateWordCnts(hworden
);
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)
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
;
547 } else {/* read next header */
548 efuse_addr
= efuse_addr
+ (word_cnts
*2)+1;
549 ReadState
= PG_STATE_HEADER
;
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
;
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))
570 static bool hal_EfuseFixHeaderProcess(struct adapter
*pAdapter
, u8 efuseType
, struct pgpkt
*pFixPkt
, u16
*pAddr
)
572 u8 originaldata
[8], badworden
= 0;
573 u16 efuse_addr
= *pAddr
;
574 u32 PgWriteSuccess
= 0;
576 memset((void *)originaldata
, 0xff, 8);
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
);
582 if (badworden
!= 0xf) { /* write fail */
583 PgWriteSuccess
= Efuse_PgPacketWrite(pAdapter
, pFixPkt
->offset
, badworden
, originaldata
);
588 efuse_addr
= Efuse_GetCurrentSize(pAdapter
);
590 efuse_addr
= efuse_addr
+ (pFixPkt
->word_cnts
*2) + 1;
593 efuse_addr
= efuse_addr
+ (pFixPkt
->word_cnts
*2) + 1;
599 static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter
*pAdapter
, u8 efuseType
, u16
*pAddr
, struct pgpkt
*pTargetPkt
)
602 u16 efuse_addr
= *pAddr
, efuse_max_available_len
= 0;
603 u8 pg_header
= 0, tmp_header
= 0, pg_header_temp
= 0;
606 EFUSE_GetEfuseDefinition(pAdapter
, efuseType
, TYPE_AVAILABLE_EFUSE_BYTES_BANK
, (void *)&efuse_max_available_len
);
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
);
613 while (tmp_header
== 0xFF) {
614 if (repeatcnt
++ > EFUSE_REPEAT_THRESHOLD_
)
617 efuse_OneByteWrite(pAdapter
, efuse_addr
, pg_header
);
618 efuse_OneByteRead(pAdapter
, efuse_addr
, &tmp_header
);
621 /* to write ext_header */
622 if (tmp_header
== pg_header
) {
624 pg_header_temp
= pg_header
;
625 pg_header
= ((pTargetPkt
->offset
& 0x78) << 1) | pTargetPkt
->word_en
;
627 efuse_OneByteWrite(pAdapter
, efuse_addr
, pg_header
);
628 efuse_OneByteRead(pAdapter
, efuse_addr
, &tmp_header
);
630 while (tmp_header
== 0xFF) {
631 if (repeatcnt
++ > EFUSE_REPEAT_THRESHOLD_
)
634 efuse_OneByteWrite(pAdapter
, efuse_addr
, pg_header
);
635 efuse_OneByteRead(pAdapter
, efuse_addr
, &tmp_header
);
638 if ((tmp_header
& 0x0F) == 0x0F) { /* word_en PG fail */
639 if (repeatcnt
++ > EFUSE_REPEAT_THRESHOLD_
) {
645 } else if (pg_header
!= tmp_header
) { /* offset PG fail */
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
))
656 } else if ((tmp_header
& 0x1F) == 0x0F) { /* wrong extended header */
666 static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter
*pAdapter
, u8 efuseType
, u16
*pAddr
, struct pgpkt
*pTargetPkt
)
669 u8 pg_header
= 0, tmp_header
= 0;
670 u16 efuse_addr
= *pAddr
;
673 pg_header
= ((pTargetPkt
->offset
<< 4) & 0xf0) | pTargetPkt
->word_en
;
675 efuse_OneByteWrite(pAdapter
, efuse_addr
, pg_header
);
676 efuse_OneByteRead(pAdapter
, efuse_addr
, &tmp_header
);
678 while (tmp_header
== 0xFF) {
679 if (repeatcnt
++ > EFUSE_REPEAT_THRESHOLD_
)
681 efuse_OneByteWrite(pAdapter
, efuse_addr
, pg_header
);
682 efuse_OneByteRead(pAdapter
, efuse_addr
, &tmp_header
);
685 if (pg_header
== tmp_header
) {
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
))
700 static bool hal_EfusePgPacketWriteData(struct adapter
*pAdapter
, u8 efuseType
, u16
*pAddr
, struct pgpkt
*pTargetPkt
)
702 u16 efuse_addr
= *pAddr
;
704 u32 PgWriteSuccess
= 0;
707 badworden
= Efuse_WordEnableDataWrite(pAdapter
, efuse_addr
+1, pTargetPkt
->word_en
, pTargetPkt
->data
);
708 if (badworden
== 0x0F) {
712 /* reorganize other pg packet */
713 PgWriteSuccess
= Efuse_PgPacketWrite(pAdapter
, pTargetPkt
->offset
, badworden
, pTargetPkt
->data
);
722 hal_EfusePgPacketWriteHeader(
723 struct adapter
*pAdapter
,
726 struct pgpkt
*pTargetPkt
)
730 if (pTargetPkt
->offset
>= EFUSE_MAX_SECTION_BASE
)
731 bRet
= hal_EfusePgPacketWrite2ByteHeader(pAdapter
, efuseType
, pAddr
, pTargetPkt
);
733 bRet
= hal_EfusePgPacketWrite1ByteHeader(pAdapter
, efuseType
, pAddr
, pTargetPkt
);
738 static bool wordEnMatched(struct pgpkt
*pTargetPkt
, struct pgpkt
*pCurPkt
,
741 u8 match_word_en
= 0x0F; /* default all words are disabled */
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 */
757 *pWden
= match_word_en
;
759 if (match_word_en
!= 0xf)
765 static bool hal_EfuseCheckIfDatafollowed(struct adapter
*pAdapter
, u8 word_cnts
, u16 startAddr
)
770 for (i
= 0; i
< (word_cnts
*2); i
++) {
771 if (efuse_OneByteRead(pAdapter
, (startAddr
+i
), &efuse_data
) && (efuse_data
!= 0xFF))
777 static bool hal_EfusePartialWriteCheck(struct adapter
*pAdapter
, u8 efuseType
, u16
*pAddr
, struct pgpkt
*pTargetPkt
)
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;
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
);
788 rtw_hal_get_hwreg(pAdapter
, HW_VAR_EFUSE_BYTES
, (u8
*)&startAddr
);
789 startAddr
%= EFUSE_REAL_CONTENT_LEN
;
792 if (startAddr
>= efuse_max_available_len
) {
797 if (efuse_OneByteRead(pAdapter
, startAddr
, &efuse_data
) && (efuse_data
!= 0xFF)) {
798 if (EXT_HEADER(efuse_data
)) {
799 cur_header
= efuse_data
;
801 efuse_OneByteRead(pAdapter
, startAddr
, &efuse_data
);
802 if (ALL_WORDS_DISABLED(efuse_data
)) {
806 curPkt
.offset
= ((cur_header
& 0xE0) >> 5) | ((efuse_data
& 0xF0) >> 1);
807 curPkt
.word_en
= efuse_data
& 0x0F;
810 cur_header
= efuse_data
;
811 curPkt
.offset
= (cur_header
>>4) & 0x0F;
812 curPkt
.word_en
= cur_header
& 0x0F;
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 */
827 PgWriteSuccess
= Efuse_PgPacketWrite(pAdapter
, pTargetPkt
->offset
, badworden
, pTargetPkt
->data
);
829 if (!PgWriteSuccess
) {
830 bRet
= false; /* write fail, return */
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 */
839 pTargetPkt
->word_cnts
= Efuse_CalculateWordCnts(pTargetPkt
->word_en
);
841 /* read from next header */
842 startAddr
= startAddr
+ (curPkt
.word_cnts
*2) + 1;
844 /* not used header, 0xff */
854 hal_EfusePgCheckAvailableAddr(
855 struct adapter
*pAdapter
,
859 u16 efuse_max_available_len
= 0;
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
);
864 if (Efuse_GetCurrentSize(pAdapter
) >= efuse_max_available_len
)
869 static void hal_EfuseConstructPGPkt(u8 offset
, u8 word_en
, u8
*pData
, struct pgpkt
*pTargetPkt
)
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
);
878 bool Efuse_PgPacketWrite(struct adapter
*pAdapter
, u8 offset
, u8 word_en
, u8
*pData
)
880 struct pgpkt targetPkt
;
882 u8 efuseType
= EFUSE_WIFI
;
884 if (!hal_EfusePgCheckAvailableAddr(pAdapter
, efuseType
))
887 hal_EfuseConstructPGPkt(offset
, word_en
, pData
, &targetPkt
);
889 if (!hal_EfusePartialWriteCheck(pAdapter
, efuseType
, &startAddr
, &targetPkt
))
892 if (!hal_EfusePgPacketWriteHeader(pAdapter
, efuseType
, &startAddr
, &targetPkt
))
895 if (!hal_EfusePgPacketWriteData(pAdapter
, efuseType
, &startAddr
, &targetPkt
))
901 u8
Efuse_CalculateWordCnts(u8 word_en
)
904 if (!(word_en
& BIT(0)))
905 word_cnts
++; /* 0 : write enable */
906 if (!(word_en
& BIT(1)))
908 if (!(word_en
& BIT(2)))
910 if (!(word_en
& BIT(3)))
915 u8
efuse_OneByteRead(struct adapter
*pAdapter
, u16 addr
, u8
*data
)
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));
924 usb_write8(pAdapter
, EFUSE_CTRL
+3, 0x72);/* read cmd */
926 while (!(0x80 & usb_read8(pAdapter
, EFUSE_CTRL
+3)) && (tmpidx
< 100))
929 *data
= usb_read8(pAdapter
, EFUSE_CTRL
);
938 u8
efuse_OneByteWrite(struct adapter
*pAdapter
, u16 addr
, u8 data
)
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 */
949 usb_write8(pAdapter
, EFUSE_CTRL
+3, 0xF2);/* write cmd */
951 while ((0x80 & usb_read8(pAdapter
, EFUSE_CTRL
+3)) && (tmpidx
< 100))
963 * Overview: Read allowed word in current efuse section data.
965 void efuse_WordEnableDataRead(u8 word_en
, u8
*sourdata
, u8
*targetdata
)
967 if (!(word_en
&BIT(0))) {
968 targetdata
[0] = sourdata
[0];
969 targetdata
[1] = sourdata
[1];
971 if (!(word_en
&BIT(1))) {
972 targetdata
[2] = sourdata
[2];
973 targetdata
[3] = sourdata
[3];
975 if (!(word_en
&BIT(2))) {
976 targetdata
[4] = sourdata
[4];
977 targetdata
[5] = sourdata
[5];
979 if (!(word_en
&BIT(3))) {
980 targetdata
[6] = sourdata
[6];
981 targetdata
[7] = sourdata
[7];
985 static u8
efuse_read8(struct adapter
*padapter
, u16 address
, u8
*value
)
987 return efuse_OneByteRead(padapter
, address
, value
);
990 static u8
efuse_write8(struct adapter
*padapter
, u16 address
, u8
*value
)
992 return efuse_OneByteWrite(padapter
, address
, *value
);
996 * read/wirte raw efuse data
998 u8
rtw_efuse_access(struct adapter
*padapter
, u8 write
, u16 start_addr
, u16 cnts
, u8
*data
)
1001 u16 real_content_len
= 0, max_available_size
= 0;
1003 u8 (*rw8
)(struct adapter
*, u16
, u8
*);
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
);
1008 if (start_addr
> real_content_len
)
1012 if ((start_addr
+ cnts
) > max_available_size
)
1014 rw8
= &efuse_write8
;
1019 Efuse_PowerSwitch(padapter
, write
, true);
1021 /* e-fuse one byte read / write */
1022 for (i
= 0; i
< cnts
; i
++) {
1023 if (start_addr
>= real_content_len
) {
1028 res
= rw8(padapter
, start_addr
++, data
++);
1033 Efuse_PowerSwitch(padapter
, write
, false);
1038 u16
efuse_GetMaxSize(struct adapter
*padapter
)
1041 EFUSE_GetEfuseDefinition(padapter
, EFUSE_WIFI
, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL
, (void *)&max_size
);
1045 u8
efuse_GetCurrentSize(struct adapter
*padapter
, u16
*size
)
1047 Efuse_PowerSwitch(padapter
, false, true);
1048 *size
= Efuse_GetCurrentSize(padapter
);
1049 Efuse_PowerSwitch(padapter
, false, false);
1054 u8
rtw_efuse_map_read(struct adapter
*padapter
, u16 addr
, u16 cnts
, u8
*data
)
1058 EFUSE_GetEfuseDefinition(padapter
, EFUSE_WIFI
, TYPE_EFUSE_MAP_LEN
, (void *)&mapLen
);
1060 if ((addr
+ cnts
) > mapLen
)
1063 Efuse_PowerSwitch(padapter
, false, true);
1065 efuse_ReadEFuse(padapter
, EFUSE_WIFI
, addr
, cnts
, data
);
1067 Efuse_PowerSwitch(padapter
, false, false);
1072 u8
rtw_efuse_map_write(struct adapter
*padapter
, u16 addr
, u16 cnts
, u8
*data
)
1076 u8 newdata
[PGPKT_DATA_SIZE
+ 1];
1081 EFUSE_GetEfuseDefinition(padapter
, EFUSE_WIFI
, TYPE_EFUSE_MAP_LEN
, (void *)&mapLen
);
1083 if ((addr
+ cnts
) > mapLen
)
1086 map
= kzalloc(mapLen
, GFP_KERNEL
);
1090 ret
= rtw_efuse_map_read(padapter
, 0, mapLen
, map
);
1094 Efuse_PowerSwitch(padapter
, true, true);
1096 offset
= (addr
>> 3);
1098 memset(newdata
, 0xFF, PGPKT_DATA_SIZE
+ 1);
1099 i
= addr
& 0x7; /* index of one package */
1100 idx
= 0; /* data index */
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
];
1113 for (; i
< PGPKT_DATA_SIZE
; i
+= 2) {
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];
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];
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
);
1142 for (i
= 0; i
< PGPKT_DATA_SIZE
; i
++)
1143 DBG_88E("data=%x \t", newdata
[i
]);
1154 memset(newdata
, 0xFF, PGPKT_DATA_SIZE
);
1157 Efuse_PowerSwitch(padapter
, true, false);
1164 * Function: efuse_ShadowRead1Byte
1165 * efuse_ShadowRead2Byte
1166 * efuse_ShadowRead4Byte
1168 * Overview: Read from efuse init map by one/two/four bytes !!!!!
1171 efuse_ShadowRead1Byte(
1172 struct adapter
*pAdapter
,
1176 struct eeprom_priv
*pEEPROM
= GET_EEPROM_EFUSE_PRIV(pAdapter
);
1178 *Value
= pEEPROM
->efuse_eeprom_data
[Offset
];
1183 efuse_ShadowRead2Byte(
1184 struct adapter
*pAdapter
,
1188 struct eeprom_priv
*pEEPROM
= GET_EEPROM_EFUSE_PRIV(pAdapter
);
1190 *Value
= pEEPROM
->efuse_eeprom_data
[Offset
];
1191 *Value
|= pEEPROM
->efuse_eeprom_data
[Offset
+1]<<8;
1196 efuse_ShadowRead4Byte(
1197 struct adapter
*pAdapter
,
1201 struct eeprom_priv
*pEEPROM
= GET_EEPROM_EFUSE_PRIV(pAdapter
);
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;
1211 * Overview: Read All Efuse content
1213 static void Efuse_ReadAllMap(struct adapter
*pAdapter
, u8 efuseType
, u8
*Efuse
)
1217 Efuse_PowerSwitch(pAdapter
, false, true);
1219 EFUSE_GetEfuseDefinition(pAdapter
, efuseType
, TYPE_EFUSE_MAP_LEN
, (void *)&mapLen
);
1221 efuse_ReadEFuse(pAdapter
, efuseType
, 0, mapLen
, Efuse
);
1223 Efuse_PowerSwitch(pAdapter
, false, false);
1227 * Overview: Transfer current EFUSE content to shadow init and modify map.
1229 void EFUSE_ShadowMapUpdate(
1230 struct adapter
*pAdapter
,
1233 struct eeprom_priv
*pEEPROM
= GET_EEPROM_EFUSE_PRIV(pAdapter
);
1236 EFUSE_GetEfuseDefinition(pAdapter
, efuseType
, TYPE_EFUSE_MAP_LEN
, (void *)&mapLen
);
1238 if (pEEPROM
->bautoload_fail_flag
)
1239 memset(pEEPROM
->efuse_eeprom_data
, 0xFF, mapLen
);
1241 Efuse_ReadAllMap(pAdapter
, efuseType
, pEEPROM
->efuse_eeprom_data
);
1245 * Overview: Read from efuse init map !!!!!
1247 void EFUSE_ShadowRead(struct adapter
*pAdapter
, u8 Type
, u16 Offset
, u32
*Value
)
1250 efuse_ShadowRead1Byte(pAdapter
, Offset
, (u8
*)Value
);
1252 efuse_ShadowRead2Byte(pAdapter
, Offset
, (u16
*)Value
);
1254 efuse_ShadowRead4Byte(pAdapter
, Offset
, (u32
*)Value
);