#define CFGCH_BAND1_2G 0
 #define CFGCH_BAND1_5G 1
 #define CFGCH_BAND1_6G 3
+#define RR_CFGCH_POW_LCK BIT(15)
+#define RR_CFGCH_TRX_AH BIT(14)
+#define RR_CFGCH_BCN BIT(13)
+#define RR_CFGCH_BW2 BIT(12)
 #define RR_CFGCH_BAND0 GENMASK(9, 8)
 #define CFGCH_BAND0_2G 0
 #define CFGCH_BAND0_5G 1
 #define RR_TIA_N6 BIT(8)
 #define RR_MIXER 0x9f
 #define RR_MIXER_GN GENMASK(4, 3)
+#define RR_POW 0xa0
+#define RR_POW_SYN GENMASK(3, 2)
 #define RR_LOGEN 0xa3
 #define RR_LOGEN_RPT GENMASK(19, 16)
+#define RR_SX 0xaf
+#define RR_LDO 0xb1
+#define RR_LDO_SEL GENMASK(8, 6)
+#define RR_VCO 0xb2
+#define RR_LPF 0xb7
+#define RR_LPF_BUSY BIT(8)
 #define RR_XTALX2 0xb8
 #define RR_MALSEL 0xbe
+#define RR_SYNFB 0xc5
+#define RR_SYNFB_LK BIT(15)
+#define RR_LCKST 0xcf
+#define RR_LCKST_BIN BIT(0)
 #define RR_LCK_TRG 0xd3
 #define RR_LCK_TRGSEL BIT(8)
+#define RR_MMD 0xd5
+#define RR_MMD_RST_EN BIT(8)
+#define RR_MMD_RST_SYN BIT(6)
 #define RR_IQKPLL 0xdc
 #define RR_IQKPLL_MOD GENMASK(9, 8)
+#define RR_SYNLUT 0xdd
+#define RR_SYNLUT_MOD BIT(4)
 #define RR_RCKD 0xde
 #define RR_RCKD_POW GENMASK(19, 13)
 #define RR_RCKD_BW BIT(2)
 #define R_P0_RFMODE 0x12AC
 #define B_P0_RFMODE_ORI_TXRX_FTM_TX GENMASK(31, 4)
 #define B_P0_RFMODE_MUX GENMASK(11, 4)
+#define R_P0_RFMODE_ORI_RX 0x12AC
+#define B_P0_RFMODE_ORI_RX_ALL GENMASK(23, 12)
 #define R_P0_NRBW 0x12B8
 #define B_P0_NRBW_DBG BIT(30)
 #define R_S0_RXDC 0x12D4
 #define B_RXCCA_DIS_V1 BIT(0)
 #define R_RXSC 0x237C
 #define B_RXSC_EN BIT(0)
+#define R_RX_RPL_OFST 0x23AC
+#define B_RX_RPL_OFST_CCK_MASK GENMASK(6, 0)
 #define R_RXSCOBC 0x23B0
 #define B_RXSCOBC_TH GENMASK(18, 0)
 #define R_RXSCOCCK 0x23B4
 #define R_P1_RFMODE 0x32AC
 #define B_P1_RFMODE_ORI_TXRX_FTM_TX GENMASK(31, 4)
 #define B_P1_RFMODE_MUX GENMASK(11, 4)
+#define R_P1_RFMODE_ORI_RX 0x32AC
+#define B_P1_RFMODE_ORI_RX_ALL GENMASK(23, 12)
 #define R_P1_DBGMOD 0x32B8
 #define B_P1_DBGMOD_ON BIT(30)
 #define R_S1_RXDC 0x32D4
 #define R_T2F_GI_COMB 0x4424
 #define B_T2F_GI_COMB_EN BIT(2)
 #define R_BT_DYN_DC_EST_EN 0x441C
+#define R_BT_DYN_DC_EST_EN_V1 0x4420
 #define B_BT_DYN_DC_EST_EN_MSK BIT(31)
+#define R_ASSIGN_SBD_OPT_V1 0x4440
+#define B_ASSIGN_SBD_OPT_EN_V1 BIT(31)
 #define R_ASSIGN_SBD_OPT 0x4450
 #define B_ASSIGN_SBD_OPT_EN BIT(24)
 #define R_DCFO_COMP_S0 0x448C
 #define R_2P4G_BAND 0x4970
 #define B_2P4G_BAND_SEL BIT(1)
 #define R_FC0_BW 0x4974
-#define B_FC0_BW_INV GENMASK(6, 0)
+#define R_FC0_BW_V1 0x49C0
 #define B_FC0_BW_SET GENMASK(31, 30)
 #define B_ANT_RX_BT_SEG0 GENMASK(25, 22)
 #define B_ANT_RX_1RCCA_SEG1 GENMASK(21, 18)
 #define B_ANT_RX_1RCCA_SEG0 GENMASK(17, 14)
+#define B_FC0_BW_INV GENMASK(6, 0)
 #define R_CHBW_MOD 0x4978
+#define R_CHBW_MOD_V1 0x49C4
 #define B_BT_SHARE BIT(14)
 #define B_CHBW_MOD_SBW GENMASK(13, 12)
 #define B_CHBW_MOD_PRICH GENMASK(11, 8)
 #define B_ANT_RX_SEG0 GENMASK(3, 0)
