Commit cbd0c851 authored by Larry Finger's avatar Larry Finger Committed by John W. Linville

rtlwifi: rtl8723ae: rtl8723-common: Copy common firmware code

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: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 0a168b48
......@@ -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))
......
......@@ -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)
{
......@@ -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)
{
......@@ -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;
......@@ -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);
}
......@@ -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
......@@ -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)
......@@ -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);
......
......@@ -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"
......
......@@ -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"
......
......@@ -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"
......@@ -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");
......
......@@ -40,6 +40,8 @@
#include "../rtl8723com/phy_common.h"
#include "dm.h"
#include "hw.h"
#include "fw.h"
#include "../rtl8723com/fw_common.h"
#include "sw.h"
#include "trx.h"
#include "led.h"
......@@ -194,6 +196,11 @@ void rtl8723ae_deinit_sw_vars(struct ieee80211_hw *hw)
}
}
static bool is_fw_header(struct rtl92c_firmware_header *hdr)
{
return (hdr->signature & 0xfff0) == 0x2300;
}
static struct rtl_hal_ops rtl8723ae_hal_ops = {
.init_sw_vars = rtl8723ae_init_sw_vars,
.deinit_sw_vars = rtl8723ae_deinit_sw_vars,
......@@ -239,6 +246,7 @@ static struct rtl_hal_ops rtl8723ae_hal_ops = {
.c2h_command_handle = rtl_8723e_c2h_command_handle,
.bt_wifi_media_status_notify = rtl_8723e_bt_wifi_media_status_notify,
.bt_coex_off_before_lps = rtl8723ae_bt_coex_off_before_lps,
.is_fw_header = is_fw_header,
};
static struct rtl_mod_params rtl8723ae_mod_params = {
......
rtl8723-common-objs := \
main.o \
fw_common.o \
phy_common.o
obj-$(CONFIG_RTL8723_COMMON) += rtl8723-common.o
......
......@@ -24,27 +24,103 @@
*****************************************************************************/
#ifndef __FW_COMMON_H__
#define __FW_COMMON_H__#endif
#define __FW_COMMON_H__
#define REG_SYS_FUNC_EN 0x0002
#define REG_MCUFWDL 0x0080
#define FW_8192C_START_ADDRESS 0x1000
#define FW_8192C_PAGE_SIZE 4096
#define FW_8192C_POLLING_TIMEOUT_COUNT 6000
#define FW_8192C_POLLING_DELAY 5
#define MCUFWDL_RDY BIT(1)
#define FWDL_CHKSUM_RPT BIT(2)
#define WINTINI_RDY BIT(6)
#define REG_RSV_CTRL 0x001C
#define REG_HMETFR 0x01CC
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,
VERSION_TEST_CHIP_1T1R_8723B = 0x0106,
VERSION_NORMAL_SMIC_CHIP_1T1R_8723B = 0x010E,
VERSION_UNKNOWN = 0xFF,
};
enum rtl8723ae_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
};
enum rtl8723be_cmd {
H2C_8723BE_RSVDPAGE = 0,
H2C_8723BE_JOINBSSRPT = 1,
H2C_8723BE_SCAN = 2,
H2C_8723BE_KEEP_ALIVE_CTRL = 3,
H2C_8723BE_DISCONNECT_DECISION = 4,
H2C_8723BE_INIT_OFFLOAD = 6,
H2C_8723BE_AP_OFFLOAD = 8,
H2C_8723BE_BCN_RSVDPAGE = 9,
H2C_8723BE_PROBERSP_RSVDPAGE = 10,
H2C_8723BE_SETPWRMODE = 0x20,
H2C_8723BE_PS_TUNING_PARA = 0x21,
H2C_8723BE_PS_TUNING_PARA2 = 0x22,
H2C_8723BE_PS_LPS_PARA = 0x23,
H2C_8723BE_P2P_PS_OFFLOAD = 0x24,
H2C_8723BE_WO_WLAN = 0x80,
H2C_8723BE_REMOTE_WAKE_CTRL = 0x81,
H2C_8723BE_AOAC_GLOBAL_INFO = 0x82,
H2C_8723BE_AOAC_RSVDPAGE = 0x83,
H2C_8723BE_RSSI_REPORT = 0x42,
H2C_8723BE_RA_MASK = 0x40,
H2C_8723BE_SELECTIVE_SUSPEND_ROF_CMD,
H2C_8723BE_P2P_PS_MODE,
H2C_8723BE_PSD_RESULT,
/*Not defined CTW CMD for P2P yet*/
H2C_8723BE_P2P_PS_CTW_CMD,
MAX_8723BE_H2CCMD
};
struct rtl92c_firmware_header {
u16 signature;
u8 category;
u8 function;
u16 version;
u8 subversion;
u8 rsvd1;
u8 month;
u8 date;
u8 hour;
u8 minute;
u16 ramcodesize;
u16 rsvd2;
u32 svnindex;
u32 rsvd3;
u32 rsvd4;
u32 rsvd5;
};
void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw);
void rtl8723be_firmware_selfreset(struct ieee80211_hw *hw);
void rtl8723_enable_fw_download(struct ieee80211_hw *hw, bool enable);
void rtl8723_fw_block_write(struct ieee80211_hw *hw,
const u8 *buffer, u32 size);
void rtl8723_fw_page_write(struct ieee80211_hw *hw,
u32 page, const u8 *buffer, u32 size);
void rtl8723_write_fw(struct ieee80211_hw *hw,
enum version_8723be version,
enum version_8723e version,
u8 *buffer, u32 size);
int rtl8723_fw_free_to_go(struct ieee80211_hw *hw, bool is_8723be);
int rtl8723_download_fw(struct ieee80211_hw *hw,
bool buse_wake_on_wlan_fw, bool is_8723be);
bool rtl8723_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum);
void rtl8723_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
u32 cmd_len, u8 *p_cmdbuffer);
void rtl8723_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
u32 cmd_len, u8 *p_cmdbuffer);
void rtl8723_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw,
struct sk_buff *skb);
void rtl8723_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished);
void rtl8723_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow);
void rtl8723_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
int rtl8723_download_fw(struct ieee80211_hw *hw, bool is_8723be);
#endif
......@@ -1712,6 +1712,8 @@ struct rtl_tcb_desc {
bool btx_enable_sw_calc_duration;
};
struct rtl92c_firmware_header;
struct rtl_hal_ops {
int (*init_sw_vars) (struct ieee80211_hw *hw);
void (*deinit_sw_vars) (struct ieee80211_hw *hw);
......@@ -1809,6 +1811,7 @@ struct rtl_hal_ops {
void (*fill_h2c_cmd) (struct ieee80211_hw *hw, u8 element_id,
u32 cmd_len, u8 *p_cmdbuffer);
bool (*get_btc_status) (void);
bool (*is_fw_header) (struct rtl92c_firmware_header *hdr);
};
struct rtl_intf_ops {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment