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 static bool Efuse_Read1ByteFromFakeContent(
51 struct adapter *pAdapter,
55 if (Offset >= EFUSE_MAX_HW_SIZE)
57 if (fakeEfuseBank == 0)
58 *Value = fakeEfuseContent[Offset];
60 *Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
65 Efuse_Write1ByteToFakeContent(
66 struct adapter *pAdapter,
70 if (Offset >= EFUSE_MAX_HW_SIZE)
72 if (fakeEfuseBank == 0)
73 fakeEfuseContent[Offset] = Value;
75 fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
79 /* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
81 Efuse_CalculateWordCnts(u8 word_en)
84 if (!(word_en & BIT(0)))
85 word_cnts++; /* 0 : write enable */
86 if (!(word_en & BIT(1)))
88 if (!(word_en & BIT(2)))
90 if (!(word_en & BIT(3)))
97 * Execute E-Fuse read byte operation.
98 * Referred from SD1 Richard.
100 * 1. Boot from E-Fuse and successfully auto-load.
101 * 2. PASSIVE_LEVEL (USB interface)
102 * Created by Roger, 2008.10.21.
106 struct adapter *Adapter,
116 Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
121 usb_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
122 readbyte = usb_read8(Adapter, EFUSE_CTRL+2);
123 usb_write8(Adapter, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
126 readbyte = usb_read8(Adapter, EFUSE_CTRL+3);
127 usb_write8(Adapter, EFUSE_CTRL+3, (readbyte & 0x7f));
129 /* Check bit 32 read-ready */
131 value32 = usb_read32(Adapter, EFUSE_CTRL);
132 while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) {
133 value32 = usb_read32(Adapter, EFUSE_CTRL);
137 /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
138 /* This fix the problem that Efuse read error in high temperature condition. */
139 /* Designer says that there shall be some delay after ready bit is set, or the */
140 /* result will always stay on last data we read. */
142 value32 = usb_read32(Adapter, EFUSE_CTRL);
144 *pbuf = (u8)(value32 & 0xff);
147 /*-----------------------------------------------------------------------------
148 * Function: EFUSE_Read1Byte
150 * Overview: Copy from WMAC fot EFUSE read 1 byte.
160 * 09/23/2008 MHC Copy from WMAC.
162 *---------------------------------------------------------------------------*/
163 u8 EFUSE_Read1Byte(struct adapter *Adapter, u16 Address)
166 u8 Bytetemp = {0x00};
171 EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen);
173 if (Address < contentLen) { /* E-fuse 512Byte */
174 /* Write E-fuse Register address bit0~7 */
175 temp = Address & 0xFF;
176 usb_write8(Adapter, EFUSE_CTRL+1, temp);
177 Bytetemp = usb_read8(Adapter, EFUSE_CTRL+2);
178 /* Write E-fuse Register address bit8~9 */
179 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
180 usb_write8(Adapter, EFUSE_CTRL+2, temp);
182 /* Write 0x30[31]= 0 */
183 Bytetemp = usb_read8(Adapter, EFUSE_CTRL+3);
184 temp = Bytetemp & 0x7F;
185 usb_write8(Adapter, EFUSE_CTRL+3, temp);
187 /* Wait Write-ready (0x30[31]= 1) */
188 Bytetemp = usb_read8(Adapter, EFUSE_CTRL+3);
189 while (!(Bytetemp & 0x80)) {
190 Bytetemp = usb_read8(Adapter, EFUSE_CTRL+3);
197 data = usb_read8(Adapter, EFUSE_CTRL);
203 } /* EFUSE_Read1Byte */
205 /* 11/16/2008 MH Read one byte from real Efuse. */
206 u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
212 result = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
215 /* -----------------e-fuse reg ctrl --------------------------------- */
217 usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
218 usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
219 (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
221 usb_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */
223 while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
226 *data = usb_read8(pAdapter, EFUSE_CTRL);
235 /* 11/16/2008 MH Write one byte to reald Efuse. */
236 u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
242 result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
246 /* -----------------e-fuse reg ctrl --------------------------------- */
248 usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
249 usb_write8(pAdapter, EFUSE_CTRL+2,
250 (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
251 (u8)((addr>>8) & 0x03));
252 usb_write8(pAdapter, EFUSE_CTRL, data);/* data */
254 usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
256 while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
267 int Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
271 ret = pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, pseudo);
277 static int Efuse_PgPacketWrite_BT(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
281 ret = pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, pseudo);
286 /*-----------------------------------------------------------------------------
287 * Function: efuse_WordEnableDataRead
289 * Overview: Read allowed word in current efuse section data.
299 * 11/16/2008 MHC Create Version 0.
300 * 11/21/2008 MHC Fix Write bug when we only enable late word.
302 *---------------------------------------------------------------------------*/
303 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
305 if (!(word_en&BIT(0))) {
306 targetdata[0] = sourdata[0];
307 targetdata[1] = sourdata[1];
309 if (!(word_en&BIT(1))) {
310 targetdata[2] = sourdata[2];
311 targetdata[3] = sourdata[3];
313 if (!(word_en&BIT(2))) {
314 targetdata[4] = sourdata[4];
315 targetdata[5] = sourdata[5];
317 if (!(word_en&BIT(3))) {
318 targetdata[6] = sourdata[6];
319 targetdata[7] = sourdata[7];
323 static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
325 return efuse_OneByteRead(padapter, address, value, false);
328 static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
330 return efuse_OneByteWrite(padapter, address, *value, false);
334 * read/wirte raw efuse data
336 u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts, u8 *data)
339 u16 real_content_len = 0, max_available_size = 0;
341 u8 (*rw8)(struct adapter *, u16, u8*);
343 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len);
344 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
346 if (start_addr > real_content_len)
350 if ((start_addr + cnts) > max_available_size)
357 Efuse_PowerSwitch(padapter, write, true);
359 /* e-fuse one byte read / write */
360 for (i = 0; i < cnts; i++) {
361 if (start_addr >= real_content_len) {
366 res = rw8(padapter, start_addr++, data++);
371 Efuse_PowerSwitch(padapter, write, false);
376 u16 efuse_GetMaxSize(struct adapter *padapter)
379 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size);
383 u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
385 Efuse_PowerSwitch(padapter, false, true);
386 *size = Efuse_GetCurrentSize(padapter, false);
387 Efuse_PowerSwitch(padapter, false, false);
392 u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
396 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
398 if ((addr + cnts) > mapLen)
401 Efuse_PowerSwitch(padapter, false, true);
403 efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
405 Efuse_PowerSwitch(padapter, false, false);
410 u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
414 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
416 if ((addr + cnts) > mapLen)
419 Efuse_PowerSwitch(padapter, false, true);
421 efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
423 Efuse_PowerSwitch(padapter, false, false);
428 u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
432 u8 newdata[PGPKT_DATA_SIZE + 1];
437 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
439 if ((addr + cnts) > mapLen)
442 map = rtw_zmalloc(mapLen);
446 ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
450 Efuse_PowerSwitch(padapter, true, true);
452 offset = (addr >> 3);
454 _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
455 i = addr & 0x7; /* index of one package */
456 idx = 0; /* data index */
460 if (data[idx] != map[addr+idx]) {
461 word_en &= ~BIT(i >> 1);
462 newdata[i-1] = map[addr+idx-1];
463 newdata[i] = data[idx];
469 for (; i < PGPKT_DATA_SIZE; i += 2) {
472 if ((cnts - idx) == 1) {
473 if (data[idx] != map[addr+idx]) {
474 word_en &= ~BIT(i >> 1);
475 newdata[i] = data[idx];
476 newdata[i+1] = map[addr+idx+1];
481 if ((data[idx] != map[addr+idx]) ||
482 (data[idx+1] != map[addr+idx+1])) {
483 word_en &= ~BIT(i >> 1);
484 newdata[i] = data[idx];
485 newdata[i+1] = data[idx + 1];
493 if (word_en != 0xF) {
494 ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
495 DBG_88E("offset=%x\n", offset);
496 DBG_88E("word_en=%x\n", word_en);
498 for (i = 0; i < PGPKT_DATA_SIZE; i++)
499 DBG_88E("data=%x \t", newdata[i]);
510 _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
513 Efuse_PowerSwitch(padapter, true, false);
520 u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
524 u8 newdata[PGPKT_DATA_SIZE + 1];
529 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
531 if ((addr + cnts) > mapLen)
534 map = rtw_zmalloc(mapLen);
538 ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
542 Efuse_PowerSwitch(padapter, true, true);
544 offset = (addr >> 3);
546 _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
547 i = addr & 0x7; /* index of one package */
548 idx = 0; /* data index */
552 if (data[idx] != map[addr+idx]) {
553 word_en &= ~BIT(i >> 1);
554 newdata[i-1] = map[addr+idx-1];
555 newdata[i] = data[idx];
561 for (; i < PGPKT_DATA_SIZE; i += 2) {
564 if ((cnts - idx) == 1) {
565 if (data[idx] != map[addr+idx]) {
566 word_en &= ~BIT(i >> 1);
567 newdata[i] = data[idx];
568 newdata[i+1] = map[addr+idx+1];
573 if ((data[idx] != map[addr+idx]) ||
574 (data[idx+1] != map[addr+idx+1])) {
575 word_en &= ~BIT(i >> 1);
576 newdata[i] = data[idx];
577 newdata[i+1] = data[idx + 1];
585 if (word_en != 0xF) {
586 DBG_88E("%s: offset=%#X\n", __func__, offset);
587 DBG_88E("%s: word_en=%#X\n", __func__, word_en);
588 DBG_88E("%s: data=", __func__);
589 for (i = 0; i < PGPKT_DATA_SIZE; i++)
590 DBG_88E("0x%02X ", newdata[i]);
593 ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, false);
604 _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
607 Efuse_PowerSwitch(padapter, true, false);
616 /*-----------------------------------------------------------------------------
617 * Function: efuse_ShadowRead1Byte
618 * efuse_ShadowRead2Byte
619 * efuse_ShadowRead4Byte
621 * Overview: Read from efuse init map by one/two/four bytes !!!!!
631 * 11/12/2008 MHC Create Version 0.
633 *---------------------------------------------------------------------------*/
635 efuse_ShadowRead1Byte(
636 struct adapter *pAdapter,
640 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
642 *Value = pEEPROM->efuse_eeprom_data[Offset];
644 } /* EFUSE_ShadowRead1Byte */
648 efuse_ShadowRead2Byte(
649 struct adapter *pAdapter,
653 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
655 *Value = pEEPROM->efuse_eeprom_data[Offset];
656 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
658 } /* EFUSE_ShadowRead2Byte */
660 /* Read Four Bytes */
662 efuse_ShadowRead4Byte(
663 struct adapter *pAdapter,
667 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
669 *Value = pEEPROM->efuse_eeprom_data[Offset];
670 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
671 *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
672 *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
674 } /* efuse_ShadowRead4Byte */
676 /*-----------------------------------------------------------------------------
677 * Function: Efuse_ReadAllMap
679 * Overview: Read All Efuse content
689 * 11/11/2008 MHC Create Version 0.
691 *---------------------------------------------------------------------------*/
692 static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
696 Efuse_PowerSwitch(pAdapter, false, true);
698 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
700 efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
702 Efuse_PowerSwitch(pAdapter, false, false);
705 /*-----------------------------------------------------------------------------
706 * Function: EFUSE_ShadowMapUpdate
708 * Overview: Transfer current EFUSE content to shadow init and modify map.
718 * 11/13/2008 MHC Create Version 0.
720 *---------------------------------------------------------------------------*/
721 void EFUSE_ShadowMapUpdate(
722 struct adapter *pAdapter,
726 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
729 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
731 if (pEEPROM->bautoload_fail_flag)
732 _rtw_memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
734 Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
735 } /* EFUSE_ShadowMapUpdate */
737 /*-----------------------------------------------------------------------------
738 * Function: EFUSE_ShadowRead
740 * Overview: Read from efuse init map !!!!!
750 * 11/12/2008 MHC Create Version 0.
752 *---------------------------------------------------------------------------*/
753 void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
756 efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
758 efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
760 efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
762 } /* EFUSE_ShadowRead */