wifi: rtl8xxxu: Support new chip RTL8710BU aka RTL8188GU

This chip is found in cheap "free driver" USB adapters from Aliexpress.
Initially they pretend to be a CD-ROM containing the driver for Windows.
"Ejecting" switches the device to wifi mode.

Features: 2.4 GHz, b/g/n mode, 1T1R, 150 Mbps.

This chip is more unique than other Realtek chips:

* The registers at addresses 0x0-0xff, which all the other chips use,
  can't be used here. New registers at 0x8000-0x80ff must be used
  instead. And it's not a simple matter of adding 0x8000: 0x2
  (REG_SYS_FUNC) became 0x8004, 0x80 (REG_MCU_FW_DL) became 0x8090,
  etc.

* Also there are a few new registers which must be accessed indirectly
  because their addresses don't fit in 16 bits. No other chips seem to
  have these.

* The vendor driver compiles to 8188gu.ko, but the code calls the chip
  RTL8710B(U) pretty much everywhere, including messages visible to the
  user.

Another difference compared to the other chips supported by rtl8xxxu is
that it has a new PHY status struct, or three of them actually, from
which we extract the RSSI, among other things. This is not unique,
though, just new. The chips supported by rtw88 also use it.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
Tested-by: Philipp Hortmann <philipp.g.hortmann@gmail.com> # Edimax N150
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/4edbe29f-00b9-8eef-9789-20bed0b141e2@gmail.com
This commit is contained in:
Bitterblue Smith 2023-03-13 15:58:14 +02:00 committed by Kalle Valo
parent d46e04ccd4
commit 70664495e3
12 changed files with 2481 additions and 62 deletions

View file

@ -11,7 +11,7 @@ config RTL8XXXU
parts written to utilize the Linux mac80211 stack.
The driver is known to work with a number of RTL8723AU,
RL8188CU, RTL8188RU, RTL8191CU, RTL8192CU, RTL8723BU, RTL8192EU,
RTL8188FU, and RTL8188EU devices.
RTL8188FU, RTL8188EU, and RTL8710BU (aka RTL8188GU) devices.
This driver is under development and has a limited feature
set. In particular it does not yet support 40MHz channels

View file

@ -3,4 +3,4 @@ obj-$(CONFIG_RTL8XXXU) += rtl8xxxu.o
rtl8xxxu-y := rtl8xxxu_core.o rtl8xxxu_8192e.o rtl8xxxu_8723b.o \
rtl8xxxu_8723a.o rtl8xxxu_8192c.o rtl8xxxu_8188f.o \
rtl8xxxu_8188e.o
rtl8xxxu_8188e.o rtl8xxxu_8710b.o

View file

