1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-26 07:55:01 +00:00

rtw88: update Realtek's rtw88 driver

This version is based on
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
98f7e32f20d28ec452afb208f9cffc08448a2652 ( tag: v6.11 ).

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Bjoern A. Zeeb 2024-09-24 19:55:17 +00:00
parent 1f3bff0d30
commit 8e9553a4cd
38 changed files with 6259 additions and 2087 deletions

View File

@ -44,6 +44,15 @@ rtw88_8822cs-objs := rtw8822cs.o
obj-$(CONFIG_RTW88_8822CU) += rtw88_8822cu.o
rtw88_8822cu-objs := rtw8822cu.o
obj-$(CONFIG_RTW88_8723X) += rtw88_8723x.o
rtw88_8723x-objs := rtw8723x.o
obj-$(CONFIG_RTW88_8703B) += rtw88_8703b.o
rtw88_8703b-objs := rtw8703b.o rtw8703b_tables.o
obj-$(CONFIG_RTW88_8723CS) += rtw88_8723cs.o
rtw88_8723cs-objs := rtw8723cs.o
obj-$(CONFIG_RTW88_8723D) += rtw88_8723d.o
rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o

4
coex.c
View File

@ -3937,7 +3937,9 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
if (!coex_stat->wl_under_ips &&
(!coex_stat->wl_under_lps || coex_stat->wl_force_lps_ctrl) &&
!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
rtw_coex_get_bt_supported_version(rtwdev,
&coex_stat->bt_supported_version);
rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);

54
debug.c
View File

@ -316,23 +316,13 @@ static ssize_t rtw_debugfs_set_single_input(struct file *filp,
{
struct seq_file *seqpriv = (struct seq_file *)filp->private_data;
struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
char tmp[32 + 1];
u32 input;
int num;
int ret;
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
ret = kstrtou32_from_user(buffer, count, 0, &input);
if (ret)
return ret;
num = kstrtoint(tmp, 0, &input);
if (num) {
rtw_warn(rtwdev, "kstrtoint failed\n");
return num;
}
debugfs_priv->cb_data = input;
return count;
@ -485,19 +475,12 @@ static ssize_t rtw_debugfs_set_fix_rate(struct file *filp,
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u8 fix_rate;
char tmp[32 + 1];
int ret;
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
ret = kstrtou8_from_user(buffer, count, 0, &fix_rate);
if (ret)
return ret;
ret = kstrtou8(tmp, 0, &fix_rate);
if (ret) {
rtw_warn(rtwdev, "invalid args, [rate]\n");
return ret;
}
dm_info->fix_rate = fix_rate;
return count;
@ -879,20 +862,13 @@ static ssize_t rtw_debugfs_set_coex_enable(struct file *filp,
struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
struct rtw_coex *coex = &rtwdev->coex;
char tmp[32 + 1];
bool enable;
int ret;
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
ret = kstrtobool_from_user(buffer, count, &enable);
if (ret)
return ret;
ret = kstrtobool(tmp, &enable);
if (ret) {
rtw_warn(rtwdev, "invalid arguments\n");
return ret;
}
mutex_lock(&rtwdev->mutex);
coex->manual_control = !enable;
mutex_unlock(&rtwdev->mutex);
@ -951,18 +927,13 @@ static ssize_t rtw_debugfs_set_fw_crash(struct file *filp,
struct seq_file *seqpriv = (struct seq_file *)filp->private_data;
struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
char tmp[32 + 1];
bool input;
int ret;
ret = rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
ret = kstrtobool_from_user(buffer, count, &input);
if (ret)
return ret;
ret = kstrtobool(tmp, &input);
if (ret)
return -EINVAL;
if (!input)
return -EINVAL;
@ -1030,11 +1001,12 @@ static ssize_t rtw_debugfs_set_dm_cap(struct file *filp,
struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
int bit;
int ret, bit;
bool en;
if (kstrtoint_from_user(buffer, count, 10, &bit))
return -EINVAL;
ret = kstrtoint_from_user(buffer, count, 10, &bit);
if (ret)
return ret;
en = bit > 0;
bit = abs(bit);
@ -1233,9 +1205,9 @@ static struct rtw_debugfs_priv rtw_debug_priv_dm_cap = {
#define rtw_debugfs_add_core(name, mode, fopname, parent) \
do { \
rtw_debug_priv_ ##name.rtwdev = rtwdev; \
if (!debugfs_create_file(#name, mode, \
if (IS_ERR(debugfs_create_file(#name, mode, \
parent, &rtw_debug_priv_ ##name,\
&file_ops_ ##fopname)) \
&file_ops_ ##fopname))) \
pr_debug("Unable to initialize debugfs:%s\n", \
#name); \
} while (0)
@ -1314,8 +1286,8 @@ void rtw_debugfs_init(struct rtw_dev *rtwdev)
#ifdef CONFIG_RTW88_DEBUG
void __rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
const char *fmt, ...)
void rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
@ -1330,6 +1302,6 @@ void __rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
va_end(args);
}
EXPORT_SYMBOL(__rtw_dbg);
EXPORT_SYMBOL(rtw_dbg);
#endif /* CONFIG_RTW88_DEBUG */

17
debug.h
View File

@ -26,6 +26,7 @@ enum rtw_debug_mask {
RTW_DBG_STATE = 0x00020000,
RTW_DBG_SDIO = 0x00040000,
RTW_DBG_UNEXP = 0x80000000,
RTW_DBG_ALL = 0xffffffff
};
@ -43,16 +44,26 @@ static inline void rtw_debugfs_init(struct rtw_dev *rtwdev) {}
#ifdef CONFIG_RTW88_DEBUG
__printf(3, 4)
void __rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
const char *fmt, ...);
void rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
const char *fmt, ...);
#define rtw_dbg(rtwdev, a...) __rtw_dbg(rtwdev, ##a)
static inline bool rtw_dbg_is_enabled(struct rtw_dev *rtwdev,
enum rtw_debug_mask mask)
{
return !!(rtw_debug_mask & mask);
}
#else
static inline void rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
const char *fmt, ...) {}
static inline bool rtw_dbg_is_enabled(struct rtw_dev *rtwdev,
enum rtw_debug_mask mask)
{
return false;
}
#endif /* CONFIG_RTW88_DEBUG */
#define rtw_info(rtwdev, a...) dev_info(rtwdev->dev, ##a)

92
fw.c
View File

@ -17,6 +17,79 @@
#include "phy.h"
#include "mac.h"
static const struct rtw_hw_reg_desc fw_h2c_regs[] = {
{REG_FWIMR, MASKDWORD, "FWIMR"},
{REG_FWIMR, BIT_FS_H2CCMD_INT_EN, "FWIMR enable"},
{REG_FWISR, MASKDWORD, "FWISR"},
{REG_FWISR, BIT_FS_H2CCMD_INT, "FWISR enable"},
{REG_HMETFR, BIT_INT_BOX_ALL, "BoxBitMap"},
{REG_HMEBOX0, MASKDWORD, "MSG 0"},
{REG_HMEBOX0_EX, MASKDWORD, "MSG_EX 0"},
{REG_HMEBOX1, MASKDWORD, "MSG 1"},
{REG_HMEBOX1_EX, MASKDWORD, "MSG_EX 1"},
{REG_HMEBOX2, MASKDWORD, "MSG 2"},
{REG_HMEBOX2_EX, MASKDWORD, "MSG_EX 2"},
{REG_HMEBOX3, MASKDWORD, "MSG 3"},
{REG_HMEBOX3_EX, MASKDWORD, "MSG_EX 3"},
{REG_FT1IMR, MASKDWORD, "FT1IMR"},
{REG_FT1IMR, BIT_FS_H2C_CMD_OK_INT_EN, "FT1IMR enable"},
{REG_FT1ISR, MASKDWORD, "FT1ISR"},
{REG_FT1ISR, BIT_FS_H2C_CMD_OK_INT, "FT1ISR enable "},
};
static const struct rtw_hw_reg_desc fw_c2h_regs[] = {
{REG_FWIMR, MASKDWORD, "FWIMR"},
{REG_FWIMR, BIT_FS_H2CCMD_INT_EN, "CPWM"},
{REG_FWIMR, BIT_FS_HRCV_INT_EN, "HRECV"},
{REG_FWISR, MASKDWORD, "FWISR"},
{REG_FWISR, BIT_FS_H2CCMD_INT, "CPWM"},
{REG_FWISR, BIT_FS_HRCV_INT, "HRECV"},
{REG_CPWM, MASKDWORD, "REG_CPWM"},
};
static const struct rtw_hw_reg_desc fw_core_regs[] = {
{REG_ARFR2_V1, MASKDWORD, "EPC"},
{REG_ARFRH2_V1, MASKDWORD, "BADADDR"},
{REG_ARFR3_V1, MASKDWORD, "CAUSE"},
{REG_ARFR3_V1, BIT_EXC_CODE, "ExcCode"},
{REG_ARFRH3_V1, MASKDWORD, "Status"},
{REG_ARFR4, MASKDWORD, "SP"},
{REG_ARFRH4, MASKDWORD, "RA"},
{REG_FW_DBG6, MASKDWORD, "DBG 6"},
{REG_FW_DBG7, MASKDWORD, "DBG 7"},
};
static void _rtw_fw_dump_dbg_info(struct rtw_dev *rtwdev,
const struct rtw_hw_reg_desc regs[], u32 size)
{
const struct rtw_hw_reg_desc *reg;
u32 val;
int i;
for (i = 0; i < size; i++) {
reg = &regs[i];
val = rtw_read32_mask(rtwdev, reg->addr, reg->mask);
rtw_dbg(rtwdev, RTW_DBG_FW, "[%s]addr:0x%x mask:0x%x value:0x%x\n",
reg->desc, reg->addr, reg->mask, val);
}
}
void rtw_fw_dump_dbg_info(struct rtw_dev *rtwdev)
{
int i;
if (!rtw_dbg_is_enabled(rtwdev, RTW_DBG_FW))
return;
_rtw_fw_dump_dbg_info(rtwdev, fw_h2c_regs, ARRAY_SIZE(fw_h2c_regs));
_rtw_fw_dump_dbg_info(rtwdev, fw_c2h_regs, ARRAY_SIZE(fw_c2h_regs));
for (i = 0 ; i < RTW_DEBUG_DUMP_TIMES; i++) {
rtw_dbg(rtwdev, RTW_DBG_FW, "Firmware Coredump %dth\n", i + 1);
_rtw_fw_dump_dbg_info(rtwdev, fw_core_regs, ARRAY_SIZE(fw_core_regs));
}
}
static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
struct sk_buff *skb)
{
@ -349,6 +422,7 @@ static void rtw_fw_send_h2c_command_register(struct rtw_dev *rtwdev,
if (ret) {
rtw_err(rtwdev, "failed to send h2c command\n");
rtw_fw_dump_dbg_info(rtwdev);
return;
}
@ -709,12 +783,18 @@ void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,
static const u8 rssi_min = 0, rssi_max = 100, rssi_offset = 100;
struct rtw_sta_info *si =
sta ? (struct rtw_sta_info *)sta->drv_priv : NULL;
s32 threshold = bss_conf->cqm_rssi_thold + rssi_offset;
s32 thold = RTW_DEFAULT_CQM_THOLD;
u32 hyst = RTW_DEFAULT_CQM_HYST;
u8 h2c_pkt[H2C_PKT_SIZE] = {0};
if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER))
return;
if (bss_conf->cqm_rssi_thold)
thold = bss_conf->cqm_rssi_thold;
if (bss_conf->cqm_rssi_hyst)
hyst = bss_conf->cqm_rssi_hyst;
if (!connect) {
SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P1);
SET_BCN_FILTER_OFFLOAD_P1_ENABLE(h2c_pkt, connect);
@ -731,15 +811,15 @@ void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
memset(h2c_pkt, 0, sizeof(h2c_pkt));
threshold = clamp_t(s32, threshold, rssi_min, rssi_max);
thold = clamp_t(s32, thold + rssi_offset, rssi_min, rssi_max);
SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P1);
SET_BCN_FILTER_OFFLOAD_P1_ENABLE(h2c_pkt, connect);
SET_BCN_FILTER_OFFLOAD_P1_OFFLOAD_MODE(h2c_pkt,
BCN_FILTER_OFFLOAD_MODE_DEFAULT);
SET_BCN_FILTER_OFFLOAD_P1_THRESHOLD(h2c_pkt, (u8)threshold);
SET_BCN_FILTER_OFFLOAD_P1_THRESHOLD(h2c_pkt, thold);
SET_BCN_FILTER_OFFLOAD_P1_BCN_LOSS_CNT(h2c_pkt, BCN_LOSS_CNT);
SET_BCN_FILTER_OFFLOAD_P1_MACID(h2c_pkt, si->mac_id);
SET_BCN_FILTER_OFFLOAD_P1_HYST(h2c_pkt, bss_conf->cqm_rssi_hyst);
SET_BCN_FILTER_OFFLOAD_P1_HYST(h2c_pkt, hyst);
SET_BCN_FILTER_OFFLOAD_P1_BCN_INTERVAL(h2c_pkt, bss_conf->beacon_int);
rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
}
@ -924,7 +1004,7 @@ static u8 rtw_get_rsvd_page_probe_req_location(struct rtw_dev *rtwdev,
if (rsvd_pkt->type != RSVD_PROBE_REQ)
continue;
if ((!ssid && !rsvd_pkt->ssid) ||
rtw_ssid_equal(rsvd_pkt->ssid, ssid))
cfg80211_ssid_eq(rsvd_pkt->ssid, ssid))
location = rsvd_pkt->page;
}
@ -941,7 +1021,7 @@ static u16 rtw_get_rsvd_page_probe_req_size(struct rtw_dev *rtwdev,
if (rsvd_pkt->type != RSVD_PROBE_REQ)
continue;
if ((!ssid && !rsvd_pkt->ssid) ||
rtw_ssid_equal(rsvd_pkt->ssid, ssid))
cfg80211_ssid_eq(rsvd_pkt->ssid, ssid))
size = rsvd_pkt->probe_req_size;
}

5
fw.h
View File

@ -29,6 +29,8 @@
#define BCN_FILTER_CONNECTION_LOSS 1
#define BCN_FILTER_CONNECTED 2
#define BCN_FILTER_NOTIFY_BEACON_LOSS 3
#define RTW_DEFAULT_CQM_THOLD -70
#define RTW_DEFAULT_CQM_HYST 4
#define SCAN_NOTIFY_TIMEOUT msecs_to_jiffies(10)
@ -44,6 +46,8 @@
#define RTW_OLD_PROBE_PG_CNT 2
#define RTW_PROBE_PG_CNT 4
#define RTW_DEBUG_DUMP_TIMES 10
enum rtw_c2h_cmd_id {
C2H_CCX_TX_RPT = 0x03,
C2H_BT_INFO = 0x09,
@ -808,6 +812,7 @@ static inline bool rtw_fw_feature_ext_check(struct rtw_fw_state *fw,
return !!(fw->feature_ext & feature);
}
void rtw_fw_dump_dbg_info(struct rtw_dev *rtwdev);
void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
struct sk_buff *skb);
void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);

27
mac.c
View File

@ -309,6 +309,13 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq;
ret = rtw_pwr_seq_parser(rtwdev, pwr_seq);
if (pwr_on && rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) {
if (chip->id == RTW_CHIP_TYPE_8822C ||
chip->id == RTW_CHIP_TYPE_8822B ||
chip->id == RTW_CHIP_TYPE_8821C)
rtw_write8_clr(rtwdev, REG_SYS_STATUS1 + 1, BIT(0));
}
if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO)
rtw_write32(rtwdev, REG_SDIO_HIMR, imr);
@ -936,6 +943,12 @@ static int __rtw_download_firmware_legacy(struct rtw_dev *rtwdev,
{
int ret = 0;
/* reset firmware if still present */
if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B &&
rtw_read8_mask(rtwdev, REG_MCUFW_CTRL, BIT_RAM_DL_SEL)) {
rtw_write8(rtwdev, REG_MCUFW_CTRL, 0x00);
}
en_download_firmware_legacy(rtwdev, true);
ret = download_firmware_legacy(rtwdev, fw->firmware->data, fw->firmware->size);
en_download_firmware_legacy(rtwdev, false);
@ -1026,14 +1039,15 @@ static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev,
msleep(20);
}
/* priority queue is still not empty, throw a warning,
/* priority queue is still not empty, throw a debug message
*
* Note that if we want to flush the tx queue when having a lot of
* traffic (ex, 100Mbps up), some of the packets could be dropped.
* And it requires like ~2secs to flush the full priority queue.
*/
if (!drop)
rtw_warn(rtwdev, "timed out to flush queue %d\n", prio_queue);
rtw_dbg(rtwdev, RTW_DBG_UNEXP,
"timed out to flush queue %d\n", prio_queue);
}
static void rtw_mac_flush_prio_queues(struct rtw_dev *rtwdev,
@ -1187,6 +1201,15 @@ static int __priority_queue_cfg(struct rtw_dev *rtwdev,
rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2 + 2, fifo->rsvd_boundary);
rtw_write16(rtwdev, REG_BCNQ1_BDNY_V1, fifo->rsvd_boundary);
rtw_write32(rtwdev, REG_RXFF_BNDY, chip->rxff_size - C2H_PKT_BUF - 1);
if (rtwdev->hci.type == RTW_HCI_TYPE_USB) {
rtw_write8_mask(rtwdev, REG_AUTO_LLT_V1, BIT_MASK_BLK_DESC_NUM,
chip->usb_tx_agg_desc_num);
rtw_write8(rtwdev, REG_AUTO_LLT_V1 + 3, chip->usb_tx_agg_desc_num);
rtw_write8_set(rtwdev, REG_TXDMA_OFFSET_CHK + 1, BIT(1));
}
rtw_write8_set(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1);
if (!check_hw_ready(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1, 0))

View File

@ -62,7 +62,7 @@ static int rtw_ops_start(struct ieee80211_hw *hw)
return ret;
}
static void rtw_ops_stop(struct ieee80211_hw *hw)
static void rtw_ops_stop(struct ieee80211_hw *hw, bool suspend)
{
struct rtw_dev *rtwdev = hw->priv;
@ -280,9 +280,9 @@ static void rtw_ops_configure_filter(struct ieee80211_hw *hw,
if (changed_flags & FIF_ALLMULTI) {
if (*new_flags & FIF_ALLMULTI)
rtwdev->hal.rcr |= BIT_AM | BIT_AB;
rtwdev->hal.rcr |= BIT_AM;
else
rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB);
rtwdev->hal.rcr &= ~(BIT_AM);
}
if (changed_flags & FIF_FCSFAIL) {
if (*new_flags & FIF_FCSFAIL)
@ -386,6 +386,8 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
rtw_coex_media_status_notify(rtwdev, vif->cfg.assoc);
if (rtw_bf_support)
rtw_bf_assoc(rtwdev, vif, conf);
rtw_fw_beacon_filter_config(rtwdev, true, vif);
} else {
rtw_leave_lps(rtwdev);
rtw_bf_disassoc(rtwdev, vif, conf);
@ -927,6 +929,10 @@ static void rtw_ops_sta_rc_update(struct ieee80211_hw *hw,
}
const struct ieee80211_ops rtw_ops = {
.add_chanctx = ieee80211_emulate_add_chanctx,
.remove_chanctx = ieee80211_emulate_remove_chanctx,
.change_chanctx = ieee80211_emulate_change_chanctx,
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
.tx = rtw_ops_tx,
.wake_tx_queue = rtw_ops_wake_tx_queue,
.start = rtw_ops_start,

25
main.c
View File

@ -227,9 +227,6 @@ static void rtw_watch_dog_work(struct work_struct *work)
else
clear_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
rtw_coex_wl_status_check(rtwdev);
rtw_coex_query_bt_hid_list(rtwdev);
if (busy_traffic != test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags))
rtw_coex_wl_status_change_notify(rtwdev, 0);
@ -257,6 +254,8 @@ static void rtw_watch_dog_work(struct work_struct *work)
/* make sure BB/RF is working for dynamic mech */
rtw_leave_lps(rtwdev);
rtw_coex_wl_status_check(rtwdev);
rtw_coex_query_bt_hid_list(rtwdev);
rtw_phy_dynamic_mechanism(rtwdev);
@ -2008,6 +2007,11 @@ static int rtw_chip_efuse_info_setup(struct rtw_dev *rtwdev)
efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0;
efuse->ext_lna_2g = efuse->lna_type_5g & BIT(3) ? 1 : 0;
if (!is_valid_ether_addr(efuse->addr)) {
eth_random_addr(efuse->addr);
dev_warn(rtwdev->dev, "efuse MAC invalid, using random\n");
}
out_disable:
rtw_chip_efuse_disable(rtwdev);
@ -2027,8 +2031,6 @@ static int rtw_chip_board_info_setup(struct rtw_dev *rtwdev)
rtw_phy_setup_phy_cond(rtwdev, hal->pkg_type);
rtw_phy_init_tx_power(rtwdev);
if (rfe_def->agc_btg_tbl)
rtw_load_table(rtwdev, rfe_def->agc_btg_tbl);
rtw_load_table(rtwdev, rfe_def->phy_pg_tbl);
rtw_load_table(rtwdev, rfe_def->txpwr_lmt_tbl);
rtw_phy_tx_power_by_rate_config(hal);
@ -2201,6 +2203,7 @@ EXPORT_SYMBOL(rtw_core_deinit);
int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
{
bool sta_mode_only = rtwdev->hci.type == RTW_HCI_TYPE_SDIO;
struct rtw_hal *hal = &rtwdev->hal;
int max_tx_headroom = 0;
int ret;
@ -2229,10 +2232,12 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
if (sta_mode_only)
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
else
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_ADHOC);
hw->wiphy->available_antennas_tx = hal->antenna_tx;
hw->wiphy->available_antennas_rx = hal->antenna_rx;
@ -2243,7 +2248,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
hw->wiphy->max_scan_ssids = RTW_SCAN_MAX_SSIDS;
hw->wiphy->max_scan_ie_len = rtw_get_max_scan_ie_len(rtwdev);
if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) {
if (!sta_mode_only && rtwdev->chip->id == RTW_CHIP_TYPE_8822C) {
hw->wiphy->iface_combinations = rtw_iface_combs;
hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtw_iface_combs);
}

27
main.h
View File

@ -187,6 +187,7 @@ enum rtw_chip_type {
RTW_CHIP_TYPE_8822C,
RTW_CHIP_TYPE_8723D,
RTW_CHIP_TYPE_8821C,
RTW_CHIP_TYPE_8703B,
};
enum rtw_tx_queue_type {
@ -342,8 +343,10 @@ enum rtw_regulatory_domains {
RTW_REGD_UKRAINE = 7,
RTW_REGD_MEXICO = 8,
RTW_REGD_CN = 9,
RTW_REGD_WW,
RTW_REGD_QATAR = 10,
RTW_REGD_UK = 11,
RTW_REGD_WW,
RTW_REGD_MAX
};
@ -522,6 +525,12 @@ struct rtw_hw_reg {
u32 mask;
};
struct rtw_hw_reg_desc {
u32 addr;
u32 mask;
const char *desc;
};
struct rtw_ltecoex_addr {
u32 ctrl;
u32 wdata;
@ -1188,6 +1197,8 @@ struct rtw_chip_info {
u16 fw_fifo_addr[RTW_FW_FIFO_MAX];
const struct rtw_fwcd_segs *fwcd_segs;
u8 usb_tx_agg_desc_num;
u8 default_1ss_tx_path;
bool path_div_supported;
@ -1692,11 +1703,13 @@ struct rtw_dm_info {
s8 delta_power_index[RTW_RF_PATH_MAX];
s8 delta_power_index_last[RTW_RF_PATH_MAX];
u8 default_ofdm_index;
u8 default_cck_index;
bool pwr_trk_triggered;
bool pwr_trk_init_trigger;
struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX];
s8 txagc_remnant_cck;
s8 txagc_remnant_ofdm;
u8 rx_cck_agc_report_type;
/* backup dack results for each path and I/Q */
u32 dack_adck[RTW_RF_PATH_MAX];
@ -2082,18 +2095,6 @@ static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw_vif *rtwvif)
return container_of(p, struct ieee80211_vif, drv_priv);
}
static inline bool rtw_ssid_equal(struct cfg80211_ssid *a,
struct cfg80211_ssid *b)
{
if (!a || !b || a->ssid_len != b->ssid_len)
return false;
if (memcmp(a->ssid, b->ssid, a->ssid_len))
return false;
return true;
}
static inline void rtw_chip_efuse_grant_on(struct rtw_dev *rtwdev)
{
if (rtwdev->chip->ops->efuse_grant)

28
pci.c
View File

@ -729,7 +729,8 @@ static void __pci_flush_queue(struct rtw_dev *rtwdev, u8 pci_q, bool drop)
}
if (!drop)
rtw_warn(rtwdev, "timed out to flush pci tx ring[%d]\n", pci_q);
rtw_dbg(rtwdev, RTW_DBG_UNEXP,
"timed out to flush pci tx ring[%d]\n", pci_q);
}
static void __rtw_pci_flush_queues(struct rtw_dev *rtwdev, u32 pci_queues,
@ -1450,6 +1451,7 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev)
{
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
const struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_efuse *efuse = &rtwdev->efuse;
struct pci_dev *pdev = rtwpci->pdev;
const struct rtw_intf_phy_para *para;
u16 cut;
@ -1498,6 +1500,9 @@ static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev)
rtw_err(rtwdev, "failed to set PCI cap, ret = %d\n",
ret);
}
if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 5)
rtw_write32_mask(rtwdev, REG_ANAPARSW_MAC_0, BIT_CF_L_V2, 0x1);
}
static int __maybe_unused rtw_pci_suspend(struct device *dev)
@ -1608,7 +1613,7 @@ static struct rtw_hci_ops rtw_pci_ops = {
static int rtw_pci_request_irq(struct rtw_dev *rtwdev, struct pci_dev *pdev)
{
unsigned int flags = PCI_IRQ_LEGACY;
unsigned int flags = PCI_IRQ_INTX;
int ret;
if (!rtw_disable_msi)
@ -1677,12 +1682,16 @@ static int rtw_pci_napi_poll(struct napi_struct *napi, int budget)
return work_done;
}
static void rtw_pci_napi_init(struct rtw_dev *rtwdev)
static int rtw_pci_napi_init(struct rtw_dev *rtwdev)
{
struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
init_dummy_netdev(&rtwpci->netdev);
netif_napi_add(&rtwpci->netdev, &rtwpci->napi, rtw_pci_napi_poll);
rtwpci->netdev = alloc_netdev_dummy(0);
if (!rtwpci->netdev)
return -ENOMEM;
netif_napi_add(rtwpci->netdev, &rtwpci->napi, rtw_pci_napi_poll);
return 0;
}
static void rtw_pci_napi_deinit(struct rtw_dev *rtwdev)
@ -1691,6 +1700,7 @@ static void rtw_pci_napi_deinit(struct rtw_dev *rtwdev)
rtw_pci_napi_stop(rtwdev);
netif_napi_del(&rtwpci->napi);
free_netdev(rtwpci->netdev);
}
int rtw_pci_probe(struct pci_dev *pdev,
@ -1740,7 +1750,11 @@ int rtw_pci_probe(struct pci_dev *pdev,
goto err_pci_declaim;
}
rtw_pci_napi_init(rtwdev);
ret = rtw_pci_napi_init(rtwdev);
if (ret) {
rtw_err(rtwdev, "failed to setup NAPI\n");
goto err_pci_declaim;
}
ret = rtw_chip_info_setup(rtwdev);
if (ret) {
@ -1828,5 +1842,5 @@ void rtw_pci_shutdown(struct pci_dev *pdev)
EXPORT_SYMBOL(rtw_pci_shutdown);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ac wireless PCI driver");
MODULE_DESCRIPTION("Realtek PCI 802.11ac wireless driver");
MODULE_LICENSE("Dual BSD/GPL");

2
pci.h
View File

@ -215,7 +215,7 @@ struct rtw_pci {
bool running;
/* napi structure */
struct net_device netdev;
struct net_device *netdev;
struct napi_struct napi;
u16 rx_tag;

3
phy.c
View File

@ -1761,12 +1761,15 @@ static void rtw_load_rfk_table(struct rtw_dev *rtwdev)
void rtw_phy_load_tables(struct rtw_dev *rtwdev)
{
const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev);
const struct rtw_chip_info *chip = rtwdev->chip;
u8 rf_path;
rtw_load_table(rtwdev, chip->mac_tbl);
rtw_load_table(rtwdev, chip->bb_tbl);
rtw_load_table(rtwdev, chip->agc_tbl);
if (rfe_def->agc_btg_tbl)
rtw_load_table(rtwdev, rfe_def->agc_btg_tbl);
rtw_load_rfk_table(rtwdev);
for (rf_path = 0; rf_path < rtwdev->hal.rf_path_num; rf_path++) {

2
ps.c
View File

@ -104,6 +104,7 @@ void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter)
*/
WARN(1, "firmware failed to ack driver for %s Deep Power mode\n",
enter ? "entering" : "leaving");
rtw_fw_dump_dbg_info(rtwdev);
}
}
EXPORT_SYMBOL(rtw_power_mode_change);
@ -164,6 +165,7 @@ static void rtw_fw_leave_lps_check(struct rtw_dev *rtwdev)
if (ret) {
rtw_write32_clr(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN);
rtw_warn(rtwdev, "firmware failed to leave lps state\n");
rtw_fw_dump_dbg_info(rtwdev);
}
}

