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, &param);
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, &param);
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