@ -103,7 +103,8 @@ enum rtl8xxxu_rtl_chip {
RTL8822B = 0x8822b,
RTL8703B = 0x8703b,
RTL8195A = 0x8195a,
RTL8188F = 0x8188f
RTL8188F = 0x8188f,
RTL8710B = 0x8710b,
};
enum rtl8xxxu_rx_type {
@ -618,6 +619,265 @@ struct rtl8723au_phy_stats {
#endif
};
struct jaguar2_phy_stats_type0 {
/* DW0 */
u8 page_num;
u8 pwdb;
#ifdef __LITTLE_ENDIAN
u8 gain: 6;
u8 rsvd_0: 1;
u8 trsw: 1;
#else
u8 trsw: 1;
u8 rsvd_0: 1;
u8 gain: 6;
#endif
u8 rsvd_1;
/* DW1 */
u8 rsvd_2;
#ifdef __LITTLE_ENDIAN
u8 rxsc: 4;
u8 agc_table: 4;
#else
u8 agc_table: 4;
u8 rxsc: 4;
#endif
u8 channel;
u8 band;
/* DW2 */
u16 length;
#ifdef __LITTLE_ENDIAN
u8 antidx_a: 3;
u8 antidx_b: 3;
u8 rsvd_3: 2;
u8 antidx_c: 3;
u8 antidx_d: 3;
u8 rsvd_4:2;
#else
u8 rsvd_3: 2;
u8 antidx_b: 3;
u8 antidx_a: 3;
u8 rsvd_4:2;
u8 antidx_d: 3;
u8 antidx_c: 3;
#endif
/* DW3 */
u8 signal_quality;
#ifdef __LITTLE_ENDIAN
u8 vga:5;
u8 lna_l:3;
u8 bb_power:6;
u8 rsvd_9:1;
u8 lna_h:1;
#else
u8 lna_l:3;
u8 vga:5;
u8 lna_h:1;
u8 rsvd_9:1;
u8 bb_power:6;
#endif
u8 rsvd_5;
/* DW4 */
u32 rsvd_6;
/* DW5 */
u32 rsvd_7;
/* DW6 */
u32 rsvd_8;
} __packed;
struct jaguar2_phy_stats_type1 {
/* DW0 and DW1 */
u8 page_num;
u8 pwdb[4];
#ifdef __LITTLE_ENDIAN
u8 l_rxsc: 4;
u8 ht_rxsc: 4;
#else
u8 ht_rxsc: 4;
u8 l_rxsc: 4;
#endif
u8 channel;
#ifdef __LITTLE_ENDIAN
u8 band: 2;
u8 rsvd_0: 1;
u8 hw_antsw_occu: 1;
u8 gnt_bt: 1;
u8 ldpc: 1;
u8 stbc: 1;
u8 beamformed: 1;
#else
u8 beamformed: 1;
u8 stbc: 1;
u8 ldpc: 1;
u8 gnt_bt: 1;
u8 hw_antsw_occu: 1;
u8 rsvd_0: 1;
u8 band: 2;
#endif
/* DW2 */
u16 lsig_length;
#ifdef __LITTLE_ENDIAN
u8 antidx_a: 3;
u8 antidx_b: 3;
u8 rsvd_1: 2;
u8 antidx_c: 3;
u8 antidx_d: 3;
u8 rsvd_2: 2;
#else
u8 rsvd_1: 2;
u8 antidx_b: 3;
u8 antidx_a: 3;
u8 rsvd_2: 2;
u8 antidx_d: 3;
u8 antidx_c: 3;
#endif
/* DW3 */
u8 paid;
#ifdef __LITTLE_ENDIAN
u8 paid_msb: 1;
u8 gid: 6;
u8 rsvd_3: 1;
#else
u8 rsvd_3: 1;
u8 gid: 6;
u8 paid_msb: 1;
#endif
u8 intf_pos;
#ifdef __LITTLE_ENDIAN
u8 intf_pos_msb: 1;
u8 rsvd_4: 2;
u8 nb_intf_flag: 1;
u8 rf_mode: 2;
u8 rsvd_5: 2;
#else
u8 rsvd_5: 2;
u8 rf_mode: 2;
u8 nb_intf_flag: 1;
u8 rsvd_4: 2;
u8 intf_pos_msb: 1;
#endif
/* DW4 */
s8 rxevm[4]; /* s(8,1) */
/* DW5 */
s8 cfo_tail[4]; /* s(8,7) */
/* DW6 */
s8 rxsnr[4]; /* s(8,1) */
} __packed;
struct jaguar2_phy_stats_type2 {
/* DW0 ane DW1 */
u8 page_num;
u8 pwdb[4];
#ifdef __LITTLE_ENDIAN
u8 l_rxsc: 4;
u8 ht_rxsc: 4;
#else
u8 ht_rxsc: 4;
u8 l_rxsc: 4;
#endif
u8 channel;
#ifdef __LITTLE_ENDIAN
u8 band: 2;
u8 rsvd_0: 1;
u8 hw_antsw_occu: 1;
u8 gnt_bt: 1;
u8 ldpc: 1;
u8 stbc: 1;
u8 beamformed: 1;
#else
u8 beamformed: 1;
u8 stbc: 1;
u8 ldpc: 1;
u8 gnt_bt: 1;
u8 hw_antsw_occu: 1;
u8 rsvd_0: 1;
u8 band: 2;
#endif
/* DW2 */
#ifdef __LITTLE_ENDIAN
u8 shift_l_map: 6;
u8 rsvd_1: 2;
#else
u8 rsvd_1: 2;
u8 shift_l_map: 6;
#endif
u8 cnt_pw2cca;
#ifdef __LITTLE_ENDIAN
u8 agc_table_a: 4;
u8 agc_table_b: 4;
u8 agc_table_c: 4;
u8 agc_table_d: 4;
#else
u8 agc_table_b: 4;
u8 agc_table_a: 4;
u8 agc_table_d: 4;
u8 agc_table_c: 4;
#endif
/* DW3 ~ DW6*/
u8 cnt_cca2agc_rdy;
#ifdef __LITTLE_ENDIAN
u8 gain_a: 6;
u8 rsvd_2: 1;
u8 trsw_a: 1;
u8 gain_b: 6;
u8 rsvd_3: 1;
u8 trsw_b: 1;
u8 gain_c: 6;
u8 rsvd_4: 1;
u8 trsw_c: 1;
u8 gain_d: 6;
u8 rsvd_5: 1;
u8 trsw_d: 1;
u8 aagc_step_a: 2;
u8 aagc_step_b: 2;
u8 aagc_step_c: 2;
u8 aagc_step_d: 2;
#else
u8 trsw_a: 1;
u8 rsvd_2: 1;
u8 gain_a: 6;
u8 trsw_b: 1;
u8 rsvd_3: 1;
u8 gain_b: 6;
u8 trsw_c: 1;
u8 rsvd_4: 1;
u8 gain_c: 6;
u8 trsw_d: 1;
u8 rsvd_5: 1;
u8 gain_d: 6;
u8 aagc_step_d: 2;
u8 aagc_step_c: 2;
u8 aagc_step_b: 2;
u8 aagc_step_a: 2;
#endif
u8 ht_aagc_gain[4];
u8 dagc_gain[4];
#ifdef __LITTLE_ENDIAN
u8 counter: 6;
u8 rsvd_6: 2;
u8 syn_count: 5;
u8 rsvd_7:3;
#else
u8 rsvd_6: 2;
u8 counter: 6;
u8 rsvd_7:3;
u8 syn_count: 5;
#endif
} __packed;
/*
* Regs to backup
*/
@ -963,6 +1223,29 @@ struct rtl8188eu_efuse {
u8 res12[0xc3];
} __packed;
struct rtl8710bu_efuse {
__le16 rtl_id;
u8 res0[0x1e];
struct rtl8188fu_efuse_tx_power tx_power_index_A; /* 0x20 */
u8 res1[0x9c]; /* 0x2c */
u8 channel_plan; /* 0xc8 */
u8 xtal_k; /* 0xc9 */
u8 thermal_meter; /* 0xca */
u8 res2[0x4f];
u8 mac_addr[ETH_ALEN]; /* 0x11a */
u8 res3[0x11];
u8 rf_board_option; /* 0x131 */
u8 res4[2];
u8 eeprom_version; /* 0x134 */
u8 eeprom_customer_id; /* 0x135 */
u8 res5[5];
u8 country_code; /* 0x13b */
u8 res6[0x84];
u8 vid[2]; /* 0x1c0 */
u8 pid[2]; /* 0x1c2 */
u8 res7[0x3c];
} __packed;
struct rtl8xxxu_reg8val {
u16 reg;
u8 val;
@ -1486,6 +1769,7 @@ struct rtl8xxxu_priv {
struct rtl8723au_idx ht20_tx_power_diff[RTL8723B_TX_COUNT];
struct rtl8723au_idx ht40_tx_power_diff[RTL8723B_TX_COUNT];
struct rtl8xxxu_power_base *power_base;
u8 package_type;
u32 chip_cut:4;
u32 rom_rev:4;
u32 is_multi_func:1;
@ -1505,6 +1789,7 @@ struct rtl8xxxu_priv {
u32 ep_tx_low_queue:1;
u32 rx_buf_aggregation:1;
u32 cck_agc_report_type:1;
u32 cck_new_agc:1;
u8 default_crystal_cap;
unsigned int pipe_interrupt;
unsigned int pipe_in;
@ -1522,6 +1807,8 @@ struct rtl8xxxu_priv {
int nr_out_eps;
struct mutex h2c_mutex;
/* Protect the indirect register accesses of RTL8710BU. */
struct mutex syson_indirect_access_mutex;
struct usb_anchor rx_anchor;
struct usb_anchor tx_anchor;
@ -1542,6 +1829,7 @@ struct rtl8xxxu_priv {
struct rtl8192eu_efuse efuse8192eu;
struct rtl8188fu_efuse efuse8188fu;
struct rtl8188eu_efuse efuse8188eu;
struct rtl8710bu_efuse efuse8710bu;
} efuse_wifi;
u32 adda_backup[RTL8XXXU_ADDA_REGS];
u32 mac_backup[RTL8XXXU_MAC_REGS];
@ -1586,6 +1874,7 @@ struct rtl8xxxu_tx_urb {
struct rtl8xxxu_fileops {
int (*identify_chip) (struct rtl8xxxu_priv *priv);
int (*read_efuse) (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);
@ -1599,6 +1888,11 @@ struct rtl8xxxu_fileops {
void (*phy_iq_calibrate) (struct rtl8xxxu_priv *priv);
void (*config_channel) (struct ieee80211_hw *hw);
int (*parse_rx_desc) (struct rtl8xxxu_priv *priv, struct sk_buff *skb);
void (*parse_phystats) (struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct rtl8723au_phy_stats *phy_stats,
u32 rxmcs, struct ieee80211_hdr *hdr,
bool crc_icv_err);
void (*init_aggregation) (struct rtl8xxxu_priv *priv);
void (*init_statistics) (struct rtl8xxxu_priv *priv);
void (*init_burst) (struct rtl8xxxu_priv *priv);
@ -1618,7 +1912,7 @@ struct rtl8xxxu_fileops {
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);
s8 (*cck_rssi) (struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats);
int (*led_classdev_brightness_set) (struct led_classdev *led_cdev,
enum led_brightness brightness);
int writeN_block_size;
@ -1687,10 +1981,12 @@ 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);
int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv);
void rtl8xxxu_reset_8051(struct rtl8xxxu_priv *priv);
int rtl8xxxu_auto_llt_table(struct rtl8xxxu_priv *priv);
void rtl8xxxu_gen2_prepare_calibrate(struct rtl8xxxu_priv *priv, u8 start);
void rtl8723a_phy_lc_calibrate(struct rtl8xxxu_priv *priv);
void rtl8188f_phy_lc_calibrate(struct rtl8xxxu_priv *priv);
int rtl8xxxu_flush_fifo(struct rtl8xxxu_priv *priv);
int rtl8xxxu_gen2_h2c_cmd(struct rtl8xxxu_priv *priv,
struct h2c_cmd *h2c, int len);
@ -1724,6 +2020,16 @@ 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);
void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct rtl8723au_phy_stats *phy_stats,
u32 rxmcs, struct ieee80211_hdr *hdr,
bool crc_icv_err);
void jaguar2_rx_parse_phystats(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct rtl8723au_phy_stats *phy_stats,
u32 rxmcs, struct ieee80211_hdr *hdr,
bool crc_icv_err);
int rtl8xxxu_gen2_channel_to_group(int channel);
bool rtl8xxxu_simularity_compare(struct rtl8xxxu_priv *priv,
int result[][8], int c1, int c2);
@ -1749,12 +2055,13 @@ void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
void rtl8723bu_phy_init_antenna_selection(struct rtl8xxxu_priv *priv);
void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap);
void rtl8188f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap);
s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt);
s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats);
void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt,
u8 rate, u8 sgi, u8 bw);
void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra);
void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb);
extern struct rtl8xxxu_fileops rtl8710bu_fops;
extern struct rtl8xxxu_fileops rtl8188fu_fops;
extern struct rtl8xxxu_fileops rtl8188eu_fops;
extern struct rtl8xxxu_fileops rtl8192cu_fops;