27
reg.h
View File

@ -224,12 +224,25 @@
#define REG_RXFF_BNDY 0x011C
#define REG_FE1IMR 0x0120
#define BIT_FS_RXDONE BIT(16)
#define REG_CPWM 0x012C
#define REG_FWIMR 0x0130
#define BIT_FS_H2CCMD_INT_EN BIT(4)
#define BIT_FS_HRCV_INT_EN BIT(5)
#define REG_FWISR 0x0134
#define BIT_FS_H2CCMD_INT BIT(4)
#define BIT_FS_HRCV_INT BIT(5)
#define REG_PKTBUF_DBG_CTRL 0x0140
#define REG_C2HEVT 0x01A0
#define REG_MCUTST_1 0x01C0
#define REG_MCUTST_II 0x01C4
#define REG_WOWLAN_WAKE_REASON 0x01C7
#define REG_HMETFR 0x01CC
#define BIT_INT_BOX0 BIT(0)
#define BIT_INT_BOX1 BIT(1)
#define BIT_INT_BOX2 BIT(2)
#define BIT_INT_BOX3 BIT(3)
#define BIT_INT_BOX_ALL (BIT_INT_BOX0 | BIT_INT_BOX1 | BIT_INT_BOX2 | \
BIT_INT_BOX3)
#define REG_HMEBOX0 0x01D0
#define REG_HMEBOX1 0x01D4
#define REG_HMEBOX2 0x01D8
@ -257,6 +270,7 @@
#define BIT_MASK_BCN_HEAD_1_V1 0xfff
#define REG_AUTO_LLT_V1 0x0208
#define BIT_AUTO_INIT_LLT_V1 BIT(0)
#define BIT_MASK_BLK_DESC_NUM GENMASK(7, 4)
#define REG_DWBCN0_CTRL 0x0208
#define BIT_BCN_VALID BIT(16)
#define REG_TXDMA_OFFSET_CHK 0x020C
@ -338,6 +352,11 @@
#define BIT_EN_GNT_BT_AWAKE BIT(3)
#define BIT_EN_EOF_V1 BIT(2)
#define REG_DATA_SC 0x0483
#define REG_ARFR2_V1 0x048C
#define REG_ARFRH2_V1 0x0490
#define REG_ARFR3_V1 0x0494
#define BIT_EXC_CODE GENMASK(6, 2)
#define REG_ARFRH3_V1 0x0498
#define REG_ARFR4 0x049C
#define BIT_WL_RFK BIT(0)
#define REG_ARFRH4 0x04A0
@ -539,6 +558,9 @@
#define REG_RFE_INV16 0x0cbe
#define BIT_RFE_BUF_EN BIT(3)
#define REG_ANAPARSW_MAC_0 0x1010
#define BIT_CF_L_V2 GENMASK(29, 28)
#define REG_ANAPAR_XTAL_0 0x1040
#define BIT_XCAP_0 GENMASK(23, 10)
#define REG_CPU_DMEM_CON 0x1080
@ -548,11 +570,16 @@
#define REG_H2C_PKT_READADDR 0x10D0
#define REG_H2C_PKT_WRITEADDR 0x10D4
#define REG_FW_DBG6 0x10F8
#define REG_FW_DBG7 0x10FC
#define FW_KEY_MASK 0xffffff00
#define REG_CR_EXT 0x1100
#define REG_FT1IMR 0x1138
#define BIT_FS_H2C_CMD_OK_INT_EN BIT(25)
#define REG_FT1ISR 0x113c
#define BIT_FS_H2C_CMD_OK_INT BIT(25)
#define REG_DDMA_CH0SA 0x1200
#define REG_DDMA_CH0DA 0x1204
#define REG_DDMA_CH0CTRL 0x1208

24
regd.c
View File

