Commit 1ba63a8a authored by Ping-Ke Shih's avatar Ping-Ke Shih Committed by Kalle Valo
Browse files

wifi: rtw89: 8922a: add chip_ops::cfg_txrx_path



This function is to set TX/RX path. Especially for 1SS rate, it can select
to TX on one or two antenna. Before this operation, stop hardware to
prevent transmitting/receiving unexpected packets. After that, restore
settings and reset hardware to prevent it stays on abnormal state.

Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20240124033637.12330-4-pkshih@realtek.com
parent b16daa62
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -7686,9 +7686,23 @@
#define B_SWSI_READ_ADDR_ADDR_V1 GENMASK(7, 0)
#define B_SWSI_READ_ADDR_PATH_V1 GENMASK(10, 8)
#define B_SWSI_READ_ADDR_V1 GENMASK(10, 0)
#define R_BRK_R 0x0418
#define B_VHTMCS_LMT GENMASK(22, 21)
#define B_HTMCS_LMT GENMASK(9, 8)
#define R_BRK_EHT 0x0474
#define B_RXEHT_NSS_MAX GENMASK(4, 2)
#define R_BRK_RXEHT 0x0478
#define B_RXEHT_N_USER_MAX GENMASK(31, 24)
#define B_RXEHTTB_NSS_MAX GENMASK(16, 14)
#define R_EN_SND_WO_NDP 0x047c
#define R_EN_SND_WO_NDP_C1 0x147c
#define B_EN_SND_WO_NDP BIT(1)
#define R_BRK_HE 0x0480
#define B_TB_NSS_MAX GENMASK(25, 23)
#define B_NSS_MAX GENMASK(16, 14)
#define B_N_USR_MAX GENMASK(13, 6)
#define R_RXCCA_BE1 0x0520
#define B_RXCCA_BE1_DIS BIT(0)
#define R_UPD_CLK_ADC 0x0700
#define B_UPD_CLK_ADC_VAL GENMASK(26, 25)
#define B_UPD_CLK_ADC_ON BIT(24)
@@ -7735,6 +7749,7 @@
#define B_PMAC_RXMOD_MSK GENMASK(7, 4)
#define R_MAC_SEL 0x09A4
#define B_MAC_SEL_OFDM_TRI_FILTER BIT(31)
#define B_MAC_SEL GENMASK(19, 17)
#define B_MAC_SEL_PWR_EN BIT(16)
#define B_MAC_SEL_DPD_EN BIT(10)
#define B_MAC_SEL_MOD GENMASK(4, 2)
@@ -7828,6 +7843,8 @@
#define R_CLK_GCK 0x1008
#define B_CLK_GCK GENMASK(24, 0)
#define R_EDCCA_RPT_SEL_BE 0x10CC
#define R_ADC_FIFO_V1 0x10FC
#define B_ADC_FIFO_EN_V1 GENMASK(31, 24)
#define R_S0_HW_SI_DIS 0x1200
#define B_S0_HW_SI_DIS_W_R_TRIG GENMASK(30, 28)
#define R_P0_RXCK 0x12A0
@@ -8937,6 +8954,11 @@
#define R_IQK_DPK_PRST 0xE4AC
#define R_IQK_DPK_PRST_C1 0xE5AC
#define B_IQK_DPK_PRST BIT(27)
#define R_TXPWR_RSTA 0xE60C
#define B_TXPWR_RSTA BIT(16)
#define R_TSSI_PWR_P0 0xE610
#define R_TSSI_PWR_P1 0xE710
#define B_TSSI_CONT_EN BIT(3)
#define R_TSSI_MAP_OFST_P0 0xE620
#define R_TSSI_MAP_OFST_P1 0xE720
#define B_TSSI_MAP_OFST_OFDM GENMASK(17, 9)
@@ -8949,6 +8971,8 @@
#define R_TXAGC_REF1_P0 0xE62C
#define R_TXAGC_REF1_P1 0xE72C
#define B_TXAGC_REF1_CCK_CW GENMASK(8, 0)
#define R_TXPWR_RSTB 0xE70C
#define B_TXPWR_RSTB BIT(16)

