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]), default 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,
104 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
108 if (efuseType == EFUSE_WIFI)
109 ret = rtl8723a_EfuseGetCurrentSize_WiFi(pAdapter);
111 ret = rtl8723a_EfuseGetCurrentSize_BT(pAdapter);
116 /* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
118 Efuse_CalculateWordCnts23a(u8 word_en)
121 if (!(word_en & BIT(0))) word_cnts++; /* 0 : write enable */
122 if (!(word_en & BIT(1))) word_cnts++;
123 if (!(word_en & BIT(2))) word_cnts++;
124 if (!(word_en & BIT(3))) word_cnts++;
130 /* Execute E-Fuse read byte operation. */
131 /* Referred from SD1 Richard. */
134 /* 1. Boot from E-Fuse and successfully auto-load. */
135 /* 2. PASSIVE_LEVEL (USB interface) */
137 /* Created by Roger, 2008.10.21. */
140 ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
147 rtl8723au_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
148 readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
149 rtl8723au_write8(Adapter, EFUSE_CTRL+2,
150 ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
153 readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
154 rtl8723au_write8(Adapter, EFUSE_CTRL+3, readbyte & 0x7f);
156 /* Check bit 32 read-ready */
158 value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
159 /* while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10)) */
160 while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10000))
162 value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
166 /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
167 /* This fix the problem that Efuse read error in high temperature condition. */
168 /* Designer says that there shall be some delay after ready bit is set, or the */
169 /* result will always stay on last data we read. */
171 value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
173 *pbuf = (u8)(value32 & 0xff);
177 EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
185 case TYPE_EFUSE_MAX_SECTION:
186 pMax_section = (u8 *) pOut;
188 if (efuseType == EFUSE_WIFI)
189 *pMax_section = EFUSE_MAX_SECTION_8723A;
191 *pMax_section = EFUSE_BT_MAX_SECTION;
194 case TYPE_EFUSE_REAL_CONTENT_LEN:
195 pu2Tmp = (u16 *) pOut;
197 if (efuseType == EFUSE_WIFI)
198 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
200 *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
203 case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
204 pu2Tmp = (u16 *) pOut;
206 if (efuseType == EFUSE_WIFI)
207 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
208 EFUSE_OOB_PROTECT_BYTES);
210 *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN -
211 EFUSE_PROTECT_BYTES_BANK);
214 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
215 pu2Tmp = (u16 *) pOut;
217 if (efuseType == EFUSE_WIFI)
218 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
219 EFUSE_OOB_PROTECT_BYTES);
221 *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN -
222 (EFUSE_PROTECT_BYTES_BANK * 3));
225 case TYPE_EFUSE_MAP_LEN:
226 pu2Tmp = (u16 *) pOut;
228 if (efuseType == EFUSE_WIFI)
229 *pu2Tmp = EFUSE_MAP_LEN_8723A;
231 *pu2Tmp = EFUSE_BT_MAP_LEN;
234 case TYPE_EFUSE_PROTECT_BYTES_BANK:
235 pu1Tmp = (u8 *) pOut;
237 if (efuseType == EFUSE_WIFI)
238 *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
240 *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
243 case TYPE_EFUSE_CONTENT_LEN_BANK:
244 pu2Tmp = (u16 *) pOut;
246 if (efuseType == EFUSE_WIFI)
247 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
249 *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
253 pu1Tmp = (u8 *) pOut;
259 /*-----------------------------------------------------------------------------
260 * Function: EFUSE_Read1Byte23a
262 * Overview: Copy from WMAC fot EFUSE read 1 byte.
272 * 09/23/2008 MHC Copy from WMAC.
274 *---------------------------------------------------------------------------*/
276 EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
279 u8 Bytetemp = {0x00};
284 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
285 TYPE_EFUSE_REAL_CONTENT_LEN,
286 (void *)&contentLen);
288 if (Address < contentLen) /* E-fuse 512Byte */
290 /* Write E-fuse Register address bit0~7 */
291 temp = Address & 0xFF;
292 rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp);
293 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
294 /* Write E-fuse Register address bit8~9 */
295 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
296 rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp);
298 /* Write 0x30[31]= 0 */
299 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
300 temp = Bytetemp & 0x7F;
301 rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp);
303 /* Wait Write-ready (0x30[31]= 1) */
304 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
305 while(!(Bytetemp & 0x80))
307 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
315 data = rtl8723au_read8(Adapter, EFUSE_CTRL);
320 }/* EFUSE_Read1Byte23a */
322 /*-----------------------------------------------------------------------------
323 * Function: EFUSE_Write1Byte
325 * Overview: Copy from WMAC fot EFUSE write 1 byte.
335 * 09/23/2008 MHC Copy from WMAC.
337 *---------------------------------------------------------------------------*/
341 struct rtw_adapter * Adapter,
346 struct rtw_adapter * Adapter,
350 u8 Bytetemp = {0x00};
355 /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr =%x Data =%x\n", Address, Value)); */
356 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
357 TYPE_EFUSE_REAL_CONTENT_LEN,
358 (void *)&contentLen);
360 if (Address < contentLen) /* E-fuse 512Byte */
362 rtl8723au_write8(Adapter, EFUSE_CTRL, Value);
364 /* Write E-fuse Register address bit0~7 */
365 temp = Address & 0xFF;
366 rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp);
367 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
369 /* Write E-fuse Register address bit8~9 */
370 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
371 rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp);
373 /* Write 0x30[31]= 1 */
374 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
375 temp = Bytetemp | 0x80;
376 rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp);
378 /* Wait Write-ready (0x30[31]= 0) */
379 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
380 while(Bytetemp & 0x80)
382 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
391 }/* EFUSE_Write1Byte */
393 /* 11/16/2008 MH Read one byte from real Efuse. */
395 efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
400 /* -----------------e-fuse reg ctrl --------------------------------- */
402 rtl8723au_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
403 rtl8723au_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03)) |
404 (rtl8723au_read8(pAdapter, EFUSE_CTRL+2)&0xFC));
406 rtl8723au_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */
408 while(!(0x80 &rtl8723au_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100))
411 *data = rtl8723au_read8(pAdapter, EFUSE_CTRL);
420 /* 11/16/2008 MH Write one byte to reald Efuse. */
422 efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
427 /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr = %x Data =%x\n", addr, data)); */
431 /* -----------------e-fuse reg ctrl --------------------------------- */
433 rtl8723au_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
434 rtl8723au_write8(pAdapter, EFUSE_CTRL+2,
435 (rtl8723au_read8(pAdapter, EFUSE_CTRL+2)&0xFC)|(u8)((addr>>8)&0x03));
436 rtl8723au_write8(pAdapter, EFUSE_CTRL, data);/* data */
438 rtl8723au_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
440 while((0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL+3)) &&
453 /*-----------------------------------------------------------------------------
454 * Function: efuse_WordEnableDataRead23a
456 * Overview: Read allowed word in current efuse section data.
466 * 11/16/2008 MHC Create Version 0.
467 * 11/21/2008 MHC Fix Write bug when we only enable late word.
469 *---------------------------------------------------------------------------*/
471 efuse_WordEnableDataRead23a(u8 word_en,
475 if (!(word_en&BIT(0)))
477 targetdata[0] = sourdata[0];
478 targetdata[1] = sourdata[1];
480 if (!(word_en&BIT(1)))
482 targetdata[2] = sourdata[2];
483 targetdata[3] = sourdata[3];
485 if (!(word_en&BIT(2)))
487 targetdata[4] = sourdata[4];
488 targetdata[5] = sourdata[5];
490 if (!(word_en&BIT(3)))
492 targetdata[6] = sourdata[6];
493 targetdata[7] = sourdata[7];
497 static int efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value)
499 return efuse_OneByteRead23a(padapter, address, value);
502 static int efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value)
504 return efuse_OneByteWrite23a(padapter, address, *value);
508 * read/write raw efuse data
510 int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
514 u16 real_content_len = 0, max_available_size = 0;
516 int (*rw8)(struct rtw_adapter *, u16, u8*);
518 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
519 TYPE_EFUSE_REAL_CONTENT_LEN,
520 (void *)&real_content_len);
521 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
522 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
523 (void *)&max_available_size);
525 if (start_addr > real_content_len)
528 if (true == bWrite) {
529 if ((start_addr + cnts) > max_available_size)
535 Efuse_PowerSwitch(padapter, bWrite, true);
537 /* e-fuse one byte read / write */
538 for (i = 0; i < cnts; i++) {
539 if (start_addr >= real_content_len) {
544 res = rw8(padapter, start_addr++, data++);
549 Efuse_PowerSwitch(padapter, bWrite, false);
554 u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter)
557 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
558 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
563 int rtw_efuse_map_read23a(struct rtw_adapter *padapter,
564 u16 addr, u16 cnts, u8 *data)
568 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
569 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
571 if ((addr + cnts) > mapLen)
574 Efuse_PowerSwitch(padapter, false, true);
576 rtl8723a_readefuse(padapter, EFUSE_WIFI, addr, cnts, data);
578 Efuse_PowerSwitch(padapter, false, false);
583 int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter,
584 u16 addr, u16 cnts, u8 *data)
588 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
589 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
591 if ((addr + cnts) > mapLen)
594 Efuse_PowerSwitch(padapter, false, true);
596 rtl8723a_readefuse(padapter, EFUSE_BT, addr, cnts, data);
598 Efuse_PowerSwitch(padapter, false, false);
603 /*-----------------------------------------------------------------------------
604 * Function: Efuse_ReadAllMap
606 * Overview: Read All Efuse content
616 * 11/11/2008 MHC Create Version 0.
618 *---------------------------------------------------------------------------*/
620 Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse);
622 Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse)
626 Efuse_PowerSwitch(pAdapter, false, true);
628 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN,
631 rtl8723a_readefuse(pAdapter, efuseType, 0, mapLen, Efuse);
633 Efuse_PowerSwitch(pAdapter, false, false);
636 /*-----------------------------------------------------------------------------
637 * Function: efuse_ShadowRead1Byte
638 * efuse_ShadowRead2Byte
639 * efuse_ShadowRead4Byte
641 * Overview: Read from efuse init map by one/two/four bytes !!!!!
651 * 11/12/2008 MHC Create Version 0.
653 *---------------------------------------------------------------------------*/
655 efuse_ShadowRead1Byte(
656 struct rtw_adapter * pAdapter,
660 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
662 *Value = pEEPROM->efuse_eeprom_data[Offset];
663 } /* EFUSE_ShadowRead23a1Byte */
667 efuse_ShadowRead2Byte(
668 struct rtw_adapter * pAdapter,
672 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
674 *Value = pEEPROM->efuse_eeprom_data[Offset];
675 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
676 } /* EFUSE_ShadowRead23a2Byte */
678 /* Read Four Bytes */
680 efuse_ShadowRead4Byte(
681 struct rtw_adapter * pAdapter,
685 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
687 *Value = pEEPROM->efuse_eeprom_data[Offset];
688 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
689 *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
690 *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
691 } /* efuse_ShadowRead4Byte */
693 /*-----------------------------------------------------------------------------
694 * Function: EFUSE_ShadowMapUpdate23a
696 * Overview: Transfer current EFUSE content to shadow init and modify map.
706 * 11/13/2008 MHC Create Version 0.
708 *---------------------------------------------------------------------------*/
709 void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType)
711 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
714 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
715 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
717 if (pEEPROM->bautoload_fail_flag == true)
718 memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
720 Efuse_ReadAllMap(pAdapter, efuseType,
721 pEEPROM->efuse_eeprom_data);
723 }/* EFUSE_ShadowMapUpdate23a */
725 /*-----------------------------------------------------------------------------
726 * Function: EFUSE_ShadowRead23a
728 * Overview: Read from efuse init map !!!!!
738 * 11/12/2008 MHC Create Version 0.
740 *---------------------------------------------------------------------------*/
743 struct rtw_adapter * pAdapter,
749 efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
751 efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
753 efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
754 } /* EFUSE_ShadowRead23a */