wifi: rtw89: 8922a: add set_channel MAC part
authorPing-Ke Shih <pkshih@realtek.com>
Thu, 15 Feb 2024 05:57:38 +0000 (13:57 +0800)
committerKalle Valo <kvalo@kernel.org>
Mon, 19 Feb 2024 16:20:59 +0000 (18:20 +0200)
To set channel, add a function to get TXSB (TX subband) that is hardware
index to indicate primary channel. Then, configure band, channel,
bandwidth and TXSB via registers.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20240215055741.14148-2-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/phy.c
drivers/net/wireless/realtek/rtw89/phy.h
drivers/net/wireless/realtek/rtw89/reg.h
drivers/net/wireless/realtek/rtw89/rtw8922a.c

index 81f73821e3fc07582f564c69175e8179b1b20ca6..dfbf59895e4ed7bb14b69a88fb0fd9bf153bf9bf 100644 (file)
@@ -725,6 +725,53 @@ u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
 }
 EXPORT_SYMBOL(rtw89_phy_get_txsc);
 
+u8 rtw89_phy_get_txsb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
+                     enum rtw89_bandwidth dbw)
+{
+       enum rtw89_bandwidth cbw = chan->band_width;
+       u8 pri_ch = chan->primary_channel;
+       u8 central_ch = chan->channel;
+       u8 txsb_idx = 0;
+
+       if (cbw == dbw || cbw == RTW89_CHANNEL_WIDTH_20)
+               return txsb_idx;
+
+       switch (cbw) {
+       case RTW89_CHANNEL_WIDTH_40:
+               txsb_idx = pri_ch > central_ch ? 1 : 0;
+               break;
+       case RTW89_CHANNEL_WIDTH_80:
+               if (dbw == RTW89_CHANNEL_WIDTH_20)
+                       txsb_idx = (pri_ch - central_ch + 6) / 4;
+               else
+                       txsb_idx = pri_ch > central_ch ? 1 : 0;
+               break;
+       case RTW89_CHANNEL_WIDTH_160:
+               if (dbw == RTW89_CHANNEL_WIDTH_20)
+                       txsb_idx = (pri_ch - central_ch + 14) / 4;
+               else if (dbw == RTW89_CHANNEL_WIDTH_40)
+                       txsb_idx = (pri_ch - central_ch + 12) / 8;
+               else
+                       txsb_idx = pri_ch > central_ch ? 1 : 0;
+               break;
+       case RTW89_CHANNEL_WIDTH_320:
+               if (dbw == RTW89_CHANNEL_WIDTH_20)
+                       txsb_idx = (pri_ch - central_ch + 30) / 4;
+               else if (dbw == RTW89_CHANNEL_WIDTH_40)
+                       txsb_idx = (pri_ch - central_ch + 28) / 8;
+               else if (dbw == RTW89_CHANNEL_WIDTH_80)
+                       txsb_idx = (pri_ch - central_ch + 24) / 16;
+               else
+                       txsb_idx = pri_ch > central_ch ? 1 : 0;
+               break;
+       default:
+               break;
+       }
+
+       return txsb_idx;
+}
+EXPORT_SYMBOL(rtw89_phy_get_txsb);
+
 static bool rtw89_phy_check_swsi_busy(struct rtw89_dev *rtwdev)
 {
        return !!rtw89_phy_read32_mask(rtwdev, R_SWSI_V1, B_SWSI_W_BUSY_V1) ||
index 76234daab896d355fedaaaf4aa97b920253a450c..de19f1c7f93123cbf6f840320dd684bb07b537c6 100644 (file)
@@ -778,6 +778,8 @@ void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
 u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
                      const struct rtw89_chan *chan,
                      enum rtw89_bandwidth dbw);
+u8 rtw89_phy_get_txsb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
+                     enum rtw89_bandwidth dbw);
 u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
                      u32 addr, u32 mask);
 u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
index 23a09efabab7c4cdfc033ea1efb737f3b93f3b15..ae637203ee8aa4b5e07c26ada76c8d1fc4da217c 100644 (file)
                        B_BE_RMAC_CKEN | B_BE_TXTIME_CKEN | B_BE_RESP_PKTCTL_CKEN | \
                        B_BE_SIGB_CKEN)
 