/* WiFi CPU local domain */
#define R_AX_WDT_CTRL 0x0040
+279 −0
Original line number Diff line number Diff line
@@ -9,12 +9,15 @@
#include "phy.h"
#include "reg.h"
#include "rtw8922a.h"
#include "rtw8922a_rfk.h"

#define RTW8922A_FW_FORMAT_MAX 0
#define RTW8922A_FW_BASENAME "rtw89/rtw8922a_fw"
#define RTW8922A_MODULE_FIRMWARE \
	RTW8922A_FW_BASENAME ".bin"

#define HE_N_USER_MAX_8922A 4

static const struct rtw89_hfc_ch_cfg rtw8922a_hfc_chcfg_pcie[] = {
	{2, 1641, grp_0}, /* ACH 0 */
	{2, 1641, grp_0}, /* ACH 1 */
@@ -1049,10 +1052,167 @@ static void rtw8922a_bb_postinit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
	rtw89_phy_write32_idx(rtwdev, R_UDP_COEEF, B_UDP_COEEF, 0x1, phy_idx);
}

static void rtw8922a_bb_reset_en(struct rtw89_dev *rtwdev, enum rtw89_band band,
				 bool en, enum rtw89_phy_idx phy_idx)
{
	if (en) {
		rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx);
		if (band == RTW89_BAND_2G)
			rtw89_phy_write32_idx(rtwdev, R_RXCCA_BE1,
					      B_RXCCA_BE1_DIS, 0x0, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x0, phy_idx);
	} else {
		rtw89_phy_write32_idx(rtwdev, R_RXCCA_BE1, B_RXCCA_BE1_DIS, 0x1, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x1, phy_idx);
		fsleep(1);
		rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx);
	}
}

static int rtw8922a_ctrl_tx_path_tmac(struct rtw89_dev *rtwdev,
				      enum rtw89_rf_path tx_path,
				      enum rtw89_phy_idx phy_idx)
{
	struct rtw89_reg2_def path_com_cr[] = {
		{0x11A00, 0x21C86900},
		{0x11A04, 0x00E4E433},
		{0x11A08, 0x39390CC9},
		{0x11A0C, 0x4E433240},
		{0x11A10, 0x90CC900E},
		{0x11A14, 0x00240393},
		{0x11A18, 0x201C8600},
	};
	int ret = 0;
	u32 reg;
	int i;

	rtw89_phy_write32_idx(rtwdev, R_MAC_SEL, B_MAC_SEL, 0x0, phy_idx);

	if (phy_idx == RTW89_PHY_1 && !rtwdev->dbcc_en)
		return 0;

	if (tx_path == RF_PATH_A) {
		path_com_cr[0].data = 0x21C82900;
		path_com_cr[1].data = 0x00E4E431;
		path_com_cr[2].data = 0x39390C49;
		path_com_cr[3].data = 0x4E431240;
		path_com_cr[4].data = 0x90C4900E;
		path_com_cr[6].data = 0x201C8200;
	} else if (tx_path == RF_PATH_B) {
		path_com_cr[0].data = 0x21C04900;
		path_com_cr[1].data = 0x00E4E032;
		path_com_cr[2].data = 0x39380C89;
		path_com_cr[3].data = 0x4E032240;
		path_com_cr[4].data = 0x80C8900E;
		path_com_cr[6].data = 0x201C0400;
	} else if (tx_path == RF_PATH_AB) {
		path_com_cr[0].data = 0x21C86900;
		path_com_cr[1].data = 0x00E4E433;
		path_com_cr[2].data = 0x39390CC9;
		path_com_cr[3].data = 0x4E433240;
		path_com_cr[4].data = 0x90CC900E;
		path_com_cr[6].data = 0x201C8600;
	} else {
		ret = -EINVAL;
	}

	for (i = 0; i < ARRAY_SIZE(path_com_cr); i++) {
		reg = rtw89_mac_reg_by_idx(rtwdev, path_com_cr[i].addr, phy_idx);
		rtw89_write32(rtwdev, reg, path_com_cr[i].data);
	}

	return ret;
}

