Skip to content

Commit

Permalink
rtlwifi: rtl8723ae: rtl8723-common: Copy common firmware code
Browse files Browse the repository at this point in the history
The drivers for RTL8723AE and RTL8723BE have some code in common.
This commit copies the common firmware routines into the shared
code.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Larry Finger authored and John W. Linville committed Mar 4, 2014
1 parent 0a168b4 commit cbd0c85
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 805 deletions.
5 changes: 0 additions & 5 deletions drivers/net/wireless/rtlwifi/rtl8723ae/def.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@
#define E_CUT_VERSION BIT(14)
#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28))

enum version_8723e {
VERSION_TEST_UMC_CHIP_8723 = 0x0081,
VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT = 0x0089,
VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT = 0x1089,
};

/* MASK */
#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2))
Expand Down
260 changes: 22 additions & 238 deletions drivers/net/wireless/rtlwifi/rtl8723ae/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,199 +34,7 @@
#include "reg.h"
#include "def.h"
#include "fw.h"

static void _rtl8723ae_enable_fw_download(struct ieee80211_hw *hw, bool enable)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 tmp;
if (enable) {
tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);

tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);

tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
} else {
tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);

rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
}
}

static void _rtl8723ae_fw_block_write(struct ieee80211_hw *hw,
const u8 *buffer, u32 size)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 blockSize = sizeof(u32);
u8 *bufferPtr = (u8 *) buffer;
u32 *pu4BytePtr = (u32 *) buffer;
u32 i, offset, blockCount, remainSize;

blockCount = size / blockSize;
remainSize = size % blockSize;

for (i = 0; i < blockCount; i++) {
offset = i * blockSize;
rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
*(pu4BytePtr + i));
}

if (remainSize) {
offset = blockCount * blockSize;
bufferPtr += offset;
for (i = 0; i < remainSize; i++) {
rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
offset + i), *(bufferPtr + i));
}
}
}

static void _rtl8723ae_fw_page_write(struct ieee80211_hw *hw,
u32 page, const u8 *buffer, u32 size)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 value8;
u8 u8page = (u8) (page & 0x07);

value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;

rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
_rtl8723ae_fw_block_write(hw, buffer, size);
}

static void _rtl8723ae_write_fw(struct ieee80211_hw *hw,
enum version_8723e version, u8 *buffer,
u32 size)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 *bufferPtr = (u8 *) buffer;
u32 page_nums, remain_size;
u32 page, offset;

RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);

page_nums = size / FW_8192C_PAGE_SIZE;
remain_size = size % FW_8192C_PAGE_SIZE;

if (page_nums > 6) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Page numbers should not be greater then 6\n");
}

for (page = 0; page < page_nums; page++) {
offset = page * FW_8192C_PAGE_SIZE;
_rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
FW_8192C_PAGE_SIZE);
}

if (remain_size) {
offset = page_nums * FW_8192C_PAGE_SIZE;
page = page_nums;
_rtl8723ae_fw_page_write(hw, page, (bufferPtr + offset),
remain_size);
}

RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n");
}

static int _rtl8723ae_fw_free_to_go(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
int err = -EIO;
u32 counter = 0;
u32 value32;

do {
value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
(!(value32 & FWDL_ChkSum_rpt)));

if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"chksum report faill ! REG_MCUFWDL:0x%08x .\n",
value32);
goto exit;
}

RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
"Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);

value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
value32 |= MCUFWDL_RDY;
value32 &= ~WINTINI_RDY;
rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);

counter = 0;

do {
value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
if (value32 & WINTINI_RDY) {
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
"Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
value32);
err = 0;
goto exit;
}

mdelay(FW_8192C_POLLING_DELAY);

} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);

RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);

exit:
return err;
}

int rtl8723ae_download_fw(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl8723ae_firmware_header *pfwheader;
u8 *pfwdata;
u32 fwsize;
int err;
enum version_8723e version = rtlhal->version;

if (!rtlhal->pfirmware)
return 1;

pfwheader = (struct rtl8723ae_firmware_header *)rtlhal->pfirmware;
pfwdata = (u8 *) rtlhal->pfirmware;
fwsize = rtlhal->fwsize;

if (IS_FW_HEADER_EXIST(pfwheader)) {
RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
"Firmware Version(%d), Signature(%#x),Size(%d)\n",
pfwheader->version, pfwheader->signature,
(int)sizeof(struct rtl8723ae_firmware_header));

pfwdata = pfwdata + sizeof(struct rtl8723ae_firmware_header);
fwsize = fwsize - sizeof(struct rtl8723ae_firmware_header);
}

