diff options
Diffstat (limited to 'drivers/net/wireless/rtlwifi/efuse.c')
| -rw-r--r-- | drivers/net/wireless/rtlwifi/efuse.c | 146 |
1 files changed, 87 insertions, 59 deletions
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index ed1058b7158..2ffc7298f68 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009-2010 Realtek Corporation. + * Copyright(c) 2009-2012 Realtek Corporation. * * Tmis program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -35,8 +35,6 @@ static const u8 MAX_PGPKT_SIZE = 9; static const u8 PGPKT_DATA_SIZE = 8; static const int EFUSE_MAX_SIZE = 512; -static const u8 EFUSE_OOB_PROTECT_BYTES = 15; - static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { {0, 0, 0, 2}, {0, 1, 0, 2}, @@ -162,8 +160,8 @@ void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) const u32 efuse_len = rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("Addr=%x Data =%x\n", address, value)); + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "Addr=%x Data =%x\n", + address, value); if (address < efuse_len) { rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value); @@ -231,6 +229,7 @@ void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) *pbuf = (u8) (value32 & 0xff); } +EXPORT_SYMBOL_GPL(read_efuse_byte); void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) { @@ -240,6 +239,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) u8 rtemp8[1]; u16 efuse_addr = 0; u8 offset, wren; + u8 u1temp = 0; u16 i; u16 j; const u16 efuse_max_section = @@ -252,8 +252,8 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) { RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("read_efuse(): Invalid offset(%#x) with read " - "bytes(%#x)!!\n", _offset, _size_byte)); + "read_efuse(): Invalid offset(%#x) with read bytes(%#x)!!\n", + _offset, _size_byte); return; } @@ -262,9 +262,9 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) sizeof(u8), GFP_ATOMIC); if (!efuse_tbl) return; - efuse_word = kmalloc(EFUSE_MAX_WORD_UNIT * sizeof(u16 *), GFP_ATOMIC); + efuse_word = kzalloc(EFUSE_MAX_WORD_UNIT * sizeof(u16 *), GFP_ATOMIC); if (!efuse_word) - goto done; + goto out; for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { efuse_word[i] = kmalloc(efuse_max_section * sizeof(u16), GFP_ATOMIC); @@ -280,23 +280,44 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) if (*rtemp8 != 0xFF) { efuse_utilized++; RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, - ("Addr=%d\n", efuse_addr)); + "Addr=%d\n", efuse_addr); efuse_addr++; } while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { - offset = ((*rtemp8 >> 4) & 0x0f); + /* Check PG header for section num. */ + if ((*rtemp8 & 0x1F) == 0x0F) {/* extended header */ + u1temp = ((*rtemp8 & 0xE0) >> 5); + read_efuse_byte(hw, efuse_addr, rtemp8); - if (offset < efuse_max_section) { + if ((*rtemp8 & 0x0F) == 0x0F) { + efuse_addr++; + read_efuse_byte(hw, efuse_addr, rtemp8); + + if (*rtemp8 != 0xFF && + (efuse_addr < efuse_len)) { + 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) { RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, - ("offset-%d Worden=%x\n", offset, wren)); + "offset-%d Worden=%x\n", offset, wren); for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { if (!(wren & 0x01)) { RTPRINT(rtlpriv, FEEPROM, - EFUSE_READ_ALL, ("Addr=%d\n", - efuse_addr)); + EFUSE_READ_ALL, + "Addr=%d\n", efuse_addr); read_efuse_byte(hw, efuse_addr, rtemp8); efuse_addr++; @@ -308,8 +329,8 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) break; RTPRINT(rtlpriv, FEEPROM, - EFUSE_READ_ALL, ("Addr=%d\n", - efuse_addr)); + EFUSE_READ_ALL, + "Addr=%d\n", efuse_addr); read_efuse_byte(hw, efuse_addr, rtemp8); efuse_addr++; @@ -326,7 +347,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) } RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, - ("Addr=%d\n", efuse_addr)); + "Addr=%d\n", efuse_addr); read_efuse_byte(hw, efuse_addr, rtemp8); if (*rtemp8 != 0xFF && (efuse_addr < efuse_len)) { efuse_utilized++; @@ -352,11 +373,12 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_utilized); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_USAGE, - (u8 *)&efuse_usage); + &efuse_usage); done: for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) kfree(efuse_word[i]); kfree(efuse_word); +out: kfree(efuse_tbl); } @@ -391,13 +413,13 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) efuse_used = rtlefuse->efuse_usedbytes; if ((totalbytes + efuse_used) >= - (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) + (EFUSE_MAX_SIZE - + rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) result = false; RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("efuse_shadow_update_chk(): totalbytes(%#x), " - "hdr_num(%#x), words_need(%#x), efuse_used(%d)\n", - totalbytes, hdr_num, words_need, efuse_used)); + "efuse_shadow_update_chk(): totalbytes(%#x), hdr_num(%#x), words_need(%#x), efuse_used(%d)\n", + totalbytes, hdr_num, words_need, efuse_used); return result; } @@ -410,7 +432,7 @@ void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, else if (type == 2) efuse_shadow_read_2byte(hw, offset, (u16 *) value); else if (type == 4) - efuse_shadow_read_4byte(hw, offset, (u32 *) value); + efuse_shadow_read_4byte(hw, offset, value); } @@ -434,7 +456,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw) u8 word_en = 0x0F; u8 first_pg = false; - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("--->\n")); + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "--->\n"); if (!efuse_shadow_update_chk(hw)) { efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); @@ -443,7 +465,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw) rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("<---efuse out of capacity!!\n")); + "<---efuse out of capacity!!\n"); return false; } efuse_power_switch(hw, true, true); @@ -478,12 +500,12 @@ bool efuse_shadow_update(struct ieee80211_hw *hw) &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base], 8); RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, - ("U-efuse\n"), tmpdata, 8); + "U-efuse", tmpdata, 8); if (!efuse_pg_packet_write(hw, (u8) offset, word_en, tmpdata)) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - ("PG section(%#x) fail!!\n", offset)); + "PG section(%#x) fail!!\n", offset); break; } } @@ -497,7 +519,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw) &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("<---\n")); + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "<---\n"); return true; } @@ -634,8 +656,8 @@ static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) struct rtl_priv *rtlpriv = rtl_priv(hw); u8 tmpidx = 0; - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("Addr = %x Data=%x\n", addr, data)); + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "Addr = %x Data=%x\n", + addr, data); rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, (u8) (addr & 0xff)); @@ -778,7 +800,7 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, dataempty = false; } - if (dataempty == false) { + if (!dataempty) { *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; *write_state = PG_STATE_HEADER; } else { @@ -851,7 +873,7 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, } } } - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse PG_STATE_HEADER-1\n")); + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse PG_STATE_HEADER-1\n"); } static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, @@ -916,7 +938,7 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, } RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - ("efuse PG_STATE_HEADER-2\n")); + "efuse PG_STATE_HEADER-2\n"); } } @@ -933,10 +955,10 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, u8 badworden = 0x0F; static int repeat_times; - if (efuse_get_current_size(hw) >= - (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { + if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE - + rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - ("efuse_pg_packet_write error\n")); + "efuse_pg_packet_write error\n"); return false; } @@ -948,15 +970,15 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, efuse_word_enable_data_read(word_en, data, target_pkt.data); target_word_cnts = efuse_calculate_word_cnts(target_pkt.word_en); - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, ("efuse Power ON\n")); + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n"); - while (continual && (efuse_addr < - (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) { + while (continual && (efuse_addr < (EFUSE_MAX_SIZE - + rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) { if (write_state == PG_STATE_HEADER) { badworden = 0x0F; RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - ("efuse PG_STATE_HEADER\n")); + "efuse PG_STATE_HEADER\n"); if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) @@ -976,7 +998,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, } else if (write_state == PG_STATE_DATA) { RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - ("efuse PG_STATE_DATA\n")); + "efuse PG_STATE_DATA\n"); badworden = efuse_word_enable_data_write(hw, efuse_addr + 1, target_pkt.word_en, @@ -999,14 +1021,15 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, result = false; } RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - ("efuse PG_STATE_HEADER-3\n")); + "efuse PG_STATE_HEADER-3\n"); } } } - if (efuse_addr >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) { + if (efuse_addr >= (EFUSE_MAX_SIZE - + rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("efuse_addr(%#x) Out of size!!\n", efuse_addr)); + "efuse_addr(%#x) Out of size!!\n", efuse_addr); } return true; @@ -1046,8 +1069,8 @@ static u8 efuse_word_enable_data_write(struct ieee80211_hw *hw, u8 tmpdata[8]; memset(tmpdata, 0xff, PGPKT_DATA_SIZE); - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - ("word_en = %x efuse_addr=%x\n", word_en, efuse_addr)); + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "word_en = %x efuse_addr=%x\n", + word_en, efuse_addr); if (!(word_en & BIT(0))) { tmpaddr = start_addr; @@ -1103,8 +1126,11 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) u8 tempval; u16 tmpV16; - if (pwrstate && (rtlhal->hw_type != - HARDWARE_TYPE_RTL8192SE)) { + if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE) + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], + 0x69); + tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL]); if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { @@ -1154,6 +1180,10 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) } } else { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE) + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_ACCESS], 0); + if (write) { tempval = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + @@ -1174,20 +1204,18 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) static u16 efuse_get_current_size(struct ieee80211_hw *hw) { - int continual = true; u16 efuse_addr = 0; u8 hworden; u8 efuse_data, word_cnts; - while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) - && (efuse_addr < EFUSE_MAX_SIZE)) { - if (efuse_data != 0xFF) { - hworden = efuse_data & 0x0F; - word_cnts = efuse_calculate_word_cnts(hworden); - efuse_addr = efuse_addr + (word_cnts * 2) + 1; - } else { - continual = false; - } + while (efuse_one_byte_read(hw, efuse_addr, &efuse_data) && + efuse_addr < EFUSE_MAX_SIZE) { + if (efuse_data == 0xFF) + break; + + hworden = efuse_data & 0x0F; + word_cnts = efuse_calculate_word_cnts(hworden); + efuse_addr = efuse_addr + (word_cnts * 2) + 1; } return efuse_addr; |
