162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 262306a36Sopenharmony_ci/* Copyright(c) 2018-2019 Realtek Corporation. 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include "main.h" 662306a36Sopenharmony_ci#include "reg.h" 762306a36Sopenharmony_ci#include "bf.h" 862306a36Sopenharmony_ci#include "debug.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_civoid rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, 1162306a36Sopenharmony_ci struct ieee80211_bss_conf *bss_conf) 1262306a36Sopenharmony_ci{ 1362306a36Sopenharmony_ci struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; 1462306a36Sopenharmony_ci struct rtw_bfee *bfee = &rtwvif->bfee; 1562306a36Sopenharmony_ci struct rtw_bf_info *bfinfo = &rtwdev->bf_info; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci if (bfee->role == RTW_BFEE_NONE) 1862306a36Sopenharmony_ci return; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci if (bfee->role == RTW_BFEE_MU) 2162306a36Sopenharmony_ci bfinfo->bfer_mu_cnt--; 2262306a36Sopenharmony_ci else if (bfee->role == RTW_BFEE_SU) 2362306a36Sopenharmony_ci bfinfo->bfer_su_cnt--; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci rtw_chip_config_bfee(rtwdev, rtwvif, bfee, false); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci bfee->role = RTW_BFEE_NONE; 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_civoid rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, 3162306a36Sopenharmony_ci struct ieee80211_bss_conf *bss_conf) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 3462306a36Sopenharmony_ci struct ieee80211_hw *hw = rtwdev->hw; 3562306a36Sopenharmony_ci struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; 3662306a36Sopenharmony_ci struct rtw_bfee *bfee = &rtwvif->bfee; 3762306a36Sopenharmony_ci struct rtw_bf_info *bfinfo = &rtwdev->bf_info; 3862306a36Sopenharmony_ci struct ieee80211_sta *sta; 3962306a36Sopenharmony_ci struct ieee80211_sta_vht_cap *vht_cap; 4062306a36Sopenharmony_ci struct ieee80211_sta_vht_cap *ic_vht_cap; 4162306a36Sopenharmony_ci const u8 *bssid = bss_conf->bssid; 4262306a36Sopenharmony_ci u32 sound_dim; 4362306a36Sopenharmony_ci u8 i; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (!(chip->band & RTW_BAND_5G)) 4662306a36Sopenharmony_ci return; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci rcu_read_lock(); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci sta = ieee80211_find_sta(vif, bssid); 5162306a36Sopenharmony_ci if (!sta) { 5262306a36Sopenharmony_ci rcu_read_unlock(); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci rtw_warn(rtwdev, "failed to find station entry for bss %pM\n", 5562306a36Sopenharmony_ci bssid); 5662306a36Sopenharmony_ci return; 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci ic_vht_cap = &hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap; 6062306a36Sopenharmony_ci vht_cap = &sta->deflink.vht_cap; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci rcu_read_unlock(); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) && 6562306a36Sopenharmony_ci (vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { 6662306a36Sopenharmony_ci if (bfinfo->bfer_mu_cnt >= chip->bfer_mu_max_num) { 6762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_BF, "mu bfer number over limit\n"); 6862306a36Sopenharmony_ci return; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci ether_addr_copy(bfee->mac_addr, bssid); 7262306a36Sopenharmony_ci bfee->role = RTW_BFEE_MU; 7362306a36Sopenharmony_ci bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7); 7462306a36Sopenharmony_ci bfee->aid = vif->cfg.aid; 7562306a36Sopenharmony_ci bfinfo->bfer_mu_cnt++; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true); 7862306a36Sopenharmony_ci } else if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) && 7962306a36Sopenharmony_ci (vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { 8062306a36Sopenharmony_ci if (bfinfo->bfer_su_cnt >= chip->bfer_su_max_num) { 8162306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_BF, "su bfer number over limit\n"); 8262306a36Sopenharmony_ci return; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci sound_dim = vht_cap->cap & 8662306a36Sopenharmony_ci IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; 8762306a36Sopenharmony_ci sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci ether_addr_copy(bfee->mac_addr, bssid); 9062306a36Sopenharmony_ci bfee->role = RTW_BFEE_SU; 9162306a36Sopenharmony_ci bfee->sound_dim = (u8)sound_dim; 9262306a36Sopenharmony_ci bfee->g_id = 0; 9362306a36Sopenharmony_ci bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7); 9462306a36Sopenharmony_ci bfinfo->bfer_su_cnt++; 9562306a36Sopenharmony_ci for (i = 0; i < chip->bfer_su_max_num; i++) { 9662306a36Sopenharmony_ci if (!test_bit(i, bfinfo->bfer_su_reg_maping)) { 9762306a36Sopenharmony_ci set_bit(i, bfinfo->bfer_su_reg_maping); 9862306a36Sopenharmony_ci bfee->su_reg_index = i; 9962306a36Sopenharmony_ci break; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true); 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_civoid rtw_bf_init_bfer_entry_mu(struct rtw_dev *rtwdev, 10862306a36Sopenharmony_ci struct mu_bfer_init_para *param) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci u16 mu_bf_ctl = 0; 11162306a36Sopenharmony_ci u8 *addr = param->bfer_address; 11262306a36Sopenharmony_ci int i; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci for (i = 0; i < ETH_ALEN; i++) 11562306a36Sopenharmony_ci rtw_write8(rtwdev, REG_ASSOCIATED_BFMER0_INFO + i, addr[i]); 11662306a36Sopenharmony_ci rtw_write16(rtwdev, REG_ASSOCIATED_BFMER0_INFO + 6, param->paid); 11762306a36Sopenharmony_ci rtw_write16(rtwdev, REG_TX_CSI_RPT_PARAM_BW20, param->csi_para); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci mu_bf_ctl = rtw_read16(rtwdev, REG_WMAC_MU_BF_CTL) & 0xC000; 12062306a36Sopenharmony_ci mu_bf_ctl |= param->my_aid | (param->csi_length_sel << 12); 12162306a36Sopenharmony_ci rtw_write16(rtwdev, REG_WMAC_MU_BF_CTL, mu_bf_ctl); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_civoid rtw_bf_cfg_sounding(struct rtw_dev *rtwdev, struct rtw_vif *vif, 12562306a36Sopenharmony_ci enum rtw_trx_desc_rate rate) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci u32 psf_ctl = 0; 12862306a36Sopenharmony_ci u8 csi_rsc = 0x1; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci psf_ctl = rtw_read32(rtwdev, REG_BBPSF_CTRL) | 13162306a36Sopenharmony_ci BIT_WMAC_USE_NDPARATE | 13262306a36Sopenharmony_ci (csi_rsc << 13); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, 13562306a36Sopenharmony_ci RTW_SND_CTRL_SOUNDING); 13662306a36Sopenharmony_ci rtw_write8(rtwdev, REG_SND_PTCL_CTRL + 3, 0x26); 13762306a36Sopenharmony_ci rtw_write8_clr(rtwdev, REG_RXFLTMAP1, BIT_RXFLTMAP1_BF_REPORT_POLL); 13862306a36Sopenharmony_ci rtw_write8_clr(rtwdev, REG_RXFLTMAP4, BIT_RXFLTMAP4_BF_REPORT_POLL); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (vif->net_type == RTW_NET_AP_MODE) 14162306a36Sopenharmony_ci rtw_write32(rtwdev, REG_BBPSF_CTRL, psf_ctl | BIT(12)); 14262306a36Sopenharmony_ci else 14362306a36Sopenharmony_ci rtw_write32(rtwdev, REG_BBPSF_CTRL, psf_ctl & ~BIT(12)); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_civoid rtw_bf_cfg_mu_bfee(struct rtw_dev *rtwdev, struct cfg_mumimo_para *param) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci u8 mu_tbl_sel; 14962306a36Sopenharmony_ci u8 mu_valid; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci mu_valid = rtw_read8(rtwdev, REG_MU_TX_CTL) & 15262306a36Sopenharmony_ci ~BIT_MASK_R_MU_TABLE_VALID; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci rtw_write8(rtwdev, REG_MU_TX_CTL, 15562306a36Sopenharmony_ci (mu_valid | BIT(0) | BIT(1)) & ~(BIT(7))); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci mu_tbl_sel = rtw_read8(rtwdev, REG_MU_TX_CTL + 1) & 0xF8; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci rtw_write8(rtwdev, REG_MU_TX_CTL + 1, mu_tbl_sel); 16062306a36Sopenharmony_ci rtw_write32(rtwdev, REG_MU_STA_GID_VLD, param->given_gid_tab[0]); 16162306a36Sopenharmony_ci rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO, param->given_user_pos[0]); 16262306a36Sopenharmony_ci rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO + 4, 16362306a36Sopenharmony_ci param->given_user_pos[1]); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci rtw_write8(rtwdev, REG_MU_TX_CTL + 1, mu_tbl_sel | 1); 16662306a36Sopenharmony_ci rtw_write32(rtwdev, REG_MU_STA_GID_VLD, param->given_gid_tab[1]); 16762306a36Sopenharmony_ci rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO, param->given_user_pos[2]); 16862306a36Sopenharmony_ci rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO + 4, 16962306a36Sopenharmony_ci param->given_user_pos[3]); 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_civoid rtw_bf_del_bfer_entry_mu(struct rtw_dev *rtwdev) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci rtw_write32(rtwdev, REG_ASSOCIATED_BFMER0_INFO, 0); 17562306a36Sopenharmony_ci rtw_write32(rtwdev, REG_ASSOCIATED_BFMER0_INFO + 4, 0); 17662306a36Sopenharmony_ci rtw_write16(rtwdev, REG_WMAC_MU_BF_CTL, 0); 17762306a36Sopenharmony_ci rtw_write8(rtwdev, REG_MU_TX_CTL, 0); 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_civoid rtw_bf_del_sounding(struct rtw_dev *rtwdev) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, 0); 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_civoid rtw_bf_enable_bfee_su(struct rtw_dev *rtwdev, struct rtw_vif *vif, 18662306a36Sopenharmony_ci struct rtw_bfee *bfee) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci u8 nc_index = hweight8(rtwdev->hal.antenna_rx) - 1; 18962306a36Sopenharmony_ci u8 nr_index = bfee->sound_dim; 19062306a36Sopenharmony_ci u8 grouping = 0, codebookinfo = 1, coefficientsize = 3; 19162306a36Sopenharmony_ci u32 addr_bfer_info, addr_csi_rpt, csi_param; 19262306a36Sopenharmony_ci u8 i; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_BF, "config as an su bfee\n"); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci switch (bfee->su_reg_index) { 19762306a36Sopenharmony_ci case 1: 19862306a36Sopenharmony_ci addr_bfer_info = REG_ASSOCIATED_BFMER1_INFO; 19962306a36Sopenharmony_ci addr_csi_rpt = REG_TX_CSI_RPT_PARAM_BW20 + 2; 20062306a36Sopenharmony_ci break; 20162306a36Sopenharmony_ci case 0: 20262306a36Sopenharmony_ci default: 20362306a36Sopenharmony_ci addr_bfer_info = REG_ASSOCIATED_BFMER0_INFO; 20462306a36Sopenharmony_ci addr_csi_rpt = REG_TX_CSI_RPT_PARAM_BW20; 20562306a36Sopenharmony_ci break; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* Sounding protocol control */ 20962306a36Sopenharmony_ci rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, 21062306a36Sopenharmony_ci RTW_SND_CTRL_SOUNDING); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* MAC address/Partial AID of Beamformer */ 21362306a36Sopenharmony_ci for (i = 0; i < ETH_ALEN; i++) 21462306a36Sopenharmony_ci rtw_write8(rtwdev, addr_bfer_info + i, bfee->mac_addr[i]); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci csi_param = (u16)((coefficientsize << 10) | 21762306a36Sopenharmony_ci (codebookinfo << 8) | 21862306a36Sopenharmony_ci (grouping << 6) | 21962306a36Sopenharmony_ci (nr_index << 3) | 22062306a36Sopenharmony_ci nc_index); 22162306a36Sopenharmony_ci rtw_write16(rtwdev, addr_csi_rpt, csi_param); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* ndp rx standby timer */ 22462306a36Sopenharmony_ci rtw_write8(rtwdev, REG_SND_PTCL_CTRL + 3, RTW_NDP_RX_STANDBY_TIME); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_bf_enable_bfee_su); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci/* nc index: 1 2T2R 0 1T1R 22962306a36Sopenharmony_ci * nr index: 1 use Nsts 0 use reg setting 23062306a36Sopenharmony_ci * codebookinfo: 1 802.11ac 3 802.11n 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_civoid rtw_bf_enable_bfee_mu(struct rtw_dev *rtwdev, struct rtw_vif *vif, 23362306a36Sopenharmony_ci struct rtw_bfee *bfee) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci struct rtw_bf_info *bf_info = &rtwdev->bf_info; 23662306a36Sopenharmony_ci struct mu_bfer_init_para param; 23762306a36Sopenharmony_ci u8 nc_index = hweight8(rtwdev->hal.antenna_rx) - 1; 23862306a36Sopenharmony_ci u8 nr_index = 1; 23962306a36Sopenharmony_ci u8 grouping = 0, codebookinfo = 1, coefficientsize = 0; 24062306a36Sopenharmony_ci u32 csi_param; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_BF, "config as an mu bfee\n"); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci csi_param = (u16)((coefficientsize << 10) | 24562306a36Sopenharmony_ci (codebookinfo << 8) | 24662306a36Sopenharmony_ci (grouping << 6) | 24762306a36Sopenharmony_ci (nr_index << 3) | 24862306a36Sopenharmony_ci nc_index); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_BF, "nc=%d nr=%d group=%d codebookinfo=%d coefficientsize=%d\n", 25162306a36Sopenharmony_ci nc_index, nr_index, grouping, codebookinfo, 25262306a36Sopenharmony_ci coefficientsize); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci param.paid = bfee->p_aid; 25562306a36Sopenharmony_ci param.csi_para = csi_param; 25662306a36Sopenharmony_ci param.my_aid = bfee->aid & 0xfff; 25762306a36Sopenharmony_ci param.csi_length_sel = HAL_CSI_SEG_4K; 25862306a36Sopenharmony_ci ether_addr_copy(param.bfer_address, bfee->mac_addr); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci rtw_bf_init_bfer_entry_mu(rtwdev, ¶m); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci bf_info->cur_csi_rpt_rate = DESC_RATE6M; 26362306a36Sopenharmony_ci rtw_bf_cfg_sounding(rtwdev, vif, DESC_RATE6M); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci /* accept action_no_ack */ 26662306a36Sopenharmony_ci rtw_write16_set(rtwdev, REG_RXFLTMAP0, BIT_RXFLTMAP0_ACTIONNOACK); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* accept NDPA and BF report poll */ 26962306a36Sopenharmony_ci rtw_write16_set(rtwdev, REG_RXFLTMAP1, BIT_RXFLTMAP1_BF); 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_bf_enable_bfee_mu); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_civoid rtw_bf_remove_bfee_su(struct rtw_dev *rtwdev, 27462306a36Sopenharmony_ci struct rtw_bfee *bfee) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci struct rtw_bf_info *bfinfo = &rtwdev->bf_info; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_BF, "remove as a su bfee\n"); 27962306a36Sopenharmony_ci rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, 28062306a36Sopenharmony_ci RTW_SND_CTRL_REMOVE); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci switch (bfee->su_reg_index) { 28362306a36Sopenharmony_ci case 0: 28462306a36Sopenharmony_ci rtw_write32(rtwdev, REG_ASSOCIATED_BFMER0_INFO, 0); 28562306a36Sopenharmony_ci rtw_write16(rtwdev, REG_ASSOCIATED_BFMER0_INFO + 4, 0); 28662306a36Sopenharmony_ci rtw_write16(rtwdev, REG_TX_CSI_RPT_PARAM_BW20, 0); 28762306a36Sopenharmony_ci break; 28862306a36Sopenharmony_ci case 1: 28962306a36Sopenharmony_ci rtw_write32(rtwdev, REG_ASSOCIATED_BFMER1_INFO, 0); 29062306a36Sopenharmony_ci rtw_write16(rtwdev, REG_ASSOCIATED_BFMER1_INFO + 4, 0); 29162306a36Sopenharmony_ci rtw_write16(rtwdev, REG_TX_CSI_RPT_PARAM_BW20 + 2, 0); 29262306a36Sopenharmony_ci break; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci clear_bit(bfee->su_reg_index, bfinfo->bfer_su_reg_maping); 29662306a36Sopenharmony_ci bfee->su_reg_index = 0xFF; 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_bf_remove_bfee_su); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_civoid rtw_bf_remove_bfee_mu(struct rtw_dev *rtwdev, 30162306a36Sopenharmony_ci struct rtw_bfee *bfee) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci struct rtw_bf_info *bfinfo = &rtwdev->bf_info; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci rtw_write8_mask(rtwdev, REG_SND_PTCL_CTRL, BIT_MASK_BEAMFORM, 30662306a36Sopenharmony_ci RTW_SND_CTRL_REMOVE); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci rtw_bf_del_bfer_entry_mu(rtwdev); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci if (bfinfo->bfer_su_cnt == 0 && bfinfo->bfer_mu_cnt == 0) 31162306a36Sopenharmony_ci rtw_bf_del_sounding(rtwdev); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_bf_remove_bfee_mu); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_civoid rtw_bf_set_gid_table(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, 31662306a36Sopenharmony_ci struct ieee80211_bss_conf *conf) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; 31962306a36Sopenharmony_ci struct rtw_bfee *bfee = &rtwvif->bfee; 32062306a36Sopenharmony_ci struct cfg_mumimo_para param; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (bfee->role != RTW_BFEE_MU) { 32362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_BF, "this vif is not mu bfee\n"); 32462306a36Sopenharmony_ci return; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci param.grouping_bitmap = 0; 32862306a36Sopenharmony_ci param.mu_tx_en = 0; 32962306a36Sopenharmony_ci memset(param.sounding_sts, 0, 6); 33062306a36Sopenharmony_ci memcpy(param.given_gid_tab, conf->mu_group.membership, 8); 33162306a36Sopenharmony_ci memcpy(param.given_user_pos, conf->mu_group.position, 16); 33262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_BF, "STA0: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n", 33362306a36Sopenharmony_ci param.given_gid_tab[0], param.given_user_pos[0], 33462306a36Sopenharmony_ci param.given_user_pos[1]); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_BF, "STA1: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n", 33762306a36Sopenharmony_ci param.given_gid_tab[1], param.given_user_pos[2], 33862306a36Sopenharmony_ci param.given_user_pos[3]); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci rtw_bf_cfg_mu_bfee(rtwdev, ¶m); 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_bf_set_gid_table); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_civoid rtw_bf_phy_init(struct rtw_dev *rtwdev) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci u8 tmp8; 34762306a36Sopenharmony_ci u32 tmp32; 34862306a36Sopenharmony_ci u8 retry_limit = 0xA; 34962306a36Sopenharmony_ci u8 ndpa_rate = 0x10; 35062306a36Sopenharmony_ci u8 ack_policy = 3; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci tmp32 = rtw_read32(rtwdev, REG_MU_TX_CTL); 35362306a36Sopenharmony_ci /* Enable P1 aggr new packet according to P0 transfer time */ 35462306a36Sopenharmony_ci tmp32 |= BIT_MU_P1_WAIT_STATE_EN; 35562306a36Sopenharmony_ci /* MU Retry Limit */ 35662306a36Sopenharmony_ci tmp32 &= ~BIT_MASK_R_MU_RL; 35762306a36Sopenharmony_ci tmp32 |= (retry_limit << BIT_SHIFT_R_MU_RL) & BIT_MASK_R_MU_RL; 35862306a36Sopenharmony_ci /* Disable Tx MU-MIMO until sounding done */ 35962306a36Sopenharmony_ci tmp32 &= ~BIT_EN_MU_MIMO; 36062306a36Sopenharmony_ci /* Clear validity of MU STAs */ 36162306a36Sopenharmony_ci tmp32 &= ~BIT_MASK_R_MU_TABLE_VALID; 36262306a36Sopenharmony_ci rtw_write32(rtwdev, REG_MU_TX_CTL, tmp32); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci /* MU-MIMO Option as default value */ 36562306a36Sopenharmony_ci tmp8 = ack_policy << BIT_SHIFT_WMAC_TXMU_ACKPOLICY; 36662306a36Sopenharmony_ci tmp8 |= BIT_WMAC_TXMU_ACKPOLICY_EN; 36762306a36Sopenharmony_ci rtw_write8(rtwdev, REG_WMAC_MU_BF_OPTION, tmp8); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci /* MU-MIMO Control as default value */ 37062306a36Sopenharmony_ci rtw_write16(rtwdev, REG_WMAC_MU_BF_CTL, 0); 37162306a36Sopenharmony_ci /* Set MU NDPA rate & BW source */ 37262306a36Sopenharmony_ci rtw_write32_set(rtwdev, REG_TXBF_CTRL, BIT_USE_NDPA_PARAMETER); 37362306a36Sopenharmony_ci /* Set NDPA Rate */ 37462306a36Sopenharmony_ci rtw_write8(rtwdev, REG_NDPA_OPT_CTRL, ndpa_rate); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci rtw_write32_mask(rtwdev, REG_BBPSF_CTRL, BIT_MASK_CSI_RATE, 37762306a36Sopenharmony_ci DESC_RATE6M); 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_bf_phy_init); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_civoid rtw_bf_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate, 38262306a36Sopenharmony_ci u8 fixrate_en, u8 *new_rate) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci u32 csi_cfg; 38562306a36Sopenharmony_ci u16 cur_rrsr; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci csi_cfg = rtw_read32(rtwdev, REG_BBPSF_CTRL) & ~BIT_MASK_CSI_RATE; 38862306a36Sopenharmony_ci cur_rrsr = rtw_read16(rtwdev, REG_RRSR); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci if (rssi >= 40) { 39162306a36Sopenharmony_ci if (cur_rate != DESC_RATE54M) { 39262306a36Sopenharmony_ci cur_rrsr |= BIT(DESC_RATE54M); 39362306a36Sopenharmony_ci csi_cfg |= (DESC_RATE54M & BIT_MASK_CSI_RATE_VAL) << 39462306a36Sopenharmony_ci BIT_SHIFT_CSI_RATE; 39562306a36Sopenharmony_ci rtw_write16(rtwdev, REG_RRSR, cur_rrsr); 39662306a36Sopenharmony_ci rtw_write32(rtwdev, REG_BBPSF_CTRL, csi_cfg); 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci *new_rate = DESC_RATE54M; 39962306a36Sopenharmony_ci } else { 40062306a36Sopenharmony_ci if (cur_rate != DESC_RATE24M) { 40162306a36Sopenharmony_ci cur_rrsr &= ~BIT(DESC_RATE54M); 40262306a36Sopenharmony_ci csi_cfg |= (DESC_RATE54M & BIT_MASK_CSI_RATE_VAL) << 40362306a36Sopenharmony_ci BIT_SHIFT_CSI_RATE; 40462306a36Sopenharmony_ci rtw_write16(rtwdev, REG_RRSR, cur_rrsr); 40562306a36Sopenharmony_ci rtw_write32(rtwdev, REG_BBPSF_CTRL, csi_cfg); 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci *new_rate = DESC_RATE24M; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_bf_cfg_csi_rate); 411