static void rtw8922a_bb_reset(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
}

static int rtw8922a_cfg_rx_nss_limit(struct rtw89_dev *rtwdev, u8 rx_nss,
				     enum rtw89_phy_idx phy_idx)
{
	if (rx_nss == 1) {
		rtw89_phy_write32_idx(rtwdev, R_BRK_R, B_HTMCS_LMT, 0, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_R, B_VHTMCS_LMT, 0, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_HE, B_N_USR_MAX,
				      HE_N_USER_MAX_8922A, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_HE, B_NSS_MAX, 0, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_HE, B_TB_NSS_MAX, 0, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_EHT, B_RXEHT_NSS_MAX, 0, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_RXEHT, B_RXEHTTB_NSS_MAX, 0,
				      phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_RXEHT, B_RXEHT_N_USER_MAX,
				      HE_N_USER_MAX_8922A, phy_idx);
	} else if (rx_nss == 2) {
		rtw89_phy_write32_idx(rtwdev, R_BRK_R, B_HTMCS_LMT, 1, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_R, B_VHTMCS_LMT, 1, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_HE, B_N_USR_MAX,
				      HE_N_USER_MAX_8922A, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_HE, B_NSS_MAX, 1, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_HE, B_TB_NSS_MAX, 1, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_EHT, B_RXEHT_NSS_MAX, 1, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_RXEHT, B_RXEHTTB_NSS_MAX, 1,
				      phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_BRK_RXEHT, B_RXEHT_N_USER_MAX,
				      HE_N_USER_MAX_8922A, phy_idx);
	} else {
		return -EINVAL;
	}

	return 0;
}

static void rtw8922a_tssi_reset(struct rtw89_dev *rtwdev,
				enum rtw89_rf_path path,
				enum rtw89_phy_idx phy_idx)
{
	if (rtwdev->mlo_dbcc_mode == MLO_1_PLUS_1_1RF) {
		if (phy_idx == RTW89_PHY_0) {
			rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTA, B_TXPWR_RSTA, 0x0);
			rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTA, B_TXPWR_RSTA, 0x1);
		} else {
			rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB, B_TXPWR_RSTB, 0x0);
			rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB, B_TXPWR_RSTB, 0x1);
		}
	} else {
		rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTA, B_TXPWR_RSTA, 0x0);
		rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTA, B_TXPWR_RSTA, 0x1);
		rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB, B_TXPWR_RSTB, 0x0);
		rtw89_phy_write32_mask(rtwdev, R_TXPWR_RSTB, B_TXPWR_RSTB, 0x1);
	}
}

static int rtw8922a_ctrl_rx_path_tmac(struct rtw89_dev *rtwdev,
				      enum rtw89_rf_path rx_path,
				      enum rtw89_phy_idx phy_idx)
{
	u8 rx_nss = (rx_path == RF_PATH_AB) ? 2 : 1;

	/* Set to 0 first to avoid abnormal EDCCA report */
	rtw89_phy_write32_idx(rtwdev, R_ANT_CHBW, B_ANT_RX_SG0, 0x0, phy_idx);

	if (rx_path == RF_PATH_A) {
		rtw89_phy_write32_idx(rtwdev, R_ANT_CHBW, B_ANT_RX_SG0, 0x1, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_FC0INV_SBW, B_RX_1RCCA, 1, phy_idx);
		rtw8922a_cfg_rx_nss_limit(rtwdev, rx_nss, phy_idx);
		rtw8922a_tssi_reset(rtwdev, rx_path, phy_idx);
	} else if (rx_path == RF_PATH_B) {
		rtw89_phy_write32_idx(rtwdev, R_ANT_CHBW, B_ANT_RX_SG0, 0x2, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_FC0INV_SBW, B_RX_1RCCA, 2, phy_idx);
		rtw8922a_cfg_rx_nss_limit(rtwdev, rx_nss, phy_idx);
		rtw8922a_tssi_reset(rtwdev, rx_path, phy_idx);
	} else if (rx_path == RF_PATH_AB) {
		rtw89_phy_write32_idx(rtwdev, R_ANT_CHBW, B_ANT_RX_SG0, 0x3, phy_idx);
		rtw89_phy_write32_idx(rtwdev, R_FC0INV_SBW, B_RX_1RCCA, 3, phy_idx);
		rtw8922a_cfg_rx_nss_limit(rtwdev, rx_nss, phy_idx);
		rtw8922a_tssi_reset(rtwdev, rx_path, phy_idx);
	} else {
		return -EINVAL;
	}

