summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek')
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h31
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c107
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c62
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c75
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c111
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c82
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c504
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h11
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c8
-rw-r--r--drivers/net/wireless/realtek/rtw89/Makefile2
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c20
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h129
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c1019
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c317
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h261
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c515
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h77
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c55
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c39
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.h12
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c31
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h2
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h255
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a.c18
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c18
-rw-r--r--drivers/net/wireless/realtek/rtw89/util.h11
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.c859
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.h21
32 files changed, 4147 insertions, 511 deletions
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
index ad3f32f4c6e7..136992f0200c 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -570,7 +570,7 @@ struct rtl8723au_phy_stats {
u8 cck_rpt_b_ofdm_cfosho_b;
u8 reserved_1;
u8 noise_power_db_msb;
- u8 path_cfotail[RTL8723A_MAX_RF_PATHS];
+ s8 path_cfotail[RTL8723A_MAX_RF_PATHS];
u8 pcts_mask[RTL8723A_MAX_RF_PATHS];
s8 stream_rxevm[RTL8723A_MAX_RF_PATHS];
u8 path_rxsnr[RTL8723A_MAX_RF_PATHS];
@@ -1323,6 +1323,19 @@ struct rtl8xxxu_ra_report {
u8 desc_rate;
};
+#define CFO_TH_XTAL_HIGH 20 /* kHz */
+#define CFO_TH_XTAL_LOW 10 /* kHz */
+#define CFO_TH_ATC 80 /* kHz */
+
+struct rtl8xxxu_cfo_tracking {
+ bool adjust;
+ bool atc_status;
+ int cfo_tail[2];
+ u8 crystal_cap;
+ u32 packet_count;
+ u32 packet_count_pre;
+};
+
struct rtl8xxxu_priv {
struct ieee80211_hw *hw;
struct usb_device *udev;
@@ -1381,9 +1394,9 @@ struct rtl8xxxu_priv {
u32 ep_tx_high_queue:1;
u32 ep_tx_normal_queue:1;
u32 ep_tx_low_queue:1;
- u32 has_xtalk:1;
u32 rx_buf_aggregation:1;
- u8 xtalk;
+ u32 cck_agc_report_type:1;
+ u8 default_crystal_cap;
unsigned int pipe_interrupt;
unsigned int pipe_in;
unsigned int pipe_out[TXDESC_QUEUE_MAX];
@@ -1441,6 +1454,7 @@ struct rtl8xxxu_priv {
struct sk_buff_head c2hcmd_queue;
struct rtl8xxxu_btcoex bt_coex;
struct rtl8xxxu_ra_report ra_report;
+ struct rtl8xxxu_cfo_tracking cfo_tracking;
};
struct rtl8xxxu_rx_urb {
@@ -1456,6 +1470,7 @@ struct rtl8xxxu_tx_urb {
};
struct rtl8xxxu_fileops {
+ int (*identify_chip) (struct rtl8xxxu_priv *priv);
int (*parse_efuse) (struct rtl8xxxu_priv *priv);
int (*load_firmware) (struct rtl8xxxu_priv *priv);
int (*power_on) (struct rtl8xxxu_priv *priv);
@@ -1471,6 +1486,7 @@ struct rtl8xxxu_fileops {
int (*parse_rx_desc) (struct rtl8xxxu_priv *priv, struct sk_buff *skb);
void (*init_aggregation) (struct rtl8xxxu_priv *priv);
void (*init_statistics) (struct rtl8xxxu_priv *priv);
+ void (*init_burst) (struct rtl8xxxu_priv *priv);
void (*enable_rf) (struct rtl8xxxu_priv *priv);
void (*disable_rf) (struct rtl8xxxu_priv *priv);
void (*usb_quirks) (struct rtl8xxxu_priv *priv);
@@ -1485,6 +1501,8 @@ struct rtl8xxxu_fileops {
struct rtl8xxxu_txdesc32 *tx_desc, bool sgi,
bool short_preamble, bool ampdu_enable,
u32 rts_rate);
+ void (*set_crystal_cap) (struct rtl8xxxu_priv *priv, u8 crystal_cap);
+ s8 (*cck_rssi) (struct rtl8xxxu_priv *priv, u8 cck_agc_rpt);
int writeN_block_size;
int rx_agg_buf_size;
char tx_desc_size;
@@ -1545,6 +1563,10 @@ int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv,
int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, char *fw_name);
void rtl8xxxu_firmware_self_reset(struct rtl8xxxu_priv *priv);
void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv);
+void rtl8xxxu_identify_vendor_1bit(struct rtl8xxxu_priv *priv, u32 vendor);
+void rtl8xxxu_identify_vendor_2bits(struct rtl8xxxu_priv *priv, u32 vendor);
+void rtl8xxxu_config_endpoints_sie(struct rtl8xxxu_priv *priv);
+int rtl8xxxu_config_endpoints_no_sie(struct rtl8xxxu_priv *priv);
int rtl8xxxu_read_efuse8(struct rtl8xxxu_priv *priv, u16 offset, u8 *data);
void rtl8xxxu_reset_8051(struct rtl8xxxu_priv *priv);
int rtl8xxxu_auto_llt_table(struct rtl8xxxu_priv *priv);
@@ -1576,6 +1598,7 @@ void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen1_enable_rf(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen1_disable_rf(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen2_disable_rf(struct rtl8xxxu_priv *priv);
+void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv);
int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb);
int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb);
int rtl8xxxu_gen2_channel_to_group(int channel);
@@ -1594,6 +1617,8 @@ void rtl8xxxu_fill_txdesc_v2(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5);
void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv);
+void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap);
+s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt);
extern struct rtl8xxxu_fileops rtl8188fu_fops;
extern struct rtl8xxxu_fileops rtl8192cu_fops;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
index 0025bb32538d..2c4f403ba68f 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c
@@ -321,7 +321,37 @@ static const struct rtl8xxxu_rfregval rtl8188fu_cut_b_radioa_init_table[] = {
{0xff, 0xffffffff}
};
-static void rtl8xxxu_8188f_channel_to_group(int channel, int *group, int *cck_group)
+static int rtl8188fu_identify_chip(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u32 sys_cfg, vendor;
+ int ret = 0;
+
+ strscpy(priv->chip_name, "8188FU", sizeof(priv->chip_name));
+ priv->rtl_chip = RTL8188F;
+ priv->rf_paths = 1;
+ priv->rx_paths = 1;
+ priv->tx_paths = 1;
+ priv->has_wifi = 1;
+
+ sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
+ priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
+ if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
+ dev_info(dev, "Unsupported test chip\n");
+ ret = -ENOTSUPP;
+ goto out;
+ }
+
+ vendor = sys_cfg & SYS_CFG_VENDOR_EXT_MASK;
+ rtl8xxxu_identify_vendor_2bits(priv, vendor);
+
+ ret = rtl8xxxu_config_endpoints_no_sie(priv);
+
+out:
+ return ret;
+}
+
+static void rtl8188f_channel_to_group(int channel, int *group, int *cck_group)
{
if (channel < 3)
*group = 0;
@@ -347,7 +377,7 @@ rtl8188f_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
u8 cck, ofdmbase, mcsbase;
int group, cck_group;
- rtl8xxxu_8188f_channel_to_group(channel, &group, &cck_group);
+ rtl8188f_channel_to_group(channel, &group, &cck_group);
cck = priv->cck_tx_power_index_A[cck_group];
@@ -703,7 +733,7 @@ static int rtl8188fu_parse_efuse(struct rtl8xxxu_priv *priv)
priv->ofdm_tx_power_diff[0].a = efuse->tx_power_index_A.ht20_ofdm_1s_diff.a;
priv->ht20_tx_power_diff[0].a = efuse->tx_power_index_A.ht20_ofdm_1s_diff.b;
- priv->xtalk = efuse->xtal_k & 0x3f;
+ priv->default_crystal_cap = efuse->xtal_k & 0x3f;
dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name);
dev_info(&priv->udev->dev, "Product: %.7s\n", efuse->device_name);
@@ -737,7 +767,6 @@ static void rtl8188fu_init_phy_bb(struct rtl8xxxu_priv *priv)
{
u8 val8;
u16 val16;
- u32 val32;
/* Enable BB and RF */
val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
@@ -759,12 +788,6 @@ static void rtl8188fu_init_phy_bb(struct rtl8xxxu_priv *priv)
rtl8xxxu_init_phy_regs(priv, rtl8188fu_phy_init_table);
rtl8xxxu_init_phy_regs(priv, rtl8188f_agc_table);
-
- val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL);
- val8 = priv->xtalk;
- val32 &= ~0x007FF800;
- val32 |= ((val8 | (val8 << 6)) << 11);
- rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32);
}
static int rtl8188fu_init_phy_rf(struct rtl8xxxu_priv *priv)
@@ -1636,7 +1659,68 @@ static void rtl8188f_usb_quirks(struct rtl8xxxu_priv *priv)
rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32);
}
+#define XTAL1 GENMASK(22, 17)
+#define XTAL0 GENMASK(16, 11)
+
+static void rtl8188f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
+{
+ struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking;
+ u32 val32;
+
+ if (crystal_cap == cfo->crystal_cap)
+ return;
+
+ val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL);
+
+ dev_dbg(&priv->udev->dev,
+ "%s: Adjusting crystal cap from 0x%x (actually 0x%lx 0x%lx) to 0x%x\n",
+ __func__,
+ cfo->crystal_cap,
+ FIELD_GET(XTAL1, val32),
+ FIELD_GET(XTAL0, val32),
+ crystal_cap);
+
+ val32 &= ~(XTAL1 | XTAL0);
+ val32 |= FIELD_PREP(XTAL1, crystal_cap) |
+ FIELD_PREP(XTAL0, crystal_cap);
+ rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32);
+
+ cfo->crystal_cap = crystal_cap;
+}
+
+static s8 rtl8188f_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
+{
+ s8 rx_pwr_all = 0x00;
+ u8 vga_idx, lna_idx;
+
+ lna_idx = (cck_agc_rpt & 0xE0) >> 5;
+ vga_idx = cck_agc_rpt & 0x1F;
+
+ switch (lna_idx) {
+ case 7:
+ if (vga_idx <= 27)
+ rx_pwr_all = -100 + 2 * (27 - vga_idx);
+ else
+ rx_pwr_all = -100;
+ break;
+ case 5:
+ rx_pwr_all = -74 + 2 * (21 - vga_idx);
+ break;
+ case 3:
+ rx_pwr_all = -60 + 2 * (20 - vga_idx);
+ break;
+ case 1:
+ rx_pwr_all = -44 + 2 * (19 - vga_idx);
+ break;
+ default:
+ break;
+ }
+
+ return rx_pwr_all;
+}
+
struct rtl8xxxu_fileops rtl8188fu_fops = {
+ .identify_chip = rtl8188fu_identify_chip,
.parse_efuse = rtl8188fu_parse_efuse,
.load_firmware = rtl8188fu_load_firmware,
.power_on = rtl8188fu_power_on,
@@ -1652,6 +1736,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
.parse_rx_desc = rtl8xxxu_parse_rxdesc24,
.init_aggregation = rtl8188fu_init_aggregation,
.init_statistics = rtl8188fu_init_statistics,
+ .init_burst = rtl8xxxu_init_burst,
.enable_rf = rtl8188f_enable_rf,
.disable_rf = rtl8188f_disable_rf,
.usb_quirks = rtl8188f_usb_quirks,
@@ -1659,6 +1744,8 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
.update_rate_mask = rtl8xxxu_gen2_update_rate_mask,
.report_connect = rtl8xxxu_gen2_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v2,
+ .set_crystal_cap = rtl8188f_set_crystal_cap,
+ .cck_rssi = rtl8188f_cck_rssi,
.writeN_block_size = 128,
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
index e9bc94edfa79..3bef9ffc8b02 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
@@ -326,6 +326,64 @@ static const struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = {
{0xff, 0xffffffff}
};
+static int rtl8192cu_identify_chip(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u32 val32, bonding, sys_cfg, vendor;
+ int ret = 0;
+
+ sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
+ priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
+ if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
+ dev_info(dev, "Unsupported test chip\n");
+ ret = -ENOTSUPP;
+ goto out;
+ }
+
+ if (sys_cfg & SYS_CFG_TYPE_ID) {
+ bonding = rtl8xxxu_read32(priv, REG_HPON_FSM);
+ bonding &= HPON_FSM_BONDING_MASK;
+ if (bonding == HPON_FSM_BONDING_1T2R) {
+ strscpy(priv->chip_name, "8191CU", sizeof(priv->chip_name));
+ priv->tx_paths = 1;
+ priv->usb_interrupts = 1;
+ priv->rtl_chip = RTL8191C;
+ } else {
+ strscpy(priv->chip_name, "8192CU", sizeof(priv->chip_name));
+ priv->tx_paths = 2;
+ priv->usb_interrupts = 0;
+ priv->rtl_chip = RTL8192C;
+ }
+ priv->rf_paths = 2;
+ priv->rx_paths = 2;
+ } else {
+ strscpy(priv->chip_name, "8188CU", sizeof(priv->chip_name));
+ priv->rf_paths = 1;
+ priv->rx_paths = 1;
+ priv->tx_paths = 1;
+ priv->rtl_chip = RTL8188C;
+ priv->usb_interrupts = 0;
+ }
+ priv->has_wifi = 1;
+
+ vendor = sys_cfg & SYS_CFG_VENDOR_ID;
+ rtl8xxxu_identify_vendor_1bit(priv, vendor);
+
+ val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
+ priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID);
+
+ rtl8xxxu_config_endpoints_sie(priv);
+
+ /*
+ * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX
+ */
+ if (!priv->ep_tx_count)
+ ret = rtl8xxxu_config_endpoints_no_sie(priv);
+
+out:
+ return ret;
+}
+
static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv)
{
char *fw_name;
@@ -392,7 +450,7 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv)
priv->power_base = &rtl8192c_power_base;
if (efuse->rf_regulatory & 0x20) {
- sprintf(priv->chip_name, "8188RU");
+ strscpy(priv->chip_name, "8188RU", sizeof(priv->chip_name));
priv->rtl_chip = RTL8188R;
priv->hi_pa = 1;
priv->no_pape = 1;
@@ -541,6 +599,7 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv)
}
struct rtl8xxxu_fileops rtl8192cu_fops = {
+ .identify_chip = rtl8192cu_identify_chip,
.parse_efuse = rtl8192cu_parse_efuse,
.load_firmware = rtl8192cu_load_firmware,
.power_on = rtl8192cu_power_on,
@@ -561,6 +620,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = {
.update_rate_mask = rtl8xxxu_update_rate_mask,
.report_connect = rtl8xxxu_gen1_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v1,
+ .cck_rssi = rtl8723a_cck_rssi,
.writeN_block_size = 128,
.rx_agg_buf_size = 16000,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
index 550290ae9e17..6dc1e5858e77 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
@@ -478,6 +478,53 @@ static const struct rtl8xxxu_rfregval rtl8192eu_radiob_init_table[] = {
{0xff, 0xffffffff}
};
+static int rtl8192eu_identify_chip(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u32 val32, bonding, sys_cfg, vendor;
+ int ret = 0;
+
+ sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
+ priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
+ if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
+ dev_info(dev, "Unsupported test chip\n");
+ ret = -ENOTSUPP;
+ goto out;
+ }
+
+ bonding = rtl8xxxu_read32(priv, REG_HPON_FSM);
+ bonding &= HPON_FSM_BONDING_MASK;
+ if (bonding == HPON_FSM_BONDING_1T2R) {
+ strscpy(priv->chip_name, "8191EU", sizeof(priv->chip_name));
+ priv->tx_paths = 1;
+ priv->rtl_chip = RTL8191E;
+ } else {
+ strscpy(priv->chip_name, "8192EU", sizeof(priv->chip_name));
+ priv->tx_paths = 2;
+ priv->rtl_chip = RTL8192E;
+ }
+ priv->rf_paths = 2;
+ priv->rx_paths = 2;
+ priv->has_wifi = 1;
+
+ vendor = sys_cfg & SYS_CFG_VENDOR_EXT_MASK;
+ rtl8xxxu_identify_vendor_2bits(priv, vendor);
+
+ val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
+ priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID);
+
+ rtl8xxxu_config_endpoints_sie(priv);
+
+ /*
+ * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX
+ */
+ if (!priv->ep_tx_count)
+ ret = rtl8xxxu_config_endpoints_no_sie(priv);
+
+out:
+ return ret;
+}
+
static void
rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
{
@@ -635,8 +682,7 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv)
efuse->tx_power_index_B.pwr_diff[i - 1].ht40;
}
- priv->has_xtalk = 1;
- priv->xtalk = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f;
+ priv->default_crystal_cap = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f;
/*
* device_info section seems to be laid out as records
@@ -1671,7 +1717,30 @@ static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_PAD_CTRL1, val8);
}
+static s8 rtl8192e_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
+{
+ static const s8 lna_gain_table_0[8] = {15, 9, -10, -21, -23, -27, -43, -44};
+ static const s8 lna_gain_table_1[8] = {24, 18, 13, -4, -11, -18, -31, -36};
+
+ s8 rx_pwr_all = 0x00;
+ u8 vga_idx, lna_idx;
+ s8 lna_gain = 0;
+
+ lna_idx = (cck_agc_rpt & 0xE0) >> 5;
+ vga_idx = cck_agc_rpt & 0x1F;
+
+ if (priv->cck_agc_report_type == 0)
+ lna_gain = lna_gain_table_0[lna_idx];
+ else
+ lna_gain = lna_gain_table_1[lna_idx];
+
+ rx_pwr_all = lna_gain - (2 * vga_idx);
+
+ return rx_pwr_all;
+}
+
struct rtl8xxxu_fileops rtl8192eu_fops = {
+ .identify_chip = rtl8192eu_identify_chip,
.parse_efuse = rtl8192eu_parse_efuse,
.load_firmware = rtl8192eu_load_firmware,
.power_on = rtl8192eu_power_on,
@@ -1691,6 +1760,8 @@ struct rtl8xxxu_fileops rtl8192eu_fops = {
.update_rate_mask = rtl8xxxu_gen2_update_rate_mask,
.report_connect = rtl8xxxu_gen2_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v2,
+ .set_crystal_cap = rtl8723a_set_crystal_cap,
+ .cck_rssi = rtl8192e_cck_rssi,
.writeN_block_size = 128,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
index 44565bf4c1c2..707ac48ecc83 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723a.c
@@ -129,6 +129,55 @@ static const struct rtl8xxxu_rfregval rtl8723au_radioa_1t_init_table[] = {
{0xff, 0xffffffff}
};
+static int rtl8723au_identify_chip(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u32 val32, sys_cfg, vendor;
+ int ret = 0;
+
+ sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
+ priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
+ if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
+ dev_info(dev, "Unsupported test chip\n");
+ ret = -ENOTSUPP;
+ goto out;
+ }
+
+ strscpy(priv->chip_name, "8723AU", sizeof(priv->chip_name));
+ priv->usb_interrupts = 1;
+ priv->rtl_chip = RTL8723A;
+
+ priv->rf_paths = 1;
+ priv->rx_paths = 1;
+ priv->tx_paths = 1;
+
+ val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL);
+ if (val32 & MULTI_WIFI_FUNC_EN)
+ priv->has_wifi = 1;
+ if (val32 & MULTI_BT_FUNC_EN)
+ priv->has_bluetooth = 1;
+ if (val32 & MULTI_GPS_FUNC_EN)
+ priv->has_gps = 1;
+ priv->is_multi_func = 1;
+
+ vendor = sys_cfg & SYS_CFG_VENDOR_ID;
+ rtl8xxxu_identify_vendor_1bit(priv, vendor);
+
+ val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
+ priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID);
+
+ rtl8xxxu_config_endpoints_sie(priv);
+
+ /*
+ * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX
+ */
+ if (!priv->ep_tx_count)
+ ret = rtl8xxxu_config_endpoints_no_sie(priv);
+
+out:
+ return ret;
+}
+
static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv)
{
struct rtl8723au_efuse *efuse = &priv->efuse_wifi.efuse8723;
@@ -166,10 +215,10 @@ static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv)
efuse->ht20_max_power_offset,
sizeof(efuse->ht20_max_power_offset));
- if (priv->efuse_wifi.efuse8723.version >= 0x01) {
- priv->has_xtalk = 1;
- priv->xtalk = priv->efuse_wifi.efuse8723.xtal_k & 0x3f;
- }
+ if (priv->efuse_wifi.efuse8723.version >= 0x01)
+ priv->default_crystal_cap = priv->efuse_wifi.efuse8723.xtal_k & 0x3f;
+ else
+ priv->fops->set_crystal_cap = NULL;
priv->power_base = &rtl8723a_power_base;
@@ -357,7 +406,59 @@ exit:
return ret;
}
+#define XTAL1 GENMASK(23, 18)
+#define XTAL0 GENMASK(17, 12)
+
+void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
+{
+ struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking;
+ u32 val32;
+
+ if (crystal_cap == cfo->crystal_cap)
+ return;
+
+ val32 = rtl8xxxu_read32(priv, REG_MAC_PHY_CTRL);
+
+ dev_dbg(&priv->udev->dev,
+ "%s: Adjusting crystal cap from 0x%x (actually 0x%lx 0x%lx) to 0x%x\n",
+ __func__,
+ cfo->crystal_cap,
+ FIELD_GET(XTAL1, val32),
+ FIELD_GET(XTAL0, val32),
+ crystal_cap);
+
+ val32 &= ~(XTAL1 | XTAL0);
+ val32 |= FIELD_PREP(XTAL1, crystal_cap) |
+ FIELD_PREP(XTAL0, crystal_cap);
+ rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32);
+
+ cfo->crystal_cap = crystal_cap;
+}
+
+s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
+{
+ s8 rx_pwr_all = 0x00;
+
+ switch (cck_agc_rpt & 0xc0) {
+ case 0xc0:
+ rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x80:
+ rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x40:
+ rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+ break;
+ case 0x00:
+ rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+ break;
+ }
+
+ return rx_pwr_all;
+}
+
struct rtl8xxxu_fileops rtl8723au_fops = {
+ .identify_chip = rtl8723au_identify_chip,
.parse_efuse = rtl8723au_parse_efuse,
.load_firmware = rtl8723au_load_firmware,
.power_on = rtl8723au_power_on,
@@ -378,6 +479,8 @@ struct rtl8xxxu_fileops rtl8723au_fops = {
.update_rate_mask = rtl8xxxu_update_rate_mask,
.report_connect = rtl8xxxu_gen1_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v1,
+ .set_crystal_cap = rtl8723a_set_crystal_cap,
+ .cck_rssi = rtl8723a_cck_rssi,
.writeN_block_size = 1024,
.rx_agg_buf_size = 16000,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
index a27fe06d6f77..a0ec895b61a4 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
@@ -304,6 +304,53 @@ static const struct rtl8xxxu_rfregval rtl8723bu_radioa_1t_init_table[] = {
{0xff, 0xffffffff}
};
+static int rtl8723bu_identify_chip(struct rtl8xxxu_priv *priv)
+{
+ struct device *dev = &priv->udev->dev;
+ u32 val32, sys_cfg, vendor;
+ int ret = 0;
+
+ sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
+ priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
+ if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
+ dev_info(dev, "Unsupported test chip\n");
+ ret = -ENOTSUPP;
+ goto out;
+ }
+
+ strscpy(priv->chip_name, "8723BU", sizeof(priv->chip_name));
+ priv->rtl_chip = RTL8723B;
+ priv->rf_paths = 1;
+ priv->rx_paths = 1;
+ priv->tx_paths = 1;
+
+ val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL);
+ if (val32 & MULTI_WIFI_FUNC_EN)
+ priv->has_wifi = 1;
+ if (val32 & MULTI_BT_FUNC_EN)
+ priv->has_bluetooth = 1;
+ if (val32 & MULTI_GPS_FUNC_EN)
+ priv->has_gps = 1;
+ priv->is_multi_func = 1;
+
+ vendor = sys_cfg & SYS_CFG_VENDOR_EXT_MASK;
+ rtl8xxxu_identify_vendor_2bits(priv, vendor);
+
+ val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
+ priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID);
+
+ rtl8xxxu_config_endpoints_sie(priv);
+
+ /*
+ * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX
+ */
+ if (!priv->ep_tx_count)
+ ret = rtl8xxxu_config_endpoints_no_sie(priv);
+
+out:
+ return ret;
+}
+
static void rtl8723bu_write_btreg(struct rtl8xxxu_priv *priv, u8 reg, u8 data)
{
struct h2c_cmd h2c;
@@ -445,8 +492,7 @@ static int rtl8723bu_parse_efuse(struct rtl8xxxu_priv *priv)
efuse->tx_power_index_B.pwr_diff[i - 1].ht40;
}
- priv->has_xtalk = 1;
- priv->xtalk = priv->efuse_wifi.efuse8723bu.xtal_k & 0x3f;
+ priv->default_crystal_cap = priv->efuse_wifi.efuse8723bu.xtal_k & 0x3f;
dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name);
dev_info(&priv->udev->dev, "Product: %.41s\n", efuse->device_name);
@@ -1640,7 +1686,36 @@ static void rtl8723bu_init_statistics(struct rtl8xxxu_priv *priv)
rtl8xxxu_write32(priv, REG_OFDM0_FA_RSTC, val32);
}
+static s8 rtl8723b_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
+{
+ s8 rx_pwr_all = 0x00;
+ u8 vga_idx, lna_idx;
+
+ lna_idx = (cck_agc_rpt & 0xE0) >> 5;
+ vga_idx = cck_agc_rpt & 0x1F;
+
+ switch (lna_idx) {
+ case 6:
+ rx_pwr_all = -34 - (2 * vga_idx);
+ break;
+ case 4:
+ rx_pwr_all = -14 - (2 * vga_idx);
+ break;
+ case 1:
+ rx_pwr_all = 6 - (2 * vga_idx);
+ break;
+ case 0:
+ rx_pwr_all = 16 - (2 * vga_idx);
+ break;
+ default:
+ break;
+ }
+
+ return rx_pwr_all;
+}
+
struct rtl8xxxu_fileops rtl8723bu_fops = {
+ .identify_chip = rtl8723bu_identify_chip,
.parse_efuse = rtl8723bu_parse_efuse,
.load_firmware = rtl8723bu_load_firmware,
.power_on = rtl8723bu_power_on,
@@ -1656,6 +1731,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
.parse_rx_desc = rtl8xxxu_parse_rxdesc24,
.init_aggregation = rtl8723bu_init_aggregation,
.init_statistics = rtl8723bu_init_statistics,
+ .init_burst = rtl8xxxu_init_burst,
.enable_rf = rtl8723b_enable_rf,
.disable_rf = rtl8xxxu_gen2_disable_rf,
.usb_quirks = rtl8xxxu_gen2_usb_quirks,
@@ -1663,6 +1739,8 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
.update_rate_mask = rtl8xxxu_gen2_update_rate_mask,
.report_connect = rtl8xxxu_gen2_report_connect,
.fill_txdesc = rtl8xxxu_fill_txdesc_v2,
+ .set_crystal_cap = rtl8723a_set_crystal_cap,
+ .cck_rssi = rtl8723b_cck_rssi,
.writeN_block_size = 1024,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 65bb4dc8f555..e8fcd531c437 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -1574,30 +1574,14 @@ rtl8xxxu_set_spec_sifs(struct rtl8xxxu_priv *priv, u16 cck, u16 ofdm)
static void rtl8xxxu_print_chipinfo(struct rt