diff mbox series

[SRU,N,v2,1/1] UBUNTU: SAUCE: wifi: rtw89: add support for hardware rfkill

Message ID 20240820062312.95582-2-en-wei.wu@canonical.com
State New
Headers show
Series rtw89: Support hardware rfkill | expand

Commit Message

En-Wei Wu Aug. 20, 2024, 6:23 a.m. UTC
From: Kuan-Chung Chen <damon.chen@realtek.com>

BugLink: https://bugs.launchpad.net/bugs/2077384

Add support for ieee80211::rfkill_poll ops. This enables periodic
monitoring of the hardware rfkill state, triggering updates when the
status changes.

Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20240724052626.12774-3-pkshih@realtek.com
(backported from commit 0b38e6277aed8a59ccb64fcc1172d962c1f11b4c linux-next)
Signed-off-by: En-Wei Wu <en-wei.wu@canonical.com>
---
 drivers/net/wireless/realtek/rtw89/core.c     | 68 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/core.h     | 10 +++
 drivers/net/wireless/realtek/rtw89/mac80211.c | 17 +++++
 drivers/net/wireless/realtek/rtw89/reg.h      | 24 +++++++
 drivers/net/wireless/realtek/rtw89/rtw8851b.c | 11 +++
 drivers/net/wireless/realtek/rtw89/rtw8852a.c | 11 +++
 drivers/net/wireless/realtek/rtw89/rtw8852b.c | 11 +++
 drivers/net/wireless/realtek/rtw89/rtw8852c.c | 11 +++
 drivers/net/wireless/realtek/rtw89/rtw8922a.c | 56 +++++++++++++++
 9 files changed, 219 insertions(+)

Comments

Kuan-Ying Lee Aug. 22, 2024, 5:38 a.m. UTC | #1
On Tue, Aug 20, 2024 at 02:23:12PM +0800, En-Wei Wu wrote:
> From: Kuan-Chung Chen <damon.chen@realtek.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/2077384
> 
> Add support for ieee80211::rfkill_poll ops. This enables periodic
> monitoring of the hardware rfkill state, triggering updates when the
> status changes.
> 
> Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
> Link: https://patch.msgid.link/20240724052626.12774-3-pkshih@realtek.com
> (backported from commit 0b38e6277aed8a59ccb64fcc1172d962c1f11b4c linux-next)

If this is a backported patch, there must be a brief explanation after the
above line, between square brackets, with the name of the person who
introduced the change.

