diff options
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/rtw8922a.c')
| -rw-r--r-- | drivers/net/wireless/realtek/rtw89/rtw8922a.c | 204 |
1 files changed, 192 insertions, 12 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 9a4db04a1967..4437279c554b 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -12,9 +12,10 @@ #include "reg.h" #include "rtw8922a.h" #include "rtw8922a_rfk.h" +#include "sar.h" #include "util.h" -#define RTW8922A_FW_FORMAT_MAX 2 +#define RTW8922A_FW_FORMAT_MAX 4 #define RTW8922A_FW_BASENAME "rtw89/rtw8922a_fw" #define RTW8922A_MODULE_FIRMWARE \ RTW8922A_FW_BASENAME "-" __stringify(RTW8922A_FW_FORMAT_MAX) ".bin" @@ -205,10 +206,17 @@ static const struct rtw89_edcca_regs rtw8922a_edcca_regs = { .edcca_p_mask = B_EDCCA_LVL_MSK1, .ppdu_level = R_SEG0R_PPDU_LVL_BE, .ppdu_mask = B_EDCCA_LVL_MSK1, - .rpt_a = R_EDCCA_RPT_A_BE, - .rpt_b = R_EDCCA_RPT_B_BE, - .rpt_sel = R_EDCCA_RPT_SEL_BE, - .rpt_sel_mask = B_EDCCA_RPT_SEL_MSK, + .p = {{ + .rpt_a = R_EDCCA_RPT_A_BE, + .rpt_b = R_EDCCA_RPT_B_BE, + .rpt_sel = R_EDCCA_RPT_SEL_BE, + .rpt_sel_mask = B_EDCCA_RPT_SEL_MSK, + }, { + .rpt_a = R_EDCCA_RPT_P1_A_BE, + .rpt_b = R_EDCCA_RPT_P1_B_BE, + .rpt_sel = R_EDCCA_RPT_SEL_BE, + .rpt_sel_mask = B_EDCCA_RPT_SEL_P1_MSK, + }}, .rpt_sel_be = R_EDCCA_RPTREG_SEL_BE, .rpt_sel_be_mask = B_EDCCA_RPTREG_SEL_BE_MSK, .tx_collision_t2r_st = R_TX_COLLISION_T2R_ST_BE, @@ -2063,7 +2071,8 @@ static void __rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev, rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, phy_idx, 5); rtw89_phy_rfk_dack_and_wait(rtwdev, phy_idx, chan, 58); - rtw89_phy_rfk_rxdck_and_wait(rtwdev, phy_idx, chan, false, 32); + if (!test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) + rtw89_phy_rfk_rxdck_and_wait(rtwdev, phy_idx, chan, false, 128); } static void rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev) @@ -2149,6 +2158,56 @@ static void rtw8922a_set_txpwr_ref(struct rtw89_dev *rtwdev, B_BE_PWR_REF_CTRL_CCK, ref_cck); } +static const struct rtw89_reg_def rtw8922a_txpwr_ref[][3] = { + {{ .addr = R_TXAGC_REF_DBM_P0, .mask = B_TXAGC_OFDM_REF_DBM_P0}, + { .addr = R_TXAGC_REF_DBM_P0, .mask = B_TXAGC_CCK_REF_DBM_P0}, + { .addr = R_TSSI_K_P0, .mask = B_TSSI_K_OFDM_P0} + }, + {{ .addr = R_TXAGC_REF_DBM_RF1_P0, .mask = B_TXAGC_OFDM_REF_DBM_RF1_P0}, + { .addr = R_TXAGC_REF_DBM_RF1_P0, .mask = B_TXAGC_CCK_REF_DBM_RF1_P0}, + { .addr = R_TSSI_K_RF1_P0, .mask = B_TSSI_K_OFDM_RF1_P0} + }, +}; + +static void rtw8922a_set_txpwr_diff(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + s16 pwr_ofst = rtw89_phy_ant_gain_pwr_offset(rtwdev, chan); + const struct rtw89_chip_info *chip = rtwdev->chip; + static const u32 path_ofst[] = {0x0, 0x100}; + const struct rtw89_reg_def *txpwr_ref; + static const s16 tssi_k_base = 0x12; + s16 tssi_k_ofst = abs(pwr_ofst) + tssi_k_base; + s16 ofst_dec[RF_PATH_NUM_8922A]; + s16 tssi_k[RF_PATH_NUM_8922A]; + s16 pwr_ref_ofst; + s16 pwr_ref = 0; + u8 i; + + if (rtwdev->hal.cv == CHIP_CAV) + pwr_ref = 16; + + pwr_ref <<= chip->txpwr_factor_rf; + pwr_ref_ofst = pwr_ref - rtw89_phy_txpwr_bb_to_rf(rtwdev, abs(pwr_ofst)); + + ofst_dec[RF_PATH_A] = pwr_ofst > 0 ? pwr_ref : pwr_ref_ofst; + ofst_dec[RF_PATH_B] = pwr_ofst > 0 ? pwr_ref_ofst : pwr_ref; + tssi_k[RF_PATH_A] = pwr_ofst > 0 ? tssi_k_base : tssi_k_ofst; + tssi_k[RF_PATH_B] = pwr_ofst > 0 ? tssi_k_ofst : tssi_k_base; + + for (i = 0; i < RF_PATH_NUM_8922A; i++) { + txpwr_ref = rtw8922a_txpwr_ref[phy_idx]; + + rtw89_phy_write32_mask(rtwdev, txpwr_ref[0].addr + path_ofst[i], + txpwr_ref[0].mask, ofst_dec[i]); + rtw89_phy_write32_mask(rtwdev, txpwr_ref[1].addr + path_ofst[i], + txpwr_ref[1].mask, ofst_dec[i]); + rtw89_phy_write32_mask(rtwdev, txpwr_ref[2].addr + path_ofst[i], + txpwr_ref[2].mask, tssi_k[i]); + } +} + static void rtw8922a_bb_tx_triangular(struct rtw89_dev *rtwdev, bool en, enum rtw89_phy_idx phy_idx) { @@ -2176,6 +2235,31 @@ static void rtw8922a_set_tx_shape(struct rtw89_dev *rtwdev, rtw8922a_bb_tx_triangular(rtwdev, true, phy_idx); } +static void rtw8922a_set_txpwr_sar_diff(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + struct rtw89_sar_parm sar_parm = { + .center_freq = chan->freq, + .force_path = true, + }; + s16 sar_rf; + s8 sar_mac; + + if (phy_idx != RTW89_PHY_0) + return; + + sar_parm.path = RF_PATH_A; + sar_mac = rtw89_query_sar(rtwdev, &sar_parm); + sar_rf = rtw89_phy_txpwr_mac_to_rf(rtwdev, sar_mac); + rtw89_phy_write32_mask(rtwdev, R_P0_TXPWRB_BE, B_TXPWRB_MAX_BE, sar_rf); + + sar_parm.path = RF_PATH_B; + sar_mac = rtw89_query_sar(rtwdev, &sar_parm); + sar_rf = rtw89_phy_txpwr_mac_to_rf(rtwdev, sar_mac); + rtw89_phy_write32_mask(rtwdev, R_P1_TXPWRB_BE, B_TXPWRB_MAX_BE, sar_rf); +} + static void rtw8922a_set_txpwr(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx) @@ -2185,6 +2269,9 @@ static void rtw8922a_set_txpwr(struct rtw89_dev *rtwdev, rtw8922a_set_tx_shape(rtwdev, chan, phy_idx); rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx); rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx); + rtw8922a_set_txpwr_diff(rtwdev, chan, phy_idx); + rtw8922a_set_txpwr_ref(rtwdev, phy_idx); + rtw8922a_set_txpwr_sar_diff(rtwdev, chan, phy_idx); } static void rtw8922a_set_txpwr_ctrl(struct rtw89_dev *rtwdev, @@ -2260,19 +2347,29 @@ static void rtw8922a_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) enum rtw89_band band = chan->band_type; struct rtw89_hal *hal = &rtwdev->hal; u8 ntx_path = RF_PATH_AB; + u8 nrx_path = RF_PATH_AB; u32 tx_en0, tx_en1; + u8 rx_nss = 2; if (hal->antenna_tx == RF_A) ntx_path = RF_PATH_A; else if (hal->antenna_tx == RF_B) ntx_path = RF_PATH_B; + if (hal->antenna_rx == RF_A) + nrx_path = RF_PATH_A; + else if (hal->antenna_rx == RF_B) + nrx_path = RF_PATH_B; + + if (nrx_path != RF_PATH_AB) + rx_nss = 1; + rtw8922a_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, true); if (rtwdev->dbcc_en) rtw8922a_hal_reset(rtwdev, RTW89_PHY_1, RTW89_MAC_1, band, &tx_en1, true); - rtw8922a_ctrl_trx_path(rtwdev, ntx_path, 2, RF_PATH_AB, 2); + rtw8922a_ctrl_trx_path(rtwdev, ntx_path, 2, nrx_path, rx_nss); rtw8922a_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, false); if (rtwdev->dbcc_en) @@ -2303,6 +2400,48 @@ static u8 rtw8922a_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_p return clamp_t(int, th, 0, U8_MAX); } +static u32 rtw8922a_chan_to_rf18_val(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + u32 val = u32_encode_bits(chan->channel, RR_CFGCH_CH); + + switch (chan->band_type) { + case RTW89_BAND_2G: + default: + break; + case RTW89_BAND_5G: + val |= u32_encode_bits(CFGCH_BAND1_5G, RR_CFGCH_BAND1) | + u32_encode_bits(CFGCH_BAND0_5G, RR_CFGCH_BAND0); + break; + case RTW89_BAND_6G: + val |= u32_encode_bits(CFGCH_BAND1_6G, RR_CFGCH_BAND1) | + u32_encode_bits(CFGCH_BAND0_6G, RR_CFGCH_BAND0); + break; + } + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_5: + case RTW89_CHANNEL_WIDTH_10: + case RTW89_CHANNEL_WIDTH_20: + default: + break; + case RTW89_CHANNEL_WIDTH_40: + val |= u32_encode_bits(CFGCH_BW_V2_40M, RR_CFGCH_BW_V2); + break; + case RTW89_CHANNEL_WIDTH_80: + val |= u32_encode_bits(CFGCH_BW_V2_80M, RR_CFGCH_BW_V2); + break; + case RTW89_CHANNEL_WIDTH_160: + val |= u32_encode_bits(CFGCH_BW_V2_160M, RR_CFGCH_BW_V2); + break; + case RTW89_CHANNEL_WIDTH_320: + val |= u32_encode_bits(CFGCH_BW_V2_320M, RR_CFGCH_BW_V2); + break; + } + + return val; +} + static void rtw8922a_btc_set_rfe(struct rtw89_dev *rtwdev) { union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo; @@ -2565,8 +2704,10 @@ static void rtw8922a_query_ppdu(struct rtw89_dev *rtwdev, u8 path; u8 *rx_power = phy_ppdu->rssi; - status->signal = - RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], rx_power[RF_PATH_B])); + if (!status->signal) + status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], + rx_power[RF_PATH_B])); + for (path = 0; path < rtwdev->chip->rf_path_num; path++) { status->chains |= BIT(path); status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]); @@ -2607,6 +2748,16 @@ static void rtw8922a_convert_rpl_to_rssi(struct rtw89_dev *rtwdev, phy_ppdu->rssi_avg = phy_ppdu->rpl_avg; } +static void rtw8922a_phy_rpt_to_rssi(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + struct ieee80211_rx_status *rx_status) +{ + if (desc_info->rssi <= 0x1 || (desc_info->rssi >> 2) > MAX_RSSI) + return; + + rx_status->signal = (desc_info->rssi >> 2) - MAX_RSSI; +} + static int rtw8922a_mac_enable_bb_rf(struct rtw89_dev *rtwdev) { rtw89_write8_set(rtwdev, R_BE_FEN_RST_ENABLE, @@ -2624,6 +2775,10 @@ static int rtw8922a_mac_disable_bb_rf(struct rtw89_dev *rtwdev) return 0; } +static const struct rtw89_chanctx_listener rtw8922a_chanctx_listener = { + .callbacks[RTW89_CHANCTX_CALLBACK_TAS] = rtw89_tas_chanctx_cb, +}; + #ifdef CONFIG_PM static const struct wiphy_wowlan_support rtw_wowlan_stub_8922a = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | @@ -2662,9 +2817,11 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = { .set_txpwr_ctrl = rtw8922a_set_txpwr_ctrl, .init_txpwr_unit = NULL, .get_thermal = rtw8922a_get_thermal, + .chan_to_rf18_val = rtw8922a_chan_to_rf18_val, .ctrl_btg_bt_rx = rtw8922a_ctrl_btg_bt_rx, .query_ppdu = rtw8922a_query_ppdu, .convert_rpl_to_rssi = rtw8922a_convert_rpl_to_rssi, + .phy_rpt_to_rssi = rtw8922a_phy_rpt_to_rssi, .ctrl_nbtg_bt_tx = rtw8922a_ctrl_nbtg_bt_tx, .cfg_txrx_path = rtw8922a_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = NULL, @@ -2674,6 +2831,9 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = { .query_rxdesc = rtw89_core_query_rxdesc_v2, .fill_txdesc = rtw89_core_fill_txdesc_v2, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v2, + .get_ch_dma = {rtw89_core_get_ch_dma, + rtw89_core_get_ch_dma_v2, + NULL,}, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v2, .mac_cfg_gnt = rtw89_mac_cfg_gnt_v2, .stop_sch_tx = rtw89_mac_stop_sch_tx_v2, @@ -2682,6 +2842,8 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = { .h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl_g7, .h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl_g7, .h2c_ampdu_cmac_tbl = rtw89_fw_h2c_ampdu_cmac_tbl_g7, + .h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl_g7, + .h2c_punctured_cmac_tbl = rtw89_fw_h2c_punctured_cmac_tbl_g7, .h2c_default_dmac_tbl = rtw89_fw_h2c_default_dmac_tbl_v2, .h2c_update_beacon = rtw89_fw_h2c_update_beacon_be, .h2c_ba_cam = rtw89_fw_h2c_ba_cam_v1, @@ -2708,14 +2870,15 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .try_ce_fw = false, .bbmcu_nr = 1, .needed_fw_elms = RTW89_BE_GEN_DEF_NEEDED_FW_ELEMENTS, + .fw_blacklist = &rtw89_fw_blacklist_default, .fifo_size = 589824, .small_fifo_size = false, .dle_scc_rsvd_size = 0, .max_amsdu_limit = 8000, .dis_2g_40m_ul_ofdma = false, .rsvd_ple_ofst = 0x8f800, - .hfc_param_ini = rtw8922a_hfc_param_ini_pcie, - .dle_mem = rtw8922a_dle_mem_pcie, + .hfc_param_ini = {rtw8922a_hfc_param_ini_pcie, NULL, NULL}, + .dle_mem = {rtw8922a_dle_mem_pcie, NULL, NULL, NULL}, .wde_qempty_acq_grpnum = 4, .wde_qempty_mgq_grpsel = 4, .rf_base_addr = {0xe000, 0xf000}, @@ -2729,6 +2892,8 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .nctl_post_table = NULL, .dflt_parms = NULL, /* load parm from fw */ .rfe_parms_conf = NULL, /* load parm from fw */ + .chanctx_listener = &rtw8922a_chanctx_listener, + .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, .dig_table = NULL, @@ -2746,10 +2911,17 @@ const struct rtw89_chip_info rtw8922a_chip_info = { BIT(NL80211_CHAN_WIDTH_80) | BIT(NL80211_CHAN_WIDTH_160), .support_unii4 = true, + .support_ant_gain = true, + .support_tas = true, + .support_sar_by_ant = true, + .support_noise = false, .ul_tb_waveform_ctrl = false, .ul_tb_pwr_diff = false, + .rx_freq_frome_ie = false, .hw_sec_hdr = true, .hw_mgmt_tx_encrypt = true, + .hw_tkip_crypto = true, + .hw_mlo_bmc_crypto = false, .rf_path_num = 2, .tx_nss = 2, .rx_nss = 2, @@ -2759,6 +2931,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .bacam_num = 24, .bacam_dynamic_num = 8, .bacam_ver = RTW89_BACAM_V1, + .addrcam_ver = 0, .ppdu_max_usr = 16, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 0x1300, @@ -2771,7 +2944,6 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .phycap_size = 0x38, .para_ver = 0xf, .wlcx_desired = 0x07110000, - .btcx_desired = 0x7, .scbd = 0x1, .mailbox = 0x1, @@ -2806,6 +2978,8 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .cfo_hw_comp = true, .dcfo_comp = NULL, .dcfo_comp_sft = 0, + .nhm_report = NULL, + .nhm_th = NULL, .imr_info = NULL, .imr_dmac_table = &rtw8922a_imr_dmac_table, .imr_cmac_table = &rtw8922a_imr_cmac_table, @@ -2823,6 +2997,12 @@ const struct rtw89_chip_info rtw8922a_chip_info = { }; EXPORT_SYMBOL(rtw8922a_chip_info); +const struct rtw89_chip_variant rtw8922ae_vs_variant = { + .no_mcs_12_13 = true, + .fw_min_ver_code = RTW89_FW_VER_CODE(0, 35, 54, 0), +}; +EXPORT_SYMBOL(rtw8922ae_vs_variant); + MODULE_FIRMWARE(RTW8922A_MODULE_FIRMWARE); MODULE_AUTHOR("Realtek Corporation"); MODULE_DESCRIPTION("Realtek 802.11be wireless 8922A driver"); |