+#define R_P0_RPL1 0x49B0
+#define B_P0_RPL1_41_MASK GENMASK(31, 24)
+#define B_P0_RPL1_40_MASK GENMASK(23, 16)
+#define B_P0_RPL1_20_MASK GENMASK(15, 8)
+#define B_P0_RPL1_MASK (B_P0_RPL1_41_MASK | B_P0_RPL1_40_MASK | B_P0_RPL1_20_MASK)
+#define B_P0_RPL1_SHIFT 8
+#define B_P0_RPL1_BIAS_MASK GENMASK(7, 0)
+#define R_P0_RPL2 0x49B4
+#define B_P0_RTL2_8A_MASK GENMASK(31, 24)
+#define B_P0_RTL2_81_MASK GENMASK(23, 16)
+#define B_P0_RTL2_80_MASK GENMASK(15, 8)
+#define B_P0_RTL2_42_MASK GENMASK(7, 0)
+#define R_P0_RPL3 0x49B8
+#define B_P0_RTL3_89_MASK GENMASK(31, 24)
+#define B_P0_RTL3_84_MASK GENMASK(23, 16)
+#define B_P0_RTL3_83_MASK GENMASK(15, 8)
+#define B_P0_RTL3_82_MASK GENMASK(7, 0)
 #define R_PD_BOOST_EN 0x49E8
 #define B_PD_BOOST_EN BIT(7)
 #define R_P1_BACKOFF_IBADC_V1 0x49F0
 #define B_P1_BACKOFF_IBADC_V1 GENMASK(31, 26)
+#define R_P1_RPL1 0x4A00
+#define R_P1_RPL2 0x4A04
+#define R_P1_RPL3 0x4A08
 #define R_BK_FC0_INV_V1 0x4A1C
 #define B_BK_FC0_INV_MSK_V1 GENMASK(18, 0)
 #define R_CCK_FC0_INV_V1 0x4A20
 #define B_P1_AGC_EN BIT(31)
 #define R_PATH1_TIA_INIT_V1 0x4AA8
 #define B_PATH1_TIA_INIT_IDX_MSK_V1 BIT(9)
+#define R_P0_AGC_RSVD 0x4ACC
 #define R_PATH0_RXBB_V1 0x4AD4
 #define B_PATH0_RXBB_MSK_V1 GENMASK(31, 0)
+#define R_P1_AGC_RSVD 0x4AD8
 #define R_PATH1_RXBB_V1 0x4AE0
 #define B_PATH1_RXBB_MSK_V1 GENMASK(31, 0)
 #define R_PATH0_BT_BACKOFF_V1 0x4AE4
 #define B_PATH0_NOTCH2_EN BIT(12)
 #define B_PATH0_NOTCH2_VAL GENMASK(11, 0)
 #define R_PATH0_5MDET 0x4C4C
+#define R_PATH0_5MDET_V1 0x46F8
 #define B_PATH0_5MDET_EN BIT(12)
 #define B_PATH0_5MDET_SB2 BIT(8)
 #define B_PATH0_5MDET_SB0 BIT(6)
 #define B_PATH1_NOTCH2_EN BIT(12)
 #define B_PATH1_NOTCH2_VAL GENMASK(11, 0)
 #define R_PATH1_5MDET 0x4D10
+#define R_PATH1_5MDET_V1 0x47B8
 #define B_PATH1_5MDET_EN BIT(12)
 #define B_PATH1_5MDET_SB2 BIT(8)
 #define B_PATH1_5MDET_SB0 BIT(6)
 
 #include "phy.h"
 #include "reg.h"
 #include "rtw8852b.h"
+#include "rtw8852b_rfk.h"
 #include "rtw8852b_table.h"
 #include "txrx.h"
 
        rtw8852b_pa_bias_trim(rtwdev);
 }
 