@ -70,16 +70,16 @@ static const struct rtw_regulatory rtw_reg_map[] = {
COUNTRY_REGD_ENT("BY", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("BZ", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("CA", RTW_REGD_IC, RTW_REGD_IC),
COUNTRY_REGD_ENT("CC", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CC", RTW_REGD_ACMA, RTW_REGD_ACMA),
COUNTRY_REGD_ENT("CD", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CF", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CH", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CI", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CK", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CL", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("CL", RTW_REGD_CHILE, RTW_REGD_CHILE),
COUNTRY_REGD_ENT("CM", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("CN", RTW_REGD_CN, RTW_REGD_CN),
COUNTRY_REGD_ENT("CO", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("CR", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("CV", RTW_REGD_ETSI, RTW_REGD_ETSI),
@ -106,7 +106,7 @@ static const struct rtw_regulatory rtw_reg_map[] = {
COUNTRY_REGD_ENT("FO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("FR", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GB", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GB", RTW_REGD_UK, RTW_REGD_UK),
COUNTRY_REGD_ENT("GD", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("GE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("GF", RTW_REGD_ETSI, RTW_REGD_ETSI),
@ -214,7 +214,7 @@ static const struct rtw_regulatory rtw_reg_map[] = {
COUNTRY_REGD_ENT("PT", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("PW", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("PY", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("QA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("QA", RTW_REGD_QATAR, RTW_REGD_QATAR),
COUNTRY_REGD_ENT("RE", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("RO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("RS", RTW_REGD_ETSI, RTW_REGD_ETSI),
@ -234,7 +234,7 @@ static const struct rtw_regulatory rtw_reg_map[] = {
COUNTRY_REGD_ENT("SN", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SO", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SR", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("ST", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("ST", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("SV", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("SX", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("SZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
@ -253,7 +253,7 @@ static const struct rtw_regulatory rtw_reg_map[] = {
COUNTRY_REGD_ENT("TV", RTW_REGD_ETSI, RTW_REGD_WW),
COUNTRY_REGD_ENT("TW", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("TZ", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("UA", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("UA", RTW_REGD_UKRAINE, RTW_REGD_UKRAINE),
COUNTRY_REGD_ENT("UG", RTW_REGD_ETSI, RTW_REGD_ETSI),
COUNTRY_REGD_ENT("US", RTW_REGD_FCC, RTW_REGD_FCC),
COUNTRY_REGD_ENT("UY", RTW_REGD_FCC, RTW_REGD_FCC),
@ -502,6 +502,14 @@ u8 rtw_regd_get(struct rtw_dev *rtwdev)
}
EXPORT_SYMBOL(rtw_regd_get);
bool rtw_regd_srrc(struct rtw_dev *rtwdev)
{
struct rtw_regd *regd = &rtwdev->regd;
return rtw_reg_match(regd->regulatory, "CN");
}
EXPORT_SYMBOL(rtw_regd_srrc);
struct rtw_regd_alternative_t {
bool set;
u8 alt;
@ -519,6 +527,8 @@ rtw_regd_alt[RTW_REGD_MAX] = {
DECL_REGD_ALT(RTW_REGD_UKRAINE, RTW_REGD_ETSI),
DECL_REGD_ALT(RTW_REGD_MEXICO, RTW_REGD_FCC),
DECL_REGD_ALT(RTW_REGD_CN, RTW_REGD_ETSI),
DECL_REGD_ALT(RTW_REGD_QATAR, RTW_REGD_ETSI),
DECL_REGD_ALT(RTW_REGD_UK, RTW_REGD_ETSI),
};
bool rtw_regd_has_alt(u8 regd, u8 *regd_alt)

2
regd.h
View File

@ -68,4 +68,6 @@ int rtw_regd_init(struct rtw_dev *rtwdev);
int rtw_regd_hint(struct rtw_dev *rtwdev);
u8 rtw_regd_get(struct rtw_dev *rtwdev);
bool rtw_regd_has_alt(u8 regd, u8 *regd_alt);
bool rtw_regd_srrc(struct rtw_dev *rtwdev);
#endif

2110
rtw8703b.c Normal file

File diff suppressed because it is too large Load Diff

102
rtw8703b.h Normal file
View File

@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright Fiona Klute <fiona.klute@gmx.de> */
#ifndef __RTW8703B_H__
#define __RTW8703B_H__
#include "rtw8723x.h"
extern const struct rtw_chip_info rtw8703b_hw_spec;
/* phy status parsing */
#define VGA_BITS GENMASK(4, 0)
#define LNA_L_BITS GENMASK(7, 5)
#define LNA_H_BIT BIT(7)
/* masks for assembling LNA index from high and low bits */
#define BIT_LNA_H_MASK BIT(3)
#define BIT_LNA_L_MASK GENMASK(2, 0)
struct phy_rx_agc_info {
#ifdef __LITTLE_ENDIAN
u8 gain: 7;
u8 trsw: 1;
#else
u8 trsw: 1;
u8 gain: 7;
#endif
} __packed;
/* This struct is called phy_status_rpt_8192cd in the vendor driver,
* there might be potential to share it with drivers for other chips
* of the same generation.
*/
struct phy_status_8703b {
struct phy_rx_agc_info path_agc[2];
u8 ch_corr[2];
u8 cck_sig_qual_ofdm_pwdb_all;
/* for CCK: bits 0:4: VGA index, bits 5:7: LNA index (low) */
u8 cck_agc_rpt_ofdm_cfosho_a;
/* for CCK: bit 7 is high bit of LNA index if long report type */
u8 cck_rpt_b_ofdm_cfosho_b;
u8 reserved_1;
u8 noise_power_db_msb;
s8 path_cfotail[2];
u8 pcts_mask[2];
s8 stream_rxevm[2];
u8 path_rxsnr[2];
u8 noise_power_db_lsb;
u8 reserved_2[3];
u8 stream_csi[2];
u8 stream_target_csi[2];
s8 sig_evm;
u8 reserved_3;
#ifdef __LITTLE_ENDIAN
u8 antsel_rx_keep_2: 1;
u8 sgi_en: 1;
u8 rxsc: 2;
u8 idle_long: 1;
u8 r_ant_train_en: 1;
u8 ant_sel_b: 1;
u8 ant_sel: 1;
#else /* __BIG_ENDIAN */
u8 ant_sel: 1;
u8 ant_sel_b: 1;
u8 r_ant_train_en: 1;
u8 idle_long: 1;
u8 rxsc: 2;
u8 sgi_en: 1;
u8 antsel_rx_keep_2: 1;
#endif
} __packed;
/* Baseband registers */
#define REG_BB_PWR_SAV5_11N 0x0818
/* BIT(11) should be 1 for 8703B *and* 8723D, which means LNA uses 4
* bit for CCK rates in report, not 3. Vendor driver logs a warning if
* it's 0, but handles the case.
*
* Purpose of other parts of this register is unknown, 8723cs driver
* code indicates some other chips use certain bits for antenna
* diversity.
*/
#define REG_BB_AMP 0x0950
#define BIT_MASK_RX_LNA (BIT(11))
/* 0xaXX: 40MHz channel settings */
#define REG_CCK_TXSF2 0x0a24 /* CCK TX filter 2 */
#define REG_CCK_DBG 0x0a28 /* debug port */
#define REG_OFDM0_A_TX_AFE 0x0c84
#define REG_TXIQK_MATRIXB_LSB2_11N 0x0c9c
#define REG_OFDM0_TX_PSD_NOISE 0x0ce4 /* TX pseudo noise weighting */
#define REG_IQK_RDY 0x0e90 /* is != 0 when IQK is done */
/* RF registers */
#define RF_RCK1 0x1E
#define AGG_BURST_NUM 3
#define AGG_BURST_SIZE 0 /* 1K */
#define BIT_MASK_AGG_BURST_NUM (GENMASK(3, 2))
#define BIT_MASK_AGG_BURST_SIZE (GENMASK(5, 4))
#endif /* __RTW8703B_H__ */

902
rtw8703b_tables.c Normal file
View File

@ -0,0 +1,902 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright Fiona Klute <fiona.klute@gmx.de> */
#include "main.h"
#include "phy.h"
#include "rtw8703b_tables.h"
static const struct rtw_phy_pg_cfg_pair rtw8703b_bb_pg[] = {
{ 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00003200, },
{ 0, 0, 0, 0x0000086c, 0xffffff00, 0x32323200, },
{ 0, 0, 0, 0x00000e00, 0xffffffff, 0x34363636, },
{ 0, 0, 0, 0x00000e04, 0xffffffff, 0x28303234, },
{ 0, 0, 0, 0x00000e10, 0xffffffff, 0x30343434, },
{ 0, 0, 0, 0x00000e14, 0xffffffff, 0x26262830, },
};
RTW_DECL_TABLE_BB_PG(rtw8703b_bb_pg);
/* Regd: FCC -> 0, ETSI -> 2, MKK -> 1
* Band: 2.4G -> 0, 5G -> 1
* Bandwidth (bw): 20M -> 0, 40M -> 1, 80M -> 2, 160M -> 3
* Rate Section (rs): CCK -> 0, OFDM -> 1, HT -> 2, VHT -> 3
*/
static const struct rtw_txpwr_lmt_cfg_pair rtw8703b_txpwr_lmt[] = {
{0, 0, 0, 0, 1, 30},
{2, 0, 0, 0, 1, 26},
{1, 0, 0, 0, 1, 32},
{0, 0, 0, 0, 2, 30},
{2, 0, 0, 0, 2, 26},
{1, 0, 0, 0, 2, 32},
{0, 0, 0, 0, 3, 30},
{2, 0, 0, 0, 3, 26},
{1, 0, 0, 0, 3, 32},
{0, 0, 0, 0, 4, 30},
{2, 0, 0, 0, 4, 26},
{1, 0, 0, 0, 4, 32},
{0, 0, 0, 0, 5, 30},
{2, 0, 0, 0, 5, 26},
{1, 0, 0, 0, 5, 32},
{0, 0, 0, 0, 6, 30},
{2, 0, 0, 0, 6, 26},
{1, 0, 0, 0, 6, 32},
{0, 0, 0, 0, 7, 30},
{2, 0, 0, 0, 7, 26},
{1, 0, 0, 0, 7, 32},
{0, 0, 0, 0, 8, 30},
{2, 0, 0, 0, 8, 26},
{1, 0, 0, 0, 8, 32},
{0, 0, 0, 0, 9, 30},
{2, 0, 0, 0, 9, 26},
{1, 0, 0, 0, 9, 32},
{0, 0, 0, 0, 10, 30},
{2, 0, 0, 0, 10, 26},
{1, 0, 0, 0, 10, 32},
{0, 0, 0, 0, 11, 30},
{2, 0, 0, 0, 11, 26},
{1, 0, 0, 0, 11, 32},
{0, 0, 0, 0, 12, 63},
{2, 0, 0, 0, 12, 26},
{1, 0, 0, 0, 12, 32},
{0, 0, 0, 0, 13, 63},
{2, 0, 0, 0, 13, 26},
{1, 0, 0, 0, 13, 32},
{0, 0, 0, 0, 14, 63},
{2, 0, 0, 0, 14, 63},
{1, 0, 0, 0, 14, 32},
{0, 0, 0, 1, 1, 28},
{2, 0, 0, 1, 1, 28},
{1, 0, 0, 1, 1, 28},
{0, 0, 0, 1, 2, 28},
{2, 0, 0, 1, 2, 32},
{1, 0, 0, 1, 2, 32},
{0, 0, 0, 1, 3, 32},
{2, 0, 0, 1, 3, 32},
{1, 0, 0, 1, 3, 32},
{0, 0, 0, 1, 4, 32},
{2, 0, 0, 1, 4, 32},
{1, 0, 0, 1, 4, 32},
{0, 0, 0, 1, 5, 32},
{2, 0, 0, 1, 5, 32},
{1, 0, 0, 1, 5, 32},
{0, 0, 0, 1, 6, 32},
{2, 0, 0, 1, 6, 32},
{1, 0, 0, 1, 6, 32},
{0, 0, 0, 1, 7, 32},
{2, 0, 0, 1, 7, 32},
{1, 0, 0, 1, 7, 32},
{0, 0, 0, 1, 8, 32},
{2, 0, 0, 1, 8, 32},
{1, 0, 0, 1, 8, 32},
{0, 0, 0, 1, 9, 32},
{2, 0, 0, 1, 9, 32},
{1, 0, 0, 1, 9, 32},
{0, 0, 0, 1, 10, 28},
{2, 0, 0, 1, 10, 32},
{1, 0, 0, 1, 10, 32},
{0, 0, 0, 1, 11, 28},
{2, 0, 0, 1, 11, 32},
{1, 0, 0, 1, 11, 32},
{0, 0, 0, 1, 12, 63},
{2, 0, 0, 1, 12, 32},
{1, 0, 0, 1, 12, 32},
{0, 0, 0, 1, 13, 63},
{2, 0, 0, 1, 13, 28},
{1, 0, 0, 1, 13, 28},
{0, 0, 0, 1, 14, 63},
{2, 0, 0, 1, 14, 63},
{1, 0, 0, 1, 14, 63},
{0, 0, 0, 2, 1, 26},
{2, 0, 0, 2, 1, 26},
{1, 0, 0, 2, 1, 28},
{0, 0, 0, 2, 2, 26},
{2, 0, 0, 2, 2, 32},
{1, 0, 0, 2, 2, 32},
{0, 0, 0, 2, 3, 32},
{2, 0, 0, 2, 3, 32},
{1, 0, 0, 2, 3, 32},
{0, 0, 0, 2, 4, 32},
{2, 0, 0, 2, 4, 32},
{1, 0, 0, 2, 4, 32},
{0, 0, 0, 2, 5, 32},
{2, 0, 0, 2, 5, 32},
{1, 0, 0, 2, 5, 32},
{0, 0, 0, 2, 6, 32},
{2, 0, 0, 2, 6, 32},
{1, 0, 0, 2, 6, 32},
{0, 0, 0, 2, 7, 32},
{2, 0, 0, 2, 7, 32},
{1, 0, 0, 2, 7, 32},
{0, 0, 0, 2, 8, 32},
{2, 0, 0, 2, 8, 32},
{1, 0, 0, 2, 8, 32},
{0, 0, 0, 2, 9, 32},
{2, 0, 0, 2, 9, 32},
{1, 0, 0, 2, 9, 32},
{0, 0, 0, 2, 10, 26},
{2, 0, 0, 2, 10, 32},
{1, 0, 0, 2, 10, 32},
{0, 0, 0, 2, 11, 26},
{2, 0, 0, 2, 11, 32},
{1, 0, 0, 2, 11, 32},
{0, 0, 0, 2, 12, 63},
{2, 0, 0, 2, 12, 32},
{1, 0, 0, 2, 12, 32},
{0, 0, 0, 2, 13, 63},
{2, 0, 0, 2, 13, 26},
{1, 0, 0, 2, 13, 28},
{0, 0, 0, 2, 14, 63},
{2, 0, 0, 2, 14, 63},
{1, 0, 0, 2, 14, 63},
{0, 0, 1, 2, 1, 63},
{2, 0, 1, 2, 1, 63},
{1, 0, 1, 2, 1, 63},
{0, 0, 1, 2, 2, 63},
{2, 0, 1, 2, 2, 63},
{1, 0, 1, 2, 2, 63},
{0, 0, 1, 2, 3, 26},
{2, 0, 1, 2, 3, 26},
{1, 0, 1, 2, 3, 26},
{0, 0, 1, 2, 4, 26},
{2, 0, 1, 2, 4, 28},
{1, 0, 1, 2, 4, 26},
{0, 0, 1, 2, 5, 28},
{2, 0, 1, 2, 5, 28},
{1, 0, 1, 2, 5, 26},
{0, 0, 1, 2, 6, 28},
{2, 0, 1, 2, 6, 28},
{1, 0, 1, 2, 6, 26},
{0, 0, 1, 2, 7, 28},
{2, 0, 1, 2, 7, 28},
{1, 0, 1, 2, 7, 26},
{0, 0, 1, 2, 8, 26},
{2, 0, 1, 2, 8, 28},
{1, 0, 1, 2, 8, 26},
{0, 0, 1, 2, 9, 26},
{2, 0, 1, 2, 9, 28},
{1, 0, 1, 2, 9, 26},
{0, 0, 1, 2, 10, 26},
{2, 0, 1, 2, 10, 28},
{1, 0, 1, 2, 10, 26},
{0, 0, 1, 2, 11, 26},
{2, 0, 1, 2, 11, 26},
{1, 0, 1, 2, 11, 26},
{0, 0, 1, 2, 12, 63},
{2, 0, 1, 2, 12, 26},
{1, 0, 1, 2, 12, 26},
{0, 0, 1, 2, 13, 63},
{2, 0, 1, 2, 13, 26},
{1, 0, 1, 2, 13, 26},
{0, 0, 1, 2, 14, 63},
{2, 0, 1, 2, 14, 63},
{1, 0, 1, 2, 14, 63},
};
RTW_DECL_TABLE_TXPWR_LMT(rtw8703b_txpwr_lmt);
static const u32 rtw8703b_mac[] = {
0x02F, 0x00000030,
0x035, 0x00000000,
0x067, 0x00000002,
0x092, 0x00000080,
0x421, 0x0000000F,
0x428, 0x0000000A,
0x429, 0x00000010,
0x430, 0x00000000,
0x431, 0x00000000,
0x432, 0x00000000,
0x433, 0x00000001,
0x434, 0x00000002,
0x435, 0x00000003,
0x436, 0x00000005,
0x437, 0x00000007,
0x438, 0x00000000,
0x439, 0x00000000,
0x43A, 0x00000000,
0x43B, 0x00000001,
0x43C, 0x00000002,
0x43D, 0x00000003,
0x43E, 0x00000005,
0x43F, 0x00000007,
0x440, 0x0000005D,
0x441, 0x00000001,
0x442, 0x00000000,
0x444, 0x00000010,
0x445, 0x00000000,
0x446, 0x00000000,
0x447, 0x00000000,
0x448, 0x00000000,
0x449, 0x000000F0,
0x44A, 0x0000000F,
0x44B, 0x0000003E,
0x44C, 0x00000010,
0x44D, 0x00000000,
0x44E, 0x00000000,
0x44F, 0x00000000,
0x450, 0x00000000,
0x451, 0x000000F0,
0x452, 0x0000000F,
0x453, 0x00000000,
0x456, 0x0000005E,
0x460, 0x00000066,
0x461, 0x00000066,
0x4C8, 0x000000FF,
0x4C9, 0x00000008,
0x4CC, 0x000000FF,
0x4CD, 0x000000FF,
0x4CE, 0x00000001,
0x500, 0x00000026,
0x501, 0x000000A2,
0x502, 0x0000002F,
0x503, 0x00000000,
0x504, 0x00000028,
0x505, 0x000000A3,
0x506, 0x0000005E,
0x507, 0x00000000,
0x508, 0x0000002B,
0x509, 0x000000A4,
0x50A, 0x0000005E,
0x50B, 0x00000000,
0x50C, 0x0000004F,
0x50D, 0x000000A4,
0x50E, 0x00000000,
0x50F, 0x00000000,
0x512, 0x0000001C,
0x514, 0x0000000A,
0x516, 0x0000000A,
0x525, 0x0000004F,
0x550, 0x00000010,
0x551, 0x00000010,
0x559, 0x00000002,
0x55C, 0x00000028,
0x55D, 0x000000FF,
0x605, 0x00000030,
0x608, 0x0000000E,
0x609, 0x0000002A,
0x620, 0x000000FF,
0x621, 0x000000FF,
0x622, 0x000000FF,
0x623, 0x000000FF,
0x624, 0x000000FF,
0x625, 0x000000FF,
0x626, 0x000000FF,
0x627, 0x000000FF,
0x638, 0x00000028,
0x63C, 0x0000000A,
0x63D, 0x0000000A,
0x63E, 0x0000000C,
0x63F, 0x0000000C,
0x640, 0x00000040,
0x642, 0x00000040,
0x643, 0x00000000,
0x652, 0x000000C8,
0x66A, 0x000000B0,
0x66E, 0x00000005,
0x700, 0x00000021,
0x701, 0x00000043,
0x702, 0x00000065,
0x703, 0x00000087,
0x708, 0x00000021,
0x709, 0x00000043,
0x70A, 0x00000065,
0x70B, 0x00000087,
0x765, 0x00000018,
0x76E, 0x00000004,
};
RTW_DECL_TABLE_PHY_COND(rtw8703b_mac, rtw_phy_cfg_mac);
static const u32 rtw8703b_agc[] = {
0xC78, 0xFC000101,
0xC78, 0xFB010101,
0xC78, 0xFA020101,
0xC78, 0xF9030101,
0xC78, 0xF8040101,
0xC78, 0xF7050101,
0xC78, 0xF6060101,
0xC78, 0xF5070101,
0xC78, 0xF4080101,
0xC78, 0xF3090101,
0xC78, 0xF20A0101,
0xC78, 0xF10B0101,
0xC78, 0xF00C0101,
0xC78, 0xEF0D0101,
0xC78, 0xEE0E0101,
0xC78, 0xED0F0101,
0xC78, 0xEC100101,
0xC78, 0xEB110101,
0xC78, 0xEA120101,
0xC78, 0xE9130101,
0xC78, 0xE8140101,
0xC78, 0xE7150101,
0xC78, 0xE6160101,
0xC78, 0xE5170101,
0xC78, 0xE4180101,
0xC78, 0xE3190101,
0xC78, 0x661A0101,
0xC78, 0x651B0101,
0xC78, 0x641C0101,
0xC78, 0x631D0101,
0xC78, 0x071E0101,
0xC78, 0x061F0101,
0xC78, 0x05200101,
0xC78, 0x04210101,
0xC78, 0x03220101,
0xC78, 0xE8230001,
0xC78, 0xE7240001,
0xC78, 0xE6250001,
0xC78, 0xE5260001,
0xC78, 0xE4270001,
0xC78, 0x89280001,
0xC78, 0x88290001,
0xC78, 0x872A0001,
0xC78, 0x862B0001,
0xC78, 0x852C0001,
0xC78, 0x482D0001,
0xC78, 0x472E0001,
0xC78, 0x462F0001,
0xC78, 0x45300001,
0xC78, 0x44310001,
0xC78, 0x07320001,
0xC78, 0x06330001,
0xC78, 0x05340001,
0xC78, 0x04350001,
0xC78, 0x03360001,
0xC78, 0x02370001,
0xC78, 0x01380001,
0xC78, 0x00390001,
0xC78, 0x003A0001,
0xC78, 0x003B0001,
0xC78, 0x003C0001,
0xC78, 0x003D0001,
0xC78, 0x003E0001,
0xC78, 0x003F0001,
0xC78, 0x7F002001,
0xC78, 0x7F012001,
0xC78, 0x7F022001,
0xC78, 0x7F032001,
0xC78, 0x7F042001,
0xC78, 0x7F052001,
0xC78, 0x7F062001,
0xC78, 0x7F072001,
0xC78, 0x7F082001,
0xC78, 0x7F092001,
0xC78, 0x7F0A2001,
0xC78, 0x7F0B2001,
0xC78, 0x7F0C2001,
0xC78, 0x7F0D2001,
0xC78, 0x7F0E2001,
0xC78, 0x7F0F2001,
0xC78, 0x7F102001,
0xC78, 0x7F112001,
0xC78, 0x7E122001,
0xC78, 0x7D132001,
0xC78, 0x7C142001,
0xC78, 0x7B152001,
0xC78, 0x7A162001,
0xC78, 0x79172001,
0xC78, 0x78182001,
0xC78, 0x77192001,
0xC78, 0x761A2001,
0xC78, 0x751B2001,
0xC78, 0x741C2001,
0xC78, 0x731D2001,
0xC78, 0x721E2001,
0xC78, 0x711F2001,
0xC78, 0x70202001,
0xC78, 0x6F212001,
0xC78, 0x6E222001,
0xC78, 0x6D232001,
0xC78, 0x6C242001,
0xC78, 0x6B252001,
0xC78, 0x6A262001,
0xC78, 0x69272001,
0xC78, 0x68282001,
0xC78, 0x67292001,
0xC78, 0x662A2001,
0xC78, 0x652B2001,
0xC78, 0x642C2001,
0xC78, 0x632D2001,
0xC78, 0x622E2001,
0xC78, 0x612F2001,
0xC78, 0x60302001,
0xC78, 0x42312001,
0xC78, 0x41322001,
0xC78, 0x40332001,
0xC78, 0x23342001,
0xC78, 0x22352001,
0xC78, 0x21362001,
0xC78, 0x20372001,
0xC78, 0x00382001,
0xC78, 0x02392001,
0xC78, 0x013A2001,
0xC78, 0x003B2001,
0xC78, 0x003C2001,
0xC78, 0x003D2001,
0xC78, 0x003E2001,
0xC78, 0x003F2001,
0xC78, 0x7F003101,
0xC78, 0x7F013101,
0xC78, 0x7F023101,
0xC78, 0x7F033101,
0xC78, 0x7F043101,
0xC78, 0x7F053101,
0xC78, 0x7F063101,
0xC78, 0x7E073101,
0xC78, 0x7D083101,
0xC78, 0x7C093101,
0xC78, 0x7B0A3101,
0xC78, 0x7A0B3101,
0xC78, 0x790C3101,
0xC78, 0x780D3101,
0xC78, 0x770E3101,
0xC78, 0x760F3101,
0xC78, 0x75103101,
0xC78, 0x74113101,
0xC78, 0x73123101,
0xC78, 0x72133101,
0xC78, 0x71143101,
0xC78, 0x70153101,
0xC78, 0x6F163101,
0xC78, 0x69173101,
0xC78, 0x68183101,
0xC78, 0x67193101,
0xC78, 0x661A3101,
0xC78, 0x651B3101,
0xC78, 0x641C3101,
0xC78, 0x631D3101,
0xC78, 0x621E3101,
0xC78, 0x611F3101,
0xC78, 0x60203101,
0xC78, 0x42213101,
0xC78, 0x41223101,
0xC78, 0x40233101,
0xC78, 0x22243101,
0xC78, 0x21253101,
0xC78, 0x20263101,
0xC78, 0x00273101,
0xC78, 0x00283101,
0xC78, 0x00293101,
0xC78, 0x002A3101,
0xC78, 0x002B3101,
0xC78, 0x002C3101,
0xC78, 0x002D3101,
0xC78, 0x002E3101,
0xC78, 0x002F3101,
0xC78, 0x00303101,
0xC78, 0x00313101,
0xC78, 0x00323101,
0xC78, 0x00333101,
0xC78, 0x00343101,
0xC78, 0x00353101,
0xC78, 0x00363101,
0xC78, 0x00373101,
0xC78, 0x00383101,
0xC78, 0x00393101,
0xC78, 0x003A3101,
0xC78, 0x003B3101,
0xC78, 0x003C3101,
0xC78, 0x003D3101,
0xC78, 0x003E3101,
0xC78, 0x003F3101,
0xC78, 0xFA403101,
0xC78, 0xF9413101,
0xC78, 0xF8423101,
0xC78, 0xF7433101,
0xC78, 0xF6443101,
0xC78, 0xF5453101,
0xC78, 0xF4463101,
0xC78, 0xF3473101,
0xC78, 0xF2483101,
0xC78, 0xE1493101,
0xC78, 0xE04A3101,
0xC78, 0xEF4B3101,
0xC78, 0xEE4C3101,
0xC78, 0xED4D3101,
0xC78, 0xEC4E3101,
0xC78, 0xEB4F3101,
0xC78, 0xEA503101,
0xC78, 0xE9513101,
0xC78, 0xE8523101,
0xC78, 0xE7533101,
0xC78, 0xE6543101,
0xC78, 0xE5553101,
0xC78, 0xE4563101,
0xC78, 0xE3573101,
0xC78, 0xE2583101,
0xC78, 0xE1593101,
0xC78, 0xE05A3101,
0xC78, 0xC25B3101,
0xC78, 0xC15C3101,
0xC78, 0xC05D3101,
0xC78, 0x825E3101,
0xC78, 0x815F3101,
0xC78, 0x80603101,
0xC78, 0x80613101,
0xC78, 0x80623101,
0xC78, 0x80633101,
0xC78, 0x80643101,
0xC78, 0x80653101,
0xC78, 0x80663101,
0xC78, 0x80673101,
0xC78, 0x80683101,
0xC78, 0x80693101,
0xC78, 0x806A3101,
0xC78, 0x806B3101,
0xC78, 0x806C3101,
0xC78, 0x806D3101,
0xC78, 0x806E3101,
0xC78, 0x806F3101,
0xC78, 0x80703101,
0xC78, 0x80713101,
0xC78, 0x80723101,
0xC78, 0x80733101,
0xC78, 0x80743101,
0xC78, 0x80753101,
0xC78, 0x80763101,
0xC78, 0x80773101,
0xC78, 0x80783101,
0xC78, 0x80793101,
0xC78, 0x807A3101,
0xC78, 0x807B3101,
0xC78, 0x807C3101,
0xC78, 0x807D3101,
0xC78, 0x807E3101,
0xC78, 0x807F3101,
0xC78, 0xFF402001,
0xC78, 0xFF412001,
0xC78, 0xFF422001,
0xC78, 0xFF432001,
0xC78, 0xFF442001,
0xC78, 0xFF452001,
0xC78, 0xFF462001,
0xC78, 0xFF472001,
0xC78, 0xFF482001,
0xC78, 0xFF492001,
0xC78, 0xFF4A2001,
0xC78, 0xFF4B2001,
0xC78, 0xFF4C2001,
0xC78, 0xFE4D2001,
0xC78, 0xFD4E2001,
0xC78, 0xFC4F2001,
0xC78, 0xFB502001,
0xC78, 0xFA512001,
0xC78, 0xF9522001,
0xC78, 0xF8532001,
0xC78, 0xF7542001,
0xC78, 0xF6552001,
0xC78, 0xF5562001,
0xC78, 0xF4572001,
0xC78, 0xF3582001,
0xC78, 0xF2592001,
0xC78, 0xF15A2001,
0xC78, 0xF05B2001,
0xC78, 0xEF5C2001,
0xC78, 0xEE5D2001,
0xC78, 0xED5E2001,
0xC78, 0xEC5F2001,
0xC78, 0xEB602001,
0xC78, 0xEA612001,
0xC78, 0xE9622001,
0xC78, 0xE8632001,
0xC78, 0xE7642001,
0xC78, 0xE6652001,
0xC78, 0xE5662001,
0xC78, 0xE4672001,
0xC78, 0xE3682001,
0xC78, 0xC5692001,
0xC78, 0xC46A2001,
0xC78, 0xC36B2001,
0xC78, 0xA46C2001,
0xC78, 0x846D2001,
0xC78, 0x836E2001,
0xC78, 0x826F2001,
0xC78, 0x81702001,
0xC78, 0x80712001,
0xC78, 0x80722001,
0xC78, 0x80732001,
0xC78, 0x80742001,
0xC78, 0x80752001,
0xC78, 0x80762001,
0xC78, 0x80772001,
0xC78, 0x80782001,
0xC78, 0x80792001,
0xC78, 0x807A2001,
0xC78, 0x807B2001,
0xC78, 0x807C2001,
0xC78, 0x807D2001,
0xC78, 0x807E2001,
0xC78, 0x807F2001,
0xC50, 0x69553422,
0xC50, 0x69553420,
};
RTW_DECL_TABLE_PHY_COND(rtw8703b_agc, rtw_phy_cfg_agc);
/* init values for BB registers */
static const u32 rtw8703b_bb[] = {
0x800, 0x83045700,
0x804, 0x00000003,
0x808, 0x0000FC00,
0x80C, 0x0000000A,
0x810, 0x10001331,
0x814, 0x020C3D10,
0x818, 0x02200385,
0x81C, 0x00000000,
0x820, 0x01000100,
0x824, 0x00390204,
0x828, 0x00000000,
0x82C, 0x00000000,
0x830, 0x00000000,
0x834, 0x00000000,
0x838, 0x00000000,
0x83C, 0x00000000,
0x840, 0x00010000,
0x844, 0x00000000,
0x848, 0x00000000,
0x84C, 0x00000000,
0x850, 0x00000000,
0x854, 0x00000000,
0x858, 0x569A11A9,
0x85C, 0x01000014,
0x860, 0x66F60110,
0x864, 0x061F0649,
0x868, 0x00000000,
0x86C, 0x27272700,
0x870, 0x07000760,
0x874, 0x25004000,
0x878, 0x00000808,
0x87C, 0x004F0201,
0x880, 0xB0000B1E,
0x884, 0x00000001,
0x888, 0x00000000,
0x88C, 0xCCC000C0,
0x890, 0x00000800,
0x894, 0xFFFFFFFE,
0x898, 0x40302010,
0x89C, 0x00706050,
0x900, 0x00000000,
0x904, 0x00000023,
0x908, 0x00000000,
0x90C, 0x81121111,
0x910, 0x00000002,
0x914, 0x00000201,
0x948, 0x99000000,
0x94C, 0x00000010,
0x950, 0x20003800,
0x954, 0x4A880000,
0x958, 0x4BC5D87A,
0x95C, 0x04EB9B79,
0xA00, 0x00D047C8,
0xA04, 0x80FF800C,
0xA08, 0x8C838300,
0xA0C, 0x2E7F120F,
0xA10, 0x9500BB78,
0xA14, 0x1114D028,
0xA18, 0x00881117,
0xA1C, 0x89140F00,
0xA20, 0xD1D80000,
0xA24, 0x5A7DA0BD,
0xA28, 0x0000223B,
0xA2C, 0x00D30000,
0xA70, 0x101FBF00,
0xA74, 0x00000007,
0xA78, 0x00008900,
0xA7C, 0x225B0606,
0xA80, 0x2180FA74,
0xA84, 0x00120000,
0xA88, 0x040C0000,
0xA8C, 0x12345678,
0xA90, 0xABCDEF00,
0xA94, 0x001B1B89,
0xA98, 0x05100000,
0xA9C, 0x3F000000,
0xAA0, 0x00000000,
0xB2C, 0x00000000,
0xC00, 0x48071D40,
0xC04, 0x03A05611,
0xC08, 0x000000E4,
0xC0C, 0x6C6C6C6C,
0xC10, 0x18800000,
0xC14, 0x40000100,
0xC18, 0x08800000,
0xC1C, 0x40000100,
0xC20, 0x00000000,
0xC24, 0x00000000,
0xC28, 0x00000000,
0xC2C, 0x00000000,
0xC30, 0x69E9AC4B,
0xC34, 0x31000040,
0xC38, 0x21688080,
0xC3C, 0x000016CC,
0xC40, 0x1F78403F,
0xC44, 0x00010036,
0xC48, 0xEC020107,
0xC4C, 0x007F037F,
0xC50, 0x69553420,
0xC54, 0x43BC0094,
0xC58, 0x00015967,
0xC5C, 0x18250492,
0xC60, 0x00000000,
0xC64, 0x7112848B,
0xC68, 0x47C07BFF,
0xC6C, 0x00000036,
0xC70, 0x2C7F000D,
0xC74, 0x020600DB,
0xC78, 0x0000001F,
0xC7C, 0x00B91612,
0xC80, 0x390000E4,
0xC84, 0x19F60000,
0xC88, 0x40000100,
0xC8C, 0x20200000,
0xC90, 0x00091521,
0xC94, 0x00000000,
0xC98, 0x00121820,
0xC9C, 0x00007F7F,
0xCA0, 0x00000000,
0xCA4, 0x000300A0,
0xCA8, 0x00000000,
0xCAC, 0x00000000,
0xCB0, 0x00000000,
0xCB4, 0x00000000,
0xCB8, 0x00000000,
0xCBC, 0x28000000,
0xCC0, 0x00000000,
0xCC4, 0x00000000,
0xCC8, 0x00000000,
0xCCC, 0x00000000,
0xCD0, 0x00000000,
0xCD4, 0x00000000,
0xCD8, 0x64B22427,
0xCDC, 0x00766932,
0xCE0, 0x00222222,
0xCE4, 0x10000000,
0xCE8, 0x37644302,
0xCEC, 0x2F97D40C,
0xD00, 0x00030740,
0xD04, 0x40020401,
0xD08, 0x0000907F,
0xD0C, 0x20010201,
0xD10, 0xA0633333,
0xD14, 0x3333BC53,
0xD18, 0x7A8F5B6F,
0xD2C, 0xCB979975,
0xD30, 0x00000000,
0xD34, 0x80608000,
0xD38, 0x98000000,
0xD3C, 0x40127353,
0xD40, 0x00000000,
0xD44, 0x00000000,
0xD48, 0x00000000,
0xD4C, 0x00000000,
0xD50, 0x6437140A,
0xD54, 0x00000000,
0xD58, 0x00000282,
0xD5C, 0x30032064,
0xD60, 0x4653DE68,
0xD64, 0x04518A3C,
0xD68, 0x00002101,
0xE00, 0x2D2D2D2D,
0xE04, 0x2D2D2D2D,
0xE08, 0x0390272D,
0xE10, 0x2D2D2D2D,
0xE14, 0x2D2D2D2D,
0xE18, 0x2D2D2D2D,
0xE1C, 0x2D2D2D2D,
0xE28, 0x00000000,
0xE30, 0x1000DC1F,
0xE34, 0x10008C1F,
0xE38, 0x02140102,
0xE3C, 0x681604C2,
0xE40, 0x01007C00,
0xE44, 0x01004800,
0xE48, 0xFB000000,
0xE4C, 0x000028D1,
0xE50, 0x1000DC1F,
0xE54, 0x10008C1F,
0xE58, 0x02140102,
0xE5C, 0x28160D05,
0xE60, 0x00000048,
0xE68, 0x001B25A4,
0xE6C, 0x01C00014,
0xE70, 0x01C00014,
0xE74, 0x02000014,
0xE78, 0x02000014,
0xE7C, 0x02000014,
0xE80, 0x02000014,
0xE84, 0x01C00014,
0xE88, 0x02000014,
0xE8C, 0x01C00014,
0xED0, 0x01C00014,
0xED4, 0x01C00014,
0xED8, 0x01C00014,
0xEDC, 0x00000014,
0xEE0, 0x00000014,
0xEE8, 0x21555448,
0xEEC, 0x03C00014,
0xF14, 0x00000003,
0xF4C, 0x00000000,
0xF00, 0x00000300,
};
RTW_DECL_TABLE_PHY_COND(rtw8703b_bb, rtw_phy_cfg_bb);
static const u32 rtw8703b_rf_a[] = {
0x018, 0x00008C01,
0x0B5, 0x0008C050,
0x0B1, 0x00054258,
0x0B2, 0x00054C00,
0x030, 0x00018000,
0x031, 0x00000027,
0x032, 0x000A7F07,
0x030, 0x00020000,
0x031, 0x00000027,
0x032, 0x000E7D87,
0x01C, 0x000F8635,
0x0EF, 0x00080000,
0x030, 0x00008000,
0x031, 0x00000004,
0x032, 0x00006105,
0x0EF, 0x00000000,
0x0EF, 0x00000400,
0x041, 0x0000BD54,
0x041, 0x00003DD4,
0x041, 0x0000FDD4,
0x0EF, 0x00000000,
0x0DF, 0x00000600,
0x050, 0x0000C6DB,
0x051, 0x00004505,
0x052, 0x0000E31D,
0x053, 0x00040579,
0x054, 0x00000000,
0x055, 0x0008206E,
0x056, 0x00040000,
0x0EF, 0x00000100,
0x034, 0x0000ADD7,
0x034, 0x00009DD4,
0x034, 0x00008DD1,
0x034, 0x00007DCE,
0x034, 0x00006DCB,
0x034, 0x00005CCE,
0x034, 0x000048CD,
0x034, 0x000034CC,
0x034, 0x0000244F,
0x034, 0x0000144C,
0x034, 0x0000004E,
0x0EF, 0x00000000,
0x0EF, 0x00002000,
0x03B, 0x0003801F,
0x03B, 0x00030002,
0x03B, 0x00028001,
0x03B, 0x00020000,
0x03B, 0x00018003,
0x03B, 0x00010002,
0x03B, 0x00008001,
0x03B, 0x00000000,
0x0EF, 0x00000000,
0x082, 0x000C0000,
0x083, 0x000AF025,
0x01E, 0x00000C08,
};
RTW_DECL_TABLE_RF_RADIO(rtw8703b_rf_a, A);

14
rtw8703b_tables.h Normal file
View File

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright Fiona Klute <fiona.klute@gmx.de> */
#ifndef __RTW8703B_TABLES_H__
#define __RTW8703B_TABLES_H__
extern const struct rtw_table rtw8703b_bb_pg_tbl;
extern const struct rtw_table rtw8703b_txpwr_lmt_tbl;
extern const struct rtw_table rtw8703b_mac_tbl;
extern const struct rtw_table rtw8703b_agc_tbl;
extern const struct rtw_table rtw8703b_bb_tbl;
extern const struct rtw_table rtw8703b_rf_a_tbl;
#endif

34
rtw8723cs.c Normal file
View File

@ -0,0 +1,34 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright Fiona Klute <fiona.klute@gmx.de> */
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/module.h>
#include "main.h"
#include "rtw8703b.h"
#include "sdio.h"
static const struct sdio_device_id rtw_8723cs_id_table[] = {
{
SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK,
SDIO_DEVICE_ID_REALTEK_RTW8723CS),
.driver_data = (kernel_ulong_t)&rtw8703b_hw_spec,
},
{}
};
MODULE_DEVICE_TABLE(sdio, rtw_8723cs_id_table);
static struct sdio_driver rtw_8723cs_driver = {
.name = "rtw8723cs",
.id_table = rtw_8723cs_id_table,
.probe = rtw_sdio_probe,
.remove = rtw_sdio_remove,
.drv = {
.pm = &rtw_sdio_pm_ops,
.shutdown = rtw_sdio_shutdown
}};
module_sdio_driver(rtw_8723cs_driver);
MODULE_AUTHOR("Fiona Klute <fiona.klute@gmx.de>");
MODULE_DESCRIPTION("Realtek 802.11n wireless 8723cs driver");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -9,36 +9,13 @@
#include "tx.h"
#include "rx.h"
#include "phy.h"
#include "rtw8723x.h"
#include "rtw8723d.h"
#include "rtw8723d_table.h"
#include "mac.h"
#include "reg.h"
#include "debug.h"
static const struct rtw_hw_reg rtw8723d_txagc[] = {
[DESC_RATE1M] = { .addr = 0xe08, .mask = 0x0000ff00 },
[DESC_RATE2M] = { .addr = 0x86c, .mask = 0x0000ff00 },
[DESC_RATE5_5M] = { .addr = 0x86c, .mask = 0x00ff0000 },
[DESC_RATE11M] = { .addr = 0x86c, .mask = 0xff000000 },
[DESC_RATE6M] = { .addr = 0xe00, .mask = 0x000000ff },
[DESC_RATE9M] = { .addr = 0xe00, .mask = 0x0000ff00 },
[DESC_RATE12M] = { .addr = 0xe00, .mask = 0x00ff0000 },
[DESC_RATE18M] = { .addr = 0xe00, .mask = 0xff000000 },
[DESC_RATE24M] = { .addr = 0xe04, .mask = 0x000000ff },
[DESC_RATE36M] = { .addr = 0xe04, .mask = 0x0000ff00 },
[DESC_RATE48M] = { .addr = 0xe04, .mask = 0x00ff0000 },
[DESC_RATE54M] = { .addr = 0xe04, .mask = 0xff000000 },
[DESC_RATEMCS0] = { .addr = 0xe10, .mask = 0x000000ff },
[DESC_RATEMCS1] = { .addr = 0xe10, .mask = 0x0000ff00 },
[DESC_RATEMCS2] = { .addr = 0xe10, .mask = 0x00ff0000 },
[DESC_RATEMCS3] = { .addr = 0xe10, .mask = 0xff000000 },
[DESC_RATEMCS4] = { .addr = 0xe14, .mask = 0x000000ff },
[DESC_RATEMCS5] = { .addr = 0xe14, .mask = 0x0000ff00 },
[DESC_RATEMCS6] = { .addr = 0xe14, .mask = 0x00ff0000 },
[DESC_RATEMCS7] = { .addr = 0xe14, .mask = 0xff000000 },
};
#define WLAN_TXQ_RPT_EN 0x1F
#define WLAN_SLOT_TIME 0x09
#define WLAN_RL_VAL 0x3030
#define WLAN_BAR_VAL 0x0201ffff
@ -65,34 +42,6 @@ static const struct rtw_hw_reg rtw8723d_txagc[] = {
#define WLAN_LTR_CTRL1 0xCB004010
#define WLAN_LTR_CTRL2 0x01233425
static void rtw8723d_lck(struct rtw_dev *rtwdev)
{
u32 lc_cal;
u8 val_ctx, rf_val;
int ret;
val_ctx = rtw_read8(rtwdev, REG_CTX);
if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE);
else
rtw_write8(rtwdev, REG_TXPAUSE, 0xFF);
lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK);
ret = read_poll_timeout(rtw_read_rf, rf_val, rf_val != 0x1,
10000, 1000000, false,
rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK);
if (ret)
rtw_warn(rtwdev, "failed to poll LCK status bit\n");
rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
rtw_write8(rtwdev, REG_CTX, val_ctx);
else
rtw_write8(rtwdev, REG_TXPAUSE, 0x00);
}
static const u32 rtw8723d_ofdm_swing_table[] = {
0x0b40002d, 0x0c000030, 0x0cc00033, 0x0d800036, 0x0e400039, 0x0f00003c,
0x10000040, 0x11000044, 0x12000048, 0x1300004c, 0x14400051, 0x15800056,
@ -196,7 +145,7 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
rtw_write16_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN);
rtw8723d_lck(rtwdev);
rtw8723x_lck(rtwdev);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x20);
@ -204,67 +153,6 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
rtw8723d_pwrtrack_init(rtwdev);
}
static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723d_efuse *map)
{
ether_addr_copy(efuse->addr, map->e.mac_addr);
}
static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723d_efuse *map)
{
ether_addr_copy(efuse->addr, map->u.mac_addr);
}
static void rtw8723ds_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723d_efuse *map)
{
ether_addr_copy(efuse->addr, map->s.mac_addr);
}
static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw8723d_efuse *map;
int i;
map = (struct rtw8723d_efuse *)log_map;
efuse->rfe_option = 0;
efuse->rf_board_option = map->rf_board_option;
efuse->crystal_cap = map->xtal_k;
efuse->pa_type_2g = map->pa_type;
efuse->lna_type_2g = map->lna_type_2g[0];
efuse->channel_plan = map->channel_plan;
efuse->country_code[0] = map->country_code[0];
efuse->country_code[1] = map->country_code[1];
efuse->bt_setting = map->rf_bt_setting;
efuse->regd = map->rf_board_option & 0x7;
efuse->thermal_meter[0] = map->thermal_meter;
efuse->thermal_meter_k = map->thermal_meter;
efuse->afe = map->afe;
for (i = 0; i < 4; i++)
efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
switch (rtw_hci_type(rtwdev)) {
case RTW_HCI_TYPE_PCIE:
rtw8723de_efuse_parsing(efuse, map);
break;
case RTW_HCI_TYPE_USB:
rtw8723du_efuse_parsing(efuse, map);
break;
case RTW_HCI_TYPE_SDIO:
rtw8723ds_efuse_parsing(efuse, map);
break;
default:
/* unsupported now */
return -ENOTSUPP;
}
return 0;
}
static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
@ -540,297 +428,11 @@ static void rtw8723d_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw8723d_set_channel_bb(rtwdev, channel, bw, primary_chan_idx);
}
#define BIT_CFENDFORM BIT(9)
#define BIT_WMAC_TCR_ERR0 BIT(12)
#define BIT_WMAC_TCR_ERR1 BIT(13)
#define BIT_TCR_CFG (BIT_CFENDFORM | BIT_WMAC_TCR_ERR0 | \
BIT_WMAC_TCR_ERR1)
#define WLAN_RX_FILTER0 0xFFFF
#define WLAN_RX_FILTER1 0x400
#define WLAN_RX_FILTER2 0xFFFF
#define WLAN_RCR_CFG 0x700060CE
static int rtw8723d_mac_init(struct rtw_dev *rtwdev)
{
rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, WLAN_TXQ_RPT_EN);
rtw_write32(rtwdev, REG_TCR, BIT_TCR_CFG);
rtw_write16(rtwdev, REG_RXFLTMAP0, WLAN_RX_FILTER0);
rtw_write16(rtwdev, REG_RXFLTMAP1, WLAN_RX_FILTER1);
rtw_write16(rtwdev, REG_RXFLTMAP2, WLAN_RX_FILTER2);
rtw_write32(rtwdev, REG_RCR, WLAN_RCR_CFG);
rtw_write32(rtwdev, REG_INT_MIG, 0);
rtw_write32(rtwdev, REG_MCUTST_1, 0x0);
rtw_write8(rtwdev, REG_MISC_CTRL, BIT_DIS_SECOND_CCA);
rtw_write8(rtwdev, REG_2ND_CCA_CTRL, 0);
return 0;
}
static void rtw8723d_shutdown(struct rtw_dev *rtwdev)
{
rtw_write16_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS);
}
static void rtw8723d_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
{
u8 ldo_pwr;
ldo_pwr = rtw_read8(rtwdev, REG_LDO_EFUSE_CTRL + 3);
if (enable) {
ldo_pwr &= ~BIT_MASK_LDO25_VOLTAGE;
ldo_pwr |= (BIT_LDO25_VOLTAGE_V25 << 4) | BIT_LDO25_EN;
} else {
ldo_pwr &= ~BIT_LDO25_EN;
}
rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr);
}
static void
rtw8723d_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
{
struct rtw_hal *hal = &rtwdev->hal;
const struct rtw_hw_reg *txagc;
u8 rate, pwr_index;
int j;
for (j = 0; j < rtw_rate_size[rs]; j++) {
rate = rtw_rate_section[rs][j];
pwr_index = hal->tx_pwr_tbl[path][rate];
if (rate >= ARRAY_SIZE(rtw8723d_txagc)) {
rtw_warn(rtwdev, "rate 0x%x isn't supported\n", rate);
continue;
}
txagc = &rtw8723d_txagc[rate];
if (!txagc->addr) {
rtw_warn(rtwdev, "rate 0x%x isn't defined\n", rate);
continue;
}
rtw_write32_mask(rtwdev, txagc->addr, txagc->mask, pwr_index);
}
}
static void rtw8723d_set_tx_power_index(struct rtw_dev *rtwdev)
{
struct rtw_hal *hal = &rtwdev->hal;
int rs, path;
for (path = 0; path < hal->rf_path_num; path++) {
for (rs = 0; rs <= RTW_RATE_SECTION_HT_1S; rs++)
rtw8723d_set_tx_power_index_by_rate(rtwdev, path, rs);
}
}
static void rtw8723d_efuse_grant(struct rtw_dev *rtwdev, bool on)
{
if (on) {
rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR);
rtw_write16_set(rtwdev, REG_SYS_CLKR, BIT_LOADER_CLK_EN | BIT_ANA8M);
} else {
rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
}
}
static void rtw8723d_false_alarm_statistics(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
u32 crc32_cnt;
u32 val32;
/* hold counter */
rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 1);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KEEP, 1);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KEEP, 1);
cck_fa_cnt = rtw_read32_mask(rtwdev, REG_CCK_FA_LSB_11N, MASKBYTE0);
cck_fa_cnt += rtw_read32_mask(rtwdev, REG_CCK_FA_MSB_11N, MASKBYTE3) << 8;
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE1_11N);
ofdm_fa_cnt = u32_get_bits(val32, BIT_MASK_OFDM_FF_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_SF_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE2_11N);
dm_info->ofdm_cca_cnt = u32_get_bits(val32, BIT_MASK_OFDM_CCA_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_PF_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE3_11N);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_RI_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_CRC_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE4_11N);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_MNS_CNT);
dm_info->cck_fa_cnt = cck_fa_cnt;
dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
dm_info->total_fa_cnt = cck_fa_cnt + ofdm_fa_cnt;
dm_info->cck_err_cnt = rtw_read32(rtwdev, REG_IGI_C_11N);
dm_info->cck_ok_cnt = rtw_read32(rtwdev, REG_IGI_D_11N);
crc32_cnt = rtw_read32(rtwdev, REG_OFDM_CRC32_CNT_11N);
dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_ERR);
dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_OK);
crc32_cnt = rtw_read32(rtwdev, REG_HT_CRC32_CNT_11N);
dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_ERR);
dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_OK);
dm_info->vht_err_cnt = 0;
dm_info->vht_ok_cnt = 0;
val32 = rtw_read32(rtwdev, REG_CCK_CCA_CNT_11N);
dm_info->cck_cca_cnt = (u32_get_bits(val32, BIT_MASK_CCK_FA_MSB) << 8) |
u32_get_bits(val32, BIT_MASK_CCK_FA_LSB);
dm_info->total_cca_cnt = dm_info->cck_cca_cnt + dm_info->ofdm_cca_cnt;
/* reset counter */
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 2);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 2);
rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 1);
rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0);
}
static const u32 iqk_adda_regs[] = {
0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec
};
static const u32 iqk_mac8_regs[] = {0x522, 0x550, 0x551};
static const u32 iqk_mac32_regs[] = {0x40};
static const u32 iqk_bb_regs[] = {
0xc04, 0xc08, 0x874, 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0xa04
};
#define IQK_ADDA_REG_NUM ARRAY_SIZE(iqk_adda_regs)
#define IQK_MAC8_REG_NUM ARRAY_SIZE(iqk_mac8_regs)
#define IQK_MAC32_REG_NUM ARRAY_SIZE(iqk_mac32_regs)
#define IQK_BB_REG_NUM ARRAY_SIZE(iqk_bb_regs)
struct iqk_backup_regs {
u32 adda[IQK_ADDA_REG_NUM];
u8 mac8[IQK_MAC8_REG_NUM];
u32 mac32[IQK_MAC32_REG_NUM];
u32 bb[IQK_BB_REG_NUM];
u32 lte_path;
u32 lte_gnt;
u32 bb_sel_btg;
u8 btg_sel;
u8 igia;
u8 igib;
};
static void rtw8723d_iqk_backup_regs(struct rtw_dev *rtwdev,
struct iqk_backup_regs *backup)
{
int i;
for (i = 0; i < IQK_ADDA_REG_NUM; i++)
backup->adda[i] = rtw_read32(rtwdev, iqk_adda_regs[i]);
for (i = 0; i < IQK_MAC8_REG_NUM; i++)
backup->mac8[i] = rtw_read8(rtwdev, iqk_mac8_regs[i]);
for (i = 0; i < IQK_MAC32_REG_NUM; i++)
backup->mac32[i] = rtw_read32(rtwdev, iqk_mac32_regs[i]);
for (i = 0; i < IQK_BB_REG_NUM; i++)
backup->bb[i] = rtw_read32(rtwdev, iqk_bb_regs[i]);
backup->igia = rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0);
backup->igib = rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0);
backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);
}
static void rtw8723d_iqk_restore_regs(struct rtw_dev *rtwdev,
const struct iqk_backup_regs *backup)
{
int i;
for (i = 0; i < IQK_ADDA_REG_NUM; i++)
rtw_write32(rtwdev, iqk_adda_regs[i], backup->adda[i]);
for (i = 0; i < IQK_MAC8_REG_NUM; i++)
rtw_write8(rtwdev, iqk_mac8_regs[i], backup->mac8[i]);
for (i = 0; i < IQK_MAC32_REG_NUM; i++)
rtw_write32(rtwdev, iqk_mac32_regs[i], backup->mac32[i]);
for (i = 0; i < IQK_BB_REG_NUM; i++)
rtw_write32(rtwdev, iqk_bb_regs[i], backup->bb[i]);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, backup->igia);
rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, backup->igib);
rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x01008c00);
rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x01008c00);
}
static void rtw8723d_iqk_backup_path_ctrl(struct rtw_dev *rtwdev,
struct iqk_backup_regs *backup)
{
backup->btg_sel = rtw_read8(rtwdev, REG_BTG_SEL);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] original 0x67 = 0x%x\n",
backup->btg_sel);
}
static void rtw8723d_iqk_config_path_ctrl(struct rtw_dev *rtwdev)
{
rtw_write32_mask(rtwdev, REG_PAD_CTRL1, BIT_BT_BTG_SEL, 0x1);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] set 0x67 = 0x%x\n",
rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
}
static void rtw8723d_iqk_restore_path_ctrl(struct rtw_dev *rtwdev,
const struct iqk_backup_regs *backup)
{
rtw_write8(rtwdev, REG_BTG_SEL, backup->btg_sel);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] restore 0x67 = 0x%x\n",
rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
}
static void rtw8723d_iqk_backup_lte_path_gnt(struct rtw_dev *rtwdev,
struct iqk_backup_regs *backup)
{
backup->lte_path = rtw_read32(rtwdev, REG_LTECOEX_PATH_CONTROL);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0038);
mdelay(1);
backup->lte_gnt = rtw_read32(rtwdev, REG_LTECOEX_READ_DATA);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] OriginalGNT = 0x%x\n",
backup->lte_gnt);
}
static void rtw8723d_iqk_config_lte_path_gnt(struct rtw_dev *rtwdev)
{
rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, 0x0000ff00);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc0020038);
rtw_write32_mask(rtwdev, REG_LTECOEX_PATH_CONTROL, BIT_LTE_MUX_CTRL_PATH, 0x1);
}
static void rtw8723d_iqk_restore_lte_path_gnt(struct rtw_dev *rtwdev,
const struct iqk_backup_regs *bak)
{
rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, bak->lte_gnt);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc00f0038);
rtw_write32(rtwdev, REG_LTECOEX_PATH_CONTROL, bak->lte_path);
}
struct rtw_8723d_iqk_cfg {
const char *name;
u32 val_bb_sel_btg;
@ -930,6 +532,8 @@ static u8 rtw8723d_iqk_check_rx_failed(struct rtw_dev *rtwdev,
return 0;
}
#define IQK_LTE_WRITE_VAL_8723D 0x0000ff00
static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx,
const struct rtw_8723d_iqk_cfg *iqk_cfg)
{
@ -937,7 +541,7 @@ static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx,
/* enter IQK mode */
rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
rtw8723d_iqk_config_lte_path_gnt(rtwdev);
rtw8723x_iqk_config_lte_path_gnt(rtwdev, IQK_LTE_WRITE_VAL_8723D);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0054);
mdelay(1);
@ -959,9 +563,9 @@ static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx,
static void rtw8723d_iqk_txrx_path_post(struct rtw_dev *rtwdev,
const struct rtw_8723d_iqk_cfg *iqk_cfg,
const struct iqk_backup_regs *backup)
const struct rtw8723x_iqk_backup_regs *backup)
{
rtw8723d_iqk_restore_lte_path_gnt(rtwdev, backup);
rtw8723x_iqk_restore_lte_path_gnt(rtwdev, backup);
rtw_write32(rtwdev, REG_BB_SEL_BTG, backup->bb_sel_btg);
/* leave IQK mode */
@ -974,7 +578,7 @@ static void rtw8723d_iqk_txrx_path_post(struct rtw_dev *rtwdev,
static u8 rtw8723d_iqk_tx_path(struct rtw_dev *rtwdev,
const struct rtw_8723d_iqk_cfg *iqk_cfg,
const struct iqk_backup_regs *backup)
const struct rtw8723x_iqk_backup_regs *backup)
{
u8 status;
@ -1033,7 +637,7 @@ static u8 rtw8723d_iqk_tx_path(struct rtw_dev *rtwdev,
static u8 rtw8723d_iqk_rx_path(struct rtw_dev *rtwdev,
const struct rtw_8723d_iqk_cfg *iqk_cfg,
const struct iqk_backup_regs *backup)
const struct rtw8723x_iqk_backup_regs *backup)
{
u32 tx_x, tx_y;
u8 status;
@ -1220,14 +824,6 @@ void rtw8723d_iqk_fill_s0_matrix(struct rtw_dev *rtwdev, const s32 result[])
result[IQK_S0_RX_Y]);
}
static void rtw8723d_iqk_path_adda_on(struct rtw_dev *rtwdev)
{
int i;
for (i = 0; i < IQK_ADDA_REG_NUM; i++)
rtw_write32(rtwdev, iqk_adda_regs[i], 0x03c00016);
}
static void rtw8723d_iqk_config_mac(struct rtw_dev *rtwdev)
{
rtw_write8(rtwdev, REG_TXPAUSE, 0xff);
@ -1245,70 +841,14 @@ void rtw8723d_iqk_rf_standby(struct rtw_dev *rtwdev, enum rtw_rf_path path)
rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
}
static
bool rtw8723d_iqk_similarity_cmp(struct rtw_dev *rtwdev, s32 result[][IQK_NR],
u8 c1, u8 c2)
{
u32 i, j, diff;
u32 bitmap = 0;
u8 candidate[PATH_NR] = {IQK_ROUND_INVALID, IQK_ROUND_INVALID};
bool ret = true;
s32 tmp1, tmp2;
for (i = 0; i < IQK_NR; i++) {
tmp1 = iqkxy_to_s32(result[c1][i]);
tmp2 = iqkxy_to_s32(result[c2][i]);
diff = abs(tmp1 - tmp2);
if (diff <= MAX_TOLERANCE)
continue;
if ((i == IQK_S1_RX_X || i == IQK_S0_RX_X) && !bitmap) {
if (result[c1][i] + result[c1][i + 1] == 0)
candidate[i / IQK_SX_NR] = c2;
else if (result[c2][i] + result[c2][i + 1] == 0)
candidate[i / IQK_SX_NR] = c1;
else
bitmap |= BIT(i);
} else {
bitmap |= BIT(i);
}
}
if (bitmap != 0)
goto check_sim;
for (i = 0; i < PATH_NR; i++) {
if (candidate[i] == IQK_ROUND_INVALID)
continue;
for (j = i * IQK_SX_NR; j < i * IQK_SX_NR + 2; j++)
result[IQK_ROUND_HYBRID][j] = result[candidate[i]][j];
ret = false;
}
return ret;
check_sim:
for (i = 0; i < IQK_NR; i++) {
j = i & ~1; /* 2 bits are a pair for IQ[X, Y] */
if (bitmap & GENMASK(j + 1, j))
continue;
result[IQK_ROUND_HYBRID][i] = result[c1][i];
}
return false;
}
#define ADDA_ON_VAL_8723D 0x03c00016
static
void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723d_path path)
void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723x_path path)
{
if (path == PATH_S0) {
rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_A);
rtw8723d_iqk_path_adda_on(rtwdev);
rtw8723x_iqk_path_adda_on(rtwdev, ADDA_ON_VAL_8723D);
}
rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
@ -1317,13 +857,13 @@ void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723d_path path)
if (path == PATH_S1) {
rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_B);
rtw8723d_iqk_path_adda_on(rtwdev);
rtw8723x_iqk_path_adda_on(rtwdev, ADDA_ON_VAL_8723D);
}
}
static
void rtw8723d_iqk_one_round(struct rtw_dev *rtwdev, s32 result[][IQK_NR], u8 t,
const struct iqk_backup_regs *backup)
const struct rtw8723x_iqk_backup_regs *backup)
{
u32 i;
u8 s1_ok, s0_ok;
@ -1331,7 +871,7 @@ void rtw8723d_iqk_one_round(struct rtw_dev *rtwdev, s32 result[][IQK_NR], u8 t,
rtw_dbg(rtwdev, RTW_DBG_RFK,
"[IQK] IQ Calibration for 1T1R_S0/S1 for %d times\n", t);
rtw8723d_iqk_path_adda_on(rtwdev);
rtw8723x_iqk_path_adda_on(rtwdev, ADDA_ON_VAL_8723D);
rtw8723d_iqk_config_mac(rtwdev);
rtw_write32_mask(rtwdev, REG_CCK_ANT_SEL_11N, 0x0f000000, 0xf);
rtw_write32(rtwdev, REG_BB_RX_PATH_11N, 0x03a05611);
@ -1427,7 +967,7 @@ static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
s32 result[IQK_ROUND_SIZE][IQK_NR];
struct iqk_backup_regs backup;
struct rtw8723x_iqk_backup_regs backup;
u8 i, j;
u8 final_candidate = IQK_ROUND_INVALID;
bool good;
@ -1436,23 +976,23 @@ static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev)
memset(result, 0, sizeof(result));
rtw8723d_iqk_backup_path_ctrl(rtwdev, &backup);
rtw8723d_iqk_backup_lte_path_gnt(rtwdev, &backup);
rtw8723d_iqk_backup_regs(rtwdev, &backup);
rtw8723x_iqk_backup_path_ctrl(rtwdev, &backup);
rtw8723x_iqk_backup_lte_path_gnt(rtwdev, &backup);
rtw8723x_iqk_backup_regs(rtwdev, &backup);
for (i = IQK_ROUND_0; i <= IQK_ROUND_2; i++) {
rtw8723d_iqk_config_path_ctrl(rtwdev);
rtw8723d_iqk_config_lte_path_gnt(rtwdev);
rtw8723x_iqk_config_path_ctrl(rtwdev);
rtw8723x_iqk_config_lte_path_gnt(rtwdev, IQK_LTE_WRITE_VAL_8723D);
rtw8723d_iqk_one_round(rtwdev, result, i, &backup);
if (i > IQK_ROUND_0)
rtw8723d_iqk_restore_regs(rtwdev, &backup);
rtw8723d_iqk_restore_lte_path_gnt(rtwdev, &backup);
rtw8723d_iqk_restore_path_ctrl(rtwdev, &backup);
rtw8723x_iqk_restore_regs(rtwdev, &backup);
rtw8723x_iqk_restore_lte_path_gnt(rtwdev, &backup);
rtw8723x_iqk_restore_path_ctrl(rtwdev, &backup);
for (j = IQK_ROUND_0; j < i; j++) {
good = rtw8723d_iqk_similarity_cmp(rtwdev, result, j, i);
good = rtw8723x_iqk_similarity_cmp(rtwdev, result, j, i);
if (good) {
final_candidate = j;
@ -1546,26 +1086,6 @@ static void rtw8723d_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
}
/* for coex */
static void rtw8723d_coex_cfg_init(struct rtw_dev *rtwdev)
{
/* enable TBTT nterrupt */
rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
/* BT report packet sample rate */
/* 0x790[5:0]=0x5 */
rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
/* enable BT counter statistics */
rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
/* enable PTA (3-wire function form BT side) */
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS);
/* enable PTA (tx/rx signal form WiFi side) */
rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
}
static void rtw8723d_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
{
}
@ -1671,39 +1191,6 @@ static void rtw8723d_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
}
}
static u8 rtw8723d_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u8 tx_rate = dm_info->tx_rate;
u8 limit_ofdm = 30;
switch (tx_rate) {
case DESC_RATE1M...DESC_RATE5_5M:
case DESC_RATE11M:
break;
case DESC_RATE6M...DESC_RATE48M:
limit_ofdm = 36;
break;
case DESC_RATE54M:
limit_ofdm = 34;
break;
case DESC_RATEMCS0...DESC_RATEMCS2:
limit_ofdm = 38;
break;
case DESC_RATEMCS3...DESC_RATEMCS4:
limit_ofdm = 36;
break;
case DESC_RATEMCS5...DESC_RATEMCS7:
limit_ofdm = 34;
break;
default:
rtw_warn(rtwdev, "pwrtrack unhandled tx_rate 0x%x\n", tx_rate);
break;
}
return limit_ofdm;
}
static void rtw8723d_set_iqk_matrix_by_result(struct rtw_dev *rtwdev,
u32 ofdm_swing, u8 rf_path)
{
@ -1845,7 +1332,7 @@ static void rtw8723d_pwrtrack_set(struct rtw_dev *rtwdev, u8 path)
s8 final_ofdm_swing_index;
s8 final_cck_swing_index;
limit_ofdm = rtw8723d_pwrtrack_get_limit_ofdm(rtwdev);
limit_ofdm = rtw8723x_pwrtrack_get_limit_ofdm(rtwdev);
final_ofdm_swing_index = RTW_DEF_OFDM_SWING_INDEX +
dm_info->delta_power_index[path];
@ -1873,26 +1360,6 @@ static void rtw8723d_pwrtrack_set(struct rtw_dev *rtwdev, u8 path)
rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
}
static void rtw8723d_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path,
u8 delta)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
const s8 *pwrtrk_xtal;
s8 xtal_cap;
if (dm_info->thermal_avg[therm_path] >
rtwdev->efuse.thermal_meter[therm_path])
pwrtrk_xtal = tbl->pwrtrk_xtal_p;
else
pwrtrk_xtal = tbl->pwrtrk_xtal_n;
xtal_cap = rtwdev->efuse.crystal_cap & 0x3F;
xtal_cap = clamp_t(s8, xtal_cap + pwrtrk_xtal[delta], 0, 0x3F);
rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL,
xtal_cap | (xtal_cap << 6));
}
static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
@ -1912,7 +1379,7 @@ static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev)
do_iqk = rtw_phy_pwrtrack_need_iqk(rtwdev);
if (do_iqk)
rtw8723d_lck(rtwdev);
rtw8723x_lck(rtwdev);
if (dm_info->pwr_trk_init_trigger)
dm_info->pwr_trk_init_trigger = false;
@ -1937,7 +1404,7 @@ static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev)
rtw8723d_pwrtrack_set(rtwdev, path);
}
rtw8723d_pwrtrack_set_xtal(rtwdev, RF_PATH_A, delta);
rtw8723x_pwrtrack_set_xtal(rtwdev, RF_PATH_A, delta);
iqk:
if (do_iqk)
@ -1963,49 +1430,29 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev)
dm_info->pwr_trk_triggered = false;
}
static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *txdesc)
{
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
__le16 chksum = 0;
__le16 *data = (__le16 *)(txdesc);
struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
while (words--)
chksum ^= *data++;
chksum = ~chksum;
le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
RTW_TX_DESC_W7_TXDESC_CHECKSUM);
}
static struct rtw_chip_ops rtw8723d_ops = {
.phy_set_param = rtw8723d_phy_set_param,
.read_efuse = rtw8723d_read_efuse,
.read_efuse = rtw8723x_read_efuse,
.query_rx_desc = rtw8723d_query_rx_desc,
.set_channel = rtw8723d_set_channel,
.mac_init = rtw8723d_mac_init,
.mac_init = rtw8723x_mac_init,
.shutdown = rtw8723d_shutdown,
.read_rf = rtw_phy_read_rf_sipi,
.write_rf = rtw_phy_write_rf_reg_sipi,
.set_tx_power_index = rtw8723d_set_tx_power_index,
.set_tx_power_index = rtw8723x_set_tx_power_index,
.set_antenna = NULL,
.cfg_ldo25 = rtw8723d_cfg_ldo25,
.efuse_grant = rtw8723d_efuse_grant,
.false_alarm_statistics = rtw8723d_false_alarm_statistics,
.cfg_ldo25 = rtw8723x_cfg_ldo25,
.efuse_grant = rtw8723x_efuse_grant,
.false_alarm_statistics = rtw8723x_false_alarm_statistics,
.phy_calibration = rtw8723d_phy_calibration,
.cck_pd_set = rtw8723d_phy_cck_pd_set,
.pwr_track = rtw8723d_pwr_track,
.config_bfee = NULL,
.set_gid_table = NULL,
.cfg_csi_rate = NULL,
.fill_txdesc_checksum = rtw8723d_fill_txdesc_checksum,
.fill_txdesc_checksum = rtw8723x_fill_txdesc_checksum,
.coex_set_init = rtw8723d_coex_cfg_init,
.coex_set_init = rtw8723x_coex_cfg_init,
.coex_set_ant_switch = NULL,
.coex_set_gnt_fix = rtw8723d_coex_cfg_gnt_fix,
.coex_set_gnt_debug = rtw8723d_coex_cfg_gnt_debug,
@ -2592,22 +2039,6 @@ static const struct rtw_rqpn rqpn_table_8723d[] = {
RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
};
static const struct rtw_prioq_addrs prioq_addrs_8723d = {
.prio[RTW_DMA_MAPPING_EXTRA] = {
.rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,
},
.prio[RTW_DMA_MAPPING_LOW] = {
.rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,
},
.prio[RTW_DMA_MAPPING_NORMAL] = {
.rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,
},
.prio[RTW_DMA_MAPPING_HIGH] = {
.rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,
},
.wsize = false,
};
static const struct rtw_intf_phy_para pcie_gen1_param_8723d[] = {
{0x0008, 0x4a22,
RTW_IP_SEL_PHY,
@ -2628,28 +2059,6 @@ static const struct rtw_intf_phy_para_table phy_para_table_8723d = {
.n_gen1_para = ARRAY_SIZE(pcie_gen1_param_8723d),
};
static const struct rtw_hw_reg rtw8723d_dig[] = {
[0] = { .addr = 0xc50, .mask = 0x7f },
[1] = { .addr = 0xc50, .mask = 0x7f },
};
static const struct rtw_hw_reg rtw8723d_dig_cck[] = {
[0] = { .addr = 0xa0c, .mask = 0x3f00 },
};
static const struct rtw_rf_sipi_addr rtw8723d_rf_sipi_addr[] = {
[RF_PATH_A] = { .hssi_1 = 0x820, .lssi_read = 0x8a0,
.hssi_2 = 0x824, .lssi_read_pi = 0x8b8},
[RF_PATH_B] = { .hssi_1 = 0x828, .lssi_read = 0x8a4,
.hssi_2 = 0x82c, .lssi_read_pi = 0x8bc},
};
static const struct rtw_ltecoex_addr rtw8723d_ltecoex_addr = {
.ctrl = REG_LTECOEX_CTRL,
.wdata = REG_LTECOEX_WRITE_DATA,
.rdata = REG_LTECOEX_READ_DATA,
};
static const struct rtw_rfe_def rtw8723d_rfe_defs[] = {
[0] = { .phy_pg_tbl = &rtw8723d_bb_pg_tbl,
.txpwr_lmt_tbl = &rtw8723d_txpwr_lmt_tbl,},
@ -2762,6 +2171,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = {
.band = RTW_BAND_2G,
.page_size = TX_PAGE_SIZE,
.dig_min = 0x20,
.usb_tx_agg_desc_num = 1,
.ht_supported = true,
.vht_supported = false,
.lps_deep_mode_supported = 0,
@ -2770,14 +2180,14 @@ const struct rtw_chip_info rtw8723d_hw_spec = {
.pwr_off_seq = card_disable_flow_8723d,
.page_table = page_table_8723d,
.rqpn_table = rqpn_table_8723d,
.prioq_addrs = &prioq_addrs_8723d,
.prioq_addrs = &rtw8723x_common.prioq_addrs,
.intf_table = &phy_para_table_8723d,
.dig = rtw8723d_dig,
.dig_cck = rtw8723d_dig_cck,
.dig = rtw8723x_common.dig,
.dig_cck = rtw8723x_common.dig_cck,
.rf_sipi_addr = {0x840, 0x844},
.rf_sipi_read_addr = rtw8723d_rf_sipi_addr,
.rf_sipi_read_addr = rtw8723x_common.rf_sipi_addr,
.fix_rf_phy_num = 2,
.ltecoex_addr = &rtw8723d_ltecoex_addr,
.ltecoex_addr = &rtw8723x_common.ltecoex_addr,
.mac_tbl = &rtw8723d_mac_tbl,
.agc_tbl = &rtw8723d_agc_tbl,
.bb_tbl = &rtw8723d_bb_tbl,

View File

@ -5,89 +5,7 @@
#ifndef __RTW8723D_H__
#define __RTW8723D_H__
enum rtw8723d_path {
PATH_S1,
PATH_S0,
PATH_NR,
};
enum rtw8723d_iqk_round {
IQK_ROUND_0,
IQK_ROUND_1,
IQK_ROUND_2,
IQK_ROUND_HYBRID,
IQK_ROUND_SIZE,
IQK_ROUND_INVALID = 0xff,
};
enum rtw8723d_iqk_result {
IQK_S1_TX_X,
IQK_S1_TX_Y,
IQK_S1_RX_X,
IQK_S1_RX_Y,
IQK_S0_TX_X,
IQK_S0_TX_Y,
IQK_S0_RX_X,
IQK_S0_RX_Y,
IQK_NR,
IQK_SX_NR = IQK_NR / PATH_NR,
};
struct rtw8723de_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vender_id[2];
u8 device_id[2];
u8 sub_vender_id[2];
u8 sub_device_id[2];
};
struct rtw8723du_efuse {
u8 res4[48]; /* 0xd0 */
u8 vender_id[2]; /* 0x100 */
u8 product_id[2]; /* 0x102 */
u8 usb_option; /* 0x104 */
u8 mac_addr[ETH_ALEN]; /* 0x107 */
};
struct rtw8723ds_efuse {
u8 res4[0x4a]; /* 0xd0 */
u8 mac_addr[ETH_ALEN]; /* 0x11a */
};
struct rtw8723d_efuse {
__le16 rtl_id;
u8 rsvd[2];
u8 afe;
u8 rsvd1[11];
/* power index for four RF paths */
struct rtw_txpwr_idx txpwr_idx_table[4];
u8 channel_plan; /* 0xb8 */
u8 xtal_k;
u8 thermal_meter;
u8 iqk_lck;
u8 pa_type; /* 0xbc */
u8 lna_type_2g[2]; /* 0xbd */
u8 lna_type_5g[2];
u8 rf_board_option;
u8 rf_feature_option;
u8 rf_bt_setting;
u8 eeprom_version;
u8 eeprom_customer_id;
u8 tx_bb_swing_setting_2g;
u8 res_c7;
u8 tx_pwr_calibrate_rate;
u8 rf_antenna_option; /* 0xc9 */
u8 rfe_option;
u8 country_code[2];
u8 res[3];
union {
struct rtw8723de_efuse e;
struct rtw8723du_efuse u;
struct rtw8723ds_efuse s;
};
};
#include "rtw8723x.h"
extern const struct rtw_chip_info rtw8723d_hw_spec;
@ -113,193 +31,9 @@ extern const struct rtw_chip_info rtw8723d_hw_spec;
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
static inline s32 iqkxy_to_s32(s32 val)
{
/* val is Q10.8 */
return sign_extend32(val, 9);
}
static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
{
/* x, y and return value are Q10.8 */
s32 t;
t = x * y;
if (ext)
*ext = (t >> 7) & 0x1; /* Q.16 --> Q.9; get LSB of Q.9 */
return (t >> 8); /* Q.16 --> Q.8 */
}
#define OFDM_SWING_A(swing) FIELD_GET(GENMASK(9, 0), swing)
#define OFDM_SWING_B(swing) FIELD_GET(GENMASK(15, 10), swing)
#define OFDM_SWING_C(swing) FIELD_GET(GENMASK(21, 16), swing)
#define OFDM_SWING_D(swing) FIELD_GET(GENMASK(31, 22), swing)
#define RTW_DEF_OFDM_SWING_INDEX 28
#define RTW_DEF_CCK_SWING_INDEX 28
#define MAX_TOLERANCE 5
#define IQK_TX_X_ERR 0x142
#define IQK_TX_Y_ERR 0x42
#define IQK_RX_X_UPPER 0x11a
#define IQK_RX_X_LOWER 0xe6
#define IQK_RX_Y_LMT 0x1a
#define IQK_TX_OK BIT(0)
#define IQK_RX_OK BIT(1)
#define PATH_IQK_RETRY 2
#define SPUR_THRES 0x16
#define CCK_DFIR_NR 3
#define DIS_3WIRE 0xccf000c0
#define EN_3WIRE 0xccc000c0
#define START_PSD 0x400000
#define FREQ_CH13 0xfccd
#define FREQ_CH14 0xff9a
#define RFCFGCH_CHANNEL_MASK GENMASK(7, 0)
#define RFCFGCH_BW_MASK (BIT(11) | BIT(10))
#define RFCFGCH_BW_20M (BIT(11) | BIT(10))
#define RFCFGCH_BW_40M BIT(10)
#define BIT_MASK_RFMOD BIT(0)
#define BIT_LCK BIT(15)
#define REG_GPIO_INTM 0x0048
#define REG_BTG_SEL 0x0067
#define BIT_MASK_BTG_WL BIT(7)
#define REG_LTECOEX_PATH_CONTROL 0x0070
#define REG_LTECOEX_CTRL 0x07c0
#define REG_LTECOEX_WRITE_DATA 0x07c4
#define REG_LTECOEX_READ_DATA 0x07c8
#define REG_PSDFN 0x0808
#define REG_BB_PWR_SAV1_11N 0x0874
#define REG_ANA_PARAM1 0x0880
#define REG_ANALOG_P4 0x088c
#define REG_PSDRPT 0x08b4
#define REG_FPGA1_RFMOD 0x0900
#define REG_BB_SEL_BTG 0x0948
#define REG_BBRX_DFIR 0x0954
#define BIT_MASK_RXBB_DFIR GENMASK(27, 24)
#define BIT_RXBB_DFIR_EN BIT(19)
#define REG_CCK0_SYS 0x0a00
#define BIT_CCK_SIDE_BAND BIT(4)
#define REG_CCK_ANT_SEL_11N 0x0a04
#define REG_PWRTH 0x0a08
#define REG_CCK_FA_RST_11N 0x0a2c
#define BIT_MASK_CCK_CNT_KEEP BIT(12)
#define BIT_MASK_CCK_CNT_EN BIT(13)
#define BIT_MASK_CCK_CNT_KPEN (BIT_MASK_CCK_CNT_KEEP | BIT_MASK_CCK_CNT_EN)
#define BIT_MASK_CCK_FA_KEEP BIT(14)
#define BIT_MASK_CCK_FA_EN BIT(15)
#define BIT_MASK_CCK_FA_KPEN (BIT_MASK_CCK_FA_KEEP | BIT_MASK_CCK_FA_EN)
#define REG_CCK_FA_LSB_11N 0x0a5c
#define REG_CCK_FA_MSB_11N 0x0a58
#define REG_CCK_CCA_CNT_11N 0x0a60
#define BIT_MASK_CCK_FA_MSB GENMASK(7, 0)
#define BIT_MASK_CCK_FA_LSB GENMASK(15, 8)
#define REG_PWRTH2 0x0aa8
#define REG_CSRATIO 0x0aaa
#define REG_OFDM_FA_HOLDC_11N 0x0c00
#define BIT_MASK_OFDM_FA_KEEP BIT(31)
#define REG_BB_RX_PATH_11N 0x0c04
#define REG_TRMUX_11N 0x0c08
#define REG_OFDM_FA_RSTC_11N 0x0c0c
#define BIT_MASK_OFDM_FA_RST BIT(31)
#define REG_A_RXIQI 0x0c14
#define BIT_MASK_RXIQ_S1_X 0x000003FF
#define BIT_MASK_RXIQ_S1_Y1 0x0000FC00
#define BIT_SET_RXIQ_S1_Y1(y) ((y) & 0x3F)
#define REG_OFDM0_RXDSP 0x0c40
#define BIT_MASK_RXDSP GENMASK(28, 24)
#define BIT_EN_RXDSP BIT(9)
#define REG_OFDM_0_ECCA_THRESHOLD 0x0c4c
#define BIT_MASK_OFDM0_EXT_A BIT(31)
#define BIT_MASK_OFDM0_EXT_C BIT(29)
#define BIT_MASK_OFDM0_EXTS (BIT(31) | BIT(29) | BIT(28))
#define BIT_SET_OFDM0_EXTS(a, c, d) (((a) << 31) | ((c) << 29) | ((d) << 28))
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58
#define REG_AGCRSSI 0x0c78
#define REG_OFDM_0_XA_TX_IQ_IMBALANCE 0x0c80
#define BIT_MASK_TXIQ_ELM_A 0x03ff
#define BIT_SET_TXIQ_ELM_ACD(a, c, d) (((d) << 22) | (((c) & 0x3F) << 16) | \
((a) & 0x03ff))
#define BIT_MASK_TXIQ_ELM_C GENMASK(21, 16)
#define BIT_SET_TXIQ_ELM_C2(c) ((c) & 0x3F)
#define BIT_MASK_TXIQ_ELM_D GENMASK(31, 22)
#define REG_TXIQK_MATRIXA_LSB2_11N 0x0c94
#define BIT_SET_TXIQ_ELM_C1(c) (((c) & 0x000003C0) >> 6)
#define REG_RXIQK_MATRIX_LSB_11N 0x0ca0
#define BIT_MASK_RXIQ_S1_Y2 0xF0000000
#define BIT_SET_RXIQ_S1_Y2(y) (((y) >> 6) & 0xF)
#define REG_TXIQ_AB_S0 0x0cd0
#define BIT_MASK_TXIQ_A_S0 0x000007FE
#define BIT_MASK_TXIQ_A_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_B_S0 0x0007E000
#define REG_TXIQ_CD_S0 0x0cd4
#define BIT_MASK_TXIQ_C_S0 0x000007FE
#define BIT_MASK_TXIQ_C_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_D_S0 GENMASK(22, 13)
#define BIT_MASK_TXIQ_D_EXT_S0 BIT(12)
#define REG_RXIQ_AB_S0 0x0cd8
#define BIT_MASK_RXIQ_X_S0 0x000003FF
#define BIT_MASK_RXIQ_Y_S0 0x003FF000
#define REG_OFDM_FA_TYPE1_11N 0x0cf0
#define BIT_MASK_OFDM_FF_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_SF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_RSTD_11N 0x0d00
#define BIT_MASK_OFDM_FA_RST1 BIT(27)
#define BIT_MASK_OFDM_FA_KEEP1 BIT(31)
#define REG_CTX 0x0d03
#define BIT_MASK_CTX_TYPE GENMASK(6, 4)
#define REG_OFDM1_CFOTRK 0x0d2c
#define BIT_EN_CFOTRK BIT(28)
#define REG_OFDM1_CSI1 0x0d40
#define REG_OFDM1_CSI2 0x0d44
#define REG_OFDM1_CSI3 0x0d48
#define REG_OFDM1_CSI4 0x0d4c
#define REG_OFDM_FA_TYPE2_11N 0x0da0
#define BIT_MASK_OFDM_CCA_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_PF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE3_11N 0x0da4
#define BIT_MASK_OFDM_RI_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_CRC_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE4_11N 0x0da8
#define BIT_MASK_OFDM_MNS_CNT GENMASK(15, 0)
#define REG_FPGA0_IQK_11N 0x0e28
#define BIT_MASK_IQK_MOD 0xffffff00
#define EN_IQK 0x808000
#define RST_IQK 0x000000
#define REG_TXIQK_TONE_A_11N 0x0e30
#define REG_RXIQK_TONE_A_11N 0x0e34
#define REG_TXIQK_PI_A_11N 0x0e38
#define REG_RXIQK_PI_A_11N 0x0e3c
#define REG_TXIQK_11N 0x0e40
#define BIT_SET_TXIQK_11N(x, y) (0x80007C00 | ((x) << 16) | (y))
#define REG_RXIQK_11N 0x0e44
#define REG_IQK_AGC_PTS_11N 0x0e48
#define REG_IQK_AGC_RSP_11N 0x0e4c
#define REG_TX_IQK_TONE_B 0x0e50
#define REG_RX_IQK_TONE_B 0x0e54
#define REG_IQK_RES_TX 0x0e94
#define BIT_MASK_RES_TX GENMASK(25, 16)
#define REG_IQK_RES_TY 0x0e9c
#define BIT_MASK_RES_TY GENMASK(25, 16)
#define REG_IQK_RES_RX 0x0ea4
#define BIT_MASK_RES_RX GENMASK(25, 16)
#define REG_IQK_RES_RY 0x0eac
#define BIT_IQK_TX_FAIL BIT(28)
#define BIT_IQK_RX_FAIL BIT(27)
#define BIT_IQK_DONE BIT(26)
#define BIT_MASK_RES_RY GENMASK(25, 16)
#define REG_PAGE_F_RST_11N 0x0f14
#define BIT_MASK_F_RST_ALL BIT(16)
#define REG_IGI_C_11N 0x0f84
#define REG_IGI_D_11N 0x0f88
#define REG_HT_CRC32_CNT_11N 0x0f90
#define BIT_MASK_HT_CRC_OK GENMASK(15, 0)
#define BIT_MASK_HT_CRC_ERR GENMASK(31, 16)
#define REG_OFDM_CRC32_CNT_11N 0x0f94
#define BIT_MASK_OFDM_LCRC_OK GENMASK(15, 0)
#define BIT_MASK_OFDM_LCRC_ERR GENMASK(31, 16)
#define REG_HT_CRC32_CNT_11N_AGG 0x0fb8
#endif

721
rtw8723x.c Normal file
View File

@ -0,0 +1,721 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright 2024 Fiona Klute
*
* Based on code originally in rtw8723d.[ch],
* Copyright(c) 2018-2019 Realtek Corporation
*/
#include "main.h"
#include "debug.h"
#include "phy.h"
#include "reg.h"
#include "tx.h"
#include "rtw8723x.h"
static const struct rtw_hw_reg rtw8723x_txagc[] = {
[DESC_RATE1M] = { .addr = 0xe08, .mask = 0x0000ff00 },
[DESC_RATE2M] = { .addr = 0x86c, .mask = 0x0000ff00 },
[DESC_RATE5_5M] = { .addr = 0x86c, .mask = 0x00ff0000 },
[DESC_RATE11M] = { .addr = 0x86c, .mask = 0xff000000 },
[DESC_RATE6M] = { .addr = 0xe00, .mask = 0x000000ff },
[DESC_RATE9M] = { .addr = 0xe00, .mask = 0x0000ff00 },
[DESC_RATE12M] = { .addr = 0xe00, .mask = 0x00ff0000 },
[DESC_RATE18M] = { .addr = 0xe00, .mask = 0xff000000 },
[DESC_RATE24M] = { .addr = 0xe04, .mask = 0x000000ff },
[DESC_RATE36M] = { .addr = 0xe04, .mask = 0x0000ff00 },
[DESC_RATE48M] = { .addr = 0xe04, .mask = 0x00ff0000 },
[DESC_RATE54M] = { .addr = 0xe04, .mask = 0xff000000 },
[DESC_RATEMCS0] = { .addr = 0xe10, .mask = 0x000000ff },
[DESC_RATEMCS1] = { .addr = 0xe10, .mask = 0x0000ff00 },
[DESC_RATEMCS2] = { .addr = 0xe10, .mask = 0x00ff0000 },
[DESC_RATEMCS3] = { .addr = 0xe10, .mask = 0xff000000 },
[DESC_RATEMCS4] = { .addr = 0xe14, .mask = 0x000000ff },
[DESC_RATEMCS5] = { .addr = 0xe14, .mask = 0x0000ff00 },
[DESC_RATEMCS6] = { .addr = 0xe14, .mask = 0x00ff0000 },
[DESC_RATEMCS7] = { .addr = 0xe14, .mask = 0xff000000 },
};
static void __rtw8723x_lck(struct rtw_dev *rtwdev)
{
u32 lc_cal;
u8 val_ctx, rf_val;
int ret;
val_ctx = rtw_read8(rtwdev, REG_CTX);
if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE);
else
rtw_write8(rtwdev, REG_TXPAUSE, 0xFF);
lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK);
ret = read_poll_timeout(rtw_read_rf, rf_val, rf_val != 0x1,
10000, 1000000, false,
rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK);
if (ret)
rtw_warn(rtwdev, "failed to poll LCK status bit\n");
rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
rtw_write8(rtwdev, REG_CTX, val_ctx);
else
rtw_write8(rtwdev, REG_TXPAUSE, 0x00);
}
#define DBG_EFUSE_VAL(rtwdev, map, name) \
rtw_dbg(rtwdev, RTW_DBG_EFUSE, # name "=0x%02x\n", \
(map)->name)
#define DBG_EFUSE_2BYTE(rtwdev, map, name) \
rtw_dbg(rtwdev, RTW_DBG_EFUSE, # name "=0x%02x%02x\n", \
(map)->name[0], (map)->name[1])
static void rtw8723xe_efuse_debug(struct rtw_dev *rtwdev,
struct rtw8723x_efuse *map)
{
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "mac_addr=%pM\n", map->e.mac_addr);
DBG_EFUSE_2BYTE(rtwdev, map, e.vendor_id);
DBG_EFUSE_2BYTE(rtwdev, map, e.device_id);
DBG_EFUSE_2BYTE(rtwdev, map, e.sub_vendor_id);
DBG_EFUSE_2BYTE(rtwdev, map, e.sub_device_id);
}
static void rtw8723xu_efuse_debug(struct rtw_dev *rtwdev,
struct rtw8723x_efuse *map)
{
DBG_EFUSE_2BYTE(rtwdev, map, u.vendor_id);
DBG_EFUSE_2BYTE(rtwdev, map, u.product_id);
DBG_EFUSE_VAL(rtwdev, map, u.usb_option);
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "mac_addr=%pM\n", map->u.mac_addr);
}
static void rtw8723xs_efuse_debug(struct rtw_dev *rtwdev,
struct rtw8723x_efuse *map)
{
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "mac_addr=%pM\n", map->s.mac_addr);
}
static void __rtw8723x_debug_txpwr_limit(struct rtw_dev *rtwdev,
struct rtw_txpwr_idx *table,
int tx_path_count)
{
if (!rtw_dbg_is_enabled(rtwdev, RTW_DBG_EFUSE))
return;
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"Power index table (2.4G):\n");
/* CCK base */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "CCK base\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF G0 G1 G2 G3 G4 G5\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %3u %3u %3u %3u %3u %3u\n",
'A' + i,
table[i].pwr_idx_2g.cck_base[0],
table[i].pwr_idx_2g.cck_base[1],
table[i].pwr_idx_2g.cck_base[2],
table[i].pwr_idx_2g.cck_base[3],
table[i].pwr_idx_2g.cck_base[4],
table[i].pwr_idx_2g.cck_base[5]);
/* CCK diff */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "CCK diff\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %2d %2d %2d %2d\n",
'A' + i, 0 /* no diff for 1S */,
table[i].pwr_idx_2g.ht_2s_diff.cck,
table[i].pwr_idx_2g.ht_3s_diff.cck,
table[i].pwr_idx_2g.ht_4s_diff.cck);
/* BW40-1S base */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "BW40-1S base\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF G0 G1 G2 G3 G4\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %3u %3u %3u %3u %3u\n",
'A' + i,
table[i].pwr_idx_2g.bw40_base[0],
table[i].pwr_idx_2g.bw40_base[1],
table[i].pwr_idx_2g.bw40_base[2],
table[i].pwr_idx_2g.bw40_base[3],
table[i].pwr_idx_2g.bw40_base[4]);
/* OFDM diff */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "OFDM diff\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %2d %2d %2d %2d\n",
'A' + i,
table[i].pwr_idx_2g.ht_1s_diff.ofdm,
table[i].pwr_idx_2g.ht_2s_diff.ofdm,
table[i].pwr_idx_2g.ht_3s_diff.ofdm,
table[i].pwr_idx_2g.ht_4s_diff.ofdm);
/* BW20 diff */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "BW20 diff\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %2d %2d %2d %2d\n",
'A' + i,
table[i].pwr_idx_2g.ht_1s_diff.bw20,
table[i].pwr_idx_2g.ht_2s_diff.bw20,
table[i].pwr_idx_2g.ht_3s_diff.bw20,
table[i].pwr_idx_2g.ht_4s_diff.bw20);
/* BW40 diff */
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "BW40 diff\n");
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");
for (int i = 0; i < tx_path_count; i++)
rtw_dbg(rtwdev, RTW_DBG_EFUSE,
"[%c]: %2d %2d %2d %2d\n",
'A' + i, 0 /* no diff for 1S */,
table[i].pwr_idx_2g.ht_2s_diff.bw40,
table[i].pwr_idx_2g.ht_3s_diff.bw40,
table[i].pwr_idx_2g.ht_4s_diff.bw40);
}
static void efuse_debug_dump(struct rtw_dev *rtwdev,
struct rtw8723x_efuse *map)
{
if (!rtw_dbg_is_enabled(rtwdev, RTW_DBG_EFUSE))
return;
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "EFUSE raw logical map:\n");
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1,
(u8 *)map, sizeof(struct rtw8723x_efuse), false);
rtw_dbg(rtwdev, RTW_DBG_EFUSE, "Parsed rtw8723x EFUSE data:\n");
DBG_EFUSE_VAL(rtwdev, map, rtl_id);
DBG_EFUSE_VAL(rtwdev, map, afe);
rtw8723x_debug_txpwr_limit(rtwdev, map->txpwr_idx_table, 4);
DBG_EFUSE_VAL(rtwdev, map, channel_plan);
DBG_EFUSE_VAL(rtwdev, map, xtal_k);
DBG_EFUSE_VAL(rtwdev, map, thermal_meter);
DBG_EFUSE_VAL(rtwdev, map, iqk_lck);
DBG_EFUSE_VAL(rtwdev, map, pa_type);
DBG_EFUSE_2BYTE(rtwdev, map, lna_type_2g);
DBG_EFUSE_2BYTE(rtwdev, map, lna_type_5g);
DBG_EFUSE_VAL(rtwdev, map, rf_board_option);
DBG_EFUSE_VAL(rtwdev, map, rf_feature_option);
DBG_EFUSE_VAL(rtwdev, map, rf_bt_setting);
DBG_EFUSE_VAL(rtwdev, map, eeprom_version);
DBG_EFUSE_VAL(rtwdev, map, eeprom_customer_id);
DBG_EFUSE_VAL(rtwdev, map, tx_bb_swing_setting_2g);
DBG_EFUSE_VAL(rtwdev, map, tx_pwr_calibrate_rate);
DBG_EFUSE_VAL(rtwdev, map, rf_antenna_option);
DBG_EFUSE_VAL(rtwdev, map, rfe_option);
DBG_EFUSE_2BYTE(rtwdev, map, country_code);
switch (rtw_hci_type(rtwdev)) {
case RTW_HCI_TYPE_PCIE:
rtw8723xe_efuse_debug(rtwdev, map);
break;
case RTW_HCI_TYPE_USB:
rtw8723xu_efuse_debug(rtwdev, map);
break;
case RTW_HCI_TYPE_SDIO:
rtw8723xs_efuse_debug(rtwdev, map);
break;
default:
/* unsupported now */
break;
}
}
static void rtw8723xe_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723x_efuse *map)
{
ether_addr_copy(efuse->addr, map->e.mac_addr);
}
static void rtw8723xu_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723x_efuse *map)
{
ether_addr_copy(efuse->addr, map->u.mac_addr);
}
static void rtw8723xs_efuse_parsing(struct rtw_efuse *efuse,
struct rtw8723x_efuse *map)
{
ether_addr_copy(efuse->addr, map->s.mac_addr);
}
static int __rtw8723x_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
struct rtw8723x_efuse *map;
int i;
map = (struct rtw8723x_efuse *)log_map;
efuse_debug_dump(rtwdev, map);
efuse->rfe_option = 0;
efuse->rf_board_option = map->rf_board_option;
efuse->crystal_cap = map->xtal_k;
efuse->pa_type_2g = map->pa_type;
efuse->lna_type_2g = map->lna_type_2g[0];
efuse->channel_plan = map->channel_plan;
efuse->country_code[0] = map->country_code[0];
efuse->country_code[1] = map->country_code[1];
efuse->bt_setting = map->rf_bt_setting;
efuse->regd = map->rf_board_option & 0x7;
efuse->thermal_meter[0] = map->thermal_meter;
efuse->thermal_meter_k = map->thermal_meter;
efuse->afe = map->afe;
for (i = 0; i < 4; i++)
efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
switch (rtw_hci_type(rtwdev)) {
case RTW_HCI_TYPE_PCIE:
rtw8723xe_efuse_parsing(efuse, map);
break;
case RTW_HCI_TYPE_USB:
rtw8723xu_efuse_parsing(efuse, map);
break;
case RTW_HCI_TYPE_SDIO:
rtw8723xs_efuse_parsing(efuse, map);
break;
default:
/* unsupported now */
return -EOPNOTSUPP;
}
return 0;
}
#define BIT_CFENDFORM BIT(9)
#define BIT_WMAC_TCR_ERR0 BIT(12)
#define BIT_WMAC_TCR_ERR1 BIT(13)
#define BIT_TCR_CFG (BIT_CFENDFORM | BIT_WMAC_TCR_ERR0 | \
BIT_WMAC_TCR_ERR1)
#define WLAN_RX_FILTER0 0xFFFF
#define WLAN_RX_FILTER1 0x400
#define WLAN_RX_FILTER2 0xFFFF
#define WLAN_RCR_CFG 0x700060CE
static int __rtw8723x_mac_init(struct rtw_dev *rtwdev)
{
rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, WLAN_TXQ_RPT_EN);
rtw_write32(rtwdev, REG_TCR, BIT_TCR_CFG);
rtw_write16(rtwdev, REG_RXFLTMAP0, WLAN_RX_FILTER0);
rtw_write16(rtwdev, REG_RXFLTMAP1, WLAN_RX_FILTER1);
rtw_write16(rtwdev, REG_RXFLTMAP2, WLAN_RX_FILTER2);
rtw_write32(rtwdev, REG_RCR, WLAN_RCR_CFG);
rtw_write32(rtwdev, REG_INT_MIG, 0);
rtw_write32(rtwdev, REG_MCUTST_1, 0x0);
rtw_write8(rtwdev, REG_MISC_CTRL, BIT_DIS_SECOND_CCA);
rtw_write8(rtwdev, REG_2ND_CCA_CTRL, 0);
return 0;
}
static void __rtw8723x_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
{
u8 ldo_pwr;
ldo_pwr = rtw_read8(rtwdev, REG_LDO_EFUSE_CTRL + 3);
if (enable) {
ldo_pwr &= ~BIT_MASK_LDO25_VOLTAGE;
ldo_pwr |= (BIT_LDO25_VOLTAGE_V25 << 4) | BIT_LDO25_EN;
} else {
ldo_pwr &= ~BIT_LDO25_EN;
}
rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr);
}
static void
rtw8723x_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
{
struct rtw_hal *hal = &rtwdev->hal;
const struct rtw_hw_reg *txagc;
u8 rate, pwr_index;
int j;
for (j = 0; j < rtw_rate_size[rs]; j++) {
rate = rtw_rate_section[rs][j];
pwr_index = hal->tx_pwr_tbl[path][rate];
if (rate >= ARRAY_SIZE(rtw8723x_txagc)) {
rtw_warn(rtwdev, "rate 0x%x isn't supported\n", rate);
continue;
}
txagc = &rtw8723x_txagc[rate];
if (!txagc->addr) {
rtw_warn(rtwdev, "rate 0x%x isn't defined\n", rate);
continue;
}
rtw_write32_mask(rtwdev, txagc->addr, txagc->mask, pwr_index);
}
}
static void __rtw8723x_set_tx_power_index(struct rtw_dev *rtwdev)
{
struct rtw_hal *hal = &rtwdev->hal;
int rs, path;
for (path = 0; path < hal->rf_path_num; path++) {
for (rs = 0; rs <= RTW_RATE_SECTION_HT_1S; rs++)
rtw8723x_set_tx_power_index_by_rate(rtwdev, path, rs);
}
}
static void __rtw8723x_efuse_grant(struct rtw_dev *rtwdev, bool on)
{
if (on) {
rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR);
rtw_write16_set(rtwdev, REG_SYS_CLKR, BIT_LOADER_CLK_EN | BIT_ANA8M);
} else {
rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
}
}
static void __rtw8723x_false_alarm_statistics(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u32 cck_fa_cnt;
u32 ofdm_fa_cnt;
u32 crc32_cnt;
u32 val32;
/* hold counter */
rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 1);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KEEP, 1);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KEEP, 1);
cck_fa_cnt = rtw_read32_mask(rtwdev, REG_CCK_FA_LSB_11N, MASKBYTE0);
cck_fa_cnt += rtw_read32_mask(rtwdev, REG_CCK_FA_MSB_11N, MASKBYTE3) << 8;
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE1_11N);
ofdm_fa_cnt = u32_get_bits(val32, BIT_MASK_OFDM_FF_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_SF_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE2_11N);
dm_info->ofdm_cca_cnt = u32_get_bits(val32, BIT_MASK_OFDM_CCA_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_PF_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE3_11N);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_RI_CNT);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_CRC_CNT);
val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE4_11N);
ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_MNS_CNT);
dm_info->cck_fa_cnt = cck_fa_cnt;
dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
dm_info->total_fa_cnt = cck_fa_cnt + ofdm_fa_cnt;
dm_info->cck_err_cnt = rtw_read32(rtwdev, REG_IGI_C_11N);
dm_info->cck_ok_cnt = rtw_read32(rtwdev, REG_IGI_D_11N);
crc32_cnt = rtw_read32(rtwdev, REG_OFDM_CRC32_CNT_11N);
dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_ERR);
dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_OK);
crc32_cnt = rtw_read32(rtwdev, REG_HT_CRC32_CNT_11N);
dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_ERR);
dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_OK);
dm_info->vht_err_cnt = 0;
dm_info->vht_ok_cnt = 0;
val32 = rtw_read32(rtwdev, REG_CCK_CCA_CNT_11N);
dm_info->cck_cca_cnt = (u32_get_bits(val32, BIT_MASK_CCK_FA_MSB) << 8) |
u32_get_bits(val32, BIT_MASK_CCK_FA_LSB);
dm_info->total_cca_cnt = dm_info->cck_cca_cnt + dm_info->ofdm_cca_cnt;
/* reset counter */
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 1);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 0);
rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 2);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 0);
rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 2);
rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 1);
rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0);
}
/* IQK (IQ calibration) */
static
void __rtw8723x_iqk_backup_regs(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup)
{
int i;
for (i = 0; i < RTW8723X_IQK_ADDA_REG_NUM; i++)
backup->adda[i] = rtw_read32(rtwdev,
rtw8723x_common.iqk_adda_regs[i]);
for (i = 0; i < RTW8723X_IQK_MAC8_REG_NUM; i++)
backup->mac8[i] = rtw_read8(rtwdev,
rtw8723x_common.iqk_mac8_regs[i]);
for (i = 0; i < RTW8723X_IQK_MAC32_REG_NUM; i++)
backup->mac32[i] = rtw_read32(rtwdev,
rtw8723x_common.iqk_mac32_regs[i]);
for (i = 0; i < RTW8723X_IQK_BB_REG_NUM; i++)
backup->bb[i] = rtw_read32(rtwdev,
rtw8723x_common.iqk_bb_regs[i]);
backup->igia = rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0);
backup->igib = rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0);
backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);
}
static
void __rtw8723x_iqk_restore_regs(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *backup)
{
int i;
for (i = 0; i < RTW8723X_IQK_ADDA_REG_NUM; i++)
rtw_write32(rtwdev, rtw8723x_common.iqk_adda_regs[i],
backup->adda[i]);
for (i = 0; i < RTW8723X_IQK_MAC8_REG_NUM; i++)
rtw_write8(rtwdev, rtw8723x_common.iqk_mac8_regs[i],
backup->mac8[i]);
for (i = 0; i < RTW8723X_IQK_MAC32_REG_NUM; i++)
rtw_write32(rtwdev, rtw8723x_common.iqk_mac32_regs[i],
backup->mac32[i]);
for (i = 0; i < RTW8723X_IQK_BB_REG_NUM; i++)
rtw_write32(rtwdev, rtw8723x_common.iqk_bb_regs[i],
backup->bb[i]);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, backup->igia);
rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, 0x50);
rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, backup->igib);
rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x01008c00);
rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x01008c00);
}
static
bool __rtw8723x_iqk_similarity_cmp(struct rtw_dev *rtwdev,
s32 result[][IQK_NR],
u8 c1, u8 c2)
{
u32 i, j, diff;
u32 bitmap = 0;
u8 candidate[PATH_NR] = {IQK_ROUND_INVALID, IQK_ROUND_INVALID};
bool ret = true;
s32 tmp1, tmp2;
for (i = 0; i < IQK_NR; i++) {
tmp1 = iqkxy_to_s32(result[c1][i]);
tmp2 = iqkxy_to_s32(result[c2][i]);
diff = abs(tmp1 - tmp2);
if (diff <= MAX_TOLERANCE)
continue;
if ((i == IQK_S1_RX_X || i == IQK_S0_RX_X) && !bitmap) {
if (result[c1][i] + result[c1][i + 1] == 0)
candidate[i / IQK_SX_NR] = c2;
else if (result[c2][i] + result[c2][i + 1] == 0)
candidate[i / IQK_SX_NR] = c1;
else
bitmap |= BIT(i);
} else {
bitmap |= BIT(i);
}
}
if (bitmap != 0)
goto check_sim;
for (i = 0; i < PATH_NR; i++) {
if (candidate[i] == IQK_ROUND_INVALID)
continue;
for (j = i * IQK_SX_NR; j < i * IQK_SX_NR + 2; j++)
result[IQK_ROUND_HYBRID][j] = result[candidate[i]][j];
ret = false;
}
return ret;
check_sim:
for (i = 0; i < IQK_NR; i++) {
j = i & ~1; /* 2 bits are a pair for IQ[X, Y] */
if (bitmap & GENMASK(j + 1, j))
continue;
result[IQK_ROUND_HYBRID][i] = result[c1][i];
}
return false;
}
static u8 __rtw8723x_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u8 tx_rate = dm_info->tx_rate;
u8 limit_ofdm = 30;
switch (tx_rate) {
case DESC_RATE1M...DESC_RATE5_5M:
case DESC_RATE11M:
break;
case DESC_RATE6M...DESC_RATE48M:
limit_ofdm = 36;
break;
case DESC_RATE54M:
limit_ofdm = 34;
break;
case DESC_RATEMCS0...DESC_RATEMCS2:
limit_ofdm = 38;
break;
case DESC_RATEMCS3...DESC_RATEMCS4:
limit_ofdm = 36;
break;
case DESC_RATEMCS5...DESC_RATEMCS7:
limit_ofdm = 34;
break;
default:
rtw_warn(rtwdev, "pwrtrack unhandled tx_rate 0x%x\n", tx_rate);
break;
}
return limit_ofdm;
}
static
void __rtw8723x_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path,
u8 delta)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
const s8 *pwrtrk_xtal;
s8 xtal_cap;
if (dm_info->thermal_avg[therm_path] >
rtwdev->efuse.thermal_meter[therm_path])
pwrtrk_xtal = tbl->pwrtrk_xtal_p;
else
pwrtrk_xtal = tbl->pwrtrk_xtal_n;
xtal_cap = rtwdev->efuse.crystal_cap & 0x3F;
xtal_cap = clamp_t(s8, xtal_cap + pwrtrk_xtal[delta], 0, 0x3F);
rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL,
xtal_cap | (xtal_cap << 6));
}
static
void __rtw8723x_fill_txdesc_checksum(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *txdesc)
{
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
__le16 chksum = 0;
__le16 *data = (__le16 *)(txdesc);
struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;
le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);
while (words--)
chksum ^= *data++;
chksum = ~chksum;
le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),
RTW_TX_DESC_W7_TXDESC_CHECKSUM);
}
static void __rtw8723x_coex_cfg_init(struct rtw_dev *rtwdev)
{
/* enable TBTT nterrupt */
rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
/* BT report packet sample rate */
/* 0x790[5:0]=0x5 */
rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
/* enable BT counter statistics */
rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
/* enable PTA (3-wire function form BT side) */
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS);
/* enable PTA (tx/rx signal form WiFi side) */
rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
}
const struct rtw8723x_common rtw8723x_common = {
.iqk_adda_regs = {
0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84,
0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec
},
.iqk_mac8_regs = {0x522, 0x550, 0x551},
.iqk_mac32_regs = {0x40},
.iqk_bb_regs = {
0xc04, 0xc08, 0x874, 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0xa04
},
.ltecoex_addr = {
.ctrl = REG_LTECOEX_CTRL,
.wdata = REG_LTECOEX_WRITE_DATA,
.rdata = REG_LTECOEX_READ_DATA,
},
.rf_sipi_addr = {
[RF_PATH_A] = { .hssi_1 = 0x820, .lssi_read = 0x8a0,
.hssi_2 = 0x824, .lssi_read_pi = 0x8b8},
[RF_PATH_B] = { .hssi_1 = 0x828, .lssi_read = 0x8a4,
.hssi_2 = 0x82c, .lssi_read_pi = 0x8bc},
},
.dig = {
[0] = { .addr = 0xc50, .mask = 0x7f },
[1] = { .addr = 0xc50, .mask = 0x7f },
},
.dig_cck = {
[0] = { .addr = 0xa0c, .mask = 0x3f00 },
},
.prioq_addrs = {
.prio[RTW_DMA_MAPPING_EXTRA] = {
.rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,
},
.prio[RTW_DMA_MAPPING_LOW] = {
.rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,
},
.prio[RTW_DMA_MAPPING_NORMAL] = {
.rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,
},
.prio[RTW_DMA_MAPPING_HIGH] = {
.rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,
},
.wsize = false,
},
.lck = __rtw8723x_lck,
.read_efuse = __rtw8723x_read_efuse,
.mac_init = __rtw8723x_mac_init,
.cfg_ldo25 = __rtw8723x_cfg_ldo25,
.set_tx_power_index = __rtw8723x_set_tx_power_index,
.efuse_grant = __rtw8723x_efuse_grant,
.false_alarm_statistics = __rtw8723x_false_alarm_statistics,
.iqk_backup_regs = __rtw8723x_iqk_backup_regs,
.iqk_restore_regs = __rtw8723x_iqk_restore_regs,
.iqk_similarity_cmp = __rtw8723x_iqk_similarity_cmp,
.pwrtrack_get_limit_ofdm = __rtw8723x_pwrtrack_get_limit_ofdm,
.pwrtrack_set_xtal = __rtw8723x_pwrtrack_set_xtal,
.coex_cfg_init = __rtw8723x_coex_cfg_init,
.fill_txdesc_checksum = __rtw8723x_fill_txdesc_checksum,
.debug_txpwr_limit = __rtw8723x_debug_txpwr_limit,
};
EXPORT_SYMBOL(rtw8723x_common);
MODULE_AUTHOR("Realtek Corporation");
MODULE_AUTHOR("Fiona Klute <fiona.klute@gmx.de>");
MODULE_DESCRIPTION("Common functions for Realtek 802.11n wireless 8723x drivers");
MODULE_LICENSE("Dual BSD/GPL");