+#define R_BE_WMAC_RFMOD 0x10010
+#define R_BE_WMAC_RFMOD_C1 0x14010
+#define B_BE_CMAC_ASSERTION BIT(31)
+#define B_BE_WMAC_RFMOD_MASK GENMASK(2, 0)
+#define BE_WMAC_RFMOD_20M 0
+#define BE_WMAC_RFMOD_40M 1
+#define BE_WMAC_RFMOD_80M 2
+#define BE_WMAC_RFMOD_160M 3
+#define BE_WMAC_RFMOD_320M 4
+
 #define R_BE_TX_SUB_BAND_VALUE 0x10088
 #define R_BE_TX_SUB_BAND_VALUE_C1 0x14088
 #define B_BE_PRI20_BITMAP_MASK GENMASK(31, 16)
 #define B_BE_MACTX_LATENCY_MASK GENMASK(10, 8)
 #define B_BE_PREBKF_TIME_MASK GENMASK(4, 0)
 
+#define R_BE_PREBKF_CFG_1 0x1033C
+#define R_BE_PREBKF_CFG_1_C1 0x1433C
+#define B_BE_SIFS_TIMEOUT_TB_AGGR_MASK GENMASK(31, 24)
+#define B_BE_SIFS_PREBKF_MASK GENMASK(23, 16)
+#define B_BE_SIFS_TIMEOUT_T2_MASK GENMASK(14, 8)
+#define B_BE_SIFS_MACTXEN_T1_MASK GENMASK(6, 0)
+
 #define R_BE_CCA_CFG_0 0x10340
 #define R_BE_CCA_CFG_0_C1 0x14340
 #define B_BE_R_SIFS_AGGR_TIME_V1_MASK GENMASK(31, 24)
 
 #define R_BE_MUEDCA_EN 0x10370
 #define R_BE_MUEDCA_EN_C1 0x14370
+#define B_BE_SIFS_TIMEOUT_TB_T2_MASK GENMASK(30, 24)
+#define B_BE_SIFS_MACTXEN_TB_T1_MASK GENMASK(22, 16)
 #define B_BE_MUEDCA_WMM_SEL BIT(8)
-#define B_BE_SET_MUEDCATIMER_TF_1 BIT(5)
+#define B_BE_SET_MUEDCATIMER_TF_MASK GENMASK(5, 4)
 #define B_BE_SET_MUEDCATIMER_TF_0 BIT(4)
+#define B_BE_MUEDCA_EN_MASK GENMASK(1, 0)
 #define B_BE_MUEDCA_EN_0 BIT(0)
 
 #define R_BE_CTN_DRV_TXEN 0x10398
 #define B_BE_SPEC_SIFS_OFDM_PTCL_MASK GENMASK(15, 8)
 #define B_BE_SPEC_SIFS_CCK_PTCL_MASK GENMASK(7, 0)
 
+#define R_BE_TXRATE_CHK 0x10828
+#define R_BE_TXRATE_CHK_C1 0x14828
+#define B_BE_LATENCY_PADDING_PKT_TH_MASK GENMASK(31, 24)
+#define B_BE_PLCP_FETCH_BUFF_MASK GENMASK(23, 16)
+#define B_BE_OFDM_CCK_ERR_PROC BIT(6)
+#define B_BE_PKT_LAST_TX BIT(5)
+#define B_BE_BAND_MODE BIT(4)
+#define B_BE_MAX_TXNSS_MASK GENMASK(3, 2)
+#define B_BE_RTS_LIMIT_IN_OFDM6 BIT(1)
+#define B_BE_CHECK_CCK_EN BIT(0)
+
 #define R_BE_MBSSID_DROP_0 0x1083C
 #define R_BE_MBSSID_DROP_0_C1 0x1483C
 #define B_BE_GI_LTF_FB_SEL BIT(30)
index 2f1e7767d58a05bfe3512d9d411687e23979a9c8..ac6fed211070bd59853b8858a45fcda26e0d4527 100644 (file)
@@ -771,6 +771,97 @@ static void rtw8922a_power_trim(struct rtw89_dev *rtwdev)
        rtw8922a_pad_bias_trim(rtwdev);
 }
 
