From: navin patidar Date: Fri, 20 Jun 2014 14:59:47 +0000 (+0530) Subject: staging: rtl8188eu: Move all efuse related code to rtw_efuse.c X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=ee5f8a431ead8f334f4c04f91ecafa34cb9d52ca;p=deliverable%2Flinux.git staging: rtl8188eu: Move all efuse related code to rtw_efuse.c Signed-off-by: navin patidar Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 7eb89465d8a8..672bfed3c428 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -23,10 +23,881 @@ #include #include #include +#include +#include #define REG_EFUSE_CTRL 0x0030 #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */ +enum{ + VOLTAGE_V25 = 0x03, + LDOE25_SHIFT = 28 , + }; + +/* + * Function: Efuse_PowerSwitch + * + * Overview: When we want to enable write operation, we should change to + * pwr on state. When we stop write, we should switch to 500k mode + * and disable LDO 2.5V. + */ + +void Efuse_PowerSwitch( + struct adapter *pAdapter, + u8 bWrite, + u8 PwrState) +{ + u8 tempval; + u16 tmpV16; + + if (PwrState) { + usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); + + /* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */ + tmpV16 = usb_read16(pAdapter, REG_SYS_ISO_CTRL); + if (!(tmpV16 & PWC_EV12V)) { + tmpV16 |= PWC_EV12V; + usb_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16); + } + /* Reset: 0x0000h[28], default valid */ + tmpV16 = usb_read16(pAdapter, REG_SYS_FUNC_EN); + if (!(tmpV16 & FEN_ELDR)) { + tmpV16 |= FEN_ELDR; + usb_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16); + } + + /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */ + tmpV16 = usb_read16(pAdapter, REG_SYS_CLKR); + if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) { + tmpV16 |= (LOADER_CLK_EN | ANA8M); + usb_write16(pAdapter, REG_SYS_CLKR, tmpV16); + } + + if (bWrite) { + /* Enable LDO 2.5V before read/write action */ + tempval = usb_read8(pAdapter, EFUSE_TEST+3); + tempval &= 0x0F; + tempval |= (VOLTAGE_V25 << 4); + usb_write8(pAdapter, EFUSE_TEST+3, (tempval | 0x80)); + } + } else { + usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); + + if (bWrite) { + /* Disable LDO 2.5V after read/write action */ + tempval = usb_read8(pAdapter, EFUSE_TEST+3); + usb_write8(pAdapter, EFUSE_TEST+3, (tempval & 0x7F)); + } + } +} + +static void +efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) +{ + u8 *efuseTbl = NULL; + u8 rtemp8; + u16 eFuse_Addr = 0; + u8 offset, wren; + u16 i, j; + u16 **eFuseWord = NULL; + u16 efuse_utilized = 0; + u8 u1temp = 0; + + efuseTbl = (u8 *)rtw_zmalloc(EFUSE_MAP_LEN_88E); + if (efuseTbl == NULL) { + DBG_88E("%s: alloc efuseTbl fail!\n", __func__); + goto exit; + } + + eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); + if (eFuseWord == NULL) { + DBG_88E("%s: alloc eFuseWord fail!\n", __func__); + goto exit; + } + + /* 0. Refresh efuse init map as all oxFF. */ + for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) + eFuseWord[i][j] = 0xFFFF; + + /* */ + /* 1. Read the first byte to check if efuse is empty!!! */ + /* */ + /* */ + rtemp8 = *(phymap+eFuse_Addr); + if (rtemp8 != 0xFF) { + efuse_utilized++; + eFuse_Addr++; + } else { + DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8); + goto exit; + } + + /* */ + /* 2. Read real efuse content. Filter PG header and every section data. */ + /* */ + while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { + /* Check PG header for section num. */ + if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */ + u1temp = ((rtemp8 & 0xE0) >> 5); + rtemp8 = *(phymap+eFuse_Addr); + if ((rtemp8 & 0x0F) == 0x0F) { + eFuse_Addr++; + rtemp8 = *(phymap+eFuse_Addr); + + if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) + eFuse_Addr++; + continue; + } else { + offset = ((rtemp8 & 0xF0) >> 1) | u1temp; + wren = (rtemp8 & 0x0F); + eFuse_Addr++; + } + } else { + offset = ((rtemp8 >> 4) & 0x0f); + wren = (rtemp8 & 0x0f); + } + + if (offset < EFUSE_MAX_SECTION_88E) { + /* Get word enable value from PG header */ + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + /* Check word enable condition in the section */ + if (!(wren & 0x01)) { + rtemp8 = *(phymap+eFuse_Addr); + eFuse_Addr++; + efuse_utilized++; + eFuseWord[offset][i] = (rtemp8 & 0xff); + if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) + break; + rtemp8 = *(phymap+eFuse_Addr); + eFuse_Addr++; + efuse_utilized++; + eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00); + + if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) + break; + } + wren >>= 1; + } + } + /* Read next PG header */ + rtemp8 = *(phymap+eFuse_Addr); + + if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { + efuse_utilized++; + eFuse_Addr++; + } + } + + /* */ + /* 3. Collect 16 sections and 4 word unit into Efuse map. */ + /* */ + for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { + efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff); + efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff); + } + } + + /* */ + /* 4. Copy from Efuse map to output pointer memory!!! */ + /* */ + for (i = 0; i < _size_byte; i++) + pbuf[i] = efuseTbl[_offset+i]; + + /* */ + /* 5. Calculate Efuse utilization. */ + /* */ + +exit: + kfree(efuseTbl); + + if (eFuseWord) + rtw_mfree2d((void *)eFuseWord, EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); +} + +static void efuse_read_phymap_from_txpktbuf( + struct adapter *adapter, + int bcnhead, /* beacon head, where FW store len(2-byte) and efuse physical map. */ + u8 *content, /* buffer to store efuse physical map */ + u16 *size /* for efuse content: the max byte to read. will update to byte read */ + ) +{ + u16 dbg_addr = 0; + u32 start = 0, passing_time = 0; + u8 reg_0x143 = 0; + u32 lo32 = 0, hi32 = 0; + u16 len = 0, count = 0; + int i = 0; + u16 limit = *size; + + u8 *pos = content; + + if (bcnhead < 0) /* if not valid */ + bcnhead = usb_read8(adapter, REG_TDECTRL+1); + + DBG_88E("%s bcnhead:%d\n", __func__, bcnhead); + + usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); + + dbg_addr = bcnhead*128/8; /* 8-bytes addressing */ + + while (1) { + usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i); + + usb_write8(adapter, REG_TXPKTBUF_DBG, 0); + start = jiffies; + while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) && + (passing_time = rtw_get_passing_time_ms(start)) < 1000) { + DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106)); + msleep(1); + } + + lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L); + hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H); + + if (i == 0) { + u8 lenc[2]; + u16 lenbak, aaabak; + u16 aaa; + lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L); + lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1); + + aaabak = le16_to_cpup((__le16 *)lenc); + lenbak = le16_to_cpu(*((__le16 *)lenc)); + aaa = le16_to_cpup((__le16 *)&lo32); + len = le16_to_cpu(*((__le16 *)&lo32)); + + limit = (len-2 < limit) ? len-2 : limit; + + DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak); + + memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count); + count += (limit >= count+2) ? 2 : limit-count; + pos = content+count; + + } else { + memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count); + count += (limit >= count+4) ? 4 : limit-count; + pos = content+count; + } + + if (limit > count && len-2 > count) { + memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count); + count += (limit >= count+4) ? 4 : limit-count; + pos = content+count; + } + + if (limit <= count || len-2 <= count) + break; + i++; + } + usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS); + DBG_88E("%s read count:%u\n", __func__, count); + *size = count; +} + +static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map) +{ + s32 status = _FAIL; + u8 physical_map[512]; + u16 size = 512; + + usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy); + _rtw_memset(physical_map, 0xFF, 512); + usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); + status = iol_execute(padapter, CMD_READ_EFUSE_MAP); + if (status == _SUCCESS) + efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size); + efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map); + return status; +} + +void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf) +{ + + if (rtw_IOL_applied(Adapter)) { + rtw_hal_power_on(Adapter); + iol_mode_enable(Adapter, 1); + iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf); + iol_mode_enable(Adapter, 0); + } + return; +} + +/* Do not support BT */ +void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut) +{ + switch (type) { + case TYPE_EFUSE_MAX_SECTION: + { + u8 *pMax_section; + pMax_section = (u8 *)pOut; + *pMax_section = EFUSE_MAX_SECTION_88E; + } + break; + case TYPE_EFUSE_REAL_CONTENT_LEN: + { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; + } + break; + case TYPE_EFUSE_CONTENT_LEN_BANK: + { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; + } + break; + case TYPE_AVAILABLE_EFUSE_BYTES_BANK: + { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); + } + break; + case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL: + { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); + } + break; + case TYPE_EFUSE_MAP_LEN: + { + u16 *pu2Tmp; + pu2Tmp = (u16 *)pOut; + *pu2Tmp = (u16)EFUSE_MAP_LEN_88E; + } + break; + case TYPE_EFUSE_PROTECT_BYTES_BANK: + { + u8 *pu1Tmp; + pu1Tmp = (u8 *)pOut; + *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E); + } + break; + default: + { + u8 *pu1Tmp; + pu1Tmp = (u8 *)pOut; + *pu1Tmp = 0; + } + break; + } +} + +u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data) +{ + u16 tmpaddr = 0; + u16 start_addr = efuse_addr; + u8 badworden = 0x0F; + u8 tmpdata[8]; + + _rtw_memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE); + + if (!(word_en&BIT0)) { + tmpaddr = start_addr; + efuse_OneByteWrite(pAdapter, start_addr++, data[0]); + efuse_OneByteWrite(pAdapter, start_addr++, data[1]); + + efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]); + efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]); + if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) + badworden &= (~BIT0); + } + if (!(word_en&BIT1)) { + tmpaddr = start_addr; + efuse_OneByteWrite(pAdapter, start_addr++, data[2]); + efuse_OneByteWrite(pAdapter, start_addr++, data[3]); + + efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]); + efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]); + if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) + badworden &= (~BIT1); + } + if (!(word_en&BIT2)) { + tmpaddr = start_addr; + efuse_OneByteWrite(pAdapter, start_addr++, data[4]); + efuse_OneByteWrite(pAdapter, start_addr++, data[5]); + + efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]); + efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]); + if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) + badworden &= (~BIT2); + } + if (!(word_en&BIT3)) { + tmpaddr = start_addr; + efuse_OneByteWrite(pAdapter, start_addr++, data[6]); + efuse_OneByteWrite(pAdapter, start_addr++, data[7]); + + efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]); + efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]); + if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) + badworden &= (~BIT3); + } + return badworden; +} + +u16 Efuse_GetCurrentSize(struct adapter *pAdapter) +{ + int bContinual = true; + u16 efuse_addr = 0; + u8 hoffset = 0, hworden = 0; + u8 efuse_data, word_cnts = 0; + + rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr); + + while (bContinual && + efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && + AVAILABLE_EFUSE_ADDR(efuse_addr)) { + if (efuse_data != 0xFF) { + if ((efuse_data&0x1F) == 0x0F) { /* extended header */ + hoffset = efuse_data; + efuse_addr++; + efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data); + if ((efuse_data & 0x0F) == 0x0F) { + efuse_addr++; + continue; + } else { + hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + hworden = efuse_data & 0x0F; + } + } else { + hoffset = (efuse_data>>4) & 0x0F; + hworden = efuse_data & 0x0F; + } + word_cnts = Efuse_CalculateWordCnts(hworden); + /* read next header */ + efuse_addr = efuse_addr + (word_cnts*2)+1; + } else { + bContinual = false; + } + } + + rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr); + + return efuse_addr; +} + +int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) +{ + u8 ReadState = PG_STATE_HEADER; + int bContinual = true; + int bDataEmpty = true; + u8 efuse_data, word_cnts = 0; + u16 efuse_addr = 0; + u8 hoffset = 0, hworden = 0; + u8 tmpidx = 0; + u8 tmpdata[8]; + u8 max_section = 0; + u8 tmp_header = 0; + + EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section); + + if (data == NULL) + return false; + if (offset > max_section) + return false; + + _rtw_memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); + _rtw_memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); + + /* Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ + /* Skip dummy parts to prevent unexpected data read from Efuse. */ + /* By pass right now. 2009.02.19. */ + while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) { + /* Header Read ------------- */ + if (ReadState & PG_STATE_HEADER) { + if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) { + if (EXT_HEADER(efuse_data)) { + tmp_header = efuse_data; + efuse_addr++; + efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data); + if (!ALL_WORDS_DISABLED(efuse_data)) { + hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + hworden = efuse_data & 0x0F; + } else { + DBG_88E("Error, All words disabled\n"); + efuse_addr++; + continue; + } + } else { + hoffset = (efuse_data>>4) & 0x0F; + hworden = efuse_data & 0x0F; + } + word_cnts = Efuse_CalculateWordCnts(hworden); + bDataEmpty = true; + + if (hoffset == offset) { + for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) { + if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) { + tmpdata[tmpidx] = efuse_data; + if (efuse_data != 0xff) + bDataEmpty = false; + } + } + if (bDataEmpty == false) { + ReadState = PG_STATE_DATA; + } else {/* read next header */ + efuse_addr = efuse_addr + (word_cnts*2)+1; + ReadState = PG_STATE_HEADER; + } + } else {/* read next header */ + efuse_addr = efuse_addr + (word_cnts*2)+1; + ReadState = PG_STATE_HEADER; + } + } else { + bContinual = false; + } + } else if (ReadState & PG_STATE_DATA) { + /* Data section Read ------------- */ + efuse_WordEnableDataRead(hworden, tmpdata, data); + efuse_addr = efuse_addr + (word_cnts*2)+1; + ReadState = PG_STATE_HEADER; + } + + } + + if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff) && (data[3] == 0xff) && + (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff) && (data[7] == 0xff)) + return false; + else + return true; +} + +static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr) +{ + u8 originaldata[8], badworden = 0; + u16 efuse_addr = *pAddr; + u32 PgWriteSuccess = 0; + + _rtw_memset((void *)originaldata, 0xff, 8); + + if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) { + /* check if data exist */ + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata); + + if (badworden != 0xf) { /* write fail */ + PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata); + + if (!PgWriteSuccess) + return false; + else + efuse_addr = Efuse_GetCurrentSize(pAdapter); + } else { + efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; + } + } else { + efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; + } + *pAddr = efuse_addr; + return true; +} + +static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) +{ + bool bRet = false; + u16 efuse_addr = *pAddr, efuse_max_available_len = 0; + u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0; + u8 repeatcnt = 0; + + EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len); + + while (efuse_addr < efuse_max_available_len) { + pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F; + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); + + while (tmp_header == 0xFF) { + if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) + return false; + + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); + } + + /* to write ext_header */ + if (tmp_header == pg_header) { + efuse_addr++; + pg_header_temp = pg_header; + pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en; + + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); + + while (tmp_header == 0xFF) { + if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) + return false; + + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); + } + + if ((tmp_header & 0x0F) == 0x0F) { /* word_en PG fail */ + if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) { + return false; + } else { + efuse_addr++; + continue; + } + } else if (pg_header != tmp_header) { /* offset PG fail */ + struct pgpkt fixPkt; + fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1); + fixPkt.word_en = tmp_header & 0x0F; + fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); + if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) + return false; + } else { + bRet = true; + break; + } + } else if ((tmp_header & 0x1F) == 0x0F) { /* wrong extended header */ + efuse_addr += 2; + continue; + } + } + + *pAddr = efuse_addr; + return bRet; +} + +static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) +{ + bool bRet = false; + u8 pg_header = 0, tmp_header = 0; + u16 efuse_addr = *pAddr; + u8 repeatcnt = 0; + + pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en; + + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); + + while (tmp_header == 0xFF) { + if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) + return false; + efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); + efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); + } + + if (pg_header == tmp_header) { + bRet = true; + } else { + struct pgpkt fixPkt; + fixPkt.offset = (tmp_header>>4) & 0x0F; + fixPkt.word_en = tmp_header & 0x0F; + fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); + if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) + return false; + } + + *pAddr = efuse_addr; + return bRet; +} + +static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) +{ + u16 efuse_addr = *pAddr; + u8 badworden = 0; + u32 PgWriteSuccess = 0; + + badworden = 0x0f; + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data); + if (badworden == 0x0F) { + /* write ok */ + return true; + } else { + /* reorganize other pg packet */ + PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data); + if (!PgWriteSuccess) + return false; + else + return true; + } +} + +static bool +hal_EfusePgPacketWriteHeader( + struct adapter *pAdapter, + u8 efuseType, + u16 *pAddr, + struct pgpkt *pTargetPkt) +{ + bool bRet = false; + + if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) + bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt); + else + bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt); + + return bRet; +} + +static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt, + u8 *pWden) +{ + u8 match_word_en = 0x0F; /* default all words are disabled */ + + /* check if the same words are enabled both target and current PG packet */ + if (((pTargetPkt->word_en & BIT0) == 0) && + ((pCurPkt->word_en & BIT0) == 0)) + match_word_en &= ~BIT0; /* enable word 0 */ + if (((pTargetPkt->word_en & BIT1) == 0) && + ((pCurPkt->word_en & BIT1) == 0)) + match_word_en &= ~BIT1; /* enable word 1 */ + if (((pTargetPkt->word_en & BIT2) == 0) && + ((pCurPkt->word_en & BIT2) == 0)) + match_word_en &= ~BIT2; /* enable word 2 */ + if (((pTargetPkt->word_en & BIT3) == 0) && + ((pCurPkt->word_en & BIT3) == 0)) + match_word_en &= ~BIT3; /* enable word 3 */ + + *pWden = match_word_en; + + if (match_word_en != 0xf) + return true; + else + return false; +} + +static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr) +{ + bool bRet = false; + u8 i, efuse_data; + + for (i = 0; i < (word_cnts*2); i++) { + if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF)) + bRet = true; + } + return bRet; +} + +static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) +{ + bool bRet = false; + u8 i, efuse_data = 0, cur_header = 0; + u8 matched_wden = 0, badworden = 0; + u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0; + struct pgpkt curPkt; + + EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len); + EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max); + + rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr); + startAddr %= EFUSE_REAL_CONTENT_LEN; + + while (1) { + if (startAddr >= efuse_max_available_len) { + bRet = false; + break; + } + + if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) { + if (EXT_HEADER(efuse_data)) { + cur_header = efuse_data; + startAddr++; + efuse_OneByteRead(pAdapter, startAddr, &efuse_data); + if (ALL_WORDS_DISABLED(efuse_data)) { + bRet = false; + break; + } else { + curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + curPkt.word_en = efuse_data & 0x0F; + } + } else { + cur_header = efuse_data; + curPkt.offset = (cur_header>>4) & 0x0F; + curPkt.word_en = cur_header & 0x0F; + } + + curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en); + /* if same header is found but no data followed */ + /* write some part of data followed by the header. */ + if ((curPkt.offset == pTargetPkt->offset) && + (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) && + wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) { + /* Here to write partial data */ + badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data); + if (badworden != 0x0F) { + u32 PgWriteSuccess = 0; + /* if write fail on some words, write these bad words again */ + + PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data); + + if (!PgWriteSuccess) { + bRet = false; /* write fail, return */ + break; + } + } + /* partial write ok, update the target packet for later use */ + for (i = 0; i < 4; i++) { + if ((matched_wden & (0x1<word_en |= (0x1<word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); + } + /* read from next header */ + startAddr = startAddr + (curPkt.word_cnts*2) + 1; + } else { + /* not used header, 0xff */ + *pAddr = startAddr; + bRet = true; + break; + } + } + return bRet; +} + +static bool +hal_EfusePgCheckAvailableAddr( + struct adapter *pAdapter, + u8 efuseType + ) +{ + u16 efuse_max_available_len = 0; + + /* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */ + EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len); + + if (Efuse_GetCurrentSize(pAdapter) >= efuse_max_available_len) + return false; + return true; +} + +static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt) +{ + _rtw_memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8); + pTargetPkt->offset = offset; + pTargetPkt->word_en = word_en; + efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data); + pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); +} + +bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData) +{ + struct pgpkt targetPkt; + u16 startAddr = 0; + u8 efuseType = EFUSE_WIFI; + + if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType)) + return false; + + hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); + + if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt)) + return false; + + if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt)) + return false; + + if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt)) + return false; + + return true; +} + u8 Efuse_CalculateWordCnts(u8 word_en) { u8 word_cnts = 0; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 10ff404dc04a..7ea0320c9141 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -30,7 +30,7 @@ #include -static void iol_mode_enable(struct adapter *padapter, u8 enable) +void iol_mode_enable(struct adapter *padapter, u8 enable) { u8 reg_0xf0 = 0; @@ -51,7 +51,7 @@ static void iol_mode_enable(struct adapter *padapter, u8 enable) } } -static s32 iol_execute(struct adapter *padapter, u8 control) +s32 iol_execute(struct adapter *padapter, u8 control) { s32 status = _FAIL; u8 reg_0x88 = 0; @@ -84,227 +84,6 @@ static s32 iol_InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy) return rst; } -static void -efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) -{ - u8 *efuseTbl = NULL; - u8 rtemp8; - u16 eFuse_Addr = 0; - u8 offset, wren; - u16 i, j; - u16 **eFuseWord = NULL; - u16 efuse_utilized = 0; - u8 u1temp = 0; - - efuseTbl = (u8 *)rtw_zmalloc(EFUSE_MAP_LEN_88E); - if (efuseTbl == NULL) { - DBG_88E("%s: alloc efuseTbl fail!\n", __func__); - goto exit; - } - - eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); - if (eFuseWord == NULL) { - DBG_88E("%s: alloc eFuseWord fail!\n", __func__); - goto exit; - } - - /* 0. Refresh efuse init map as all oxFF. */ - for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) - eFuseWord[i][j] = 0xFFFF; - - /* */ - /* 1. Read the first byte to check if efuse is empty!!! */ - /* */ - /* */ - rtemp8 = *(phymap+eFuse_Addr); - if (rtemp8 != 0xFF) { - efuse_utilized++; - eFuse_Addr++; - } else { - DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8); - goto exit; - } - - /* */ - /* 2. Read real efuse content. Filter PG header and every section data. */ - /* */ - while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { - /* Check PG header for section num. */ - if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */ - u1temp = ((rtemp8 & 0xE0) >> 5); - rtemp8 = *(phymap+eFuse_Addr); - if ((rtemp8 & 0x0F) == 0x0F) { - eFuse_Addr++; - rtemp8 = *(phymap+eFuse_Addr); - - if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) - eFuse_Addr++; - continue; - } else { - offset = ((rtemp8 & 0xF0) >> 1) | u1temp; - wren = (rtemp8 & 0x0F); - eFuse_Addr++; - } - } else { - offset = ((rtemp8 >> 4) & 0x0f); - wren = (rtemp8 & 0x0f); - } - - if (offset < EFUSE_MAX_SECTION_88E) { - /* Get word enable value from PG header */ - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - /* Check word enable condition in the section */ - if (!(wren & 0x01)) { - rtemp8 = *(phymap+eFuse_Addr); - eFuse_Addr++; - efuse_utilized++; - eFuseWord[offset][i] = (rtemp8 & 0xff); - if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) - break; - rtemp8 = *(phymap+eFuse_Addr); - eFuse_Addr++; - efuse_utilized++; - eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00); - - if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) - break; - } - wren >>= 1; - } - } - /* Read next PG header */ - rtemp8 = *(phymap+eFuse_Addr); - - if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { - efuse_utilized++; - eFuse_Addr++; - } - } - - /* */ - /* 3. Collect 16 sections and 4 word unit into Efuse map. */ - /* */ - for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { - efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff); - efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff); - } - } - - /* */ - /* 4. Copy from Efuse map to output pointer memory!!! */ - /* */ - for (i = 0; i < _size_byte; i++) - pbuf[i] = efuseTbl[_offset+i]; - - /* */ - /* 5. Calculate Efuse utilization. */ - /* */ - -exit: - kfree(efuseTbl); - - if (eFuseWord) - rtw_mfree2d((void *)eFuseWord, EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16)); -} - -static void efuse_read_phymap_from_txpktbuf( - struct adapter *adapter, - int bcnhead, /* beacon head, where FW store len(2-byte) and efuse physical map. */ - u8 *content, /* buffer to store efuse physical map */ - u16 *size /* for efuse content: the max byte to read. will update to byte read */ - ) -{ - u16 dbg_addr = 0; - u32 start = 0, passing_time = 0; - u8 reg_0x143 = 0; - u32 lo32 = 0, hi32 = 0; - u16 len = 0, count = 0; - int i = 0; - u16 limit = *size; - - u8 *pos = content; - - if (bcnhead < 0) /* if not valid */ - bcnhead = usb_read8(adapter, REG_TDECTRL+1); - - DBG_88E("%s bcnhead:%d\n", __func__, bcnhead); - - usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); - - dbg_addr = bcnhead*128/8; /* 8-bytes addressing */ - - while (1) { - usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i); - - usb_write8(adapter, REG_TXPKTBUF_DBG, 0); - start = jiffies; - while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) && - (passing_time = rtw_get_passing_time_ms(start)) < 1000) { - DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106)); - msleep(1); - } - - lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L); - hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H); - - if (i == 0) { - u8 lenc[2]; - u16 lenbak, aaabak; - u16 aaa; - lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L); - lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1); - - aaabak = le16_to_cpup((__le16 *)lenc); - lenbak = le16_to_cpu(*((__le16 *)lenc)); - aaa = le16_to_cpup((__le16 *)&lo32); - len = le16_to_cpu(*((__le16 *)&lo32)); - - limit = (len-2 < limit) ? len-2 : limit; - - DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak); - - memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count); - count += (limit >= count+2) ? 2 : limit-count; - pos = content+count; - - } else { - memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count); - count += (limit >= count+4) ? 4 : limit-count; - pos = content+count; - } - - if (limit > count && len-2 > count) { - memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count); - count += (limit >= count+4) ? 4 : limit-count; - pos = content+count; - } - - if (limit <= count || len-2 <= count) - break; - i++; - } - usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS); - DBG_88E("%s read count:%u\n", __func__, count); - *size = count; -} - -static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map) -{ - s32 status = _FAIL; - u8 physical_map[512]; - u16 size = 512; - - usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy); - _rtw_memset(physical_map, 0xFF, 512); - usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); - status = iol_execute(padapter, CMD_READ_EFUSE_MAP); - if (status == _SUCCESS) - efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size); - efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map); - return status; -} s32 rtl8188e_iol_efuse_patch(struct adapter *padapter) { @@ -720,656 +499,6 @@ static void rtl8188e_free_hal_data(struct adapter *padapter) padapter->HalData = NULL; } -/* */ -/* Efuse related code */ -/* */ -enum{ - VOLTAGE_V25 = 0x03, - LDOE25_SHIFT = 28 , - }; - -/* - * Function: Efuse_PowerSwitch - * - * Overview: When we want to enable write operation, we should change to - * pwr on state. When we stop write, we should switch to 500k mode - * and disable LDO 2.5V. - */ - -void Efuse_PowerSwitch( - struct adapter *pAdapter, - u8 bWrite, - u8 PwrState) -{ - u8 tempval; - u16 tmpV16; - - if (PwrState) { - usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); - - /* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */ - tmpV16 = usb_read16(pAdapter, REG_SYS_ISO_CTRL); - if (!(tmpV16 & PWC_EV12V)) { - tmpV16 |= PWC_EV12V; - usb_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16); - } - /* Reset: 0x0000h[28], default valid */ - tmpV16 = usb_read16(pAdapter, REG_SYS_FUNC_EN); - if (!(tmpV16 & FEN_ELDR)) { - tmpV16 |= FEN_ELDR; - usb_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16); - } - - /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */ - tmpV16 = usb_read16(pAdapter, REG_SYS_CLKR); - if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) { - tmpV16 |= (LOADER_CLK_EN | ANA8M); - usb_write16(pAdapter, REG_SYS_CLKR, tmpV16); - } - - if (bWrite) { - /* Enable LDO 2.5V before read/write action */ - tempval = usb_read8(pAdapter, EFUSE_TEST+3); - tempval &= 0x0F; - tempval |= (VOLTAGE_V25 << 4); - usb_write8(pAdapter, EFUSE_TEST+3, (tempval | 0x80)); - } - } else { - usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); - - if (bWrite) { - /* Disable LDO 2.5V after read/write action */ - tempval = usb_read8(pAdapter, EFUSE_TEST+3); - usb_write8(pAdapter, EFUSE_TEST+3, (tempval & 0x7F)); - } - } -} - -void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf) -{ - - if (rtw_IOL_applied(Adapter)) { - rtw_hal_power_on(Adapter); - iol_mode_enable(Adapter, 1); - iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf); - iol_mode_enable(Adapter, 0); - } - return; -} - -/* Do not support BT */ -void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut) -{ - switch (type) { - case TYPE_EFUSE_MAX_SECTION: - { - u8 *pMax_section; - pMax_section = (u8 *)pOut; - *pMax_section = EFUSE_MAX_SECTION_88E; - } - break; - case TYPE_EFUSE_REAL_CONTENT_LEN: - { - u16 *pu2Tmp; - pu2Tmp = (u16 *)pOut; - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; - } - break; - case TYPE_EFUSE_CONTENT_LEN_BANK: - { - u16 *pu2Tmp; - pu2Tmp = (u16 *)pOut; - *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E; - } - break; - case TYPE_AVAILABLE_EFUSE_BYTES_BANK: - { - u16 *pu2Tmp; - pu2Tmp = (u16 *)pOut; - *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); - } - break; - case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL: - { - u16 *pu2Tmp; - pu2Tmp = (u16 *)pOut; - *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E); - } - break; - case TYPE_EFUSE_MAP_LEN: - { - u16 *pu2Tmp; - pu2Tmp = (u16 *)pOut; - *pu2Tmp = (u16)EFUSE_MAP_LEN_88E; - } - break; - case TYPE_EFUSE_PROTECT_BYTES_BANK: - { - u8 *pu1Tmp; - pu1Tmp = (u8 *)pOut; - *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E); - } - break; - default: - { - u8 *pu1Tmp; - pu1Tmp = (u8 *)pOut; - *pu1Tmp = 0; - } - break; - } -} - -u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data) -{ - u16 tmpaddr = 0; - u16 start_addr = efuse_addr; - u8 badworden = 0x0F; - u8 tmpdata[8]; - - _rtw_memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE); - - if (!(word_en&BIT0)) { - tmpaddr = start_addr; - efuse_OneByteWrite(pAdapter, start_addr++, data[0]); - efuse_OneByteWrite(pAdapter, start_addr++, data[1]); - - efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]); - if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) - badworden &= (~BIT0); - } - if (!(word_en&BIT1)) { - tmpaddr = start_addr; - efuse_OneByteWrite(pAdapter, start_addr++, data[2]); - efuse_OneByteWrite(pAdapter, start_addr++, data[3]); - - efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]); - if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) - badworden &= (~BIT1); - } - if (!(word_en&BIT2)) { - tmpaddr = start_addr; - efuse_OneByteWrite(pAdapter, start_addr++, data[4]); - efuse_OneByteWrite(pAdapter, start_addr++, data[5]); - - efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]); - if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) - badworden &= (~BIT2); - } - if (!(word_en&BIT3)) { - tmpaddr = start_addr; - efuse_OneByteWrite(pAdapter, start_addr++, data[6]); - efuse_OneByteWrite(pAdapter, start_addr++, data[7]); - - efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]); - if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) - badworden &= (~BIT3); - } - return badworden; -} - -u16 Efuse_GetCurrentSize(struct adapter *pAdapter) -{ - int bContinual = true; - u16 efuse_addr = 0; - u8 hoffset = 0, hworden = 0; - u8 efuse_data, word_cnts = 0; - - rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr); - - while (bContinual && - efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && - AVAILABLE_EFUSE_ADDR(efuse_addr)) { - if (efuse_data != 0xFF) { - if ((efuse_data&0x1F) == 0x0F) { /* extended header */ - hoffset = efuse_data; - efuse_addr++; - efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data); - if ((efuse_data & 0x0F) == 0x0F) { - efuse_addr++; - continue; - } else { - hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); - hworden = efuse_data & 0x0F; - } - } else { - hoffset = (efuse_data>>4) & 0x0F; - hworden = efuse_data & 0x0F; - } - word_cnts = Efuse_CalculateWordCnts(hworden); - /* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; - } else { - bContinual = false; - } - } - - rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr); - - return efuse_addr; -} - -int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) -{ - u8 ReadState = PG_STATE_HEADER; - int bContinual = true; - int bDataEmpty = true; - u8 efuse_data, word_cnts = 0; - u16 efuse_addr = 0; - u8 hoffset = 0, hworden = 0; - u8 tmpidx = 0; - u8 tmpdata[8]; - u8 max_section = 0; - u8 tmp_header = 0; - - EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section); - - if (data == NULL) - return false; - if (offset > max_section) - return false; - - _rtw_memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); - _rtw_memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); - - /* Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ - /* Skip dummy parts to prevent unexpected data read from Efuse. */ - /* By pass right now. 2009.02.19. */ - while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) { - /* Header Read ------------- */ - if (ReadState & PG_STATE_HEADER) { - if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) { - if (EXT_HEADER(efuse_data)) { - tmp_header = efuse_data; - efuse_addr++; - efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data); - if (!ALL_WORDS_DISABLED(efuse_data)) { - hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); - hworden = efuse_data & 0x0F; - } else { - DBG_88E("Error, All words disabled\n"); - efuse_addr++; - continue; - } - } else { - hoffset = (efuse_data>>4) & 0x0F; - hworden = efuse_data & 0x0F; - } - word_cnts = Efuse_CalculateWordCnts(hworden); - bDataEmpty = true; - - if (hoffset == offset) { - for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) { - if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) { - tmpdata[tmpidx] = efuse_data; - if (efuse_data != 0xff) - bDataEmpty = false; - } - } - if (bDataEmpty == false) { - ReadState = PG_STATE_DATA; - } else {/* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; - ReadState = PG_STATE_HEADER; - } - } else {/* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; - ReadState = PG_STATE_HEADER; - } - } else { - bContinual = false; - } - } else if (ReadState & PG_STATE_DATA) { - /* Data section Read ------------- */ - efuse_WordEnableDataRead(hworden, tmpdata, data); - efuse_addr = efuse_addr + (word_cnts*2)+1; - ReadState = PG_STATE_HEADER; - } - - } - - if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff) && (data[3] == 0xff) && - (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff) && (data[7] == 0xff)) - return false; - else - return true; -} - -static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr) -{ - u8 originaldata[8], badworden = 0; - u16 efuse_addr = *pAddr; - u32 PgWriteSuccess = 0; - - _rtw_memset((void *)originaldata, 0xff, 8); - - if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) { - /* check if data exist */ - badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata); - - if (badworden != 0xf) { /* write fail */ - PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata); - - if (!PgWriteSuccess) - return false; - else - efuse_addr = Efuse_GetCurrentSize(pAdapter); - } else { - efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; - } - } else { - efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; - } - *pAddr = efuse_addr; - return true; -} - -static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) -{ - bool bRet = false; - u16 efuse_addr = *pAddr, efuse_max_available_len = 0; - u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0; - u8 repeatcnt = 0; - - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len); - - while (efuse_addr < efuse_max_available_len) { - pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F; - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); - efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); - - while (tmp_header == 0xFF) { - if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) - return false; - - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); - efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); - } - - /* to write ext_header */ - if (tmp_header == pg_header) { - efuse_addr++; - pg_header_temp = pg_header; - pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en; - - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); - efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); - - while (tmp_header == 0xFF) { - if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) - return false; - - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); - efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); - } - - if ((tmp_header & 0x0F) == 0x0F) { /* word_en PG fail */ - if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) { - return false; - } else { - efuse_addr++; - continue; - } - } else if (pg_header != tmp_header) { /* offset PG fail */ - struct pgpkt fixPkt; - fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1); - fixPkt.word_en = tmp_header & 0x0F; - fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); - if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) - return false; - } else { - bRet = true; - break; - } - } else if ((tmp_header & 0x1F) == 0x0F) { /* wrong extended header */ - efuse_addr += 2; - continue; - } - } - - *pAddr = efuse_addr; - return bRet; -} - -static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) -{ - bool bRet = false; - u8 pg_header = 0, tmp_header = 0; - u16 efuse_addr = *pAddr; - u8 repeatcnt = 0; - - pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en; - - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); - efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); - - while (tmp_header == 0xFF) { - if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) - return false; - efuse_OneByteWrite(pAdapter, efuse_addr, pg_header); - efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header); - } - - if (pg_header == tmp_header) { - bRet = true; - } else { - struct pgpkt fixPkt; - fixPkt.offset = (tmp_header>>4) & 0x0F; - fixPkt.word_en = tmp_header & 0x0F; - fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); - if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) - return false; - } - - *pAddr = efuse_addr; - return bRet; -} - -static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) -{ - u16 efuse_addr = *pAddr; - u8 badworden = 0; - u32 PgWriteSuccess = 0; - - badworden = 0x0f; - badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data); - if (badworden == 0x0F) { - /* write ok */ - return true; - } else { - /* reorganize other pg packet */ - PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data); - if (!PgWriteSuccess) - return false; - else - return true; - } -} - -static bool -hal_EfusePgPacketWriteHeader( - struct adapter *pAdapter, - u8 efuseType, - u16 *pAddr, - struct pgpkt *pTargetPkt) -{ - bool bRet = false; - - if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) - bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt); - else - bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt); - - return bRet; -} - -static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt, - u8 *pWden) -{ - u8 match_word_en = 0x0F; /* default all words are disabled */ - - /* check if the same words are enabled both target and current PG packet */ - if (((pTargetPkt->word_en & BIT0) == 0) && - ((pCurPkt->word_en & BIT0) == 0)) - match_word_en &= ~BIT0; /* enable word 0 */ - if (((pTargetPkt->word_en & BIT1) == 0) && - ((pCurPkt->word_en & BIT1) == 0)) - match_word_en &= ~BIT1; /* enable word 1 */ - if (((pTargetPkt->word_en & BIT2) == 0) && - ((pCurPkt->word_en & BIT2) == 0)) - match_word_en &= ~BIT2; /* enable word 2 */ - if (((pTargetPkt->word_en & BIT3) == 0) && - ((pCurPkt->word_en & BIT3) == 0)) - match_word_en &= ~BIT3; /* enable word 3 */ - - *pWden = match_word_en; - - if (match_word_en != 0xf) - return true; - else - return false; -} - -static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr) -{ - bool bRet = false; - u8 i, efuse_data; - - for (i = 0; i < (word_cnts*2); i++) { - if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF)) - bRet = true; - } - return bRet; -} - -static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt) -{ - bool bRet = false; - u8 i, efuse_data = 0, cur_header = 0; - u8 matched_wden = 0, badworden = 0; - u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0; - struct pgpkt curPkt; - - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len); - EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max); - - rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr); - startAddr %= EFUSE_REAL_CONTENT_LEN; - - while (1) { - if (startAddr >= efuse_max_available_len) { - bRet = false; - break; - } - - if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) { - if (EXT_HEADER(efuse_data)) { - cur_header = efuse_data; - startAddr++; - efuse_OneByteRead(pAdapter, startAddr, &efuse_data); - if (ALL_WORDS_DISABLED(efuse_data)) { - bRet = false; - break; - } else { - curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); - curPkt.word_en = efuse_data & 0x0F; - } - } else { - cur_header = efuse_data; - curPkt.offset = (cur_header>>4) & 0x0F; - curPkt.word_en = cur_header & 0x0F; - } - - curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en); - /* if same header is found but no data followed */ - /* write some part of data followed by the header. */ - if ((curPkt.offset == pTargetPkt->offset) && - (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) && - wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) { - /* Here to write partial data */ - badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data); - if (badworden != 0x0F) { - u32 PgWriteSuccess = 0; - /* if write fail on some words, write these bad words again */ - - PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data); - - if (!PgWriteSuccess) { - bRet = false; /* write fail, return */ - break; - } - } - /* partial write ok, update the target packet for later use */ - for (i = 0; i < 4; i++) { - if ((matched_wden & (0x1<word_en |= (0x1<word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); - } - /* read from next header */ - startAddr = startAddr + (curPkt.word_cnts*2) + 1; - } else { - /* not used header, 0xff */ - *pAddr = startAddr; - bRet = true; - break; - } - } - return bRet; -} - -static bool -hal_EfusePgCheckAvailableAddr( - struct adapter *pAdapter, - u8 efuseType - ) -{ - u16 efuse_max_available_len = 0; - - /* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */ - EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len); - - if (Efuse_GetCurrentSize(pAdapter) >= efuse_max_available_len) - return false; - return true; -} - -static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt) -{ - _rtw_memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8); - pTargetPkt->offset = offset; - pTargetPkt->word_en = word_en; - efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data); - pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); -} - -bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData) -{ - struct pgpkt targetPkt; - u16 startAddr = 0; - u8 efuseType = EFUSE_WIFI; - - if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType)) - return false; - - hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); - - if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt)) - return false; - - if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt)) - return false; - - if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt)) - return false; - - return true; -} - static struct HAL_VERSION ReadChipVersion8188E(struct adapter *padapter) { u32 value32; diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 4b59c8e392a9..94a5f93af49b 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -467,6 +467,8 @@ void rtl8188e_start_thread(struct adapter *padapter); void rtl8188e_stop_thread(struct adapter *padapter); void rtw_IOL_cmd_tx_pkt_buf_dump(struct adapter *Adapter, int len); +s32 iol_execute(struct adapter *padapter, u8 control); +void iol_mode_enable(struct adapter *padapter, u8 enable); s32 rtl8188e_iol_efuse_patch(struct adapter *padapter); void rtw_cancel_all_timer(struct adapter *padapter);