	return 0;
}

static int rtw8922a_ctrl_mlo(struct rtw89_dev *rtwdev, enum rtw89_mlo_dbcc_mode mode)
{
	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
@@ -1130,6 +1290,85 @@ static void rtw8922a_set_channel(struct rtw89_dev *rtwdev,
	rtw8922a_set_channel_bb(rtwdev, chan, phy_idx);
}

static void rtw8922a_dfs_en_idx(struct rtw89_dev *rtwdev,
				enum rtw89_phy_idx phy_idx, enum rtw89_rf_path path,
				bool en)
{
	u32 path_ofst = (path == RF_PATH_B) ? 0x100 : 0x0;

	if (en)
		rtw89_phy_write32_idx(rtwdev, 0x2800 + path_ofst, BIT(1), 1,
				      phy_idx);
	else
		rtw89_phy_write32_idx(rtwdev, 0x2800 + path_ofst, BIT(1), 0,
				      phy_idx);
}

static void rtw8922a_dfs_en(struct rtw89_dev *rtwdev, bool en,
			    enum rtw89_phy_idx phy_idx)
{
	rtw8922a_dfs_en_idx(rtwdev, phy_idx, RF_PATH_A, en);
	rtw8922a_dfs_en_idx(rtwdev, phy_idx, RF_PATH_B, en);
}

static void rtw8922a_adc_en_path(struct rtw89_dev *rtwdev,
				 enum rtw89_rf_path path, bool en)
{
	u32 val;

	val = rtw89_phy_read32_mask(rtwdev, R_ADC_FIFO_V1, B_ADC_FIFO_EN_V1);

	if (en) {
		if (path == RF_PATH_A)
			val &= ~0x1;
		else
			val &= ~0x2;
	} else {
		if (path == RF_PATH_A)
			val |= 0x1;
		else
			val |= 0x2;
	}

	rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO_V1, B_ADC_FIFO_EN_V1, val);
}

static void rtw8922a_adc_en(struct rtw89_dev *rtwdev, bool en, u8 phy_idx)
{
	if (rtwdev->mlo_dbcc_mode == MLO_1_PLUS_1_1RF) {
		if (phy_idx == RTW89_PHY_0)
			rtw8922a_adc_en_path(rtwdev, RF_PATH_A, en);
		else
			rtw8922a_adc_en_path(rtwdev, RF_PATH_B, en);
	} else {
		rtw8922a_adc_en_path(rtwdev, RF_PATH_A, en);
		rtw8922a_adc_en_path(rtwdev, RF_PATH_B, en);
	}
}

static
void rtw8922a_hal_reset(struct rtw89_dev *rtwdev,
			enum rtw89_phy_idx phy_idx, enum rtw89_mac_idx mac_idx,
			enum rtw89_band band, u32 *tx_en, bool enter)
{
	if (enter) {
		rtw89_chip_stop_sch_tx(rtwdev, mac_idx, tx_en, RTW89_SCH_TX_SEL_ALL);
		rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, false);
		rtw8922a_dfs_en(rtwdev, false, phy_idx);
		rtw8922a_tssi_cont_en_phyidx(rtwdev, false, phy_idx);
		rtw8922a_adc_en(rtwdev, false, phy_idx);
		fsleep(40);
		rtw8922a_bb_reset_en(rtwdev, band, false, phy_idx);
	} else {
		rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, true);
		rtw8922a_adc_en(rtwdev, true, phy_idx);
		rtw8922a_dfs_en(rtwdev, true, phy_idx);
		rtw8922a_tssi_cont_en_phyidx(rtwdev, true, phy_idx);
		rtw8922a_bb_reset_en(rtwdev, band, true, phy_idx);
		rtw89_chip_resume_sch_tx(rtwdev, mac_idx, *tx_en);
	}
}