+static void rtw8922a_set_channel_mac(struct rtw89_dev *rtwdev,
+                                    const struct rtw89_chan *chan,
+                                    u8 mac_idx)
+{
+       u32 sub_carr = rtw89_mac_reg_by_idx(rtwdev, R_BE_TX_SUB_BAND_VALUE, mac_idx);
+       u32 chk_rate = rtw89_mac_reg_by_idx(rtwdev, R_BE_TXRATE_CHK, mac_idx);
+       u32 rf_mod = rtw89_mac_reg_by_idx(rtwdev, R_BE_WMAC_RFMOD, mac_idx);
+       u8 txsb20 = 0, txsb40 = 0, txsb80 = 0;
+       u8 rf_mod_val, chk_rate_mask;
+       u32 txsb;
+       u32 reg;
+
+       switch (chan->band_width) {
+       case RTW89_CHANNEL_WIDTH_160:
+               txsb80 = rtw89_phy_get_txsb(rtwdev, chan, RTW89_CHANNEL_WIDTH_80);
+               fallthrough;
+       case RTW89_CHANNEL_WIDTH_80:
+               txsb40 = rtw89_phy_get_txsb(rtwdev, chan, RTW89_CHANNEL_WIDTH_40);
+               fallthrough;
+       case RTW89_CHANNEL_WIDTH_40:
+               txsb20 = rtw89_phy_get_txsb(rtwdev, chan, RTW89_CHANNEL_WIDTH_20);
+               break;
+       default:
+               break;
+       }
+
+       switch (chan->band_width) {
+       case RTW89_CHANNEL_WIDTH_160:
+               rf_mod_val = BE_WMAC_RFMOD_160M;
+               txsb = u32_encode_bits(txsb20, B_BE_TXSB_20M_MASK) |
+                      u32_encode_bits(txsb40, B_BE_TXSB_40M_MASK) |
+                      u32_encode_bits(txsb80, B_BE_TXSB_80M_MASK);
+               break;
+       case RTW89_CHANNEL_WIDTH_80:
+               rf_mod_val = BE_WMAC_RFMOD_80M;
+               txsb = u32_encode_bits(txsb20, B_BE_TXSB_20M_MASK) |
+                      u32_encode_bits(txsb40, B_BE_TXSB_40M_MASK);
+               break;
+       case RTW89_CHANNEL_WIDTH_40:
+               rf_mod_val = BE_WMAC_RFMOD_40M;
+               txsb = u32_encode_bits(txsb20, B_BE_TXSB_20M_MASK);
+               break;
+       case RTW89_CHANNEL_WIDTH_20:
+       default:
+               rf_mod_val = BE_WMAC_RFMOD_20M;
+               txsb = 0;
+               break;
+       }
+
+       if (txsb20 <= BE_PRI20_BITMAP_MAX)
+               txsb |= u32_encode_bits(BIT(txsb20), B_BE_PRI20_BITMAP_MASK);
+
+       rtw89_write8_mask(rtwdev, rf_mod, B_BE_WMAC_RFMOD_MASK, rf_mod_val);
+       rtw89_write32(rtwdev, sub_carr, txsb);
+
+       switch (chan->band_type) {
+       case RTW89_BAND_2G:
+               chk_rate_mask = B_BE_BAND_MODE;
+               break;
+       case RTW89_BAND_5G:
+       case RTW89_BAND_6G:
+               chk_rate_mask = B_BE_CHECK_CCK_EN | B_BE_RTS_LIMIT_IN_OFDM6;
+               break;
+       default:
+               rtw89_warn(rtwdev, "Invalid band_type:%d\n", chan->band_type);
+               return;
+       }
+
+       rtw89_write8_clr(rtwdev, chk_rate, B_BE_BAND_MODE | B_BE_CHECK_CCK_EN |
+                                          B_BE_RTS_LIMIT_IN_OFDM6);
+       rtw89_write8_set(rtwdev, chk_rate, chk_rate_mask);
+
+       switch (chan->band_width) {
+       case RTW89_CHANNEL_WIDTH_320:
+       case RTW89_CHANNEL_WIDTH_160:
+       case RTW89_CHANNEL_WIDTH_80:
+       case RTW89_CHANNEL_WIDTH_40:
+               reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_PREBKF_CFG_1, mac_idx);
+               rtw89_write32_mask(rtwdev, reg, B_BE_SIFS_MACTXEN_T1_MASK, 0x41);
+               reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_MUEDCA_EN, mac_idx);
+               rtw89_write32_mask(rtwdev, reg, B_BE_SIFS_MACTXEN_TB_T1_MASK, 0x41);
+               break;
+       default:
+               reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_PREBKF_CFG_1, mac_idx);
+               rtw89_write32_mask(rtwdev, reg, B_BE_SIFS_MACTXEN_T1_MASK, 0x3f);
+               reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_MUEDCA_EN, mac_idx);
+               rtw89_write32_mask(rtwdev, reg, B_BE_SIFS_MACTXEN_TB_T1_MASK, 0x3e);
+               break;
+       }
+}
+
 struct rtw8922a_bb_gain {
        u32 gain_g[BB_PATH_NUM_8922A];
        u32 gain_a[BB_PATH_NUM_8922A];
@@ -1298,6 +1389,7 @@ static void rtw8922a_set_channel(struct rtw89_dev *rtwdev,
                                 enum rtw89_mac_idx mac_idx,
                                 enum rtw89_phy_idx phy_idx)
 {
+       rtw8922a_set_channel_mac(rtwdev, chan, mac_idx);
        rtw8922a_set_channel_bb(rtwdev, chan, phy_idx);
 }