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>
27 /*------------------------Define local variable------------------------------*/
29 u32 fakeEfuseUsedBytes
;
30 u8 fakeEfuseContent
[EFUSE_MAX_HW_SIZE
] = {0};
31 u8 fakeEfuseInitMap
[EFUSE_MAX_MAP_LEN
] = {0};
32 u8 fakeEfuseModifiedMap
[EFUSE_MAX_MAP_LEN
] = {0};
35 u8 BTEfuseContent
[EFUSE_MAX_BT_BANK
][EFUSE_MAX_HW_SIZE
];
36 u8 BTEfuseInitMap
[EFUSE_BT_MAX_MAP_LEN
] = {0};
37 u8 BTEfuseModifiedMap
[EFUSE_BT_MAX_MAP_LEN
] = {0};
39 u32 fakeBTEfuseUsedBytes
;
40 u8 fakeBTEfuseContent
[EFUSE_MAX_BT_BANK
][EFUSE_MAX_HW_SIZE
];
41 u8 fakeBTEfuseInitMap
[EFUSE_BT_MAX_MAP_LEN
] = {0};
42 u8 fakeBTEfuseModifiedMap
[EFUSE_BT_MAX_MAP_LEN
] = {0};
43 /*------------------------Define local variable------------------------------*/
46 #define REG_EFUSE_CTRL 0x0030
47 #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
50 /* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
52 Efuse_CalculateWordCnts(u8 word_en
)
55 if (!(word_en
& BIT(0)))
56 word_cnts
++; /* 0 : write enable */
57 if (!(word_en
& BIT(1)))
59 if (!(word_en
& BIT(2)))
61 if (!(word_en
& BIT(3)))
68 * Execute E-Fuse read byte operation.
69 * Referred from SD1 Richard.
71 * 1. Boot from E-Fuse and successfully auto-load.
72 * 2. PASSIVE_LEVEL (USB interface)
73 * Created by Roger, 2008.10.21.
77 struct adapter
*Adapter
,
87 usb_write8(Adapter
, EFUSE_CTRL
+1, (_offset
& 0xff));
88 readbyte
= usb_read8(Adapter
, EFUSE_CTRL
+2);
89 usb_write8(Adapter
, EFUSE_CTRL
+2, ((_offset
>> 8) & 0x03) | (readbyte
& 0xfc));
92 readbyte
= usb_read8(Adapter
, EFUSE_CTRL
+3);
93 usb_write8(Adapter
, EFUSE_CTRL
+3, (readbyte
& 0x7f));
95 /* Check bit 32 read-ready */
97 value32
= usb_read32(Adapter
, EFUSE_CTRL
);
98 while (!(((value32
>> 24) & 0xff) & 0x80) && (retry
< 10000)) {
99 value32
= usb_read32(Adapter
, EFUSE_CTRL
);
103 /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
104 /* This fix the problem that Efuse read error in high temperature condition. */
105 /* Designer says that there shall be some delay after ready bit is set, or the */
106 /* result will always stay on last data we read. */
108 value32
= usb_read32(Adapter
, EFUSE_CTRL
);
110 *pbuf
= (u8
)(value32
& 0xff);
113 /*-----------------------------------------------------------------------------
114 * Function: EFUSE_Read1Byte
116 * Overview: Copy from WMAC fot EFUSE read 1 byte.
126 * 09/23/2008 MHC Copy from WMAC.
128 *---------------------------------------------------------------------------*/
129 u8
EFUSE_Read1Byte(struct adapter
*Adapter
, u16 Address
)
132 u8 Bytetemp
= {0x00};
137 EFUSE_GetEfuseDefinition(Adapter
, EFUSE_WIFI
, TYPE_EFUSE_REAL_CONTENT_LEN
, (void *)&contentLen
);
139 if (Address
< contentLen
) { /* E-fuse 512Byte */
140 /* Write E-fuse Register address bit0~7 */
141 temp
= Address
& 0xFF;
142 usb_write8(Adapter
, EFUSE_CTRL
+1, temp
);
143 Bytetemp
= usb_read8(Adapter
, EFUSE_CTRL
+2);
144 /* Write E-fuse Register address bit8~9 */
145 temp
= ((Address
>> 8) & 0x03) | (Bytetemp
& 0xFC);
146 usb_write8(Adapter
, EFUSE_CTRL
+2, temp
);
148 /* Write 0x30[31]= 0 */
149 Bytetemp
= usb_read8(Adapter
, EFUSE_CTRL
+3);
150 temp
= Bytetemp
& 0x7F;
151 usb_write8(Adapter
, EFUSE_CTRL
+3, temp
);
153 /* Wait Write-ready (0x30[31]= 1) */
154 Bytetemp
= usb_read8(Adapter
, EFUSE_CTRL
+3);
155 while (!(Bytetemp
& 0x80)) {
156 Bytetemp
= usb_read8(Adapter
, EFUSE_CTRL
+3);
163 data
= usb_read8(Adapter
, EFUSE_CTRL
);
169 } /* EFUSE_Read1Byte */
171 /* 11/16/2008 MH Read one byte from real Efuse. */
172 u8
efuse_OneByteRead(struct adapter
*pAdapter
, u16 addr
, u8
*data
, bool pseudo
)
177 /* -----------------e-fuse reg ctrl --------------------------------- */
179 usb_write8(pAdapter
, EFUSE_CTRL
+1, (u8
)(addr
& 0xff));
180 usb_write8(pAdapter
, EFUSE_CTRL
+2, ((u8
)((addr
>>8) & 0x03)) |
181 (usb_read8(pAdapter
, EFUSE_CTRL
+2) & 0xFC));
183 usb_write8(pAdapter
, EFUSE_CTRL
+3, 0x72);/* read cmd */
185 while (!(0x80 & usb_read8(pAdapter
, EFUSE_CTRL
+3)) && (tmpidx
< 100))
188 *data
= usb_read8(pAdapter
, EFUSE_CTRL
);
197 /* 11/16/2008 MH Write one byte to reald Efuse. */
198 u8
efuse_OneByteWrite(struct adapter
*pAdapter
, u16 addr
, u8 data
, bool pseudo
)
203 /* -----------------e-fuse reg ctrl --------------------------------- */
205 usb_write8(pAdapter
, EFUSE_CTRL
+1, (u8
)(addr
&0xff));
206 usb_write8(pAdapter
, EFUSE_CTRL
+2,
207 (usb_read8(pAdapter
, EFUSE_CTRL
+2) & 0xFC) |
208 (u8
)((addr
>>8) & 0x03));
209 usb_write8(pAdapter
, EFUSE_CTRL
, data
);/* data */
211 usb_write8(pAdapter
, EFUSE_CTRL
+3, 0xF2);/* write cmd */
213 while ((0x80 & usb_read8(pAdapter
, EFUSE_CTRL
+3)) && (tmpidx
< 100))
224 /*-----------------------------------------------------------------------------
225 * Function: efuse_WordEnableDataRead
227 * Overview: Read allowed word in current efuse section data.
237 * 11/16/2008 MHC Create Version 0.
238 * 11/21/2008 MHC Fix Write bug when we only enable late word.
240 *---------------------------------------------------------------------------*/
241 void efuse_WordEnableDataRead(u8 word_en
, u8
*sourdata
, u8
*targetdata
)
243 if (!(word_en
&BIT(0))) {
244 targetdata
[0] = sourdata
[0];
245 targetdata
[1] = sourdata
[1];
247 if (!(word_en
&BIT(1))) {
248 targetdata
[2] = sourdata
[2];
249 targetdata
[3] = sourdata
[3];
251 if (!(word_en
&BIT(2))) {
252 targetdata
[4] = sourdata
[4];
253 targetdata
[5] = sourdata
[5];
255 if (!(word_en
&BIT(3))) {
256 targetdata
[6] = sourdata
[6];
257 targetdata
[7] = sourdata
[7];
261 static u8
efuse_read8(struct adapter
*padapter
, u16 address
, u8
*value
)
263 return efuse_OneByteRead(padapter
, address
, value
, false);
266 static u8
efuse_write8(struct adapter
*padapter
, u16 address
, u8
*value
)
268 return efuse_OneByteWrite(padapter
, address
, *value
, false);
272 * read/wirte raw efuse data
274 u8
rtw_efuse_access(struct adapter
*padapter
, u8 write
, u16 start_addr
, u16 cnts
, u8
*data
)
277 u16 real_content_len
= 0, max_available_size
= 0;
279 u8 (*rw8
)(struct adapter
*, u16
, u8
*);
281 EFUSE_GetEfuseDefinition(padapter
, EFUSE_WIFI
, TYPE_EFUSE_REAL_CONTENT_LEN
, (void *)&real_content_len
);
282 EFUSE_GetEfuseDefinition(padapter
, EFUSE_WIFI
, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL
, (void *)&max_available_size
);
284 if (start_addr
> real_content_len
)
288 if ((start_addr
+ cnts
) > max_available_size
)
295 Efuse_PowerSwitch(padapter
, write
, true);
297 /* e-fuse one byte read / write */
298 for (i
= 0; i
< cnts
; i
++) {
299 if (start_addr
>= real_content_len
) {
304 res
= rw8(padapter
, start_addr
++, data
++);
309 Efuse_PowerSwitch(padapter
, write
, false);
314 u16
efuse_GetMaxSize(struct adapter
*padapter
)
317 EFUSE_GetEfuseDefinition(padapter
, EFUSE_WIFI
, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL
, (void *)&max_size
);
321 u8
efuse_GetCurrentSize(struct adapter
*padapter
, u16
*size
)
323 Efuse_PowerSwitch(padapter
, false, true);
324 *size
= Efuse_GetCurrentSize(padapter
, false);
325 Efuse_PowerSwitch(padapter
, false, false);
330 u8
rtw_efuse_map_read(struct adapter
*padapter
, u16 addr
, u16 cnts
, u8
*data
)
334 EFUSE_GetEfuseDefinition(padapter
, EFUSE_WIFI
, TYPE_EFUSE_MAP_LEN
, (void *)&mapLen
);
336 if ((addr
+ cnts
) > mapLen
)
339 Efuse_PowerSwitch(padapter
, false, true);
341 efuse_ReadEFuse(padapter
, EFUSE_WIFI
, addr
, cnts
, data
, false);
343 Efuse_PowerSwitch(padapter
, false, false);
349 u8
rtw_efuse_map_write(struct adapter
*padapter
, u16 addr
, u16 cnts
, u8
*data
)
353 u8 newdata
[PGPKT_DATA_SIZE
+ 1];
358 EFUSE_GetEfuseDefinition(padapter
, EFUSE_WIFI
, TYPE_EFUSE_MAP_LEN
, (void *)&mapLen
);
360 if ((addr
+ cnts
) > mapLen
)
363 map
= rtw_zmalloc(mapLen
);
367 ret
= rtw_efuse_map_read(padapter
, 0, mapLen
, map
);
371 Efuse_PowerSwitch(padapter
, true, true);
373 offset
= (addr
>> 3);
375 _rtw_memset(newdata
, 0xFF, PGPKT_DATA_SIZE
+ 1);
376 i
= addr
& 0x7; /* index of one package */
377 idx
= 0; /* data index */
381 if (data
[idx
] != map
[addr
+idx
]) {
382 word_en
&= ~BIT(i
>> 1);
383 newdata
[i
-1] = map
[addr
+idx
-1];
384 newdata
[i
] = data
[idx
];
390 for (; i
< PGPKT_DATA_SIZE
; i
+= 2) {
393 if ((cnts
- idx
) == 1) {
394 if (data
[idx
] != map
[addr
+idx
]) {
395 word_en
&= ~BIT(i
>> 1);
396 newdata
[i
] = data
[idx
];
397 newdata
[i
+1] = map
[addr
+idx
+1];
402 if ((data
[idx
] != map
[addr
+idx
]) ||
403 (data
[idx
+1] != map
[addr
+idx
+1])) {
404 word_en
&= ~BIT(i
>> 1);
405 newdata
[i
] = data
[idx
];
406 newdata
[i
+1] = data
[idx
+ 1];
414 if (word_en
!= 0xF) {
415 ret
= Efuse_PgPacketWrite(padapter
, offset
, word_en
, newdata
, false);
416 DBG_88E("offset=%x\n", offset
);
417 DBG_88E("word_en=%x\n", word_en
);
419 for (i
= 0; i
< PGPKT_DATA_SIZE
; i
++)
420 DBG_88E("data=%x \t", newdata
[i
]);
431 _rtw_memset(newdata
, 0xFF, PGPKT_DATA_SIZE
);
434 Efuse_PowerSwitch(padapter
, true, false);
440 /*-----------------------------------------------------------------------------
441 * Function: efuse_ShadowRead1Byte
442 * efuse_ShadowRead2Byte
443 * efuse_ShadowRead4Byte
445 * Overview: Read from efuse init map by one/two/four bytes !!!!!
455 * 11/12/2008 MHC Create Version 0.
457 *---------------------------------------------------------------------------*/
459 efuse_ShadowRead1Byte(
460 struct adapter
*pAdapter
,
464 struct eeprom_priv
*pEEPROM
= GET_EEPROM_EFUSE_PRIV(pAdapter
);
466 *Value
= pEEPROM
->efuse_eeprom_data
[Offset
];
468 } /* EFUSE_ShadowRead1Byte */
472 efuse_ShadowRead2Byte(
473 struct adapter
*pAdapter
,
477 struct eeprom_priv
*pEEPROM
= GET_EEPROM_EFUSE_PRIV(pAdapter
);
479 *Value
= pEEPROM
->efuse_eeprom_data
[Offset
];
480 *Value
|= pEEPROM
->efuse_eeprom_data
[Offset
+1]<<8;
482 } /* EFUSE_ShadowRead2Byte */
484 /* Read Four Bytes */
486 efuse_ShadowRead4Byte(
487 struct adapter
*pAdapter
,
491 struct eeprom_priv
*pEEPROM
= GET_EEPROM_EFUSE_PRIV(pAdapter
);
493 *Value
= pEEPROM
->efuse_eeprom_data
[Offset
];
494 *Value
|= pEEPROM
->efuse_eeprom_data
[Offset
+1]<<8;
495 *Value
|= pEEPROM
->efuse_eeprom_data
[Offset
+2]<<16;
496 *Value
|= pEEPROM
->efuse_eeprom_data
[Offset
+3]<<24;
498 } /* efuse_ShadowRead4Byte */
500 /*-----------------------------------------------------------------------------
501 * Function: Efuse_ReadAllMap
503 * Overview: Read All Efuse content
513 * 11/11/2008 MHC Create Version 0.
515 *---------------------------------------------------------------------------*/
516 static void Efuse_ReadAllMap(struct adapter
*pAdapter
, u8 efuseType
, u8
*Efuse
, bool pseudo
)
520 Efuse_PowerSwitch(pAdapter
, false, true);
522 EFUSE_GetEfuseDefinition(pAdapter
, efuseType
, TYPE_EFUSE_MAP_LEN
, (void *)&mapLen
);
524 efuse_ReadEFuse(pAdapter
, efuseType
, 0, mapLen
, Efuse
, pseudo
);
526 Efuse_PowerSwitch(pAdapter
, false, false);
529 /*-----------------------------------------------------------------------------
530 * Function: EFUSE_ShadowMapUpdate
532 * Overview: Transfer current EFUSE content to shadow init and modify map.
542 * 11/13/2008 MHC Create Version 0.
544 *---------------------------------------------------------------------------*/
545 void EFUSE_ShadowMapUpdate(
546 struct adapter
*pAdapter
,
550 struct eeprom_priv
*pEEPROM
= GET_EEPROM_EFUSE_PRIV(pAdapter
);
553 EFUSE_GetEfuseDefinition(pAdapter
, efuseType
, TYPE_EFUSE_MAP_LEN
, (void *)&mapLen
);
555 if (pEEPROM
->bautoload_fail_flag
)
556 _rtw_memset(pEEPROM
->efuse_eeprom_data
, 0xFF, mapLen
);
558 Efuse_ReadAllMap(pAdapter
, efuseType
, pEEPROM
->efuse_eeprom_data
, pseudo
);
559 } /* EFUSE_ShadowMapUpdate */
561 /*-----------------------------------------------------------------------------
562 * Function: EFUSE_ShadowRead
564 * Overview: Read from efuse init map !!!!!
574 * 11/12/2008 MHC Create Version 0.
576 *---------------------------------------------------------------------------*/
577 void EFUSE_ShadowRead(struct adapter
*pAdapter
, u8 Type
, u16 Offset
, u32
*Value
)
580 efuse_ShadowRead1Byte(pAdapter
, Offset
, (u8
*)Value
);
582 efuse_ShadowRead2Byte(pAdapter
, Offset
, (u16
*)Value
);
584 efuse_ShadowRead4Byte(pAdapter
, Offset
, (u32
*)Value
);
586 } /* EFUSE_ShadowRead */