518
rtw8723x.h Normal file
View File

@ -0,0 +1,518 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright 2024 Fiona Klute
*
* Based on code originally in rtw8723d.[ch],
* Copyright(c) 2018-2019 Realtek Corporation
*/
#ifndef __RTW8723X_H__
#define __RTW8723X_H__
#include "main.h"
#include "debug.h"
#include "phy.h"
#include "reg.h"
enum rtw8723x_path {
PATH_S1,
PATH_S0,
PATH_NR,
};
enum rtw8723x_iqk_round {
IQK_ROUND_0,
IQK_ROUND_1,
IQK_ROUND_2,
IQK_ROUND_HYBRID,
IQK_ROUND_SIZE,
IQK_ROUND_INVALID = 0xff,
};
enum rtw8723x_iqk_result {
IQK_S1_TX_X,
IQK_S1_TX_Y,
IQK_S1_RX_X,
IQK_S1_RX_Y,
IQK_S0_TX_X,
IQK_S0_TX_Y,
IQK_S0_RX_X,
IQK_S0_RX_Y,
IQK_NR,
IQK_SX_NR = IQK_NR / PATH_NR,
};
struct rtw8723xe_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vendor_id[2];
u8 device_id[2];
u8 sub_vendor_id[2];
u8 sub_device_id[2];
};
struct rtw8723xu_efuse {
u8 res4[48]; /* 0xd0 */
u8 vendor_id[2]; /* 0x100 */
u8 product_id[2]; /* 0x102 */
u8 usb_option; /* 0x104 */
u8 res5[2]; /* 0x105 */
u8 mac_addr[ETH_ALEN]; /* 0x107 */
};
struct rtw8723xs_efuse {
u8 res4[0x4a]; /* 0xd0 */
u8 mac_addr[ETH_ALEN]; /* 0x11a */
};
struct rtw8723x_efuse {
__le16 rtl_id;
u8 rsvd[2];
u8 afe;
u8 rsvd1[11];
/* power index for four RF paths */
struct rtw_txpwr_idx txpwr_idx_table[4];
u8 channel_plan; /* 0xb8 */
u8 xtal_k;
u8 thermal_meter;
u8 iqk_lck;
u8 pa_type; /* 0xbc */
u8 lna_type_2g[2]; /* 0xbd */
u8 lna_type_5g[2];
u8 rf_board_option;
u8 rf_feature_option;
u8 rf_bt_setting;
u8 eeprom_version;
u8 eeprom_customer_id;
u8 tx_bb_swing_setting_2g;
u8 res_c7;
u8 tx_pwr_calibrate_rate;
u8 rf_antenna_option; /* 0xc9 */
u8 rfe_option;
u8 country_code[2];
u8 res[3];
union {
struct rtw8723xe_efuse e;
struct rtw8723xu_efuse u;
struct rtw8723xs_efuse s;
};
};
#define RTW8723X_IQK_ADDA_REG_NUM 16
#define RTW8723X_IQK_MAC8_REG_NUM 3
#define RTW8723X_IQK_MAC32_REG_NUM 1
#define RTW8723X_IQK_BB_REG_NUM 9
struct rtw8723x_iqk_backup_regs {
u32 adda[RTW8723X_IQK_ADDA_REG_NUM];
u8 mac8[RTW8723X_IQK_MAC8_REG_NUM];
u32 mac32[RTW8723X_IQK_MAC32_REG_NUM];
u32 bb[RTW8723X_IQK_BB_REG_NUM];
u32 lte_path;
u32 lte_gnt;
u32 bb_sel_btg;
u8 btg_sel;
u8 igia;
u8 igib;
};
struct rtw8723x_common {
/* registers that must be backed up before IQK and restored after */
u32 iqk_adda_regs[RTW8723X_IQK_ADDA_REG_NUM];
u32 iqk_mac8_regs[RTW8723X_IQK_MAC8_REG_NUM];
u32 iqk_mac32_regs[RTW8723X_IQK_MAC32_REG_NUM];
u32 iqk_bb_regs[RTW8723X_IQK_BB_REG_NUM];
/* chip register definitions */
struct rtw_ltecoex_addr ltecoex_addr;
struct rtw_rf_sipi_addr rf_sipi_addr[2];
struct rtw_hw_reg dig[2];
struct rtw_hw_reg dig_cck[1];
struct rtw_prioq_addrs prioq_addrs;
/* common functions */
void (*lck)(struct rtw_dev *rtwdev);
int (*read_efuse)(struct rtw_dev *rtwdev, u8 *log_map);
int (*mac_init)(struct rtw_dev *rtwdev);
void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable);
void (*set_tx_power_index)(struct rtw_dev *rtwdev);
void (*efuse_grant)(struct rtw_dev *rtwdev, bool on);
void (*false_alarm_statistics)(struct rtw_dev *rtwdev);
void (*iqk_backup_regs)(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup);
void (*iqk_restore_regs)(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *backup);
bool (*iqk_similarity_cmp)(struct rtw_dev *rtwdev, s32 result[][IQK_NR],
u8 c1, u8 c2);
u8 (*pwrtrack_get_limit_ofdm)(struct rtw_dev *rtwdev);
void (*pwrtrack_set_xtal)(struct rtw_dev *rtwdev, u8 therm_path,
u8 delta);
void (*coex_cfg_init)(struct rtw_dev *rtwdev);
void (*fill_txdesc_checksum)(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *txdesc);
void (*debug_txpwr_limit)(struct rtw_dev *rtwdev,
struct rtw_txpwr_idx *table,
int tx_path_count);
};
extern const struct rtw8723x_common rtw8723x_common;
#define PATH_IQK_RETRY 2
#define MAX_TOLERANCE 5
#define IQK_TX_X_ERR 0x142
#define IQK_TX_Y_ERR 0x42
#define IQK_RX_X_ERR 0x132
#define IQK_RX_Y_ERR 0x36
#define IQK_RX_X_UPPER 0x11a
#define IQK_RX_X_LOWER 0xe6
#define IQK_RX_Y_LMT 0x1a
#define IQK_TX_OK BIT(0)
#define IQK_RX_OK BIT(1)
#define WLAN_TXQ_RPT_EN 0x1F
#define SPUR_THRES 0x16
#define DIS_3WIRE 0xccf000c0
#define EN_3WIRE 0xccc000c0
#define START_PSD 0x400000
#define FREQ_CH5 0xfccd
#define FREQ_CH6 0xfc4d
#define FREQ_CH7 0xffcd
#define FREQ_CH8 0xff4d
#define FREQ_CH13 0xfccd
#define FREQ_CH14 0xff9a
#define RFCFGCH_CHANNEL_MASK GENMASK(7, 0)
#define RFCFGCH_BW_MASK (BIT(11) | BIT(10))
#define RFCFGCH_BW_20M (BIT(11) | BIT(10))
#define RFCFGCH_BW_40M BIT(10)
#define BIT_MASK_RFMOD BIT(0)
#define BIT_LCK BIT(15)
#define REG_GPIO_INTM 0x0048
#define REG_BTG_SEL 0x0067
#define BIT_MASK_BTG_WL BIT(7)
#define REG_LTECOEX_PATH_CONTROL 0x0070
#define REG_LTECOEX_CTRL 0x07c0
#define REG_LTECOEX_WRITE_DATA 0x07c4
#define REG_LTECOEX_READ_DATA 0x07c8
#define REG_PSDFN 0x0808
#define REG_BB_PWR_SAV1_11N 0x0874
#define REG_ANA_PARAM1 0x0880
#define REG_ANALOG_P4 0x088c
#define REG_PSDRPT 0x08b4
#define REG_FPGA1_RFMOD 0x0900
#define REG_BB_SEL_BTG 0x0948
#define REG_BBRX_DFIR 0x0954
#define BIT_MASK_RXBB_DFIR GENMASK(27, 24)
#define BIT_RXBB_DFIR_EN BIT(19)
#define REG_CCK0_SYS 0x0a00
#define BIT_CCK_SIDE_BAND BIT(4)
#define REG_CCK_ANT_SEL_11N 0x0a04
#define REG_PWRTH 0x0a08
#define REG_CCK_FA_RST_11N 0x0a2c
#define BIT_MASK_CCK_CNT_KEEP BIT(12)
#define BIT_MASK_CCK_CNT_EN BIT(13)
#define BIT_MASK_CCK_CNT_KPEN (BIT_MASK_CCK_CNT_KEEP | BIT_MASK_CCK_CNT_EN)
#define BIT_MASK_CCK_FA_KEEP BIT(14)
#define BIT_MASK_CCK_FA_EN BIT(15)
#define BIT_MASK_CCK_FA_KPEN (BIT_MASK_CCK_FA_KEEP | BIT_MASK_CCK_FA_EN)
#define REG_CCK_FA_LSB_11N 0x0a5c
#define REG_CCK_FA_MSB_11N 0x0a58
#define REG_CCK_CCA_CNT_11N 0x0a60
#define BIT_MASK_CCK_FA_MSB GENMASK(7, 0)
#define BIT_MASK_CCK_FA_LSB GENMASK(15, 8)
#define REG_PWRTH2 0x0aa8
#define REG_CSRATIO 0x0aaa
#define REG_OFDM_FA_HOLDC_11N 0x0c00
#define BIT_MASK_OFDM_FA_KEEP BIT(31)
#define REG_BB_RX_PATH_11N 0x0c04
#define REG_TRMUX_11N 0x0c08
#define REG_OFDM_FA_RSTC_11N 0x0c0c
#define BIT_MASK_OFDM_FA_RST BIT(31)
#define REG_A_RXIQI 0x0c14
#define BIT_MASK_RXIQ_S1_X 0x000003FF
#define BIT_MASK_RXIQ_S1_Y1 0x0000FC00
#define BIT_SET_RXIQ_S1_Y1(y) ((y) & 0x3F)
#define REG_OFDM0_RXDSP 0x0c40
#define BIT_MASK_RXDSP GENMASK(28, 24)
#define BIT_EN_RXDSP BIT(9)
#define REG_OFDM_0_ECCA_THRESHOLD 0x0c4c
#define BIT_MASK_OFDM0_EXT_A BIT(31)
#define BIT_MASK_OFDM0_EXT_C BIT(29)
#define BIT_MASK_OFDM0_EXTS (BIT(31) | BIT(29) | BIT(28))
#define BIT_SET_OFDM0_EXTS(a, c, d) (((a) << 31) | ((c) << 29) | ((d) << 28))
#define BIT_MASK_OFDM0_EXTS_B (BIT(27) | BIT(25) | BIT(24))
#define BIT_SET_OFDM0_EXTS_B(a, c, d) (((a) << 27) | ((c) << 25) | ((d) << 24))
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58
#define REG_AGCRSSI 0x0c78
#define REG_OFDM_0_XA_TX_IQ_IMBALANCE 0x0c80
#define REG_OFDM_0_XB_TX_IQ_IMBALANCE 0x0c88
#define BIT_MASK_TXIQ_ELM_A 0x03ff
#define BIT_SET_TXIQ_ELM_ACD(a, c, d) (((d) << 22) | (((c) & 0x3F) << 16) | \
((a) & 0x03ff))
#define BIT_MASK_TXIQ_ELM_C GENMASK(21, 16)
#define BIT_SET_TXIQ_ELM_C2(c) ((c) & 0x3F)
#define BIT_MASK_TXIQ_ELM_D GENMASK(31, 22)
#define REG_TXIQK_MATRIXA_LSB2_11N 0x0c94
#define BIT_SET_TXIQ_ELM_C1(c) (((c) & 0x000003C0) >> 6)
#define REG_RXIQK_MATRIX_LSB_11N 0x0ca0
#define BIT_MASK_RXIQ_S1_Y2 0xF0000000
#define BIT_SET_RXIQ_S1_Y2(y) (((y) >> 6) & 0xF)
#define REG_TXIQ_AB_S0 0x0cd0
#define BIT_MASK_TXIQ_A_S0 0x000007FE
#define BIT_MASK_TXIQ_A_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_B_S0 0x0007E000
#define REG_TXIQ_CD_S0 0x0cd4
#define BIT_MASK_TXIQ_C_S0 0x000007FE
#define BIT_MASK_TXIQ_C_EXT_S0 BIT(0)
#define BIT_MASK_TXIQ_D_S0 GENMASK(22, 13)
#define BIT_MASK_TXIQ_D_EXT_S0 BIT(12)
#define REG_RXIQ_AB_S0 0x0cd8
#define BIT_MASK_RXIQ_X_S0 0x000003FF
#define BIT_MASK_RXIQ_Y_S0 0x003FF000
#define REG_OFDM_FA_TYPE1_11N 0x0cf0
#define BIT_MASK_OFDM_FF_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_SF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_RSTD_11N 0x0d00
#define BIT_MASK_OFDM_FA_RST1 BIT(27)
#define BIT_MASK_OFDM_FA_KEEP1 BIT(31)
#define REG_CTX 0x0d03
#define BIT_MASK_CTX_TYPE GENMASK(6, 4)
#define REG_OFDM1_CFOTRK 0x0d2c
#define BIT_EN_CFOTRK BIT(28)
#define REG_OFDM1_CSI1 0x0d40
#define REG_OFDM1_CSI2 0x0d44
#define REG_OFDM1_CSI3 0x0d48
#define REG_OFDM1_CSI4 0x0d4c
#define REG_OFDM_FA_TYPE2_11N 0x0da0
#define BIT_MASK_OFDM_CCA_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_PF_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE3_11N 0x0da4
#define BIT_MASK_OFDM_RI_CNT GENMASK(15, 0)
#define BIT_MASK_OFDM_CRC_CNT GENMASK(31, 16)
#define REG_OFDM_FA_TYPE4_11N 0x0da8
#define BIT_MASK_OFDM_MNS_CNT GENMASK(15, 0)
#define REG_FPGA0_IQK_11N 0x0e28
#define BIT_MASK_IQK_MOD 0xffffff00
#define EN_IQK 0x808000
#define RST_IQK 0x000000
#define REG_TXIQK_TONE_A_11N 0x0e30
#define REG_RXIQK_TONE_A_11N 0x0e34
#define REG_TXIQK_PI_A_11N 0x0e38
#define REG_RXIQK_PI_A_11N 0x0e3c
#define REG_TXIQK_11N 0x0e40
#define BIT_SET_TXIQK_11N(x, y) (0x80007C00 | ((x) << 16) | (y))
#define REG_RXIQK_11N 0x0e44
#define REG_IQK_AGC_PTS_11N 0x0e48
#define REG_IQK_AGC_RSP_11N 0x0e4c
#define REG_TX_IQK_TONE_B 0x0e50
#define REG_RX_IQK_TONE_B 0x0e54
#define REG_TXIQK_PI_B 0x0e58
#define REG_RXIQK_PI_B 0x0e5c
#define REG_IQK_RES_TX 0x0e94
#define BIT_MASK_RES_TX GENMASK(25, 16)
#define REG_IQK_RES_TY 0x0e9c
#define BIT_MASK_RES_TY GENMASK(25, 16)
#define REG_IQK_RES_RX 0x0ea4
#define BIT_MASK_RES_RX GENMASK(25, 16)
#define REG_IQK_RES_RY 0x0eac
#define BIT_IQK_TX_FAIL BIT(28)
#define BIT_IQK_RX_FAIL BIT(27)
#define BIT_IQK_DONE BIT(26)
#define BIT_MASK_RES_RY GENMASK(25, 16)
#define REG_PAGE_F_RST_11N 0x0f14
#define BIT_MASK_F_RST_ALL BIT(16)
#define REG_IGI_C_11N 0x0f84
#define REG_IGI_D_11N 0x0f88
#define REG_HT_CRC32_CNT_11N 0x0f90
#define BIT_MASK_HT_CRC_OK GENMASK(15, 0)
#define BIT_MASK_HT_CRC_ERR GENMASK(31, 16)
#define REG_OFDM_CRC32_CNT_11N 0x0f94
#define BIT_MASK_OFDM_LCRC_OK GENMASK(15, 0)
#define BIT_MASK_OFDM_LCRC_ERR GENMASK(31, 16)
#define REG_HT_CRC32_CNT_11N_AGG 0x0fb8
#define OFDM_SWING_A(swing) FIELD_GET(GENMASK(9, 0), swing)
#define OFDM_SWING_B(swing) FIELD_GET(GENMASK(15, 10), swing)
#define OFDM_SWING_C(swing) FIELD_GET(GENMASK(21, 16), swing)
#define OFDM_SWING_D(swing) FIELD_GET(GENMASK(31, 22), swing)
static inline s32 iqkxy_to_s32(s32 val)
{
/* val is Q10.8 */
return sign_extend32(val, 9);
}
static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
{
/* x, y and return value are Q10.8 */
s32 t;
t = x * y;
if (ext)
*ext = (t >> 7) & 0x1; /* Q.16 --> Q.9; get LSB of Q.9 */
return (t >> 8); /* Q.16 --> Q.8 */
}
static inline
void rtw8723x_debug_txpwr_limit(struct rtw_dev *rtwdev,
struct rtw_txpwr_idx *table,
int tx_path_count)
{
rtw8723x_common.debug_txpwr_limit(rtwdev, table, tx_path_count);
}
static inline void rtw8723x_lck(struct rtw_dev *rtwdev)
{
rtw8723x_common.lck(rtwdev);
}
static inline int rtw8723x_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
return rtw8723x_common.read_efuse(rtwdev, log_map);
}
static inline int rtw8723x_mac_init(struct rtw_dev *rtwdev)
{
return rtw8723x_common.mac_init(rtwdev);
}
static inline void rtw8723x_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
{
rtw8723x_common.cfg_ldo25(rtwdev, enable);
}
static inline void rtw8723x_set_tx_power_index(struct rtw_dev *rtwdev)
{
rtw8723x_common.set_tx_power_index(rtwdev);
}
static inline void rtw8723x_efuse_grant(struct rtw_dev *rtwdev, bool on)
{
rtw8723x_common.efuse_grant(rtwdev, on);
}
static inline void rtw8723x_false_alarm_statistics(struct rtw_dev *rtwdev)
{
rtw8723x_common.false_alarm_statistics(rtwdev);
}
static inline
void rtw8723x_iqk_backup_regs(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup)
{
rtw8723x_common.iqk_backup_regs(rtwdev, backup);
}
static inline
void rtw8723x_iqk_restore_regs(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *backup)
{
rtw8723x_common.iqk_restore_regs(rtwdev, backup);
}
static inline
bool rtw8723x_iqk_similarity_cmp(struct rtw_dev *rtwdev, s32 result[][IQK_NR],
u8 c1, u8 c2)
{
return rtw8723x_common.iqk_similarity_cmp(rtwdev, result, c1, c2);
}
static inline u8 rtw8723x_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev)
{
return rtw8723x_common.pwrtrack_get_limit_ofdm(rtwdev);
}
static inline
void rtw8723x_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path,
u8 delta)
{
rtw8723x_common.pwrtrack_set_xtal(rtwdev, therm_path, delta);
}
static inline void rtw8723x_coex_cfg_init(struct rtw_dev *rtwdev)
{
rtw8723x_common.coex_cfg_init(rtwdev);
}
static inline
void rtw8723x_fill_txdesc_checksum(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *txdesc)
{
rtw8723x_common.fill_txdesc_checksum(rtwdev, pkt_info, txdesc);
}
/* IQK helper functions, defined as inline so they can be shared
* without needing an EXPORT_SYMBOL each.
*/
static inline void
rtw8723x_iqk_backup_path_ctrl(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup)
{
backup->btg_sel = rtw_read8(rtwdev, REG_BTG_SEL);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] original 0x67 = 0x%x\n",
backup->btg_sel);
}
static inline void rtw8723x_iqk_config_path_ctrl(struct rtw_dev *rtwdev)
{
rtw_write32_mask(rtwdev, REG_PAD_CTRL1, BIT_BT_BTG_SEL, 0x1);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] set 0x67 = 0x%x\n",
rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
}
static inline void
rtw8723x_iqk_restore_path_ctrl(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *backup)
{
rtw_write8(rtwdev, REG_BTG_SEL, backup->btg_sel);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] restore 0x67 = 0x%x\n",
rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
}
static inline void
rtw8723x_iqk_backup_lte_path_gnt(struct rtw_dev *rtwdev,
struct rtw8723x_iqk_backup_regs *backup)
{
backup->lte_path = rtw_read32(rtwdev, REG_LTECOEX_PATH_CONTROL);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0038);
mdelay(1);
backup->lte_gnt = rtw_read32(rtwdev, REG_LTECOEX_READ_DATA);
rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] OriginalGNT = 0x%x\n",
backup->lte_gnt);
}
static inline void
rtw8723x_iqk_config_lte_path_gnt(struct rtw_dev *rtwdev,
u32 write_data)
{
rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, write_data);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc0020038);
rtw_write32_mask(rtwdev, REG_LTECOEX_PATH_CONTROL,
BIT_LTE_MUX_CTRL_PATH, 0x1);
}
static inline void
rtw8723x_iqk_restore_lte_path_gnt(struct rtw_dev *rtwdev,
const struct rtw8723x_iqk_backup_regs *bak)
{
rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, bak->lte_gnt);
rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc00f0038);
rtw_write32(rtwdev, REG_LTECOEX_PATH_CONTROL, bak->lte_path);
}
/* set all ADDA registers to the given value */
static inline void rtw8723x_iqk_path_adda_on(struct rtw_dev *rtwdev, u32 value)
{
for (int i = 0; i < RTW8723X_IQK_ADDA_REG_NUM; i++)
rtw_write32(rtwdev, rtw8723x_common.iqk_adda_regs[i], value);
}
#endif /* __RTW8723X_H__ */