if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) {
rtl8723ae_firmware_selfreset(hw);
rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
}
_rtl8723ae_enable_fw_download(hw, true);
_rtl8723ae_write_fw(hw, version, pfwdata, fwsize);
_rtl8723ae_enable_fw_download(hw, false);

err = _rtl8723ae_fw_free_to_go(hw);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Firmware is not ready to run!\n");
} else {
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
"Firmware is ready to run!\n");
}
return 0;
}
#include "../rtl8723com/fw_common.h"

static bool rtl8723ae_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
{
Expand Down Expand Up @@ -463,50 +271,6 @@ void rtl8723ae_fill_h2c_cmd(struct ieee80211_hw *hw,
return;
}

void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw)
{
u8 u1tmp;
u8 delay = 100;
struct rtl_priv *rtlpriv = rtl_priv(hw);

rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);

while (u1tmp & BIT(2)) {
delay--;
if (delay == 0)
break;
udelay(50);
u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
}
if (delay == 0) {
u1tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1tmp&(~BIT(2)));
}
}

void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 u1_h2c_set_pwrmode[3] = { 0 };
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));

RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);

SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
(rtlpriv->mac80211.p2p) ?
ppsc->smart_ps : 1);
SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
ppsc->reg_max_lps_awakeintvl);

RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl8723ae_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
u1_h2c_set_pwrmode, 3);
rtl8723ae_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);

}

static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
Expand Down Expand Up @@ -812,7 +576,6 @@ void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));

p2p_ps_offload->offload_en = 1;

if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
p2p_ps_offload->role = 1;
p2p_ps_offload->allstasleep = 0;
Expand All @@ -836,3 +599,24 @@ void rtl8723ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
}
rtl8723ae_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
}

void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 u1_h2c_set_pwrmode[3] = { 0 };
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));

RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);

SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
SET_H2CCMD_PWRMODE_PARM_SMART_PS_23A(u1_h2c_set_pwrmode,
(rtlpriv->mac80211.p2p) ?
ppsc->smart_ps : 1);
SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
ppsc->reg_max_lps_awakeintvl);

RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl8723ae_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
u1_h2c_set_pwrmode, 3);
rtl8723ae_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
}
18 changes: 2 additions & 16 deletions drivers/net/wireless/rtlwifi/rtl8723ae/fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#define FW_8192C_END_ADDRESS 0x3FFF
#define FW_8192C_PAGE_SIZE 4096
#define FW_8192C_POLLING_DELAY 5
#define FW_8192C_POLLING_TIMEOUT_COUNT 1000
#define FW_8192C_POLLING_TIMEOUT_COUNT 6000

#define BEACON_PG 0
#define PSPOLL_PG 2
Expand Down Expand Up @@ -65,21 +65,9 @@ struct rtl8723ae_firmware_header {
u32 rsvd5;
};

enum rtl8192c_h2c_cmd {
H2C_AP_OFFLOAD = 0,
H2C_SETPWRMODE = 1,
H2C_JOINBSSRPT = 2,
H2C_RSVDPAGE = 3,
H2C_RSSI_REPORT = 4,
H2C_P2P_PS_CTW_CMD = 5,
H2C_P2P_PS_OFFLOAD = 6,
H2C_RA_MASK = 7,
MAX_H2CCMD
};

#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \
#define SET_H2CCMD_PWRMODE_PARM_SMART_PS_23A(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
Expand All @@ -92,10 +80,8 @@ enum rtl8192c_h2c_cmd {
#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)

int rtl8723ae_download_fw(struct ieee80211_hw *hw);
void rtl8723ae_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
u32 cmd_len, u8 *p_cmdbuffer);
void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw);
void rtl8723ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
void rtl8723ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
void rtl8723ae_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "../pci.h"
#include "dm.h"
#include "fw.h"
#include "../rtl8723com/fw_common.h"
#include "../rtl8723com/fw_common.h"
#include "phy.h"
#include "reg.h"
#include "hal_btc.h"
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "phy.h"
#include "../rtl8723com/phy_common.h"
#include "fw.h"
#include "../rtl8723com/fw_common.h"
#include "reg.h"
#include "def.h"

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "phy.h"
#include "dm.h"
#include "fw.h"
#include "../rtl8723com/fw_common.h"
#include "led.h"
#include "hw.h"
#include "pwrseqcmd.h"
Expand Down Expand Up @@ -890,7 +891,7 @@ int rtl8723ae_hw_init(struct ieee80211_hw *hw)
return err;
}

err = rtl8723ae_download_fw(hw);
err = rtl8723_download_fw(hw, false);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"Failed to download FW. Init HW without FW now..\n");
Expand Down
Loading

0 comments on commit cbd0c85

Please sign in to comment.