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);
148 * 1. Execute E-Fuse read byte operation according as map offset and
149 * save to E-Fuse table.
150 * 2. Referred from SD1 Richard.
152 * 1. Boot from E-Fuse and successfully auto-load.
153 * 2. PASSIVE_LEVEL (USB interface)
154 * Created by Roger, 2008.10.21.
156 * 1. Reorganize code flow and reserve bytes. and add description.
157 * 2. Add efuse utilization collect.
159 * Read Efuse must check if we write section 1 data again!!!
160 * Sec1 write addr must be after sec5.
163 static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
165 Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
168 /*-----------------------------------------------------------------------------
169 * Function: EFUSE_Read1Byte
171 * Overview: Copy from WMAC fot EFUSE read 1 byte.
181 * 09/23/2008 MHC Copy from WMAC.
183 *---------------------------------------------------------------------------*/
184 u8 EFUSE_Read1Byte(struct adapter *Adapter, u16 Address)
187 u8 Bytetemp = {0x00};
192 EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen);
194 if (Address < contentLen) { /* E-fuse 512Byte */
195 /* Write E-fuse Register address bit0~7 */
196 temp = Address & 0xFF;
197 usb_write8(Adapter, EFUSE_CTRL+1, temp);
198 Bytetemp = usb_read8(Adapter, EFUSE_CTRL+2);
199 /* Write E-fuse Register address bit8~9 */
200 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
201 usb_write8(Adapter, EFUSE_CTRL+2, temp);
203 /* Write 0x30[31]= 0 */
204 Bytetemp = usb_read8(Adapter, EFUSE_CTRL+3);
205 temp = Bytetemp & 0x7F;
206 usb_write8(Adapter, EFUSE_CTRL+3, temp);
208 /* Wait Write-ready (0x30[31]= 1) */
209 Bytetemp = usb_read8(Adapter, EFUSE_CTRL+3);
210 while (!(Bytetemp & 0x80)) {
211 Bytetemp = usb_read8(Adapter, EFUSE_CTRL+3);
218 data = usb_read8(Adapter, EFUSE_CTRL);
224 } /* EFUSE_Read1Byte */
226 /* 11/16/2008 MH Read one byte from real Efuse. */
227 u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
233 result = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
236 /* -----------------e-fuse reg ctrl --------------------------------- */
238 usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
239 usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
240 (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
242 usb_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */
244 while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
247 *data = usb_read8(pAdapter, EFUSE_CTRL);
256 /* 11/16/2008 MH Write one byte to reald Efuse. */
257 u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
263 result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
267 /* -----------------e-fuse reg ctrl --------------------------------- */
269 usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
270 usb_write8(pAdapter, EFUSE_CTRL+2,
271 (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
272 (u8)((addr>>8) & 0x03));
273 usb_write8(pAdapter, EFUSE_CTRL, data);/* data */
275 usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
277 while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
288 int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool pseudo)
292 ret = pAdapter->HalFunc.Efuse_PgPacketRead(pAdapter, offset, data, pseudo);
297 int Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
301 ret = pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, pseudo);
307 static int Efuse_PgPacketWrite_BT(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
311 ret = pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, pseudo);
316 /*-----------------------------------------------------------------------------
317 * Function: efuse_WordEnableDataRead
319 * Overview: Read allowed word in current efuse section data.
329 * 11/16/2008 MHC Create Version 0.
330 * 11/21/2008 MHC Fix Write bug when we only enable late word.
332 *---------------------------------------------------------------------------*/
333 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
335 if (!(word_en&BIT(0))) {
336 targetdata[0] = sourdata[0];
337 targetdata[1] = sourdata[1];
339 if (!(word_en&BIT(1))) {
340 targetdata[2] = sourdata[2];
341 targetdata[3] = sourdata[3];
343 if (!(word_en&BIT(2))) {
344 targetdata[4] = sourdata[4];
345 targetdata[5] = sourdata[5];
347 if (!(word_en&BIT(3))) {
348 targetdata[6] = sourdata[6];
349 targetdata[7] = sourdata[7];
353 static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
355 return efuse_OneByteRead(padapter, address, value, false);
358 static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
360 return efuse_OneByteWrite(padapter, address, *value, false);
364 * read/wirte raw efuse data
366 u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts, u8 *data)
369 u16 real_content_len = 0, max_available_size = 0;
371 u8 (*rw8)(struct adapter *, u16, u8*);
373 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len);
374 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
376 if (start_addr > real_content_len)
380 if ((start_addr + cnts) > max_available_size)
387 Efuse_PowerSwitch(padapter, write, true);
389 /* e-fuse one byte read / write */
390 for (i = 0; i < cnts; i++) {
391 if (start_addr >= real_content_len) {
396 res = rw8(padapter, start_addr++, data++);
401 Efuse_PowerSwitch(padapter, write, false);
406 u16 efuse_GetMaxSize(struct adapter *padapter)
409 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size);
413 u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
415 Efuse_PowerSwitch(padapter, false, true);
416 *size = Efuse_GetCurrentSize(padapter, false);
417 Efuse_PowerSwitch(padapter, false, false);
422 u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
426 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
428 if ((addr + cnts) > mapLen)
431 Efuse_PowerSwitch(padapter, false, true);
433 efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
435 Efuse_PowerSwitch(padapter, false, false);
440 u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
444 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
446 if ((addr + cnts) > mapLen)
449 Efuse_PowerSwitch(padapter, false, true);
451 efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
453 Efuse_PowerSwitch(padapter, false, false);
458 u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
462 u8 newdata[PGPKT_DATA_SIZE + 1];
467 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
469 if ((addr + cnts) > mapLen)
472 map = rtw_zmalloc(mapLen);
476 ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
480 Efuse_PowerSwitch(padapter, true, true);
482 offset = (addr >> 3);
484 _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
485 i = addr & 0x7; /* index of one package */
486 idx = 0; /* data index */
490 if (data[idx] != map[addr+idx]) {
491 word_en &= ~BIT(i >> 1);
492 newdata[i-1] = map[addr+idx-1];
493 newdata[i] = data[idx];
499 for (; i < PGPKT_DATA_SIZE; i += 2) {
502 if ((cnts - idx) == 1) {
503 if (data[idx] != map[addr+idx]) {
504 word_en &= ~BIT(i >> 1);
505 newdata[i] = data[idx];
506 newdata[i+1] = map[addr+idx+1];
511 if ((data[idx] != map[addr+idx]) ||
512 (data[idx+1] != map[addr+idx+1])) {
513 word_en &= ~BIT(i >> 1);
514 newdata[i] = data[idx];
515 newdata[i+1] = data[idx + 1];
523 if (word_en != 0xF) {
524 ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
525 DBG_88E("offset=%x\n", offset);
526 DBG_88E("word_en=%x\n", word_en);
528 for (i = 0; i < PGPKT_DATA_SIZE; i++)
529 DBG_88E("data=%x \t", newdata[i]);
540 _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
543 Efuse_PowerSwitch(padapter, true, false);
550 u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
554 u8 newdata[PGPKT_DATA_SIZE + 1];
559 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
561 if ((addr + cnts) > mapLen)
564 map = rtw_zmalloc(mapLen);
568 ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
572 Efuse_PowerSwitch(padapter, true, true);
574 offset = (addr >> 3);
576 _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
577 i = addr & 0x7; /* index of one package */
578 idx = 0; /* data index */
582 if (data[idx] != map[addr+idx]) {
583 word_en &= ~BIT(i >> 1);
584 newdata[i-1] = map[addr+idx-1];
585 newdata[i] = data[idx];
591 for (; i < PGPKT_DATA_SIZE; i += 2) {
594 if ((cnts - idx) == 1) {
595 if (data[idx] != map[addr+idx]) {
596 word_en &= ~BIT(i >> 1);
597 newdata[i] = data[idx];
598 newdata[i+1] = map[addr+idx+1];
603 if ((data[idx] != map[addr+idx]) ||
604 (data[idx+1] != map[addr+idx+1])) {
605 word_en &= ~BIT(i >> 1);
606 newdata[i] = data[idx];
607 newdata[i+1] = data[idx + 1];
615 if (word_en != 0xF) {
616 DBG_88E("%s: offset=%#X\n", __func__, offset);
617 DBG_88E("%s: word_en=%#X\n", __func__, word_en);
618 DBG_88E("%s: data=", __func__);
619 for (i = 0; i < PGPKT_DATA_SIZE; i++)
620 DBG_88E("0x%02X ", newdata[i]);
623 ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, false);
634 _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
637 Efuse_PowerSwitch(padapter, true, false);
646 /*-----------------------------------------------------------------------------
647 * Function: efuse_ShadowRead1Byte
648 * efuse_ShadowRead2Byte
649 * efuse_ShadowRead4Byte
651 * Overview: Read from efuse init map by one/two/four bytes !!!!!
661 * 11/12/2008 MHC Create Version 0.
663 *---------------------------------------------------------------------------*/
665 efuse_ShadowRead1Byte(
666 struct adapter *pAdapter,
670 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
672 *Value = pEEPROM->efuse_eeprom_data[Offset];
674 } /* EFUSE_ShadowRead1Byte */
678 efuse_ShadowRead2Byte(
679 struct adapter *pAdapter,
683 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
685 *Value = pEEPROM->efuse_eeprom_data[Offset];
686 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
688 } /* EFUSE_ShadowRead2Byte */
690 /* Read Four Bytes */
692 efuse_ShadowRead4Byte(
693 struct adapter *pAdapter,
697 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
699 *Value = pEEPROM->efuse_eeprom_data[Offset];
700 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
701 *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
702 *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
704 } /* efuse_ShadowRead4Byte */
706 /*-----------------------------------------------------------------------------
707 * Function: Efuse_ReadAllMap
709 * Overview: Read All Efuse content
719 * 11/11/2008 MHC Create Version 0.
721 *---------------------------------------------------------------------------*/
722 static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
726 Efuse_PowerSwitch(pAdapter, false, true);
728 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
730 efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
732 Efuse_PowerSwitch(pAdapter, false, false);
735 /*-----------------------------------------------------------------------------
736 * Function: EFUSE_ShadowMapUpdate
738 * Overview: Transfer current EFUSE content to shadow init and modify map.
748 * 11/13/2008 MHC Create Version 0.
750 *---------------------------------------------------------------------------*/
751 void EFUSE_ShadowMapUpdate(
752 struct adapter *pAdapter,
756 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
759 EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
761 if (pEEPROM->bautoload_fail_flag)
762 _rtw_memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
764 Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
765 } /* EFUSE_ShadowMapUpdate */
767 /*-----------------------------------------------------------------------------
768 * Function: EFUSE_ShadowRead
770 * Overview: Read from efuse init map !!!!!
780 * 11/12/2008 MHC Create Version 0.
782 *---------------------------------------------------------------------------*/
783 void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
786 efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
788 efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
790 efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
792 } /* EFUSE_ShadowRead */