int (*read_efuse)(struct rtw89_dev *rtwdev, u8 *log_map);
        int (*read_phycap)(struct rtw89_dev *rtwdev, u8 *phycap_map);
        void (*fem_setup)(struct rtw89_dev *rtwdev);
+       void (*rfe_gpio)(struct rtw89_dev *rtwdev);
        void (*rfk_init)(struct rtw89_dev *rtwdev);
        void (*rfk_channel)(struct rtw89_dev *rtwdev);
        void (*rfk_band_changed)(struct rtw89_dev *rtwdev,
                chip->ops->fem_setup(rtwdev);
 }
 
+static inline void rtw89_chip_rfe_gpio(struct rtw89_dev *rtwdev)
+{
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+
+       if (chip->ops->rfe_gpio)
+               chip->ops->rfe_gpio(rtwdev);
+}
+
 static inline void rtw89_chip_bb_sethw(struct rtw89_dev *rtwdev)
 {
        const struct rtw89_chip_info *chip = rtwdev->chip;
 
        rtw89_phy_cfo_init(rtwdev);
        rtw89_phy_ul_tb_info_init(rtwdev);
        rtw89_phy_antdiv_init(rtwdev);
+       rtw89_chip_rfe_gpio(rtwdev);
        rtw89_phy_antdiv_set_ant(rtwdev);
 
        rtw89_phy_init_rf_nctl(rtwdev);
 
 #define R_AX_EECS_EESK_FUNC_SEL 0x02D8
 #define B_AX_PINMUX_EESK_FUNC_SEL_MASK GENMASK(7, 4)
 
+#define R_AX_GPIO16_23_FUNC_SEL 0x02D8
+#define B_AX_PINMUX_GPIO17_FUNC_SEL_MASK GENMASK(7, 4)
+#define B_AX_PINMUX_GPIO16_FUNC_SEL_MASK GENMASK(3, 0)
+
 #define R_AX_LED1_FUNC_SEL 0x02DC
 #define B_AX_PINMUX_EESK_FUNC_SEL_V1_MASK GENMASK(27, 24)
 #define PINMUX_EESK_FUNC_SEL_BT_LOG 0x1
 #define R_RFE_E_A2 0x0334
 #define R_RFE_O_SEL_A2 0x0338
 #define R_RFE_SEL0_A2 0x033C
+#define B_RFE_SEL0_MASK GENMASK(1, 0)
 #define R_RFE_SEL32_A2 0x0340
 #define R_CIRST 0x035c
 #define B_CIRST_SYN GENMASK(11, 10)
 #define B_P0_ANTSEL_RX_ORI GENMASK(7, 4)
 #define R_RFSW_CTRL_ANT0_BASE 0x5870
 #define B_RFSW_CTRL_ANT_MAPPING GENMASK(15, 0)
+#define R_RFE_SEL0_BASE 0x5880
+#define B_RFE_SEL0_SRC_MASK GENMASK(3, 0)
+#define RFE_SEL0_SRC_ANTSEL_0 8
+#define R_RFE_INV0 0x5890
 #define R_P0_RFM 0x5894
 #define B_P0_RFM_DIS_WL BIT(7)
 #define B_P0_RFM_TX_OPT BIT(6)
 
        .sc_xi_mask             = B_AX_XTAL_SC_XI_A_BLOCK_MASK,
 };
 
+static void rtw8851b_set_bb_gpio(struct rtw89_dev *rtwdev, u8 gpio_idx, bool inv,
+                                u8 src_sel)
+{
+       u32 addr, mask;
+
+       if (gpio_idx >= 32)
+               return;
+
+       /* 2 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 2 bits */
+       addr = R_RFE_SEL0_A2 + (gpio_idx / 16) * sizeof(u32);
+       mask = B_RFE_SEL0_MASK << (gpio_idx % 16) * 2;
+
+       rtw89_phy_write32_mask(rtwdev, addr, mask, RF_PATH_A);
+       rtw89_phy_write32_mask(rtwdev, R_RFE_INV0, BIT(gpio_idx), inv);
+
+       /* 4 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 4 bits */
+       addr = R_RFE_SEL0_BASE + (gpio_idx / 8) * sizeof(u32);
+       mask = B_RFE_SEL0_SRC_MASK << (gpio_idx % 8) * 4;
+
+       rtw89_phy_write32_mask(rtwdev, addr, mask, src_sel);
+}
+
+static void rtw8851b_set_mac_gpio(struct rtw89_dev *rtwdev, u8 func)
+{
+       static const struct rtw89_reg3_def func16 = {
+               R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO16_FUNC_SEL_MASK, BIT(3)
+       };
+       static const struct rtw89_reg3_def func17 = {
+               R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO17_FUNC_SEL_MASK, BIT(7) >> 4,
+       };
+       const struct rtw89_reg3_def *def;
+
+       switch (func) {
+       case 16:
+               def = &func16;
+               break;
+       case 17:
+               def = &func17;
+               break;
+       default:
+               rtw89_warn(rtwdev, "undefined gpio func %d\n", func);
+               return;
+       }
+
+       rtw89_write8_mask(rtwdev, def->addr, def->mask, def->data);
+}
+
+static void rtw8851b_rfe_gpio(struct rtw89_dev *rtwdev)
+{
+       u8 rfe_type = rtwdev->efuse.rfe_type;
+
+       if (rfe_type > 50)
+               return;
+
+       if (rfe_type % 3 == 2) {
+               rtw8851b_set_bb_gpio(rtwdev, 16, true, RFE_SEL0_SRC_ANTSEL_0);
+               rtw8851b_set_bb_gpio(rtwdev, 17, false, RFE_SEL0_SRC_ANTSEL_0);
+
+               rtw8851b_set_mac_gpio(rtwdev, 16);
+               rtw8851b_set_mac_gpio(rtwdev, 17);
+       }
+}
+
 static const struct rtw89_chip_ops rtw8851b_chip_ops = {
        .fem_setup              = NULL,
+       .rfe_gpio               = rtw8851b_rfe_gpio,
        .fill_txdesc            = rtw89_core_fill_txdesc,
        .fill_txdesc_fwcmd      = rtw89_core_fill_txdesc,
        .h2c_dctl_sec_cam       = NULL,
 
        .read_efuse             = rtw8852a_read_efuse,
        .read_phycap            = rtw8852a_read_phycap,
        .fem_setup              = rtw8852a_fem_setup,
+       .rfe_gpio               = NULL,
        .rfk_init               = rtw8852a_rfk_init,
        .rfk_channel            = rtw8852a_rfk_channel,
        .rfk_band_changed       = rtw8852a_rfk_band_changed,
 
        .read_efuse             = rtw8852b_read_efuse,
        .read_phycap            = rtw8852b_read_phycap,
        .fem_setup              = NULL,
+       .rfe_gpio               = NULL,
        .rfk_init               = rtw8852b_rfk_init,
        .rfk_channel            = rtw8852b_rfk_channel,
        .rfk_band_changed       = rtw8852b_rfk_band_changed,
 
        .read_efuse             = rtw8852c_read_efuse,
        .read_phycap            = rtw8852c_read_phycap,
        .fem_setup              = NULL,
+       .rfe_gpio               = NULL,
        .rfk_init               = rtw8852c_rfk_init,
        .rfk_channel            = rtw8852c_rfk_channel,
        .rfk_band_changed       = rtw8852c_rfk_band_changed,