diff options
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/rtw8852c.c')
| -rw-r--r-- | drivers/net/wireless/realtek/rtw89/rtw8852c.c | 717 |
1 files changed, 498 insertions, 219 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index a87482cc25f5..db99450e9158 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2,6 +2,7 @@ /* Copyright(c) 2019-2022 Realtek Corporation */ +#include "chan.h" #include "coex.h" #include "debug.h" #include "fw.h" @@ -11,8 +12,14 @@ #include "rtw8852c.h" #include "rtw8852c_rfk.h" #include "rtw8852c_table.h" +#include "sar.h" #include "util.h" +#define RTW8852C_FW_FORMAT_MAX 2 +#define RTW8852C_FW_BASENAME "rtw89/rtw8852c_fw" +#define RTW8852C_MODULE_FIRMWARE \ + RTW8852C_FW_BASENAME "-" __stringify(RTW8852C_FW_FORMAT_MAX) ".bin" + static const struct rtw89_hfc_ch_cfg rtw8852c_hfc_chcfg_pcie[] = { {13, 1614, grp_0}, /* ACH 0 */ {13, 1614, grp_0}, /* ACH 1 */ @@ -44,6 +51,48 @@ static const struct rtw89_hfc_param_ini rtw8852c_hfc_param_ini_pcie[] = { [RTW89_QTA_INVALID] = {NULL}, }; +static const struct rtw89_hfc_ch_cfg rtw8852c_hfc_chcfg_usb[] = { + {18, 344, grp_0}, /* ACH 0 */ + {0, 0, grp_0}, /* ACH 1 */ + {18, 344, grp_0}, /* ACH 2 */ + {0, 0, grp_0}, /* ACH 3 */ + {18, 344, grp_0}, /* ACH 4 */ + {0, 0, grp_0}, /* ACH 5 */ + {18, 344, grp_0}, /* ACH 6 */ + {0, 0, grp_0}, /* ACH 7 */ + {18, 344, grp_0}, /* B0MGQ */ + {0, 0, grp_0}, /* B0HIQ */ + {18, 344, grp_0}, /* B1MGQ */ + {0, 0, grp_0}, /* B1HIQ */ + {0, 0, 0} /* FWCMDQ */ +}; + +static const struct rtw89_hfc_pub_cfg rtw8852c_hfc_pubcfg_usb = { + 344, /* Group 0 */ + 0, /* Group 1 */ + 344, /* Public Max */ + 0 /* WP threshold */ +}; + +static const struct rtw89_hfc_prec_cfg rtw8852c_hfc_preccfg_usb = { + 9, /* CH 0-11 pre-cost */ + 32, /* H2C pre-cost */ + 146, /* WP CH 0-7 pre-cost */ + 146, /* WP CH 8-11 pre-cost */ + 1, /* CH 0-11 full condition */ + 1, /* H2C full condition */ + 1, /* WP CH 0-7 full condition */ + 1, /* WP CH 8-11 full condition */ +}; + +static const struct rtw89_hfc_param_ini rtw8852c_hfc_param_ini_usb[] = { + [RTW89_QTA_SCC] = {rtw8852c_hfc_chcfg_usb, &rtw8852c_hfc_pubcfg_usb, + &rtw8852c_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_DLFW] = {NULL, NULL, + &rtw8852c_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_INVALID] = {NULL}, +}; + static const struct rtw89_dle_mem rtw8852c_dle_mem_pcie[] = { [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size19, &rtw89_mac_size.ple_size19, &rtw89_mac_size.wde_qt18, @@ -57,6 +106,32 @@ static const struct rtw89_dle_mem rtw8852c_dle_mem_pcie[] = { NULL}, }; +static const struct rtw89_dle_mem rtw8852c_dle_mem_usb2[] = { + [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size31, + &rtw89_mac_size.ple_size34, &rtw89_mac_size.wde_qt31, + &rtw89_mac_size.wde_qt31, &rtw89_mac_size.ple_qt78, + &rtw89_mac_size.ple_qt79}, + [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size18, + &rtw89_mac_size.ple_size18, &rtw89_mac_size.wde_qt17, + &rtw89_mac_size.wde_qt17, &rtw89_mac_size.ple_qt44, + &rtw89_mac_size.ple_qt45}, + [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, + NULL}, +}; + +static const struct rtw89_dle_mem rtw8852c_dle_mem_usb3[] = { + [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size17, + &rtw89_mac_size.ple_size17, &rtw89_mac_size.wde_qt16, + &rtw89_mac_size.wde_qt16, &rtw89_mac_size.ple_qt42, + &rtw89_mac_size.ple_qt43}, + [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size18, + &rtw89_mac_size.ple_size18, &rtw89_mac_size.wde_qt17, + &rtw89_mac_size.wde_qt17, &rtw89_mac_size.ple_qt44, + &rtw89_mac_size.ple_qt45}, + [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, + NULL}, +}; + static const u32 rtw8852c_h2c_regs[RTW89_H2CREG_MAX] = { R_AX_H2CREG_DATA0_V1, R_AX_H2CREG_DATA1_V1, R_AX_H2CREG_DATA2_V1, R_AX_H2CREG_DATA3_V1 @@ -67,6 +142,10 @@ static const u32 rtw8852c_c2h_regs[RTW89_H2CREG_MAX] = { R_AX_C2HREG_DATA3_V1 }; +static const u32 rtw8852c_wow_wakeup_regs[RTW89_WOW_REASON_NUM] = { + R_AX_C2HREG_DATA3_V1 + 3, R_AX_DBG_WOW, +}; + static const struct rtw89_page_regs rtw8852c_page_regs = { .hci_fc_ctrl = R_AX_HCI_FC_CTRL_V1, .ch_page_ctrl = R_AX_CH_PAGE_CTRL_V1, @@ -137,10 +216,23 @@ static const struct rtw89_rrsr_cfgs rtw8852c_rrsr_cfgs = { .rsc = {R_AX_PTCL_RRSR1, B_AX_RSC_MASK, 2}, }; +static const struct rtw89_rfkill_regs rtw8852c_rfkill_regs = { + .pinmux = {R_AX_GPIO8_15_FUNC_SEL, + B_AX_PINMUX_GPIO9_FUNC_SEL_MASK, + 0xf}, + .mode = {R_AX_GPIO_EXT_CTRL + 2, + (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16, + 0x0}, +}; + static const struct rtw89_dig_regs rtw8852c_dig_regs = { .seg0_pd_reg = R_SEG0R_PD, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK, + .bmode_pd_reg = R_BMODE_PDTH_EN_V1, + .bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1, + .bmode_pd_lower_bound_reg = R_BMODE_PDTH_V1, + .bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1, .p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK}, .p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK}, .p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1}, @@ -157,17 +249,41 @@ static const struct rtw89_dig_regs rtw8852c_dig_regs = { B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK}, }; -static void rtw8852c_ctrl_btg(struct rtw89_dev *rtwdev, bool btg); +static const struct rtw89_edcca_regs rtw8852c_edcca_regs = { + .edcca_level = R_SEG0R_EDCCA_LVL, + .edcca_mask = B_EDCCA_LVL_MSK0, + .edcca_p_mask = B_EDCCA_LVL_MSK1, + .ppdu_level = R_SEG0R_EDCCA_LVL, + .ppdu_mask = B_EDCCA_LVL_MSK3, + .p = {{ + .rpt_a = R_EDCCA_RPT_A, + .rpt_b = R_EDCCA_RPT_B, + .rpt_sel = R_EDCCA_RPT_SEL, + .rpt_sel_mask = B_EDCCA_RPT_SEL_MSK, + }, { + .rpt_a = R_EDCCA_RPT_P1_A, + .rpt_b = R_EDCCA_RPT_P1_B, + .rpt_sel = R_EDCCA_RPT_SEL, + .rpt_sel_mask = B_EDCCA_RPT_SEL_P1_MSK, + }}, + .tx_collision_t2r_st = R_TX_COLLISION_T2R_ST, + .tx_collision_t2r_st_mask = B_TX_COLLISION_T2R_ST_M, +}; + +static void rtw8852c_ctrl_btg_bt_rx(struct rtw89_dev *rtwdev, bool en, + enum rtw89_phy_idx phy_idx); + static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path, enum rtw89_mac_idx mac_idx); static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev) { u32 val32; - u32 ret; + int ret; val32 = rtw89_read32_mask(rtwdev, R_AX_SYS_STATUS1, B_AX_PAD_HCI_SEL_V2_MASK); - if (val32 == MAC_AX_HCI_SEL_PCIE_USB) + if (val32 == MAC_AX_HCI_SEL_PCIE_USB || + rtwdev->hci.type == RTW89_HCI_TYPE_USB) rtw89_write32_set(rtwdev, R_AX_LDO_AON_CTRL0, B_AX_PD_REGU_L); rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_AFSM_WLSUS_EN | @@ -177,6 +293,9 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev) rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APDM_HPDN); rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0, + B_AX_OCP_L1_MASK, 0x7); + ret = read_poll_timeout(rtw89_read32, val32, val32 & B_AX_RDY_SYSPWR, 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL); if (ret) @@ -196,7 +315,9 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev) rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); - rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); + + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND, B_AX_CMAC1_FEN); rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND, B_AX_R_SYM_ISO_CMAC12PP); @@ -240,7 +361,7 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev) ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_SRAM2RFC); if (ret) return ret; - ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0, XTAL_SI_LDO_LPS); + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0x10, XTAL_SI_LDO_LPS); if (ret) return ret; ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_4, 0, XTAL_SI_LPS_CAP); @@ -255,9 +376,11 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev) rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14); rtw89_write32_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); - rtw89_write32_set(rtwdev, R_AX_GPIO0_15_EECS_EESK_LED1_PULL_LOW_EN, - B_AX_EECS_PULL_LOW_EN | B_AX_EESK_PULL_LOW_EN | - B_AX_LED1_PULL_LOW_EN); + + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32_set(rtwdev, R_AX_GPIO0_15_EECS_EESK_LED1_PULL_LOW_EN, + B_AX_EECS_PULL_LOW_EN | B_AX_EESK_PULL_LOW_EN | + B_AX_LED1_PULL_LOW_EN); rtw89_write32_set(rtwdev, R_AX_DMAC_FUNC_EN, B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_MPDU_PROC_EN | @@ -282,7 +405,7 @@ static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev) static int rtw8852c_pwr_off_func(struct rtw89_dev *rtwdev) { u32 val32; - u32 ret; + int ret; ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_RFC2RF, XTAL_SI_RFC2RF); @@ -312,6 +435,7 @@ static int rtw8852c_pwr_off_func(struct rtw89_dev *rtwdev) return ret; rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON); + rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, B_AX_FEN_BB_GLB_RSTN | B_AX_FEN_BBRSTB); rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND, B_AX_R_SYM_FEN_WLBBGLB_1 | B_AX_R_SYM_FEN_WLBBFUN_1); @@ -334,19 +458,26 @@ static int rtw8852c_pwr_off_func(struct rtw89_dev *rtwdev) if (ret) return ret; - rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, 0x0001A0B0); + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION); + else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_EDSWR); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_XTAL_OFF_A_DIE); - rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + rtw89_write32_set(rtwdev, R_AX_SYS_SWR_CTRL1, B_AX_SYM_CTRL_SPS_PWMFREQ); + rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0, + B_AX_REG_ZCDC_H_MASK, 0x3); - return 0; -} + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) { + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + } else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) { + val32 = rtw89_read32(rtwdev, R_AX_SYS_PW_CTRL); + val32 &= ~B_AX_AFSM_PCIE_SUS_EN; + val32 |= B_AX_AFSM_WLSUS_EN; + rtw89_write32(rtwdev, R_AX_SYS_PW_CTRL, val32); + } -static void rtw8852c_e_efuse_parsing(struct rtw89_efuse *efuse, - struct rtw8852c_efuse *map) -{ - ether_addr_copy(efuse->addr, map->e.mac_addr); - efuse->rfe_type = map->rfe_type; - efuse->xtal_cap = map->xtal_k; + return 0; } static void rtw8852c_efuse_parsing_tssi(struct rtw89_dev *rtwdev, @@ -414,11 +545,36 @@ static void rtw8852c_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev, valid |= _decode_efuse_gain(map->rx_gain_5g_high, &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_HIGH], &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_5G_HIGH]); + valid |= _decode_efuse_gain(map->rx_gain_6g_l0, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_L0], + &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_L0]); + valid |= _decode_efuse_gain(map->rx_gain_6g_l1, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_L1], + &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_L1]); + valid |= _decode_efuse_gain(map->rx_gain_6g_m0, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_M0], + &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_M0]); + valid |= _decode_efuse_gain(map->rx_gain_6g_m1, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_M1], + &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_M1]); + valid |= _decode_efuse_gain(map->rx_gain_6g_h0, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_H0], + &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_H0]); + valid |= _decode_efuse_gain(map->rx_gain_6g_h1, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_H1], + &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_H1]); + valid |= _decode_efuse_gain(map->rx_gain_6g_uh0, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_UH0], + &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_UH0]); + valid |= _decode_efuse_gain(map->rx_gain_6g_uh1, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_6G_UH1], + &gain->offset[RF_PATH_B][RTW89_GAIN_OFFSET_6G_UH1]); gain->offset_valid = valid; } -static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map) +static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, + enum rtw89_efuse_block block) { struct rtw89_efuse *efuse = &rtwdev->efuse; struct rtw8852c_efuse *map; @@ -432,12 +588,18 @@ static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map) switch (rtwdev->hci.type) { case RTW89_HCI_TYPE_PCIE: - rtw8852c_e_efuse_parsing(efuse, map); + ether_addr_copy(efuse->addr, map->e.mac_addr); + break; + case RTW89_HCI_TYPE_USB: + ether_addr_copy(efuse->addr, map->u.mac_addr); break; default: return -ENOTSUPP; } + efuse->rfe_type = map->rfe_type; + efuse->xtal_cap = map->xtal_k; + rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); return 0; @@ -508,12 +670,16 @@ static void rtw8852c_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev, } } +#define __THM_MASK_SIGN BIT(0) +#define __THM_MASK_3BITS GENMASK(3, 1) +#define __THM_MASK_VAL8 BIT(4) + static void rtw8852c_thermal_trim(struct rtw89_dev *rtwdev) { -#define __thm_setting(raw) \ -({ \ - u8 __v = (raw); \ - ((__v & 0x1) << 3) | ((__v & 0x1f) >> 1); \ +#define __thm_setting(raw) \ +({ \ + u8 __v = (raw); \ + ((__v & __THM_MASK_SIGN) << 3) | ((__v & __THM_MASK_3BITS) >> 1); \ }) struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; u8 i, val; @@ -601,10 +767,9 @@ static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, u8 mac_idx) { - u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx); - u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, - mac_idx); - u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx); + u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_AX_WMAC_RFMOD, mac_idx); + u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx); + u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXRATE_CHK, mac_idx); u8 txsc20 = 0, txsc40 = 0, txsc80 = 0; u8 rf_mod_val = 0, chk_rate_mask = 0; u32 txsc; @@ -792,7 +957,7 @@ static void rtw8852c_set_gain_error(struct rtw89_dev *rtwdev, enum rtw89_subband subband, enum rtw89_rf_path path) { - const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain; + const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain.ax; u8 gain_band = rtw89_subband_to_bb_gain_band(subband); s32 val; u32 reg; @@ -852,76 +1017,6 @@ static void rtw8852c_set_gain_error(struct rtw89_dev *rtwdev, } } -static -const u8 rtw8852c_ch_base_table[16] = {1, 0xff, - 36, 100, 132, 149, 0xff, - 1, 33, 65, 97, 129, 161, 193, 225, 0xff}; -#define RTW8852C_CH_BASE_IDX_2G 0 -#define RTW8852C_CH_BASE_IDX_5G_FIRST 2 -#define RTW8852C_CH_BASE_IDX_5G_LAST 5 -#define RTW8852C_CH_BASE_IDX_6G_FIRST 7 -#define RTW8852C_CH_BASE_IDX_6G_LAST 14 - -#define RTW8852C_CH_BASE_IDX_MASK GENMASK(7, 4) -#define RTW8852C_CH_OFFSET_MASK GENMASK(3, 0) - -static u8 rtw8852c_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band) -{ - u8 chan_idx; - u8 last, first; - u8 idx; - - switch (band) { - case RTW89_BAND_2G: - chan_idx = FIELD_PREP(RTW8852C_CH_BASE_IDX_MASK, RTW8852C_CH_BASE_IDX_2G) | - FIELD_PREP(RTW8852C_CH_OFFSET_MASK, central_ch); - return chan_idx; - case RTW89_BAND_5G: - first = RTW8852C_CH_BASE_IDX_5G_FIRST; - last = RTW8852C_CH_BASE_IDX_5G_LAST; - break; - case RTW89_BAND_6G: - first = RTW8852C_CH_BASE_IDX_6G_FIRST; - last = RTW8852C_CH_BASE_IDX_6G_LAST; - break; - default: - rtw89_warn(rtwdev, "Unsupported band %d\n", band); - return 0; - } - - for (idx = last; idx >= first; idx--) - if (central_ch >= rtw8852c_ch_base_table[idx]) - break; - - if (idx < first) { - rtw89_warn(rtwdev, "Unknown band %d channel %d\n", band, central_ch); - return 0; - } - - chan_idx = FIELD_PREP(RTW8852C_CH_BASE_IDX_MASK, idx) | - FIELD_PREP(RTW8852C_CH_OFFSET_MASK, - (central_ch - rtw8852c_ch_base_table[idx]) >> 1); - return chan_idx; -} - -static void rtw8852c_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx, - u8 *ch, enum nl80211_band *band) -{ - u8 idx, offset; - - idx = FIELD_GET(RTW8852C_CH_BASE_IDX_MASK, chan_idx); - offset = FIELD_GET(RTW8852C_CH_OFFSET_MASK, chan_idx); - - if (idx == RTW8852C_CH_BASE_IDX_2G) { - *band = NL80211_BAND_2GHZ; - *ch = offset; - return; - } - - *band = idx <= RTW8852C_CH_BASE_IDX_5G_LAST ? NL80211_BAND_5GHZ : NL80211_BAND_6GHZ; - *ch = rtw8852c_ch_base_table[idx] + (offset << 1); -} - static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx, @@ -1084,7 +1179,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev, } } - chan_idx = rtw8852c_encode_chan_idx(rtwdev, chan->primary_channel, band); + chan_idx = rtw89_encode_chan_idx(rtwdev, chan->primary_channel, band); rtw89_phy_write32_idx(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0, chan_idx, phy_idx); } @@ -1445,18 +1540,19 @@ static void rtw8852c_5m_mask(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx) { - u8 pri_ch = chan->primary_channel; + u8 pri_ch = chan->pri_ch_idx; bool mask_5m_low; bool mask_5m_en; switch (chan->band_width) { case RTW89_CHANNEL_WIDTH_40: mask_5m_en = true; - mask_5m_low = pri_ch == 2; + mask_5m_low = pri_ch == RTW89_SC_20_LOWER; break; case RTW89_CHANNEL_WIDTH_80: - mask_5m_en = ((pri_ch == 3) || (pri_ch == 4)); - mask_5m_low = pri_ch == 4; + mask_5m_en = pri_ch == RTW89_SC_20_UPMOST || + pri_ch == RTW89_SC_20_LOWEST; + mask_5m_low = pri_ch == RTW89_SC_20_LOWEST; break; default: mask_5m_en = false; @@ -1711,15 +1807,15 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev, } rtw8852c_spur_elimination(rtwdev, chan, pri_ch_idx, phy_idx); - rtw8852c_ctrl_btg(rtwdev, chan->band_type == RTW89_BAND_2G); + rtw8852c_ctrl_btg_bt_rx(rtwdev, chan->band_type == RTW89_BAND_2G, + RTW89_PHY_0); rtw8852c_5m_mask(rtwdev, chan, phy_idx); if (chan->band_width == RTW89_CHANNEL_WIDTH_160 && rtwdev->hal.cv != CHIP_CAV) { rtw89_phy_write32_idx(rtwdev, R_P80_AT_HIGH_FREQ, B_P80_AT_HIGH_FREQ, 0x0, phy_idx); - reg = rtw89_mac_reg_by_idx(R_P80_AT_HIGH_FREQ_BB_WRP, - phy_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_P80_AT_HIGH_FREQ_BB_WRP, phy_idx); if (chan->primary_channel > chan->channel) { rtw89_phy_write32_mask(rtwdev, R_P80_AT_HIGH_FREQ_RU_ALLOC, @@ -1816,7 +1912,7 @@ static void rtw8852c_set_channel_help(struct rtw89_dev *rtwdev, bool enter, RTW89_SCH_TX_SEL_ALL); rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, false); rtw8852c_dfs_en(rtwdev, false); - rtw8852c_tssi_cont_en_phyidx(rtwdev, false, phy_idx); + rtw8852c_tssi_cont_en_phyidx(rtwdev, false, phy_idx, chan); rtw8852c_adc_en(rtwdev, false); fsleep(40); rtw8852c_bb_reset_en(rtwdev, chan->band_type, phy_idx, false); @@ -1824,7 +1920,7 @@ static void rtw8852c_set_channel_help(struct rtw89_dev *rtwdev, bool enter, rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, true); rtw8852c_adc_en(rtwdev, true); rtw8852c_dfs_en(rtwdev, true); - rtw8852c_tssi_cont_en_phyidx(rtwdev, true, phy_idx); + rtw8852c_tssi_cont_en_phyidx(rtwdev, true, phy_idx, chan); rtw8852c_bb_reset_en(rtwdev, chan->band_type, phy_idx, true); rtw89_chip_resume_sch_tx(rtwdev, mac_idx, p->tx_en); } @@ -1838,33 +1934,45 @@ static void rtw8852c_rfk_init(struct rtw89_dev *rtwdev) rtwdev->is_tssi_mode[RF_PATH_B] = false; memset(rfk_mcc, 0, sizeof(*rfk_mcc)); rtw8852c_lck_init(rtwdev); + rtw8852c_dpk_init(rtwdev); rtw8852c_rck(rtwdev); - rtw8852c_dack(rtwdev); + rtw8852c_dack(rtwdev, RTW89_CHANCTX_0); rtw8852c_rx_dck(rtwdev, RTW89_PHY_0, false); } -static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev) +static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_phy_idx phy_idx = RTW89_PHY_0; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8852c_mcc_get_ch_info(rtwdev, phy_idx); + rtw89_btc_ntfy_conn_rfk(rtwdev, true); + rtw8852c_rx_dck(rtwdev, phy_idx, false); - rtw8852c_iqk(rtwdev, phy_idx); - rtw8852c_tssi(rtwdev, phy_idx); - rtw8852c_dpk(rtwdev, phy_idx); + rtw8852c_iqk(rtwdev, phy_idx, chanctx_idx); + rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852c_tssi(rtwdev, phy_idx, chanctx_idx); + rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30); + rtw8852c_dpk(rtwdev, phy_idx, chanctx_idx); + + rtw89_btc_ntfy_conn_rfk(rtwdev, false); rtw89_fw_h2c_rf_ntfy_mcc(rtwdev); } static void rtw8852c_rfk_band_changed(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx) + enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan) { - rtw8852c_tssi_scan(rtwdev, phy_idx); + rtw8852c_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, bool start) +static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + bool start) { - rtw8852c_wifi_scan_notify(rtwdev, start, RTW89_PHY_0); + rtw8852c_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx); } static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev) @@ -1875,9 +1983,9 @@ static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev) } static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx, s16 ref) + enum rtw89_phy_idx phy_idx, + s16 ref, u16 pwr_ofst_decrease) { - s8 ofst_int = 0; u8 base_cw_0db = 0x27; u16 tssi_16dbm_cw = 0x12c; s16 pwr_s10_3 = 0; @@ -1886,13 +1994,14 @@ static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, u32 pwr_cw = 0; u32 tssi_ofst_cw = 0; - pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3); + pwr_s10_3 = (ref << 1) + (s16)(base_cw_0db << 3) - pwr_ofst_decrease; bb_pwr_cw = FIELD_GET(GENMASK(2, 0), pwr_s10_3); rf_pwr_cw = FIELD_GET(GENMASK(8, 3), pwr_s10_3); rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63); pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw; - tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)); + tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)) - + pwr_ofst_decrease; rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n", tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw); @@ -1923,12 +2032,12 @@ void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, for (i = 0; i < 4; i++) { /* 1TX */ - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_V1_MASK << (8 * i), val_1t); /* 2TX */ - reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_V1_MASK << (8 * i), val_2t); @@ -1936,9 +2045,10 @@ void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, } static void rtw8852c_set_txpwr_ref(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx) + enum rtw89_phy_idx phy_idx, s16 pwr_ofst) { static const u32 addr[RF_PATH_NUM_8852C] = {0x5800, 0x7800}; + u16 ofst_dec[RF_PATH_NUM_8852C]; const u32 mask = 0x7FFFFFF; const u8 ofst_ofdm = 0x4; const u8 ofst_cck = 0x8; @@ -1952,22 +2062,24 @@ static void rtw8852c_set_txpwr_ref(struct rtw89_dev *rtwdev, rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL, GENMASK(27, 10), 0x0); - rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n"); - val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm); + ofst_dec[RF_PATH_A] = pwr_ofst > 0 ? 0 : abs(pwr_ofst); + ofst_dec[RF_PATH_B] = pwr_ofst > 0 ? pwr_ofst : 0; - for (i = 0; i < RF_PATH_NUM_8852C; i++) - rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, - phy_idx); + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n"); + for (i = 0; i < RF_PATH_NUM_8852C; i++) { + val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm, ofst_dec[i]); + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, phy_idx); + } rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n"); - val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck); - - for (i = 0; i < RF_PATH_NUM_8852C; i++) - rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, - phy_idx); + for (i = 0; i < RF_PATH_NUM_8852C; i++) { + val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck, ofst_dec[i]); + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, phy_idx); + } } static void rtw8852c_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, u8 tx_shape_idx, enum rtw89_phy_idx phy_idx) { @@ -1991,7 +2103,6 @@ static void rtw8852c_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev, __DECL_DFIR_ADDR(filter, 0x45BC, 0x45CC, 0x45D0, 0x45D4, 0x45D8, 0x45C0, 0x45C4, 0x45C8); - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); u8 ch = chan->channel; const u32 *param; int i; @@ -2026,17 +2137,58 @@ static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx) { + const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms; u8 band = chan->band_type; u8 regd = rtw89_regd_get(rtwdev, band); - u8 tx_shape_cck = rtw89_8852c_tx_shape[band][RTW89_RS_CCK][regd]; - u8 tx_shape_ofdm = rtw89_8852c_tx_shape[band][RTW89_RS_OFDM][regd]; + u8 tx_shape_cck = (*rfe_parms->tx_shape.lmt)[band][RTW89_RS_CCK][regd]; + u8 tx_shape_ofdm = (*rfe_parms->tx_shape.lmt)[band][RTW89_RS_OFDM][regd]; if (band == RTW89_BAND_2G) - rtw8852c_bb_set_tx_shape_dfir(rtwdev, tx_shape_cck, phy_idx); + rtw8852c_bb_set_tx_shape_dfir(rtwdev, chan, tx_shape_cck, phy_idx); rtw89_phy_tssi_ctrl_set_bandedge_cfg(rtwdev, (enum rtw89_mac_idx)phy_idx, tx_shape_ofdm); + + rtw89_phy_write32_set(rtwdev, R_P0_DAC_COMP_POST_DPD_EN, + B_P0_DAC_COMP_POST_DPD_EN); + rtw89_phy_write32_set(rtwdev, R_P1_DAC_COMP_POST_DPD_EN, + B_P1_DAC_COMP_POST_DPD_EN); +} + +static void rtw8852c_set_txpwr_diff(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + s16 pwr_ofst; + + pwr_ofst = rtw89_phy_ant_gain_pwr_offset(rtwdev, chan); + rtw8852c_set_txpwr_ref(rtwdev, phy_idx, pwr_ofst); +} + +static void rtw8852c_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_TXPWRB, B_TXPWRB_MAX, 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, B_TXPWRB_MAX, sar_rf); } static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev, @@ -2048,12 +2200,14 @@ static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev, rtw8852c_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); + rtw8852c_set_txpwr_diff(rtwdev, chan, phy_idx); + rtw8852c_set_txpwr_sar_diff(rtwdev, chan, phy_idx); } static void rtw8852c_set_txpwr_ctrl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { - rtw8852c_set_txpwr_ref(rtwdev, phy_idx); + rtw8852c_set_txpwr_ref(rtwdev, phy_idx, 0); } static void @@ -2109,7 +2263,7 @@ rtw8852c_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) static void rtw8852c_bb_cfg_rx_path(struct rtw89_dev *rtwdev, u8 rx_path) { - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); u8 band = chan->band_type; u32 rst_mask0 = B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI; u32 rst_mask1 = B_P1_TXPW_RSTB_MANON | B_P1_TXPW_RSTB_TSSI; @@ -2204,7 +2358,8 @@ static void rtw8852c_bb_cfg_rx_path(struct rtw89_dev *rtwdev, u8 rx_path) 1); rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 1); - rtw8852c_ctrl_btg(rtwdev, band == RTW89_BAND_2G); + rtw8852c_ctrl_btg_bt_rx(rtwdev, band == RTW89_BAND_2G, + RTW89_PHY_0); rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, rst_mask0, 1); rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, @@ -2245,7 +2400,7 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path, for (addr = R_AX_MACID_ANT_TABLE; addr <= R_AX_MACID_ANT_TABLE_LAST; addr += 4) { - reg = rtw89_mac_reg_by_idx(addr, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, addr, mac_idx); rtw89_write32(rtwdev, reg, 0); } @@ -2275,14 +2430,15 @@ static void rtw8852c_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev, u8 tx_path, for (i = 0; i < cr_size; i++) { rtw89_debug(rtwdev, RTW89_DBG_TSSI, "0x%x = 0x%x\n", path_com[i].addr, path_com[i].data); - reg = rtw89_mac_reg_by_idx(path_com[i].addr, mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, path_com[i].addr, mac_idx); rtw89_write32(rtwdev, reg, path_com[i].data); } } -static void rtw8852c_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en) +static void rtw8852c_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en, + enum rtw89_phy_idx phy_idx) { - if (bt_en) { + if (en) { rtw89_phy_write32_mask(rtwdev, R_PATH0_FRC_FIR_TYPE_V1, B_PATH0_FRC_FIR_TYPE_MSK_V1, 0x3); rtw89_phy_write32_mask(rtwdev, R_PATH1_FRC_FIR_TYPE_V1, @@ -2346,10 +2502,20 @@ static void rtw8852c_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en) static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; + u8 nrx_path = RF_PATH_AB; + u8 rx_nss = hal->rx_nss; + + if (hal->antenna_rx == RF_A) + nrx_path = RF_PATH_A; + else if (hal->antenna_rx == RF_B) + nrx_path = RF_PATH_B; - rtw8852c_bb_cfg_rx_path(rtwdev, RF_PATH_AB); + if (nrx_path != RF_PATH_AB) + rx_nss = 1; - if (hal->rx_nss == 1) { + rtw8852c_bb_cfg_rx_path(rtwdev, nrx_path); + + if (rx_nss == 1) { rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0); @@ -2364,45 +2530,86 @@ static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) static u8 rtw8852c_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path) { + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + s8 comp = 0; + u8 val; + rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x0); rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); fsleep(200); - return rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL); + val = rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL); + + if (info->pg_thermal_trim) { + u8 trim = info->thermal_trim[rf_path]; + + if (trim & __THM_MASK_VAL8) + comp = 8 * (trim & __THM_MASK_SIGN ? -1 : 1); + } + + return val + comp; } static void rtw8852c_btc_set_rfe(struct rtw89_dev *rtwdev) { - struct rtw89_btc *btc = &rtwdev->btc; - struct rtw89_btc_module *module = &btc->mdinfo; + const struct rtw89_btc_ver *ver = rtwdev->btc.ver; + union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo; - module->rfe_type = rtwdev->efuse.rfe_type; - module->cv = rtwdev->hal.cv; - module->bt_solo = 0; - module->switch_type = BTC_SWITCH_INTERNAL; + if (ver->fcxinit == 7) { + md->md_v7.rfe_type = rtwdev->efuse.rfe_type; + md->md_v7.kt_ver = rtwdev->hal.cv; + md->md_v7.bt_solo = 0; + md->md_v7.switch_type = BTC_SWITCH_INTERNAL; - if (module->rfe_type > 0) - module->ant.num = (module->rfe_type % 2 ? 2 : 3); - else - module->ant.num = 2; + if (md->md_v7.rfe_type > 0) + md->md_v7.ant.num = (md->md_v7.rfe_type % 2 ? 2 : 3); + else + md->md_v7.ant.num = 2; - module->ant.diversity = 0; - module->ant.isolation = 10; + md->md_v7.ant.diversity = 0; + md->md_v7.ant.isolation = 10; - if (module->ant.num == 3) { - module->ant.type = BTC_ANT_DEDICATED; - module->bt_pos = BTC_BT_ALONE; + if (md->md_v7.ant.num == 3) { + md->md_v7.ant.type = BTC_ANT_DEDICATED; + md->md_v7.bt_pos = BTC_BT_ALONE; + } else { + md->md_v7.ant.type = BTC_ANT_SHARED; + md->md_v7.bt_pos = BTC_BT_BTG; + } + rtwdev->btc.btg_pos = md->md_v7.ant.btg_pos; + rtwdev->btc.ant_type = md->md_v7.ant.type; } else { - module->ant.type = BTC_ANT_SHARED; - module->bt_pos = BTC_BT_BTG; + md->md.rfe_type = rtwdev->efuse.rfe_type; + md->md.cv = rtwdev->hal.cv; + md->md.bt_solo = 0; + md->md.switch_type = BTC_SWITCH_INTERNAL; + + if (md->md.rfe_type > 0) + md->md.ant.num = (md->md.rfe_type % 2 ? 2 : 3); + else + md->md.ant.num = 2; + + md->md.ant.diversity = 0; + md->md.ant.isolation = 10; + + if (md->md.ant.num == 3) { + md->md.ant.type = BTC_ANT_DEDICATED; + md->md.bt_pos = BTC_BT_ALONE; + } else { + md->md.ant.type = BTC_ANT_SHARED; + md->md.bt_pos = BTC_BT_BTG; + } + rtwdev->btc.btg_pos = md->md.ant.btg_pos; + rtwdev->btc.ant_type = md->md.ant.type; } } -static void rtw8852c_ctrl_btg(struct rtw89_dev *rtwdev, bool btg) +static void rtw8852c_ctrl_btg_bt_rx(struct rtw89_dev *rtwdev, bool en, + enum rtw89_phy_idx phy_idx) { - if (btg) { + if (en) { rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1, B_PATH0_BT_SHARE_V1, 0x1); rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1, @@ -2458,7 +2665,6 @@ void rtw8852c_set_trx_mask(struct rtw89_dev *rtwdev, u8 path, u8 group, u32 val) static void rtw8852c_btc_init_cfg(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; - struct rtw89_btc_module *module = &btc->mdinfo; const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_mac_ax_coex coex_params = { .pta_mode = RTW89_MAC_AX_COEX_RTK_MODE, @@ -2477,7 +2683,7 @@ static void rtw8852c_btc_init_cfg(struct rtw89_dev *rtwdev) rtw89_write_rf(rtwdev, RF_PATH_B, RR_WLSEL, RFREG_MASK, 0x0); /* set WL Tx thru in TRX mask table if GNT_WL = 0 && BT_S1 = ss group */ - if (module->ant.type == BTC_ANT_SHARED) { + if (btc->ant_type == BTC_ANT_SHARED) { rtw8852c_set_trx_mask(rtwdev, RF_PATH_A, BTC_BT_SS_GROUP, 0x5ff); rtw8852c_set_trx_mask(rtwdev, @@ -2597,7 +2803,8 @@ do { \ static s8 rtw8852c_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val) { - return clamp_t(s8, val, -100, 0) + 100; + /* +6 for compensate offset */ + return clamp_t(s8, val + 6, -100, 0) + 100; } static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_ul[] = { @@ -2606,7 +2813,7 @@ static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_ul[] = { {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */ - {255, 0, 0, 7}, /* the below id is for non-shared-antenna free-run */ + {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */ {6, 1, 0, 7}, {13, 1, 0, 7}, {13, 1, 0, 7} @@ -2618,7 +2825,7 @@ static const struct rtw89_btc_rf_trx_para rtw89_btc_8852c_rf_dl[] = { {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */ {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */ {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */ - {255, 0, 0, 7}, /* the below id is for non-shared-antenna free-run */ + {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */ {255, 1, 0, 7}, {255, 1, 0, 7}, {255, 1, 0, 7} @@ -2640,6 +2847,9 @@ static const struct rtw89_btc_fbtc_mreg rtw89_btc_8852c_mon_reg[] = { RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd200), RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd220), RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4aa4), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4778), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x476c), }; static @@ -2703,20 +2913,25 @@ static void rtw8852c_set_wl_lna2(struct rtw89_dev *rtwdev, u8 level) static void rtw8852c_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level) { + struct rtw89_btc *btc = &rtwdev->btc; + switch (level) { case 0: /* original */ - rtw8852c_bb_ctrl_btc_preagc(rtwdev, false); - rtw8852c_set_wl_lna2(rtwdev, 0); + default: + rtw8852c_ctrl_nbtg_bt_tx(rtwdev, false, RTW89_PHY_0); + btc->dm.wl_lna2 = 0; break; case 1: /* for FDD free-run */ - rtw8852c_bb_ctrl_btc_preagc(rtwdev, true); - rtw8852c_set_wl_lna2(rtwdev, 0); + rtw8852c_ctrl_nbtg_bt_tx(rtwdev, true, RTW89_PHY_0); + btc->dm.wl_lna2 = 0; break; case 2: /* for BTG Co-Rx*/ - rtw8852c_bb_ctrl_btc_preagc(rtwdev, false); - rtw8852c_set_wl_lna2(rtwdev, 1); + rtw8852c_ctrl_nbtg_bt_tx(rtwdev, false, RTW89_PHY_0); + btc->dm.wl_lna2 = 1; break; } + + rtw8852c_set_wl_lna2(rtwdev, btc->dm.wl_lna2); } static void rtw8852c_fill_freq_with_ppdu(struct rtw89_dev *rtwdev, @@ -2730,7 +2945,7 @@ static void rtw8852c_fill_freq_with_ppdu(struct rtw89_dev *rtwdev, if (chan_idx == 0) return; - rtw8852c_decode_chan_idx(rtwdev, chan_idx, &ch, &band); + rtw89_decode_chan_idx(rtwdev, chan_idx, &ch, &band); status->freq = ieee80211_channel_to_frequency(ch, band); status->band = band; } @@ -2742,7 +2957,10 @@ static void rtw8852c_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]); @@ -2790,24 +3008,34 @@ static int rtw8852c_mac_enable_bb_rf(struct rtw89_dev *rtwdev) static int rtw8852c_mac_disable_bb_rf(struct rtw89_dev *rtwdev) { + rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN); return 0; } +static const struct rtw89_chanctx_listener rtw8852c_chanctx_listener = { + .callbacks[RTW89_CHANCTX_CALLBACK_RFK] = rtw8852c_rfk_chanctx_cb, + .callbacks[RTW89_CHANCTX_CALLBACK_TAS] = rtw89_tas_chanctx_cb, +}; + #ifdef CONFIG_PM static const struct wiphy_wowlan_support rtw_wowlan_stub_8852c = { - .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_NET_DETECT, .n_patterns = RTW89_MAX_PATTERN_NUM, .pattern_max_len = RTW89_MAX_PATTERN_SIZE, .pattern_min_len = 1, + .max_nd_match_sets = RTW89_SCANOFLD_MAX_SSID, }; #endif static const struct rtw89_chip_ops rtw8852c_chip_ops = { .enable_bb_rf = rtw8852c_mac_enable_bb_rf, .disable_bb_rf = rtw8852c_mac_disable_bb_rf, + .bb_preinit = NULL, + .bb_postinit = NULL, .bb_reset = rtw8852c_bb_reset, .bb_sethw = rtw8852c_bb_sethw, .read_rf = rtw89_phy_read_rf_v1, @@ -2817,7 +3045,10 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .read_efuse = rtw8852c_read_efuse, .read_phycap = rtw8852c_read_phycap, .fem_setup = NULL, + .rfe_gpio = NULL, + .rfk_hw_init = NULL, .rfk_init = rtw8852c_rfk_init, + .rfk_init_late = NULL, .rfk_channel = rtw8852c_rfk_channel, .rfk_band_changed = rtw8852c_rfk_band_changed, .rfk_scan = rtw8852c_rfk_scan, @@ -2827,20 +3058,36 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .set_txpwr_ctrl = rtw8852c_set_txpwr_ctrl, .init_txpwr_unit = rtw8852c_init_txpwr_unit, .get_thermal = rtw8852c_get_thermal, - .ctrl_btg = rtw8852c_ctrl_btg, + .chan_to_rf18_val = NULL, + .ctrl_btg_bt_rx = rtw8852c_ctrl_btg_bt_rx, .query_ppdu = rtw8852c_query_ppdu, - .bb_ctrl_btc_preagc = rtw8852c_bb_ctrl_btc_preagc, + .convert_rpl_to_rssi = NULL, + .phy_rpt_to_rssi = NULL, + .ctrl_nbtg_bt_tx = rtw8852c_ctrl_nbtg_bt_tx, .cfg_txrx_path = rtw8852c_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset, + .digital_pwr_comp = NULL, .pwr_on_func = rtw8852c_pwr_on_func, .pwr_off_func = rtw8852c_pwr_off_func, + .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc_v1, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v1, + .get_ch_dma = {rtw89_core_get_ch_dma, + rtw89_core_get_ch_dma_v2, + NULL,}, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v1, .mac_cfg_gnt = rtw89_mac_cfg_gnt_v1, .stop_sch_tx = rtw89_mac_stop_sch_tx_v1, .resume_sch_tx = rtw89_mac_resume_sch_tx_v1, .h2c_dctl_sec_cam = rtw89_fw_h2c_dctl_sec_cam_v1, + .h2c_default_cmac_tbl = rtw89_fw_h2c_default_cmac_tbl, + .h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl, + .h2c_ampdu_cmac_tbl = NULL, + .h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl, + .h2c_punctured_cmac_tbl = NULL, + .h2c_default_dmac_tbl = NULL, + .h2c_update_beacon = rtw89_fw_h2c_update_beacon, + .h2c_ba_cam = rtw89_fw_h2c_ba_cam, .btc_set_rfe = rtw8852c_btc_set_rfe, .btc_init_cfg = rtw8852c_btc_init_cfg, @@ -2855,18 +3102,33 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { const struct rtw89_chip_info rtw8852c_chip_info = { .chip_id = RTL8852C, + .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852c_chip_ops, - .fw_name = "rtw89/rtw8852c_fw.bin", + .mac_def = &rtw89_mac_gen_ax, + .phy_def = &rtw89_phy_gen_ax, + .fw_basename = RTW8852C_FW_BASENAME, + .fw_format_max = RTW8852C_FW_FORMAT_MAX, + .try_ce_fw = false, + .bbmcu_nr = 0, + .needed_fw_elms = 0, + .fw_blacklist = &rtw89_fw_blacklist_default, .fifo_size = 458752, + .small_fifo_size = false, .dle_scc_rsvd_size = 0, .max_amsdu_limit = 8000, .dis_2g_40m_ul_ofdma = false, .rsvd_ple_ofst = 0x6f800, - .hfc_param_ini = rtw8852c_hfc_param_ini_pcie, - .dle_mem = rtw8852c_dle_mem_pcie, - .wde_qempty_acq_num = 16, - .wde_qempty_mgq_sel = 16, + .hfc_param_ini = {rtw8852c_hfc_param_ini_pcie, + rtw8852c_hfc_param_ini_usb, + NULL}, + .dle_mem = {rtw8852c_dle_mem_pcie, + rtw8852c_dle_mem_usb2, + rtw8852c_dle_mem_usb3, + NULL}, + .wde_qempty_acq_grpnum = 16, + .wde_qempty_mgq_grpsel = 16, .rf_base_addr = {0xe000, 0xf000}, + .thermal_th = {0x32, 0x35}, .pwr_on_seq = NULL, .pwr_off_seq = NULL, .bb_table = &rtw89_8852c_phy_bb_table, @@ -2874,25 +3136,39 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .rf_table = {&rtw89_8852c_phy_radiob_table, &rtw89_8852c_phy_radioa_table,}, .nctl_table = &rtw89_8852c_phy_nctl_table, - .byr_table = &rtw89_8852c_byr_table, - .txpwr_lmt_2g = &rtw89_8852c_txpwr_lmt_2g, - .txpwr_lmt_5g = &rtw89_8852c_txpwr_lmt_5g, - .txpwr_lmt_6g = &rtw89_8852c_txpwr_lmt_6g, - .txpwr_lmt_ru_2g = &rtw89_8852c_txpwr_lmt_ru_2g, - .txpwr_lmt_ru_5g = &rtw89_8852c_txpwr_lmt_ru_5g, - .txpwr_lmt_ru_6g = &rtw89_8852c_txpwr_lmt_ru_6g, + .nctl_post_table = NULL, + .dflt_parms = &rtw89_8852c_dflt_parms, + .rfe_parms_conf = NULL, + .chanctx_listener = &rtw8852c_chanctx_listener, + .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, .dig_table = NULL, .dig_regs = &rtw8852c_dig_regs, .tssi_dbw_table = &rtw89_8852c_tssi_dbw_table, - .support_chanctx_num = 1, + .support_macid_num = RTW89_MAX_MAC_ID_NUM, + .support_link_num = 0, + .support_chanctx_num = 2, + .support_rnr = false, .support_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ) | BIT(NL80211_BAND_6GHZ), - .support_bw160 = true, - .support_ul_tb_ctrl = false, + .support_bandwidths = BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + 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 = true, + .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, @@ -2901,34 +3177,22 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .scam_num = 128, .bacam_num = 8, .bacam_dynamic_num = 8, - .bacam_v1 = true, + .bacam_ver = RTW89_BACAM_V0_EXT, + .addrcam_ver = 0, + .ppdu_max_usr = 8, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, .logical_efuse_size = 2048, .limit_efuse_size = 1280, .dav_phy_efuse_size = 96, .dav_log_efuse_size = 16, + .efuse_blocks = NULL, .phycap_addr = 0x590, .phycap_size = 0x60, .para_ver = 0x1, .wlcx_desired = 0x06000000, - .btcx_desired = 0x7, .scbd = 0x1, .mailbox = 0x1, - .btc_fwinfo_buf = 1280, - - .fcxbtcrpt_ver = 4, - .fcxtdma_ver = 3, - .fcxslots_ver = 1, - .fcxcysta_ver = 3, - .fcxstep_ver = 3, - .fcxnullsta_ver = 2, - .fcxmreg_ver = 1, - .fcxgpiodbg_ver = 1, - .fcxbtver_ver = 1, - .fcxbtscan_ver = 1, - .fcxbtafh_ver = 1, - .fcxbtdevinfo_ver = 1, .afh_guard_ch = 6, .wl_rssi_thres = rtw89_btc_8852c_wl_rssi_thres, @@ -2949,24 +3213,39 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .hci_func_en_addr = R_AX_HCI_FUNC_EN_V1, .h2c_desc_size = sizeof(struct rtw89_rxdesc_short), .txwd_body_size = sizeof(struct rtw89_txwd_body_v1), + .txwd_info_size = sizeof(struct rtw89_txwd_info), .h2c_ctrl_reg = R_AX_H2CREG_CTRL_V1, + .h2c_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_H2C_DEQ_CNT_MASK >> 8}, .h2c_regs = rtw8852c_h2c_regs, .c2h_ctrl_reg = R_AX_C2HREG_CTRL_V1, + .c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8}, .c2h_regs = rtw8852c_c2h_regs, .page_regs = &rtw8852c_page_regs, + .wow_reason_reg = rtw8852c_wow_wakeup_regs, .cfo_src_fd = false, + .cfo_hw_comp = false, .dcfo_comp = &rtw8852c_dcfo_comp, - .dcfo_comp_sft = 5, + .dcfo_comp_sft = 12, + .nhm_report = NULL, + .nhm_th = NULL, .imr_info = &rtw8852c_imr_info, + .imr_dmac_table = NULL, + .imr_cmac_table = NULL, .rrsr_cfgs = &rtw8852c_rrsr_cfgs, + .bss_clr_vld = {R_BSS_CLR_MAP, B_BSS_CLR_MAP_VLD0}, + .bss_clr_map_reg = R_BSS_CLR_MAP, + .rfkill_init = &rtw8852c_rfkill_regs, + .rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9}, .dma_ch_mask = 0, + .edcca_regs = &rtw8852c_edcca_regs, #ifdef CONFIG_PM .wowlan_stub = &rtw_wowlan_stub_8852c, #endif + .xtal_info = NULL, }; EXPORT_SYMBOL(rtw8852c_chip_info); -MODULE_FIRMWARE("rtw89/rtw8852c_fw.bin"); +MODULE_FIRMWARE(RTW8852C_MODULE_FIRMWARE); MODULE_AUTHOR("Realtek Corporation"); MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852C driver"); MODULE_LICENSE("Dual BSD/GPL"); |