View File

@ -381,6 +381,65 @@ static void rtw8821c_set_channel_rxdfir(struct rtw_dev *rtwdev, u8 bw)
}
}
static void rtw8821c_cck_tx_filter_srrc(struct rtw_dev *rtwdev, u8 channel, u8 bw)
{
struct rtw_hal *hal = &rtwdev->hal;
if (channel == 14) {
rtw_write32_mask(rtwdev, REG_CCA_FLTR, MASKHWORD, 0xe82c);
rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, 0x0000b81c);
rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, 0x0000);
rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD, 0x00003667);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00002);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001e);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001c);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000e);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000c);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00000);
} else if (channel == 13 ||
(channel == 11 && bw == RTW_CHANNEL_WIDTH_40)) {
rtw_write32_mask(rtwdev, REG_CCA_FLTR, MASKHWORD, 0xf8fe);
rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, 0x64b80c1c);
rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, 0x8810);
rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD, 0x01235667);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00002);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001e);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00027);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001c);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00027);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000e);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00029);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000c);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00026);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00000);
} else {
rtw_write32_mask(rtwdev, REG_CCA_FLTR, MASKHWORD, 0xe82c);
rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD,
hal->ch_param[0]);
rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD,
hal->ch_param[1] & MASKLWORD);
rtw_write32_mask(rtwdev, REG_TXFILTER, MASKDWORD,
hal->ch_param[2]);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00002);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001e);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0001c);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000e);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x0000c);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0x00000);
rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, RFREG_MASK, 0x00000);
}
}
static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
u8 primary_ch_idx)
{
@ -395,6 +454,13 @@ static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw_write32_mask(rtwdev, REG_TXSCALE_A, 0xf00, 0x0);
rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x96a);
if (rtw_regd_srrc(rtwdev)) {
rtw8821c_cck_tx_filter_srrc(rtwdev, channel, bw);
goto set_bw;
}
/* CCK TX filter parameters for default case */
if (channel == 14) {
rtw_write32_mask(rtwdev, REG_TXSF2, MASKDWORD, 0x0000b81c);
rtw_write32_mask(rtwdev, REG_TXSF6, MASKLWORD, 0x0000);
@ -430,6 +496,7 @@ static void rtw8821c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x412);
}
set_bw:
switch (bw) {
case RTW_CHANNEL_WIDTH_20:
default:
@ -706,9 +773,9 @@ static void rtw8821c_false_alarm_statistics(struct rtw_dev *rtwdev)
dm_info->cck_fa_cnt = cck_fa_cnt;
dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
dm_info->total_fa_cnt = ofdm_fa_cnt;
if (cck_enable)
dm_info->total_fa_cnt += cck_fa_cnt;
dm_info->total_fa_cnt = ofdm_fa_cnt;
crc32_cnt = rtw_read32(rtwdev, REG_CRC_CCK);
dm_info->cck_ok_cnt = FIELD_GET(GENMASK(15, 0), crc32_cnt);
@ -1941,6 +2008,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = {
.band = RTW_BAND_2G | RTW_BAND_5G,
.page_size = TX_PAGE_SIZE,
.dig_min = 0x1c,
.usb_tx_agg_desc_num = 3,
.ht_supported = true,
.vht_supported = true,
.lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),

View File

@ -238,6 +238,7 @@ extern const struct rtw_chip_info rtw8821c_hw_spec;
#define REG_RXSB 0xa00
#define REG_ADCINI 0xa04
#define REG_PWRTH 0xa08
#define REG_CCA_FLTR 0xa20
#define REG_TXSF2 0xa24
#define REG_TXSF6 0xa28
#define REG_FA_CCK 0xa5c

File diff suppressed because it is too large Load Diff

View File

@ -9,24 +9,36 @@
#include "usb.h"
static const struct usb_device_id rtw_8821cu_id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb820, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc820, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82a, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* TOTOLINK A650UA v3 */
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8731, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb820, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc80c, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc820, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82a, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331d, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* D-Link */
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc811, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd811, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */
{},
};
MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table);