+static void rtw8852b_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);
+       u8 txsc20 = 0, txsc40 = 0;
+
+       switch (chan->band_width) {
+       case RTW89_CHANNEL_WIDTH_80:
+               txsc40 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_40);
+               fallthrough;
+       case RTW89_CHANNEL_WIDTH_40:
+               txsc20 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_20);
+               break;
+       default:
+               break;
+       }
+
+       switch (chan->band_width) {
+       case RTW89_CHANNEL_WIDTH_80:
+               rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(1));
+               rtw89_write32(rtwdev, sub_carr, txsc20 | (txsc40 << 4));
+               break;
+       case RTW89_CHANNEL_WIDTH_40:
+               rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(0));
+               rtw89_write32(rtwdev, sub_carr, txsc20);
+               break;
+       case RTW89_CHANNEL_WIDTH_20:
+               rtw89_write8_clr(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK);
+               rtw89_write32(rtwdev, sub_carr, 0);
+               break;
+       default:
+               break;
+       }
+
+       if (chan->channel > 14) {
+               rtw89_write8_clr(rtwdev, chk_rate, B_AX_BAND_MODE);
+               rtw89_write8_set(rtwdev, chk_rate,
+                                B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6);
+       } else {
+               rtw89_write8_set(rtwdev, chk_rate, B_AX_BAND_MODE);
+               rtw89_write8_clr(rtwdev, chk_rate,
+                                B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6);
+       }
+}
+
+static const u32 rtw8852b_sco_barker_threshold[14] = {
+       0x1cfea, 0x1d0e1, 0x1d1d7, 0x1d2cd, 0x1d3c3, 0x1d4b9, 0x1d5b0, 0x1d6a6,
+       0x1d79c, 0x1d892, 0x1d988, 0x1da7f, 0x1db75, 0x1ddc4
+};
+
+static const u32 rtw8852b_sco_cck_threshold[14] = {
+       0x27de3, 0x27f35, 0x28088, 0x281da, 0x2832d, 0x2847f, 0x285d2, 0x28724,
+       0x28877, 0x289c9, 0x28b1c, 0x28c6e, 0x28dc1, 0x290ed
+};
+
+static void rtw8852b_ctrl_sco_cck(struct rtw89_dev *rtwdev, u8 primary_ch)
+{
+       u8 ch_element = primary_ch - 1;
+
+       rtw89_phy_write32_mask(rtwdev, R_RXSCOBC, B_RXSCOBC_TH,
+                              rtw8852b_sco_barker_threshold[ch_element]);
+       rtw89_phy_write32_mask(rtwdev, R_RXSCOCCK, B_RXSCOCCK_TH,
+                              rtw8852b_sco_cck_threshold[ch_element]);
+}
+
+static u8 rtw8852b_sco_mapping(u8 central_ch)
+{
+       if (central_ch == 1)
+               return 109;
+       else if (central_ch >= 2 && central_ch <= 6)
+               return 108;
+       else if (central_ch >= 7 && central_ch <= 10)
+               return 107;
+       else if (central_ch >= 11 && central_ch <= 14)
+               return 106;
+       else if (central_ch == 36 || central_ch == 38)
+               return 51;
+       else if (central_ch >= 40 && central_ch <= 58)
+               return 50;
+       else if (central_ch >= 60 && central_ch <= 64)
+               return 49;
+       else if (central_ch == 100 || central_ch == 102)
+               return 48;
+       else if (central_ch >= 104 && central_ch <= 126)
+               return 47;
+       else if (central_ch >= 128 && central_ch <= 151)
+               return 46;
+       else if (central_ch >= 153 && central_ch <= 177)
+               return 45;
+       else
+               return 0;
+}
+
+struct rtw8852b_bb_gain {
+       u32 gain_g[BB_PATH_NUM_8852B];
+       u32 gain_a[BB_PATH_NUM_8852B];
+       u32 gain_mask;
+};
+
+static const struct rtw8852b_bb_gain bb_gain_lna[LNA_GAIN_NUM] = {
+       { .gain_g = {0x4678, 0x475C}, .gain_a = {0x45DC, 0x4740},
+         .gain_mask = 0x00ff0000 },
+       { .gain_g = {0x4678, 0x475C}, .gain_a = {0x45DC, 0x4740},
+         .gain_mask = 0xff000000 },
+       { .gain_g = {0x467C, 0x4760}, .gain_a = {0x4660, 0x4744},
+         .gain_mask = 0x000000ff },
+       { .gain_g = {0x467C, 0x4760}, .gain_a = {0x4660, 0x4744},
+         .gain_mask = 0x0000ff00 },
+       { .gain_g = {0x467C, 0x4760}, .gain_a = {0x4660, 0x4744},
+         .gain_mask = 0x00ff0000 },
+       { .gain_g = {0x467C, 0x4760}, .gain_a = {0x4660, 0x4744},
+         .gain_mask = 0xff000000 },
+       { .gain_g = {0x4680, 0x4764}, .gain_a = {0x4664, 0x4748},
+         .gain_mask = 0x000000ff },
+};
+
+static const struct rtw8852b_bb_gain bb_gain_tia[TIA_GAIN_NUM] = {
+       { .gain_g = {0x4680, 0x4764}, .gain_a = {0x4664, 0x4748},
+         .gain_mask = 0x00ff0000 },
+       { .gain_g = {0x4680, 0x4764}, .gain_a = {0x4664, 0x4748},
+         .gain_mask = 0xff000000 },
+};
+
+static void rtw8852b_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;
+       u8 gain_band = rtw89_subband_to_bb_gain_band(subband);
+       s32 val;
+       u32 reg;
+       u32 mask;
+       int i;
+
+       for (i = 0; i < LNA_GAIN_NUM; i++) {
+               if (subband == RTW89_CH_2G)
+                       reg = bb_gain_lna[i].gain_g[path];
+               else
+                       reg = bb_gain_lna[i].gain_a[path];
+
+               mask = bb_gain_lna[i].gain_mask;
+               val = gain->lna_gain[gain_band][path][i];
+               rtw89_phy_write32_mask(rtwdev, reg, mask, val);
+       }
+
+       for (i = 0; i < TIA_GAIN_NUM; i++) {
+               if (subband == RTW89_CH_2G)
+                       reg = bb_gain_tia[i].gain_g[path];
+               else
+                       reg = bb_gain_tia[i].gain_a[path];
+
+               mask = bb_gain_tia[i].gain_mask;
+               val = gain->tia_gain[gain_band][path][i];
+               rtw89_phy_write32_mask(rtwdev, reg, mask, val);
+       }
+}
+
+static void rtw8852b_set_gain_offset(struct rtw89_dev *rtwdev,
+                                    enum rtw89_subband subband,
+                                    enum rtw89_phy_idx phy_idx)
+{
+       static const u32 gain_err_addr[2] = {R_P0_AGC_RSVD, R_P1_AGC_RSVD};
+       static const u32 rssi_ofst_addr[2] = {R_PATH0_G_TIA1_LNA6_OP1DB_V1,
+                                             R_PATH1_G_TIA1_LNA6_OP1DB_V1};
+       struct rtw89_hal *hal = &rtwdev->hal;
+       struct rtw89_phy_efuse_gain *efuse_gain = &rtwdev->efuse_gain;
+       enum rtw89_gain_offset gain_ofdm_band;
+       s32 offset_a, offset_b;
+       s32 offset_ofdm, offset_cck;
+       s32 tmp;
+       u8 path;
+
+       if (!efuse_gain->comp_valid)
+               goto next;
+
+       for (path = RF_PATH_A; path < BB_PATH_NUM_8852B; path++) {
+               tmp = efuse_gain->comp[path][subband];
+               tmp = clamp_t(s32, tmp << 2, S8_MIN, S8_MAX);
+               rtw89_phy_write32_mask(rtwdev, gain_err_addr[path], MASKBYTE0, tmp);
+       }
+
+next:
+       if (!efuse_gain->offset_valid)
+               return;
+
+       gain_ofdm_band = rtw89_subband_to_gain_offset_band_of_ofdm(subband);
+
+       offset_a = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band];
+       offset_b = -efuse_gain->offset[RF_PATH_B][gain_ofdm_band];
+
+       tmp = -((offset_a << 2) + (efuse_gain->offset_base[RTW89_PHY_0] >> 2));
+       tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+       rtw89_phy_write32_mask(rtwdev, rssi_ofst_addr[RF_PATH_A], B_PATH0_R_G_OFST_MASK, tmp);
+
+       tmp = -((offset_b << 2) + (efuse_gain->offset_base[RTW89_PHY_0] >> 2));
+       tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+       rtw89_phy_write32_mask(rtwdev, rssi_ofst_addr[RF_PATH_B], B_PATH0_R_G_OFST_MASK, tmp);
+
+       if (hal->antenna_rx == RF_B) {
+               offset_ofdm = -efuse_gain->offset[RF_PATH_B][gain_ofdm_band];
+               offset_cck = -efuse_gain->offset[RF_PATH_B][0];
+       } else {
+               offset_ofdm = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band];
+               offset_cck = -efuse_gain->offset[RF_PATH_A][0];
+       }
+
+       tmp = (offset_ofdm << 4) + efuse_gain->offset_base[RTW89_PHY_0];
+       tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+       rtw89_phy_write32_idx(rtwdev, R_P0_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx);
+
+       tmp = (offset_ofdm << 4) + efuse_gain->rssi_base[RTW89_PHY_0];
+       tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX);
+       rtw89_phy_write32_idx(rtwdev, R_P1_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx);
+
+       if (subband == RTW89_CH_2G) {
+               tmp = (offset_cck << 3) + (efuse_gain->offset_base[RTW89_PHY_0] >> 1);
+               tmp = clamp_t(s32, tmp, S8_MIN >> 1, S8_MAX >> 1);
+               rtw89_phy_write32_mask(rtwdev, R_RX_RPL_OFST,
+                                      B_RX_RPL_OFST_CCK_MASK, tmp);
+       }
+}
+
+static
+void rtw8852b_set_rxsc_rpl_comp(struct rtw89_dev *rtwdev, enum rtw89_subband subband)
+{
+       const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain;
+       u8 band = rtw89_subband_to_bb_gain_band(subband);
+       u32 val;
+
+       val = FIELD_PREP(B_P0_RPL1_20_MASK, (gain->rpl_ofst_20[band][RF_PATH_A] +
+                                            gain->rpl_ofst_20[band][RF_PATH_B]) / 2) |
+             FIELD_PREP(B_P0_RPL1_40_MASK, (gain->rpl_ofst_40[band][RF_PATH_A][0] +
+                                            gain->rpl_ofst_40[band][RF_PATH_B][0]) / 2) |
+             FIELD_PREP(B_P0_RPL1_41_MASK, (gain->rpl_ofst_40[band][RF_PATH_A][1] +
+                                            gain->rpl_ofst_40[band][RF_PATH_B][1]) / 2);
+       val >>= B_P0_RPL1_SHIFT;
+       rtw89_phy_write32_mask(rtwdev, R_P0_RPL1, B_P0_RPL1_MASK, val);
+       rtw89_phy_write32_mask(rtwdev, R_P1_RPL1, B_P0_RPL1_MASK, val);
+
+       val = FIELD_PREP(B_P0_RTL2_42_MASK, (gain->rpl_ofst_40[band][RF_PATH_A][2] +
+                                            gain->rpl_ofst_40[band][RF_PATH_B][2]) / 2) |
+             FIELD_PREP(B_P0_RTL2_80_MASK, (gain->rpl_ofst_80[band][RF_PATH_A][0] +
+                                            gain->rpl_ofst_80[band][RF_PATH_B][0]) / 2) |
+             FIELD_PREP(B_P0_RTL2_81_MASK, (gain->rpl_ofst_80[band][RF_PATH_A][1] +
+                                            gain->rpl_ofst_80[band][RF_PATH_B][1]) / 2) |
+             FIELD_PREP(B_P0_RTL2_8A_MASK, (gain->rpl_ofst_80[band][RF_PATH_A][10] +
+                                            gain->rpl_ofst_80[band][RF_PATH_B][10]) / 2);
+       rtw89_phy_write32(rtwdev, R_P0_RPL2, val);
+       rtw89_phy_write32(rtwdev, R_P1_RPL2, val);
+
+       val = FIELD_PREP(B_P0_RTL3_82_MASK, (gain->rpl_ofst_80[band][RF_PATH_A][2] +
+                                            gain->rpl_ofst_80[band][RF_PATH_B][2]) / 2) |
+             FIELD_PREP(B_P0_RTL3_83_MASK, (gain->rpl_ofst_80[band][RF_PATH_A][3] +
+                                            gain->rpl_ofst_80[band][RF_PATH_B][3]) / 2) |
+             FIELD_PREP(B_P0_RTL3_84_MASK, (gain->rpl_ofst_80[band][RF_PATH_A][4] +
+                                            gain->rpl_ofst_80[band][RF_PATH_B][4]) / 2) |
+             FIELD_PREP(B_P0_RTL3_89_MASK, (gain->rpl_ofst_80[band][RF_PATH_A][9] +
+                                            gain->rpl_ofst_80[band][RF_PATH_B][9]) / 2);
+       rtw89_phy_write32(rtwdev, R_P0_RPL3, val);
+       rtw89_phy_write32(rtwdev, R_P1_RPL3, val);
+}
+
+static void rtw8852b_ctrl_ch(struct rtw89_dev *rtwdev,
+                            const struct rtw89_chan *chan,
+                            enum rtw89_phy_idx phy_idx)
+{
+       u8 central_ch = chan->channel;
+       u8 subband = chan->subband_type;
+       u8 sco_comp;
+       bool is_2g = central_ch <= 14;
+
+       /* Path A */
+       if (is_2g)
+               rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1,
+                                     B_PATH0_BAND_SEL_MSK_V1, 1, phy_idx);
+       else
+               rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1,
+                                     B_PATH0_BAND_SEL_MSK_V1, 0, phy_idx);
+
+       /* Path B */
+       if (is_2g)
+               rtw89_phy_write32_idx(rtwdev, R_PATH1_BAND_SEL_V1,
+                                     B_PATH1_BAND_SEL_MSK_V1, 1, phy_idx);
+       else
+               rtw89_phy_write32_idx(rtwdev, R_PATH1_BAND_SEL_V1,
+                                     B_PATH1_BAND_SEL_MSK_V1, 0, phy_idx);
+
+       /* SCO compensate FC setting */
+       sco_comp = rtw8852b_sco_mapping(central_ch);
+       rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_INV, sco_comp, phy_idx);
+
+       if (chan->band_type == RTW89_BAND_6G)
+               return;
+
+       /* CCK parameters */
+       if (central_ch == 14) {
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3b13ff);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x1c42de);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfdb0ad);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xf60f6e);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xfd8f92);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0x2d011);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0x1c02c);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xfff00a);
+       } else {
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3d23ff);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x29b354);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfc1c8);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xfdb053);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xf86f9a);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0xfaef92);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0xfe5fcc);
+               rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xffdff5);
+       }
+
+       rtw8852b_set_gain_error(rtwdev, subband, RF_PATH_A);
+       rtw8852b_set_gain_error(rtwdev, subband, RF_PATH_B);
+       rtw8852b_set_gain_offset(rtwdev, subband, phy_idx);
+       rtw8852b_set_rxsc_rpl_comp(rtwdev, subband);
+}
+
+static void rtw8852b_bw_setting(struct rtw89_dev *rtwdev, u8 bw, u8 path)
+{
+       static const u32 adc_sel[2] = {0xC0EC, 0xC1EC};
+       static const u32 wbadc_sel[2] = {0xC0E4, 0xC1E4};
+
+       switch (bw) {
+       case RTW89_CHANNEL_WIDTH_5:
+               rtw89_phy_write32_mask(rtwdev, adc_sel[path], 0x6000, 0x1);
+               rtw89_phy_write32_mask(rtwdev, wbadc_sel[path], 0x30, 0x0);
+               break;
+       case RTW89_CHANNEL_WIDTH_10:
+               rtw89_phy_write32_mask(rtwdev, adc_sel[path], 0x6000, 0x2);
+               rtw89_phy_write32_mask(rtwdev, wbadc_sel[path], 0x30, 0x1);
+               break;
+       case RTW89_CHANNEL_WIDTH_20:
+               rtw89_phy_write32_mask(rtwdev, adc_sel[path], 0x6000, 0x0);
+               rtw89_phy_write32_mask(rtwdev, wbadc_sel[path], 0x30, 0x2);
+               break;
+       case RTW89_CHANNEL_WIDTH_40:
+               rtw89_phy_write32_mask(rtwdev, adc_sel[path], 0x6000, 0x0);
+               rtw89_phy_write32_mask(rtwdev, wbadc_sel[path], 0x30, 0x2);
+               break;
+       case RTW89_CHANNEL_WIDTH_80:
+               rtw89_phy_write32_mask(rtwdev, adc_sel[path], 0x6000, 0x0);
+               rtw89_phy_write32_mask(rtwdev, wbadc_sel[path], 0x30, 0x2);
+               break;
+       default:
+               rtw89_warn(rtwdev, "Fail to set ADC\n");
+       }
+}
+
+static void rtw8852b_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_ch, u8 bw,
+                            enum rtw89_phy_idx phy_idx)
+{
+       u32 rx_path_0;
+
+       switch (bw) {
+       case RTW89_CHANNEL_WIDTH_5:
+               rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x1, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx);
+
+               /*Set RF mode at 3 */
+               rtw89_phy_write32_idx(rtwdev, R_P0_RFMODE_ORI_RX,
+                                     B_P0_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_P1_RFMODE_ORI_RX,
+                                     B_P1_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
+               break;
+       case RTW89_CHANNEL_WIDTH_10:
+               rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x2, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx);
+
+               /*Set RF mode at 3 */
+               rtw89_phy_write32_idx(rtwdev, R_P0_RFMODE_ORI_RX,
+                                     B_P0_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_P1_RFMODE_ORI_RX,
+                                     B_P1_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
+               break;
+       case RTW89_CHANNEL_WIDTH_20:
+               rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx);
+
+               /*Set RF mode at 3 */
+               rtw89_phy_write32_idx(rtwdev, R_P0_RFMODE_ORI_RX,
+                                     B_P0_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_P1_RFMODE_ORI_RX,
+                                     B_P1_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
+               break;
+       case RTW89_CHANNEL_WIDTH_40:
+               rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x1, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH,
+                                     pri_ch, phy_idx);
+
+               /*Set RF mode at 3 */
+               rtw89_phy_write32_idx(rtwdev, R_P0_RFMODE_ORI_RX,
+                                     B_P0_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_P1_RFMODE_ORI_RX,
+                                     B_P1_RFMODE_ORI_RX_ALL, 0x333, phy_idx);
+               /*CCK primary channel */
+               if (pri_ch == RTW89_SC_20_UPPER)
+                       rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 1);
+               else
+                       rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 0);
+
+               break;
+       case RTW89_CHANNEL_WIDTH_80:
+               rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x2, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH,
+                                     pri_ch, phy_idx);
+
+               /*Set RF mode at A */
+               rtw89_phy_write32_idx(rtwdev, R_P0_RFMODE_ORI_RX,
+                                     B_P0_RFMODE_ORI_RX_ALL, 0xaaa, phy_idx);
+               rtw89_phy_write32_idx(rtwdev, R_P1_RFMODE_ORI_RX,
+                                     B_P1_RFMODE_ORI_RX_ALL, 0xaaa, phy_idx);
+               break;
+       default:
+               rtw89_warn(rtwdev, "Fail to switch bw (bw:%d, pri ch:%d)\n", bw,
+                          pri_ch);
+       }
+
+       rtw8852b_bw_setting(rtwdev, bw, RF_PATH_A);
+       rtw8852b_bw_setting(rtwdev, bw, RF_PATH_B);
+
+       rx_path_0 = rtw89_phy_read32_idx(rtwdev, R_CHBW_MOD_V1, B_ANT_RX_SEG0,
+                                        phy_idx);
+       if (rx_path_0 == 0x1)
+               rtw89_phy_write32_idx(rtwdev, R_P1_RFMODE_ORI_RX,
+                                     B_P1_RFMODE_ORI_RX_ALL, 0x111, phy_idx);
+       else if (rx_path_0 == 0x2)
+               rtw89_phy_write32_idx(rtwdev, R_P0_RFMODE_ORI_RX,
+                                     B_P0_RFMODE_ORI_RX_ALL, 0x111, phy_idx);
+}
+
+static void rtw8852b_ctrl_cck_en(struct rtw89_dev *rtwdev, bool cck_en)
+{
+       if (cck_en) {
+               rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 1);
+               rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0);
+       } else {
+               rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 0);
+               rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 1);
+       }
+}
+
+static void rtw8852b_5m_mask(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
+                            enum rtw89_phy_idx phy_idx)
+{
+       u8 pri_ch = chan->primary_channel;
+       bool mask_5m_low;
+       bool mask_5m_en;
+
+       switch (chan->band_width) {
+       case RTW89_CHANNEL_WIDTH_40:
+               /* Prich=1: Mask 5M High, Prich=2: Mask 5M Low */
+               mask_5m_en = true;
+               mask_5m_low = pri_ch == 2;
+               break;
+       case RTW89_CHANNEL_WIDTH_80:
+               /* Prich=3: Mask 5M High, Prich=4: Mask 5M Low, Else: Disable */
+               mask_5m_en = pri_ch == 3 || pri_ch == 4;
+               mask_5m_low = pri_ch == 4;
+               break;
+       default:
+               mask_5m_en = false;
+               break;
+       }
+
+       if (!mask_5m_en) {
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_5MDET_V1, B_PATH1_5MDET_EN, 0x0);
+               rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1,
+                                     B_ASSIGN_SBD_OPT_EN_V1, 0x0, phy_idx);
+               return;
+       }
+
+       if (mask_5m_low) {
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x4);
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1);
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x1);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_5MDET_V1, B_PATH1_5MDET_TH, 0x4);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_5MDET_V1, B_PATH1_5MDET_EN, 0x1);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_5MDET_V1, B_PATH1_5MDET_SB2, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_5MDET_V1, B_PATH1_5MDET_SB0, 0x1);
+       } else {
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x4);
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1);
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x1);
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_5MDET_V1, B_PATH1_5MDET_TH, 0x4);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_5MDET_V1, B_PATH1_5MDET_EN, 0x1);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_5MDET_V1, B_PATH1_5MDET_SB2, 0x1);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_5MDET_V1, B_PATH1_5MDET_SB0, 0x0);
+       }
+       rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1,
+                             B_ASSIGN_SBD_OPT_EN_V1, 0x1, phy_idx);
+}
+
+static void rtw8852b_bb_reset_all(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+       rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx);
+       rtw89_phy_write32_idx(rtwdev, R_S1_HW_SI_DIS, B_S1_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx);
+       fsleep(1);
+       rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx);
+       rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx);
+       rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx);
+       rtw89_phy_write32_idx(rtwdev, R_S1_HW_SI_DIS, B_S1_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx);
+       rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx);
+}
+
+static void rtw8852b_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan,
+                                   enum rtw89_phy_idx phy_idx)
+{
+       bool cck_en = chan->channel <= 14;
+       u8 pri_ch_idx = chan->pri_ch_idx;
+
+       if (cck_en)
+               rtw8852b_ctrl_sco_cck(rtwdev,  chan->primary_channel);
+
+       rtw8852b_ctrl_ch(rtwdev, chan, phy_idx);
+       rtw8852b_ctrl_bw(rtwdev, pri_ch_idx, chan->band_width, phy_idx);
+       rtw8852b_ctrl_cck_en(rtwdev, cck_en);
+       if (chan->band_type == RTW89_BAND_5G) {
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1,
+                                      B_PATH0_BT_SHARE_V1, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1,
+                                      B_PATH0_BTG_PATH_V1, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_BT_SHARE_V1,
+                                      B_PATH1_BT_SHARE_V1, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_PATH1_BTG_PATH_V1,
+                                      B_PATH1_BTG_PATH_V1, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1,
+                                      B_BT_DYN_DC_EST_EN_MSK, 0x0);
+               rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0);
+       }
+       rtw89_phy_write32_mask(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0,
+                              chan->primary_channel);
+       rtw8852b_5m_mask(rtwdev, chan, phy_idx);
+       rtw8852b_bb_reset_all(rtwdev, phy_idx);
+}
+
+static void rtw8852b_set_channel(struct rtw89_dev *rtwdev,
+                                const struct rtw89_chan *chan,
+                                enum rtw89_mac_idx mac_idx,
+                                enum rtw89_phy_idx phy_idx)
+{
+       rtw8852b_set_channel_mac(rtwdev, chan, mac_idx);
+       rtw8852b_set_channel_bb(rtwdev, chan, phy_idx);
+       rtw8852b_set_channel_rf(rtwdev, chan, phy_idx);
+}
+
 static u32 rtw8852b_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
                                     enum rtw89_phy_idx phy_idx, s16 ref)
 {
 static const struct rtw89_chip_ops rtw8852b_chip_ops = {
        .enable_bb_rf           = rtw8852b_mac_enable_bb_rf,
        .disable_bb_rf          = rtw8852b_mac_disable_bb_rf,
+       .set_channel            = rtw8852b_set_channel,
        .read_efuse             = rtw8852b_read_efuse,
        .read_phycap            = rtw8852b_read_phycap,
        .power_trim             = rtw8852b_power_trim,
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2019-2022  Realtek Corporation
+ */
+
+#include "coex.h"
+#include "debug.h"
+#include "mac.h"
+#include "phy.h"
+#include "reg.h"
+#include "rtw8852b.h"
+#include "rtw8852b_rfk.h"
+#include "rtw8852b_rfk_table.h"
+#include "rtw8852b_table.h"
+
+static u8 _kpath(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
+{
+       u8 val;
+
+       rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]dbcc_en: %x,PHY%d\n",
+                   rtwdev->dbcc_en, phy_idx);
+
+       if (!rtwdev->dbcc_en) {
+               val = RF_AB;
+       } else {
+               if (phy_idx == RTW89_PHY_0)
+                       val = RF_A;
+               else
+                       val = RF_B;
+       }
+       return val;
+}
+
+static void _bw_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+                       enum rtw89_bandwidth bw, bool dav)
+{
+       u32 rf_reg18;
+       u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1;
+
+       rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__);
+
+       rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK);
+       if (rf_reg18 == INV_RF_DATA) {
+               rtw89_debug(rtwdev, RTW89_DBG_RFK,
+                           "[RFK]Invalid RF_0x18 for Path-%d\n", path);
+               return;
+       }
+       rf_reg18 &= ~RR_CFGCH_BW;
+
+       switch (bw) {
+       case RTW89_CHANNEL_WIDTH_5:
+       case RTW89_CHANNEL_WIDTH_10:
+       case RTW89_CHANNEL_WIDTH_20:
+               rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_20M);
+               break;
+       case RTW89_CHANNEL_WIDTH_40:
+               rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_40M);
+               break;
+       case RTW89_CHANNEL_WIDTH_80:
+               rf_reg18 |= FIELD_PREP(RR_CFGCH_BW, CFGCH_BW_80M);
+               break;
+       default:
+               rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]Fail to set CH\n");
+       }
+
+       rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN |
+                     RR_CFGCH_BW2) & RFREG_MASK;
+       rf_reg18 |= RR_CFGCH_BW2;
+       rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18);
+
+       rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set %x at path%d, %x =0x%x\n",
+                   bw, path, reg18_addr,
+                   rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK));
+}
+
+static void _ctrl_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+                    enum rtw89_bandwidth bw)
+{
+       _bw_setting(rtwdev, RF_PATH_A, bw, true);
+       _bw_setting(rtwdev, RF_PATH_B, bw, true);
+       _bw_setting(rtwdev, RF_PATH_A, bw, false);
+       _bw_setting(rtwdev, RF_PATH_B, bw, false);
+}
+
+static bool _set_s0_arfc18(struct rtw89_dev *rtwdev, u32 val)
+{
+       u32 bak;
+       u32 tmp;
+       int ret;
+
+       bak = rtw89_read_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK);
+       rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RR_LDO_SEL, 0x1);
+       rtw89_write_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK, val);
+
+       ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp == 0, 1, 1000,
+                                      false, rtwdev, RF_PATH_A, RR_LPF, RR_LPF_BUSY);
+       if (ret)
+               rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]LCK timeout\n");
+
+       rtw89_write_rf(rtwdev, RF_PATH_A, RR_LDO, RFREG_MASK, bak);
+
+       return !!ret;
+}
+
+static void _lck_check(struct rtw89_dev *rtwdev)
+{
+       u32 tmp;
+
+       if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
+               rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN MMD reset\n");
+
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x1);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x0);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_SYN, 0x1);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_MMD, RR_MMD_RST_EN, 0x0);
+       }
+
+       udelay(10);
+
+       if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
+               rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]re-set RF 0x18\n");
+
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
+               tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
+               _set_s0_arfc18(rtwdev, tmp);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0);
+       }
+
+       if (rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RR_SYNFB_LK) == 0) {
+               rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]SYN off/on\n");
+
+               tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RFREG_MASK, tmp);
+               tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_SX, RFREG_MASK, tmp);
+
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x1);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x0);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_POW, RR_POW_SYN, 0x3);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_SYNLUT, RR_SYNLUT_MOD, 0x0);
+
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x1);
+               tmp = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK);
+               _set_s0_arfc18(rtwdev, tmp);
+               rtw89_write_rf(rtwdev, RF_PATH_A, RR_LCK_TRG, RR_LCK_TRGSEL, 0x0);
+
+               rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]0xb2=%x, 0xc5=%x\n",
+                           rtw89_read_rf(rtwdev, RF_PATH_A, RR_VCO, RFREG_MASK),
+                           rtw89_read_rf(rtwdev, RF_PATH_A, RR_SYNFB, RFREG_MASK));
+       }
+}
+
+static void _set_ch(struct rtw89_dev *rtwdev, u32 val)
+{
+       bool timeout;
+
+       timeout = _set_s0_arfc18(rtwdev, val);
+       if (!timeout)
+               _lck_check(rtwdev);
+}
+
+static void _ch_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path,
+                       u8 central_ch, bool dav)
+{
+       u32 reg18_addr = dav ? RR_CFGCH : RR_CFGCH_V1;
+       bool is_2g_ch = central_ch <= 14;
+       u32 rf_reg18;
+
+       rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]===> %s\n", __func__);
+
+       rf_reg18 = rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK);
+       rf_reg18 &= ~(RR_CFGCH_BAND1 | RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH |
+                     RR_CFGCH_BCN | RR_CFGCH_BAND0 | RR_CFGCH_CH);
+       rf_reg18 |= FIELD_PREP(RR_CFGCH_CH, central_ch);
+
+       if (!is_2g_ch)
+               rf_reg18 |= FIELD_PREP(RR_CFGCH_BAND1, CFGCH_BAND1_5G) |
+                           FIELD_PREP(RR_CFGCH_BAND0, CFGCH_BAND0_5G);
+
+       rf_reg18 &= ~(RR_CFGCH_POW_LCK | RR_CFGCH_TRX_AH | RR_CFGCH_BCN |
+                     RR_CFGCH_BW2) & RFREG_MASK;
+       rf_reg18 |= RR_CFGCH_BW2;
+
+       if (path == RF_PATH_A && dav)
+               _set_ch(rtwdev, rf_reg18);
+       else
+               rtw89_write_rf(rtwdev, path, reg18_addr, RFREG_MASK, rf_reg18);
+
+       rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 0);
+       rtw89_write_rf(rtwdev, path, RR_LCKST, RR_LCKST_BIN, 1);
+
+       rtw89_debug(rtwdev, RTW89_DBG_RFK,
+                   "[RFK]CH: %d for Path-%d, reg0x%x = 0x%x\n",
+                   central_ch, path, reg18_addr,
+                   rtw89_read_rf(rtwdev, path, reg18_addr, RFREG_MASK));
+}
+
+static void _ctrl_ch(struct rtw89_dev *rtwdev, u8 central_ch)
+{
+       _ch_setting(rtwdev, RF_PATH_A, central_ch, true);
+       _ch_setting(rtwdev, RF_PATH_B, central_ch, true);
+       _ch_setting(rtwdev, RF_PATH_A, central_ch, false);
+       _ch_setting(rtwdev, RF_PATH_B, central_ch, false);
+}
+
+static void _set_rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_bandwidth bw,
+                        enum rtw89_rf_path path)
+{
+       rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x1);
+       rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_M2, 0x12);
+
+       if (bw == RTW89_CHANNEL_WIDTH_20)
+               rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x1b);
+       else if (bw == RTW89_CHANNEL_WIDTH_40)
+               rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x13);
+       else if (bw == RTW89_CHANNEL_WIDTH_80)
+               rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0xb);
+       else
+               rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, 0x3);
+
+       rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK] set S%d RXBB BW 0x3F = 0x%x\n", path,
+                   rtw89_read_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB));
+
+       rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x0);
+}
+
+static void _rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
+                    enum rtw89_bandwidth bw)
+{
+       u8 kpath, path;
+
+       kpath = _kpath(rtwdev, phy);
+
+       for (path = 0; path < RF_PATH_NUM_8852B; path++) {
+               if (!(kpath & BIT(path)))
+                       continue;
+
+               _set_rxbb_bw(rtwdev, bw, path);
+       }
+}
+
+static void rtw8852b_ctrl_bw_ch(struct rtw89_dev *rtwdev,
+                               enum rtw89_phy_idx phy, u8 central_ch,
+                               enum rtw89_band band, enum rtw89_bandwidth bw)
+{
+       _ctrl_ch(rtwdev, central_ch);
+       _ctrl_bw(rtwdev, phy, bw);
+       _rxbb_bw(rtwdev, phy, bw);
+}
+
+void rtw8852b_set_channel_rf(struct rtw89_dev *rtwdev,
+                            const struct rtw89_chan *chan,
+                            enum rtw89_phy_idx phy_idx)
+{
+       rtw8852b_ctrl_bw_ch(rtwdev, phy_idx, chan->channel, chan->band_type,
+                           chan->band_width);
+}