View file

@ -1326,13 +1326,14 @@ static void rtl8188e_usb_quirks(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_EARLY_MODE_CONTROL_8188E + 3, 0x01);
}
static s8 rtl8188e_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
static s8 rtl8188e_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
{
/* only use lna 0/1/2/3/7 */
static const s8 lna_gain_table_0[8] = {17, -1, -13, -29, -32, -35, -38, -41};
/* only use lna 3/7 */
static const s8 lna_gain_table_1[8] = {29, 20, 12, 3, -6, -15, -24, -33};
u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
s8 rx_pwr_all = 0x00;
u8 vga_idx, lna_idx;
s8 lna_gain = 0;
@ -1856,6 +1857,7 @@ struct rtl8xxxu_fileops rtl8188eu_fops = {
.load_firmware = rtl8188eu_load_firmware,
.power_on = rtl8188eu_power_on,
.power_off = rtl8188eu_power_off,
.read_efuse = rtl8xxxu_read_efuse,
.reset_8051 = rtl8188eu_reset_8051,
.llt_init = rtl8xxxu_init_llt_table,
.init_phy_bb = rtl8188eu_init_phy_bb,
@ -1864,6 +1866,7 @@ struct rtl8xxxu_fileops rtl8188eu_fops = {
.phy_iq_calibrate = rtl8188eu_phy_iq_calibrate,
.config_channel = rtl8188eu_config_channel,
.parse_rx_desc = rtl8xxxu_parse_rxdesc16,
.parse_phystats = rtl8723au_rx_parse_phystats,
.init_aggregation = rtl8188eu_init_aggregation,
.enable_rf = rtl8188e_enable_rf,
.disable_rf = rtl8188e_disable_rf,

View file

@ -791,7 +791,7 @@ static int rtl8188fu_init_phy_rf(struct rtl8xxxu_priv *priv)
return ret;
}
static void rtl8188f_phy_lc_calibrate(struct rtl8xxxu_priv *priv)
void rtl8188f_phy_lc_calibrate(struct rtl8xxxu_priv *priv)
{
u32 val32;
u32 rf_amode, lstf;
@ -1677,8 +1677,9 @@ void rtl8188f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
cfo->crystal_cap = crystal_cap;
}
static s8 rtl8188f_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
static s8 rtl8188f_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
{
u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
s8 rx_pwr_all = 0x00;
u8 vga_idx, lna_idx;
@ -1714,6 +1715,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
.load_firmware = rtl8188fu_load_firmware,
.power_on = rtl8188fu_power_on,
.power_off = rtl8188fu_power_off,
.read_efuse = rtl8xxxu_read_efuse,
.reset_8051 = rtl8xxxu_reset_8051,
.llt_init = rtl8xxxu_auto_llt_table,
.init_phy_bb = rtl8188fu_init_phy_bb,
@ -1723,6 +1725,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = {
.phy_iq_calibrate = rtl8188fu_phy_iq_calibrate,
.config_channel = rtl8188fu_config_channel,
.parse_rx_desc = rtl8xxxu_parse_rxdesc24,
.parse_phystats = rtl8723au_rx_parse_phystats,
.init_aggregation = rtl8188fu_init_aggregation,
.init_statistics = rtl8188fu_init_statistics,
.init_burst = rtl8xxxu_init_burst,

View file

@ -594,6 +594,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = {
.load_firmware = rtl8192cu_load_firmware,
.power_on = rtl8192cu_power_on,
.power_off = rtl8xxxu_power_off,
.read_efuse = rtl8xxxu_read_efuse,
.reset_8051 = rtl8xxxu_reset_8051,
.llt_init = rtl8xxxu_init_llt_table,
.init_phy_bb = rtl8xxxu_gen1_init_phy_bb,
@ -602,6 +603,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = {
.phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate,
.config_channel = rtl8xxxu_gen1_config_channel,
.parse_rx_desc = rtl8xxxu_parse_rxdesc16,
.parse_phystats = rtl8723au_rx_parse_phystats,
.init_aggregation = rtl8xxxu_gen1_init_aggregation,
.enable_rf = rtl8xxxu_gen1_enable_rf,
.disable_rf = rtl8xxxu_gen1_disable_rf,

View file

@ -1742,11 +1742,12 @@ static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
}
static s8 rtl8192e_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
static s8 rtl8192e_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
{
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};
u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
s8 rx_pwr_all = 0x00;
u8 vga_idx, lna_idx;
s8 lna_gain = 0;
@ -1793,6 +1794,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops = {
.load_firmware = rtl8192eu_load_firmware,
.power_on = rtl8192eu_power_on,
.power_off = rtl8192eu_power_off,
.read_efuse = rtl8xxxu_read_efuse,
.reset_8051 = rtl8xxxu_reset_8051,
.llt_init = rtl8xxxu_auto_llt_table,
.init_phy_bb = rtl8192eu_init_phy_bb,
@ -1801,6 +1803,7 @@ struct rtl8xxxu_fileops rtl8192eu_fops = {
.phy_iq_calibrate = rtl8192eu_phy_iq_calibrate,
.config_channel = rtl8xxxu_gen2_config_channel,
.parse_rx_desc = rtl8xxxu_parse_rxdesc24,
.parse_phystats = rtl8723au_rx_parse_phystats,
.enable_rf = rtl8192e_enable_rf,
.disable_rf = rtl8xxxu_gen2_disable_rf,
.usb_quirks = rtl8xxxu_gen2_usb_quirks,

File diff suppressed because it is too large Load diff

View file

@ -435,8 +435,9 @@ void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
cfo->crystal_cap = crystal_cap;
}
s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, u8 cck_agc_rpt)
s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
{
u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
s8 rx_pwr_all = 0x00;
switch (cck_agc_rpt & 0xc0) {
@ -487,6 +488,7 @@ struct rtl8xxxu_fileops rtl8723au_fops = {
.load_firmware = rtl8723au_load_firmware,
.power_on = rtl8723au_power_on,
.power_off = rtl8xxxu_power_off,
.read_efuse = rtl8xxxu_read_efuse,
.reset_8051 = rtl8xxxu_reset_8051,
.llt_init = rtl8xxxu_init_llt_table,
.init_phy_bb = rtl8xxxu_gen1_init_phy_bb,
@ -495,6 +497,7 @@ struct rtl8xxxu_fileops rtl8723au_fops = {
.phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate,
.config_channel = rtl8xxxu_gen1_config_channel,
.parse_rx_desc = rtl8xxxu_parse_rxdesc16,
.parse_phystats = rtl8723au_rx_parse_phystats,
.init_aggregation = rtl8xxxu_gen1_init_aggregation,
.enable_rf = rtl8xxxu_gen1_enable_rf,
.disable_rf = rtl8xxxu_gen1_disable_rf,

View file

@ -1675,8 +1675,9 @@ 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)
static s8 rtl8723b_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
{
u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
s8 rx_pwr_all = 0x00;
u8 vga_idx, lna_idx;
@ -1709,6 +1710,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
.load_firmware = rtl8723bu_load_firmware,
.power_on = rtl8723bu_power_on,
.power_off = rtl8723bu_power_off,
.read_efuse = rtl8xxxu_read_efuse,
.reset_8051 = rtl8723bu_reset_8051,
.llt_init = rtl8xxxu_auto_llt_table,
.init_phy_bb = rtl8723bu_init_phy_bb,
@ -1718,6 +1720,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = {
.phy_iq_calibrate = rtl8723bu_phy_iq_calibrate,
.config_channel = rtl8xxxu_gen2_config_channel,
.parse_rx_desc = rtl8xxxu_parse_rxdesc24,
.parse_phystats = rtl8723au_rx_parse_phystats,
.init_aggregation = rtl8723bu_init_aggregation,
.init_statistics = rtl8723bu_init_statistics,
.init_burst = rtl8xxxu_init_burst,

View file

@ -54,6 +54,8 @@ MODULE_FIRMWARE("rtlwifi/rtl8192eu_nic.bin");
MODULE_FIRMWARE("rtlwifi/rtl8723bu_nic.bin");
MODULE_FIRMWARE("rtlwifi/rtl8723bu_bt.bin");
MODULE_FIRMWARE("rtlwifi/rtl8188fufw.bin");
MODULE_FIRMWARE("rtlwifi/rtl8710bufw_SMIC.bin");
MODULE_FIRMWARE("rtlwifi/rtl8710bufw_UMC.bin");
module_param_named(debug, rtl8xxxu_debug, int, 0600);
MODULE_PARM_DESC(debug, "Set debug mask");
@ -654,6 +656,9 @@ u8 rtl8xxxu_read8(struct rtl8xxxu_priv *priv, u16 addr)
int len;
u8 data;
if (priv->rtl_chip == RTL8710B && addr <= 0xff)
addr |= 0x8000;
mutex_lock(&priv->usb_buf_mutex);
len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
REALTEK_USB_CMD_REQ, REALTEK_USB_READ,
@ -674,6 +679,9 @@ u16 rtl8xxxu_read16(struct rtl8xxxu_priv *priv, u16 addr)
int len;
u16 data;
if (priv->rtl_chip == RTL8710B && addr <= 0xff)
addr |= 0x8000;
mutex_lock(&priv->usb_buf_mutex);
len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
REALTEK_USB_CMD_REQ, REALTEK_USB_READ,
@ -694,6 +702,9 @@ u32 rtl8xxxu_read32(struct rtl8xxxu_priv *priv, u16 addr)
int len;
u32 data;
if (priv->rtl_chip == RTL8710B && addr <= 0xff)
addr |= 0x8000;
mutex_lock(&priv->usb_buf_mutex);
len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
REALTEK_USB_CMD_REQ, REALTEK_USB_READ,
@ -713,6 +724,9 @@ int rtl8xxxu_write8(struct rtl8xxxu_priv *priv, u16 addr, u8 val)
struct usb_device *udev = priv->udev;
int ret;
if (priv->rtl_chip == RTL8710B && addr <= 0xff)
addr |= 0x8000;
mutex_lock(&priv->usb_buf_mutex);
priv->usb_buf.val8 = val;
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
@ -733,6 +747,9 @@ int rtl8xxxu_write16(struct rtl8xxxu_priv *priv, u16 addr, u16 val)
struct usb_device *udev = priv->udev;
int ret;
if (priv->rtl_chip == RTL8710B && addr <= 0xff)
addr |= 0x8000;
mutex_lock(&priv->usb_buf_mutex);
priv->usb_buf.val16 = cpu_to_le16(val);
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
@ -752,6 +769,9 @@ int rtl8xxxu_write32(struct rtl8xxxu_priv *priv, u16 addr, u32 val)
struct usb_device *udev = priv->udev;
int ret;
if (priv->rtl_chip == RTL8710B && addr <= 0xff)
addr |= 0x8000;
mutex_lock(&priv->usb_buf_mutex);
priv->usb_buf.val32 = cpu_to_le32(val);
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
@ -1699,7 +1719,7 @@ rtl8xxxu_read_efuse8(struct rtl8xxxu_priv *priv, u16 offset, u8 *data)
return 0;
}
static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv)
int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv)
{
struct device *dev = &priv->udev->dev;
int i, ret = 0;
@ -1845,12 +1865,18 @@ void rtl8xxxu_reset_8051(struct rtl8xxxu_priv *priv)
static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv)
{
struct device *dev = &priv->udev->dev;
u16 reg_mcu_fw_dl;
int ret = 0, i;
u32 val32;
if (priv->rtl_chip == RTL8710B)
reg_mcu_fw_dl = REG_8051FW_CTRL_V1_8710B;
else
reg_mcu_fw_dl = REG_MCU_FW_DL;
/* Poll checksum report */
for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) {
val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL);
val32 = rtl8xxxu_read32(priv, reg_mcu_fw_dl);
if (val32 & MCU_FW_DL_CSUM_REPORT)
break;
}
@ -1861,10 +1887,10 @@ static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv)
goto exit;
}
val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL);
val32 = rtl8xxxu_read32(priv, reg_mcu_fw_dl);
val32 |= MCU_FW_DL_READY;
val32 &= ~MCU_WINT_INIT_READY;
rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32);
rtl8xxxu_write32(priv, reg_mcu_fw_dl, val32);
/*
* Reset the 8051 in order for the firmware to start running,
@ -1874,7 +1900,7 @@ static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv)
/* Wait for firmware to become ready */
for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) {
val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL);
val32 = rtl8xxxu_read32(priv, reg_mcu_fw_dl);
if (val32 & MCU_WINT_INIT_READY)
break;
@ -1890,7 +1916,7 @@ static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv)
/*
* Init H2C command
*/
if (priv->rtl_chip == RTL8723B || priv->rtl_chip == RTL8188F)
if (priv->rtl_chip == RTL8723B || priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B)
rtl8xxxu_write8(priv, REG_HMTFR, 0x0f);
exit:
return ret;
@ -1899,42 +1925,56 @@ static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv)
static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
{
int pages, remainder, i, ret;
u16 reg_mcu_fw_dl;
u8 val8;
u16 val16;
u32 val32;
u8 *fwptr;
val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC + 1);
val8 |= 4;
rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, val8);
if (priv->rtl_chip == RTL8710B) {
reg_mcu_fw_dl = REG_8051FW_CTRL_V1_8710B;
} else {
reg_mcu_fw_dl = REG_MCU_FW_DL;
/* 8051 enable */
val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
val16 |= SYS_FUNC_CPU_ENABLE;
rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC + 1);
val8 |= 4;
rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, val8);
val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL);
/* 8051 enable */
val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
val16 |= SYS_FUNC_CPU_ENABLE;
rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
}
val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl);
if (val8 & MCU_FW_RAM_SEL) {
dev_info(&priv->udev->dev,
"Firmware is already running, resetting the MCU.\n");
rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
rtl8xxxu_write8(priv, reg_mcu_fw_dl, 0x00);
priv->fops->reset_8051(priv);
}
/* MCU firmware download enable */
val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL);
val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl);
val8 |= MCU_FW_DL_ENABLE;
rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8);
rtl8xxxu_write8(priv, reg_mcu_fw_dl, val8);
/* 8051 reset */
val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL);
val32 = rtl8xxxu_read32(priv, reg_mcu_fw_dl);
val32 &= ~BIT(19);
rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32);
rtl8xxxu_write32(priv, reg_mcu_fw_dl, val32);
if (priv->rtl_chip == RTL8710B) {
/* We must set 0x8090[8]=1 before download FW. */
val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl + 1);
val8 |= BIT(0);
rtl8xxxu_write8(priv, reg_mcu_fw_dl + 1, val8);
}
/* Reset firmware download checksum */
val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL);
val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl);
val8 |= MCU_FW_DL_CSUM_REPORT;
rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8);
rtl8xxxu_write8(priv, reg_mcu_fw_dl, val8);
pages = priv->fw_size / RTL_FW_PAGE_SIZE;
remainder = priv->fw_size % RTL_FW_PAGE_SIZE;
@ -1942,9 +1982,9 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
fwptr = priv->fw_data->data;
for (i = 0; i < pages; i++) {
val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8;
val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl + 2) & 0xF8;
val8 |= i;
rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8);
rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8);
ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
fwptr, RTL_FW_PAGE_SIZE);
@ -1957,9 +1997,9 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
}
if (remainder) {
val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8;
val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl + 2) & 0xF8;
val8 |= i;
rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8);
rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8);
ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
fwptr, remainder);
if (ret != remainder) {
@ -1971,9 +2011,9 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
ret = 0;
fw_abort:
/* MCU firmware download disable */
val16 = rtl8xxxu_read16(priv, REG_MCU_FW_DL);
val16 = rtl8xxxu_read16(priv, reg_mcu_fw_dl);
val16 &= ~MCU_FW_DL_ENABLE;
rtl8xxxu_write16(priv, REG_MCU_FW_DL, val16);
rtl8xxxu_write16(priv, reg_mcu_fw_dl, val16);
return ret;
}
@ -2013,6 +2053,7 @@ int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, const char *fw_name)
case 0x5300:
case 0x2300:
case 0x88f0:
case 0x10b0:
break;
default:
ret = -EINVAL;
@ -3823,7 +3864,7 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv)
rtl8xxxu_write8(priv, REG_HT_SINGLE_AMPDU_8723B, val8);
rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, 0x0c14);
if (priv->rtl_chip == RTL8723B)
if (priv->rtl_chip == RTL8723B || priv->rtl_chip == RTL8710B)
val8 = 0x5e;
else if (priv->rtl_chip == RTL8188F)
val8 = 0x70; /* 0x5e would make it very slow */
@ -3831,13 +3872,17 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv)
rtl8xxxu_write32(priv, REG_AGGLEN_LMT, 0xffffffff);
rtl8xxxu_write8(priv, REG_RX_PKT_LIMIT, 0x18);
rtl8xxxu_write8(priv, REG_PIFS, 0x00);
if (priv->rtl_chip == RTL8188F) {
if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B) {
rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, FWHW_TXQ_CTRL_AMPDU_RETRY);
rtl8xxxu_write32(priv, REG_FAST_EDCA_CTRL, 0x03086666);
}
/*
* The RTL8710BU vendor driver uses 0x50 here and it works fine,
* but in rtl8xxxu 0x50 causes slow upload and random packet loss. Why?
*/
if (priv->rtl_chip == RTL8723B)
val8 = 0x50;
else if (priv->rtl_chip == RTL8188F)
else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B)
val8 = 0x28; /* 0x50 would make the upload slow */
rtl8xxxu_write8(priv, REG_USTIME_TSF_8723B, val8);
rtl8xxxu_write8(priv, REG_USTIME_EDCA, val8);
@ -3923,7 +3968,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
/* RFSW Control - clear bit 14 ?? */
if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E &&
priv->rtl_chip != RTL8188E)
priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B)
rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003);
val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW |
@ -3936,7 +3981,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32);
/* 0x860[6:5]= 00 - why? - this sets antenna B */
if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188E)
if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188E &&
priv->rtl_chip != RTL8710B)
rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210);
if (!macpower) {
@ -4009,10 +4055,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
val8 &= 0xf8;
rtl8xxxu_write8(priv, 0xa3, val8);
}
if (priv->rtl_chip == RTL8710B)
rtl8xxxu_write8(priv, REG_EARLY_MODE_CONTROL_8710B, 0);
}
/*
* Unit in 8 bytes, not obvious what it is used for
* Unit in 8 bytes.
* Get Rx PHY status in order to report RSSI and others.
*/
rtl8xxxu_write8(priv, REG_RX_DRVINFO_SZ, 4);
@ -4031,6 +4081,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
val8 = rtl8xxxu_read8(priv, REG_USB_SPECIAL_OPTION);
val8 |= USB_SPEC_INT_BULK_SELECT;
rtl8xxxu_write8(priv, REG_USB_SPECIAL_OPTION, val8);
} else if (priv->rtl_chip == RTL8710B) {
rtl8xxxu_write32(priv, REG_HIMR0_8710B, 0);
} else {
/*
* Enable all interrupts - not obvious USB needs to do this
@ -4050,7 +4102,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC;
rtl8xxxu_write32(priv, REG_RCR, val32);
if (priv->rtl_chip == RTL8188F) {
if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B) {
/* Accept all data frames */
rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
@ -4119,7 +4171,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
val16 = BEACON_DISABLE_TSF_UPDATE | (BEACON_DISABLE_TSF_UPDATE << 8);
rtl8xxxu_write16(priv, REG_BEACON_CTRL, val16);
rtl8xxxu_write16(priv, REG_TBTT_PROHIBIT, 0x6404);
if (priv->rtl_chip != RTL8188F)
if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B)
/* Firmware will control REG_DRVERLYINT when power saving is enable, */
/* so don't set this register on STA mode. */
rtl8xxxu_write8(priv, REG_DRIVER_EARLY_INT, DRIVER_EARLY_INT_TIME);
@ -4129,14 +4181,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
/*
* Initialize burst parameters
*/
if (priv->fops->init_burst)
priv->fops->init_burst(priv);
if (fops->init_aggregation)
fops->init_aggregation(priv);
if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E) {
if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E ||
priv->rtl_chip == RTL8710B) {
rtl8xxxu_write16(priv, REG_PKT_VO_VI_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
rtl8xxxu_write16(priv, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
}
@ -4159,7 +4211,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
fops->set_tx_power(priv, 1, false);
/* Let the 8051 take control of antenna setting */
if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188F) {
if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188F &&
priv->rtl_chip != RTL8710B) {
val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
val8 |= LEDCFG2_DPDT_SELECT;
rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
@ -4170,7 +4223,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
/* Disable BAR - not sure if this has any effect on USB */
rtl8xxxu_write32(priv, REG_BAR_MODE_CTRL, 0x0201ffff);
if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E)
if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B)
rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0);
if (fops->init_statistics)
@ -4209,7 +4262,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
* This should enable thermal meter
*/
if (fops->gen2_thermal_meter) {
if (priv->rtl_chip == RTL8188F) {
if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B) {
val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_T_METER_8723B);
val32 |= 0x30000;
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_T_METER_8723B, val32);
@ -4281,6 +4334,24 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
rtl8xxxu_write32(priv, REG_AGC_RPT, val32);
}
if (priv->rtl_chip == RTL8710B) {
/*
* 0x76D[5:4] is Port0,Port1 Enable Bit.
* This is only for 8710B, 2b'00 for MP and 2b'11 for Normal Driver
*/
val8 = rtl8xxxu_read8(priv, REG_PORT_CONTROL_8710B);
val8 |= BIT(5) | BIT(4);
rtl8xxxu_write8(priv, REG_PORT_CONTROL_8710B, val8);
/* Set 0x5c[8] and [2:0] = 1, LDO mode */
val32 = rtl8xxxu_read32(priv, REG_WL_RF_PSS_8710B);
val32 |= 0x107;
rtl8xxxu_write32(priv, REG_WL_RF_PSS_8710B, val32);
}
val32 = rtl8xxxu_read32(priv, 0xa9c);
priv->cck_new_agc = u32_get_bits(val32, BIT(17));
/* Initialise the center frequency offset tracking */
if (priv->fops->set_crystal_cap) {
val32 = rtl8xxxu_read32(priv, REG_OFDM1_CFO_TRACKING);
@ -5370,6 +5441,10 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
rtl8xxxu_calc_tx_desc_csum(tx_desc);
/* avoid zero checksum make tx hang */
if (priv->rtl_chip == RTL8710B)
tx_desc->csum = ~tx_desc->csum;
usb_fill_bulk_urb(&tx_urb->urb, priv->udev, priv->pipe_out[queue],
skb->data, skb->len, rtl8xxxu_tx_complete, skb);
@ -5385,11 +5460,11 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw,
dev_kfree_skb(skb);
}
static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct rtl8723au_phy_stats *phy_stats,
u32 rxmcs, struct ieee80211_hdr *hdr,
bool crc_icv_err)
void rtl8723au_rx_parse_phystats(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct rtl8723au_phy_stats *phy_stats,
u32 rxmcs, struct ieee80211_hdr *hdr,
bool crc_icv_err)
{
if (phy_stats->sgi_en)
rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
@ -5398,9 +5473,7 @@ static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv,
/*
* Handle PHY stats for CCK rates
*/
u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
rx_status->signal = priv->fops->cck_rssi(priv, cck_agc_rpt);
rx_status->signal = priv->fops->cck_rssi(priv, phy_stats);
} else {
bool parse_cfo = priv->fops->set_crystal_cap &&
priv->vif &&
@ -5422,6 +5495,96 @@ static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv,
}
}
static void jaguar2_rx_parse_phystats_type0(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct jaguar2_phy_stats_type0 *phy_stats0,
u32 rxmcs, struct ieee80211_hdr *hdr,
bool crc_icv_err)
{
s8 rx_power = phy_stats0->pwdb - 110;
if (!priv->cck_new_agc)
rx_power = priv->fops->cck_rssi(priv, (struct rtl8723au_phy_stats *)phy_stats0);
rx_status->signal = rx_power;
}
static void jaguar2_rx_parse_phystats_type1(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct jaguar2_phy_stats_type1 *phy_stats1,
u32 rxmcs, struct ieee80211_hdr *hdr,
bool crc_icv_err)
{
bool parse_cfo = priv->fops->set_crystal_cap &&
priv->vif &&
priv->vif->type == NL80211_IFTYPE_STATION &&
priv->vif->cfg.assoc &&
!crc_icv_err &&
!ieee80211_is_ctl(hdr->frame_control) &&
ether_addr_equal(priv->vif->bss_conf.bssid, hdr->addr2);
u8 pwdb_max = 0;
int rx_path;
if (parse_cfo) {
/* Only path-A and path-B have CFO tail and short CFO */
priv->cfo_tracking.cfo_tail[RF_A] = phy_stats1->cfo_tail[RF_A];
priv->cfo_tracking.cfo_tail[RF_B] = phy_stats1->cfo_tail[RF_B];
priv->cfo_tracking.packet_count++;
}
for (rx_path = 0; rx_path < priv->rx_paths; rx_path++)
pwdb_max = max(pwdb_max, phy_stats1->pwdb[rx_path]);
rx_status->signal = pwdb_max - 110;
}
static void jaguar2_rx_parse_phystats_type2(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct jaguar2_phy_stats_type2 *phy_stats2,
u32 rxmcs, struct ieee80211_hdr *hdr,
bool crc_icv_err)
{
u8 pwdb_max = 0;
int rx_path;
for (rx_path = 0; rx_path < priv->rx_paths; rx_path++)
pwdb_max = max(pwdb_max, phy_stats2->pwdb[rx_path]);
rx_status->signal = pwdb_max - 110;
}
void jaguar2_rx_parse_phystats(struct rtl8xxxu_priv *priv,
struct ieee80211_rx_status *rx_status,
struct rtl8723au_phy_stats *phy_stats,
u32 rxmcs, struct ieee80211_hdr *hdr,
bool crc_icv_err)
{
struct jaguar2_phy_stats_type0 *phy_stats0 = (struct jaguar2_phy_stats_type0 *)phy_stats;
struct jaguar2_phy_stats_type1 *phy_stats1 = (struct jaguar2_phy_stats_type1 *)phy_stats;
struct jaguar2_phy_stats_type2 *phy_stats2 = (struct jaguar2_phy_stats_type2 *)phy_stats;
switch (phy_stats0->page_num) {
case 0:
/* CCK */
jaguar2_rx_parse_phystats_type0(priv, rx_status, phy_stats0,
rxmcs, hdr, crc_icv_err);
break;
case 1:
/* OFDM */
jaguar2_rx_parse_phystats_type1(priv, rx_status, phy_stats1,
rxmcs, hdr, crc_icv_err);
break;
case 2:
/* Also OFDM but different (how?) */
jaguar2_rx_parse_phystats_type2(priv, rx_status, phy_stats2,
rxmcs, hdr, crc_icv_err);
break;
default:
return;
}
}
static void rtl8xxxu_free_rx_resources(struct rtl8xxxu_priv *priv)
{
struct rtl8xxxu_rx_urb *rx_urb, *tmp;
@ -5920,7 +6083,7 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
skb_trim(skb, pkt_len);
if (rx_desc->phy_stats)
rtl8xxxu_rx_parse_phystats(
priv->fops->parse_phystats(
priv, rx_status, phy_stats,
rx_desc->rxmcs,
(struct ieee80211_hdr *)skb->data,
@ -5995,7 +6158,7 @@ int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
}
if (rx_desc->phy_stats)
rtl8xxxu_rx_parse_phystats(priv, rx_status, phy_stats,
priv->fops->parse_phystats(priv, rx_status, phy_stats,
rx_desc->rxmcs, (struct ieee80211_hdr *)skb->data,
rx_desc->crc32 || rx_desc->icverr);
@ -7007,6 +7170,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
case 0x818b:
case 0xf179:
case 0x8179:
case 0xb711:
untested = 0;
break;
}
@ -7055,6 +7219,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
priv->udev = udev;
priv->fops = (struct rtl8xxxu_fileops *)id->driver_info;
mutex_init(&priv->usb_buf_mutex);
mutex_init(&priv->syson_indirect_access_mutex);
mutex_init(&priv->h2c_mutex);
INIT_LIST_HEAD(&priv->tx_urb_free_list);
spin_lock_init(&priv->tx_urb_lock);
@ -7084,7 +7249,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
else
INIT_WORK(&priv->c2hcmd_work, rtl8xxxu_c2hcmd_callback);
ret = rtl8xxxu_read_efuse(priv);
ret = priv->fops->read_efuse(priv);
if (ret) {
dev_err(&udev->dev, "Fatal - failed to read EFuse\n");
goto err_set_intfdata;
@ -7174,6 +7339,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
kfree(priv->fw_data);
mutex_destroy(&priv->usb_buf_mutex);
mutex_destroy(&priv->syson_indirect_access_mutex);
mutex_destroy(&priv->h2c_mutex);
ieee80211_free_hw(hw);
@ -7203,6 +7369,7 @@ static void rtl8xxxu_disconnect(struct usb_interface *interface)
kfree(priv->fw_data);
mutex_destroy(&priv->usb_buf_mutex);
mutex_destroy(&priv->syson_indirect_access_mutex);
mutex_destroy(&priv->h2c_mutex);
if (priv->udev->state != USB_STATE_NOTATTACHED) {
@ -7283,6 +7450,12 @@ static const struct usb_device_id dev_table[] = {
/* Rosewill USB-N150 Nano */
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xffef, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8188eu_fops},
/* RTL8710BU aka RTL8188GU (not to be confused with RTL8188GTVU) */
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xb711, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8710bu_fops},
/* TOTOLINK N150UA V5 / N150UA-B */
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2005, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8710bu_fops},
#ifdef CONFIG_RTL8XXXU_UNTESTED
/* Still supported by rtlwifi */
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff),

View file

@ -490,6 +490,8 @@
#define RXDMA_PRO_DMA_BURST_CNT GENMASK(3, 2) /* Set to 0x3. */
#define RXDMA_PRO_DMA_BURST_SIZE GENMASK(5, 4) /* Set to 0x1. */
#define REG_EARLY_MODE_CONTROL_8710B 0x02bc
#define REG_RF_BB_CMD_ADDR 0x02c0
#define REG_RF_BB_CMD_DATA 0x02c4
@ -845,6 +847,7 @@
#define REG_BT_CONTROL_8723BU 0x0764
#define BT_CONTROL_BT_GRANT BIT(12)
#define REG_PORT_CONTROL_8710B 0x076d
#define REG_WLAN_ACT_CONTROL_8723B 0x076e
#define REG_FPGA0_RF_MODE 0x0800
@ -1004,8 +1007,12 @@
#define CCK_PD_TYPE1_LV3_TH 0xdd
#define CCK_PD_TYPE1_LV4_TH 0xed
#define REG_CCK0_TX_FILTER1 0x0a20
#define REG_CCK0_TX_FILTER2 0x0a24
#define REG_CCK0_DEBUG_PORT 0x0a28 /* debug port and Tx filter3 */
#define REG_AGC_RPT 0xa80
#define AGC_RPT_CCK BIT(7)
#define REG_CCK0_TX_FILTER3 0x0aac
#define REG_CONFIG_ANT_A 0x0b68
#define REG_CONFIG_ANT_B 0x0b6c
@ -1179,6 +1186,8 @@
Unavailable */
#define USB_HIMR_ROK BIT(0) /* Receive DMA OK Interrupt */
#define REG_USB_ACCESS_TIMEOUT 0xfe4c
#define REG_USB_SPECIAL_OPTION 0xfe55
#define USB_SPEC_USB_AGG_ENABLE BIT(3) /* Enable USB aggregation */
#define USB_SPEC_INT_BULK_SELECT BIT(4) /* Use interrupt endpoint to
@ -1204,6 +1213,41 @@
#define REG_NORMAL_SIE_MAC_ADDR 0xfe70 /* 0xfe70 - 0xfe75 */
#define REG_NORMAL_SIE_STRING 0xfe80 /* 0xfe80 - 0xfedf */
/*
* 8710B register addresses between 0x00 and 0xff must have 0x8000
* added to them. We take care of that in the rtl8xxxu_read{8,16,32}
* and rtl8xxxu_write{8,16,32} functions.
*/
#define REG_SYS_FUNC_8710B 0x0004
#define REG_AFE_CTRL_8710B 0x0050
#define REG_WL_RF_PSS_8710B 0x005c
#define REG_EFUSE_INDIRECT_CTRL_8710B 0x006c
#define NORMAL_REG_READ_OFFSET 0x83000000
#define NORMAL_REG_WRITE_OFFSET 0x84000000
#define EFUSE_READ_OFFSET 0x85000000
#define EFUSE_WRITE_OFFSET 0x86000000
#define REG_HIMR0_8710B 0x0080
#define REG_HISR0_8710B 0x0084
/*
* 8710B uses this instead of REG_MCU_FW_DL, but at least bits
* 0-7 have the same meaning.
*/
#define REG_8051FW_CTRL_V1_8710B 0x0090
#define REG_USB_HOST_INDIRECT_DATA_8710B 0x009c
#define REG_WL_STATUS_8710B 0x00f0
#define REG_USB_HOST_INDIRECT_ADDR_8710B 0x00f8
/*
* 8710B registers which must be accessed through rtl8710b_read_syson_reg
* and rtl8710b_write_syson_reg.
*/
#define SYSON_REG_BASE_ADDR_8710B 0x40000000
#define REG_SYS_XTAL_CTRL0_8710B 0x060
#define REG_SYS_EEPROM_CTRL0_8710B 0x0e0
#define REG_SYS_SYSTEM_CFG0_8710B 0x1f0
#define REG_SYS_SYSTEM_CFG1_8710B 0x1f4
#define REG_SYS_SYSTEM_CFG2_8710B 0x1f8
/* RF6052 registers */
#define RF6052_REG_AC 0x00
#define RF6052_REG_IQADJ_G1 0x01