View File

@ -2548,6 +2548,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = {
.band = RTW_BAND_2G | RTW_BAND_5G,
.page_size = TX_PAGE_SIZE,
.dig_min = 0x1c,
.usb_tx_agg_desc_num = 3,
.ht_supported = true,
.vht_supported = true,
.lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),

View File

@ -5366,6 +5366,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = {
.band = RTW_BAND_2G | RTW_BAND_5G,
.page_size = TX_PAGE_SIZE,
.dig_min = 0x20,
.usb_tx_agg_desc_num = 3,
.default_1ss_tx_path = BB_PATH_A,
.path_div_supported = true,
.ht_supported = true,

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ static const struct usb_device_id rtw_8822cu_id_table[] = {
};
MODULE_DEVICE_TABLE(usb, rtw_8822cu_id_table);
static int rtw8822bu_probe(struct usb_interface *intf,
static int rtw8822cu_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return rtw_usb_probe(intf, id);
@ -34,7 +34,7 @@ static int rtw8822bu_probe(struct usb_interface *intf,
static struct usb_driver rtw_8822cu_driver = {
.name = "rtw_8822cu",
.id_table = rtw_8822cu_id_table,
.probe = rtw8822bu_probe,
.probe = rtw8822cu_probe,
.disconnect = rtw_usb_disconnect,
};
module_usb_driver(rtw_8822cu_driver);

2
rx.h
View File

@ -40,6 +40,8 @@ enum rtw_rx_desc_enc {
le32_get_bits(*((__le32 *)(rxdesc) + 0x02), GENMASK(30, 29))
#define GET_RX_DESC_TSFL(rxdesc) \
le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0))
#define GET_RX_DESC_BW(rxdesc) \
(le32_get_bits(*((__le32 *)(rxdesc) + 0x04), GENMASK(31, 24)))
void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
struct sk_buff *skb);

35
sdio.c
View File

@ -500,19 +500,40 @@ static u32 rtw_sdio_get_tx_addr(struct rtw_dev *rtwdev, size_t size,
static int rtw_sdio_read_port(struct rtw_dev *rtwdev, u8 *buf, size_t count)
{
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
struct mmc_host *host = rtwsdio->sdio_func->card->host;
bool bus_claim = rtw_sdio_bus_claim_needed(rtwsdio);
u32 rxaddr = rtwsdio->rx_addr++;
int ret;
int ret = 0, err;
size_t bytes;
if (bus_claim)
sdio_claim_host(rtwsdio->sdio_func);
ret = sdio_memcpy_fromio(rtwsdio->sdio_func, buf,
RTW_SDIO_ADDR_RX_RX0FF_GEN(rxaddr), count);
if (ret)
rtw_warn(rtwdev,
"Failed to read %zu byte(s) from SDIO port 0x%08x",
count, rxaddr);
while (count > 0) {
bytes = min_t(size_t, host->max_req_size, count);
err = sdio_memcpy_fromio(rtwsdio->sdio_func, buf,
RTW_SDIO_ADDR_RX_RX0FF_GEN(rxaddr),
bytes);
if (err) {
rtw_warn(rtwdev,
"Failed to read %zu byte(s) from SDIO port 0x%08x: %d",
bytes, rxaddr, err);
/* Signal to the caller that reading did not work and
* that the data in the buffer is short/corrupted.
*/
ret = err;
/* Don't stop here - instead drain the remaining data
* from the card's buffer, else the card will return
* corrupt data for the next rtw_sdio_read_port() call.
*/
}
count -= bytes;
buf += bytes;
}
if (bus_claim)
sdio_release_host(rtwsdio->sdio_func);

3
tx.c
View File

@ -656,9 +656,8 @@ void __rtw_tx_work(struct rtw_dev *rtwdev)
list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->txqs, list) {
struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
unsigned long frame_cnt;
unsigned long byte_cnt;
ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt);
ieee80211_txq_get_depth(txq, &frame_cnt, NULL);
rtw_txq_push(rtwdev, rtwtxq, frame_cnt);
list_del_init(&rtwtxq->list);

87
usb.c
View File

@ -33,6 +33,36 @@ static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb,
rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data);
}
static void rtw_usb_reg_sec(struct rtw_dev *rtwdev, u32 addr, __le32 *data)
{
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
struct usb_device *udev = rtwusb->udev;
bool reg_on_section = false;
u16 t_reg = 0x4e0;
u8 t_len = 1;
int status;
/* There are three sections:
* 1. on (0x00~0xFF; 0x1000~0x10FF): this section is always powered on
* 2. off (< 0xFE00, excluding "on" section): this section could be
* powered off
* 3. local (>= 0xFE00): usb specific registers section
*/
if (addr <= 0xff || (addr >= 0x1000 && addr <= 0x10ff))
reg_on_section = true;
if (!reg_on_section)
return;
status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
t_reg, 0, data, t_len, 500);
if (status != t_len && status != -ENODEV)
rtw_err(rtwdev, "%s: reg 0x%x, usb write %u fail, status: %d\n",
__func__, t_reg, t_len, status);
}
static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
{
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
@ -58,6 +88,11 @@ static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
rtw_err(rtwdev, "read register 0x%x failed with %d\n",
addr, ret);
if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C ||
rtwdev->chip->id == RTW_CHIP_TYPE_8822B ||
rtwdev->chip->id == RTW_CHIP_TYPE_8821C)
rtw_usb_reg_sec(rtwdev, addr, data);
return le32_to_cpu(*data);
}
@ -102,6 +137,11 @@ static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len)
if (ret < 0 && ret != -ENODEV && count++ < 4)
rtw_err(rtwdev, "write register 0x%x failed with %d\n",
addr, ret);
if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C ||
rtwdev->chip->id == RTW_CHIP_TYPE_8822B ||
rtwdev->chip->id == RTW_CHIP_TYPE_8821C)
rtw_usb_reg_sec(rtwdev, addr, data);
}
static void rtw_usb_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
@ -233,6 +273,8 @@ static void rtw_usb_write_port_tx_complete(struct urb *urb)
info = IEEE80211_SKB_CB(skb);
tx_data = rtw_usb_get_tx_data(skb);
skb_pull(skb, rtwdev->chip->tx_pkt_desc_sz);
/* enqueue to wait for tx report */
if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn);
@ -337,7 +379,9 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list
skb_iter = skb_peek(list);
if (skb_iter && skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ)
if (skb_iter &&
skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ &&
agg_num < rtwdev->chip->usb_tx_agg_desc_num)
__skb_unlink(skb_iter, list);
else
skb_iter = NULL;
@ -393,23 +437,21 @@ static int rtw_usb_write_data(struct rtw_dev *rtwdev,
{
const struct rtw_chip_info *chip = rtwdev->chip;
struct sk_buff *skb;
unsigned int desclen, headsize, size;
unsigned int size;
u8 qsel;
int ret = 0;
size = pkt_info->tx_pkt_size;
qsel = pkt_info->qsel;
desclen = chip->tx_pkt_desc_sz;
headsize = pkt_info->offset ? pkt_info->offset : desclen;
skb = dev_alloc_skb(headsize + size);
skb = dev_alloc_skb(chip->tx_pkt_desc_sz + size);
if (unlikely(!skb))
return -ENOMEM;
skb_reserve(skb, headsize);
skb_reserve(skb, chip->tx_pkt_desc_sz);
skb_put_data(skb, buf, size);
skb_push(skb, headsize);
memset(skb->data, 0, headsize);
skb_push(skb, chip->tx_pkt_desc_sz);
memset(skb->data, 0, chip->tx_pkt_desc_sz);
rtw_tx_fill_tx_desc(pkt_info, skb);
rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
@ -611,8 +653,7 @@ static void rtw_usb_cancel_rx_bufs(struct rtw_usb *rtwusb)
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
rxcb = &rtwusb->rx_cb[i];
if (rxcb->rx_urb)
usb_kill_urb(rxcb->rx_urb);
usb_kill_urb(rxcb->rx_urb);
}
}
@ -623,10 +664,8 @@ static void rtw_usb_free_rx_bufs(struct rtw_usb *rtwusb)
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
rxcb = &rtwusb->rx_cb[i];
if (rxcb->rx_urb) {
usb_kill_urb(rxcb->rx_urb);
usb_free_urb(rxcb->rx_urb);
}
usb_kill_urb(rxcb->rx_urb);
usb_free_urb(rxcb->rx_urb);
}
}
@ -703,7 +742,6 @@ static struct rtw_hci_ops rtw_usb_ops = {
static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
{
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
int i;
rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq");
if (!rtwusb->rxwq) {
@ -715,13 +753,19 @@ static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
INIT_WORK(&rtwusb->rx_work, rtw_usb_rx_handler);
return 0;
}
static void rtw_usb_setup_rx(struct rtw_dev *rtwdev)
{
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
int i;
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
rtw_usb_rx_resubmit(rtwusb, rxcb);
}
return 0;
}
static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
@ -826,7 +870,7 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
ret = rtw_core_init(rtwdev);
if (ret)
goto err_release_hw;
goto err_free_rx_bufs;
ret = rtw_usb_intf_init(rtwdev, intf);
if (ret) {
@ -858,6 +902,8 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto err_destroy_rxwq;
}
rtw_usb_setup_rx(rtwdev);
return 0;
err_destroy_rxwq:
@ -872,6 +918,9 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
err_deinit_core:
rtw_core_deinit(rtwdev);
err_free_rx_bufs:
rtw_usb_free_rx_bufs(rtwusb);
err_release_hw:
ieee80211_free_hw(hw);
@ -909,5 +958,5 @@ void rtw_usb_disconnect(struct usb_interface *intf)
EXPORT_SYMBOL(rtw_usb_disconnect);
MODULE_AUTHOR("Realtek Corporation");
MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver");
MODULE_DESCRIPTION("Realtek USB 802.11ac wireless driver");
MODULE_LICENSE("Dual BSD/GPL");