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 REG_EFUSE_CTRL 0x0030
25 #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control */
27 #define VOLTAGE_V25 0x03
28 #define LDOE25_SHIFT 28
31 * When we want to enable write operation, we should change to
32 * pwr on state. When we stop write, we should switch to 500k mode
33 * and disable LDO 2.5V.
35 static void Efuse_PowerSwitch(struct rtw_adapter *padapter,
36 u8 bWrite, u8 PwrState)
41 if (PwrState == true) {
42 rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
45 * 1.2V Power: From VDDON with Power
46 * Cut(0x0000h[15]), default valid
48 tmpV16 = rtl8723au_read16(padapter, REG_SYS_ISO_CTRL);
49 if (!(tmpV16 & PWC_EV12V)) {
51 rtl8723au_write16(padapter, REG_SYS_ISO_CTRL, tmpV16);
53 /* Reset: 0x0000h[28], default valid */
54 tmpV16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN);
55 if (!(tmpV16 & FEN_ELDR)) {
57 rtl8723au_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
61 * Clock: Gated(0x0008h[5]) 8M(0x0008h[1])
62 * clock from ANA, default valid
64 tmpV16 = rtl8723au_read16(padapter, REG_SYS_CLKR);
65 if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
66 tmpV16 |= (LOADER_CLK_EN | ANA8M);
67 rtl8723au_write16(padapter, REG_SYS_CLKR, tmpV16);
71 /* Enable LDO 2.5V before read/write action */
72 tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3);
74 tempval |= (VOLTAGE_V25 << 4);
75 rtl8723au_write8(padapter, EFUSE_TEST + 3,
79 rtl8723au_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
82 /* Disable LDO 2.5V after read/write action */
83 tempval = rtl8723au_read8(padapter, EFUSE_TEST + 3);
84 rtl8723au_write8(padapter, EFUSE_TEST + 3,
91 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
95 if (efuseType == EFUSE_WIFI)
96 ret = rtl8723a_EfuseGetCurrentSize_WiFi(pAdapter);
98 ret = rtl8723a_EfuseGetCurrentSize_BT(pAdapter);
103 /* Get current efuse area enabled word */
105 Efuse_CalculateWordCnts23a(u8 word_en)
107 return hweight8((~word_en) & 0xf);
111 * Description: Execute E-Fuse read byte operation.
113 * Assumptions: 1. Boot from E-Fuse and successfully auto-load.
114 * 2. PASSIVE_LEVEL (USB interface)
117 ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
124 rtl8723au_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
125 readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
126 rtl8723au_write8(Adapter, EFUSE_CTRL+2,
127 ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
130 readbyte = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
131 rtl8723au_write8(Adapter, EFUSE_CTRL+3, readbyte & 0x7f);
133 /* Check bit 32 read-ready */
135 value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
136 while (!((value32 >> 24) & 0x80) && retry < 10000) {
137 value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
142 * Added suggested delay. This fixes the problem that
143 * Efuse read error in high temperature condition.
144 * Designer says that there shall be some delay after
145 * ready bit is set, or the result will always stay
146 * on last data we read.
149 value32 = rtl8723au_read32(Adapter, EFUSE_CTRL);
151 *pbuf = (u8)(value32 & 0xff);
155 EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
163 case TYPE_EFUSE_MAX_SECTION:
166 if (efuseType == EFUSE_WIFI)
167 *pMax_section = EFUSE_MAX_SECTION_8723A;
169 *pMax_section = EFUSE_BT_MAX_SECTION;
172 case TYPE_EFUSE_REAL_CONTENT_LEN:
175 if (efuseType == EFUSE_WIFI)
176 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
178 *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
181 case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
184 if (efuseType == EFUSE_WIFI)
185 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
186 EFUSE_OOB_PROTECT_BYTES);
188 *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN -
189 EFUSE_PROTECT_BYTES_BANK);
192 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
195 if (efuseType == EFUSE_WIFI)
196 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
197 EFUSE_OOB_PROTECT_BYTES);
199 *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN -
200 (EFUSE_PROTECT_BYTES_BANK * 3));
203 case TYPE_EFUSE_MAP_LEN:
206 if (efuseType == EFUSE_WIFI)
207 *pu2Tmp = EFUSE_MAP_LEN_8723A;
209 *pu2Tmp = EFUSE_BT_MAP_LEN;
212 case TYPE_EFUSE_PROTECT_BYTES_BANK:
215 if (efuseType == EFUSE_WIFI)
216 *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
218 *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
221 case TYPE_EFUSE_CONTENT_LEN_BANK:
224 if (efuseType == EFUSE_WIFI)
225 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
227 *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
237 /* Copy from WMAC for EFUSE read 1 byte. */
239 EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
242 u8 Bytetemp = {0x00};
247 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
248 TYPE_EFUSE_REAL_CONTENT_LEN,
249 (void *)&contentLen);
251 if (Address < contentLen) { /* E-fuse 512Byte */
252 /* Write E-fuse Register address bit0~7 */
253 temp = Address & 0xFF;
254 rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp);
255 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
256 /* Write E-fuse Register address bit8~9 */
257 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
258 rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp);
260 /* Write 0x30[31]= 0 */
261 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
262 temp = Bytetemp & 0x7F;
263 rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp);
265 /* Wait Write-ready (0x30[31]= 1) */
266 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
267 while (!(Bytetemp & 0x80)) {
268 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
275 data = rtl8723au_read8(Adapter, EFUSE_CTRL);
281 /* Copy from WMAC fot EFUSE write 1 byte. */
283 EFUSE_Write1Byte(struct rtw_adapter *Adapter, u16 Address, u8 Value);
285 EFUSE_Write1Byte(struct rtw_adapter *Adapter, u16 Address, u8 Value)
287 u8 Bytetemp = {0x00};
292 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
293 TYPE_EFUSE_REAL_CONTENT_LEN,
294 (void *)&contentLen);
296 if (Address < contentLen) { /* E-fuse 512Byte */
297 rtl8723au_write8(Adapter, EFUSE_CTRL, Value);
299 /* Write E-fuse Register address bit0~7 */
300 temp = Address & 0xFF;
301 rtl8723au_write8(Adapter, EFUSE_CTRL+1, temp);
302 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+2);
304 /* Write E-fuse Register address bit8~9 */
305 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
306 rtl8723au_write8(Adapter, EFUSE_CTRL+2, temp);
308 /* Write 0x30[31]= 1 */
309 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
310 temp = Bytetemp | 0x80;
311 rtl8723au_write8(Adapter, EFUSE_CTRL+3, temp);
313 /* Wait Write-ready (0x30[31]= 0) */
314 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
315 while (Bytetemp & 0x80) {
316 Bytetemp = rtl8723au_read8(Adapter, EFUSE_CTRL+3);
326 /* Read one byte from real Efuse. */
328 efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
333 /* -----------------e-fuse reg ctrl ---------------------------- */
335 rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
336 rtl8723au_write8(pAdapter, EFUSE_CTRL + 2,
337 ((u8)((addr >> 8) & 0x03)) |
338 (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
340 rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0x72); /* read cmd */
342 while (!(0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) &&
346 *data = rtl8723au_read8(pAdapter, EFUSE_CTRL);
355 /* Write one byte to reald Efuse. */
357 efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
364 /* -----------------e-fuse reg ctrl ------------------------- */
366 rtl8723au_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
367 rtl8723au_write8(pAdapter, EFUSE_CTRL + 2,
368 (rtl8723au_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
369 (u8)((addr >> 8) & 0x03));
370 rtl8723au_write8(pAdapter, EFUSE_CTRL, data); /* data */
372 rtl8723au_write8(pAdapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */
374 while ((0x80 & rtl8723au_read8(pAdapter, EFUSE_CTRL + 3)) &&
387 /* Read allowed word in current efuse section data. */
389 efuse_WordEnableDataRead23a(u8 word_en,
393 if (!(word_en&BIT(0))) {
394 targetdata[0] = sourdata[0];
395 targetdata[1] = sourdata[1];
397 if (!(word_en&BIT(1))) {
398 targetdata[2] = sourdata[2];
399 targetdata[3] = sourdata[3];
401 if (!(word_en&BIT(2))) {
402 targetdata[4] = sourdata[4];
403 targetdata[5] = sourdata[5];
405 if (!(word_en&BIT(3))) {
406 targetdata[6] = sourdata[6];
407 targetdata[7] = sourdata[7];
411 static int efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value)
413 return efuse_OneByteRead23a(padapter, address, value);
416 static int efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value)
418 return efuse_OneByteWrite23a(padapter, address, *value);
421 /* read/write raw efuse data */
422 int rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
426 u16 real_content_len = 0, max_available_size = 0;
428 int (*rw8)(struct rtw_adapter *, u16, u8*);
430 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
431 TYPE_EFUSE_REAL_CONTENT_LEN,
432 (void *)&real_content_len);
433 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
434 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
435 (void *)&max_available_size);
437 if (start_addr > real_content_len)
440 if (true == bWrite) {
441 if ((start_addr + cnts) > max_available_size)
447 Efuse_PowerSwitch(padapter, bWrite, true);
449 /* e-fuse one byte read/write */
450 for (i = 0; i < cnts; i++) {
451 if (start_addr >= real_content_len) {
456 res = rw8(padapter, start_addr++, data++);
461 Efuse_PowerSwitch(padapter, bWrite, false);
466 u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter)
470 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
471 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
476 int rtw_efuse_map_read23a(struct rtw_adapter *padapter,
477 u16 addr, u16 cnts, u8 *data)
481 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
482 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
484 if ((addr + cnts) > mapLen)
487 Efuse_PowerSwitch(padapter, false, true);
489 rtl8723a_readefuse(padapter, EFUSE_WIFI, addr, cnts, data);
491 Efuse_PowerSwitch(padapter, false, false);
496 int rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter,
497 u16 addr, u16 cnts, u8 *data)
501 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
502 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
504 if ((addr + cnts) > mapLen)
507 Efuse_PowerSwitch(padapter, false, true);
509 rtl8723a_readefuse(padapter, EFUSE_BT, addr, cnts, data);
511 Efuse_PowerSwitch(padapter, false, false);
516 /* Read All Efuse content */
518 Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse);
520 Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse)
524 Efuse_PowerSwitch(pAdapter, false, true);
526 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN,
529 rtl8723a_readefuse(pAdapter, efuseType, 0, mapLen, Efuse);
531 Efuse_PowerSwitch(pAdapter, false, false);
535 * Functions: efuse_ShadowRead1Byte
536 * efuse_ShadowRead2Byte
537 * efuse_ShadowRead4Byte
539 * Read from efuse init map by one/two/four bytes
542 efuse_ShadowRead1Byte(struct rtw_adapter *pAdapter, u16 Offset, u8 *Value)
544 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
546 *Value = pEEPROM->efuse_eeprom_data[Offset];
550 efuse_ShadowRead2Byte(struct rtw_adapter *pAdapter, u16 Offset, u16 *Value)
552 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
554 *Value = pEEPROM->efuse_eeprom_data[Offset];
555 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
559 efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset, u32 *Value)
561 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
563 *Value = pEEPROM->efuse_eeprom_data[Offset];
564 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
565 *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
566 *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
569 /* Transfer current EFUSE content to shadow init and modify map. */
571 void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType)
573 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
576 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
577 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
579 if (pEEPROM->bautoload_fail_flag == true)
580 memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
582 Efuse_ReadAllMap(pAdapter, efuseType,
583 pEEPROM->efuse_eeprom_data);
586 /* Read from efuse init map */
588 EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter,
589 u8 Type, u16 Offset, u32 *Value)
592 efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
594 efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
596 efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);