static void rtw8922a_set_txpwr_ref(struct rtw89_dev *rtwdev,
				   enum rtw89_phy_idx phy_idx)
{
@@ -1188,6 +1427,19 @@ static void rtw8922a_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
	rtw8922a_set_txpwr_ref(rtwdev, phy_idx);
}

static void rtw8922a_ctrl_trx_path(struct rtw89_dev *rtwdev,
				   enum rtw89_rf_path tx_path, u8 tx_nss,
				   enum rtw89_rf_path rx_path, u8 rx_nss)
{
	enum rtw89_phy_idx phy_idx;

	for (phy_idx = RTW89_PHY_0; phy_idx <= RTW89_PHY_1; phy_idx++) {
		rtw8922a_ctrl_tx_path_tmac(rtwdev, tx_path, phy_idx);
		rtw8922a_ctrl_rx_path_tmac(rtwdev, rx_path, phy_idx);
		rtw8922a_cfg_rx_nss_limit(rtwdev, rx_nss, phy_idx);
	}
}

static void rtw8922a_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en,
				     enum rtw89_phy_idx phy_idx)
{
@@ -1250,6 +1502,32 @@ static void rtw8922a_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en,
	}
}

static void rtw8922a_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
{
	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
	enum rtw89_band band = chan->band_type;
	struct rtw89_hal *hal = &rtwdev->hal;
	u8 ntx_path = RF_PATH_AB;
	u32 tx_en0, tx_en1;

	if (hal->antenna_tx == RF_A)
		ntx_path = RF_PATH_A;
	else if (hal->antenna_tx == RF_B)
		ntx_path = RF_PATH_B;

	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_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, false);
	if (rtwdev->dbcc_en)
		rtw8922a_hal_reset(rtwdev, RTW89_PHY_1, RTW89_MAC_1, band,
				   &tx_en0, false);
}

static void rtw8922a_fill_freq_with_ppdu(struct rtw89_dev *rtwdev,
					 struct rtw89_rx_phy_ppdu *phy_ppdu,
					 struct ieee80211_rx_status *status)
@@ -1326,6 +1604,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
	.ctrl_btg_bt_rx		= rtw8922a_ctrl_btg_bt_rx,
	.query_ppdu		= rtw8922a_query_ppdu,
	.ctrl_nbtg_bt_tx	= rtw8922a_ctrl_nbtg_bt_tx,
	.cfg_txrx_path		= rtw8922a_bb_cfg_txrx_path,
	.set_txpwr_ul_tb_offset	= NULL,
	.pwr_on_func		= rtw8922a_pwr_on_func,
	.pwr_off_func		= rtw8922a_pwr_off_func,
+33 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2023  Realtek Corporation
 */

#include "debug.h"
#include "phy.h"
#include "reg.h"
#include "rtw8922a.h"
#include "rtw8922a_rfk.h"

static void rtw8922a_tssi_cont_en(struct rtw89_dev *rtwdev, bool en,
				  enum rtw89_rf_path path)
{
	static const u32 tssi_trk_man[2] = {R_TSSI_PWR_P0, R_TSSI_PWR_P1};

	if (en)
		rtw89_phy_write32_mask(rtwdev, tssi_trk_man[path], B_TSSI_CONT_EN, 0);
	else
		rtw89_phy_write32_mask(rtwdev, tssi_trk_man[path], B_TSSI_CONT_EN, 1);
}

void rtw8922a_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, u8 phy_idx)
{
	if (rtwdev->mlo_dbcc_mode == MLO_1_PLUS_1_1RF) {
		if (phy_idx == RTW89_PHY_0)
			rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_A);
		else
			rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_B);
	} else {
		rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_A);
		rtw8922a_tssi_cont_en(rtwdev, en, RF_PATH_B);
	}
}
+12 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/* Copyright(c) 2023  Realtek Corporation
 */

#ifndef __RTW89_8922A_RFK_H__
#define __RTW89_8922A_RFK_H__

#include "core.h"

void rtw8922a_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, u8 phy_idx);

#endif