> Signed-off-by: En-Wei Wu <en-wei.wu@canonical.com>
> ---
>  drivers/net/wireless/realtek/rtw89/core.c     | 68 +++++++++++++++++++
>  drivers/net/wireless/realtek/rtw89/core.h     | 10 +++
>  drivers/net/wireless/realtek/rtw89/mac80211.c | 17 +++++
>  drivers/net/wireless/realtek/rtw89/reg.h      | 24 +++++++
>  drivers/net/wireless/realtek/rtw89/rtw8851b.c | 11 +++
>  drivers/net/wireless/realtek/rtw89/rtw8852a.c | 11 +++
>  drivers/net/wireless/realtek/rtw89/rtw8852b.c | 11 +++
>  drivers/net/wireless/realtek/rtw89/rtw8852c.c | 11 +++
>  drivers/net/wireless/realtek/rtw89/rtw8922a.c | 56 +++++++++++++++
>  9 files changed, 219 insertions(+)
> 
> diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
> index fd527a249996..0fdb83feb925 100644
> --- a/drivers/net/wireless/realtek/rtw89/core.c
> +++ b/drivers/net/wireless/realtek/rtw89/core.c
> @@ -3132,6 +3132,7 @@ static void rtw89_track_work(struct work_struct *work)
>  	rtw89_phy_edcca_track(rtwdev);
>  	rtw89_tas_track(rtwdev);
>  	rtw89_chanctx_track(rtwdev);
> +	rtw89_core_rfkill_poll(rtwdev, false);
>  
>  	if (rtwdev->lps_enabled && !rtwdev->btc.lps)
>  		rtw89_enter_lps_track(rtwdev);
> @@ -4249,6 +4250,70 @@ static int rtw89_chip_board_info_setup(struct rtw89_dev *rtwdev)
>  	return 0;
>  }
>  
> +static bool rtw89_chip_has_rfkill(struct rtw89_dev *rtwdev)
> +{
> +	return !!rtwdev->chip->rfkill_init;
> +}
> +
> +static void rtw89_core_rfkill_init(struct rtw89_dev *rtwdev)
> +{
> +	const struct rtw89_rfkill_regs *regs = rtwdev->chip->rfkill_init;
> +
> +	rtw89_write16_mask(rtwdev, regs->pinmux.addr,
> +			   regs->pinmux.mask, regs->pinmux.data);
> +	rtw89_write16_mask(rtwdev, regs->mode.addr,
> +			   regs->mode.mask, regs->mode.data);
> +}
> +
> +static bool rtw89_core_rfkill_get(struct rtw89_dev *rtwdev)
> +{
> +	const struct rtw89_reg_def *reg = &rtwdev->chip->rfkill_get;
> +
> +	return !rtw89_read8_mask(rtwdev, reg->addr, reg->mask);
> +}
> +
> +static void rtw89_rfkill_polling_init(struct rtw89_dev *rtwdev)
> +{
> +	if (!rtw89_chip_has_rfkill(rtwdev))
> +		return;
> +
> +	rtw89_core_rfkill_init(rtwdev);
> +	rtw89_core_rfkill_poll(rtwdev, true);
> +	wiphy_rfkill_start_polling(rtwdev->hw->wiphy);
> +}
> +
> +static void rtw89_rfkill_polling_deinit(struct rtw89_dev *rtwdev)
> +{
> +	if (!rtw89_chip_has_rfkill(rtwdev))
> +		return;
> +
> +	wiphy_rfkill_stop_polling(rtwdev->hw->wiphy);
> +}
> +
> +void rtw89_core_rfkill_poll(struct rtw89_dev *rtwdev, bool force)
> +{
> +	bool prev, blocked;
> +
> +	if (!rtw89_chip_has_rfkill(rtwdev))
> +		return;
> +
> +	prev = test_bit(RTW89_FLAG_HW_RFKILL_STATE, rtwdev->flags);
> +	blocked = rtw89_core_rfkill_get(rtwdev);
> +
> +	if (!force && prev == blocked)
> +		return;
> +
> +	rtw89_info(rtwdev, "rfkill hardware state changed to %s\n",
> +		   blocked ? "disable" : "enable");
> +
> +	if (blocked)
> +		set_bit(RTW89_FLAG_HW_RFKILL_STATE, rtwdev->flags);
> +	else
> +		clear_bit(RTW89_FLAG_HW_RFKILL_STATE, rtwdev->flags);
> +
> +	wiphy_rfkill_set_hw_state(rtwdev->hw->wiphy, blocked);
> +}
> +
>  int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
>  {
>  	int ret;
> @@ -4389,6 +4454,8 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
>  		goto err_unregister_hw;
>  	}
>  
> +	rtw89_rfkill_polling_init(rtwdev);
> +
>  	return 0;
>  
>  err_unregister_hw:
> @@ -4403,6 +4470,7 @@ static void rtw89_core_unregister_hw(struct rtw89_dev *rtwdev)
>  {
>  	struct ieee80211_hw *hw = rtwdev->hw;
>  
> +	rtw89_rfkill_polling_deinit(rtwdev);
>  	ieee80211_unregister_hw(hw);
>  	rtw89_core_clr_supported_band(rtwdev);
>  }
> diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
> index ea6df859ba15..82d7a2dd88b0 100644
> --- a/drivers/net/wireless/realtek/rtw89/core.h
> +++ b/drivers/net/wireless/realtek/rtw89/core.h
> @@ -3612,6 +3612,11 @@ struct rtw89_rrsr_cfgs {
>  	struct rtw89_reg3_def rsc;
>  };
>  
> +struct rtw89_rfkill_regs {
> +	struct rtw89_reg3_def pinmux;
> +	struct rtw89_reg3_def mode;
> +};
> +
>  struct rtw89_dig_regs {
>  	u32 seg0_pd_reg;
>  	u32 pd_lower_bound_mask;
> @@ -3800,6 +3805,8 @@ struct rtw89_chip_info {
>  	const struct rtw89_rrsr_cfgs *rrsr_cfgs;
>  	struct rtw89_reg_def bss_clr_vld;
>  	u32 bss_clr_map_reg;
> +	const struct rtw89_rfkill_regs *rfkill_init;
> +	struct rtw89_reg_def rfkill_get;
>  	u32 dma_ch_mask;
>  	const struct rtw89_edcca_regs *edcca_regs;
>  	const struct wiphy_wowlan_support *wowlan_stub;
> @@ -4135,6 +4142,7 @@ enum rtw89_flags {
>  	RTW89_FLAG_WOWLAN,
>  	RTW89_FLAG_FORBIDDEN_TRACK_WROK,
>  	RTW89_FLAG_CHANGING_INTERFACE,
> +	RTW89_FLAG_HW_RFKILL_STATE,
>  
>  	NUM_OF_RTW89_FLAGS,
>  };
> @@ -5803,6 +5811,8 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev,
>  void rtw89_core_set_tid_config(struct rtw89_dev *rtwdev,
>  			       struct ieee80211_sta *sta,
>  			       struct cfg80211_tid_config *tid_config);
> +void rtw89_core_rfkill_poll(struct rtw89_dev *rtwdev, bool force);
> +void rtw89_check_quirks(struct rtw89_dev *rtwdev, const struct dmi_system_id *quirks);
>  int rtw89_core_init(struct rtw89_dev *rtwdev);
>  void rtw89_core_deinit(struct rtw89_dev *rtwdev);
>  int rtw89_core_register(struct rtw89_dev *rtwdev);
> diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
> index 93889d2fface..84c19bc6f5a7 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac80211.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
> @@ -1103,6 +1103,22 @@ static void rtw89_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled)
>  }
>  #endif
>  
> +static void rtw89_ops_rfkill_poll(struct ieee80211_hw *hw)
> +{
> +	struct rtw89_dev *rtwdev = hw->priv;
> +
> +	mutex_lock(&rtwdev->mutex);
> +
> +	/* wl_disable GPIO get floating when entering LPS */
> +	if (test_bit(RTW89_FLAG_RUNNING, rtwdev->flags))
> +		goto out;
> +
> +	rtw89_core_rfkill_poll(rtwdev, false);
> +
> +out:
> +	mutex_unlock(&rtwdev->mutex);
> +}
> +
>  const struct ieee80211_ops rtw89_ops = {
>  	.tx			= rtw89_ops_tx,
>  	.wake_tx_queue		= rtw89_ops_wake_tx_queue,
> @@ -1147,5 +1163,6 @@ const struct ieee80211_ops rtw89_ops = {
>  	.resume			= rtw89_ops_resume,
>  	.set_wakeup		= rtw89_ops_set_wakeup,
>  #endif
> +	.rfkill_poll		= rtw89_ops_rfkill_poll,
>  };
>  EXPORT_SYMBOL(rtw89_ops);
> diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
> index 8456e2b0c14f..71e7713a7a08 100644
> --- a/drivers/net/wireless/realtek/rtw89/reg.h
> +++ b/drivers/net/wireless/realtek/rtw89/reg.h
> @@ -107,6 +107,15 @@
>  #define B_AX_DBG_SEL0_16BIT BIT(11)
>  #define B_AX_DBG_SEL0 GENMASK(7, 0)
>  
> +#define R_AX_GPIO_EXT_CTRL 0x0060
> +#define B_AX_GPIO_MOD_15_TO_8_MASK GENMASK(31, 24)
> +#define B_AX_GPIO_MOD_9 BIT(25)
> +#define B_AX_GPIO_IO_SEL_15_TO_8_MASK GENMASK(23, 16)
> +#define B_AX_GPIO_IO_SEL_9 BIT(17)
> +#define B_AX_GPIO_OUT_15_TO_8_MASK GENMASK(15, 8)
> +#define B_AX_GPIO_IN_15_TO_8_MASK GENMASK(7, 0)
> +#define B_AX_GPIO_IN_9 BIT(1)
> +
>  #define R_AX_SYS_SDIO_CTRL 0x0070
>  #define B_AX_PCIE_DIS_L2_CTRL_LDO_HCI BIT(15)
>  #define B_AX_PCIE_DIS_WLSUS_AFT_PDN BIT(14)
> @@ -264,6 +273,9 @@
>  
>  #define R_AX_GPIO0_7_FUNC_SEL 0x02D0
>  
> +#define R_AX_GPIO8_15_FUNC_SEL 0x02D4
> +#define B_AX_PINMUX_GPIO9_FUNC_SEL_MASK GENMASK(7, 4)
> +
>  #define R_AX_EECS_EESK_FUNC_SEL 0x02D8
>  #define B_AX_PINMUX_EESK_FUNC_SEL_MASK GENMASK(7, 4)
>  
> @@ -3822,6 +3834,15 @@
>  #define R_BE_EFUSE_CTRL_1_V1 0x0034
>  #define B_BE_EF_DATA_MASK GENMASK(31, 0)
>  
> +#define R_BE_GPIO_EXT_CTRL 0x0060
> +#define B_BE_GPIO_MOD_15_TO_8_MASK GENMASK(31, 24)
> +#define B_BE_GPIO_MOD_9 BIT(25)
> +#define B_BE_GPIO_IO_SEL_15_TO_8_MASK GENMASK(23, 16)
> +#define B_BE_GPIO_IO_SEL_9 BIT(17)
> +#define B_BE_GPIO_OUT_15_TO_8_MASK GENMASK(15, 8)
> +#define B_BE_GPIO_IN_15_TO_8_MASK GENMASK(7, 0)
> +#define B_BE_GPIO_IN_9 BIT(1)
> +
>  #define R_BE_WL_BT_PWR_CTRL 0x0068
>  #define B_BE_ISO_BD2PP BIT(31)
>  #define B_BE_LDOV12B_EN BIT(30)
> @@ -4243,6 +4264,9 @@
>  #define B_BE_REG_CK40M_EN BIT(1)
>  #define B_BE_REG_CK640M_EN BIT(0)
>  
> +#define R_BE_GPIO8_15_FUNC_SEL 0x02D4
> +#define B_BE_PINMUX_GPIO9_FUNC_SEL_MASK GENMASK(7, 4)
> +
>  #define R_BE_WLAN_XTAL_SI_CTRL 0x0270
>  #define B_BE_WL_XTAL_SI_CMD_POLL BIT(31)
>  #define B_BE_WL_XTAL_SI_CHIPID_MASK GENMASK(30, 28)
> diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
> index 5c167a9278ce..bb6484d4cfdc 100644
> --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
> +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
> @@ -181,6 +181,15 @@ static const struct rtw89_rrsr_cfgs rtw8851b_rrsr_cfgs = {
>  	.rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
>  };
>  
> +static const struct rtw89_rfkill_regs rtw8851b_rfkill_regs = {
> +	.pinmux = {R_AX_GPIO8_15_FUNC_SEL,
> +		   B_AX_PINMUX_GPIO9_FUNC_SEL_MASK,
> +		   0xf},
> +	.mode = {R_AX_GPIO_EXT_CTRL + 2,
> +		 (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16,
> +		 0x0},
> +};
> +
>  static const struct rtw89_dig_regs rtw8851b_dig_regs = {
>  	.seg0_pd_reg = R_SEG0R_PD_V1,
>  	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
> @@ -2459,6 +2468,8 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
>  	.rrsr_cfgs		= &rtw8851b_rrsr_cfgs,
>  	.bss_clr_vld		= {R_BSS_CLR_MAP_V1, B_BSS_CLR_MAP_VLD0},
>  	.bss_clr_map_reg	= R_BSS_CLR_MAP_V1,
> +	.rfkill_init		= &rtw8851b_rfkill_regs,
> +	.rfkill_get		= {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
>  	.dma_ch_mask		= BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
>  				  BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
>  				  BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
> diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
> index 0c76c52ce22c..a423304d9cdf 100644
> --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
> +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
> @@ -474,6 +474,15 @@ static const struct rtw89_rrsr_cfgs rtw8852a_rrsr_cfgs = {
>  	.rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
>  };
>  
> +static const struct rtw89_rfkill_regs rtw8852a_rfkill_regs = {
> +	.pinmux = {R_AX_GPIO8_15_FUNC_SEL,
> +		   B_AX_PINMUX_GPIO9_FUNC_SEL_MASK,
> +		   0xf},
> +	.mode = {R_AX_GPIO_EXT_CTRL + 2,
> +		 (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16,
> +		 0x0},
> +};
> +
>  static const struct rtw89_dig_regs rtw8852a_dig_regs = {
>  	.seg0_pd_reg = R_SEG0R_PD,
>  	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
> @@ -2196,6 +2205,8 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
>  	.rrsr_cfgs		= &rtw8852a_rrsr_cfgs,
>  	.bss_clr_vld		= {R_BSS_CLR_MAP, B_BSS_CLR_MAP_VLD0},
>  	.bss_clr_map_reg	= R_BSS_CLR_MAP,
> +	.rfkill_init		= &rtw8852a_rfkill_regs,
> +	.rfkill_get		= {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
>  	.dma_ch_mask		= 0,
>  	.edcca_regs		= &rtw8852a_edcca_regs,
>  #ifdef CONFIG_PM
> diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
> index de887a35f3fb..251b5998af51 100644
> --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
> +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
> @@ -306,6 +306,15 @@ static const struct rtw89_rrsr_cfgs rtw8852b_rrsr_cfgs = {
>  	.rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
>  };
>  
> +static const struct rtw89_rfkill_regs rtw8852b_rfkill_regs = {
> +	.pinmux = {R_AX_GPIO8_15_FUNC_SEL,
> +		   B_AX_PINMUX_GPIO9_FUNC_SEL_MASK,
> +		   0xf},
> +	.mode = {R_AX_GPIO_EXT_CTRL + 2,
> +		 (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16,
> +		 0x0},
> +};
> +
>  static const struct rtw89_dig_regs rtw8852b_dig_regs = {
>  	.seg0_pd_reg = R_SEG0R_PD_V1,
>  	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
> @@ -2630,6 +2639,8 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
>  	.rrsr_cfgs		= &rtw8852b_rrsr_cfgs,
>  	.bss_clr_vld		= {R_BSS_CLR_MAP_V1, B_BSS_CLR_MAP_VLD0},
>  	.bss_clr_map_reg	= R_BSS_CLR_MAP_V1,
> +	.rfkill_init		= &rtw8852b_rfkill_regs,
> +	.rfkill_get		= {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
>  	.dma_ch_mask		= BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
>  				  BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
>  				  BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
> diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
> index 8618d0204f66..828ceb187151 100644
> --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
> +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
> @@ -143,6 +143,15 @@ static const struct rtw89_rrsr_cfgs rtw8852c_rrsr_cfgs = {
>  	.rsc = {R_AX_PTCL_RRSR1, B_AX_RSC_MASK, 2},
>  };
>  
> +static const struct rtw89_rfkill_regs rtw8852c_rfkill_regs = {
> +	.pinmux = {R_AX_GPIO8_15_FUNC_SEL,
> +		   B_AX_PINMUX_GPIO9_FUNC_SEL_MASK,
> +		   0xf},
> +	.mode = {R_AX_GPIO_EXT_CTRL + 2,
> +		 (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16,
> +		 0x0},
> +};
> +
>  static const struct rtw89_dig_regs rtw8852c_dig_regs = {
>  	.seg0_pd_reg = R_SEG0R_PD,
>  	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
> @@ -2969,6 +2978,8 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
>  	.rrsr_cfgs		= &rtw8852c_rrsr_cfgs,
>  	.bss_clr_vld		= {R_BSS_CLR_MAP, B_BSS_CLR_MAP_VLD0},
>  	.bss_clr_map_reg	= R_BSS_CLR_MAP,
> +	.rfkill_init		= &rtw8852c_rfkill_regs,
> +	.rfkill_get		= {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
>  	.dma_ch_mask		= 0,
>  	.edcca_regs		= &rtw8852c_edcca_regs,
>  #ifdef CONFIG_PM
> diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
> index 0e7300cc6d9e..30bd960a024b 100644
> --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
> +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
> @@ -119,6 +119,60 @@ static const struct rtw89_imr_table rtw8922a_imr_cmac_table = {
>  	.n_regs = ARRAY_SIZE(rtw8922a_imr_cmac_regs),
>  };
>  
> +static const struct rtw89_rrsr_cfgs rtw8922a_rrsr_cfgs = {
> +	.ref_rate = {R_BE_TRXPTCL_RESP_1, B_BE_WMAC_RESP_REF_RATE_SEL, 0},
> +	.rsc = {R_BE_PTCL_RRSR1, B_BE_RSC_MASK, 2},
> +};
> +
> +static const struct rtw89_rfkill_regs rtw8922a_rfkill_regs = {
> +	.pinmux = {R_BE_GPIO8_15_FUNC_SEL,
> +		   B_BE_PINMUX_GPIO9_FUNC_SEL_MASK,
> +		   0xf},
> +	.mode = {R_BE_GPIO_EXT_CTRL + 2,
> +		 (B_BE_GPIO_MOD_9 | B_BE_GPIO_IO_SEL_9) >> 16,
> +		 0x0},
> +};
> +
> +static const struct rtw89_dig_regs rtw8922a_dig_regs = {
> +	.seg0_pd_reg = R_SEG0R_PD_V2,
> +	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
> +	.pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1,
> +	.bmode_pd_reg = R_BMODE_PDTH_EN_V2,
> +	.bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1,
> +	.bmode_pd_lower_bound_reg = R_BMODE_PDTH_V2,
> +	.bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1,
> +	.p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK},
> +	.p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK},
> +	.p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1},
> +	.p1_tia_init = {R_PATH1_TIA_INIT_V1, B_PATH1_TIA_INIT_IDX_MSK_V1},
> +	.p0_rxb_init = {R_PATH0_RXB_INIT_V1, B_PATH0_RXB_INIT_IDX_MSK_V1},
> +	.p1_rxb_init = {R_PATH1_RXB_INIT_V1, B_PATH1_RXB_INIT_IDX_MSK_V1},
> +	.p0_p20_pagcugc_en = {R_PATH0_P20_FOLLOW_BY_PAGCUGC_V3,
> +			      B_PATH0_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
> +	.p0_s20_pagcugc_en = {R_PATH0_S20_FOLLOW_BY_PAGCUGC_V3,
> +			      B_PATH0_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
> +	.p1_p20_pagcugc_en = {R_PATH1_P20_FOLLOW_BY_PAGCUGC_V3,
> +			      B_PATH1_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
> +	.p1_s20_pagcugc_en = {R_PATH1_S20_FOLLOW_BY_PAGCUGC_V3,
> +			      B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
> +};
> +
> +static const struct rtw89_edcca_regs rtw8922a_edcca_regs = {
> +	.edcca_level			= R_SEG0R_EDCCA_LVL_BE,
> +	.edcca_mask			= B_EDCCA_LVL_MSK0,
> +	.edcca_p_mask			= B_EDCCA_LVL_MSK1,
> +	.ppdu_level			= R_SEG0R_PPDU_LVL_BE,
> +	.ppdu_mask			= B_EDCCA_LVL_MSK1,
> +	.rpt_a				= R_EDCCA_RPT_A_BE,
> +	.rpt_b				= R_EDCCA_RPT_B_BE,
> +	.rpt_sel			= R_EDCCA_RPT_SEL_BE,
> +	.rpt_sel_mask			= B_EDCCA_RPT_SEL_MSK,
> +	.rpt_sel_be			= R_EDCCA_RPTREG_SEL_BE,
> +	.rpt_sel_be_mask		= B_EDCCA_RPTREG_SEL_BE_MSK,
> +	.tx_collision_t2r_st		= R_TX_COLLISION_T2R_ST_BE,
> +	.tx_collision_t2r_st_mask	= B_TX_COLLISION_T2R_ST_BE_M,
> +};
> +
>  static const struct rtw89_efuse_block_cfg rtw8922a_efuse_blocks[] = {
>  	[RTW89_EFUSE_BLOCK_SYS]			= {.offset = 0x00000, .size = 0x310},
>  	[RTW89_EFUSE_BLOCK_RF]			= {.offset = 0x10000, .size = 0x240},
> @@ -696,6 +750,8 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
>  	.imr_cmac_table		= &rtw8922a_imr_cmac_table,
>  	.bss_clr_vld		= {R_BSS_CLR_VLD_V2, B_BSS_CLR_VLD0_V2},
>  	.bss_clr_map_reg	= R_BSS_CLR_MAP_V2,
> +	.rfkill_init		= &rtw8922a_rfkill_regs,
> +	.rfkill_get		= {R_BE_GPIO_EXT_CTRL, B_BE_GPIO_IN_9},
>  	.dma_ch_mask		= 0,
>  #ifdef CONFIG_PM
>  	.wowlan_stub		= &rtw_wowlan_stub_8922a,
diff mbox series

Patch

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index fd527a249996..0fdb83feb925 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -3132,6 +3132,7 @@  static void rtw89_track_work(struct work_struct *work)
 	rtw89_phy_edcca_track(rtwdev);
 	rtw89_tas_track(rtwdev);
 	rtw89_chanctx_track(rtwdev);
+	rtw89_core_rfkill_poll(rtwdev, false);
 
 	if (rtwdev->lps_enabled && !rtwdev->btc.lps)
 		rtw89_enter_lps_track(rtwdev);
@@ -4249,6 +4250,70 @@  static int rtw89_chip_board_info_setup(struct rtw89_dev *rtwdev)
 	return 0;
 }
 
+static bool rtw89_chip_has_rfkill(struct rtw89_dev *rtwdev)
+{
+	return !!rtwdev->chip->rfkill_init;
+}
+
+static void rtw89_core_rfkill_init(struct rtw89_dev *rtwdev)
+{
+	const struct rtw89_rfkill_regs *regs = rtwdev->chip->rfkill_init;
+
+	rtw89_write16_mask(rtwdev, regs->pinmux.addr,
+			   regs->pinmux.mask, regs->pinmux.data);
+	rtw89_write16_mask(rtwdev, regs->mode.addr,
+			   regs->mode.mask, regs->mode.data);
+}
+
+static bool rtw89_core_rfkill_get(struct rtw89_dev *rtwdev)
+{
+	const struct rtw89_reg_def *reg = &rtwdev->chip->rfkill_get;
+
+	return !rtw89_read8_mask(rtwdev, reg->addr, reg->mask);
+}
+
+static void rtw89_rfkill_polling_init(struct rtw89_dev *rtwdev)
+{
+	if (!rtw89_chip_has_rfkill(rtwdev))
+		return;
+
+	rtw89_core_rfkill_init(rtwdev);
+	rtw89_core_rfkill_poll(rtwdev, true);
+	wiphy_rfkill_start_polling(rtwdev->hw->wiphy);
+}
+
+static void rtw89_rfkill_polling_deinit(struct rtw89_dev *rtwdev)
+{
+	if (!rtw89_chip_has_rfkill(rtwdev))
+		return;
+
+	wiphy_rfkill_stop_polling(rtwdev->hw->wiphy);
+}
+
+void rtw89_core_rfkill_poll(struct rtw89_dev *rtwdev, bool force)
+{
+	bool prev, blocked;
+
+	if (!rtw89_chip_has_rfkill(rtwdev))
+		return;
+
+	prev = test_bit(RTW89_FLAG_HW_RFKILL_STATE, rtwdev->flags);
+	blocked = rtw89_core_rfkill_get(rtwdev);
+
+	if (!force && prev == blocked)
+		return;
+
+	rtw89_info(rtwdev, "rfkill hardware state changed to %s\n",
+		   blocked ? "disable" : "enable");
+
+	if (blocked)
+		set_bit(RTW89_FLAG_HW_RFKILL_STATE, rtwdev->flags);
+	else
+		clear_bit(RTW89_FLAG_HW_RFKILL_STATE, rtwdev->flags);
+
+	wiphy_rfkill_set_hw_state(rtwdev->hw->wiphy, blocked);
+}
+
 int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
 {
 	int ret;
@@ -4389,6 +4454,8 @@  static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
 		goto err_unregister_hw;
 	}
 
+	rtw89_rfkill_polling_init(rtwdev);
+
 	return 0;
 
 err_unregister_hw:
@@ -4403,6 +4470,7 @@  static void rtw89_core_unregister_hw(struct rtw89_dev *rtwdev)
 {
 	struct ieee80211_hw *hw = rtwdev->hw;
 
+	rtw89_rfkill_polling_deinit(rtwdev);
 	ieee80211_unregister_hw(hw);
 	rtw89_core_clr_supported_band(rtwdev);
 }
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index ea6df859ba15..82d7a2dd88b0 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -3612,6 +3612,11 @@  struct rtw89_rrsr_cfgs {
 	struct rtw89_reg3_def rsc;
 };
 
+struct rtw89_rfkill_regs {
+	struct rtw89_reg3_def pinmux;
+	struct rtw89_reg3_def mode;
+};
+
 struct rtw89_dig_regs {
 	u32 seg0_pd_reg;
 	u32 pd_lower_bound_mask;
@@ -3800,6 +3805,8 @@  struct rtw89_chip_info {
 	const struct rtw89_rrsr_cfgs *rrsr_cfgs;
 	struct rtw89_reg_def bss_clr_vld;
 	u32 bss_clr_map_reg;
+	const struct rtw89_rfkill_regs *rfkill_init;
+	struct rtw89_reg_def rfkill_get;
 	u32 dma_ch_mask;
 	const struct rtw89_edcca_regs *edcca_regs;
 	const struct wiphy_wowlan_support *wowlan_stub;
@@ -4135,6 +4142,7 @@  enum rtw89_flags {
 	RTW89_FLAG_WOWLAN,
 	RTW89_FLAG_FORBIDDEN_TRACK_WROK,
 	RTW89_FLAG_CHANGING_INTERFACE,
+	RTW89_FLAG_HW_RFKILL_STATE,
 
 	NUM_OF_RTW89_FLAGS,
 };
@@ -5803,6 +5811,8 @@  int rtw89_core_sta_remove(struct rtw89_dev *rtwdev,
 void rtw89_core_set_tid_config(struct rtw89_dev *rtwdev,
 			       struct ieee80211_sta *sta,
 			       struct cfg80211_tid_config *tid_config);
+void rtw89_core_rfkill_poll(struct rtw89_dev *rtwdev, bool force);
+void rtw89_check_quirks(struct rtw89_dev *rtwdev, const struct dmi_system_id *quirks);
 int rtw89_core_init(struct rtw89_dev *rtwdev);
 void rtw89_core_deinit(struct rtw89_dev *rtwdev);
 int rtw89_core_register(struct rtw89_dev *rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 93889d2fface..84c19bc6f5a7 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -1103,6 +1103,22 @@  static void rtw89_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled)
 }
 #endif
 
+static void rtw89_ops_rfkill_poll(struct ieee80211_hw *hw)
+{
+	struct rtw89_dev *rtwdev = hw->priv;
+
+	mutex_lock(&rtwdev->mutex);
+
+	/* wl_disable GPIO get floating when entering LPS */
+	if (test_bit(RTW89_FLAG_RUNNING, rtwdev->flags))
+		goto out;
+
+	rtw89_core_rfkill_poll(rtwdev, false);
+
+out:
+	mutex_unlock(&rtwdev->mutex);
+}
+
 const struct ieee80211_ops rtw89_ops = {
 	.tx			= rtw89_ops_tx,
 	.wake_tx_queue		= rtw89_ops_wake_tx_queue,
@@ -1147,5 +1163,6 @@  const struct ieee80211_ops rtw89_ops = {
 	.resume			= rtw89_ops_resume,
 	.set_wakeup		= rtw89_ops_set_wakeup,
 #endif
+	.rfkill_poll		= rtw89_ops_rfkill_poll,
 };
 EXPORT_SYMBOL(rtw89_ops);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 8456e2b0c14f..71e7713a7a08 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -107,6 +107,15 @@ 
 #define B_AX_DBG_SEL0_16BIT BIT(11)
 #define B_AX_DBG_SEL0 GENMASK(7, 0)
 
+#define R_AX_GPIO_EXT_CTRL 0x0060
+#define B_AX_GPIO_MOD_15_TO_8_MASK GENMASK(31, 24)
+#define B_AX_GPIO_MOD_9 BIT(25)
+#define B_AX_GPIO_IO_SEL_15_TO_8_MASK GENMASK(23, 16)
+#define B_AX_GPIO_IO_SEL_9 BIT(17)
+#define B_AX_GPIO_OUT_15_TO_8_MASK GENMASK(15, 8)
+#define B_AX_GPIO_IN_15_TO_8_MASK GENMASK(7, 0)
+#define B_AX_GPIO_IN_9 BIT(1)
+
 #define R_AX_SYS_SDIO_CTRL 0x0070
 #define B_AX_PCIE_DIS_L2_CTRL_LDO_HCI BIT(15)
 #define B_AX_PCIE_DIS_WLSUS_AFT_PDN BIT(14)
@@ -264,6 +273,9 @@ 
 
 #define R_AX_GPIO0_7_FUNC_SEL 0x02D0
 
+#define R_AX_GPIO8_15_FUNC_SEL 0x02D4
+#define B_AX_PINMUX_GPIO9_FUNC_SEL_MASK GENMASK(7, 4)
+
 #define R_AX_EECS_EESK_FUNC_SEL 0x02D8
 #define B_AX_PINMUX_EESK_FUNC_SEL_MASK GENMASK(7, 4)
 
@@ -3822,6 +3834,15 @@ 
 #define R_BE_EFUSE_CTRL_1_V1 0x0034
 #define B_BE_EF_DATA_MASK GENMASK(31, 0)
 
+#define R_BE_GPIO_EXT_CTRL 0x0060
+#define B_BE_GPIO_MOD_15_TO_8_MASK GENMASK(31, 24)
+#define B_BE_GPIO_MOD_9 BIT(25)
+#define B_BE_GPIO_IO_SEL_15_TO_8_MASK GENMASK(23, 16)
+#define B_BE_GPIO_IO_SEL_9 BIT(17)
+#define B_BE_GPIO_OUT_15_TO_8_MASK GENMASK(15, 8)
+#define B_BE_GPIO_IN_15_TO_8_MASK GENMASK(7, 0)
+#define B_BE_GPIO_IN_9 BIT(1)
+
 #define R_BE_WL_BT_PWR_CTRL 0x0068
 #define B_BE_ISO_BD2PP BIT(31)
 #define B_BE_LDOV12B_EN BIT(30)
@@ -4243,6 +4264,9 @@ 
 #define B_BE_REG_CK40M_EN BIT(1)
 #define B_BE_REG_CK640M_EN BIT(0)
 
+#define R_BE_GPIO8_15_FUNC_SEL 0x02D4
+#define B_BE_PINMUX_GPIO9_FUNC_SEL_MASK GENMASK(7, 4)
+
 #define R_BE_WLAN_XTAL_SI_CTRL 0x0270
 #define B_BE_WL_XTAL_SI_CMD_POLL BIT(31)
 #define B_BE_WL_XTAL_SI_CHIPID_MASK GENMASK(30, 28)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 5c167a9278ce..bb6484d4cfdc 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -181,6 +181,15 @@  static const struct rtw89_rrsr_cfgs rtw8851b_rrsr_cfgs = {
 	.rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
 };
 
+static const struct rtw89_rfkill_regs rtw8851b_rfkill_regs = {
+	.pinmux = {R_AX_GPIO8_15_FUNC_SEL,
+		   B_AX_PINMUX_GPIO9_FUNC_SEL_MASK,
+		   0xf},
+	.mode = {R_AX_GPIO_EXT_CTRL + 2,
+		 (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16,
+		 0x0},
+};
+
 static const struct rtw89_dig_regs rtw8851b_dig_regs = {
 	.seg0_pd_reg = R_SEG0R_PD_V1,
 	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
@@ -2459,6 +2468,8 @@  const struct rtw89_chip_info rtw8851b_chip_info = {
 	.rrsr_cfgs		= &rtw8851b_rrsr_cfgs,
 	.bss_clr_vld		= {R_BSS_CLR_MAP_V1, B_BSS_CLR_MAP_VLD0},
 	.bss_clr_map_reg	= R_BSS_CLR_MAP_V1,
+	.rfkill_init		= &rtw8851b_rfkill_regs,
+	.rfkill_get		= {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
 	.dma_ch_mask		= BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
 				  BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
 				  BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 0c76c52ce22c..a423304d9cdf 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -474,6 +474,15 @@  static const struct rtw89_rrsr_cfgs rtw8852a_rrsr_cfgs = {
 	.rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
 };
 
+static const struct rtw89_rfkill_regs rtw8852a_rfkill_regs = {
+	.pinmux = {R_AX_GPIO8_15_FUNC_SEL,
+		   B_AX_PINMUX_GPIO9_FUNC_SEL_MASK,
+		   0xf},
+	.mode = {R_AX_GPIO_EXT_CTRL + 2,
+		 (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16,
+		 0x0},
+};
+
 static const struct rtw89_dig_regs rtw8852a_dig_regs = {
 	.seg0_pd_reg = R_SEG0R_PD,
 	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
@@ -2196,6 +2205,8 @@  const struct rtw89_chip_info rtw8852a_chip_info = {
 	.rrsr_cfgs		= &rtw8852a_rrsr_cfgs,
 	.bss_clr_vld		= {R_BSS_CLR_MAP, B_BSS_CLR_MAP_VLD0},
 	.bss_clr_map_reg	= R_BSS_CLR_MAP,
+	.rfkill_init		= &rtw8852a_rfkill_regs,
+	.rfkill_get		= {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
 	.dma_ch_mask		= 0,
 	.edcca_regs		= &rtw8852a_edcca_regs,
 #ifdef CONFIG_PM
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index de887a35f3fb..251b5998af51 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -306,6 +306,15 @@  static const struct rtw89_rrsr_cfgs rtw8852b_rrsr_cfgs = {
 	.rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2},
 };
 
+static const struct rtw89_rfkill_regs rtw8852b_rfkill_regs = {
+	.pinmux = {R_AX_GPIO8_15_FUNC_SEL,
+		   B_AX_PINMUX_GPIO9_FUNC_SEL_MASK,
+		   0xf},
+	.mode = {R_AX_GPIO_EXT_CTRL + 2,
+		 (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16,
+		 0x0},
+};
+
 static const struct rtw89_dig_regs rtw8852b_dig_regs = {
 	.seg0_pd_reg = R_SEG0R_PD_V1,
 	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
@@ -2630,6 +2639,8 @@  const struct rtw89_chip_info rtw8852b_chip_info = {
 	.rrsr_cfgs		= &rtw8852b_rrsr_cfgs,
 	.bss_clr_vld		= {R_BSS_CLR_MAP_V1, B_BSS_CLR_MAP_VLD0},
 	.bss_clr_map_reg	= R_BSS_CLR_MAP_V1,
+	.rfkill_init		= &rtw8852b_rfkill_regs,
+	.rfkill_get		= {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
 	.dma_ch_mask		= BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) |
 				  BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) |
 				  BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI),
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 8618d0204f66..828ceb187151 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -143,6 +143,15 @@  static const struct rtw89_rrsr_cfgs rtw8852c_rrsr_cfgs = {
 	.rsc = {R_AX_PTCL_RRSR1, B_AX_RSC_MASK, 2},
 };
 
+static const struct rtw89_rfkill_regs rtw8852c_rfkill_regs = {
+	.pinmux = {R_AX_GPIO8_15_FUNC_SEL,
+		   B_AX_PINMUX_GPIO9_FUNC_SEL_MASK,
+		   0xf},
+	.mode = {R_AX_GPIO_EXT_CTRL + 2,
+		 (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16,
+		 0x0},
+};
+
 static const struct rtw89_dig_regs rtw8852c_dig_regs = {
 	.seg0_pd_reg = R_SEG0R_PD,
 	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
@@ -2969,6 +2978,8 @@  const struct rtw89_chip_info rtw8852c_chip_info = {
 	.rrsr_cfgs		= &rtw8852c_rrsr_cfgs,
 	.bss_clr_vld		= {R_BSS_CLR_MAP, B_BSS_CLR_MAP_VLD0},
 	.bss_clr_map_reg	= R_BSS_CLR_MAP,
+	.rfkill_init		= &rtw8852c_rfkill_regs,
+	.rfkill_get		= {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9},
 	.dma_ch_mask		= 0,
 	.edcca_regs		= &rtw8852c_edcca_regs,
 #ifdef CONFIG_PM
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 0e7300cc6d9e..30bd960a024b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -119,6 +119,60 @@  static const struct rtw89_imr_table rtw8922a_imr_cmac_table = {
 	.n_regs = ARRAY_SIZE(rtw8922a_imr_cmac_regs),
 };
 
+static const struct rtw89_rrsr_cfgs rtw8922a_rrsr_cfgs = {
+	.ref_rate = {R_BE_TRXPTCL_RESP_1, B_BE_WMAC_RESP_REF_RATE_SEL, 0},
+	.rsc = {R_BE_PTCL_RRSR1, B_BE_RSC_MASK, 2},
+};
+
+static const struct rtw89_rfkill_regs rtw8922a_rfkill_regs = {
+	.pinmux = {R_BE_GPIO8_15_FUNC_SEL,
+		   B_BE_PINMUX_GPIO9_FUNC_SEL_MASK,
+		   0xf},
+	.mode = {R_BE_GPIO_EXT_CTRL + 2,
+		 (B_BE_GPIO_MOD_9 | B_BE_GPIO_IO_SEL_9) >> 16,
+		 0x0},
+};
+
+static const struct rtw89_dig_regs rtw8922a_dig_regs = {
+	.seg0_pd_reg = R_SEG0R_PD_V2,
+	.pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK,
+	.pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1,
+	.bmode_pd_reg = R_BMODE_PDTH_EN_V2,
+	.bmode_cca_rssi_limit_en = B_BMODE_PDTH_LIMIT_EN_MSK_V1,
+	.bmode_pd_lower_bound_reg = R_BMODE_PDTH_V2,
+	.bmode_rssi_nocca_low_th_mask = B_BMODE_PDTH_LOWER_BOUND_MSK_V1,
+	.p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK},
+	.p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK},
+	.p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1},
+	.p1_tia_init = {R_PATH1_TIA_INIT_V1, B_PATH1_TIA_INIT_IDX_MSK_V1},
+	.p0_rxb_init = {R_PATH0_RXB_INIT_V1, B_PATH0_RXB_INIT_IDX_MSK_V1},
+	.p1_rxb_init = {R_PATH1_RXB_INIT_V1, B_PATH1_RXB_INIT_IDX_MSK_V1},
+	.p0_p20_pagcugc_en = {R_PATH0_P20_FOLLOW_BY_PAGCUGC_V3,
+			      B_PATH0_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
+	.p0_s20_pagcugc_en = {R_PATH0_S20_FOLLOW_BY_PAGCUGC_V3,
+			      B_PATH0_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
+	.p1_p20_pagcugc_en = {R_PATH1_P20_FOLLOW_BY_PAGCUGC_V3,
+			      B_PATH1_P20_FOLLOW_BY_PAGCUGC_EN_MSK},
+	.p1_s20_pagcugc_en = {R_PATH1_S20_FOLLOW_BY_PAGCUGC_V3,
+			      B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK},
+};
+
+static const struct rtw89_edcca_regs rtw8922a_edcca_regs = {
+	.edcca_level			= R_SEG0R_EDCCA_LVL_BE,
+	.edcca_mask			= B_EDCCA_LVL_MSK0,
+	.edcca_p_mask			= B_EDCCA_LVL_MSK1,
+	.ppdu_level			= R_SEG0R_PPDU_LVL_BE,
+	.ppdu_mask			= B_EDCCA_LVL_MSK1,
+	.rpt_a				= R_EDCCA_RPT_A_BE,
+	.rpt_b				= R_EDCCA_RPT_B_BE,
+	.rpt_sel			= R_EDCCA_RPT_SEL_BE,
+	.rpt_sel_mask			= B_EDCCA_RPT_SEL_MSK,
+	.rpt_sel_be			= R_EDCCA_RPTREG_SEL_BE,
+	.rpt_sel_be_mask		= B_EDCCA_RPTREG_SEL_BE_MSK,
+	.tx_collision_t2r_st		= R_TX_COLLISION_T2R_ST_BE,
+	.tx_collision_t2r_st_mask	= B_TX_COLLISION_T2R_ST_BE_M,
+};
+
 static const struct rtw89_efuse_block_cfg rtw8922a_efuse_blocks[] = {
 	[RTW89_EFUSE_BLOCK_SYS]			= {.offset = 0x00000, .size = 0x310},
 	[RTW89_EFUSE_BLOCK_RF]			= {.offset = 0x10000, .size = 0x240},
@@ -696,6 +750,8 @@  const struct rtw89_chip_info rtw8922a_chip_info = {
 	.imr_cmac_table		= &rtw8922a_imr_cmac_table,
 	.bss_clr_vld		= {R_BSS_CLR_VLD_V2, B_BSS_CLR_VLD0_V2},
 	.bss_clr_map_reg	= R_BSS_CLR_MAP_V2,
+	.rfkill_init		= &rtw8922a_rfkill_regs,
+	.rfkill_get		= {R_BE_GPIO_EXT_CTRL, B_BE_GPIO_IN_9},
 	.dma_ch_mask		= 0,
 #ifdef CONFIG_PM
 	.wowlan_stub		= &rtw_wowlan_stub_8922a,