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 ******************************************************************************/
17 #include <osdep_service.h>
18 #include <drv_types.h>
20 #include <rtw_efuse.h>
21 #include <rtl8723a_hal.h>
22 #include <usb_ops_linux.h>
24 /*------------------------Define local variable------------------------------*/
27 #define REG_EFUSE_CTRL 0x0030
28 #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
31 #define VOLTAGE_V25 0x03
32 #define LDOE25_SHIFT 28
34 /*-----------------------------------------------------------------------------
35 * Function: Efuse_PowerSwitch
37 * Overview: When we want to enable write operation, we should change to
38 * pwr on state. When we stop write, we should switch to 500k mode
39 * and disable LDO 2.5V.
49 * 11/17/2008 MHC Create Version 0.
51 *---------------------------------------------------------------------------*/
52 static void Efuse_PowerSwitch(struct rtw_adapter *padapter,
53 u8 bWrite, u8 PwrState)
58 if (PwrState == true) {
59 rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
61 /* 1.2V Power: From VDDON with Power
62 Cut(0x0000h[15]), defualt valid */
63 tmpV16 = rtl8723au_read16(padapter, REG_SYS_ISO_CTRL);
64 if (!(tmpV16 & PWC_EV12V)) {
66 rtl8723au_write16(padapter, REG_SYS_ISO_CTRL, tmpV16);
68 /* Reset: 0x0000h[28], default valid */
69 tmpV16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN);
70 if (!(tmpV16 & FEN_ELDR)) {
72 rtl8723au_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
75 /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock
76 from ANA, default valid */
77 tmpV16 = rtl8723au_read16(padapter, REG_SYS_CLKR);
78 if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
79 tmpV16 |= (LOADER_CLK_EN | ANA8M);
80 rtl8723au_write16(padapter, REG_SYS_CLKR, tmpV16);
84 /* Enable LDO 2.5V before read/write action */
85 tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3);
87 tempval |= (VOLTAGE_V25 << 4);
88 rtl8723au_write8(padapter, EFUSE_TEST + 3,
92 rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
95 /* Disable LDO 2.5V after read/write action */
96 tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3);
97 rtl8723au_write8(padapter, EFUSE_TEST + 3,
103 /*-----------------------------------------------------------------------------
104 * Function: efuse_GetCurrentSize23a
106 * Overview: Get current efuse size!!!
116 * 11/16/2008 MHC Create Version 0.
118 *---------------------------------------------------------------------------*/
120 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
124 if (efuseType == EFUSE_WIFI)
125 ret = rtl8723a_EfuseGetCurrentSize_WiFi(pAdapter);
127 ret = rtl8723a_EfuseGetCurrentSize_BT(pAdapter);
132 /* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
134 Efuse_CalculateWordCnts23a(u8 word_en)
137 if (!(word_en & BIT(0))) word_cnts++; /* 0 : write enable */
138 if (!(word_en & BIT(1))) word_cnts++;
139 if (!(word_en & BIT(2))) word_cnts++;
140 if (!(word_en & BIT(3))) word_cnts++;
146 /* Execute E-Fuse read byte operation. */
147 /* Refered from SD1 Richard. */
150 /* 1. Boot from E-Fuse and successfully auto-load. */
151 /* 2. PASSIVE_LEVEL (USB interface) */
153 /* Created by Roger, 2008.10.21. */
156 ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
163 rtl8723au_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
164 readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
165 rtl8723au_write8(Adapter, EFUSE_CTRL+2,
166 ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
169 readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
170 rtl8723au_write8(Adapter, EFUSE_CTRL+3, readbyte & 0x7f);
172 /* Check bit 32 read-ready */
174 value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
175 /* while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10)) */
176 while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10000))
178 value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
182 /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
183 /* This fix the problem that Efuse read error in high temperature condition. */
184 /* Designer says that there shall be some delay after ready bit is set, or the */
185 /* result will always stay on last data we read. */
187 value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
189 *pbuf = (u8)(value32 & 0xff);
193 EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
201 case TYPE_EFUSE_MAX_SECTION:
202 pMax_section = (u8 *) pOut;
204 if (efuseType == EFUSE_WIFI)
205 *pMax_section = EFUSE_MAX_SECTION_8723A;
207 *pMax_section = EFUSE_BT_MAX_SECTION;
210 case TYPE_EFUSE_REAL_CONTENT_LEN:
211 pu2Tmp = (u16 *) pOut;
213 if (efuseType == EFUSE_WIFI)
214 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
216 *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
219 case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
220 pu2Tmp = (u16 *) pOut;
222 if (efuseType == EFUSE_WIFI)
223 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
224 EFUSE_OOB_PROTECT_BYTES);
226 *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN -
227 EFUSE_PROTECT_BYTES_BANK);
230 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
231 pu2Tmp = (u16 *) pOut;
233 if (efuseType == EFUSE_WIFI)
234 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
235 EFUSE_OOB_PROTECT_BYTES);
237 *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN -
238 (EFUSE_PROTECT_BYTES_BANK * 3));
241 case TYPE_EFUSE_MAP_LEN:
242 pu2Tmp = (u16 *) pOut;
244 if (efuseType == EFUSE_WIFI)
245 *pu2Tmp = EFUSE_MAP_LEN_8723A;
247 *pu2Tmp = EFUSE_BT_MAP_LEN;
250 case TYPE_EFUSE_PROTECT_BYTES_BANK:
251 pu1Tmp = (u8 *) pOut;
253 if (efuseType == EFUSE_WIFI)
254 *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
256 *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
259 case TYPE_EFUSE_CONTENT_LEN_BANK:
260 pu2Tmp = (u16 *) pOut;
262 if (efuseType == EFUSE_WIFI)
263 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
265 *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
269 pu1Tmp = (u8 *) pOut;
275 /*-----------------------------------------------------------------------------
276 * Function: EFUSE_Read1Byte23a
278 * Overview: Copy from WMAC fot EFUSE read 1 byte.
288 * 09/23/2008 MHC Copy from WMAC.
290 *---------------------------------------------------------------------------*/
292 EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
295 u8 Bytetemp = {0x00};
300 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
301 TYPE_EFUSE_REAL_CONTENT_LEN,
302 (void *)&contentLen);
304 if (Address < contentLen) /* E-fuse 512Byte */
306 /* Write E-fuse Register address bit0~7 */
307 temp = Address & 0xFF;
308 rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp);
309 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
310 /* Write E-fuse Register address bit8~9 */
311 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
312 rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp);
314 /* Write 0x30[31]= 0 */
315 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
316 temp = Bytetemp & 0x7F;
317 rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp);
319 /* Wait Write-ready (0x30[31]= 1) */
320 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
321 while(!(Bytetemp & 0x80))
323 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
331 data = rtl8723au_read8(Adapter, EFUSE_CTRL);
336 }/* EFUSE_Read1Byte23a */
338 /*-----------------------------------------------------------------------------
339 * Function: EFUSE_Write1Byte
341 * Overview: Copy from WMAC fot EFUSE write 1 byte.
351 * 09/23/2008 MHC Copy from WMAC.
353 *---------------------------------------------------------------------------*/
357 struct rtw_adapter * Adapter,
362 struct rtw_adapter * Adapter,
366 u8 Bytetemp = {0x00};
371 /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr =%x Data =%x\n", Address, Value)); */
372 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
373 TYPE_EFUSE_REAL_CONTENT_LEN,
374 (void *)&contentLen);
376 if (Address < contentLen) /* E-fuse 512Byte */
378 rtl8723au_write8(Adapter, EFUSE_CTRL, Value);
380 /* Write E-fuse Register address bit0~7 */
381 temp = Address & 0xFF;
382 rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp);
383 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
385 /* Write E-fuse Register address bit8~9 */
386 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
387 rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp);
389 /* Write 0x30[31]= 1 */
390 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
391 temp = Bytetemp | 0x80;
392 rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp);
394 /* Wait Write-ready (0x30[31]= 0) */
395 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
396 while(Bytetemp & 0x80)
398 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
407 }/* EFUSE_Write1Byte */
409 /* 11/16/2008 MH Read one byte from real Efuse. */
411 efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
416 /* -----------------e-fuse reg ctrl --------------------------------- */
418 rtl8723au_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
419 rtl8723au_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03)) |
420 (rtl8723au_read8(pAdapter, EFUSE_CTRL+2)&0xFC));
422 rtl8723au_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */
424 while(!(0x80 &rtl8723au_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100))
427 *data = rtl8723au_read8(pAdapter, EFUSE_CTRL);
436 /* 11/16/2008 MH Write one byte to reald Efuse. */
438 efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
443 /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr = %x Data =%x\n", addr, data)); */
447 /* -----------------e-fuse reg ctrl --------------------------------- */
449 rtl8723au_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
450 rtl8723au_write8(pAdapter, EFUSE_CTRL+2,
451 (rtl8723au_read8(pAdapter, EFUSE_CTRL+2)&0xFC)|(u8)((addr>>8)&0x03));
452 rtl8723au_write8(pAdapter, EFUSE_CTRL, data);/* data */
454 rtl8723au_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
456 while((0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL+3)) &&
469 /*-----------------------------------------------------------------------------
470 * Function: efuse_WordEnableDataRead23a
472 * Overview: Read allowed word in current efuse section data.
482 * 11/16/2008 MHC Create Version 0.
483 * 11/21/2008 MHC Fix Write bug when we only enable late word.
485 *---------------------------------------------------------------------------*/
487 efuse_WordEnableDataRead23a(u8 word_en,
491 if (!(word_en&BIT(0)))
493 targetdata[0] = sourdata[0];
494 targetdata[1] = sourdata[1];
496 if (!(word_en&BIT(1)))
498 targetdata[2] = sourdata[2];
499 targetdata[3] = sourdata[3];
501 if (!(word_en&BIT(2)))
503 targetdata[4] = sourdata[4];
504 targetdata[5] = sourdata[5];
506 if (!(word_en&BIT(3)))
508 targetdata[6] = sourdata[6];
509 targetdata[7] = sourdata[7];
513 static int efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value)
515 return efuse_OneByteRead23a(padapter, address, value);
518 static int efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value)
520 return efuse_OneByteWrite23a(padapter, address, *value);
524 * read/wirte raw efuse data
526 int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
530 u16 real_content_len = 0, max_available_size = 0;
532 int (*rw8)(struct rtw_adapter *, u16, u8*);
534 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
535 TYPE_EFUSE_REAL_CONTENT_LEN,
536 (void *)&real_content_len);
537 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
538 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
539 (void *)&max_available_size);
541 if (start_addr > real_content_len)
544 if (true == bWrite) {
545 if ((start_addr + cnts) > max_available_size)
551 Efuse_PowerSwitch(padapter, bWrite, true);
553 /* e-fuse one byte read / write */
554 for (i = 0; i < cnts; i++) {
555 if (start_addr >= real_content_len) {
560 res = rw8(padapter, start_addr++, data++);
565 Efuse_PowerSwitch(padapter, bWrite, false);
570 u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter)
573 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
574 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
579 int efuse_GetCurrentSize23a(struct rtw_adapter *padapter, u16 *size)
581 Efuse_PowerSwitch(padapter, false, true);
582 *size = Efuse_GetCurrentSize23a(padapter, EFUSE_WIFI);
583 Efuse_PowerSwitch(padapter, false, false);
588 int rtw_efuse_map_read23a(struct rtw_adapter *padapter,
589 u16 addr, u16 cnts, u8 *data)
593 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
594 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
596 if ((addr + cnts) > mapLen)
599 Efuse_PowerSwitch(padapter, false, true);
601 rtl8723a_readefuse(padapter, EFUSE_WIFI, addr, cnts, data);
603 Efuse_PowerSwitch(padapter, false, false);
608 int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter,
609 u16 addr, u16 cnts, u8 *data)
613 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
614 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
616 if ((addr + cnts) > mapLen)
619 Efuse_PowerSwitch(padapter, false, true);
621 rtl8723a_readefuse(padapter, EFUSE_BT, addr, cnts, data);
623 Efuse_PowerSwitch(padapter, false, false);
628 /*-----------------------------------------------------------------------------
629 * Function: Efuse_ReadAllMap
631 * Overview: Read All Efuse content
641 * 11/11/2008 MHC Create Version 0.
643 *---------------------------------------------------------------------------*/
645 Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse);
647 Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse)
651 Efuse_PowerSwitch(pAdapter, false, true);
653 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN,
656 rtl8723a_readefuse(pAdapter, efuseType, 0, mapLen, Efuse);
658 Efuse_PowerSwitch(pAdapter, false, false);
661 /*-----------------------------------------------------------------------------
662 * Function: efuse_ShadowRead1Byte
663 * efuse_ShadowRead2Byte
664 * efuse_ShadowRead4Byte
666 * Overview: Read from efuse init map by one/two/four bytes !!!!!
676 * 11/12/2008 MHC Create Version 0.
678 *---------------------------------------------------------------------------*/
680 efuse_ShadowRead1Byte(
681 struct rtw_adapter * pAdapter,
685 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
687 *Value = pEEPROM->efuse_eeprom_data[Offset];
688 } /* EFUSE_ShadowRead23a1Byte */
692 efuse_ShadowRead2Byte(
693 struct rtw_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 } /* EFUSE_ShadowRead23a2Byte */
703 /* Read Four Bytes */
705 efuse_ShadowRead4Byte(
706 struct rtw_adapter * pAdapter,
710 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
712 *Value = pEEPROM->efuse_eeprom_data[Offset];
713 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
714 *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
715 *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
716 } /* efuse_ShadowRead4Byte */
718 /*-----------------------------------------------------------------------------
719 * Function: EFUSE_ShadowMapUpdate23a
721 * Overview: Transfer current EFUSE content to shadow init and modify map.
731 * 11/13/2008 MHC Create Version 0.
733 *---------------------------------------------------------------------------*/
734 void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType)
736 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
739 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
740 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
742 if (pEEPROM->bautoload_fail_flag == true)
743 memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
745 Efuse_ReadAllMap(pAdapter, efuseType,
746 pEEPROM->efuse_eeprom_data);
748 }/* EFUSE_ShadowMapUpdate23a */
750 /*-----------------------------------------------------------------------------
751 * Function: EFUSE_ShadowRead23a
753 * Overview: Read from efuse init map !!!!!
763 * 11/12/2008 MHC Create Version 0.
765 *---------------------------------------------------------------------------*/
768 struct rtw_adapter * pAdapter,
774 efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
776 efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
778 efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
779 } /* EFUSE_ShadowRead23a */