xref: /freebsd-src/sys/contrib/dev/rtw89/mac.c (revision 6d67aabd63555ab62a2f2b7f52a75ef100a2fe75)
18e93258fSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
28e93258fSBjoern A. Zeeb /* Copyright(c) 2019-2020  Realtek Corporation
38e93258fSBjoern A. Zeeb  */
48e93258fSBjoern A. Zeeb 
58e93258fSBjoern A. Zeeb #include "cam.h"
68e93258fSBjoern A. Zeeb #include "chan.h"
78e93258fSBjoern A. Zeeb #include "debug.h"
8*6d67aabdSBjoern A. Zeeb #include "efuse.h"
98e93258fSBjoern A. Zeeb #include "fw.h"
108e93258fSBjoern A. Zeeb #include "mac.h"
11e2340276SBjoern A. Zeeb #include "pci.h"
128e93258fSBjoern A. Zeeb #include "ps.h"
138e93258fSBjoern A. Zeeb #include "reg.h"
148e93258fSBjoern A. Zeeb #include "util.h"
158e93258fSBjoern A. Zeeb 
16*6d67aabdSBjoern A. Zeeb static const u32 rtw89_mac_mem_base_addrs_ax[RTW89_MAC_MEM_NUM] = {
178e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_AXIDMA]	        = AXIDMA_BASE_ADDR,
188e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_SHARED_BUF]	= SHARED_BUF_BASE_ADDR,
198e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_DMAC_TBL]	= DMAC_TBL_BASE_ADDR,
208e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_SHCUT_MACHDR]	= SHCUT_MACHDR_BASE_ADDR,
218e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_STA_SCHED]	= STA_SCHED_BASE_ADDR,
228e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_RXPLD_FLTR_CAM]	= RXPLD_FLTR_CAM_BASE_ADDR,
238e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_SECURITY_CAM]	= SECURITY_CAM_BASE_ADDR,
248e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_WOW_CAM]		= WOW_CAM_BASE_ADDR,
258e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_CMAC_TBL]	= CMAC_TBL_BASE_ADDR,
268e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_ADDR_CAM]	= ADDR_CAM_BASE_ADDR,
278e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_BA_CAM]		= BA_CAM_BASE_ADDR,
288e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_BCN_IE_CAM0]	= BCN_IE_CAM0_BASE_ADDR,
298e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_BCN_IE_CAM1]	= BCN_IE_CAM1_BASE_ADDR,
308e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_TXD_FIFO_0]	= TXD_FIFO_0_BASE_ADDR,
318e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_TXD_FIFO_1]	= TXD_FIFO_1_BASE_ADDR,
328e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_TXDATA_FIFO_0]	= TXDATA_FIFO_0_BASE_ADDR,
338e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_TXDATA_FIFO_1]	= TXDATA_FIFO_1_BASE_ADDR,
348e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_CPU_LOCAL]	= CPU_LOCAL_BASE_ADDR,
358e93258fSBjoern A. Zeeb 	[RTW89_MAC_MEM_BSSID_CAM]	= BSSID_CAM_BASE_ADDR,
36e2340276SBjoern A. Zeeb 	[RTW89_MAC_MEM_TXD_FIFO_0_V1]	= TXD_FIFO_0_BASE_ADDR_V1,
37e2340276SBjoern A. Zeeb 	[RTW89_MAC_MEM_TXD_FIFO_1_V1]	= TXD_FIFO_1_BASE_ADDR_V1,
388e93258fSBjoern A. Zeeb };
398e93258fSBjoern A. Zeeb 
408e93258fSBjoern A. Zeeb static void rtw89_mac_mem_write(struct rtw89_dev *rtwdev, u32 offset,
418e93258fSBjoern A. Zeeb 				u32 val, enum rtw89_mac_mem_sel sel)
428e93258fSBjoern A. Zeeb {
43*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
44*6d67aabdSBjoern A. Zeeb 	u32 addr = mac->mem_base_addrs[sel] + offset;
458e93258fSBjoern A. Zeeb 
46*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, mac->filter_model_addr, addr);
47*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, mac->indir_access_addr, val);
488e93258fSBjoern A. Zeeb }
498e93258fSBjoern A. Zeeb 
508e93258fSBjoern A. Zeeb static u32 rtw89_mac_mem_read(struct rtw89_dev *rtwdev, u32 offset,
518e93258fSBjoern A. Zeeb 			      enum rtw89_mac_mem_sel sel)
528e93258fSBjoern A. Zeeb {
53*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
54*6d67aabdSBjoern A. Zeeb 	u32 addr = mac->mem_base_addrs[sel] + offset;
558e93258fSBjoern A. Zeeb 
56*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, mac->filter_model_addr, addr);
57*6d67aabdSBjoern A. Zeeb 	return rtw89_read32(rtwdev, mac->indir_access_addr);
588e93258fSBjoern A. Zeeb }
598e93258fSBjoern A. Zeeb 
60*6d67aabdSBjoern A. Zeeb static int rtw89_mac_check_mac_en_ax(struct rtw89_dev *rtwdev, u8 mac_idx,
618e93258fSBjoern A. Zeeb 				     enum rtw89_mac_hwmod_sel sel)
628e93258fSBjoern A. Zeeb {
638e93258fSBjoern A. Zeeb 	u32 val, r_val;
648e93258fSBjoern A. Zeeb 
658e93258fSBjoern A. Zeeb 	if (sel == RTW89_DMAC_SEL) {
668e93258fSBjoern A. Zeeb 		r_val = rtw89_read32(rtwdev, R_AX_DMAC_FUNC_EN);
678e93258fSBjoern A. Zeeb 		val = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN);
688e93258fSBjoern A. Zeeb 	} else if (sel == RTW89_CMAC_SEL && mac_idx == 0) {
698e93258fSBjoern A. Zeeb 		r_val = rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN);
708e93258fSBjoern A. Zeeb 		val = B_AX_CMAC_EN;
718e93258fSBjoern A. Zeeb 	} else if (sel == RTW89_CMAC_SEL && mac_idx == 1) {
728e93258fSBjoern A. Zeeb 		r_val = rtw89_read32(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND);
738e93258fSBjoern A. Zeeb 		val = B_AX_CMAC1_FEN;
748e93258fSBjoern A. Zeeb 	} else {
758e93258fSBjoern A. Zeeb 		return -EINVAL;
768e93258fSBjoern A. Zeeb 	}
778e93258fSBjoern A. Zeeb 	if (r_val == RTW89_R32_EA || r_val == RTW89_R32_DEAD ||
788e93258fSBjoern A. Zeeb 	    (val & r_val) != val)
798e93258fSBjoern A. Zeeb 		return -EFAULT;
808e93258fSBjoern A. Zeeb 
818e93258fSBjoern A. Zeeb 	return 0;
828e93258fSBjoern A. Zeeb }
838e93258fSBjoern A. Zeeb 
848e93258fSBjoern A. Zeeb int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val)
858e93258fSBjoern A. Zeeb {
868e93258fSBjoern A. Zeeb 	u8 lte_ctrl;
878e93258fSBjoern A. Zeeb 	int ret;
888e93258fSBjoern A. Zeeb 
898e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
908e93258fSBjoern A. Zeeb 				50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3);
918e93258fSBjoern A. Zeeb 	if (ret)
928e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]lte not ready(W)\n");
938e93258fSBjoern A. Zeeb 
948e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_LTE_WDATA, val);
958e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_LTE_CTRL, 0xC00F0000 | offset);
968e93258fSBjoern A. Zeeb 
978e93258fSBjoern A. Zeeb 	return ret;
988e93258fSBjoern A. Zeeb }
998e93258fSBjoern A. Zeeb 
1008e93258fSBjoern A. Zeeb int rtw89_mac_read_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 *val)
1018e93258fSBjoern A. Zeeb {
1028e93258fSBjoern A. Zeeb 	u8 lte_ctrl;
1038e93258fSBjoern A. Zeeb 	int ret;
1048e93258fSBjoern A. Zeeb 
1058e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
1068e93258fSBjoern A. Zeeb 				50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3);
1078e93258fSBjoern A. Zeeb 	if (ret)
1088e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]lte not ready(W)\n");
1098e93258fSBjoern A. Zeeb 
1108e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_LTE_CTRL, 0x800F0000 | offset);
1118e93258fSBjoern A. Zeeb 	*val = rtw89_read32(rtwdev, R_AX_LTE_RDATA);
1128e93258fSBjoern A. Zeeb 
1138e93258fSBjoern A. Zeeb 	return ret;
1148e93258fSBjoern A. Zeeb }
1158e93258fSBjoern A. Zeeb 
116*6d67aabdSBjoern A. Zeeb int rtw89_mac_dle_dfi_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_dfi_ctrl *ctrl)
1178e93258fSBjoern A. Zeeb {
1188e93258fSBjoern A. Zeeb 	u32 ctrl_reg, data_reg, ctrl_data;
1198e93258fSBjoern A. Zeeb 	u32 val;
1208e93258fSBjoern A. Zeeb 	int ret;
1218e93258fSBjoern A. Zeeb 
1228e93258fSBjoern A. Zeeb 	switch (ctrl->type) {
1238e93258fSBjoern A. Zeeb 	case DLE_CTRL_TYPE_WDE:
1248e93258fSBjoern A. Zeeb 		ctrl_reg = R_AX_WDE_DBG_FUN_INTF_CTL;
1258e93258fSBjoern A. Zeeb 		data_reg = R_AX_WDE_DBG_FUN_INTF_DATA;
1268e93258fSBjoern A. Zeeb 		ctrl_data = FIELD_PREP(B_AX_WDE_DFI_TRGSEL_MASK, ctrl->target) |
1278e93258fSBjoern A. Zeeb 			    FIELD_PREP(B_AX_WDE_DFI_ADDR_MASK, ctrl->addr) |
1288e93258fSBjoern A. Zeeb 			    B_AX_WDE_DFI_ACTIVE;
1298e93258fSBjoern A. Zeeb 		break;
1308e93258fSBjoern A. Zeeb 	case DLE_CTRL_TYPE_PLE:
1318e93258fSBjoern A. Zeeb 		ctrl_reg = R_AX_PLE_DBG_FUN_INTF_CTL;
1328e93258fSBjoern A. Zeeb 		data_reg = R_AX_PLE_DBG_FUN_INTF_DATA;
1338e93258fSBjoern A. Zeeb 		ctrl_data = FIELD_PREP(B_AX_PLE_DFI_TRGSEL_MASK, ctrl->target) |
1348e93258fSBjoern A. Zeeb 			    FIELD_PREP(B_AX_PLE_DFI_ADDR_MASK, ctrl->addr) |
1358e93258fSBjoern A. Zeeb 			    B_AX_PLE_DFI_ACTIVE;
1368e93258fSBjoern A. Zeeb 		break;
1378e93258fSBjoern A. Zeeb 	default:
1388e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "[ERR] dfi ctrl type %d\n", ctrl->type);
1398e93258fSBjoern A. Zeeb 		return -EINVAL;
1408e93258fSBjoern A. Zeeb 	}
1418e93258fSBjoern A. Zeeb 
1428e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, ctrl_reg, ctrl_data);
1438e93258fSBjoern A. Zeeb 
1448e93258fSBjoern A. Zeeb 	ret = read_poll_timeout_atomic(rtw89_read32, val, !(val & B_AX_WDE_DFI_ACTIVE),
1458e93258fSBjoern A. Zeeb 				       1, 1000, false, rtwdev, ctrl_reg);
1468e93258fSBjoern A. Zeeb 	if (ret) {
1478e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "[ERR] dle dfi ctrl 0x%X set 0x%X timeout\n",
1488e93258fSBjoern A. Zeeb 			   ctrl_reg, ctrl_data);
1498e93258fSBjoern A. Zeeb 		return ret;
1508e93258fSBjoern A. Zeeb 	}
1518e93258fSBjoern A. Zeeb 
1528e93258fSBjoern A. Zeeb 	ctrl->out_data = rtw89_read32(rtwdev, data_reg);
1538e93258fSBjoern A. Zeeb 	return 0;
1548e93258fSBjoern A. Zeeb }
1558e93258fSBjoern A. Zeeb 
156*6d67aabdSBjoern A. Zeeb int rtw89_mac_dle_dfi_quota_cfg(struct rtw89_dev *rtwdev,
1578e93258fSBjoern A. Zeeb 				struct rtw89_mac_dle_dfi_quota *quota)
1588e93258fSBjoern A. Zeeb {
1598e93258fSBjoern A. Zeeb 	struct rtw89_mac_dle_dfi_ctrl ctrl;
1608e93258fSBjoern A. Zeeb 	int ret;
1618e93258fSBjoern A. Zeeb 
1628e93258fSBjoern A. Zeeb 	ctrl.type = quota->dle_type;
1638e93258fSBjoern A. Zeeb 	ctrl.target = DLE_DFI_TYPE_QUOTA;
1648e93258fSBjoern A. Zeeb 	ctrl.addr = quota->qtaid;
165*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_dle_dfi_cfg(rtwdev, &ctrl);
1668e93258fSBjoern A. Zeeb 	if (ret) {
167*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "[ERR] dle dfi quota %d\n", ret);
1688e93258fSBjoern A. Zeeb 		return ret;
1698e93258fSBjoern A. Zeeb 	}
1708e93258fSBjoern A. Zeeb 
1718e93258fSBjoern A. Zeeb 	quota->rsv_pgnum = FIELD_GET(B_AX_DLE_RSV_PGNUM, ctrl.out_data);
1728e93258fSBjoern A. Zeeb 	quota->use_pgnum = FIELD_GET(B_AX_DLE_USE_PGNUM, ctrl.out_data);
1738e93258fSBjoern A. Zeeb 	return 0;
1748e93258fSBjoern A. Zeeb }
1758e93258fSBjoern A. Zeeb 
176*6d67aabdSBjoern A. Zeeb int rtw89_mac_dle_dfi_qempty_cfg(struct rtw89_dev *rtwdev,
1778e93258fSBjoern A. Zeeb 				 struct rtw89_mac_dle_dfi_qempty *qempty)
1788e93258fSBjoern A. Zeeb {
1798e93258fSBjoern A. Zeeb 	struct rtw89_mac_dle_dfi_ctrl ctrl;
1808e93258fSBjoern A. Zeeb 	u32 ret;
1818e93258fSBjoern A. Zeeb 
1828e93258fSBjoern A. Zeeb 	ctrl.type = qempty->dle_type;
1838e93258fSBjoern A. Zeeb 	ctrl.target = DLE_DFI_TYPE_QEMPTY;
1848e93258fSBjoern A. Zeeb 	ctrl.addr = qempty->grpsel;
185*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_dle_dfi_cfg(rtwdev, &ctrl);
1868e93258fSBjoern A. Zeeb 	if (ret) {
187*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "[ERR] dle dfi qempty %d\n", ret);
1888e93258fSBjoern A. Zeeb 		return ret;
1898e93258fSBjoern A. Zeeb 	}
1908e93258fSBjoern A. Zeeb 
1918e93258fSBjoern A. Zeeb 	qempty->qempty = FIELD_GET(B_AX_DLE_QEMPTY_GRP, ctrl.out_data);
1928e93258fSBjoern A. Zeeb 	return 0;
1938e93258fSBjoern A. Zeeb }
1948e93258fSBjoern A. Zeeb 
195*6d67aabdSBjoern A. Zeeb static void dump_err_status_dispatcher_ax(struct rtw89_dev *rtwdev)
1968e93258fSBjoern A. Zeeb {
1978e93258fSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ALWAYS_IMR=0x%08x ",
1988e93258fSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR));
1998e93258fSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ALWAYS_ISR=0x%08x\n",
2008e93258fSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR));
2018e93258fSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ALWAYS_IMR=0x%08x ",
2028e93258fSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR));
2038e93258fSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ALWAYS_ISR=0x%08x\n",
2048e93258fSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR));
2058e93258fSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ALWAYS_IMR=0x%08x ",
2068e93258fSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR));
2078e93258fSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ALWAYS_ISR=0x%08x\n",
2088e93258fSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR));
2098e93258fSBjoern A. Zeeb }
2108e93258fSBjoern A. Zeeb 
211*6d67aabdSBjoern A. Zeeb static void rtw89_mac_dump_qta_lost_ax(struct rtw89_dev *rtwdev)
2128e93258fSBjoern A. Zeeb {
2138e93258fSBjoern A. Zeeb 	struct rtw89_mac_dle_dfi_qempty qempty;
2148e93258fSBjoern A. Zeeb 	struct rtw89_mac_dle_dfi_quota quota;
2158e93258fSBjoern A. Zeeb 	struct rtw89_mac_dle_dfi_ctrl ctrl;
2168e93258fSBjoern A. Zeeb 	u32 val, not_empty, i;
2178e93258fSBjoern A. Zeeb 	int ret;
2188e93258fSBjoern A. Zeeb 
2198e93258fSBjoern A. Zeeb 	qempty.dle_type = DLE_CTRL_TYPE_PLE;
2208e93258fSBjoern A. Zeeb 	qempty.grpsel = 0;
2218e93258fSBjoern A. Zeeb 	qempty.qempty = ~(u32)0;
222*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_dle_dfi_qempty_cfg(rtwdev, &qempty);
2238e93258fSBjoern A. Zeeb 	if (ret)
2248e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "%s: query DLE fail\n", __func__);
2258e93258fSBjoern A. Zeeb 	else
2268e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "DLE group0 empty: 0x%x\n", qempty.qempty);
2278e93258fSBjoern A. Zeeb 
2288e93258fSBjoern A. Zeeb 	for (not_empty = ~qempty.qempty, i = 0; not_empty != 0; not_empty >>= 1, i++) {
2298e93258fSBjoern A. Zeeb 		if (!(not_empty & BIT(0)))
2308e93258fSBjoern A. Zeeb 			continue;
2318e93258fSBjoern A. Zeeb 		ctrl.type = DLE_CTRL_TYPE_PLE;
2328e93258fSBjoern A. Zeeb 		ctrl.target = DLE_DFI_TYPE_QLNKTBL;
2338e93258fSBjoern A. Zeeb 		ctrl.addr = (QLNKTBL_ADDR_INFO_SEL_0 ? QLNKTBL_ADDR_INFO_SEL : 0) |
234*6d67aabdSBjoern A. Zeeb 			    u32_encode_bits(i, QLNKTBL_ADDR_TBL_IDX_MASK);
235*6d67aabdSBjoern A. Zeeb 		ret = rtw89_mac_dle_dfi_cfg(rtwdev, &ctrl);
2368e93258fSBjoern A. Zeeb 		if (ret)
2378e93258fSBjoern A. Zeeb 			rtw89_warn(rtwdev, "%s: query DLE fail\n", __func__);
2388e93258fSBjoern A. Zeeb 		else
239*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "qidx%d pktcnt = %d\n", i,
240*6d67aabdSBjoern A. Zeeb 				   u32_get_bits(ctrl.out_data,
241*6d67aabdSBjoern A. Zeeb 						QLNKTBL_DATA_SEL1_PKT_CNT_MASK));
2428e93258fSBjoern A. Zeeb 	}
2438e93258fSBjoern A. Zeeb 
2448e93258fSBjoern A. Zeeb 	quota.dle_type = DLE_CTRL_TYPE_PLE;
2458e93258fSBjoern A. Zeeb 	quota.qtaid = 6;
246*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_dle_dfi_quota_cfg(rtwdev, &quota);
2478e93258fSBjoern A. Zeeb 	if (ret)
2488e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "%s: query DLE fail\n", __func__);
2498e93258fSBjoern A. Zeeb 	else
2508e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "quota6 rsv/use: 0x%x/0x%x\n",
2518e93258fSBjoern A. Zeeb 			   quota.rsv_pgnum, quota.use_pgnum);
2528e93258fSBjoern A. Zeeb 
2538e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, R_AX_PLE_QTA6_CFG);
254*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "[PLE][CMAC0_RX]min_pgnum=0x%x\n",
255*6d67aabdSBjoern A. Zeeb 		   u32_get_bits(val, B_AX_PLE_Q6_MIN_SIZE_MASK));
256*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "[PLE][CMAC0_RX]max_pgnum=0x%x\n",
257*6d67aabdSBjoern A. Zeeb 		   u32_get_bits(val, B_AX_PLE_Q6_MAX_SIZE_MASK));
258*6d67aabdSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, R_AX_RX_FLTR_OPT);
259*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "[PLE][CMAC0_RX]B_AX_RX_MPDU_MAX_LEN=0x%x\n",
260*6d67aabdSBjoern A. Zeeb 		   u32_get_bits(val, B_AX_RX_MPDU_MAX_LEN_MASK));
261*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_RSP_CHK_SIG=0x%08x\n",
262*6d67aabdSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_RSP_CHK_SIG));
263*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_TRXPTCL_RESP_0=0x%08x\n",
264*6d67aabdSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_TRXPTCL_RESP_0));
265*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_CCA_CONTROL=0x%08x\n",
266*6d67aabdSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_CCA_CONTROL));
2678e93258fSBjoern A. Zeeb 
268*6d67aabdSBjoern A. Zeeb 	if (!rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_1, RTW89_CMAC_SEL)) {
269*6d67aabdSBjoern A. Zeeb 		quota.dle_type = DLE_CTRL_TYPE_PLE;
270*6d67aabdSBjoern A. Zeeb 		quota.qtaid = 7;
271*6d67aabdSBjoern A. Zeeb 		ret = rtw89_mac_dle_dfi_quota_cfg(rtwdev, &quota);
272*6d67aabdSBjoern A. Zeeb 		if (ret)
273*6d67aabdSBjoern A. Zeeb 			rtw89_warn(rtwdev, "%s: query DLE fail\n", __func__);
274*6d67aabdSBjoern A. Zeeb 		else
275*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "quota7 rsv/use: 0x%x/0x%x\n",
276*6d67aabdSBjoern A. Zeeb 				   quota.rsv_pgnum, quota.use_pgnum);
277*6d67aabdSBjoern A. Zeeb 
278*6d67aabdSBjoern A. Zeeb 		val = rtw89_read32(rtwdev, R_AX_PLE_QTA7_CFG);
279*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "[PLE][CMAC1_RX]min_pgnum=0x%x\n",
280*6d67aabdSBjoern A. Zeeb 			   u32_get_bits(val, B_AX_PLE_Q7_MIN_SIZE_MASK));
281*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "[PLE][CMAC1_RX]max_pgnum=0x%x\n",
282*6d67aabdSBjoern A. Zeeb 			   u32_get_bits(val, B_AX_PLE_Q7_MAX_SIZE_MASK));
283*6d67aabdSBjoern A. Zeeb 		val = rtw89_read32(rtwdev, R_AX_RX_FLTR_OPT_C1);
284*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "[PLE][CMAC1_RX]B_AX_RX_MPDU_MAX_LEN=0x%x\n",
285*6d67aabdSBjoern A. Zeeb 			   u32_get_bits(val, B_AX_RX_MPDU_MAX_LEN_MASK));
286*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_RSP_CHK_SIG_C1=0x%08x\n",
287*6d67aabdSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_RSP_CHK_SIG_C1));
288*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_TRXPTCL_RESP_0_C1=0x%08x\n",
289*6d67aabdSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_TRXPTCL_RESP_0_C1));
290*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_CCA_CONTROL_C1=0x%08x\n",
291*6d67aabdSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_CCA_CONTROL_C1));
2928e93258fSBjoern A. Zeeb 	}
2938e93258fSBjoern A. Zeeb 
294*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_DLE_EMPTY0=0x%08x\n",
295*6d67aabdSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_DLE_EMPTY0));
296*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_DLE_EMPTY1=0x%08x\n",
297*6d67aabdSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_DLE_EMPTY1));
298*6d67aabdSBjoern A. Zeeb 
299*6d67aabdSBjoern A. Zeeb 	dump_err_status_dispatcher_ax(rtwdev);
300*6d67aabdSBjoern A. Zeeb }
301*6d67aabdSBjoern A. Zeeb 
302*6d67aabdSBjoern A. Zeeb void rtw89_mac_dump_l0_to_l1(struct rtw89_dev *rtwdev,
3038e93258fSBjoern A. Zeeb 			     enum mac_ax_err_info err)
3048e93258fSBjoern A. Zeeb {
305*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
3068e93258fSBjoern A. Zeeb 	u32 dbg, event;
3078e93258fSBjoern A. Zeeb 
3088e93258fSBjoern A. Zeeb 	dbg = rtw89_read32(rtwdev, R_AX_SER_DBG_INFO);
309*6d67aabdSBjoern A. Zeeb 	event = u32_get_bits(dbg, B_AX_L0_TO_L1_EVENT_MASK);
3108e93258fSBjoern A. Zeeb 
3118e93258fSBjoern A. Zeeb 	switch (event) {
3128e93258fSBjoern A. Zeeb 	case MAC_AX_L0_TO_L1_RX_QTA_LOST:
3138e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "quota lost!\n");
314*6d67aabdSBjoern A. Zeeb 		mac->dump_qta_lost(rtwdev);
3158e93258fSBjoern A. Zeeb 		break;
3168e93258fSBjoern A. Zeeb 	default:
3178e93258fSBjoern A. Zeeb 		break;
3188e93258fSBjoern A. Zeeb 	}
3198e93258fSBjoern A. Zeeb }
3208e93258fSBjoern A. Zeeb 
321*6d67aabdSBjoern A. Zeeb void rtw89_mac_dump_dmac_err_status(struct rtw89_dev *rtwdev)
3228e93258fSBjoern A. Zeeb {
323e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
324e2340276SBjoern A. Zeeb 	u32 dmac_err;
325e2340276SBjoern A. Zeeb 	int i, ret;
3268e93258fSBjoern A. Zeeb 
327e2340276SBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
328e2340276SBjoern A. Zeeb 	if (ret) {
329e2340276SBjoern A. Zeeb 		rtw89_warn(rtwdev, "[DMAC] : DMAC not enabled\n");
3308e93258fSBjoern A. Zeeb 		return;
331e2340276SBjoern A. Zeeb 	}
3328e93258fSBjoern A. Zeeb 
3338e93258fSBjoern A. Zeeb 	dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
3348e93258fSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_DMAC_ERR_ISR=0x%08x\n", dmac_err);
335e2340276SBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_DMAC_ERR_IMR=0x%08x\n",
336e2340276SBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_DMAC_ERR_IMR));
3378e93258fSBjoern A. Zeeb 
3388e93258fSBjoern A. Zeeb 	if (dmac_err) {
339e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WDE_ERR_FLAG_CFG=0x%08x\n",
340e2340276SBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WDE_ERR_FLAG_CFG_NUM1));
3418e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_CFG=0x%08x\n",
342e2340276SBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_CFG_NUM1));
343e2340276SBjoern A. Zeeb 		if (chip->chip_id == RTL8852C) {
344e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_PLE_ERRFLAG_MSG=0x%08x\n",
345e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_PLE_ERRFLAG_MSG));
346e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_WDE_ERRFLAG_MSG=0x%08x\n",
347e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_WDE_ERRFLAG_MSG));
348e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_PLE_DBGERR_LOCKEN=0x%08x\n",
349e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_PLE_DBGERR_LOCKEN));
350e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_PLE_DBGERR_STS=0x%08x\n",
351e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_PLE_DBGERR_STS));
352e2340276SBjoern A. Zeeb 		}
3538e93258fSBjoern A. Zeeb 	}
3548e93258fSBjoern A. Zeeb 
3558e93258fSBjoern A. Zeeb 	if (dmac_err & B_AX_WDRLS_ERR_FLAG) {
356e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WDRLS_ERR_IMR=0x%08x\n",
3578e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WDRLS_ERR_IMR));
3588e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WDRLS_ERR_ISR=0x%08x\n",
3598e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WDRLS_ERR_ISR));
360e2340276SBjoern A. Zeeb 		if (chip->chip_id == RTL8852C)
361e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_RPQ_RXBD_IDX=0x%08x\n",
362e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX_V1));
363e2340276SBjoern A. Zeeb 		else
364e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_RPQ_RXBD_IDX=0x%08x\n",
365e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX));
3668e93258fSBjoern A. Zeeb 	}
3678e93258fSBjoern A. Zeeb 
3688e93258fSBjoern A. Zeeb 	if (dmac_err & B_AX_WSEC_ERR_FLAG) {
369e2340276SBjoern A. Zeeb 		if (chip->chip_id == RTL8852C) {
370e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_ERR_IMR=0x%08x\n",
371e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG_IMR));
372e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_ERR_ISR=0x%08x\n",
373e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG));
374e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_ENG_CTRL=0x%08x\n",
375e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
376e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_MPDU_PROC=0x%08x\n",
377e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
378e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_CAM_ACCESS=0x%08x\n",
379e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
380e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_CAM_RDATA=0x%08x\n",
381e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
382e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_DEBUG1=0x%08x\n",
383e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_DEBUG1));
384e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_TX_DEBUG=0x%08x\n",
385e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
386e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_RX_DEBUG=0x%08x\n",
387e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG));
388e2340276SBjoern A. Zeeb 
389e2340276SBjoern A. Zeeb 			rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL,
390e2340276SBjoern A. Zeeb 					   B_AX_DBG_SEL0, 0x8B);
391e2340276SBjoern A. Zeeb 			rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL,
392e2340276SBjoern A. Zeeb 					   B_AX_DBG_SEL1, 0x8B);
393e2340276SBjoern A. Zeeb 			rtw89_write32_mask(rtwdev, R_AX_SYS_STATUS1,
394e2340276SBjoern A. Zeeb 					   B_AX_SEL_0XC0_MASK, 1);
395e2340276SBjoern A. Zeeb 			for (i = 0; i < 0x10; i++) {
396e2340276SBjoern A. Zeeb 				rtw89_write32_mask(rtwdev, R_AX_SEC_ENG_CTRL,
397e2340276SBjoern A. Zeeb 						   B_AX_SEC_DBG_PORT_FIELD_MASK, i);
398e2340276SBjoern A. Zeeb 				rtw89_info(rtwdev, "sel=%x,R_AX_SEC_DEBUG2=0x%08x\n",
399e2340276SBjoern A. Zeeb 					   i, rtw89_read32(rtwdev, R_AX_SEC_DEBUG2));
400e2340276SBjoern A. Zeeb 			}
401*6d67aabdSBjoern A. Zeeb 		} else if (chip->chip_id == RTL8922A) {
402*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_SEC_ERROR_FLAG=0x%08x\n",
403*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_SEC_ERROR_FLAG));
404*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_SEC_ERROR_IMR=0x%08x\n",
405*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_SEC_ERROR_IMR));
406*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_SEC_ENG_CTRL=0x%08x\n",
407*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_SEC_ENG_CTRL));
408*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_SEC_MPDU_PROC=0x%08x\n",
409*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_SEC_MPDU_PROC));
410*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_SEC_CAM_ACCESS=0x%08x\n",
411*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_SEC_CAM_ACCESS));
412*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_SEC_CAM_RDATA=0x%08x\n",
413*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_SEC_CAM_RDATA));
414*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_SEC_DEBUG2=0x%08x\n",
415*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_SEC_DEBUG2));
416e2340276SBjoern A. Zeeb 		} else {
4178e93258fSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_ERR_IMR_ISR=0x%08x\n",
4188e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_DEBUG));
419e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_ENG_CTRL=0x%08x\n",
4208e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
421e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_MPDU_PROC=0x%08x\n",
4228e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
423e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_CAM_ACCESS=0x%08x\n",
4248e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
425e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_CAM_RDATA=0x%08x\n",
4268e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
427e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_CAM_WDATA=0x%08x\n",
4288e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_CAM_WDATA));
429e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_TX_DEBUG=0x%08x\n",
4308e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
431e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_RX_DEBUG=0x%08x\n",
4328e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG));
433e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_TRX_PKT_CNT=0x%08x\n",
4348e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_TRX_PKT_CNT));
435e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_SEC_TRX_BLK_CNT=0x%08x\n",
4368e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_SEC_TRX_BLK_CNT));
4378e93258fSBjoern A. Zeeb 		}
438e2340276SBjoern A. Zeeb 	}
4398e93258fSBjoern A. Zeeb 
4408e93258fSBjoern A. Zeeb 	if (dmac_err & B_AX_MPDU_ERR_FLAG) {
441e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_IMR=0x%08x\n",
4428e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_IMR));
4438e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_ISR=0x%08x\n",
4448e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_ISR));
445e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_IMR=0x%08x\n",
4468e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_IMR));
4478e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_ISR=0x%08x\n",
4488e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_ISR));
4498e93258fSBjoern A. Zeeb 	}
4508e93258fSBjoern A. Zeeb 
4518e93258fSBjoern A. Zeeb 	if (dmac_err & B_AX_STA_SCHEDULER_ERR_FLAG) {
452*6d67aabdSBjoern A. Zeeb 		if (chip->chip_id == RTL8922A) {
453*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_INTERRUPT_MASK_REG=0x%08x\n",
454*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_INTERRUPT_MASK_REG));
455*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_INTERRUPT_STS_REG=0x%08x\n",
456*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_INTERRUPT_STS_REG));
457*6d67aabdSBjoern A. Zeeb 		} else {
458e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_IMR=0x%08x\n",
4598e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_IMR));
4608e93258fSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_ISR=0x%08x\n",
4618e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_ISR));
4628e93258fSBjoern A. Zeeb 		}
463*6d67aabdSBjoern A. Zeeb 	}
4648e93258fSBjoern A. Zeeb 
4658e93258fSBjoern A. Zeeb 	if (dmac_err & B_AX_WDE_DLE_ERR_FLAG) {
466e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x\n",
4678e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
4688e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WDE_ERR_ISR=0x%08x\n",
4698e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
470e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x\n",
4718e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
4728e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n",
4738e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR));
4748e93258fSBjoern A. Zeeb 	}
4758e93258fSBjoern A. Zeeb 
4768e93258fSBjoern A. Zeeb 	if (dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) {
477*6d67aabdSBjoern A. Zeeb 		if (chip->chip_id == RTL8852C || chip->chip_id == RTL8922A) {
478e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_TXPKTCTL_B0_ERRFLAG_IMR=0x%08x\n",
479e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR));
480e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_TXPKTCTL_B0_ERRFLAG_ISR=0x%08x\n",
481e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR));
482e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_TXPKTCTL_B1_ERRFLAG_IMR=0x%08x\n",
483e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_IMR));
484e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_TXPKTCTL_B1_ERRFLAG_ISR=0x%08x\n",
485e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_ISR));
486e2340276SBjoern A. Zeeb 		} else {
4878e93258fSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR=0x%08x\n",
4888e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR));
4898e93258fSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR_B1=0x%08x\n",
4908e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR_B1));
4918e93258fSBjoern A. Zeeb 		}
492e2340276SBjoern A. Zeeb 	}
4938e93258fSBjoern A. Zeeb 
4948e93258fSBjoern A. Zeeb 	if (dmac_err & B_AX_PLE_DLE_ERR_FLAG) {
495e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x\n",
4968e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
4978e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WDE_ERR_ISR=0x%08x\n",
4988e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
499e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x\n",
5008e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
5018e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n",
5028e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR));
5038e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_0=0x%08x\n",
5048e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_0));
5058e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_1=0x%08x\n",
5068e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_1));
5078e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_2=0x%08x\n",
5088e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_2));
5098e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_0=0x%08x\n",
5108e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_0));
5118e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_1=0x%08x\n",
5128e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_1));
5138e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_2=0x%08x\n",
5148e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_2));
515*6d67aabdSBjoern A. Zeeb 		if (chip->chip_id == RTL8922A) {
516*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_WD_CPUQ_OP_3=0x%08x\n",
517*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_WD_CPUQ_OP_3));
518*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_WD_CPUQ_OP_STATUS=0x%08x\n",
519*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_WD_CPUQ_OP_STATUS));
520*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_PLE_CPUQ_OP_3=0x%08x\n",
521*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_PL_CPUQ_OP_3));
522*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_PL_CPUQ_OP_STATUS=0x%08x\n",
523*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_PL_CPUQ_OP_STATUS));
524*6d67aabdSBjoern A. Zeeb 		} else {
525*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_STATUS=0x%08x\n",
526*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_STATUS));
5278e93258fSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_STATUS=0x%08x\n",
5288e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_STATUS));
529e2340276SBjoern A. Zeeb 			if (chip->chip_id == RTL8852C) {
530e2340276SBjoern A. Zeeb 				rtw89_info(rtwdev, "R_AX_RX_CTRL0=0x%08x\n",
531e2340276SBjoern A. Zeeb 					   rtw89_read32(rtwdev, R_AX_RX_CTRL0));
532e2340276SBjoern A. Zeeb 				rtw89_info(rtwdev, "R_AX_RX_CTRL1=0x%08x\n",
533e2340276SBjoern A. Zeeb 					   rtw89_read32(rtwdev, R_AX_RX_CTRL1));
534e2340276SBjoern A. Zeeb 				rtw89_info(rtwdev, "R_AX_RX_CTRL2=0x%08x\n",
535e2340276SBjoern A. Zeeb 					   rtw89_read32(rtwdev, R_AX_RX_CTRL2));
536e2340276SBjoern A. Zeeb 			} else {
5378e93258fSBjoern A. Zeeb 				rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_0=0x%08x\n",
5388e93258fSBjoern A. Zeeb 					   rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_0));
5398e93258fSBjoern A. Zeeb 				rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_1=0x%08x\n",
5408e93258fSBjoern A. Zeeb 					   rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_1));
5418e93258fSBjoern A. Zeeb 				rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_2=0x%08x\n",
5428e93258fSBjoern A. Zeeb 					   rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_2));
543e2340276SBjoern A. Zeeb 			}
5448e93258fSBjoern A. Zeeb 		}
545*6d67aabdSBjoern A. Zeeb 	}
5468e93258fSBjoern A. Zeeb 
5478e93258fSBjoern A. Zeeb 	if (dmac_err & B_AX_PKTIN_ERR_FLAG) {
548e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PKTIN_ERR_IMR=0x%08x\n",
5498e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PKTIN_ERR_IMR));
5508e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PKTIN_ERR_ISR=0x%08x\n",
5518e93258fSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PKTIN_ERR_ISR));
5528e93258fSBjoern A. Zeeb 	}
5538e93258fSBjoern A. Zeeb 
554e2340276SBjoern A. Zeeb 	if (dmac_err & B_AX_DISPATCH_ERR_FLAG) {
555*6d67aabdSBjoern A. Zeeb 		if (chip->chip_id == RTL8922A) {
556*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_DISP_HOST_IMR=0x%08x\n",
557*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_DISP_HOST_IMR));
558*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_DISP_ERROR_ISR1=0x%08x\n",
559*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_DISP_ERROR_ISR1));
560*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_DISP_CPU_IMR=0x%08x\n",
561*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_DISP_CPU_IMR));
562*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_DISP_ERROR_ISR2=0x%08x\n",
563*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_DISP_ERROR_ISR2));
564*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_DISP_OTHER_IMR=0x%08x\n",
565*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_DISP_OTHER_IMR));
566*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_DISP_ERROR_ISR0=0x%08x\n",
567*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_DISP_ERROR_ISR0));
568*6d67aabdSBjoern A. Zeeb 		} else {
569e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ERR_IMR=0x%08x\n",
570e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR));
571e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ERR_ISR=0x%08x\n",
572e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR));
573e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ERR_IMR=0x%08x\n",
574e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR));
575e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ERR_ISR=0x%08x\n",
576e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR));
577e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ERR_IMR=0x%08x\n",
578e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR));
579e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ERR_ISR=0x%08x\n",
580e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR));
5818e93258fSBjoern A. Zeeb 		}
582*6d67aabdSBjoern A. Zeeb 	}
5838e93258fSBjoern A. Zeeb 
584e2340276SBjoern A. Zeeb 	if (dmac_err & B_AX_BBRPT_ERR_FLAG) {
585*6d67aabdSBjoern A. Zeeb 		if (chip->chip_id == RTL8852C || chip->chip_id == RTL8922A) {
586e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_IMR=0x%08x\n",
587e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR));
588e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_ISR=0x%08x\n",
589e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_ISR));
590e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n",
591e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
592e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n",
593e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
594e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n",
595e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
596e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n",
597e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
598e2340276SBjoern A. Zeeb 		} else {
5998e93258fSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_IMR_ISR=0x%08x\n",
6008e93258fSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR_ISR));
601e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n",
602e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
603e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n",
604e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
605e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n",
606e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
607e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n",
608e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
609e2340276SBjoern A. Zeeb 		}
610*6d67aabdSBjoern A. Zeeb 		if (chip->chip_id == RTL8922A) {
611*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_LA_ERRFLAG_IMR=0x%08x\n",
612*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_LA_ERRFLAG_IMR));
613*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_LA_ERRFLAG_ISR=0x%08x\n",
614*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_LA_ERRFLAG_ISR));
615*6d67aabdSBjoern A. Zeeb 		}
6168e93258fSBjoern A. Zeeb 	}
6178e93258fSBjoern A. Zeeb 
618*6d67aabdSBjoern A. Zeeb 	if (dmac_err & B_AX_HAXIDMA_ERR_FLAG) {
619*6d67aabdSBjoern A. Zeeb 		if (chip->chip_id == RTL8922A) {
620*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_HAXI_IDCT_MSK=0x%08x\n",
621*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_HAXI_IDCT_MSK));
622*6d67aabdSBjoern A. Zeeb 			rtw89_info(rtwdev, "R_BE_HAXI_IDCT=0x%08x\n",
623*6d67aabdSBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_BE_HAXI_IDCT));
624*6d67aabdSBjoern A. Zeeb 		} else if (chip->chip_id == RTL8852C) {
625e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_HAXIDMA_ERR_IMR=0x%08x\n",
626e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_HAXI_IDCT_MSK));
627e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_HAXIDMA_ERR_ISR=0x%08x\n",
628e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_HAXI_IDCT));
629e2340276SBjoern A. Zeeb 		}
630e2340276SBjoern A. Zeeb 	}
631e2340276SBjoern A. Zeeb 
632*6d67aabdSBjoern A. Zeeb 	if (dmac_err & B_BE_P_AXIDMA_ERR_INT) {
633*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_BE_PL_AXIDMA_IDCT_MSK=0x%08x\n",
634*6d67aabdSBjoern A. Zeeb 			   rtw89_mac_mem_read(rtwdev, R_BE_PL_AXIDMA_IDCT_MSK,
635*6d67aabdSBjoern A. Zeeb 					      RTW89_MAC_MEM_AXIDMA));
636*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_BE_PL_AXIDMA_IDCT=0x%08x\n",
637*6d67aabdSBjoern A. Zeeb 			   rtw89_mac_mem_read(rtwdev, R_BE_PL_AXIDMA_IDCT,
638*6d67aabdSBjoern A. Zeeb 					      RTW89_MAC_MEM_AXIDMA));
639*6d67aabdSBjoern A. Zeeb 	}
640*6d67aabdSBjoern A. Zeeb 
641*6d67aabdSBjoern A. Zeeb 	if (dmac_err & B_BE_MLO_ERR_INT) {
642*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_BE_MLO_ERR_IDCT_IMR=0x%08x\n",
643*6d67aabdSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_BE_MLO_ERR_IDCT_IMR));
644*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_BE_PKTIN_ERR_ISR=0x%08x\n",
645*6d67aabdSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_BE_MLO_ERR_IDCT_ISR));
646*6d67aabdSBjoern A. Zeeb 	}
647*6d67aabdSBjoern A. Zeeb 
648*6d67aabdSBjoern A. Zeeb 	if (dmac_err & B_BE_PLRLS_ERR_INT) {
649*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_BE_PLRLS_ERR_IMR=0x%08x\n",
650*6d67aabdSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_BE_PLRLS_ERR_IMR));
651*6d67aabdSBjoern A. Zeeb 		rtw89_info(rtwdev, "R_BE_PLRLS_ERR_ISR=0x%08x\n",
652*6d67aabdSBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_BE_PLRLS_ERR_ISR));
653*6d67aabdSBjoern A. Zeeb 	}
654*6d67aabdSBjoern A. Zeeb }
655*6d67aabdSBjoern A. Zeeb 
656*6d67aabdSBjoern A. Zeeb static void rtw89_mac_dump_cmac_err_status_ax(struct rtw89_dev *rtwdev,
657e2340276SBjoern A. Zeeb 					      u8 band)
658e2340276SBjoern A. Zeeb {
659e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
660e2340276SBjoern A. Zeeb 	u32 offset = 0;
661e2340276SBjoern A. Zeeb 	u32 cmac_err;
662e2340276SBjoern A. Zeeb 	int ret;
663e2340276SBjoern A. Zeeb 
664e2340276SBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, band, RTW89_CMAC_SEL);
665e2340276SBjoern A. Zeeb 	if (ret) {
666e2340276SBjoern A. Zeeb 		if (band)
667e2340276SBjoern A. Zeeb 			rtw89_warn(rtwdev, "[CMAC] : CMAC1 not enabled\n");
668e2340276SBjoern A. Zeeb 		else
669e2340276SBjoern A. Zeeb 			rtw89_warn(rtwdev, "[CMAC] : CMAC0 not enabled\n");
670e2340276SBjoern A. Zeeb 		return;
671e2340276SBjoern A. Zeeb 	}
672e2340276SBjoern A. Zeeb 
673e2340276SBjoern A. Zeeb 	if (band)
674e2340276SBjoern A. Zeeb 		offset = RTW89_MAC_AX_BAND_REG_OFFSET;
675e2340276SBjoern A. Zeeb 
676e2340276SBjoern A. Zeeb 	cmac_err = rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset);
677e2340276SBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_CMAC_ERR_ISR [%d]=0x%08x\n", band,
678e2340276SBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset));
679e2340276SBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_CMAC_FUNC_EN [%d]=0x%08x\n", band,
680e2340276SBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN + offset));
681e2340276SBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_CK_EN [%d]=0x%08x\n", band,
682e2340276SBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_CK_EN + offset));
683e2340276SBjoern A. Zeeb 
6848e93258fSBjoern A. Zeeb 	if (cmac_err & B_AX_SCHEDULE_TOP_ERR_IND) {
685e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_IMR [%d]=0x%08x\n", band,
686e2340276SBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_IMR + offset));
687e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_ISR [%d]=0x%08x\n", band,
688e2340276SBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_ISR + offset));
6898e93258fSBjoern A. Zeeb 	}
6908e93258fSBjoern A. Zeeb 
6918e93258fSBjoern A. Zeeb 	if (cmac_err & B_AX_PTCL_TOP_ERR_IND) {
692e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PTCL_IMR0 [%d]=0x%08x\n", band,
693e2340276SBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PTCL_IMR0 + offset));
694e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_PTCL_ISR0 [%d]=0x%08x\n", band,
695e2340276SBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_PTCL_ISR0 + offset));
6968e93258fSBjoern A. Zeeb 	}
6978e93258fSBjoern A. Zeeb 
6988e93258fSBjoern A. Zeeb 	if (cmac_err & B_AX_DMA_TOP_ERR_IND) {
699e2340276SBjoern A. Zeeb 		if (chip->chip_id == RTL8852C) {
700e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_RX_ERR_FLAG [%d]=0x%08x\n", band,
701e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG + offset));
702e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_RX_ERR_FLAG_IMR [%d]=0x%08x\n", band,
703e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG_IMR + offset));
704e2340276SBjoern A. Zeeb 		} else {
705e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_DLE_CTRL [%d]=0x%08x\n", band,
706e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_DLE_CTRL + offset));
707e2340276SBjoern A. Zeeb 		}
7088e93258fSBjoern A. Zeeb 	}
7098e93258fSBjoern A. Zeeb 
710e2340276SBjoern A. Zeeb 	if (cmac_err & B_AX_DMA_TOP_ERR_IND || cmac_err & B_AX_WMAC_RX_ERR_IND) {
711e2340276SBjoern A. Zeeb 		if (chip->chip_id == RTL8852C) {
712e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_ISR [%d]=0x%08x\n", band,
713e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR + offset));
714e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n", band,
715e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset));
716e2340276SBjoern A. Zeeb 		} else {
717e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n", band,
718e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset));
719e2340276SBjoern A. Zeeb 		}
7208e93258fSBjoern A. Zeeb 	}
7218e93258fSBjoern A. Zeeb 
7228e93258fSBjoern A. Zeeb 	if (cmac_err & B_AX_TXPWR_CTRL_ERR_IND) {
723e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_TXPWR_IMR [%d]=0x%08x\n", band,
724e2340276SBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_TXPWR_IMR + offset));
725e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_TXPWR_ISR [%d]=0x%08x\n", band,
726e2340276SBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_TXPWR_ISR + offset));
7278e93258fSBjoern A. Zeeb 	}
7288e93258fSBjoern A. Zeeb 
7298e93258fSBjoern A. Zeeb 	if (cmac_err & B_AX_WMAC_TX_ERR_IND) {
730e2340276SBjoern A. Zeeb 		if (chip->chip_id == RTL8852C) {
731e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_TRXPTCL_ERROR_INDICA [%d]=0x%08x\n", band,
732e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA + offset));
733e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_TRXPTCL_ERROR_INDICA_MASK [%d]=0x%08x\n", band,
734e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA_MASK + offset));
735e2340276SBjoern A. Zeeb 		} else {
736e2340276SBjoern A. Zeeb 			rtw89_info(rtwdev, "R_AX_TMAC_ERR_IMR_ISR [%d]=0x%08x\n", band,
737e2340276SBjoern A. Zeeb 				   rtw89_read32(rtwdev, R_AX_TMAC_ERR_IMR_ISR + offset));
7388e93258fSBjoern A. Zeeb 		}
739e2340276SBjoern A. Zeeb 		rtw89_info(rtwdev, "R_AX_DBGSEL_TRXPTCL [%d]=0x%08x\n", band,
740e2340276SBjoern A. Zeeb 			   rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL + offset));
741e2340276SBjoern A. Zeeb 	}
742e2340276SBjoern A. Zeeb 
743e2340276SBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_CMAC_ERR_IMR [%d]=0x%08x\n", band,
744e2340276SBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_CMAC_ERR_IMR + offset));
745e2340276SBjoern A. Zeeb }
746e2340276SBjoern A. Zeeb 
747*6d67aabdSBjoern A. Zeeb static void rtw89_mac_dump_err_status_ax(struct rtw89_dev *rtwdev,
748e2340276SBjoern A. Zeeb 					 enum mac_ax_err_info err)
749e2340276SBjoern A. Zeeb {
750e2340276SBjoern A. Zeeb 	if (err != MAC_AX_ERR_L1_ERR_DMAC &&
751e2340276SBjoern A. Zeeb 	    err != MAC_AX_ERR_L0_PROMOTE_TO_L1 &&
752e2340276SBjoern A. Zeeb 	    err != MAC_AX_ERR_L0_ERR_CMAC0 &&
753e2340276SBjoern A. Zeeb 	    err != MAC_AX_ERR_L0_ERR_CMAC1 &&
754e2340276SBjoern A. Zeeb 	    err != MAC_AX_ERR_RXI300)
755e2340276SBjoern A. Zeeb 		return;
756e2340276SBjoern A. Zeeb 
757e2340276SBjoern A. Zeeb 	rtw89_info(rtwdev, "--->\nerr=0x%x\n", err);
758e2340276SBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_SER_DBG_INFO =0x%08x\n",
759e2340276SBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_SER_DBG_INFO));
760*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "R_AX_SER_DBG_INFO =0x%08x\n",
761*6d67aabdSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_SER_DBG_INFO));
762*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "DBG Counter 1 (R_AX_DRV_FW_HSK_4)=0x%08x\n",
763*6d67aabdSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_DRV_FW_HSK_4));
764*6d67aabdSBjoern A. Zeeb 	rtw89_info(rtwdev, "DBG Counter 2 (R_AX_DRV_FW_HSK_5)=0x%08x\n",
765*6d67aabdSBjoern A. Zeeb 		   rtw89_read32(rtwdev, R_AX_DRV_FW_HSK_5));
766e2340276SBjoern A. Zeeb 
767e2340276SBjoern A. Zeeb 	rtw89_mac_dump_dmac_err_status(rtwdev);
768*6d67aabdSBjoern A. Zeeb 	rtw89_mac_dump_cmac_err_status_ax(rtwdev, RTW89_MAC_0);
769*6d67aabdSBjoern A. Zeeb 	rtw89_mac_dump_cmac_err_status_ax(rtwdev, RTW89_MAC_1);
7708e93258fSBjoern A. Zeeb 
7718e93258fSBjoern A. Zeeb 	rtwdev->hci.ops->dump_err_status(rtwdev);
7728e93258fSBjoern A. Zeeb 
7738e93258fSBjoern A. Zeeb 	if (err == MAC_AX_ERR_L0_PROMOTE_TO_L1)
7748e93258fSBjoern A. Zeeb 		rtw89_mac_dump_l0_to_l1(rtwdev, err);
7758e93258fSBjoern A. Zeeb 
7768e93258fSBjoern A. Zeeb 	rtw89_info(rtwdev, "<---\n");
7778e93258fSBjoern A. Zeeb }
7788e93258fSBjoern A. Zeeb 
779e2340276SBjoern A. Zeeb static bool rtw89_mac_suppress_log(struct rtw89_dev *rtwdev, u32 err)
780e2340276SBjoern A. Zeeb {
781e2340276SBjoern A. Zeeb 	struct rtw89_ser *ser = &rtwdev->ser;
782e2340276SBjoern A. Zeeb 	u32 dmac_err, imr, isr;
783e2340276SBjoern A. Zeeb 	int ret;
784e2340276SBjoern A. Zeeb 
785e2340276SBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8852C) {
786e2340276SBjoern A. Zeeb 		ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
787e2340276SBjoern A. Zeeb 		if (ret)
788e2340276SBjoern A. Zeeb 			return true;
789e2340276SBjoern A. Zeeb 
790e2340276SBjoern A. Zeeb 		if (err == MAC_AX_ERR_L1_ERR_DMAC) {
791e2340276SBjoern A. Zeeb 			dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
792e2340276SBjoern A. Zeeb 			imr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR);
793e2340276SBjoern A. Zeeb 			isr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR);
794e2340276SBjoern A. Zeeb 
795e2340276SBjoern A. Zeeb 			if ((dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) &&
796e2340276SBjoern A. Zeeb 			    ((isr & imr) & B_AX_B0_ISR_ERR_CMDPSR_FRZTO)) {
797e2340276SBjoern A. Zeeb 				set_bit(RTW89_SER_SUPPRESS_LOG, ser->flags);
798e2340276SBjoern A. Zeeb 				return true;
799e2340276SBjoern A. Zeeb 			}
800e2340276SBjoern A. Zeeb 		} else if (err == MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE) {
801e2340276SBjoern A. Zeeb 			if (test_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
802e2340276SBjoern A. Zeeb 				return true;
803e2340276SBjoern A. Zeeb 		} else if (err == MAC_AX_ERR_L1_RESET_RECOVERY_DONE) {
804e2340276SBjoern A. Zeeb 			if (test_and_clear_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
805e2340276SBjoern A. Zeeb 				return true;
806e2340276SBjoern A. Zeeb 		}
807e2340276SBjoern A. Zeeb 	}
808e2340276SBjoern A. Zeeb 
809e2340276SBjoern A. Zeeb 	return false;
810e2340276SBjoern A. Zeeb }
811e2340276SBjoern A. Zeeb 
8128e93258fSBjoern A. Zeeb u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
8138e93258fSBjoern A. Zeeb {
814*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
8158e93258fSBjoern A. Zeeb 	u32 err, err_scnr;
8168e93258fSBjoern A. Zeeb 	int ret;
8178e93258fSBjoern A. Zeeb 
8188e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read32, err, (err != 0), 1000, 100000,
8198e93258fSBjoern A. Zeeb 				false, rtwdev, R_AX_HALT_C2H_CTRL);
8208e93258fSBjoern A. Zeeb 	if (ret) {
8218e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "Polling FW err status fail\n");
8228e93258fSBjoern A. Zeeb 		return ret;
8238e93258fSBjoern A. Zeeb 	}
8248e93258fSBjoern A. Zeeb 
8258e93258fSBjoern A. Zeeb 	err = rtw89_read32(rtwdev, R_AX_HALT_C2H);
8268e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_HALT_C2H_CTRL, 0);
8278e93258fSBjoern A. Zeeb 
8288e93258fSBjoern A. Zeeb 	err_scnr = RTW89_ERROR_SCENARIO(err);
8298e93258fSBjoern A. Zeeb 	if (err_scnr == RTW89_WCPU_CPU_EXCEPTION)
8308e93258fSBjoern A. Zeeb 		err = MAC_AX_ERR_CPU_EXCEPTION;
8318e93258fSBjoern A. Zeeb 	else if (err_scnr == RTW89_WCPU_ASSERTION)
8328e93258fSBjoern A. Zeeb 		err = MAC_AX_ERR_ASSERTION;
833e2340276SBjoern A. Zeeb 	else if (err_scnr == RTW89_RXI300_ERROR)
834e2340276SBjoern A. Zeeb 		err = MAC_AX_ERR_RXI300;
835e2340276SBjoern A. Zeeb 
836e2340276SBjoern A. Zeeb 	if (rtw89_mac_suppress_log(rtwdev, err))
837e2340276SBjoern A. Zeeb 		return err;
8388e93258fSBjoern A. Zeeb 
8398e93258fSBjoern A. Zeeb 	rtw89_fw_st_dbg_dump(rtwdev);
840*6d67aabdSBjoern A. Zeeb 	mac->dump_err_status(rtwdev, err);
8418e93258fSBjoern A. Zeeb 
8428e93258fSBjoern A. Zeeb 	return err;
8438e93258fSBjoern A. Zeeb }
8448e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_get_err_status);
8458e93258fSBjoern A. Zeeb 
8468e93258fSBjoern A. Zeeb int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
8478e93258fSBjoern A. Zeeb {
848e2340276SBjoern A. Zeeb 	struct rtw89_ser *ser = &rtwdev->ser;
8498e93258fSBjoern A. Zeeb 	u32 halt;
8508e93258fSBjoern A. Zeeb 	int ret = 0;
8518e93258fSBjoern A. Zeeb 
8528e93258fSBjoern A. Zeeb 	if (err > MAC_AX_SET_ERR_MAX) {
8538e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "Bad set-err-status value 0x%08x\n", err);
8548e93258fSBjoern A. Zeeb 		return -EINVAL;
8558e93258fSBjoern A. Zeeb 	}
8568e93258fSBjoern A. Zeeb 
8578e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read32, halt, (halt == 0x0), 1000,
8588e93258fSBjoern A. Zeeb 				100000, false, rtwdev, R_AX_HALT_H2C_CTRL);
8598e93258fSBjoern A. Zeeb 	if (ret) {
8608e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "FW doesn't receive previous msg\n");
8618e93258fSBjoern A. Zeeb 		return -EFAULT;
8628e93258fSBjoern A. Zeeb 	}
8638e93258fSBjoern A. Zeeb 
8648e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_HALT_H2C, err);
865e2340276SBjoern A. Zeeb 
866e2340276SBjoern A. Zeeb 	if (ser->prehandle_l1 &&
867e2340276SBjoern A. Zeeb 	    (err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN))
868e2340276SBjoern A. Zeeb 		return 0;
869e2340276SBjoern A. Zeeb 
8708e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, B_AX_HALT_H2C_TRIGGER);
8718e93258fSBjoern A. Zeeb 
8728e93258fSBjoern A. Zeeb 	return 0;
8738e93258fSBjoern A. Zeeb }
8748e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_set_err_status);
8758e93258fSBjoern A. Zeeb 
8768e93258fSBjoern A. Zeeb static int hfc_reset_param(struct rtw89_dev *rtwdev)
8778e93258fSBjoern A. Zeeb {
8788e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
8798e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param_ini param_ini = {NULL};
8808e93258fSBjoern A. Zeeb 	u8 qta_mode = rtwdev->mac.dle_info.qta_mode;
8818e93258fSBjoern A. Zeeb 
8828e93258fSBjoern A. Zeeb 	switch (rtwdev->hci.type) {
8838e93258fSBjoern A. Zeeb 	case RTW89_HCI_TYPE_PCIE:
8848e93258fSBjoern A. Zeeb 		param_ini = rtwdev->chip->hfc_param_ini[qta_mode];
8858e93258fSBjoern A. Zeeb 		param->en = 0;
8868e93258fSBjoern A. Zeeb 		break;
8878e93258fSBjoern A. Zeeb 	default:
8888e93258fSBjoern A. Zeeb 		return -EINVAL;
8898e93258fSBjoern A. Zeeb 	}
8908e93258fSBjoern A. Zeeb 
8918e93258fSBjoern A. Zeeb 	if (param_ini.pub_cfg)
8928e93258fSBjoern A. Zeeb 		param->pub_cfg = *param_ini.pub_cfg;
8938e93258fSBjoern A. Zeeb 
894e2340276SBjoern A. Zeeb 	if (param_ini.prec_cfg)
8958e93258fSBjoern A. Zeeb 		param->prec_cfg = *param_ini.prec_cfg;
8968e93258fSBjoern A. Zeeb 
8978e93258fSBjoern A. Zeeb 	if (param_ini.ch_cfg)
8988e93258fSBjoern A. Zeeb 		param->ch_cfg = param_ini.ch_cfg;
8998e93258fSBjoern A. Zeeb 
9008e93258fSBjoern A. Zeeb 	memset(&param->ch_info, 0, sizeof(param->ch_info));
9018e93258fSBjoern A. Zeeb 	memset(&param->pub_info, 0, sizeof(param->pub_info));
9028e93258fSBjoern A. Zeeb 	param->mode = param_ini.mode;
9038e93258fSBjoern A. Zeeb 
9048e93258fSBjoern A. Zeeb 	return 0;
9058e93258fSBjoern A. Zeeb }
9068e93258fSBjoern A. Zeeb 
9078e93258fSBjoern A. Zeeb static int hfc_ch_cfg_chk(struct rtw89_dev *rtwdev, u8 ch)
9088e93258fSBjoern A. Zeeb {
9098e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
9108e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_ch_cfg *ch_cfg = param->ch_cfg;
9118e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_pub_cfg *pub_cfg = &param->pub_cfg;
9128e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_prec_cfg *prec_cfg = &param->prec_cfg;
9138e93258fSBjoern A. Zeeb 
9148e93258fSBjoern A. Zeeb 	if (ch >= RTW89_DMA_CH_NUM)
9158e93258fSBjoern A. Zeeb 		return -EINVAL;
9168e93258fSBjoern A. Zeeb 
9178e93258fSBjoern A. Zeeb 	if ((ch_cfg[ch].min && ch_cfg[ch].min < prec_cfg->ch011_prec) ||
9188e93258fSBjoern A. Zeeb 	    ch_cfg[ch].max > pub_cfg->pub_max)
9198e93258fSBjoern A. Zeeb 		return -EINVAL;
9208e93258fSBjoern A. Zeeb 	if (ch_cfg[ch].grp >= grp_num)
9218e93258fSBjoern A. Zeeb 		return -EINVAL;
9228e93258fSBjoern A. Zeeb 
9238e93258fSBjoern A. Zeeb 	return 0;
9248e93258fSBjoern A. Zeeb }
9258e93258fSBjoern A. Zeeb 
9268e93258fSBjoern A. Zeeb static int hfc_pub_info_chk(struct rtw89_dev *rtwdev)
9278e93258fSBjoern A. Zeeb {
9288e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
9298e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_pub_cfg *cfg = &param->pub_cfg;
9308e93258fSBjoern A. Zeeb 	struct rtw89_hfc_pub_info *info = &param->pub_info;
9318e93258fSBjoern A. Zeeb 
9328e93258fSBjoern A. Zeeb 	if (info->g0_used + info->g1_used + info->pub_aval != cfg->pub_max) {
9338e93258fSBjoern A. Zeeb 		if (rtwdev->chip->chip_id == RTL8852A)
9348e93258fSBjoern A. Zeeb 			return 0;
9358e93258fSBjoern A. Zeeb 		else
9368e93258fSBjoern A. Zeeb 			return -EFAULT;
9378e93258fSBjoern A. Zeeb 	}
9388e93258fSBjoern A. Zeeb 
9398e93258fSBjoern A. Zeeb 	return 0;
9408e93258fSBjoern A. Zeeb }
9418e93258fSBjoern A. Zeeb 
9428e93258fSBjoern A. Zeeb static int hfc_pub_cfg_chk(struct rtw89_dev *rtwdev)
9438e93258fSBjoern A. Zeeb {
9448e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
9458e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_pub_cfg *pub_cfg = &param->pub_cfg;
9468e93258fSBjoern A. Zeeb 
9478e93258fSBjoern A. Zeeb 	if (pub_cfg->grp0 + pub_cfg->grp1 != pub_cfg->pub_max)
9488e93258fSBjoern A. Zeeb 		return -EFAULT;
9498e93258fSBjoern A. Zeeb 
9508e93258fSBjoern A. Zeeb 	return 0;
9518e93258fSBjoern A. Zeeb }
9528e93258fSBjoern A. Zeeb 
9538e93258fSBjoern A. Zeeb static int hfc_ch_ctrl(struct rtw89_dev *rtwdev, u8 ch)
9548e93258fSBjoern A. Zeeb {
9558e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
9568e93258fSBjoern A. Zeeb 	const struct rtw89_page_regs *regs = chip->page_regs;
9578e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
9588e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg;
9598e93258fSBjoern A. Zeeb 	int ret = 0;
9608e93258fSBjoern A. Zeeb 	u32 val = 0;
9618e93258fSBjoern A. Zeeb 
9628e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
9638e93258fSBjoern A. Zeeb 	if (ret)
9648e93258fSBjoern A. Zeeb 		return ret;
9658e93258fSBjoern A. Zeeb 
9668e93258fSBjoern A. Zeeb 	ret = hfc_ch_cfg_chk(rtwdev, ch);
9678e93258fSBjoern A. Zeeb 	if (ret)
9688e93258fSBjoern A. Zeeb 		return ret;
9698e93258fSBjoern A. Zeeb 
9708e93258fSBjoern A. Zeeb 	if (ch > RTW89_DMA_B1HI)
9718e93258fSBjoern A. Zeeb 		return -EINVAL;
9728e93258fSBjoern A. Zeeb 
9738e93258fSBjoern A. Zeeb 	val = u32_encode_bits(cfg[ch].min, B_AX_MIN_PG_MASK) |
9748e93258fSBjoern A. Zeeb 	      u32_encode_bits(cfg[ch].max, B_AX_MAX_PG_MASK) |
9758e93258fSBjoern A. Zeeb 	      (cfg[ch].grp ? B_AX_GRP : 0);
9768e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, regs->ach_page_ctrl + ch * 4, val);
9778e93258fSBjoern A. Zeeb 
9788e93258fSBjoern A. Zeeb 	return 0;
9798e93258fSBjoern A. Zeeb }
9808e93258fSBjoern A. Zeeb 
9818e93258fSBjoern A. Zeeb static int hfc_upd_ch_info(struct rtw89_dev *rtwdev, u8 ch)
9828e93258fSBjoern A. Zeeb {
9838e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
9848e93258fSBjoern A. Zeeb 	const struct rtw89_page_regs *regs = chip->page_regs;
9858e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
9868e93258fSBjoern A. Zeeb 	struct rtw89_hfc_ch_info *info = param->ch_info;
9878e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg;
9888e93258fSBjoern A. Zeeb 	u32 val;
9898e93258fSBjoern A. Zeeb 	u32 ret;
9908e93258fSBjoern A. Zeeb 
9918e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
9928e93258fSBjoern A. Zeeb 	if (ret)
9938e93258fSBjoern A. Zeeb 		return ret;
9948e93258fSBjoern A. Zeeb 
9958e93258fSBjoern A. Zeeb 	if (ch > RTW89_DMA_H2C)
9968e93258fSBjoern A. Zeeb 		return -EINVAL;
9978e93258fSBjoern A. Zeeb 
9988e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->ach_page_info + ch * 4);
9998e93258fSBjoern A. Zeeb 	info[ch].aval = u32_get_bits(val, B_AX_AVAL_PG_MASK);
10008e93258fSBjoern A. Zeeb 	if (ch < RTW89_DMA_H2C)
10018e93258fSBjoern A. Zeeb 		info[ch].used = u32_get_bits(val, B_AX_USE_PG_MASK);
10028e93258fSBjoern A. Zeeb 	else
10038e93258fSBjoern A. Zeeb 		info[ch].used = cfg[ch].min - info[ch].aval;
10048e93258fSBjoern A. Zeeb 
10058e93258fSBjoern A. Zeeb 	return 0;
10068e93258fSBjoern A. Zeeb }
10078e93258fSBjoern A. Zeeb 
10088e93258fSBjoern A. Zeeb static int hfc_pub_ctrl(struct rtw89_dev *rtwdev)
10098e93258fSBjoern A. Zeeb {
10108e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
10118e93258fSBjoern A. Zeeb 	const struct rtw89_page_regs *regs = chip->page_regs;
10128e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_pub_cfg *cfg = &rtwdev->mac.hfc_param.pub_cfg;
10138e93258fSBjoern A. Zeeb 	u32 val;
10148e93258fSBjoern A. Zeeb 	int ret;
10158e93258fSBjoern A. Zeeb 
10168e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
10178e93258fSBjoern A. Zeeb 	if (ret)
10188e93258fSBjoern A. Zeeb 		return ret;
10198e93258fSBjoern A. Zeeb 
10208e93258fSBjoern A. Zeeb 	ret = hfc_pub_cfg_chk(rtwdev);
10218e93258fSBjoern A. Zeeb 	if (ret)
10228e93258fSBjoern A. Zeeb 		return ret;
10238e93258fSBjoern A. Zeeb 
10248e93258fSBjoern A. Zeeb 	val = u32_encode_bits(cfg->grp0, B_AX_PUBPG_G0_MASK) |
10258e93258fSBjoern A. Zeeb 	      u32_encode_bits(cfg->grp1, B_AX_PUBPG_G1_MASK);
10268e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, regs->pub_page_ctrl1, val);
10278e93258fSBjoern A. Zeeb 
10288e93258fSBjoern A. Zeeb 	val = u32_encode_bits(cfg->wp_thrd, B_AX_WP_THRD_MASK);
10298e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, regs->wp_page_ctrl2, val);
10308e93258fSBjoern A. Zeeb 
10318e93258fSBjoern A. Zeeb 	return 0;
10328e93258fSBjoern A. Zeeb }
10338e93258fSBjoern A. Zeeb 
1034*6d67aabdSBjoern A. Zeeb static void hfc_get_mix_info_ax(struct rtw89_dev *rtwdev)
10358e93258fSBjoern A. Zeeb {
10368e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
10378e93258fSBjoern A. Zeeb 	const struct rtw89_page_regs *regs = chip->page_regs;
10388e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
10398e93258fSBjoern A. Zeeb 	struct rtw89_hfc_pub_cfg *pub_cfg = &param->pub_cfg;
10408e93258fSBjoern A. Zeeb 	struct rtw89_hfc_prec_cfg *prec_cfg = &param->prec_cfg;
10418e93258fSBjoern A. Zeeb 	struct rtw89_hfc_pub_info *info = &param->pub_info;
10428e93258fSBjoern A. Zeeb 	u32 val;
10438e93258fSBjoern A. Zeeb 
10448e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->pub_page_info1);
10458e93258fSBjoern A. Zeeb 	info->g0_used = u32_get_bits(val, B_AX_G0_USE_PG_MASK);
10468e93258fSBjoern A. Zeeb 	info->g1_used = u32_get_bits(val, B_AX_G1_USE_PG_MASK);
10478e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->pub_page_info3);
10488e93258fSBjoern A. Zeeb 	info->g0_aval = u32_get_bits(val, B_AX_G0_AVAL_PG_MASK);
10498e93258fSBjoern A. Zeeb 	info->g1_aval = u32_get_bits(val, B_AX_G1_AVAL_PG_MASK);
10508e93258fSBjoern A. Zeeb 	info->pub_aval =
10518e93258fSBjoern A. Zeeb 		u32_get_bits(rtw89_read32(rtwdev, regs->pub_page_info2),
10528e93258fSBjoern A. Zeeb 			     B_AX_PUB_AVAL_PG_MASK);
10538e93258fSBjoern A. Zeeb 	info->wp_aval =
10548e93258fSBjoern A. Zeeb 		u32_get_bits(rtw89_read32(rtwdev, regs->wp_page_info1),
10558e93258fSBjoern A. Zeeb 			     B_AX_WP_AVAL_PG_MASK);
10568e93258fSBjoern A. Zeeb 
10578e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->hci_fc_ctrl);
10588e93258fSBjoern A. Zeeb 	param->en = val & B_AX_HCI_FC_EN ? 1 : 0;
10598e93258fSBjoern A. Zeeb 	param->h2c_en = val & B_AX_HCI_FC_CH12_EN ? 1 : 0;
10608e93258fSBjoern A. Zeeb 	param->mode = u32_get_bits(val, B_AX_HCI_FC_MODE_MASK);
10618e93258fSBjoern A. Zeeb 	prec_cfg->ch011_full_cond =
10628e93258fSBjoern A. Zeeb 		u32_get_bits(val, B_AX_HCI_FC_WD_FULL_COND_MASK);
10638e93258fSBjoern A. Zeeb 	prec_cfg->h2c_full_cond =
10648e93258fSBjoern A. Zeeb 		u32_get_bits(val, B_AX_HCI_FC_CH12_FULL_COND_MASK);
10658e93258fSBjoern A. Zeeb 	prec_cfg->wp_ch07_full_cond =
10668e93258fSBjoern A. Zeeb 		u32_get_bits(val, B_AX_HCI_FC_WP_CH07_FULL_COND_MASK);
10678e93258fSBjoern A. Zeeb 	prec_cfg->wp_ch811_full_cond =
10688e93258fSBjoern A. Zeeb 		u32_get_bits(val, B_AX_HCI_FC_WP_CH811_FULL_COND_MASK);
10698e93258fSBjoern A. Zeeb 
10708e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->ch_page_ctrl);
10718e93258fSBjoern A. Zeeb 	prec_cfg->ch011_prec = u32_get_bits(val, B_AX_PREC_PAGE_CH011_MASK);
10728e93258fSBjoern A. Zeeb 	prec_cfg->h2c_prec = u32_get_bits(val, B_AX_PREC_PAGE_CH12_MASK);
10738e93258fSBjoern A. Zeeb 
10748e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->pub_page_ctrl2);
10758e93258fSBjoern A. Zeeb 	pub_cfg->pub_max = u32_get_bits(val, B_AX_PUBPG_ALL_MASK);
10768e93258fSBjoern A. Zeeb 
10778e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->wp_page_ctrl1);
10788e93258fSBjoern A. Zeeb 	prec_cfg->wp_ch07_prec = u32_get_bits(val, B_AX_PREC_PAGE_WP_CH07_MASK);
10798e93258fSBjoern A. Zeeb 	prec_cfg->wp_ch811_prec = u32_get_bits(val, B_AX_PREC_PAGE_WP_CH811_MASK);
10808e93258fSBjoern A. Zeeb 
10818e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->wp_page_ctrl2);
10828e93258fSBjoern A. Zeeb 	pub_cfg->wp_thrd = u32_get_bits(val, B_AX_WP_THRD_MASK);
10838e93258fSBjoern A. Zeeb 
10848e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->pub_page_ctrl1);
10858e93258fSBjoern A. Zeeb 	pub_cfg->grp0 = u32_get_bits(val, B_AX_PUBPG_G0_MASK);
10868e93258fSBjoern A. Zeeb 	pub_cfg->grp1 = u32_get_bits(val, B_AX_PUBPG_G1_MASK);
1087*6d67aabdSBjoern A. Zeeb }
1088*6d67aabdSBjoern A. Zeeb 
1089*6d67aabdSBjoern A. Zeeb static int hfc_upd_mix_info(struct rtw89_dev *rtwdev)
1090*6d67aabdSBjoern A. Zeeb {
1091*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
1092*6d67aabdSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
1093*6d67aabdSBjoern A. Zeeb 	int ret;
1094*6d67aabdSBjoern A. Zeeb 
1095*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
1096*6d67aabdSBjoern A. Zeeb 	if (ret)
1097*6d67aabdSBjoern A. Zeeb 		return ret;
1098*6d67aabdSBjoern A. Zeeb 
1099*6d67aabdSBjoern A. Zeeb 	mac->hfc_get_mix_info(rtwdev);
11008e93258fSBjoern A. Zeeb 
11018e93258fSBjoern A. Zeeb 	ret = hfc_pub_info_chk(rtwdev);
11028e93258fSBjoern A. Zeeb 	if (param->en && ret)
11038e93258fSBjoern A. Zeeb 		return ret;
11048e93258fSBjoern A. Zeeb 
11058e93258fSBjoern A. Zeeb 	return 0;
11068e93258fSBjoern A. Zeeb }
11078e93258fSBjoern A. Zeeb 
1108*6d67aabdSBjoern A. Zeeb static void hfc_h2c_cfg_ax(struct rtw89_dev *rtwdev)
11098e93258fSBjoern A. Zeeb {
11108e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
11118e93258fSBjoern A. Zeeb 	const struct rtw89_page_regs *regs = chip->page_regs;
11128e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
11138e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_prec_cfg *prec_cfg = &param->prec_cfg;
11148e93258fSBjoern A. Zeeb 	u32 val;
11158e93258fSBjoern A. Zeeb 
11168e93258fSBjoern A. Zeeb 	val = u32_encode_bits(prec_cfg->h2c_prec, B_AX_PREC_PAGE_CH12_MASK);
11178e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, regs->ch_page_ctrl, val);
11188e93258fSBjoern A. Zeeb 
11198e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, regs->hci_fc_ctrl,
11208e93258fSBjoern A. Zeeb 			   B_AX_HCI_FC_CH12_FULL_COND_MASK,
11218e93258fSBjoern A. Zeeb 			   prec_cfg->h2c_full_cond);
11228e93258fSBjoern A. Zeeb }
11238e93258fSBjoern A. Zeeb 
1124*6d67aabdSBjoern A. Zeeb static void hfc_mix_cfg_ax(struct rtw89_dev *rtwdev)
11258e93258fSBjoern A. Zeeb {
11268e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
11278e93258fSBjoern A. Zeeb 	const struct rtw89_page_regs *regs = chip->page_regs;
11288e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
11298e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_pub_cfg *pub_cfg = &param->pub_cfg;
11308e93258fSBjoern A. Zeeb 	const struct rtw89_hfc_prec_cfg *prec_cfg = &param->prec_cfg;
11318e93258fSBjoern A. Zeeb 	u32 val;
11328e93258fSBjoern A. Zeeb 
11338e93258fSBjoern A. Zeeb 	val = u32_encode_bits(prec_cfg->ch011_prec, B_AX_PREC_PAGE_CH011_MASK) |
11348e93258fSBjoern A. Zeeb 	      u32_encode_bits(prec_cfg->h2c_prec, B_AX_PREC_PAGE_CH12_MASK);
11358e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, regs->ch_page_ctrl, val);
11368e93258fSBjoern A. Zeeb 
11378e93258fSBjoern A. Zeeb 	val = u32_encode_bits(pub_cfg->pub_max, B_AX_PUBPG_ALL_MASK);
11388e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, regs->pub_page_ctrl2, val);
11398e93258fSBjoern A. Zeeb 
11408e93258fSBjoern A. Zeeb 	val = u32_encode_bits(prec_cfg->wp_ch07_prec,
11418e93258fSBjoern A. Zeeb 			      B_AX_PREC_PAGE_WP_CH07_MASK) |
11428e93258fSBjoern A. Zeeb 	      u32_encode_bits(prec_cfg->wp_ch811_prec,
11438e93258fSBjoern A. Zeeb 			      B_AX_PREC_PAGE_WP_CH811_MASK);
11448e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, regs->wp_page_ctrl1, val);
11458e93258fSBjoern A. Zeeb 
11468e93258fSBjoern A. Zeeb 	val = u32_replace_bits(rtw89_read32(rtwdev, regs->hci_fc_ctrl),
11478e93258fSBjoern A. Zeeb 			       param->mode, B_AX_HCI_FC_MODE_MASK);
11488e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, prec_cfg->ch011_full_cond,
11498e93258fSBjoern A. Zeeb 			       B_AX_HCI_FC_WD_FULL_COND_MASK);
11508e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, prec_cfg->h2c_full_cond,
11518e93258fSBjoern A. Zeeb 			       B_AX_HCI_FC_CH12_FULL_COND_MASK);
11528e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, prec_cfg->wp_ch07_full_cond,
11538e93258fSBjoern A. Zeeb 			       B_AX_HCI_FC_WP_CH07_FULL_COND_MASK);
11548e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, prec_cfg->wp_ch811_full_cond,
11558e93258fSBjoern A. Zeeb 			       B_AX_HCI_FC_WP_CH811_FULL_COND_MASK);
11568e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, regs->hci_fc_ctrl, val);
11578e93258fSBjoern A. Zeeb }
11588e93258fSBjoern A. Zeeb 
1159*6d67aabdSBjoern A. Zeeb static void hfc_func_en_ax(struct rtw89_dev *rtwdev, bool en, bool h2c_en)
11608e93258fSBjoern A. Zeeb {
11618e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
11628e93258fSBjoern A. Zeeb 	const struct rtw89_page_regs *regs = chip->page_regs;
11638e93258fSBjoern A. Zeeb 	struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
11648e93258fSBjoern A. Zeeb 	u32 val;
11658e93258fSBjoern A. Zeeb 
11668e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, regs->hci_fc_ctrl);
11678e93258fSBjoern A. Zeeb 	param->en = en;
11688e93258fSBjoern A. Zeeb 	param->h2c_en = h2c_en;
11698e93258fSBjoern A. Zeeb 	val = en ? (val | B_AX_HCI_FC_EN) : (val & ~B_AX_HCI_FC_EN);
11708e93258fSBjoern A. Zeeb 	val = h2c_en ? (val | B_AX_HCI_FC_CH12_EN) :
11718e93258fSBjoern A. Zeeb 			 (val & ~B_AX_HCI_FC_CH12_EN);
11728e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, regs->hci_fc_ctrl, val);
11738e93258fSBjoern A. Zeeb }
11748e93258fSBjoern A. Zeeb 
1175*6d67aabdSBjoern A. Zeeb int rtw89_mac_hfc_init(struct rtw89_dev *rtwdev, bool reset, bool en, bool h2c_en)
11768e93258fSBjoern A. Zeeb {
1177*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
1178e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
1179e2340276SBjoern A. Zeeb 	u32 dma_ch_mask = chip->dma_ch_mask;
11808e93258fSBjoern A. Zeeb 	u8 ch;
11818e93258fSBjoern A. Zeeb 	u32 ret = 0;
11828e93258fSBjoern A. Zeeb 
11838e93258fSBjoern A. Zeeb 	if (reset)
11848e93258fSBjoern A. Zeeb 		ret = hfc_reset_param(rtwdev);
11858e93258fSBjoern A. Zeeb 	if (ret)
11868e93258fSBjoern A. Zeeb 		return ret;
11878e93258fSBjoern A. Zeeb 
11888e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
11898e93258fSBjoern A. Zeeb 	if (ret)
11908e93258fSBjoern A. Zeeb 		return ret;
11918e93258fSBjoern A. Zeeb 
1192*6d67aabdSBjoern A. Zeeb 	mac->hfc_func_en(rtwdev, false, false);
11938e93258fSBjoern A. Zeeb 
11948e93258fSBjoern A. Zeeb 	if (!en && h2c_en) {
1195*6d67aabdSBjoern A. Zeeb 		mac->hfc_h2c_cfg(rtwdev);
1196*6d67aabdSBjoern A. Zeeb 		mac->hfc_func_en(rtwdev, en, h2c_en);
11978e93258fSBjoern A. Zeeb 		return ret;
11988e93258fSBjoern A. Zeeb 	}
11998e93258fSBjoern A. Zeeb 
12008e93258fSBjoern A. Zeeb 	for (ch = RTW89_DMA_ACH0; ch < RTW89_DMA_H2C; ch++) {
1201e2340276SBjoern A. Zeeb 		if (dma_ch_mask & BIT(ch))
1202e2340276SBjoern A. Zeeb 			continue;
12038e93258fSBjoern A. Zeeb 		ret = hfc_ch_ctrl(rtwdev, ch);
12048e93258fSBjoern A. Zeeb 		if (ret)
12058e93258fSBjoern A. Zeeb 			return ret;
12068e93258fSBjoern A. Zeeb 	}
12078e93258fSBjoern A. Zeeb 
12088e93258fSBjoern A. Zeeb 	ret = hfc_pub_ctrl(rtwdev);
12098e93258fSBjoern A. Zeeb 	if (ret)
12108e93258fSBjoern A. Zeeb 		return ret;
12118e93258fSBjoern A. Zeeb 
1212*6d67aabdSBjoern A. Zeeb 	mac->hfc_mix_cfg(rtwdev);
12138e93258fSBjoern A. Zeeb 	if (en || h2c_en) {
1214*6d67aabdSBjoern A. Zeeb 		mac->hfc_func_en(rtwdev, en, h2c_en);
12158e93258fSBjoern A. Zeeb 		udelay(10);
12168e93258fSBjoern A. Zeeb 	}
12178e93258fSBjoern A. Zeeb 	for (ch = RTW89_DMA_ACH0; ch < RTW89_DMA_H2C; ch++) {
1218e2340276SBjoern A. Zeeb 		if (dma_ch_mask & BIT(ch))
1219e2340276SBjoern A. Zeeb 			continue;
12208e93258fSBjoern A. Zeeb 		ret = hfc_upd_ch_info(rtwdev, ch);
12218e93258fSBjoern A. Zeeb 		if (ret)
12228e93258fSBjoern A. Zeeb 			return ret;
12238e93258fSBjoern A. Zeeb 	}
12248e93258fSBjoern A. Zeeb 	ret = hfc_upd_mix_info(rtwdev);
12258e93258fSBjoern A. Zeeb 
12268e93258fSBjoern A. Zeeb 	return ret;
12278e93258fSBjoern A. Zeeb }
12288e93258fSBjoern A. Zeeb 
12298e93258fSBjoern A. Zeeb #define PWR_POLL_CNT	2000
12308e93258fSBjoern A. Zeeb static int pwr_cmd_poll(struct rtw89_dev *rtwdev,
12318e93258fSBjoern A. Zeeb 			const struct rtw89_pwr_cfg *cfg)
12328e93258fSBjoern A. Zeeb {
12338e93258fSBjoern A. Zeeb 	u8 val = 0;
12348e93258fSBjoern A. Zeeb 	int ret;
12358e93258fSBjoern A. Zeeb 	u32 addr = cfg->base == PWR_INTF_MSK_SDIO ?
12368e93258fSBjoern A. Zeeb 		   cfg->addr | SDIO_LOCAL_BASE_ADDR : cfg->addr;
12378e93258fSBjoern A. Zeeb 
12388e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read8, val, !((val ^ cfg->val) & cfg->msk),
12398e93258fSBjoern A. Zeeb 				1000, 1000 * PWR_POLL_CNT, false, rtwdev, addr);
12408e93258fSBjoern A. Zeeb 
12418e93258fSBjoern A. Zeeb 	if (!ret)
12428e93258fSBjoern A. Zeeb 		return 0;
12438e93258fSBjoern A. Zeeb 
12448e93258fSBjoern A. Zeeb 	rtw89_warn(rtwdev, "[ERR] Polling timeout\n");
12458e93258fSBjoern A. Zeeb 	rtw89_warn(rtwdev, "[ERR] addr: %X, %X\n", addr, cfg->addr);
12468e93258fSBjoern A. Zeeb 	rtw89_warn(rtwdev, "[ERR] val: %X, %X\n", val, cfg->val);
12478e93258fSBjoern A. Zeeb 
12488e93258fSBjoern A. Zeeb 	return -EBUSY;
12498e93258fSBjoern A. Zeeb }
12508e93258fSBjoern A. Zeeb 
12518e93258fSBjoern A. Zeeb static int rtw89_mac_sub_pwr_seq(struct rtw89_dev *rtwdev, u8 cv_msk,
12528e93258fSBjoern A. Zeeb 				 u8 intf_msk, const struct rtw89_pwr_cfg *cfg)
12538e93258fSBjoern A. Zeeb {
12548e93258fSBjoern A. Zeeb 	const struct rtw89_pwr_cfg *cur_cfg;
12558e93258fSBjoern A. Zeeb 	u32 addr;
12568e93258fSBjoern A. Zeeb 	u8 val;
12578e93258fSBjoern A. Zeeb 
12588e93258fSBjoern A. Zeeb 	for (cur_cfg = cfg; cur_cfg->cmd != PWR_CMD_END; cur_cfg++) {
12598e93258fSBjoern A. Zeeb 		if (!(cur_cfg->intf_msk & intf_msk) ||
12608e93258fSBjoern A. Zeeb 		    !(cur_cfg->cv_msk & cv_msk))
12618e93258fSBjoern A. Zeeb 			continue;
12628e93258fSBjoern A. Zeeb 
12638e93258fSBjoern A. Zeeb 		switch (cur_cfg->cmd) {
12648e93258fSBjoern A. Zeeb 		case PWR_CMD_WRITE:
12658e93258fSBjoern A. Zeeb 			addr = cur_cfg->addr;
12668e93258fSBjoern A. Zeeb 
12678e93258fSBjoern A. Zeeb 			if (cur_cfg->base == PWR_BASE_SDIO)
12688e93258fSBjoern A. Zeeb 				addr |= SDIO_LOCAL_BASE_ADDR;
12698e93258fSBjoern A. Zeeb 
12708e93258fSBjoern A. Zeeb 			val = rtw89_read8(rtwdev, addr);
12718e93258fSBjoern A. Zeeb 			val &= ~(cur_cfg->msk);
12728e93258fSBjoern A. Zeeb 			val |= (cur_cfg->val & cur_cfg->msk);
12738e93258fSBjoern A. Zeeb 
12748e93258fSBjoern A. Zeeb 			rtw89_write8(rtwdev, addr, val);
12758e93258fSBjoern A. Zeeb 			break;
12768e93258fSBjoern A. Zeeb 		case PWR_CMD_POLL:
12778e93258fSBjoern A. Zeeb 			if (pwr_cmd_poll(rtwdev, cur_cfg))
12788e93258fSBjoern A. Zeeb 				return -EBUSY;
12798e93258fSBjoern A. Zeeb 			break;
12808e93258fSBjoern A. Zeeb 		case PWR_CMD_DELAY:
12818e93258fSBjoern A. Zeeb 			if (cur_cfg->val == PWR_DELAY_US)
12828e93258fSBjoern A. Zeeb 				udelay(cur_cfg->addr);
12838e93258fSBjoern A. Zeeb 			else
12848e93258fSBjoern A. Zeeb 				fsleep(cur_cfg->addr * 1000);
12858e93258fSBjoern A. Zeeb 			break;
12868e93258fSBjoern A. Zeeb 		default:
12878e93258fSBjoern A. Zeeb 			return -EINVAL;
12888e93258fSBjoern A. Zeeb 		}
12898e93258fSBjoern A. Zeeb 	}
12908e93258fSBjoern A. Zeeb 
12918e93258fSBjoern A. Zeeb 	return 0;
12928e93258fSBjoern A. Zeeb }
12938e93258fSBjoern A. Zeeb 
12948e93258fSBjoern A. Zeeb static int rtw89_mac_pwr_seq(struct rtw89_dev *rtwdev,
12958e93258fSBjoern A. Zeeb 			     const struct rtw89_pwr_cfg * const *cfg_seq)
12968e93258fSBjoern A. Zeeb {
12978e93258fSBjoern A. Zeeb 	int ret;
12988e93258fSBjoern A. Zeeb 
12998e93258fSBjoern A. Zeeb 	for (; *cfg_seq; cfg_seq++) {
13008e93258fSBjoern A. Zeeb 		ret = rtw89_mac_sub_pwr_seq(rtwdev, BIT(rtwdev->hal.cv),
13018e93258fSBjoern A. Zeeb 					    PWR_INTF_MSK_PCIE, *cfg_seq);
13028e93258fSBjoern A. Zeeb 		if (ret)
13038e93258fSBjoern A. Zeeb 			return -EBUSY;
13048e93258fSBjoern A. Zeeb 	}
13058e93258fSBjoern A. Zeeb 
13068e93258fSBjoern A. Zeeb 	return 0;
13078e93258fSBjoern A. Zeeb }
13088e93258fSBjoern A. Zeeb 
13098e93258fSBjoern A. Zeeb static enum rtw89_rpwm_req_pwr_state
13108e93258fSBjoern A. Zeeb rtw89_mac_get_req_pwr_state(struct rtw89_dev *rtwdev)
13118e93258fSBjoern A. Zeeb {
13128e93258fSBjoern A. Zeeb 	enum rtw89_rpwm_req_pwr_state state;
13138e93258fSBjoern A. Zeeb 
13148e93258fSBjoern A. Zeeb 	switch (rtwdev->ps_mode) {
13158e93258fSBjoern A. Zeeb 	case RTW89_PS_MODE_RFOFF:
13168e93258fSBjoern A. Zeeb 		state = RTW89_MAC_RPWM_REQ_PWR_STATE_BAND0_RFOFF;
13178e93258fSBjoern A. Zeeb 		break;
13188e93258fSBjoern A. Zeeb 	case RTW89_PS_MODE_CLK_GATED:
13198e93258fSBjoern A. Zeeb 		state = RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED;
13208e93258fSBjoern A. Zeeb 		break;
13218e93258fSBjoern A. Zeeb 	case RTW89_PS_MODE_PWR_GATED:
13228e93258fSBjoern A. Zeeb 		state = RTW89_MAC_RPWM_REQ_PWR_STATE_PWR_GATED;
13238e93258fSBjoern A. Zeeb 		break;
13248e93258fSBjoern A. Zeeb 	default:
13258e93258fSBjoern A. Zeeb 		state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;
13268e93258fSBjoern A. Zeeb 		break;
13278e93258fSBjoern A. Zeeb 	}
13288e93258fSBjoern A. Zeeb 	return state;
13298e93258fSBjoern A. Zeeb }
13308e93258fSBjoern A. Zeeb 
13318e93258fSBjoern A. Zeeb static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
13328e93258fSBjoern A. Zeeb 				enum rtw89_rpwm_req_pwr_state req_pwr_state,
13338e93258fSBjoern A. Zeeb 				bool notify_wake)
13348e93258fSBjoern A. Zeeb {
13358e93258fSBjoern A. Zeeb 	u16 request;
13368e93258fSBjoern A. Zeeb 
13378e93258fSBjoern A. Zeeb 	spin_lock_bh(&rtwdev->rpwm_lock);
13388e93258fSBjoern A. Zeeb 
13398e93258fSBjoern A. Zeeb 	request = rtw89_read16(rtwdev, R_AX_RPWM);
13408e93258fSBjoern A. Zeeb 	request ^= request | PS_RPWM_TOGGLE;
13418e93258fSBjoern A. Zeeb 	request |= req_pwr_state;
13428e93258fSBjoern A. Zeeb 
13438e93258fSBjoern A. Zeeb 	if (notify_wake) {
13448e93258fSBjoern A. Zeeb 		request |= PS_RPWM_NOTIFY_WAKE;
13458e93258fSBjoern A. Zeeb 	} else {
13468e93258fSBjoern A. Zeeb 		rtwdev->mac.rpwm_seq_num = (rtwdev->mac.rpwm_seq_num + 1) &
13478e93258fSBjoern A. Zeeb 					    RPWM_SEQ_NUM_MAX;
13488e93258fSBjoern A. Zeeb 		request |= FIELD_PREP(PS_RPWM_SEQ_NUM,
13498e93258fSBjoern A. Zeeb 				      rtwdev->mac.rpwm_seq_num);
13508e93258fSBjoern A. Zeeb 
13518e93258fSBjoern A. Zeeb 		if (req_pwr_state < RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED)
13528e93258fSBjoern A. Zeeb 			request |= PS_RPWM_ACK;
13538e93258fSBjoern A. Zeeb 	}
13548e93258fSBjoern A. Zeeb 	rtw89_write16(rtwdev, rtwdev->hci.rpwm_addr, request);
13558e93258fSBjoern A. Zeeb 
13568e93258fSBjoern A. Zeeb 	spin_unlock_bh(&rtwdev->rpwm_lock);
13578e93258fSBjoern A. Zeeb }
13588e93258fSBjoern A. Zeeb 
13598e93258fSBjoern A. Zeeb static int rtw89_mac_check_cpwm_state(struct rtw89_dev *rtwdev,
13608e93258fSBjoern A. Zeeb 				      enum rtw89_rpwm_req_pwr_state req_pwr_state)
13618e93258fSBjoern A. Zeeb {
13628e93258fSBjoern A. Zeeb 	bool request_deep_mode;
13638e93258fSBjoern A. Zeeb 	bool in_deep_mode;
13648e93258fSBjoern A. Zeeb 	u8 rpwm_req_num;
13658e93258fSBjoern A. Zeeb 	u8 cpwm_rsp_seq;
13668e93258fSBjoern A. Zeeb 	u8 cpwm_seq;
13678e93258fSBjoern A. Zeeb 	u8 cpwm_status;
13688e93258fSBjoern A. Zeeb 
13698e93258fSBjoern A. Zeeb 	if (req_pwr_state >= RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED)
13708e93258fSBjoern A. Zeeb 		request_deep_mode = true;
13718e93258fSBjoern A. Zeeb 	else
13728e93258fSBjoern A. Zeeb 		request_deep_mode = false;
13738e93258fSBjoern A. Zeeb 
13748e93258fSBjoern A. Zeeb 	if (rtw89_read32_mask(rtwdev, R_AX_LDM, B_AX_EN_32K))
13758e93258fSBjoern A. Zeeb 		in_deep_mode = true;
13768e93258fSBjoern A. Zeeb 	else
13778e93258fSBjoern A. Zeeb 		in_deep_mode = false;
13788e93258fSBjoern A. Zeeb 
13798e93258fSBjoern A. Zeeb 	if (request_deep_mode != in_deep_mode)
13808e93258fSBjoern A. Zeeb 		return -EPERM;
13818e93258fSBjoern A. Zeeb 
13828e93258fSBjoern A. Zeeb 	if (request_deep_mode)
13838e93258fSBjoern A. Zeeb 		return 0;
13848e93258fSBjoern A. Zeeb 
13858e93258fSBjoern A. Zeeb 	rpwm_req_num = rtwdev->mac.rpwm_seq_num;
13868e93258fSBjoern A. Zeeb 	cpwm_rsp_seq = rtw89_read16_mask(rtwdev, rtwdev->hci.cpwm_addr,
13878e93258fSBjoern A. Zeeb 					 PS_CPWM_RSP_SEQ_NUM);
13888e93258fSBjoern A. Zeeb 
13898e93258fSBjoern A. Zeeb 	if (rpwm_req_num != cpwm_rsp_seq)
13908e93258fSBjoern A. Zeeb 		return -EPERM;
13918e93258fSBjoern A. Zeeb 
13928e93258fSBjoern A. Zeeb 	rtwdev->mac.cpwm_seq_num = (rtwdev->mac.cpwm_seq_num + 1) &
13938e93258fSBjoern A. Zeeb 				    CPWM_SEQ_NUM_MAX;
13948e93258fSBjoern A. Zeeb 
13958e93258fSBjoern A. Zeeb 	cpwm_seq = rtw89_read16_mask(rtwdev, rtwdev->hci.cpwm_addr, PS_CPWM_SEQ_NUM);
13968e93258fSBjoern A. Zeeb 	if (cpwm_seq != rtwdev->mac.cpwm_seq_num)
13978e93258fSBjoern A. Zeeb 		return -EPERM;
13988e93258fSBjoern A. Zeeb 
13998e93258fSBjoern A. Zeeb 	cpwm_status = rtw89_read16_mask(rtwdev, rtwdev->hci.cpwm_addr, PS_CPWM_STATE);
14008e93258fSBjoern A. Zeeb 	if (cpwm_status != req_pwr_state)
14018e93258fSBjoern A. Zeeb 		return -EPERM;
14028e93258fSBjoern A. Zeeb 
14038e93258fSBjoern A. Zeeb 	return 0;
14048e93258fSBjoern A. Zeeb }
14058e93258fSBjoern A. Zeeb 
14068e93258fSBjoern A. Zeeb void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
14078e93258fSBjoern A. Zeeb {
14088e93258fSBjoern A. Zeeb 	enum rtw89_rpwm_req_pwr_state state;
14098e93258fSBjoern A. Zeeb 	unsigned long delay = enter ? 10 : 150;
14108e93258fSBjoern A. Zeeb 	int ret;
14118e93258fSBjoern A. Zeeb 	int i;
14128e93258fSBjoern A. Zeeb 
14138e93258fSBjoern A. Zeeb 	if (enter)
14148e93258fSBjoern A. Zeeb 		state = rtw89_mac_get_req_pwr_state(rtwdev);
14158e93258fSBjoern A. Zeeb 	else
14168e93258fSBjoern A. Zeeb 		state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;
14178e93258fSBjoern A. Zeeb 
14188e93258fSBjoern A. Zeeb 	for (i = 0; i < RPWM_TRY_CNT; i++) {
14198e93258fSBjoern A. Zeeb 		rtw89_mac_send_rpwm(rtwdev, state, false);
14208e93258fSBjoern A. Zeeb 		ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret,
14218e93258fSBjoern A. Zeeb 					       !ret, delay, 15000, false,
14228e93258fSBjoern A. Zeeb 					       rtwdev, state);
14238e93258fSBjoern A. Zeeb 		if (!ret)
14248e93258fSBjoern A. Zeeb 			break;
14258e93258fSBjoern A. Zeeb 
14268e93258fSBjoern A. Zeeb 		if (i == RPWM_TRY_CNT - 1)
14278e93258fSBjoern A. Zeeb 			rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n",
14288e93258fSBjoern A. Zeeb 				  enter ? "entering" : "leaving");
14298e93258fSBjoern A. Zeeb 		else
14308e93258fSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
14318e93258fSBjoern A. Zeeb 				    "%d time firmware failed to ack for %s ps mode\n",
14328e93258fSBjoern A. Zeeb 				    i + 1, enter ? "entering" : "leaving");
14338e93258fSBjoern A. Zeeb 	}
14348e93258fSBjoern A. Zeeb }
14358e93258fSBjoern A. Zeeb 
14368e93258fSBjoern A. Zeeb void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev)
14378e93258fSBjoern A. Zeeb {
14388e93258fSBjoern A. Zeeb 	enum rtw89_rpwm_req_pwr_state state;
14398e93258fSBjoern A. Zeeb 
14408e93258fSBjoern A. Zeeb 	state = rtw89_mac_get_req_pwr_state(rtwdev);
14418e93258fSBjoern A. Zeeb 	rtw89_mac_send_rpwm(rtwdev, state, true);
14428e93258fSBjoern A. Zeeb }
14438e93258fSBjoern A. Zeeb 
14448e93258fSBjoern A. Zeeb static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
14458e93258fSBjoern A. Zeeb {
14468e93258fSBjoern A. Zeeb #define PWR_ACT 1
14478e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
14488e93258fSBjoern A. Zeeb 	const struct rtw89_pwr_cfg * const *cfg_seq;
14498e93258fSBjoern A. Zeeb 	int (*cfg_func)(struct rtw89_dev *rtwdev);
14508e93258fSBjoern A. Zeeb 	int ret;
14518e93258fSBjoern A. Zeeb 	u8 val;
14528e93258fSBjoern A. Zeeb 
14538e93258fSBjoern A. Zeeb 	if (on) {
14548e93258fSBjoern A. Zeeb 		cfg_seq = chip->pwr_on_seq;
14558e93258fSBjoern A. Zeeb 		cfg_func = chip->ops->pwr_on_func;
14568e93258fSBjoern A. Zeeb 	} else {
14578e93258fSBjoern A. Zeeb 		cfg_seq = chip->pwr_off_seq;
14588e93258fSBjoern A. Zeeb 		cfg_func = chip->ops->pwr_off_func;
14598e93258fSBjoern A. Zeeb 	}
14608e93258fSBjoern A. Zeeb 
14618e93258fSBjoern A. Zeeb 	if (test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
14628e93258fSBjoern A. Zeeb 		__rtw89_leave_ps_mode(rtwdev);
14638e93258fSBjoern A. Zeeb 
14648e93258fSBjoern A. Zeeb 	val = rtw89_read32_mask(rtwdev, R_AX_IC_PWR_STATE, B_AX_WLMAC_PWR_STE_MASK);
14658e93258fSBjoern A. Zeeb 	if (on && val == PWR_ACT) {
14668e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "MAC has already powered on\n");
14678e93258fSBjoern A. Zeeb 		return -EBUSY;
14688e93258fSBjoern A. Zeeb 	}
14698e93258fSBjoern A. Zeeb 
14708e93258fSBjoern A. Zeeb 	ret = cfg_func ? cfg_func(rtwdev) : rtw89_mac_pwr_seq(rtwdev, cfg_seq);
14718e93258fSBjoern A. Zeeb 	if (ret)
14728e93258fSBjoern A. Zeeb 		return ret;
14738e93258fSBjoern A. Zeeb 
14748e93258fSBjoern A. Zeeb 	if (on) {
14758e93258fSBjoern A. Zeeb 		set_bit(RTW89_FLAG_POWERON, rtwdev->flags);
1476*6d67aabdSBjoern A. Zeeb 		set_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
1477*6d67aabdSBjoern A. Zeeb 		set_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
14788e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_TP_MAJOR);
14798e93258fSBjoern A. Zeeb 	} else {
14808e93258fSBjoern A. Zeeb 		clear_bit(RTW89_FLAG_POWERON, rtwdev->flags);
1481*6d67aabdSBjoern A. Zeeb 		clear_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
1482*6d67aabdSBjoern A. Zeeb 		clear_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
1483*6d67aabdSBjoern A. Zeeb 		clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags);
14848e93258fSBjoern A. Zeeb 		clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags);
14858e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR);
14868e93258fSBjoern A. Zeeb 		rtw89_set_entity_state(rtwdev, false);
14878e93258fSBjoern A. Zeeb 	}
14888e93258fSBjoern A. Zeeb 
14898e93258fSBjoern A. Zeeb 	return 0;
14908e93258fSBjoern A. Zeeb #undef PWR_ACT
14918e93258fSBjoern A. Zeeb }
14928e93258fSBjoern A. Zeeb 
14938e93258fSBjoern A. Zeeb void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev)
14948e93258fSBjoern A. Zeeb {
14958e93258fSBjoern A. Zeeb 	rtw89_mac_power_switch(rtwdev, false);
14968e93258fSBjoern A. Zeeb }
14978e93258fSBjoern A. Zeeb 
1498*6d67aabdSBjoern A. Zeeb static int cmac_func_en_ax(struct rtw89_dev *rtwdev, u8 mac_idx, bool en)
14998e93258fSBjoern A. Zeeb {
15008e93258fSBjoern A. Zeeb 	u32 func_en = 0;
15018e93258fSBjoern A. Zeeb 	u32 ck_en = 0;
15028e93258fSBjoern A. Zeeb 	u32 c1pc_en = 0;
15038e93258fSBjoern A. Zeeb 	u32 addrl_func_en[] = {R_AX_CMAC_FUNC_EN, R_AX_CMAC_FUNC_EN_C1};
15048e93258fSBjoern A. Zeeb 	u32 addrl_ck_en[] = {R_AX_CK_EN, R_AX_CK_EN_C1};
15058e93258fSBjoern A. Zeeb 
15068e93258fSBjoern A. Zeeb 	func_en = B_AX_CMAC_EN | B_AX_CMAC_TXEN | B_AX_CMAC_RXEN |
15078e93258fSBjoern A. Zeeb 			B_AX_PHYINTF_EN | B_AX_CMAC_DMA_EN | B_AX_PTCLTOP_EN |
15088e93258fSBjoern A. Zeeb 			B_AX_SCHEDULER_EN | B_AX_TMAC_EN | B_AX_RMAC_EN |
15098e93258fSBjoern A. Zeeb 			B_AX_CMAC_CRPRT;
15108e93258fSBjoern A. Zeeb 	ck_en = B_AX_CMAC_CKEN | B_AX_PHYINTF_CKEN | B_AX_CMAC_DMA_CKEN |
15118e93258fSBjoern A. Zeeb 		      B_AX_PTCLTOP_CKEN | B_AX_SCHEDULER_CKEN | B_AX_TMAC_CKEN |
15128e93258fSBjoern A. Zeeb 		      B_AX_RMAC_CKEN;
15138e93258fSBjoern A. Zeeb 	c1pc_en = B_AX_R_SYM_WLCMAC1_PC_EN |
15148e93258fSBjoern A. Zeeb 			B_AX_R_SYM_WLCMAC1_P1_PC_EN |
15158e93258fSBjoern A. Zeeb 			B_AX_R_SYM_WLCMAC1_P2_PC_EN |
15168e93258fSBjoern A. Zeeb 			B_AX_R_SYM_WLCMAC1_P3_PC_EN |
15178e93258fSBjoern A. Zeeb 			B_AX_R_SYM_WLCMAC1_P4_PC_EN;
15188e93258fSBjoern A. Zeeb 
15198e93258fSBjoern A. Zeeb 	if (en) {
15208e93258fSBjoern A. Zeeb 		if (mac_idx == RTW89_MAC_1) {
15218e93258fSBjoern A. Zeeb 			rtw89_write32_set(rtwdev, R_AX_AFE_CTRL1, c1pc_en);
15228e93258fSBjoern A. Zeeb 			rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
15238e93258fSBjoern A. Zeeb 					  B_AX_R_SYM_ISO_CMAC12PP);
15248e93258fSBjoern A. Zeeb 			rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
15258e93258fSBjoern A. Zeeb 					  B_AX_CMAC1_FEN);
15268e93258fSBjoern A. Zeeb 		}
15278e93258fSBjoern A. Zeeb 		rtw89_write32_set(rtwdev, addrl_ck_en[mac_idx], ck_en);
15288e93258fSBjoern A. Zeeb 		rtw89_write32_set(rtwdev, addrl_func_en[mac_idx], func_en);
15298e93258fSBjoern A. Zeeb 	} else {
15308e93258fSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, addrl_func_en[mac_idx], func_en);
15318e93258fSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, addrl_ck_en[mac_idx], ck_en);
15328e93258fSBjoern A. Zeeb 		if (mac_idx == RTW89_MAC_1) {
15338e93258fSBjoern A. Zeeb 			rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
15348e93258fSBjoern A. Zeeb 					  B_AX_CMAC1_FEN);
15358e93258fSBjoern A. Zeeb 			rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
15368e93258fSBjoern A. Zeeb 					  B_AX_R_SYM_ISO_CMAC12PP);
15378e93258fSBjoern A. Zeeb 			rtw89_write32_clr(rtwdev, R_AX_AFE_CTRL1, c1pc_en);
15388e93258fSBjoern A. Zeeb 		}
15398e93258fSBjoern A. Zeeb 	}
15408e93258fSBjoern A. Zeeb 
15418e93258fSBjoern A. Zeeb 	return 0;
15428e93258fSBjoern A. Zeeb }
15438e93258fSBjoern A. Zeeb 
1544*6d67aabdSBjoern A. Zeeb static int dmac_func_en_ax(struct rtw89_dev *rtwdev)
15458e93258fSBjoern A. Zeeb {
15468e93258fSBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
15478e93258fSBjoern A. Zeeb 	u32 val32;
15488e93258fSBjoern A. Zeeb 
15498e93258fSBjoern A. Zeeb 	if (chip_id == RTL8852C)
15508e93258fSBjoern A. Zeeb 		val32 = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN |
15518e93258fSBjoern A. Zeeb 			 B_AX_MAC_SEC_EN | B_AX_DISPATCHER_EN |
15528e93258fSBjoern A. Zeeb 			 B_AX_DLE_CPUIO_EN | B_AX_PKT_IN_EN |
15538e93258fSBjoern A. Zeeb 			 B_AX_DMAC_TBL_EN | B_AX_PKT_BUF_EN |
15548e93258fSBjoern A. Zeeb 			 B_AX_STA_SCH_EN | B_AX_TXPKT_CTRL_EN |
15558e93258fSBjoern A. Zeeb 			 B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN |
15568e93258fSBjoern A. Zeeb 			 B_AX_DMAC_CRPRT | B_AX_H_AXIDMA_EN);
15578e93258fSBjoern A. Zeeb 	else
15588e93258fSBjoern A. Zeeb 		val32 = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN |
15598e93258fSBjoern A. Zeeb 			 B_AX_MAC_SEC_EN | B_AX_DISPATCHER_EN |
15608e93258fSBjoern A. Zeeb 			 B_AX_DLE_CPUIO_EN | B_AX_PKT_IN_EN |
15618e93258fSBjoern A. Zeeb 			 B_AX_DMAC_TBL_EN | B_AX_PKT_BUF_EN |
15628e93258fSBjoern A. Zeeb 			 B_AX_STA_SCH_EN | B_AX_TXPKT_CTRL_EN |
15638e93258fSBjoern A. Zeeb 			 B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN |
15648e93258fSBjoern A. Zeeb 			 B_AX_DMAC_CRPRT);
15658e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_DMAC_FUNC_EN, val32);
15668e93258fSBjoern A. Zeeb 
15678e93258fSBjoern A. Zeeb 	val32 = (B_AX_MAC_SEC_CLK_EN | B_AX_DISPATCHER_CLK_EN |
15688e93258fSBjoern A. Zeeb 		 B_AX_DLE_CPUIO_CLK_EN | B_AX_PKT_IN_CLK_EN |
15698e93258fSBjoern A. Zeeb 		 B_AX_STA_SCH_CLK_EN | B_AX_TXPKT_CTRL_CLK_EN |
15708e93258fSBjoern A. Zeeb 		 B_AX_WD_RLS_CLK_EN | B_AX_BBRPT_CLK_EN);
1571*6d67aabdSBjoern A. Zeeb 	if (chip_id == RTL8852BT)
1572*6d67aabdSBjoern A. Zeeb 		val32 |= B_AX_AXIDMA_CLK_EN;
15738e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_DMAC_CLK_EN, val32);
15748e93258fSBjoern A. Zeeb 
15758e93258fSBjoern A. Zeeb 	return 0;
15768e93258fSBjoern A. Zeeb }
15778e93258fSBjoern A. Zeeb 
1578*6d67aabdSBjoern A. Zeeb static int chip_func_en_ax(struct rtw89_dev *rtwdev)
15798e93258fSBjoern A. Zeeb {
15808e93258fSBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
15818e93258fSBjoern A. Zeeb 
1582*6d67aabdSBjoern A. Zeeb 	if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
1583e2340276SBjoern A. Zeeb 		rtw89_write32_set(rtwdev, R_AX_SPS_DIG_ON_CTRL0,
15848e93258fSBjoern A. Zeeb 				  B_AX_OCP_L1_MASK);
15858e93258fSBjoern A. Zeeb 
15868e93258fSBjoern A. Zeeb 	return 0;
15878e93258fSBjoern A. Zeeb }
15888e93258fSBjoern A. Zeeb 
1589*6d67aabdSBjoern A. Zeeb static int sys_init_ax(struct rtw89_dev *rtwdev)
15908e93258fSBjoern A. Zeeb {
15918e93258fSBjoern A. Zeeb 	int ret;
15928e93258fSBjoern A. Zeeb 
1593*6d67aabdSBjoern A. Zeeb 	ret = dmac_func_en_ax(rtwdev);
15948e93258fSBjoern A. Zeeb 	if (ret)
15958e93258fSBjoern A. Zeeb 		return ret;
15968e93258fSBjoern A. Zeeb 
1597*6d67aabdSBjoern A. Zeeb 	ret = cmac_func_en_ax(rtwdev, 0, true);
15988e93258fSBjoern A. Zeeb 	if (ret)
15998e93258fSBjoern A. Zeeb 		return ret;
16008e93258fSBjoern A. Zeeb 
1601*6d67aabdSBjoern A. Zeeb 	ret = chip_func_en_ax(rtwdev);
16028e93258fSBjoern A. Zeeb 	if (ret)
16038e93258fSBjoern A. Zeeb 		return ret;
16048e93258fSBjoern A. Zeeb 
16058e93258fSBjoern A. Zeeb 	return ret;
16068e93258fSBjoern A. Zeeb }
16078e93258fSBjoern A. Zeeb 
16088e93258fSBjoern A. Zeeb const struct rtw89_mac_size_set rtw89_mac_size = {
16098e93258fSBjoern A. Zeeb 	.hfc_preccfg_pcie = {2, 40, 0, 0, 1, 0, 0, 0},
1610*6d67aabdSBjoern A. Zeeb 	.hfc_prec_cfg_c0 = {2, 32, 0, 0, 0, 0, 0, 0},
1611*6d67aabdSBjoern A. Zeeb 	.hfc_prec_cfg_c2 = {0, 256, 0, 0, 0, 0, 0, 0},
16128e93258fSBjoern A. Zeeb 	/* PCIE 64 */
16138e93258fSBjoern A. Zeeb 	.wde_size0 = {RTW89_WDE_PG_64, 4095, 1,},
1614*6d67aabdSBjoern A. Zeeb 	.wde_size0_v1 = {RTW89_WDE_PG_64, 3328, 0, 0,},
16158e93258fSBjoern A. Zeeb 	/* DLFW */
16168e93258fSBjoern A. Zeeb 	.wde_size4 = {RTW89_WDE_PG_64, 0, 4096,},
1617*6d67aabdSBjoern A. Zeeb 	.wde_size4_v1 = {RTW89_WDE_PG_64, 0, 3328, 0,},
1618e2340276SBjoern A. Zeeb 	/* PCIE 64 */
1619e2340276SBjoern A. Zeeb 	.wde_size6 = {RTW89_WDE_PG_64, 512, 0,},
1620e2340276SBjoern A. Zeeb 	/* 8852B PCIE SCC */
1621e2340276SBjoern A. Zeeb 	.wde_size7 = {RTW89_WDE_PG_64, 510, 2,},
1622e2340276SBjoern A. Zeeb 	/* DLFW */
1623e2340276SBjoern A. Zeeb 	.wde_size9 = {RTW89_WDE_PG_64, 0, 1024,},
16248e93258fSBjoern A. Zeeb 	/* 8852C DLFW */
16258e93258fSBjoern A. Zeeb 	.wde_size18 = {RTW89_WDE_PG_64, 0, 2048,},
16268e93258fSBjoern A. Zeeb 	/* 8852C PCIE SCC */
16278e93258fSBjoern A. Zeeb 	.wde_size19 = {RTW89_WDE_PG_64, 3328, 0,},
16288e93258fSBjoern A. Zeeb 	/* PCIE */
16298e93258fSBjoern A. Zeeb 	.ple_size0 = {RTW89_PLE_PG_128, 1520, 16,},
1630*6d67aabdSBjoern A. Zeeb 	.ple_size0_v1 = {RTW89_PLE_PG_128, 2688, 240, 212992,},
1631*6d67aabdSBjoern A. Zeeb 	.ple_size3_v1 = {RTW89_PLE_PG_128, 2928, 0, 212992,},
16328e93258fSBjoern A. Zeeb 	/* DLFW */
16338e93258fSBjoern A. Zeeb 	.ple_size4 = {RTW89_PLE_PG_128, 64, 1472,},
1634e2340276SBjoern A. Zeeb 	/* PCIE 64 */
1635e2340276SBjoern A. Zeeb 	.ple_size6 = {RTW89_PLE_PG_128, 496, 16,},
1636e2340276SBjoern A. Zeeb 	/* DLFW */
1637e2340276SBjoern A. Zeeb 	.ple_size8 = {RTW89_PLE_PG_128, 64, 960,},
16388e93258fSBjoern A. Zeeb 	/* 8852C DLFW */
16398e93258fSBjoern A. Zeeb 	.ple_size18 = {RTW89_PLE_PG_128, 2544, 16,},
16408e93258fSBjoern A. Zeeb 	/* 8852C PCIE SCC */
16418e93258fSBjoern A. Zeeb 	.ple_size19 = {RTW89_PLE_PG_128, 1904, 16,},
16428e93258fSBjoern A. Zeeb 	/* PCIE 64 */
16438e93258fSBjoern A. Zeeb 	.wde_qt0 = {3792, 196, 0, 107,},
1644*6d67aabdSBjoern A. Zeeb 	.wde_qt0_v1 = {3302, 6, 0, 20,},
16458e93258fSBjoern A. Zeeb 	/* DLFW */
16468e93258fSBjoern A. Zeeb 	.wde_qt4 = {0, 0, 0, 0,},
1647e2340276SBjoern A. Zeeb 	/* PCIE 64 */
1648e2340276SBjoern A. Zeeb 	.wde_qt6 = {448, 48, 0, 16,},
1649e2340276SBjoern A. Zeeb 	/* 8852B PCIE SCC */
1650e2340276SBjoern A. Zeeb 	.wde_qt7 = {446, 48, 0, 16,},
16518e93258fSBjoern A. Zeeb 	/* 8852C DLFW */
16528e93258fSBjoern A. Zeeb 	.wde_qt17 = {0, 0, 0,  0,},
16538e93258fSBjoern A. Zeeb 	/* 8852C PCIE SCC */
16548e93258fSBjoern A. Zeeb 	.wde_qt18 = {3228, 60, 0, 40,},
1655*6d67aabdSBjoern A. Zeeb 	.ple_qt0 = {320, 320, 32, 16, 13, 13, 292, 292, 64, 18, 1, 4, 0,},
1656*6d67aabdSBjoern A. Zeeb 	.ple_qt1 = {320, 320, 32, 16, 1316, 1316, 1595, 1595, 1367, 1321, 1, 1307, 0,},
16578e93258fSBjoern A. Zeeb 	/* PCIE SCC */
16588e93258fSBjoern A. Zeeb 	.ple_qt4 = {264, 0, 16, 20, 26, 13, 356, 0, 32, 40, 8,},
16598e93258fSBjoern A. Zeeb 	/* PCIE SCC */
16608e93258fSBjoern A. Zeeb 	.ple_qt5 = {264, 0, 32, 20, 64, 13, 1101, 0, 64, 128, 120,},
1661*6d67aabdSBjoern A. Zeeb 	.ple_qt9 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 1, 0, 0,},
16628e93258fSBjoern A. Zeeb 	/* DLFW */
16638e93258fSBjoern A. Zeeb 	.ple_qt13 = {0, 0, 16, 48, 0, 0, 0, 0, 0, 0, 0,},
1664e2340276SBjoern A. Zeeb 	/* PCIE 64 */
1665e2340276SBjoern A. Zeeb 	.ple_qt18 = {147, 0, 16, 20, 17, 13, 89, 0, 32, 14, 8, 0,},
16668e93258fSBjoern A. Zeeb 	/* DLFW 52C */
16678e93258fSBjoern A. Zeeb 	.ple_qt44 = {0, 0, 16, 256, 0, 0, 0, 0, 0, 0, 0, 0,},
16688e93258fSBjoern A. Zeeb 	/* DLFW 52C */
16698e93258fSBjoern A. Zeeb 	.ple_qt45 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 0, 0,},
16708e93258fSBjoern A. Zeeb 	/* 8852C PCIE SCC */
16718e93258fSBjoern A. Zeeb 	.ple_qt46 = {525, 0, 16, 20, 13, 13, 178, 0, 32, 62, 8, 16,},
16728e93258fSBjoern A. Zeeb 	/* 8852C PCIE SCC */
16738e93258fSBjoern A. Zeeb 	.ple_qt47 = {525, 0, 32, 20, 1034, 13, 1199, 0, 1053, 62, 160, 1037,},
1674e2340276SBjoern A. Zeeb 	/* PCIE 64 */
1675e2340276SBjoern A. Zeeb 	.ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,},
1676e2340276SBjoern A. Zeeb 	/* 8852A PCIE WOW */
1677e2340276SBjoern A. Zeeb 	.ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,},
1678e2340276SBjoern A. Zeeb 	/* 8852B PCIE WOW */
1679e2340276SBjoern A. Zeeb 	.ple_qt_52b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
1680e2340276SBjoern A. Zeeb 	/* 8851B PCIE WOW */
1681e2340276SBjoern A. Zeeb 	.ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
1682*6d67aabdSBjoern A. Zeeb 	.ple_rsvd_qt0 = {2, 107, 107, 6, 6, 6, 6, 0, 0, 0,},
1683*6d67aabdSBjoern A. Zeeb 	.ple_rsvd_qt1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
1684*6d67aabdSBjoern A. Zeeb 	.rsvd0_size0 = {212992, 0,},
1685*6d67aabdSBjoern A. Zeeb 	.rsvd1_size0 = {587776, 2048,},
16868e93258fSBjoern A. Zeeb };
16878e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_size);
16888e93258fSBjoern A. Zeeb 
16898e93258fSBjoern A. Zeeb static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
16908e93258fSBjoern A. Zeeb 						   enum rtw89_qta_mode mode)
16918e93258fSBjoern A. Zeeb {
16928e93258fSBjoern A. Zeeb 	struct rtw89_mac_info *mac = &rtwdev->mac;
16938e93258fSBjoern A. Zeeb 	const struct rtw89_dle_mem *cfg;
16948e93258fSBjoern A. Zeeb 
16958e93258fSBjoern A. Zeeb 	cfg = &rtwdev->chip->dle_mem[mode];
16968e93258fSBjoern A. Zeeb 	if (!cfg)
16978e93258fSBjoern A. Zeeb 		return NULL;
16988e93258fSBjoern A. Zeeb 
16998e93258fSBjoern A. Zeeb 	if (cfg->mode != mode) {
17008e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "qta mode unmatch!\n");
17018e93258fSBjoern A. Zeeb 		return NULL;
17028e93258fSBjoern A. Zeeb 	}
17038e93258fSBjoern A. Zeeb 
1704*6d67aabdSBjoern A. Zeeb 	mac->dle_info.rsvd_qt = cfg->rsvd_qt;
17058e93258fSBjoern A. Zeeb 	mac->dle_info.ple_pg_size = cfg->ple_size->pge_size;
1706*6d67aabdSBjoern A. Zeeb 	mac->dle_info.ple_free_pg = cfg->ple_size->lnk_pge_num;
17078e93258fSBjoern A. Zeeb 	mac->dle_info.qta_mode = mode;
17088e93258fSBjoern A. Zeeb 	mac->dle_info.c0_rx_qta = cfg->ple_min_qt->cma0_dma;
17098e93258fSBjoern A. Zeeb 	mac->dle_info.c1_rx_qta = cfg->ple_min_qt->cma1_dma;
17108e93258fSBjoern A. Zeeb 
17118e93258fSBjoern A. Zeeb 	return cfg;
17128e93258fSBjoern A. Zeeb }
17138e93258fSBjoern A. Zeeb 
1714*6d67aabdSBjoern A. Zeeb int rtw89_mac_get_dle_rsvd_qt_cfg(struct rtw89_dev *rtwdev,
1715*6d67aabdSBjoern A. Zeeb 				  enum rtw89_mac_dle_rsvd_qt_type type,
1716*6d67aabdSBjoern A. Zeeb 				  struct rtw89_mac_dle_rsvd_qt_cfg *cfg)
1717*6d67aabdSBjoern A. Zeeb {
1718*6d67aabdSBjoern A. Zeeb 	struct rtw89_dle_info *dle_info = &rtwdev->mac.dle_info;
1719*6d67aabdSBjoern A. Zeeb 	const struct rtw89_rsvd_quota *rsvd_qt = dle_info->rsvd_qt;
1720*6d67aabdSBjoern A. Zeeb 
1721*6d67aabdSBjoern A. Zeeb 	switch (type) {
1722*6d67aabdSBjoern A. Zeeb 	case DLE_RSVD_QT_MPDU_INFO:
1723*6d67aabdSBjoern A. Zeeb 		cfg->pktid = dle_info->ple_free_pg;
1724*6d67aabdSBjoern A. Zeeb 		cfg->pg_num = rsvd_qt->mpdu_info_tbl;
1725*6d67aabdSBjoern A. Zeeb 		break;
1726*6d67aabdSBjoern A. Zeeb 	case DLE_RSVD_QT_B0_CSI:
1727*6d67aabdSBjoern A. Zeeb 		cfg->pktid = dle_info->ple_free_pg + rsvd_qt->mpdu_info_tbl;
1728*6d67aabdSBjoern A. Zeeb 		cfg->pg_num = rsvd_qt->b0_csi;
1729*6d67aabdSBjoern A. Zeeb 		break;
1730*6d67aabdSBjoern A. Zeeb 	case DLE_RSVD_QT_B1_CSI:
1731*6d67aabdSBjoern A. Zeeb 		cfg->pktid = dle_info->ple_free_pg +
1732*6d67aabdSBjoern A. Zeeb 			     rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi;
1733*6d67aabdSBjoern A. Zeeb 		cfg->pg_num = rsvd_qt->b1_csi;
1734*6d67aabdSBjoern A. Zeeb 		break;
1735*6d67aabdSBjoern A. Zeeb 	case DLE_RSVD_QT_B0_LMR:
1736*6d67aabdSBjoern A. Zeeb 		cfg->pktid = dle_info->ple_free_pg +
1737*6d67aabdSBjoern A. Zeeb 			     rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi;
1738*6d67aabdSBjoern A. Zeeb 		cfg->pg_num = rsvd_qt->b0_lmr;
1739*6d67aabdSBjoern A. Zeeb 		break;
1740*6d67aabdSBjoern A. Zeeb 	case DLE_RSVD_QT_B1_LMR:
1741*6d67aabdSBjoern A. Zeeb 		cfg->pktid = dle_info->ple_free_pg +
1742*6d67aabdSBjoern A. Zeeb 			     rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi +
1743*6d67aabdSBjoern A. Zeeb 			     rsvd_qt->b0_lmr;
1744*6d67aabdSBjoern A. Zeeb 		cfg->pg_num = rsvd_qt->b1_lmr;
1745*6d67aabdSBjoern A. Zeeb 		break;
1746*6d67aabdSBjoern A. Zeeb 	case DLE_RSVD_QT_B0_FTM:
1747*6d67aabdSBjoern A. Zeeb 		cfg->pktid = dle_info->ple_free_pg +
1748*6d67aabdSBjoern A. Zeeb 			     rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi +
1749*6d67aabdSBjoern A. Zeeb 			     rsvd_qt->b0_lmr + rsvd_qt->b1_lmr;
1750*6d67aabdSBjoern A. Zeeb 		cfg->pg_num = rsvd_qt->b0_ftm;
1751*6d67aabdSBjoern A. Zeeb 		break;
1752*6d67aabdSBjoern A. Zeeb 	case DLE_RSVD_QT_B1_FTM:
1753*6d67aabdSBjoern A. Zeeb 		cfg->pktid = dle_info->ple_free_pg +
1754*6d67aabdSBjoern A. Zeeb 			     rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi +
1755*6d67aabdSBjoern A. Zeeb 			     rsvd_qt->b0_lmr + rsvd_qt->b1_lmr + rsvd_qt->b0_ftm;
1756*6d67aabdSBjoern A. Zeeb 		cfg->pg_num = rsvd_qt->b1_ftm;
1757*6d67aabdSBjoern A. Zeeb 		break;
1758*6d67aabdSBjoern A. Zeeb 	default:
1759*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
1760*6d67aabdSBjoern A. Zeeb 	}
1761*6d67aabdSBjoern A. Zeeb 
1762*6d67aabdSBjoern A. Zeeb 	cfg->size = (u32)cfg->pg_num * dle_info->ple_pg_size;
1763*6d67aabdSBjoern A. Zeeb 
1764*6d67aabdSBjoern A. Zeeb 	return 0;
1765*6d67aabdSBjoern A. Zeeb }
1766*6d67aabdSBjoern A. Zeeb 
1767*6d67aabdSBjoern A. Zeeb static bool mac_is_txq_empty_ax(struct rtw89_dev *rtwdev)
1768e2340276SBjoern A. Zeeb {
1769e2340276SBjoern A. Zeeb 	struct rtw89_mac_dle_dfi_qempty qempty;
1770*6d67aabdSBjoern A. Zeeb 	u32 grpnum, qtmp, val32, msk32;
1771e2340276SBjoern A. Zeeb 	int i, j, ret;
1772e2340276SBjoern A. Zeeb 
1773*6d67aabdSBjoern A. Zeeb 	grpnum = rtwdev->chip->wde_qempty_acq_grpnum;
1774e2340276SBjoern A. Zeeb 	qempty.dle_type = DLE_CTRL_TYPE_WDE;
1775e2340276SBjoern A. Zeeb 
1776*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < grpnum; i++) {
1777e2340276SBjoern A. Zeeb 		qempty.grpsel = i;
1778*6d67aabdSBjoern A. Zeeb 		ret = rtw89_mac_dle_dfi_qempty_cfg(rtwdev, &qempty);
1779e2340276SBjoern A. Zeeb 		if (ret) {
1780e2340276SBjoern A. Zeeb 			rtw89_warn(rtwdev, "dle dfi acq empty %d\n", ret);
1781e2340276SBjoern A. Zeeb 			return false;
1782e2340276SBjoern A. Zeeb 		}
1783e2340276SBjoern A. Zeeb 		qtmp = qempty.qempty;
1784e2340276SBjoern A. Zeeb 		for (j = 0 ; j < QEMP_ACQ_GRP_MACID_NUM; j++) {
1785*6d67aabdSBjoern A. Zeeb 			val32 = u32_get_bits(qtmp, QEMP_ACQ_GRP_QSEL_MASK);
1786e2340276SBjoern A. Zeeb 			if (val32 != QEMP_ACQ_GRP_QSEL_MASK)
1787e2340276SBjoern A. Zeeb 				return false;
1788e2340276SBjoern A. Zeeb 			qtmp >>= QEMP_ACQ_GRP_QSEL_SH;
1789e2340276SBjoern A. Zeeb 		}
1790e2340276SBjoern A. Zeeb 	}
1791e2340276SBjoern A. Zeeb 
1792*6d67aabdSBjoern A. Zeeb 	qempty.grpsel = rtwdev->chip->wde_qempty_mgq_grpsel;
1793*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_dle_dfi_qempty_cfg(rtwdev, &qempty);
1794e2340276SBjoern A. Zeeb 	if (ret) {
1795e2340276SBjoern A. Zeeb 		rtw89_warn(rtwdev, "dle dfi mgq empty %d\n", ret);
1796e2340276SBjoern A. Zeeb 		return false;
1797e2340276SBjoern A. Zeeb 	}
1798e2340276SBjoern A. Zeeb 	msk32 = B_CMAC0_MGQ_NORMAL | B_CMAC0_MGQ_NO_PWRSAV | B_CMAC0_CPUMGQ;
1799e2340276SBjoern A. Zeeb 	if ((qempty.qempty & msk32) != msk32)
1800e2340276SBjoern A. Zeeb 		return false;
1801e2340276SBjoern A. Zeeb 
1802e2340276SBjoern A. Zeeb 	if (rtwdev->dbcc_en) {
1803e2340276SBjoern A. Zeeb 		msk32 |= B_CMAC1_MGQ_NORMAL | B_CMAC1_MGQ_NO_PWRSAV | B_CMAC1_CPUMGQ;
1804e2340276SBjoern A. Zeeb 		if ((qempty.qempty & msk32) != msk32)
1805e2340276SBjoern A. Zeeb 			return false;
1806e2340276SBjoern A. Zeeb 	}
1807e2340276SBjoern A. Zeeb 
1808e2340276SBjoern A. Zeeb 	msk32 = B_AX_WDE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_WDE_EMPTY_QTA_DMAC_DATA_CPU |
1809e2340276SBjoern A. Zeeb 		B_AX_PLE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_PLE_EMPTY_QTA_DMAC_H2C |
1810e2340276SBjoern A. Zeeb 		B_AX_WDE_EMPTY_QUE_OTHERS | B_AX_PLE_EMPTY_QUE_DMAC_MPDU_TX |
1811e2340276SBjoern A. Zeeb 		B_AX_WDE_EMPTY_QTA_DMAC_CPUIO | B_AX_PLE_EMPTY_QTA_DMAC_CPUIO |
1812e2340276SBjoern A. Zeeb 		B_AX_WDE_EMPTY_QUE_DMAC_PKTIN | B_AX_WDE_EMPTY_QTA_DMAC_HIF |
1813e2340276SBjoern A. Zeeb 		B_AX_PLE_EMPTY_QUE_DMAC_SEC_TX | B_AX_WDE_EMPTY_QTA_DMAC_PKTIN |
1814e2340276SBjoern A. Zeeb 		B_AX_PLE_EMPTY_QTA_DMAC_B0_TXPL | B_AX_PLE_EMPTY_QTA_DMAC_B1_TXPL |
1815e2340276SBjoern A. Zeeb 		B_AX_PLE_EMPTY_QTA_DMAC_MPDU_TX;
1816e2340276SBjoern A. Zeeb 	val32 = rtw89_read32(rtwdev, R_AX_DLE_EMPTY0);
1817e2340276SBjoern A. Zeeb 
1818e2340276SBjoern A. Zeeb 	return (val32 & msk32) == msk32;
1819e2340276SBjoern A. Zeeb }
1820e2340276SBjoern A. Zeeb 
1821*6d67aabdSBjoern A. Zeeb static inline u32 dle_used_size(const struct rtw89_dle_mem *cfg)
18228e93258fSBjoern A. Zeeb {
1823*6d67aabdSBjoern A. Zeeb 	const struct rtw89_dle_size *wde = cfg->wde_size;
1824*6d67aabdSBjoern A. Zeeb 	const struct rtw89_dle_size *ple = cfg->ple_size;
1825*6d67aabdSBjoern A. Zeeb 	u32 used;
1826*6d67aabdSBjoern A. Zeeb 
1827*6d67aabdSBjoern A. Zeeb 	used = wde->pge_size * (wde->lnk_pge_num + wde->unlnk_pge_num) +
18288e93258fSBjoern A. Zeeb 	       ple->pge_size * (ple->lnk_pge_num + ple->unlnk_pge_num);
1829*6d67aabdSBjoern A. Zeeb 
1830*6d67aabdSBjoern A. Zeeb 	if (cfg->rsvd0_size && cfg->rsvd1_size) {
1831*6d67aabdSBjoern A. Zeeb 		used += cfg->rsvd0_size->size;
1832*6d67aabdSBjoern A. Zeeb 		used += cfg->rsvd1_size->size;
1833*6d67aabdSBjoern A. Zeeb 	}
1834*6d67aabdSBjoern A. Zeeb 
1835*6d67aabdSBjoern A. Zeeb 	return used;
18368e93258fSBjoern A. Zeeb }
18378e93258fSBjoern A. Zeeb 
1838e2340276SBjoern A. Zeeb static u32 dle_expected_used_size(struct rtw89_dev *rtwdev,
1839e2340276SBjoern A. Zeeb 				  enum rtw89_qta_mode mode)
1840e2340276SBjoern A. Zeeb {
1841e2340276SBjoern A. Zeeb 	u32 size = rtwdev->chip->fifo_size;
1842e2340276SBjoern A. Zeeb 
1843e2340276SBjoern A. Zeeb 	if (mode == RTW89_QTA_SCC)
1844e2340276SBjoern A. Zeeb 		size -= rtwdev->chip->dle_scc_rsvd_size;
1845e2340276SBjoern A. Zeeb 
1846e2340276SBjoern A. Zeeb 	return size;
1847e2340276SBjoern A. Zeeb }
1848e2340276SBjoern A. Zeeb 
1849*6d67aabdSBjoern A. Zeeb static void dle_func_en_ax(struct rtw89_dev *rtwdev, bool enable)
18508e93258fSBjoern A. Zeeb {
18518e93258fSBjoern A. Zeeb 	if (enable)
18528e93258fSBjoern A. Zeeb 		rtw89_write32_set(rtwdev, R_AX_DMAC_FUNC_EN,
18538e93258fSBjoern A. Zeeb 				  B_AX_DLE_WDE_EN | B_AX_DLE_PLE_EN);
18548e93258fSBjoern A. Zeeb 	else
18558e93258fSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, R_AX_DMAC_FUNC_EN,
18568e93258fSBjoern A. Zeeb 				  B_AX_DLE_WDE_EN | B_AX_DLE_PLE_EN);
18578e93258fSBjoern A. Zeeb }
18588e93258fSBjoern A. Zeeb 
1859*6d67aabdSBjoern A. Zeeb static void dle_clk_en_ax(struct rtw89_dev *rtwdev, bool enable)
18608e93258fSBjoern A. Zeeb {
1861e2340276SBjoern A. Zeeb 	u32 val = B_AX_DLE_WDE_CLK_EN | B_AX_DLE_PLE_CLK_EN;
1862e2340276SBjoern A. Zeeb 
1863e2340276SBjoern A. Zeeb 	if (enable) {
1864e2340276SBjoern A. Zeeb 		if (rtwdev->chip->chip_id == RTL8851B)
1865e2340276SBjoern A. Zeeb 			val |= B_AX_AXIDMA_CLK_EN;
1866e2340276SBjoern A. Zeeb 		rtw89_write32_set(rtwdev, R_AX_DMAC_CLK_EN, val);
1867e2340276SBjoern A. Zeeb 	} else {
1868e2340276SBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, R_AX_DMAC_CLK_EN, val);
1869e2340276SBjoern A. Zeeb 	}
18708e93258fSBjoern A. Zeeb }
18718e93258fSBjoern A. Zeeb 
1872*6d67aabdSBjoern A. Zeeb static int dle_mix_cfg_ax(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg)
18738e93258fSBjoern A. Zeeb {
18748e93258fSBjoern A. Zeeb 	const struct rtw89_dle_size *size_cfg;
18758e93258fSBjoern A. Zeeb 	u32 val;
18768e93258fSBjoern A. Zeeb 	u8 bound = 0;
18778e93258fSBjoern A. Zeeb 
18788e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, R_AX_WDE_PKTBUF_CFG);
18798e93258fSBjoern A. Zeeb 	size_cfg = cfg->wde_size;
18808e93258fSBjoern A. Zeeb 
18818e93258fSBjoern A. Zeeb 	switch (size_cfg->pge_size) {
18828e93258fSBjoern A. Zeeb 	default:
18838e93258fSBjoern A. Zeeb 	case RTW89_WDE_PG_64:
18848e93258fSBjoern A. Zeeb 		val = u32_replace_bits(val, S_AX_WDE_PAGE_SEL_64,
18858e93258fSBjoern A. Zeeb 				       B_AX_WDE_PAGE_SEL_MASK);
18868e93258fSBjoern A. Zeeb 		break;
18878e93258fSBjoern A. Zeeb 	case RTW89_WDE_PG_128:
18888e93258fSBjoern A. Zeeb 		val = u32_replace_bits(val, S_AX_WDE_PAGE_SEL_128,
18898e93258fSBjoern A. Zeeb 				       B_AX_WDE_PAGE_SEL_MASK);
18908e93258fSBjoern A. Zeeb 		break;
18918e93258fSBjoern A. Zeeb 	case RTW89_WDE_PG_256:
18928e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]WDE DLE doesn't support 256 byte!\n");
18938e93258fSBjoern A. Zeeb 		return -EINVAL;
18948e93258fSBjoern A. Zeeb 	}
18958e93258fSBjoern A. Zeeb 
18968e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, bound, B_AX_WDE_START_BOUND_MASK);
18978e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, size_cfg->lnk_pge_num,
18988e93258fSBjoern A. Zeeb 			       B_AX_WDE_FREE_PAGE_NUM_MASK);
18998e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_WDE_PKTBUF_CFG, val);
19008e93258fSBjoern A. Zeeb 
19018e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, R_AX_PLE_PKTBUF_CFG);
19028e93258fSBjoern A. Zeeb 	bound = (size_cfg->lnk_pge_num + size_cfg->unlnk_pge_num)
19038e93258fSBjoern A. Zeeb 				* size_cfg->pge_size / DLE_BOUND_UNIT;
19048e93258fSBjoern A. Zeeb 	size_cfg = cfg->ple_size;
19058e93258fSBjoern A. Zeeb 
19068e93258fSBjoern A. Zeeb 	switch (size_cfg->pge_size) {
19078e93258fSBjoern A. Zeeb 	default:
19088e93258fSBjoern A. Zeeb 	case RTW89_PLE_PG_64:
19098e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]PLE DLE doesn't support 64 byte!\n");
19108e93258fSBjoern A. Zeeb 		return -EINVAL;
19118e93258fSBjoern A. Zeeb 	case RTW89_PLE_PG_128:
19128e93258fSBjoern A. Zeeb 		val = u32_replace_bits(val, S_AX_PLE_PAGE_SEL_128,
19138e93258fSBjoern A. Zeeb 				       B_AX_PLE_PAGE_SEL_MASK);
19148e93258fSBjoern A. Zeeb 		break;
19158e93258fSBjoern A. Zeeb 	case RTW89_PLE_PG_256:
19168e93258fSBjoern A. Zeeb 		val = u32_replace_bits(val, S_AX_PLE_PAGE_SEL_256,
19178e93258fSBjoern A. Zeeb 				       B_AX_PLE_PAGE_SEL_MASK);
19188e93258fSBjoern A. Zeeb 		break;
19198e93258fSBjoern A. Zeeb 	}
19208e93258fSBjoern A. Zeeb 
19218e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, bound, B_AX_PLE_START_BOUND_MASK);
19228e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, size_cfg->lnk_pge_num,
19238e93258fSBjoern A. Zeeb 			       B_AX_PLE_FREE_PAGE_NUM_MASK);
19248e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_PLE_PKTBUF_CFG, val);
19258e93258fSBjoern A. Zeeb 
19268e93258fSBjoern A. Zeeb 	return 0;
19278e93258fSBjoern A. Zeeb }
19288e93258fSBjoern A. Zeeb 
1929*6d67aabdSBjoern A. Zeeb static int chk_dle_rdy_ax(struct rtw89_dev *rtwdev, bool wde_or_ple)
1930*6d67aabdSBjoern A. Zeeb {
1931*6d67aabdSBjoern A. Zeeb 	u32 reg, mask;
1932*6d67aabdSBjoern A. Zeeb 	u32 ini;
1933*6d67aabdSBjoern A. Zeeb 
1934*6d67aabdSBjoern A. Zeeb 	if (wde_or_ple) {
1935*6d67aabdSBjoern A. Zeeb 		reg = R_AX_WDE_INI_STATUS;
1936*6d67aabdSBjoern A. Zeeb 		mask = WDE_MGN_INI_RDY;
1937*6d67aabdSBjoern A. Zeeb 	} else {
1938*6d67aabdSBjoern A. Zeeb 		reg = R_AX_PLE_INI_STATUS;
1939*6d67aabdSBjoern A. Zeeb 		mask = PLE_MGN_INI_RDY;
1940*6d67aabdSBjoern A. Zeeb 	}
1941*6d67aabdSBjoern A. Zeeb 
1942*6d67aabdSBjoern A. Zeeb 	return read_poll_timeout(rtw89_read32, ini, (ini & mask) == mask, 1,
1943*6d67aabdSBjoern A. Zeeb 				2000, false, rtwdev, reg);
1944*6d67aabdSBjoern A. Zeeb }
1945*6d67aabdSBjoern A. Zeeb 
19468e93258fSBjoern A. Zeeb #define INVALID_QT_WCPU U16_MAX
19478e93258fSBjoern A. Zeeb #define SET_QUOTA_VAL(_min_x, _max_x, _module, _idx)			\
19488e93258fSBjoern A. Zeeb 	do {								\
1949e2340276SBjoern A. Zeeb 		val = u32_encode_bits(_min_x, B_AX_ ## _module ## _MIN_SIZE_MASK) | \
1950e2340276SBjoern A. Zeeb 		      u32_encode_bits(_max_x, B_AX_ ## _module ## _MAX_SIZE_MASK);  \
19518e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev,					\
19528e93258fSBjoern A. Zeeb 			      R_AX_ ## _module ## _QTA ## _idx ## _CFG,	\
19538e93258fSBjoern A. Zeeb 			      val);					\
19548e93258fSBjoern A. Zeeb 	} while (0)
19558e93258fSBjoern A. Zeeb #define SET_QUOTA(_x, _module, _idx)					\
19568e93258fSBjoern A. Zeeb 	SET_QUOTA_VAL(min_cfg->_x, max_cfg->_x, _module, _idx)
19578e93258fSBjoern A. Zeeb 
1958*6d67aabdSBjoern A. Zeeb static void wde_quota_cfg_ax(struct rtw89_dev *rtwdev,
19598e93258fSBjoern A. Zeeb 			     const struct rtw89_wde_quota *min_cfg,
19608e93258fSBjoern A. Zeeb 			     const struct rtw89_wde_quota *max_cfg,
19618e93258fSBjoern A. Zeeb 			     u16 ext_wde_min_qt_wcpu)
19628e93258fSBjoern A. Zeeb {
19638e93258fSBjoern A. Zeeb 	u16 min_qt_wcpu = ext_wde_min_qt_wcpu != INVALID_QT_WCPU ?
19648e93258fSBjoern A. Zeeb 			  ext_wde_min_qt_wcpu : min_cfg->wcpu;
19658e93258fSBjoern A. Zeeb 	u32 val;
19668e93258fSBjoern A. Zeeb 
19678e93258fSBjoern A. Zeeb 	SET_QUOTA(hif, WDE, 0);
19688e93258fSBjoern A. Zeeb 	SET_QUOTA_VAL(min_qt_wcpu, max_cfg->wcpu, WDE, 1);
19698e93258fSBjoern A. Zeeb 	SET_QUOTA(pkt_in, WDE, 3);
19708e93258fSBjoern A. Zeeb 	SET_QUOTA(cpu_io, WDE, 4);
19718e93258fSBjoern A. Zeeb }
19728e93258fSBjoern A. Zeeb 
1973*6d67aabdSBjoern A. Zeeb static void ple_quota_cfg_ax(struct rtw89_dev *rtwdev,
19748e93258fSBjoern A. Zeeb 			     const struct rtw89_ple_quota *min_cfg,
19758e93258fSBjoern A. Zeeb 			     const struct rtw89_ple_quota *max_cfg)
19768e93258fSBjoern A. Zeeb {
19778e93258fSBjoern A. Zeeb 	u32 val;
19788e93258fSBjoern A. Zeeb 
19798e93258fSBjoern A. Zeeb 	SET_QUOTA(cma0_tx, PLE, 0);
19808e93258fSBjoern A. Zeeb 	SET_QUOTA(cma1_tx, PLE, 1);
19818e93258fSBjoern A. Zeeb 	SET_QUOTA(c2h, PLE, 2);
19828e93258fSBjoern A. Zeeb 	SET_QUOTA(h2c, PLE, 3);
19838e93258fSBjoern A. Zeeb 	SET_QUOTA(wcpu, PLE, 4);
19848e93258fSBjoern A. Zeeb 	SET_QUOTA(mpdu_proc, PLE, 5);
19858e93258fSBjoern A. Zeeb 	SET_QUOTA(cma0_dma, PLE, 6);
19868e93258fSBjoern A. Zeeb 	SET_QUOTA(cma1_dma, PLE, 7);
19878e93258fSBjoern A. Zeeb 	SET_QUOTA(bb_rpt, PLE, 8);
19888e93258fSBjoern A. Zeeb 	SET_QUOTA(wd_rel, PLE, 9);
19898e93258fSBjoern A. Zeeb 	SET_QUOTA(cpu_io, PLE, 10);
19908e93258fSBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8852C)
19918e93258fSBjoern A. Zeeb 		SET_QUOTA(tx_rpt, PLE, 11);
19928e93258fSBjoern A. Zeeb }
19938e93258fSBjoern A. Zeeb 
1994e2340276SBjoern A. Zeeb int rtw89_mac_resize_ple_rx_quota(struct rtw89_dev *rtwdev, bool wow)
1995e2340276SBjoern A. Zeeb {
1996e2340276SBjoern A. Zeeb 	const struct rtw89_ple_quota *min_cfg, *max_cfg;
1997e2340276SBjoern A. Zeeb 	const struct rtw89_dle_mem *cfg;
1998e2340276SBjoern A. Zeeb 	u32 val;
1999e2340276SBjoern A. Zeeb 
2000e2340276SBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8852C)
2001e2340276SBjoern A. Zeeb 		return 0;
2002e2340276SBjoern A. Zeeb 
2003e2340276SBjoern A. Zeeb 	if (rtwdev->mac.qta_mode != RTW89_QTA_SCC) {
2004e2340276SBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]support SCC mode only\n");
2005e2340276SBjoern A. Zeeb 		return -EINVAL;
2006e2340276SBjoern A. Zeeb 	}
2007e2340276SBjoern A. Zeeb 
2008e2340276SBjoern A. Zeeb 	if (wow)
2009e2340276SBjoern A. Zeeb 		cfg = get_dle_mem_cfg(rtwdev, RTW89_QTA_WOW);
2010e2340276SBjoern A. Zeeb 	else
2011e2340276SBjoern A. Zeeb 		cfg = get_dle_mem_cfg(rtwdev, RTW89_QTA_SCC);
2012e2340276SBjoern A. Zeeb 	if (!cfg) {
2013e2340276SBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]get_dle_mem_cfg\n");
2014e2340276SBjoern A. Zeeb 		return -EINVAL;
2015e2340276SBjoern A. Zeeb 	}
2016e2340276SBjoern A. Zeeb 
2017e2340276SBjoern A. Zeeb 	min_cfg = cfg->ple_min_qt;
2018e2340276SBjoern A. Zeeb 	max_cfg = cfg->ple_max_qt;
2019e2340276SBjoern A. Zeeb 	SET_QUOTA(cma0_dma, PLE, 6);
2020e2340276SBjoern A. Zeeb 	SET_QUOTA(cma1_dma, PLE, 7);
2021e2340276SBjoern A. Zeeb 
2022e2340276SBjoern A. Zeeb 	return 0;
2023e2340276SBjoern A. Zeeb }
20248e93258fSBjoern A. Zeeb #undef SET_QUOTA
20258e93258fSBjoern A. Zeeb 
2026e2340276SBjoern A. Zeeb void rtw89_mac_hw_mgnt_sec(struct rtw89_dev *rtwdev, bool enable)
2027e2340276SBjoern A. Zeeb {
2028e2340276SBjoern A. Zeeb 	u32 msk32 = B_AX_UC_MGNT_DEC | B_AX_BMC_MGNT_DEC;
2029e2340276SBjoern A. Zeeb 
2030*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
2031*6d67aabdSBjoern A. Zeeb 		return;
2032*6d67aabdSBjoern A. Zeeb 
2033e2340276SBjoern A. Zeeb 	if (enable)
2034e2340276SBjoern A. Zeeb 		rtw89_write32_set(rtwdev, R_AX_SEC_ENG_CTRL, msk32);
2035e2340276SBjoern A. Zeeb 	else
2036e2340276SBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, R_AX_SEC_ENG_CTRL, msk32);
2037e2340276SBjoern A. Zeeb }
2038e2340276SBjoern A. Zeeb 
20398e93258fSBjoern A. Zeeb static void dle_quota_cfg(struct rtw89_dev *rtwdev,
20408e93258fSBjoern A. Zeeb 			  const struct rtw89_dle_mem *cfg,
20418e93258fSBjoern A. Zeeb 			  u16 ext_wde_min_qt_wcpu)
20428e93258fSBjoern A. Zeeb {
2043*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
2044*6d67aabdSBjoern A. Zeeb 
2045*6d67aabdSBjoern A. Zeeb 	mac->wde_quota_cfg(rtwdev, cfg->wde_min_qt, cfg->wde_max_qt, ext_wde_min_qt_wcpu);
2046*6d67aabdSBjoern A. Zeeb 	mac->ple_quota_cfg(rtwdev, cfg->ple_min_qt, cfg->ple_max_qt);
20478e93258fSBjoern A. Zeeb }
20488e93258fSBjoern A. Zeeb 
2049*6d67aabdSBjoern A. Zeeb int rtw89_mac_dle_init(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode,
20508e93258fSBjoern A. Zeeb 		       enum rtw89_qta_mode ext_mode)
20518e93258fSBjoern A. Zeeb {
2052*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
20538e93258fSBjoern A. Zeeb 	const struct rtw89_dle_mem *cfg, *ext_cfg;
20548e93258fSBjoern A. Zeeb 	u16 ext_wde_min_qt_wcpu = INVALID_QT_WCPU;
2055*6d67aabdSBjoern A. Zeeb 	int ret;
20568e93258fSBjoern A. Zeeb 
20578e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
20588e93258fSBjoern A. Zeeb 	if (ret)
20598e93258fSBjoern A. Zeeb 		return ret;
20608e93258fSBjoern A. Zeeb 
20618e93258fSBjoern A. Zeeb 	cfg = get_dle_mem_cfg(rtwdev, mode);
20628e93258fSBjoern A. Zeeb 	if (!cfg) {
20638e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]get_dle_mem_cfg\n");
20648e93258fSBjoern A. Zeeb 		ret = -EINVAL;
20658e93258fSBjoern A. Zeeb 		goto error;
20668e93258fSBjoern A. Zeeb 	}
20678e93258fSBjoern A. Zeeb 
20688e93258fSBjoern A. Zeeb 	if (mode == RTW89_QTA_DLFW) {
20698e93258fSBjoern A. Zeeb 		ext_cfg = get_dle_mem_cfg(rtwdev, ext_mode);
20708e93258fSBjoern A. Zeeb 		if (!ext_cfg) {
20718e93258fSBjoern A. Zeeb 			rtw89_err(rtwdev, "[ERR]get_dle_ext_mem_cfg %d\n",
20728e93258fSBjoern A. Zeeb 				  ext_mode);
20738e93258fSBjoern A. Zeeb 			ret = -EINVAL;
20748e93258fSBjoern A. Zeeb 			goto error;
20758e93258fSBjoern A. Zeeb 		}
20768e93258fSBjoern A. Zeeb 		ext_wde_min_qt_wcpu = ext_cfg->wde_min_qt->wcpu;
20778e93258fSBjoern A. Zeeb 	}
20788e93258fSBjoern A. Zeeb 
2079*6d67aabdSBjoern A. Zeeb 	if (dle_used_size(cfg) != dle_expected_used_size(rtwdev, mode)) {
20808e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]wd/dle mem cfg\n");
20818e93258fSBjoern A. Zeeb 		ret = -EINVAL;
20828e93258fSBjoern A. Zeeb 		goto error;
20838e93258fSBjoern A. Zeeb 	}
20848e93258fSBjoern A. Zeeb 
2085*6d67aabdSBjoern A. Zeeb 	mac->dle_func_en(rtwdev, false);
2086*6d67aabdSBjoern A. Zeeb 	mac->dle_clk_en(rtwdev, true);
20878e93258fSBjoern A. Zeeb 
2088*6d67aabdSBjoern A. Zeeb 	ret = mac->dle_mix_cfg(rtwdev, cfg);
20898e93258fSBjoern A. Zeeb 	if (ret) {
20908e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR] dle mix cfg\n");
20918e93258fSBjoern A. Zeeb 		goto error;
20928e93258fSBjoern A. Zeeb 	}
20938e93258fSBjoern A. Zeeb 	dle_quota_cfg(rtwdev, cfg, ext_wde_min_qt_wcpu);
20948e93258fSBjoern A. Zeeb 
2095*6d67aabdSBjoern A. Zeeb 	mac->dle_func_en(rtwdev, true);
20968e93258fSBjoern A. Zeeb 
2097*6d67aabdSBjoern A. Zeeb 	ret = mac->chk_dle_rdy(rtwdev, true);
20988e93258fSBjoern A. Zeeb 	if (ret) {
20998e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]WDE cfg ready\n");
21008e93258fSBjoern A. Zeeb 		return ret;
21018e93258fSBjoern A. Zeeb 	}
21028e93258fSBjoern A. Zeeb 
2103*6d67aabdSBjoern A. Zeeb 	ret = mac->chk_dle_rdy(rtwdev, false);
21048e93258fSBjoern A. Zeeb 	if (ret) {
21058e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]PLE cfg ready\n");
21068e93258fSBjoern A. Zeeb 		return ret;
21078e93258fSBjoern A. Zeeb 	}
21088e93258fSBjoern A. Zeeb 
21098e93258fSBjoern A. Zeeb 	return 0;
21108e93258fSBjoern A. Zeeb error:
2111*6d67aabdSBjoern A. Zeeb 	mac->dle_func_en(rtwdev, false);
21128e93258fSBjoern A. Zeeb 	rtw89_err(rtwdev, "[ERR]trxcfg wde 0x8900 = %x\n",
21138e93258fSBjoern A. Zeeb 		  rtw89_read32(rtwdev, R_AX_WDE_INI_STATUS));
21148e93258fSBjoern A. Zeeb 	rtw89_err(rtwdev, "[ERR]trxcfg ple 0x8D00 = %x\n",
21158e93258fSBjoern A. Zeeb 		  rtw89_read32(rtwdev, R_AX_PLE_INI_STATUS));
21168e93258fSBjoern A. Zeeb 
21178e93258fSBjoern A. Zeeb 	return ret;
21188e93258fSBjoern A. Zeeb }
21198e93258fSBjoern A. Zeeb 
21208e93258fSBjoern A. Zeeb static int preload_init_set(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx,
21218e93258fSBjoern A. Zeeb 			    enum rtw89_qta_mode mode)
21228e93258fSBjoern A. Zeeb {
21238e93258fSBjoern A. Zeeb 	u32 reg, max_preld_size, min_rsvd_size;
21248e93258fSBjoern A. Zeeb 
21258e93258fSBjoern A. Zeeb 	max_preld_size = (mac_idx == RTW89_MAC_0 ?
21268e93258fSBjoern A. Zeeb 			  PRELD_B0_ENT_NUM : PRELD_B1_ENT_NUM) * PRELD_AMSDU_SIZE;
21278e93258fSBjoern A. Zeeb 	reg = mac_idx == RTW89_MAC_0 ?
21288e93258fSBjoern A. Zeeb 	      R_AX_TXPKTCTL_B0_PRELD_CFG0 : R_AX_TXPKTCTL_B1_PRELD_CFG0;
21298e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_B0_PRELD_USEMAXSZ_MASK, max_preld_size);
21308e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, B_AX_B0_PRELD_FEN);
21318e93258fSBjoern A. Zeeb 
21328e93258fSBjoern A. Zeeb 	min_rsvd_size = PRELD_AMSDU_SIZE;
21338e93258fSBjoern A. Zeeb 	reg = mac_idx == RTW89_MAC_0 ?
21348e93258fSBjoern A. Zeeb 	      R_AX_TXPKTCTL_B0_PRELD_CFG1 : R_AX_TXPKTCTL_B1_PRELD_CFG1;
21358e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_B0_PRELD_NXT_TXENDWIN_MASK, PRELD_NEXT_WND);
21368e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_B0_PRELD_NXT_RSVMINSZ_MASK, min_rsvd_size);
21378e93258fSBjoern A. Zeeb 
21388e93258fSBjoern A. Zeeb 	return 0;
21398e93258fSBjoern A. Zeeb }
21408e93258fSBjoern A. Zeeb 
21418e93258fSBjoern A. Zeeb static bool is_qta_poh(struct rtw89_dev *rtwdev)
21428e93258fSBjoern A. Zeeb {
21438e93258fSBjoern A. Zeeb 	return rtwdev->hci.type == RTW89_HCI_TYPE_PCIE;
21448e93258fSBjoern A. Zeeb }
21458e93258fSBjoern A. Zeeb 
2146*6d67aabdSBjoern A. Zeeb int rtw89_mac_preload_init(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx,
21478e93258fSBjoern A. Zeeb 			   enum rtw89_qta_mode mode)
21488e93258fSBjoern A. Zeeb {
21498e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
21508e93258fSBjoern A. Zeeb 
2151*6d67aabdSBjoern A. Zeeb 	if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev) ||
2152*6d67aabdSBjoern A. Zeeb 	    !is_qta_poh(rtwdev))
21538e93258fSBjoern A. Zeeb 		return 0;
21548e93258fSBjoern A. Zeeb 
21558e93258fSBjoern A. Zeeb 	return preload_init_set(rtwdev, mac_idx, mode);
21568e93258fSBjoern A. Zeeb }
21578e93258fSBjoern A. Zeeb 
21588e93258fSBjoern A. Zeeb static bool dle_is_txq_empty(struct rtw89_dev *rtwdev)
21598e93258fSBjoern A. Zeeb {
21608e93258fSBjoern A. Zeeb 	u32 msk32;
21618e93258fSBjoern A. Zeeb 	u32 val32;
21628e93258fSBjoern A. Zeeb 
21638e93258fSBjoern A. Zeeb 	msk32 = B_AX_WDE_EMPTY_QUE_CMAC0_ALL_AC | B_AX_WDE_EMPTY_QUE_CMAC0_MBH |
21648e93258fSBjoern A. Zeeb 		B_AX_WDE_EMPTY_QUE_CMAC1_MBH | B_AX_WDE_EMPTY_QUE_CMAC0_WMM0 |
21658e93258fSBjoern A. Zeeb 		B_AX_WDE_EMPTY_QUE_CMAC0_WMM1 | B_AX_WDE_EMPTY_QUE_OTHERS |
21668e93258fSBjoern A. Zeeb 		B_AX_PLE_EMPTY_QUE_DMAC_MPDU_TX | B_AX_PLE_EMPTY_QTA_DMAC_H2C |
21678e93258fSBjoern A. Zeeb 		B_AX_PLE_EMPTY_QUE_DMAC_SEC_TX | B_AX_WDE_EMPTY_QUE_DMAC_PKTIN |
21688e93258fSBjoern A. Zeeb 		B_AX_WDE_EMPTY_QTA_DMAC_HIF | B_AX_WDE_EMPTY_QTA_DMAC_WLAN_CPU |
21698e93258fSBjoern A. Zeeb 		B_AX_WDE_EMPTY_QTA_DMAC_PKTIN | B_AX_WDE_EMPTY_QTA_DMAC_CPUIO |
21708e93258fSBjoern A. Zeeb 		B_AX_PLE_EMPTY_QTA_DMAC_B0_TXPL |
21718e93258fSBjoern A. Zeeb 		B_AX_PLE_EMPTY_QTA_DMAC_B1_TXPL |
21728e93258fSBjoern A. Zeeb 		B_AX_PLE_EMPTY_QTA_DMAC_MPDU_TX |
21738e93258fSBjoern A. Zeeb 		B_AX_PLE_EMPTY_QTA_DMAC_CPUIO |
21748e93258fSBjoern A. Zeeb 		B_AX_WDE_EMPTY_QTA_DMAC_DATA_CPU |
21758e93258fSBjoern A. Zeeb 		B_AX_PLE_EMPTY_QTA_DMAC_WLAN_CPU;
21768e93258fSBjoern A. Zeeb 	val32 = rtw89_read32(rtwdev, R_AX_DLE_EMPTY0);
21778e93258fSBjoern A. Zeeb 
21788e93258fSBjoern A. Zeeb 	if ((val32 & msk32) == msk32)
21798e93258fSBjoern A. Zeeb 		return true;
21808e93258fSBjoern A. Zeeb 
21818e93258fSBjoern A. Zeeb 	return false;
21828e93258fSBjoern A. Zeeb }
21838e93258fSBjoern A. Zeeb 
21848e93258fSBjoern A. Zeeb static void _patch_ss2f_path(struct rtw89_dev *rtwdev)
21858e93258fSBjoern A. Zeeb {
21868e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
21878e93258fSBjoern A. Zeeb 
2188*6d67aabdSBjoern A. Zeeb 	if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
21898e93258fSBjoern A. Zeeb 		return;
21908e93258fSBjoern A. Zeeb 
21918e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, R_AX_SS2FINFO_PATH, B_AX_SS_DEST_QUEUE_MASK,
21928e93258fSBjoern A. Zeeb 			   SS2F_PATH_WLCPU);
21938e93258fSBjoern A. Zeeb }
21948e93258fSBjoern A. Zeeb 
2195*6d67aabdSBjoern A. Zeeb static int sta_sch_init_ax(struct rtw89_dev *rtwdev)
21968e93258fSBjoern A. Zeeb {
21978e93258fSBjoern A. Zeeb 	u32 p_val;
21988e93258fSBjoern A. Zeeb 	u8 val;
21998e93258fSBjoern A. Zeeb 	int ret;
22008e93258fSBjoern A. Zeeb 
22018e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
22028e93258fSBjoern A. Zeeb 	if (ret)
22038e93258fSBjoern A. Zeeb 		return ret;
22048e93258fSBjoern A. Zeeb 
22058e93258fSBjoern A. Zeeb 	val = rtw89_read8(rtwdev, R_AX_SS_CTRL);
22068e93258fSBjoern A. Zeeb 	val |= B_AX_SS_EN;
22078e93258fSBjoern A. Zeeb 	rtw89_write8(rtwdev, R_AX_SS_CTRL, val);
22088e93258fSBjoern A. Zeeb 
22098e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read32, p_val, p_val & B_AX_SS_INIT_DONE_1,
22108e93258fSBjoern A. Zeeb 				1, TRXCFG_WAIT_CNT, false, rtwdev, R_AX_SS_CTRL);
22118e93258fSBjoern A. Zeeb 	if (ret) {
22128e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]STA scheduler init\n");
22138e93258fSBjoern A. Zeeb 		return ret;
22148e93258fSBjoern A. Zeeb 	}
22158e93258fSBjoern A. Zeeb 
22168e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_SS_CTRL, B_AX_SS_WARM_INIT_FLG);
22178e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_SS_CTRL, B_AX_SS_NONEMPTY_SS2FINFO_EN);
22188e93258fSBjoern A. Zeeb 
22198e93258fSBjoern A. Zeeb 	_patch_ss2f_path(rtwdev);
22208e93258fSBjoern A. Zeeb 
22218e93258fSBjoern A. Zeeb 	return 0;
22228e93258fSBjoern A. Zeeb }
22238e93258fSBjoern A. Zeeb 
2224*6d67aabdSBjoern A. Zeeb static int mpdu_proc_init_ax(struct rtw89_dev *rtwdev)
22258e93258fSBjoern A. Zeeb {
22268e93258fSBjoern A. Zeeb 	int ret;
22278e93258fSBjoern A. Zeeb 
22288e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
22298e93258fSBjoern A. Zeeb 	if (ret)
22308e93258fSBjoern A. Zeeb 		return ret;
22318e93258fSBjoern A. Zeeb 
22328e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_ACTION_FWD0, TRXCFG_MPDU_PROC_ACT_FRWD);
22338e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_TF_FWD, TRXCFG_MPDU_PROC_TF_FRWD);
22348e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_MPDU_PROC,
22358e93258fSBjoern A. Zeeb 			  B_AX_APPEND_FCS | B_AX_A_ICV_ERR);
22368e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_CUT_AMSDU_CTRL, TRXCFG_MPDU_PROC_CUT_CTRL);
22378e93258fSBjoern A. Zeeb 
22388e93258fSBjoern A. Zeeb 	return 0;
22398e93258fSBjoern A. Zeeb }
22408e93258fSBjoern A. Zeeb 
2241*6d67aabdSBjoern A. Zeeb static int sec_eng_init_ax(struct rtw89_dev *rtwdev)
22428e93258fSBjoern A. Zeeb {
22438e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
22448e93258fSBjoern A. Zeeb 	u32 val = 0;
22458e93258fSBjoern A. Zeeb 	int ret;
22468e93258fSBjoern A. Zeeb 
22478e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
22488e93258fSBjoern A. Zeeb 	if (ret)
22498e93258fSBjoern A. Zeeb 		return ret;
22508e93258fSBjoern A. Zeeb 
22518e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL);
22528e93258fSBjoern A. Zeeb 	/* init clock */
22538e93258fSBjoern A. Zeeb 	val |= (B_AX_CLK_EN_CGCMP | B_AX_CLK_EN_WAPI | B_AX_CLK_EN_WEP_TKIP);
22548e93258fSBjoern A. Zeeb 	/* init TX encryption */
22558e93258fSBjoern A. Zeeb 	val |= (B_AX_SEC_TX_ENC | B_AX_SEC_RX_DEC);
22568e93258fSBjoern A. Zeeb 	val |= (B_AX_MC_DEC | B_AX_BC_DEC);
2257e2340276SBjoern A. Zeeb 	if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
2258e2340276SBjoern A. Zeeb 	    chip->chip_id == RTL8851B)
22598e93258fSBjoern A. Zeeb 		val &= ~B_AX_TX_PARTIAL_MODE;
22608e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_SEC_ENG_CTRL, val);
22618e93258fSBjoern A. Zeeb 
22628e93258fSBjoern A. Zeeb 	/* init MIC ICV append */
22638e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC);
22648e93258fSBjoern A. Zeeb 	val |= (B_AX_APPEND_ICV | B_AX_APPEND_MIC);
22658e93258fSBjoern A. Zeeb 
22668e93258fSBjoern A. Zeeb 	/* option init */
22678e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_SEC_MPDU_PROC, val);
22688e93258fSBjoern A. Zeeb 
22698e93258fSBjoern A. Zeeb 	if (chip->chip_id == RTL8852C)
22708e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, R_AX_SEC_DEBUG1,
22718e93258fSBjoern A. Zeeb 				   B_AX_TX_TIMEOUT_SEL_MASK, AX_TX_TO_VAL);
22728e93258fSBjoern A. Zeeb 
22738e93258fSBjoern A. Zeeb 	return 0;
22748e93258fSBjoern A. Zeeb }
22758e93258fSBjoern A. Zeeb 
2276*6d67aabdSBjoern A. Zeeb static int dmac_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
22778e93258fSBjoern A. Zeeb {
22788e93258fSBjoern A. Zeeb 	int ret;
22798e93258fSBjoern A. Zeeb 
2280*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_dle_init(rtwdev, rtwdev->mac.qta_mode, RTW89_QTA_INVALID);
22818e93258fSBjoern A. Zeeb 	if (ret) {
22828e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]DLE init %d\n", ret);
22838e93258fSBjoern A. Zeeb 		return ret;
22848e93258fSBjoern A. Zeeb 	}
22858e93258fSBjoern A. Zeeb 
2286*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_preload_init(rtwdev, RTW89_MAC_0, rtwdev->mac.qta_mode);
22878e93258fSBjoern A. Zeeb 	if (ret) {
22888e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]preload init %d\n", ret);
22898e93258fSBjoern A. Zeeb 		return ret;
22908e93258fSBjoern A. Zeeb 	}
22918e93258fSBjoern A. Zeeb 
2292*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_hfc_init(rtwdev, true, true, true);
22938e93258fSBjoern A. Zeeb 	if (ret) {
22948e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]HCI FC init %d\n", ret);
22958e93258fSBjoern A. Zeeb 		return ret;
22968e93258fSBjoern A. Zeeb 	}
22978e93258fSBjoern A. Zeeb 
2298*6d67aabdSBjoern A. Zeeb 	ret = sta_sch_init_ax(rtwdev);
22998e93258fSBjoern A. Zeeb 	if (ret) {
23008e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]STA SCH init %d\n", ret);
23018e93258fSBjoern A. Zeeb 		return ret;
23028e93258fSBjoern A. Zeeb 	}
23038e93258fSBjoern A. Zeeb 
2304*6d67aabdSBjoern A. Zeeb 	ret = mpdu_proc_init_ax(rtwdev);
23058e93258fSBjoern A. Zeeb 	if (ret) {
23068e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]MPDU Proc init %d\n", ret);
23078e93258fSBjoern A. Zeeb 		return ret;
23088e93258fSBjoern A. Zeeb 	}
23098e93258fSBjoern A. Zeeb 
2310*6d67aabdSBjoern A. Zeeb 	ret = sec_eng_init_ax(rtwdev);
23118e93258fSBjoern A. Zeeb 	if (ret) {
23128e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]Security Engine init %d\n", ret);
23138e93258fSBjoern A. Zeeb 		return ret;
23148e93258fSBjoern A. Zeeb 	}
23158e93258fSBjoern A. Zeeb 
23168e93258fSBjoern A. Zeeb 	return ret;
23178e93258fSBjoern A. Zeeb }
23188e93258fSBjoern A. Zeeb 
2319*6d67aabdSBjoern A. Zeeb static int addr_cam_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
23208e93258fSBjoern A. Zeeb {
23218e93258fSBjoern A. Zeeb 	u32 val, reg;
23228e93258fSBjoern A. Zeeb 	u16 p_val;
23238e93258fSBjoern A. Zeeb 	int ret;
23248e93258fSBjoern A. Zeeb 
23258e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
23268e93258fSBjoern A. Zeeb 	if (ret)
23278e93258fSBjoern A. Zeeb 		return ret;
23288e93258fSBjoern A. Zeeb 
2329*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_ADDR_CAM_CTRL, mac_idx);
23308e93258fSBjoern A. Zeeb 
23318e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, reg);
23328e93258fSBjoern A. Zeeb 	val |= u32_encode_bits(0x7f, B_AX_ADDR_CAM_RANGE_MASK) |
23338e93258fSBjoern A. Zeeb 	       B_AX_ADDR_CAM_CLR | B_AX_ADDR_CAM_EN;
23348e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
23358e93258fSBjoern A. Zeeb 
23368e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read16, p_val, !(p_val & B_AX_ADDR_CAM_CLR),
23378e93258fSBjoern A. Zeeb 				1, TRXCFG_WAIT_CNT, false, rtwdev, reg);
23388e93258fSBjoern A. Zeeb 	if (ret) {
23398e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]ADDR_CAM reset\n");
23408e93258fSBjoern A. Zeeb 		return ret;
23418e93258fSBjoern A. Zeeb 	}
23428e93258fSBjoern A. Zeeb 
23438e93258fSBjoern A. Zeeb 	return 0;
23448e93258fSBjoern A. Zeeb }
23458e93258fSBjoern A. Zeeb 
2346*6d67aabdSBjoern A. Zeeb static int scheduler_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
23478e93258fSBjoern A. Zeeb {
23488e93258fSBjoern A. Zeeb 	u32 ret;
23498e93258fSBjoern A. Zeeb 	u32 reg;
23508e93258fSBjoern A. Zeeb 	u32 val;
23518e93258fSBjoern A. Zeeb 
23528e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
23538e93258fSBjoern A. Zeeb 	if (ret)
23548e93258fSBjoern A. Zeeb 		return ret;
23558e93258fSBjoern A. Zeeb 
2356*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PREBKF_CFG_1, mac_idx);
23578e93258fSBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8852C)
23588e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK,
23598e93258fSBjoern A. Zeeb 				   SIFS_MACTXEN_T1_V1);
23608e93258fSBjoern A. Zeeb 	else
23618e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK,
23628e93258fSBjoern A. Zeeb 				   SIFS_MACTXEN_T1);
23638e93258fSBjoern A. Zeeb 
2364*6d67aabdSBjoern A. Zeeb 	if (rtw89_is_rtl885xb(rtwdev)) {
2365*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_SCH_EXT_CTRL, mac_idx);
23668e93258fSBjoern A. Zeeb 		rtw89_write32_set(rtwdev, reg, B_AX_PORT_RST_TSF_ADV);
23678e93258fSBjoern A. Zeeb 	}
23688e93258fSBjoern A. Zeeb 
2369*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CCA_CFG_0, mac_idx);
23708e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, reg, B_AX_BTCCA_EN);
23718e93258fSBjoern A. Zeeb 
2372*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PREBKF_CFG_0, mac_idx);
23738e93258fSBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8852C) {
23748e93258fSBjoern A. Zeeb 		val = rtw89_read32_mask(rtwdev, R_AX_SEC_ENG_CTRL,
23758e93258fSBjoern A. Zeeb 					B_AX_TX_PARTIAL_MODE);
23768e93258fSBjoern A. Zeeb 		if (!val)
23778e93258fSBjoern A. Zeeb 			rtw89_write32_mask(rtwdev, reg, B_AX_PREBKF_TIME_MASK,
23788e93258fSBjoern A. Zeeb 					   SCH_PREBKF_24US);
23798e93258fSBjoern A. Zeeb 	} else {
23808e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, reg, B_AX_PREBKF_TIME_MASK,
23818e93258fSBjoern A. Zeeb 				   SCH_PREBKF_24US);
23828e93258fSBjoern A. Zeeb 	}
23838e93258fSBjoern A. Zeeb 
23848e93258fSBjoern A. Zeeb 	return 0;
23858e93258fSBjoern A. Zeeb }
23868e93258fSBjoern A. Zeeb 
2387*6d67aabdSBjoern A. Zeeb static int rtw89_mac_typ_fltr_opt_ax(struct rtw89_dev *rtwdev,
23888e93258fSBjoern A. Zeeb 				     enum rtw89_machdr_frame_type type,
23898e93258fSBjoern A. Zeeb 				     enum rtw89_mac_fwd_target fwd_target,
23908e93258fSBjoern A. Zeeb 				     u8 mac_idx)
23918e93258fSBjoern A. Zeeb {
23928e93258fSBjoern A. Zeeb 	u32 reg;
23938e93258fSBjoern A. Zeeb 	u32 val;
23948e93258fSBjoern A. Zeeb 
23958e93258fSBjoern A. Zeeb 	switch (fwd_target) {
23968e93258fSBjoern A. Zeeb 	case RTW89_FWD_DONT_CARE:
23978e93258fSBjoern A. Zeeb 		val = RX_FLTR_FRAME_DROP;
23988e93258fSBjoern A. Zeeb 		break;
23998e93258fSBjoern A. Zeeb 	case RTW89_FWD_TO_HOST:
24008e93258fSBjoern A. Zeeb 		val = RX_FLTR_FRAME_TO_HOST;
24018e93258fSBjoern A. Zeeb 		break;
24028e93258fSBjoern A. Zeeb 	case RTW89_FWD_TO_WLAN_CPU:
24038e93258fSBjoern A. Zeeb 		val = RX_FLTR_FRAME_TO_WLCPU;
24048e93258fSBjoern A. Zeeb 		break;
24058e93258fSBjoern A. Zeeb 	default:
24068e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]set rx filter fwd target err\n");
24078e93258fSBjoern A. Zeeb 		return -EINVAL;
24088e93258fSBjoern A. Zeeb 	}
24098e93258fSBjoern A. Zeeb 
24108e93258fSBjoern A. Zeeb 	switch (type) {
24118e93258fSBjoern A. Zeeb 	case RTW89_MGNT:
2412*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_MGNT_FLTR, mac_idx);
24138e93258fSBjoern A. Zeeb 		break;
24148e93258fSBjoern A. Zeeb 	case RTW89_CTRL:
2415*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CTRL_FLTR, mac_idx);
24168e93258fSBjoern A. Zeeb 		break;
24178e93258fSBjoern A. Zeeb 	case RTW89_DATA:
2418*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_DATA_FLTR, mac_idx);
24198e93258fSBjoern A. Zeeb 		break;
24208e93258fSBjoern A. Zeeb 	default:
24218e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]set rx filter type err\n");
24228e93258fSBjoern A. Zeeb 		return -EINVAL;
24238e93258fSBjoern A. Zeeb 	}
24248e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
24258e93258fSBjoern A. Zeeb 
24268e93258fSBjoern A. Zeeb 	return 0;
24278e93258fSBjoern A. Zeeb }
24288e93258fSBjoern A. Zeeb 
2429*6d67aabdSBjoern A. Zeeb static int rx_fltr_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
24308e93258fSBjoern A. Zeeb {
24318e93258fSBjoern A. Zeeb 	int ret, i;
24328e93258fSBjoern A. Zeeb 	u32 mac_ftlr, plcp_ftlr;
24338e93258fSBjoern A. Zeeb 
24348e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
24358e93258fSBjoern A. Zeeb 	if (ret)
24368e93258fSBjoern A. Zeeb 		return ret;
24378e93258fSBjoern A. Zeeb 
24388e93258fSBjoern A. Zeeb 	for (i = RTW89_MGNT; i <= RTW89_DATA; i++) {
2439*6d67aabdSBjoern A. Zeeb 		ret = rtw89_mac_typ_fltr_opt_ax(rtwdev, i, RTW89_FWD_TO_HOST,
24408e93258fSBjoern A. Zeeb 						mac_idx);
24418e93258fSBjoern A. Zeeb 		if (ret)
24428e93258fSBjoern A. Zeeb 			return ret;
24438e93258fSBjoern A. Zeeb 	}
24448e93258fSBjoern A. Zeeb 	mac_ftlr = rtwdev->hal.rx_fltr;
24458e93258fSBjoern A. Zeeb 	plcp_ftlr = B_AX_CCK_CRC_CHK | B_AX_CCK_SIG_CHK |
24468e93258fSBjoern A. Zeeb 		    B_AX_LSIG_PARITY_CHK_EN | B_AX_SIGA_CRC_CHK |
24478e93258fSBjoern A. Zeeb 		    B_AX_VHT_SU_SIGB_CRC_CHK | B_AX_VHT_MU_SIGB_CRC_CHK |
24488e93258fSBjoern A. Zeeb 		    B_AX_HE_SIGB_CRC_CHK;
2449*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, mac_idx),
24508e93258fSBjoern A. Zeeb 		      mac_ftlr);
2451*6d67aabdSBjoern A. Zeeb 	rtw89_write16(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_PLCP_HDR_FLTR, mac_idx),
24528e93258fSBjoern A. Zeeb 		      plcp_ftlr);
24538e93258fSBjoern A. Zeeb 
24548e93258fSBjoern A. Zeeb 	return 0;
24558e93258fSBjoern A. Zeeb }
24568e93258fSBjoern A. Zeeb 
24578e93258fSBjoern A. Zeeb static void _patch_dis_resp_chk(struct rtw89_dev *rtwdev, u8 mac_idx)
24588e93258fSBjoern A. Zeeb {
24598e93258fSBjoern A. Zeeb 	u32 reg, val32;
24608e93258fSBjoern A. Zeeb 	u32 b_rsp_chk_nav, b_rsp_chk_cca;
24618e93258fSBjoern A. Zeeb 
24628e93258fSBjoern A. Zeeb 	b_rsp_chk_nav = B_AX_RSP_CHK_TXNAV | B_AX_RSP_CHK_INTRA_NAV |
24638e93258fSBjoern A. Zeeb 			B_AX_RSP_CHK_BASIC_NAV;
24648e93258fSBjoern A. Zeeb 	b_rsp_chk_cca = B_AX_RSP_CHK_SEC_CCA_80 | B_AX_RSP_CHK_SEC_CCA_40 |
24658e93258fSBjoern A. Zeeb 			B_AX_RSP_CHK_SEC_CCA_20 | B_AX_RSP_CHK_BTCCA |
24668e93258fSBjoern A. Zeeb 			B_AX_RSP_CHK_EDCCA | B_AX_RSP_CHK_CCA;
24678e93258fSBjoern A. Zeeb 
24688e93258fSBjoern A. Zeeb 	switch (rtwdev->chip->chip_id) {
24698e93258fSBjoern A. Zeeb 	case RTL8852A:
24708e93258fSBjoern A. Zeeb 	case RTL8852B:
2471*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RSP_CHK_SIG, mac_idx);
24728e93258fSBjoern A. Zeeb 		val32 = rtw89_read32(rtwdev, reg) & ~b_rsp_chk_nav;
24738e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, reg, val32);
24748e93258fSBjoern A. Zeeb 
2475*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_0, mac_idx);
24768e93258fSBjoern A. Zeeb 		val32 = rtw89_read32(rtwdev, reg) & ~b_rsp_chk_cca;
24778e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, reg, val32);
24788e93258fSBjoern A. Zeeb 		break;
24798e93258fSBjoern A. Zeeb 	default:
2480*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RSP_CHK_SIG, mac_idx);
24818e93258fSBjoern A. Zeeb 		val32 = rtw89_read32(rtwdev, reg) | b_rsp_chk_nav;
24828e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, reg, val32);
24838e93258fSBjoern A. Zeeb 
2484*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_0, mac_idx);
24858e93258fSBjoern A. Zeeb 		val32 = rtw89_read32(rtwdev, reg) | b_rsp_chk_cca;
24868e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, reg, val32);
24878e93258fSBjoern A. Zeeb 		break;
24888e93258fSBjoern A. Zeeb 	}
24898e93258fSBjoern A. Zeeb }
24908e93258fSBjoern A. Zeeb 
2491*6d67aabdSBjoern A. Zeeb static int cca_ctrl_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
24928e93258fSBjoern A. Zeeb {
24938e93258fSBjoern A. Zeeb 	u32 val, reg;
24948e93258fSBjoern A. Zeeb 	int ret;
24958e93258fSBjoern A. Zeeb 
24968e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
24978e93258fSBjoern A. Zeeb 	if (ret)
24988e93258fSBjoern A. Zeeb 		return ret;
24998e93258fSBjoern A. Zeeb 
2500*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CCA_CONTROL, mac_idx);
25018e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, reg);
25028e93258fSBjoern A. Zeeb 	val |= (B_AX_TB_CHK_BASIC_NAV | B_AX_TB_CHK_BTCCA |
25038e93258fSBjoern A. Zeeb 		B_AX_TB_CHK_EDCCA | B_AX_TB_CHK_CCA_P20 |
25048e93258fSBjoern A. Zeeb 		B_AX_SIFS_CHK_BTCCA | B_AX_SIFS_CHK_CCA_P20 |
25058e93258fSBjoern A. Zeeb 		B_AX_CTN_CHK_INTRA_NAV |
25068e93258fSBjoern A. Zeeb 		B_AX_CTN_CHK_BASIC_NAV | B_AX_CTN_CHK_BTCCA |
25078e93258fSBjoern A. Zeeb 		B_AX_CTN_CHK_EDCCA | B_AX_CTN_CHK_CCA_S80 |
25088e93258fSBjoern A. Zeeb 		B_AX_CTN_CHK_CCA_S40 | B_AX_CTN_CHK_CCA_S20 |
25098e93258fSBjoern A. Zeeb 		B_AX_CTN_CHK_CCA_P20);
25108e93258fSBjoern A. Zeeb 	val &= ~(B_AX_TB_CHK_TX_NAV | B_AX_TB_CHK_CCA_S80 |
25118e93258fSBjoern A. Zeeb 		 B_AX_TB_CHK_CCA_S40 | B_AX_TB_CHK_CCA_S20 |
25128e93258fSBjoern A. Zeeb 		 B_AX_SIFS_CHK_CCA_S80 | B_AX_SIFS_CHK_CCA_S40 |
25138e93258fSBjoern A. Zeeb 		 B_AX_SIFS_CHK_CCA_S20 | B_AX_CTN_CHK_TXNAV |
25148e93258fSBjoern A. Zeeb 		 B_AX_SIFS_CHK_EDCCA);
25158e93258fSBjoern A. Zeeb 
25168e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
25178e93258fSBjoern A. Zeeb 
25188e93258fSBjoern A. Zeeb 	_patch_dis_resp_chk(rtwdev, mac_idx);
25198e93258fSBjoern A. Zeeb 
25208e93258fSBjoern A. Zeeb 	return 0;
25218e93258fSBjoern A. Zeeb }
25228e93258fSBjoern A. Zeeb 
2523*6d67aabdSBjoern A. Zeeb static int nav_ctrl_init_ax(struct rtw89_dev *rtwdev)
25248e93258fSBjoern A. Zeeb {
25258e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_WMAC_NAV_CTL, B_AX_WMAC_PLCP_UP_NAV_EN |
25268e93258fSBjoern A. Zeeb 						     B_AX_WMAC_TF_UP_NAV_EN |
25278e93258fSBjoern A. Zeeb 						     B_AX_WMAC_NAV_UPPER_EN);
2528e2340276SBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, R_AX_WMAC_NAV_CTL, B_AX_WMAC_NAV_UPPER_MASK, NAV_25MS);
25298e93258fSBjoern A. Zeeb 
25308e93258fSBjoern A. Zeeb 	return 0;
25318e93258fSBjoern A. Zeeb }
25328e93258fSBjoern A. Zeeb 
2533*6d67aabdSBjoern A. Zeeb static int spatial_reuse_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
25348e93258fSBjoern A. Zeeb {
25358e93258fSBjoern A. Zeeb 	u32 reg;
25368e93258fSBjoern A. Zeeb 	int ret;
25378e93258fSBjoern A. Zeeb 
25388e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
25398e93258fSBjoern A. Zeeb 	if (ret)
25408e93258fSBjoern A. Zeeb 		return ret;
2541*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_SR_CTRL, mac_idx);
25428e93258fSBjoern A. Zeeb 	rtw89_write8_clr(rtwdev, reg, B_AX_SR_EN);
25438e93258fSBjoern A. Zeeb 
2544*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BSSID_SRC_CTRL, mac_idx);
2545*6d67aabdSBjoern A. Zeeb 	rtw89_write8_set(rtwdev, reg, B_AX_PLCP_SRC_EN);
2546*6d67aabdSBjoern A. Zeeb 
25478e93258fSBjoern A. Zeeb 	return 0;
25488e93258fSBjoern A. Zeeb }
25498e93258fSBjoern A. Zeeb 
2550*6d67aabdSBjoern A. Zeeb static int tmac_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
25518e93258fSBjoern A. Zeeb {
25528e93258fSBjoern A. Zeeb 	u32 reg;
25538e93258fSBjoern A. Zeeb 	int ret;
25548e93258fSBjoern A. Zeeb 
25558e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
25568e93258fSBjoern A. Zeeb 	if (ret)
25578e93258fSBjoern A. Zeeb 		return ret;
25588e93258fSBjoern A. Zeeb 
2559*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_MAC_LOOPBACK, mac_idx);
25608e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, reg, B_AX_MACLBK_EN);
25618e93258fSBjoern A. Zeeb 
2562*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TCR0, mac_idx);
25638e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_TCR_UDF_THSD_MASK, TCR_UDF_THSD);
25648e93258fSBjoern A. Zeeb 
2565*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXD_FIFO_CTRL, mac_idx);
25668e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_TXDFIFO_HIGH_MCS_THRE_MASK, TXDFIFO_HIGH_MCS_THRE);
25678e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_TXDFIFO_LOW_MCS_THRE_MASK, TXDFIFO_LOW_MCS_THRE);
25688e93258fSBjoern A. Zeeb 
25698e93258fSBjoern A. Zeeb 	return 0;
25708e93258fSBjoern A. Zeeb }
25718e93258fSBjoern A. Zeeb 
2572*6d67aabdSBjoern A. Zeeb static int trxptcl_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
25738e93258fSBjoern A. Zeeb {
2574e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
2575e2340276SBjoern A. Zeeb 	const struct rtw89_rrsr_cfgs *rrsr = chip->rrsr_cfgs;
25768e93258fSBjoern A. Zeeb 	u32 reg, val, sifs;
25778e93258fSBjoern A. Zeeb 	int ret;
25788e93258fSBjoern A. Zeeb 
25798e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
25808e93258fSBjoern A. Zeeb 	if (ret)
25818e93258fSBjoern A. Zeeb 		return ret;
25828e93258fSBjoern A. Zeeb 
2583*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_0, mac_idx);
25848e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, reg);
25858e93258fSBjoern A. Zeeb 	val &= ~B_AX_WMAC_SPEC_SIFS_CCK_MASK;
25868e93258fSBjoern A. Zeeb 	val |= FIELD_PREP(B_AX_WMAC_SPEC_SIFS_CCK_MASK, WMAC_SPEC_SIFS_CCK);
25878e93258fSBjoern A. Zeeb 
25888e93258fSBjoern A. Zeeb 	switch (rtwdev->chip->chip_id) {
25898e93258fSBjoern A. Zeeb 	case RTL8852A:
25908e93258fSBjoern A. Zeeb 		sifs = WMAC_SPEC_SIFS_OFDM_52A;
25918e93258fSBjoern A. Zeeb 		break;
2592*6d67aabdSBjoern A. Zeeb 	case RTL8851B:
25938e93258fSBjoern A. Zeeb 	case RTL8852B:
2594*6d67aabdSBjoern A. Zeeb 	case RTL8852BT:
25958e93258fSBjoern A. Zeeb 		sifs = WMAC_SPEC_SIFS_OFDM_52B;
25968e93258fSBjoern A. Zeeb 		break;
25978e93258fSBjoern A. Zeeb 	default:
25988e93258fSBjoern A. Zeeb 		sifs = WMAC_SPEC_SIFS_OFDM_52C;
25998e93258fSBjoern A. Zeeb 		break;
26008e93258fSBjoern A. Zeeb 	}
26018e93258fSBjoern A. Zeeb 	val &= ~B_AX_WMAC_SPEC_SIFS_OFDM_MASK;
26028e93258fSBjoern A. Zeeb 	val |= FIELD_PREP(B_AX_WMAC_SPEC_SIFS_OFDM_MASK, sifs);
26038e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
26048e93258fSBjoern A. Zeeb 
2605*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RXTRIG_TEST_USER_2, mac_idx);
26068e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, B_AX_RXTRIG_FCSCHK_EN);
26078e93258fSBjoern A. Zeeb 
2608*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, rrsr->ref_rate.addr, mac_idx);
2609e2340276SBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, rrsr->ref_rate.mask, rrsr->ref_rate.data);
2610*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, rrsr->rsc.addr, mac_idx);
2611e2340276SBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, rrsr->rsc.mask, rrsr->rsc.data);
2612e2340276SBjoern A. Zeeb 
26138e93258fSBjoern A. Zeeb 	return 0;
26148e93258fSBjoern A. Zeeb }
26158e93258fSBjoern A. Zeeb 
26168e93258fSBjoern A. Zeeb static void rst_bacam(struct rtw89_dev *rtwdev)
26178e93258fSBjoern A. Zeeb {
26188e93258fSBjoern A. Zeeb 	u32 val32;
26198e93258fSBjoern A. Zeeb 	int ret;
26208e93258fSBjoern A. Zeeb 
26218e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, R_AX_RESPBA_CAM_CTRL, B_AX_BACAM_RST_MASK,
26228e93258fSBjoern A. Zeeb 			   S_AX_BACAM_RST_ALL);
26238e93258fSBjoern A. Zeeb 
26248e93258fSBjoern A. Zeeb 	ret = read_poll_timeout_atomic(rtw89_read32_mask, val32, val32 == 0,
26258e93258fSBjoern A. Zeeb 				       1, 1000, false,
26268e93258fSBjoern A. Zeeb 				       rtwdev, R_AX_RESPBA_CAM_CTRL, B_AX_BACAM_RST_MASK);
26278e93258fSBjoern A. Zeeb 	if (ret)
26288e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "failed to reset BA CAM\n");
26298e93258fSBjoern A. Zeeb }
26308e93258fSBjoern A. Zeeb 
2631*6d67aabdSBjoern A. Zeeb static int rmac_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
26328e93258fSBjoern A. Zeeb {
26338e93258fSBjoern A. Zeeb #define TRXCFG_RMAC_CCA_TO	32
26348e93258fSBjoern A. Zeeb #define TRXCFG_RMAC_DATA_TO	15
26358e93258fSBjoern A. Zeeb #define RX_MAX_LEN_UNIT 512
26368e93258fSBjoern A. Zeeb #define PLD_RLS_MAX_PG 127
26378e93258fSBjoern A. Zeeb #define RX_SPEC_MAX_LEN (11454 + RX_MAX_LEN_UNIT)
2638*6d67aabdSBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
26398e93258fSBjoern A. Zeeb 	int ret;
26408e93258fSBjoern A. Zeeb 	u32 reg, rx_max_len, rx_qta;
26418e93258fSBjoern A. Zeeb 	u16 val;
26428e93258fSBjoern A. Zeeb 
26438e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
26448e93258fSBjoern A. Zeeb 	if (ret)
26458e93258fSBjoern A. Zeeb 		return ret;
26468e93258fSBjoern A. Zeeb 
26478e93258fSBjoern A. Zeeb 	if (mac_idx == RTW89_MAC_0)
26488e93258fSBjoern A. Zeeb 		rst_bacam(rtwdev);
26498e93258fSBjoern A. Zeeb 
2650*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RESPBA_CAM_CTRL, mac_idx);
26518e93258fSBjoern A. Zeeb 	rtw89_write8_set(rtwdev, reg, B_AX_SSN_SEL);
26528e93258fSBjoern A. Zeeb 
2653*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_DLK_PROTECT_CTL, mac_idx);
26548e93258fSBjoern A. Zeeb 	val = rtw89_read16(rtwdev, reg);
26558e93258fSBjoern A. Zeeb 	val = u16_replace_bits(val, TRXCFG_RMAC_DATA_TO,
26568e93258fSBjoern A. Zeeb 			       B_AX_RX_DLK_DATA_TIME_MASK);
26578e93258fSBjoern A. Zeeb 	val = u16_replace_bits(val, TRXCFG_RMAC_CCA_TO,
26588e93258fSBjoern A. Zeeb 			       B_AX_RX_DLK_CCA_TIME_MASK);
2659*6d67aabdSBjoern A. Zeeb 	if (chip_id == RTL8852BT)
2660*6d67aabdSBjoern A. Zeeb 		val |= B_AX_RX_DLK_RST_EN;
26618e93258fSBjoern A. Zeeb 	rtw89_write16(rtwdev, reg, val);
26628e93258fSBjoern A. Zeeb 
2663*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RCR, mac_idx);
26648e93258fSBjoern A. Zeeb 	rtw89_write8_mask(rtwdev, reg, B_AX_CH_EN_MASK, 0x1);
26658e93258fSBjoern A. Zeeb 
2666*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RX_FLTR_OPT, mac_idx);
26678e93258fSBjoern A. Zeeb 	if (mac_idx == RTW89_MAC_0)
26688e93258fSBjoern A. Zeeb 		rx_qta = rtwdev->mac.dle_info.c0_rx_qta;
26698e93258fSBjoern A. Zeeb 	else
26708e93258fSBjoern A. Zeeb 		rx_qta = rtwdev->mac.dle_info.c1_rx_qta;
26718e93258fSBjoern A. Zeeb 	rx_qta = min_t(u32, rx_qta, PLD_RLS_MAX_PG);
26728e93258fSBjoern A. Zeeb 	rx_max_len = rx_qta * rtwdev->mac.dle_info.ple_pg_size;
26738e93258fSBjoern A. Zeeb 	rx_max_len = min_t(u32, rx_max_len, RX_SPEC_MAX_LEN);
26748e93258fSBjoern A. Zeeb 	rx_max_len /= RX_MAX_LEN_UNIT;
26758e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_RX_MPDU_MAX_LEN_MASK, rx_max_len);
26768e93258fSBjoern A. Zeeb 
2677*6d67aabdSBjoern A. Zeeb 	if (chip_id == RTL8852A && rtwdev->hal.cv == CHIP_CBV) {
26788e93258fSBjoern A. Zeeb 		rtw89_write16_mask(rtwdev,
2679*6d67aabdSBjoern A. Zeeb 				   rtw89_mac_reg_by_idx(rtwdev, R_AX_DLK_PROTECT_CTL, mac_idx),
26808e93258fSBjoern A. Zeeb 				   B_AX_RX_DLK_CCA_TIME_MASK, 0);
2681*6d67aabdSBjoern A. Zeeb 		rtw89_write16_set(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_RCR, mac_idx),
26828e93258fSBjoern A. Zeeb 				  BIT(12));
26838e93258fSBjoern A. Zeeb 	}
26848e93258fSBjoern A. Zeeb 
2685*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PLCP_HDR_FLTR, mac_idx);
26868e93258fSBjoern A. Zeeb 	rtw89_write8_clr(rtwdev, reg, B_AX_VHT_SU_SIGB_CRC_CHK);
26878e93258fSBjoern A. Zeeb 
26888e93258fSBjoern A. Zeeb 	return ret;
26898e93258fSBjoern A. Zeeb }
26908e93258fSBjoern A. Zeeb 
2691*6d67aabdSBjoern A. Zeeb static int cmac_com_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
26928e93258fSBjoern A. Zeeb {
2693e2340276SBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
26948e93258fSBjoern A. Zeeb 	u32 val, reg;
26958e93258fSBjoern A. Zeeb 	int ret;
26968e93258fSBjoern A. Zeeb 
26978e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
26988e93258fSBjoern A. Zeeb 	if (ret)
26998e93258fSBjoern A. Zeeb 		return ret;
27008e93258fSBjoern A. Zeeb 
2701*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TX_SUB_CARRIER_VALUE, mac_idx);
27028e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, reg);
27038e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, 0, B_AX_TXSC_20M_MASK);
27048e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, 0, B_AX_TXSC_40M_MASK);
27058e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, 0, B_AX_TXSC_80M_MASK);
27068e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
27078e93258fSBjoern A. Zeeb 
2708*6d67aabdSBjoern A. Zeeb 	if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) {
2709*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PTCL_RRSR1, mac_idx);
2710e2340276SBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, reg, B_AX_RRSR_RATE_EN_MASK, RRSR_OFDM_CCK_EN);
2711e2340276SBjoern A. Zeeb 	}
2712e2340276SBjoern A. Zeeb 
27138e93258fSBjoern A. Zeeb 	return 0;
27148e93258fSBjoern A. Zeeb }
27158e93258fSBjoern A. Zeeb 
2716*6d67aabdSBjoern A. Zeeb bool rtw89_mac_is_qta_dbcc(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode)
27178e93258fSBjoern A. Zeeb {
27188e93258fSBjoern A. Zeeb 	const struct rtw89_dle_mem *cfg;
27198e93258fSBjoern A. Zeeb 
27208e93258fSBjoern A. Zeeb 	cfg = get_dle_mem_cfg(rtwdev, mode);
27218e93258fSBjoern A. Zeeb 	if (!cfg) {
27228e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]get_dle_mem_cfg\n");
27238e93258fSBjoern A. Zeeb 		return false;
27248e93258fSBjoern A. Zeeb 	}
27258e93258fSBjoern A. Zeeb 
27268e93258fSBjoern A. Zeeb 	return (cfg->ple_min_qt->cma1_dma && cfg->ple_max_qt->cma1_dma);
27278e93258fSBjoern A. Zeeb }
27288e93258fSBjoern A. Zeeb 
2729*6d67aabdSBjoern A. Zeeb static int ptcl_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
27308e93258fSBjoern A. Zeeb {
27318e93258fSBjoern A. Zeeb 	u32 val, reg;
27328e93258fSBjoern A. Zeeb 	int ret;
27338e93258fSBjoern A. Zeeb 
27348e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
27358e93258fSBjoern A. Zeeb 	if (ret)
27368e93258fSBjoern A. Zeeb 		return ret;
27378e93258fSBjoern A. Zeeb 
27388e93258fSBjoern A. Zeeb 	if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) {
2739*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_SIFS_SETTING, mac_idx);
27408e93258fSBjoern A. Zeeb 		val = rtw89_read32(rtwdev, reg);
27418e93258fSBjoern A. Zeeb 		val = u32_replace_bits(val, S_AX_CTS2S_TH_1K,
27428e93258fSBjoern A. Zeeb 				       B_AX_HW_CTS2SELF_PKT_LEN_TH_MASK);
27438e93258fSBjoern A. Zeeb 		val = u32_replace_bits(val, S_AX_CTS2S_TH_SEC_256B,
27448e93258fSBjoern A. Zeeb 				       B_AX_HW_CTS2SELF_PKT_LEN_TH_TWW_MASK);
27458e93258fSBjoern A. Zeeb 		val |= B_AX_HW_CTS2SELF_EN;
27468e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, reg, val);
27478e93258fSBjoern A. Zeeb 
2748*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PTCL_FSM_MON, mac_idx);
27498e93258fSBjoern A. Zeeb 		val = rtw89_read32(rtwdev, reg);
27508e93258fSBjoern A. Zeeb 		val = u32_replace_bits(val, S_AX_PTCL_TO_2MS, B_AX_PTCL_TX_ARB_TO_THR_MASK);
27518e93258fSBjoern A. Zeeb 		val &= ~B_AX_PTCL_TX_ARB_TO_MODE;
27528e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, reg, val);
27538e93258fSBjoern A. Zeeb 	}
27548e93258fSBjoern A. Zeeb 
27558e93258fSBjoern A. Zeeb 	if (mac_idx == RTW89_MAC_0) {
27568e93258fSBjoern A. Zeeb 		rtw89_write8_set(rtwdev, R_AX_PTCL_COMMON_SETTING_0,
27578e93258fSBjoern A. Zeeb 				 B_AX_CMAC_TX_MODE_0 | B_AX_CMAC_TX_MODE_1);
27588e93258fSBjoern A. Zeeb 		rtw89_write8_clr(rtwdev, R_AX_PTCL_COMMON_SETTING_0,
27598e93258fSBjoern A. Zeeb 				 B_AX_PTCL_TRIGGER_SS_EN_0 |
27608e93258fSBjoern A. Zeeb 				 B_AX_PTCL_TRIGGER_SS_EN_1 |
27618e93258fSBjoern A. Zeeb 				 B_AX_PTCL_TRIGGER_SS_EN_UL);
27628e93258fSBjoern A. Zeeb 		rtw89_write8_mask(rtwdev, R_AX_PTCLRPT_FULL_HDL,
27638e93258fSBjoern A. Zeeb 				  B_AX_SPE_RPT_PATH_MASK, FWD_TO_WLCPU);
27648e93258fSBjoern A. Zeeb 	} else if (mac_idx == RTW89_MAC_1) {
27658e93258fSBjoern A. Zeeb 		rtw89_write8_mask(rtwdev, R_AX_PTCLRPT_FULL_HDL_C1,
27668e93258fSBjoern A. Zeeb 				  B_AX_SPE_RPT_PATH_MASK, FWD_TO_WLCPU);
27678e93258fSBjoern A. Zeeb 	}
27688e93258fSBjoern A. Zeeb 
27698e93258fSBjoern A. Zeeb 	return 0;
27708e93258fSBjoern A. Zeeb }
27718e93258fSBjoern A. Zeeb 
2772*6d67aabdSBjoern A. Zeeb static int cmac_dma_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
2773e2340276SBjoern A. Zeeb {
2774e2340276SBjoern A. Zeeb 	u32 reg;
2775e2340276SBjoern A. Zeeb 	int ret;
2776e2340276SBjoern A. Zeeb 
2777*6d67aabdSBjoern A. Zeeb 	if (!rtw89_is_rtl885xb(rtwdev))
2778e2340276SBjoern A. Zeeb 		return 0;
2779e2340276SBjoern A. Zeeb 
2780e2340276SBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
2781e2340276SBjoern A. Zeeb 	if (ret)
2782e2340276SBjoern A. Zeeb 		return ret;
2783e2340276SBjoern A. Zeeb 
2784*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_RXDMA_CTRL_0, mac_idx);
2785e2340276SBjoern A. Zeeb 	rtw89_write8_clr(rtwdev, reg, RX_FULL_MODE);
2786e2340276SBjoern A. Zeeb 
2787e2340276SBjoern A. Zeeb 	return 0;
2788e2340276SBjoern A. Zeeb }
2789e2340276SBjoern A. Zeeb 
2790*6d67aabdSBjoern A. Zeeb static int cmac_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
27918e93258fSBjoern A. Zeeb {
27928e93258fSBjoern A. Zeeb 	int ret;
27938e93258fSBjoern A. Zeeb 
2794*6d67aabdSBjoern A. Zeeb 	ret = scheduler_init_ax(rtwdev, mac_idx);
27958e93258fSBjoern A. Zeeb 	if (ret) {
27968e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d SCH init %d\n", mac_idx, ret);
27978e93258fSBjoern A. Zeeb 		return ret;
27988e93258fSBjoern A. Zeeb 	}
27998e93258fSBjoern A. Zeeb 
2800*6d67aabdSBjoern A. Zeeb 	ret = addr_cam_init_ax(rtwdev, mac_idx);
28018e93258fSBjoern A. Zeeb 	if (ret) {
28028e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d ADDR_CAM reset %d\n", mac_idx,
28038e93258fSBjoern A. Zeeb 			  ret);
28048e93258fSBjoern A. Zeeb 		return ret;
28058e93258fSBjoern A. Zeeb 	}
28068e93258fSBjoern A. Zeeb 
2807*6d67aabdSBjoern A. Zeeb 	ret = rx_fltr_init_ax(rtwdev, mac_idx);
28088e93258fSBjoern A. Zeeb 	if (ret) {
28098e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d RX filter init %d\n", mac_idx,
28108e93258fSBjoern A. Zeeb 			  ret);
28118e93258fSBjoern A. Zeeb 		return ret;
28128e93258fSBjoern A. Zeeb 	}
28138e93258fSBjoern A. Zeeb 
2814*6d67aabdSBjoern A. Zeeb 	ret = cca_ctrl_init_ax(rtwdev, mac_idx);
28158e93258fSBjoern A. Zeeb 	if (ret) {
28168e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d CCA CTRL init %d\n", mac_idx,
28178e93258fSBjoern A. Zeeb 			  ret);
28188e93258fSBjoern A. Zeeb 		return ret;
28198e93258fSBjoern A. Zeeb 	}
28208e93258fSBjoern A. Zeeb 
2821*6d67aabdSBjoern A. Zeeb 	ret = nav_ctrl_init_ax(rtwdev);
28228e93258fSBjoern A. Zeeb 	if (ret) {
28238e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d NAV CTRL init %d\n", mac_idx,
28248e93258fSBjoern A. Zeeb 			  ret);
28258e93258fSBjoern A. Zeeb 		return ret;
28268e93258fSBjoern A. Zeeb 	}
28278e93258fSBjoern A. Zeeb 
2828*6d67aabdSBjoern A. Zeeb 	ret = spatial_reuse_init_ax(rtwdev, mac_idx);
28298e93258fSBjoern A. Zeeb 	if (ret) {
28308e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d Spatial Reuse init %d\n",
28318e93258fSBjoern A. Zeeb 			  mac_idx, ret);
28328e93258fSBjoern A. Zeeb 		return ret;
28338e93258fSBjoern A. Zeeb 	}
28348e93258fSBjoern A. Zeeb 
2835*6d67aabdSBjoern A. Zeeb 	ret = tmac_init_ax(rtwdev, mac_idx);
28368e93258fSBjoern A. Zeeb 	if (ret) {
28378e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d TMAC init %d\n", mac_idx, ret);
28388e93258fSBjoern A. Zeeb 		return ret;
28398e93258fSBjoern A. Zeeb 	}
28408e93258fSBjoern A. Zeeb 
2841*6d67aabdSBjoern A. Zeeb 	ret = trxptcl_init_ax(rtwdev, mac_idx);
28428e93258fSBjoern A. Zeeb 	if (ret) {
28438e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d TRXPTCL init %d\n", mac_idx, ret);
28448e93258fSBjoern A. Zeeb 		return ret;
28458e93258fSBjoern A. Zeeb 	}
28468e93258fSBjoern A. Zeeb 
2847*6d67aabdSBjoern A. Zeeb 	ret = rmac_init_ax(rtwdev, mac_idx);
28488e93258fSBjoern A. Zeeb 	if (ret) {
28498e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d RMAC init %d\n", mac_idx, ret);
28508e93258fSBjoern A. Zeeb 		return ret;
28518e93258fSBjoern A. Zeeb 	}
28528e93258fSBjoern A. Zeeb 
2853*6d67aabdSBjoern A. Zeeb 	ret = cmac_com_init_ax(rtwdev, mac_idx);
28548e93258fSBjoern A. Zeeb 	if (ret) {
28558e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d Com init %d\n", mac_idx, ret);
28568e93258fSBjoern A. Zeeb 		return ret;
28578e93258fSBjoern A. Zeeb 	}
28588e93258fSBjoern A. Zeeb 
2859*6d67aabdSBjoern A. Zeeb 	ret = ptcl_init_ax(rtwdev, mac_idx);
28608e93258fSBjoern A. Zeeb 	if (ret) {
28618e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d PTCL init %d\n", mac_idx, ret);
28628e93258fSBjoern A. Zeeb 		return ret;
28638e93258fSBjoern A. Zeeb 	}
28648e93258fSBjoern A. Zeeb 
2865*6d67aabdSBjoern A. Zeeb 	ret = cmac_dma_init_ax(rtwdev, mac_idx);
2866e2340276SBjoern A. Zeeb 	if (ret) {
2867e2340276SBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d DMA init %d\n", mac_idx, ret);
2868e2340276SBjoern A. Zeeb 		return ret;
2869e2340276SBjoern A. Zeeb 	}
2870e2340276SBjoern A. Zeeb 
28718e93258fSBjoern A. Zeeb 	return ret;
28728e93258fSBjoern A. Zeeb }
28738e93258fSBjoern A. Zeeb 
28748e93258fSBjoern A. Zeeb static int rtw89_mac_read_phycap(struct rtw89_dev *rtwdev,
28758e93258fSBjoern A. Zeeb 				 struct rtw89_mac_c2h_info *c2h_info)
28768e93258fSBjoern A. Zeeb {
2877*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
28788e93258fSBjoern A. Zeeb 	struct rtw89_mac_h2c_info h2c_info = {0};
28798e93258fSBjoern A. Zeeb 	u32 ret;
28808e93258fSBjoern A. Zeeb 
2881*6d67aabdSBjoern A. Zeeb 	mac->cnv_efuse_state(rtwdev, false);
2882*6d67aabdSBjoern A. Zeeb 
28838e93258fSBjoern A. Zeeb 	h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_GET_FEATURE;
28848e93258fSBjoern A. Zeeb 	h2c_info.content_len = 0;
28858e93258fSBjoern A. Zeeb 
28868e93258fSBjoern A. Zeeb 	ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, c2h_info);
28878e93258fSBjoern A. Zeeb 	if (ret)
2888*6d67aabdSBjoern A. Zeeb 		goto out;
28898e93258fSBjoern A. Zeeb 
28908e93258fSBjoern A. Zeeb 	if (c2h_info->id != RTW89_FWCMD_C2HREG_FUNC_PHY_CAP)
2891*6d67aabdSBjoern A. Zeeb 		ret = -EINVAL;
28928e93258fSBjoern A. Zeeb 
2893*6d67aabdSBjoern A. Zeeb out:
2894*6d67aabdSBjoern A. Zeeb 	mac->cnv_efuse_state(rtwdev, true);
2895*6d67aabdSBjoern A. Zeeb 
2896*6d67aabdSBjoern A. Zeeb 	return ret;
28978e93258fSBjoern A. Zeeb }
28988e93258fSBjoern A. Zeeb 
28998e93258fSBjoern A. Zeeb int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev)
29008e93258fSBjoern A. Zeeb {
2901e2340276SBjoern A. Zeeb 	struct rtw89_efuse *efuse = &rtwdev->efuse;
29028e93258fSBjoern A. Zeeb 	struct rtw89_hal *hal = &rtwdev->hal;
29038e93258fSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
29048e93258fSBjoern A. Zeeb 	struct rtw89_mac_c2h_info c2h_info = {0};
2905e2340276SBjoern A. Zeeb 	const struct rtw89_c2hreg_phycap *phycap;
2906e2340276SBjoern A. Zeeb 	u8 tx_nss;
2907e2340276SBjoern A. Zeeb 	u8 rx_nss;
2908e2340276SBjoern A. Zeeb 	u8 tx_ant;
2909e2340276SBjoern A. Zeeb 	u8 rx_ant;
29108e93258fSBjoern A. Zeeb 	u32 ret;
29118e93258fSBjoern A. Zeeb 
29128e93258fSBjoern A. Zeeb 	ret = rtw89_mac_read_phycap(rtwdev, &c2h_info);
29138e93258fSBjoern A. Zeeb 	if (ret)
29148e93258fSBjoern A. Zeeb 		return ret;
29158e93258fSBjoern A. Zeeb 
2916e2340276SBjoern A. Zeeb 	phycap = &c2h_info.u.phycap;
2917e2340276SBjoern A. Zeeb 
2918e2340276SBjoern A. Zeeb 	tx_nss = u32_get_bits(phycap->w1, RTW89_C2HREG_PHYCAP_W1_TX_NSS);
2919e2340276SBjoern A. Zeeb 	rx_nss = u32_get_bits(phycap->w0, RTW89_C2HREG_PHYCAP_W0_RX_NSS);
2920e2340276SBjoern A. Zeeb 	tx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM);
2921e2340276SBjoern A. Zeeb 	rx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM);
2922e2340276SBjoern A. Zeeb 
2923e2340276SBjoern A. Zeeb 	hal->tx_nss = tx_nss ? min_t(u8, tx_nss, chip->tx_nss) : chip->tx_nss;
2924e2340276SBjoern A. Zeeb 	hal->rx_nss = rx_nss ? min_t(u8, rx_nss, chip->rx_nss) : chip->rx_nss;
2925e2340276SBjoern A. Zeeb 
2926e2340276SBjoern A. Zeeb 	if (tx_ant == 1)
2927e2340276SBjoern A. Zeeb 		hal->antenna_tx = RF_B;
2928e2340276SBjoern A. Zeeb 	if (rx_ant == 1)
2929e2340276SBjoern A. Zeeb 		hal->antenna_rx = RF_B;
2930e2340276SBjoern A. Zeeb 
2931e2340276SBjoern A. Zeeb 	if (tx_nss == 1 && tx_ant == 2 && rx_ant == 2) {
2932e2340276SBjoern A. Zeeb 		hal->antenna_tx = RF_B;
2933e2340276SBjoern A. Zeeb 		hal->tx_path_diversity = true;
2934e2340276SBjoern A. Zeeb 	}
2935e2340276SBjoern A. Zeeb 
2936e2340276SBjoern A. Zeeb 	if (chip->rf_path_num == 1) {
2937e2340276SBjoern A. Zeeb 		hal->antenna_tx = RF_A;
2938e2340276SBjoern A. Zeeb 		hal->antenna_rx = RF_A;
2939e2340276SBjoern A. Zeeb 		if ((efuse->rfe_type % 3) == 2)
2940e2340276SBjoern A. Zeeb 			hal->ant_diversity = true;
2941e2340276SBjoern A. Zeeb 	}
29428e93258fSBjoern A. Zeeb 
29438e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_FW,
29448e93258fSBjoern A. Zeeb 		    "phycap hal/phy/chip: tx_nss=0x%x/0x%x/0x%x rx_nss=0x%x/0x%x/0x%x\n",
2945e2340276SBjoern A. Zeeb 		    hal->tx_nss, tx_nss, chip->tx_nss,
2946e2340276SBjoern A. Zeeb 		    hal->rx_nss, rx_nss, chip->rx_nss);
2947e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_FW,
2948e2340276SBjoern A. Zeeb 		    "ant num/bitmap: tx=%d/0x%x rx=%d/0x%x\n",
2949e2340276SBjoern A. Zeeb 		    tx_ant, hal->antenna_tx, rx_ant, hal->antenna_rx);
2950e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_FW, "TX path diversity=%d\n", hal->tx_path_diversity);
2951e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_FW, "Antenna diversity=%d\n", hal->ant_diversity);
29528e93258fSBjoern A. Zeeb 
29538e93258fSBjoern A. Zeeb 	return 0;
29548e93258fSBjoern A. Zeeb }
29558e93258fSBjoern A. Zeeb 
29568e93258fSBjoern A. Zeeb static int rtw89_hw_sch_tx_en_h2c(struct rtw89_dev *rtwdev, u8 band,
29578e93258fSBjoern A. Zeeb 				  u16 tx_en_u16, u16 mask_u16)
29588e93258fSBjoern A. Zeeb {
29598e93258fSBjoern A. Zeeb 	u32 ret;
29608e93258fSBjoern A. Zeeb 	struct rtw89_mac_c2h_info c2h_info = {0};
29618e93258fSBjoern A. Zeeb 	struct rtw89_mac_h2c_info h2c_info = {0};
2962e2340276SBjoern A. Zeeb 	struct rtw89_h2creg_sch_tx_en *sch_tx_en = &h2c_info.u.sch_tx_en;
29638e93258fSBjoern A. Zeeb 
29648e93258fSBjoern A. Zeeb 	h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_SCH_TX_EN;
2965e2340276SBjoern A. Zeeb 	h2c_info.content_len = sizeof(*sch_tx_en) - RTW89_H2CREG_HDR_LEN;
2966e2340276SBjoern A. Zeeb 
2967e2340276SBjoern A. Zeeb 	u32p_replace_bits(&sch_tx_en->w0, tx_en_u16, RTW89_H2CREG_SCH_TX_EN_W0_EN);
2968e2340276SBjoern A. Zeeb 	u32p_replace_bits(&sch_tx_en->w1, mask_u16, RTW89_H2CREG_SCH_TX_EN_W1_MASK);
2969e2340276SBjoern A. Zeeb 	u32p_replace_bits(&sch_tx_en->w1, band, RTW89_H2CREG_SCH_TX_EN_W1_BAND);
29708e93258fSBjoern A. Zeeb 
29718e93258fSBjoern A. Zeeb 	ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info);
29728e93258fSBjoern A. Zeeb 	if (ret)
29738e93258fSBjoern A. Zeeb 		return ret;
29748e93258fSBjoern A. Zeeb 
29758e93258fSBjoern A. Zeeb 	if (c2h_info.id != RTW89_FWCMD_C2HREG_FUNC_TX_PAUSE_RPT)
29768e93258fSBjoern A. Zeeb 		return -EINVAL;
29778e93258fSBjoern A. Zeeb 
29788e93258fSBjoern A. Zeeb 	return 0;
29798e93258fSBjoern A. Zeeb }
29808e93258fSBjoern A. Zeeb 
29818e93258fSBjoern A. Zeeb static int rtw89_set_hw_sch_tx_en(struct rtw89_dev *rtwdev, u8 mac_idx,
29828e93258fSBjoern A. Zeeb 				  u16 tx_en, u16 tx_en_mask)
29838e93258fSBjoern A. Zeeb {
2984*6d67aabdSBjoern A. Zeeb 	u32 reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CTN_TXEN, mac_idx);
29858e93258fSBjoern A. Zeeb 	u16 val;
29868e93258fSBjoern A. Zeeb 	int ret;
29878e93258fSBjoern A. Zeeb 
29888e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
29898e93258fSBjoern A. Zeeb 	if (ret)
29908e93258fSBjoern A. Zeeb 		return ret;
29918e93258fSBjoern A. Zeeb 
29928e93258fSBjoern A. Zeeb 	if (test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
29938e93258fSBjoern A. Zeeb 		return rtw89_hw_sch_tx_en_h2c(rtwdev, mac_idx,
29948e93258fSBjoern A. Zeeb 					      tx_en, tx_en_mask);
29958e93258fSBjoern A. Zeeb 
29968e93258fSBjoern A. Zeeb 	val = rtw89_read16(rtwdev, reg);
29978e93258fSBjoern A. Zeeb 	val = (val & ~tx_en_mask) | (tx_en & tx_en_mask);
29988e93258fSBjoern A. Zeeb 	rtw89_write16(rtwdev, reg, val);
29998e93258fSBjoern A. Zeeb 
30008e93258fSBjoern A. Zeeb 	return 0;
30018e93258fSBjoern A. Zeeb }
30028e93258fSBjoern A. Zeeb 
30038e93258fSBjoern A. Zeeb static int rtw89_set_hw_sch_tx_en_v1(struct rtw89_dev *rtwdev, u8 mac_idx,
30048e93258fSBjoern A. Zeeb 				     u32 tx_en, u32 tx_en_mask)
30058e93258fSBjoern A. Zeeb {
3006*6d67aabdSBjoern A. Zeeb 	u32 reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CTN_DRV_TXEN, mac_idx);
30078e93258fSBjoern A. Zeeb 	u32 val;
30088e93258fSBjoern A. Zeeb 	int ret;
30098e93258fSBjoern A. Zeeb 
30108e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
30118e93258fSBjoern A. Zeeb 	if (ret)
30128e93258fSBjoern A. Zeeb 		return ret;
30138e93258fSBjoern A. Zeeb 
30148e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, reg);
30158e93258fSBjoern A. Zeeb 	val = (val & ~tx_en_mask) | (tx_en & tx_en_mask);
30168e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
30178e93258fSBjoern A. Zeeb 
30188e93258fSBjoern A. Zeeb 	return 0;
30198e93258fSBjoern A. Zeeb }
30208e93258fSBjoern A. Zeeb 
30218e93258fSBjoern A. Zeeb int rtw89_mac_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx,
30228e93258fSBjoern A. Zeeb 			  u32 *tx_en, enum rtw89_sch_tx_sel sel)
30238e93258fSBjoern A. Zeeb {
30248e93258fSBjoern A. Zeeb 	int ret;
30258e93258fSBjoern A. Zeeb 
30268e93258fSBjoern A. Zeeb 	*tx_en = rtw89_read16(rtwdev,
3027*6d67aabdSBjoern A. Zeeb 			      rtw89_mac_reg_by_idx(rtwdev, R_AX_CTN_TXEN, mac_idx));
30288e93258fSBjoern A. Zeeb 
30298e93258fSBjoern A. Zeeb 	switch (sel) {
30308e93258fSBjoern A. Zeeb 	case RTW89_SCH_TX_SEL_ALL:
30318e93258fSBjoern A. Zeeb 		ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx, 0,
30328e93258fSBjoern A. Zeeb 					     B_AX_CTN_TXEN_ALL_MASK);
30338e93258fSBjoern A. Zeeb 		if (ret)
30348e93258fSBjoern A. Zeeb 			return ret;
30358e93258fSBjoern A. Zeeb 		break;
30368e93258fSBjoern A. Zeeb 	case RTW89_SCH_TX_SEL_HIQ:
30378e93258fSBjoern A. Zeeb 		ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx,
30388e93258fSBjoern A. Zeeb 					     0, B_AX_CTN_TXEN_HGQ);
30398e93258fSBjoern A. Zeeb 		if (ret)
30408e93258fSBjoern A. Zeeb 			return ret;
30418e93258fSBjoern A. Zeeb 		break;
30428e93258fSBjoern A. Zeeb 	case RTW89_SCH_TX_SEL_MG0:
30438e93258fSBjoern A. Zeeb 		ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx,
30448e93258fSBjoern A. Zeeb 					     0, B_AX_CTN_TXEN_MGQ);
30458e93258fSBjoern A. Zeeb 		if (ret)
30468e93258fSBjoern A. Zeeb 			return ret;
30478e93258fSBjoern A. Zeeb 		break;
30488e93258fSBjoern A. Zeeb 	case RTW89_SCH_TX_SEL_MACID:
30498e93258fSBjoern A. Zeeb 		ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx, 0,
30508e93258fSBjoern A. Zeeb 					     B_AX_CTN_TXEN_ALL_MASK);
30518e93258fSBjoern A. Zeeb 		if (ret)
30528e93258fSBjoern A. Zeeb 			return ret;
30538e93258fSBjoern A. Zeeb 		break;
30548e93258fSBjoern A. Zeeb 	default:
30558e93258fSBjoern A. Zeeb 		return 0;
30568e93258fSBjoern A. Zeeb 	}
30578e93258fSBjoern A. Zeeb 
30588e93258fSBjoern A. Zeeb 	return 0;
30598e93258fSBjoern A. Zeeb }
30608e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_stop_sch_tx);
30618e93258fSBjoern A. Zeeb 
30628e93258fSBjoern A. Zeeb int rtw89_mac_stop_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx,
30638e93258fSBjoern A. Zeeb 			     u32 *tx_en, enum rtw89_sch_tx_sel sel)
30648e93258fSBjoern A. Zeeb {
30658e93258fSBjoern A. Zeeb 	int ret;
30668e93258fSBjoern A. Zeeb 
30678e93258fSBjoern A. Zeeb 	*tx_en = rtw89_read32(rtwdev,
3068*6d67aabdSBjoern A. Zeeb 			      rtw89_mac_reg_by_idx(rtwdev, R_AX_CTN_DRV_TXEN, mac_idx));
30698e93258fSBjoern A. Zeeb 
30708e93258fSBjoern A. Zeeb 	switch (sel) {
30718e93258fSBjoern A. Zeeb 	case RTW89_SCH_TX_SEL_ALL:
30728e93258fSBjoern A. Zeeb 		ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx, 0,
30738e93258fSBjoern A. Zeeb 						B_AX_CTN_TXEN_ALL_MASK_V1);
30748e93258fSBjoern A. Zeeb 		if (ret)
30758e93258fSBjoern A. Zeeb 			return ret;
30768e93258fSBjoern A. Zeeb 		break;
30778e93258fSBjoern A. Zeeb 	case RTW89_SCH_TX_SEL_HIQ:
30788e93258fSBjoern A. Zeeb 		ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx,
30798e93258fSBjoern A. Zeeb 						0, B_AX_CTN_TXEN_HGQ);
30808e93258fSBjoern A. Zeeb 		if (ret)
30818e93258fSBjoern A. Zeeb 			return ret;
30828e93258fSBjoern A. Zeeb 		break;
30838e93258fSBjoern A. Zeeb 	case RTW89_SCH_TX_SEL_MG0:
30848e93258fSBjoern A. Zeeb 		ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx,
30858e93258fSBjoern A. Zeeb 						0, B_AX_CTN_TXEN_MGQ);
30868e93258fSBjoern A. Zeeb 		if (ret)
30878e93258fSBjoern A. Zeeb 			return ret;
30888e93258fSBjoern A. Zeeb 		break;
30898e93258fSBjoern A. Zeeb 	case RTW89_SCH_TX_SEL_MACID:
30908e93258fSBjoern A. Zeeb 		ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx, 0,
30918e93258fSBjoern A. Zeeb 						B_AX_CTN_TXEN_ALL_MASK_V1);
30928e93258fSBjoern A. Zeeb 		if (ret)
30938e93258fSBjoern A. Zeeb 			return ret;
30948e93258fSBjoern A. Zeeb 		break;
30958e93258fSBjoern A. Zeeb 	default:
30968e93258fSBjoern A. Zeeb 		return 0;
30978e93258fSBjoern A. Zeeb 	}
30988e93258fSBjoern A. Zeeb 
30998e93258fSBjoern A. Zeeb 	return 0;
31008e93258fSBjoern A. Zeeb }
31018e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_stop_sch_tx_v1);
31028e93258fSBjoern A. Zeeb 
31038e93258fSBjoern A. Zeeb int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en)
31048e93258fSBjoern A. Zeeb {
31058e93258fSBjoern A. Zeeb 	int ret;
31068e93258fSBjoern A. Zeeb 
31078e93258fSBjoern A. Zeeb 	ret = rtw89_set_hw_sch_tx_en(rtwdev, mac_idx, tx_en, B_AX_CTN_TXEN_ALL_MASK);
31088e93258fSBjoern A. Zeeb 	if (ret)
31098e93258fSBjoern A. Zeeb 		return ret;
31108e93258fSBjoern A. Zeeb 
31118e93258fSBjoern A. Zeeb 	return 0;
31128e93258fSBjoern A. Zeeb }
31138e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_resume_sch_tx);
31148e93258fSBjoern A. Zeeb 
31158e93258fSBjoern A. Zeeb int rtw89_mac_resume_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en)
31168e93258fSBjoern A. Zeeb {
31178e93258fSBjoern A. Zeeb 	int ret;
31188e93258fSBjoern A. Zeeb 
31198e93258fSBjoern A. Zeeb 	ret = rtw89_set_hw_sch_tx_en_v1(rtwdev, mac_idx, tx_en,
31208e93258fSBjoern A. Zeeb 					B_AX_CTN_TXEN_ALL_MASK_V1);
31218e93258fSBjoern A. Zeeb 	if (ret)
31228e93258fSBjoern A. Zeeb 		return ret;
31238e93258fSBjoern A. Zeeb 
31248e93258fSBjoern A. Zeeb 	return 0;
31258e93258fSBjoern A. Zeeb }
31268e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_resume_sch_tx_v1);
31278e93258fSBjoern A. Zeeb 
3128*6d67aabdSBjoern A. Zeeb static int dle_buf_req_ax(struct rtw89_dev *rtwdev, u16 buf_len, bool wd, u16 *pkt_id)
31298e93258fSBjoern A. Zeeb {
31308e93258fSBjoern A. Zeeb 	u32 val, reg;
31318e93258fSBjoern A. Zeeb 	int ret;
31328e93258fSBjoern A. Zeeb 
31338e93258fSBjoern A. Zeeb 	reg = wd ? R_AX_WD_BUF_REQ : R_AX_PL_BUF_REQ;
31348e93258fSBjoern A. Zeeb 	val = buf_len;
31358e93258fSBjoern A. Zeeb 	val |= B_AX_WD_BUF_REQ_EXEC;
31368e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
31378e93258fSBjoern A. Zeeb 
31388e93258fSBjoern A. Zeeb 	reg = wd ? R_AX_WD_BUF_STATUS : R_AX_PL_BUF_STATUS;
31398e93258fSBjoern A. Zeeb 
31408e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read32, val, val & B_AX_WD_BUF_STAT_DONE,
31418e93258fSBjoern A. Zeeb 				1, 2000, false, rtwdev, reg);
31428e93258fSBjoern A. Zeeb 	if (ret)
3143e2340276SBjoern A. Zeeb 		return ret;
31448e93258fSBjoern A. Zeeb 
3145e2340276SBjoern A. Zeeb 	*pkt_id = FIELD_GET(B_AX_WD_BUF_STAT_PKTID_MASK, val);
3146e2340276SBjoern A. Zeeb 	if (*pkt_id == S_WD_BUF_STAT_PKTID_INVALID)
3147e2340276SBjoern A. Zeeb 		return -ENOENT;
3148e2340276SBjoern A. Zeeb 
3149e2340276SBjoern A. Zeeb 	return 0;
31508e93258fSBjoern A. Zeeb }
31518e93258fSBjoern A. Zeeb 
3152*6d67aabdSBjoern A. Zeeb static int set_cpuio_ax(struct rtw89_dev *rtwdev,
3153e2340276SBjoern A. Zeeb 			struct rtw89_cpuio_ctrl *ctrl_para, bool wd)
31548e93258fSBjoern A. Zeeb {
31558e93258fSBjoern A. Zeeb 	u32 val, cmd_type, reg;
31568e93258fSBjoern A. Zeeb 	int ret;
31578e93258fSBjoern A. Zeeb 
31588e93258fSBjoern A. Zeeb 	cmd_type = ctrl_para->cmd_type;
31598e93258fSBjoern A. Zeeb 
31608e93258fSBjoern A. Zeeb 	reg = wd ? R_AX_WD_CPUQ_OP_2 : R_AX_PL_CPUQ_OP_2;
31618e93258fSBjoern A. Zeeb 	val = 0;
31628e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, ctrl_para->start_pktid,
31638e93258fSBjoern A. Zeeb 			       B_AX_WD_CPUQ_OP_STRT_PKTID_MASK);
31648e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, ctrl_para->end_pktid,
31658e93258fSBjoern A. Zeeb 			       B_AX_WD_CPUQ_OP_END_PKTID_MASK);
31668e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
31678e93258fSBjoern A. Zeeb 
31688e93258fSBjoern A. Zeeb 	reg = wd ? R_AX_WD_CPUQ_OP_1 : R_AX_PL_CPUQ_OP_1;
31698e93258fSBjoern A. Zeeb 	val = 0;
31708e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, ctrl_para->src_pid,
31718e93258fSBjoern A. Zeeb 			       B_AX_CPUQ_OP_SRC_PID_MASK);
31728e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, ctrl_para->src_qid,
31738e93258fSBjoern A. Zeeb 			       B_AX_CPUQ_OP_SRC_QID_MASK);
31748e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, ctrl_para->dst_pid,
31758e93258fSBjoern A. Zeeb 			       B_AX_CPUQ_OP_DST_PID_MASK);
31768e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, ctrl_para->dst_qid,
31778e93258fSBjoern A. Zeeb 			       B_AX_CPUQ_OP_DST_QID_MASK);
31788e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
31798e93258fSBjoern A. Zeeb 
31808e93258fSBjoern A. Zeeb 	reg = wd ? R_AX_WD_CPUQ_OP_0 : R_AX_PL_CPUQ_OP_0;
31818e93258fSBjoern A. Zeeb 	val = 0;
31828e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, cmd_type,
31838e93258fSBjoern A. Zeeb 			       B_AX_CPUQ_OP_CMD_TYPE_MASK);
31848e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, ctrl_para->macid,
31858e93258fSBjoern A. Zeeb 			       B_AX_CPUQ_OP_MACID_MASK);
31868e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, ctrl_para->pkt_num,
31878e93258fSBjoern A. Zeeb 			       B_AX_CPUQ_OP_PKTNUM_MASK);
31888e93258fSBjoern A. Zeeb 	val |= B_AX_WD_CPUQ_OP_EXEC;
31898e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
31908e93258fSBjoern A. Zeeb 
31918e93258fSBjoern A. Zeeb 	reg = wd ? R_AX_WD_CPUQ_OP_STATUS : R_AX_PL_CPUQ_OP_STATUS;
31928e93258fSBjoern A. Zeeb 
31938e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read32, val, val & B_AX_WD_CPUQ_OP_STAT_DONE,
31948e93258fSBjoern A. Zeeb 				1, 2000, false, rtwdev, reg);
31958e93258fSBjoern A. Zeeb 	if (ret)
31968e93258fSBjoern A. Zeeb 		return ret;
31978e93258fSBjoern A. Zeeb 
31988e93258fSBjoern A. Zeeb 	if (cmd_type == CPUIO_OP_CMD_GET_1ST_PID ||
31998e93258fSBjoern A. Zeeb 	    cmd_type == CPUIO_OP_CMD_GET_NEXT_PID)
32008e93258fSBjoern A. Zeeb 		ctrl_para->pktid = FIELD_GET(B_AX_WD_CPUQ_OP_PKTID_MASK, val);
32018e93258fSBjoern A. Zeeb 
32028e93258fSBjoern A. Zeeb 	return 0;
32038e93258fSBjoern A. Zeeb }
32048e93258fSBjoern A. Zeeb 
3205*6d67aabdSBjoern A. Zeeb int rtw89_mac_dle_quota_change(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode,
3206*6d67aabdSBjoern A. Zeeb 			       bool band1_en)
32078e93258fSBjoern A. Zeeb {
3208*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
32098e93258fSBjoern A. Zeeb 	const struct rtw89_dle_mem *cfg;
32108e93258fSBjoern A. Zeeb 
32118e93258fSBjoern A. Zeeb 	cfg = get_dle_mem_cfg(rtwdev, mode);
32128e93258fSBjoern A. Zeeb 	if (!cfg) {
32138e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]wd/dle mem cfg\n");
32148e93258fSBjoern A. Zeeb 		return -EINVAL;
32158e93258fSBjoern A. Zeeb 	}
32168e93258fSBjoern A. Zeeb 
3217*6d67aabdSBjoern A. Zeeb 	if (dle_used_size(cfg) != dle_expected_used_size(rtwdev, mode)) {
32188e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]wd/dle mem cfg\n");
32198e93258fSBjoern A. Zeeb 		return -EINVAL;
32208e93258fSBjoern A. Zeeb 	}
32218e93258fSBjoern A. Zeeb 
32228e93258fSBjoern A. Zeeb 	dle_quota_cfg(rtwdev, cfg, INVALID_QT_WCPU);
32238e93258fSBjoern A. Zeeb 
3224*6d67aabdSBjoern A. Zeeb 	return mac->dle_quota_change(rtwdev, band1_en);
3225*6d67aabdSBjoern A. Zeeb }
3226*6d67aabdSBjoern A. Zeeb 
3227*6d67aabdSBjoern A. Zeeb static int dle_quota_change_ax(struct rtw89_dev *rtwdev, bool band1_en)
3228*6d67aabdSBjoern A. Zeeb {
3229*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
3230*6d67aabdSBjoern A. Zeeb 	struct rtw89_cpuio_ctrl ctrl_para = {0};
3231*6d67aabdSBjoern A. Zeeb 	u16 pkt_id;
3232*6d67aabdSBjoern A. Zeeb 	int ret;
3233*6d67aabdSBjoern A. Zeeb 
3234*6d67aabdSBjoern A. Zeeb 	ret = mac->dle_buf_req(rtwdev, 0x20, true, &pkt_id);
3235e2340276SBjoern A. Zeeb 	if (ret) {
32368e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]WDE DLE buf req\n");
3237e2340276SBjoern A. Zeeb 		return ret;
32388e93258fSBjoern A. Zeeb 	}
32398e93258fSBjoern A. Zeeb 
32408e93258fSBjoern A. Zeeb 	ctrl_para.cmd_type = CPUIO_OP_CMD_ENQ_TO_HEAD;
32418e93258fSBjoern A. Zeeb 	ctrl_para.start_pktid = pkt_id;
32428e93258fSBjoern A. Zeeb 	ctrl_para.end_pktid = pkt_id;
32438e93258fSBjoern A. Zeeb 	ctrl_para.pkt_num = 0;
32448e93258fSBjoern A. Zeeb 	ctrl_para.dst_pid = WDE_DLE_PORT_ID_WDRLS;
32458e93258fSBjoern A. Zeeb 	ctrl_para.dst_qid = WDE_DLE_QUEID_NO_REPORT;
3246*6d67aabdSBjoern A. Zeeb 	ret = mac->set_cpuio(rtwdev, &ctrl_para, true);
32478e93258fSBjoern A. Zeeb 	if (ret) {
32488e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]WDE DLE enqueue to head\n");
32498e93258fSBjoern A. Zeeb 		return -EFAULT;
32508e93258fSBjoern A. Zeeb 	}
32518e93258fSBjoern A. Zeeb 
3252*6d67aabdSBjoern A. Zeeb 	ret = mac->dle_buf_req(rtwdev, 0x20, false, &pkt_id);
3253e2340276SBjoern A. Zeeb 	if (ret) {
32548e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]PLE DLE buf req\n");
3255e2340276SBjoern A. Zeeb 		return ret;
32568e93258fSBjoern A. Zeeb 	}
32578e93258fSBjoern A. Zeeb 
32588e93258fSBjoern A. Zeeb 	ctrl_para.cmd_type = CPUIO_OP_CMD_ENQ_TO_HEAD;
32598e93258fSBjoern A. Zeeb 	ctrl_para.start_pktid = pkt_id;
32608e93258fSBjoern A. Zeeb 	ctrl_para.end_pktid = pkt_id;
32618e93258fSBjoern A. Zeeb 	ctrl_para.pkt_num = 0;
32628e93258fSBjoern A. Zeeb 	ctrl_para.dst_pid = PLE_DLE_PORT_ID_PLRLS;
32638e93258fSBjoern A. Zeeb 	ctrl_para.dst_qid = PLE_DLE_QUEID_NO_REPORT;
3264*6d67aabdSBjoern A. Zeeb 	ret = mac->set_cpuio(rtwdev, &ctrl_para, false);
32658e93258fSBjoern A. Zeeb 	if (ret) {
32668e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]PLE DLE enqueue to head\n");
32678e93258fSBjoern A. Zeeb 		return -EFAULT;
32688e93258fSBjoern A. Zeeb 	}
32698e93258fSBjoern A. Zeeb 
32708e93258fSBjoern A. Zeeb 	return 0;
32718e93258fSBjoern A. Zeeb }
32728e93258fSBjoern A. Zeeb 
32738e93258fSBjoern A. Zeeb static int band_idle_ck_b(struct rtw89_dev *rtwdev, u8 mac_idx)
32748e93258fSBjoern A. Zeeb {
32758e93258fSBjoern A. Zeeb 	int ret;
32768e93258fSBjoern A. Zeeb 	u32 reg;
32778e93258fSBjoern A. Zeeb 	u8 val;
32788e93258fSBjoern A. Zeeb 
32798e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
32808e93258fSBjoern A. Zeeb 	if (ret)
32818e93258fSBjoern A. Zeeb 		return ret;
32828e93258fSBjoern A. Zeeb 
3283*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PTCL_TX_CTN_SEL, mac_idx);
32848e93258fSBjoern A. Zeeb 
32858e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read8, val,
32868e93258fSBjoern A. Zeeb 				(val & B_AX_PTCL_TX_ON_STAT) == 0,
32878e93258fSBjoern A. Zeeb 				SW_CVR_DUR_US,
32888e93258fSBjoern A. Zeeb 				SW_CVR_DUR_US * PTCL_IDLE_POLL_CNT,
32898e93258fSBjoern A. Zeeb 				false, rtwdev, reg);
32908e93258fSBjoern A. Zeeb 	if (ret)
32918e93258fSBjoern A. Zeeb 		return ret;
32928e93258fSBjoern A. Zeeb 
32938e93258fSBjoern A. Zeeb 	return 0;
32948e93258fSBjoern A. Zeeb }
32958e93258fSBjoern A. Zeeb 
3296*6d67aabdSBjoern A. Zeeb static int band1_enable_ax(struct rtw89_dev *rtwdev)
32978e93258fSBjoern A. Zeeb {
32988e93258fSBjoern A. Zeeb 	int ret, i;
32998e93258fSBjoern A. Zeeb 	u32 sleep_bak[4] = {0};
33008e93258fSBjoern A. Zeeb 	u32 pause_bak[4] = {0};
33018e93258fSBjoern A. Zeeb 	u32 tx_en;
33028e93258fSBjoern A. Zeeb 
33038e93258fSBjoern A. Zeeb 	ret = rtw89_chip_stop_sch_tx(rtwdev, 0, &tx_en, RTW89_SCH_TX_SEL_ALL);
33048e93258fSBjoern A. Zeeb 	if (ret) {
33058e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]stop sch tx %d\n", ret);
33068e93258fSBjoern A. Zeeb 		return ret;
33078e93258fSBjoern A. Zeeb 	}
33088e93258fSBjoern A. Zeeb 
33098e93258fSBjoern A. Zeeb 	for (i = 0; i < 4; i++) {
33108e93258fSBjoern A. Zeeb 		sleep_bak[i] = rtw89_read32(rtwdev, R_AX_MACID_SLEEP_0 + i * 4);
33118e93258fSBjoern A. Zeeb 		pause_bak[i] = rtw89_read32(rtwdev, R_AX_SS_MACID_PAUSE_0 + i * 4);
33128e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_MACID_SLEEP_0 + i * 4, U32_MAX);
33138e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_SS_MACID_PAUSE_0 + i * 4, U32_MAX);
33148e93258fSBjoern A. Zeeb 	}
33158e93258fSBjoern A. Zeeb 
33168e93258fSBjoern A. Zeeb 	ret = band_idle_ck_b(rtwdev, 0);
33178e93258fSBjoern A. Zeeb 	if (ret) {
33188e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]tx idle poll %d\n", ret);
33198e93258fSBjoern A. Zeeb 		return ret;
33208e93258fSBjoern A. Zeeb 	}
33218e93258fSBjoern A. Zeeb 
3322*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_dle_quota_change(rtwdev, rtwdev->mac.qta_mode, true);
33238e93258fSBjoern A. Zeeb 	if (ret) {
33248e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]DLE quota change %d\n", ret);
33258e93258fSBjoern A. Zeeb 		return ret;
33268e93258fSBjoern A. Zeeb 	}
33278e93258fSBjoern A. Zeeb 
33288e93258fSBjoern A. Zeeb 	for (i = 0; i < 4; i++) {
33298e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_MACID_SLEEP_0 + i * 4, sleep_bak[i]);
33308e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_SS_MACID_PAUSE_0 + i * 4, pause_bak[i]);
33318e93258fSBjoern A. Zeeb 	}
33328e93258fSBjoern A. Zeeb 
33338e93258fSBjoern A. Zeeb 	ret = rtw89_chip_resume_sch_tx(rtwdev, 0, tx_en);
33348e93258fSBjoern A. Zeeb 	if (ret) {
33358e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC1 resume sch tx %d\n", ret);
33368e93258fSBjoern A. Zeeb 		return ret;
33378e93258fSBjoern A. Zeeb 	}
33388e93258fSBjoern A. Zeeb 
3339*6d67aabdSBjoern A. Zeeb 	ret = cmac_func_en_ax(rtwdev, 1, true);
33408e93258fSBjoern A. Zeeb 	if (ret) {
33418e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC1 func en %d\n", ret);
33428e93258fSBjoern A. Zeeb 		return ret;
33438e93258fSBjoern A. Zeeb 	}
33448e93258fSBjoern A. Zeeb 
3345*6d67aabdSBjoern A. Zeeb 	ret = cmac_init_ax(rtwdev, 1);
33468e93258fSBjoern A. Zeeb 	if (ret) {
33478e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC1 init %d\n", ret);
33488e93258fSBjoern A. Zeeb 		return ret;
33498e93258fSBjoern A. Zeeb 	}
33508e93258fSBjoern A. Zeeb 
33518e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
33528e93258fSBjoern A. Zeeb 			  B_AX_R_SYM_FEN_WLBBFUN_1 | B_AX_R_SYM_FEN_WLBBGLB_1);
33538e93258fSBjoern A. Zeeb 
33548e93258fSBjoern A. Zeeb 	return 0;
33558e93258fSBjoern A. Zeeb }
33568e93258fSBjoern A. Zeeb 
33578e93258fSBjoern A. Zeeb static void rtw89_wdrls_imr_enable(struct rtw89_dev *rtwdev)
33588e93258fSBjoern A. Zeeb {
33598e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
33608e93258fSBjoern A. Zeeb 
33618e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_WDRLS_ERR_IMR, B_AX_WDRLS_IMR_EN_CLR);
33628e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_WDRLS_ERR_IMR, imr->wdrls_imr_set);
33638e93258fSBjoern A. Zeeb }
33648e93258fSBjoern A. Zeeb 
33658e93258fSBjoern A. Zeeb static void rtw89_wsec_imr_enable(struct rtw89_dev *rtwdev)
33668e93258fSBjoern A. Zeeb {
33678e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
33688e93258fSBjoern A. Zeeb 
33698e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, imr->wsec_imr_reg, imr->wsec_imr_set);
33708e93258fSBjoern A. Zeeb }
33718e93258fSBjoern A. Zeeb 
33728e93258fSBjoern A. Zeeb static void rtw89_mpdu_trx_imr_enable(struct rtw89_dev *rtwdev)
33738e93258fSBjoern A. Zeeb {
33748e93258fSBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
33758e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
33768e93258fSBjoern A. Zeeb 
33778e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_MPDU_TX_ERR_IMR,
33788e93258fSBjoern A. Zeeb 			  B_AX_TX_GET_ERRPKTID_INT_EN |
33798e93258fSBjoern A. Zeeb 			  B_AX_TX_NXT_ERRPKTID_INT_EN |
33808e93258fSBjoern A. Zeeb 			  B_AX_TX_MPDU_SIZE_ZERO_INT_EN |
33818e93258fSBjoern A. Zeeb 			  B_AX_TX_OFFSET_ERR_INT_EN |
33828e93258fSBjoern A. Zeeb 			  B_AX_TX_HDR3_SIZE_ERR_INT_EN);
33838e93258fSBjoern A. Zeeb 	if (chip_id == RTL8852C)
33848e93258fSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, R_AX_MPDU_TX_ERR_IMR,
33858e93258fSBjoern A. Zeeb 				  B_AX_TX_ETH_TYPE_ERR_EN |
33868e93258fSBjoern A. Zeeb 				  B_AX_TX_LLC_PRE_ERR_EN |
33878e93258fSBjoern A. Zeeb 				  B_AX_TX_NW_TYPE_ERR_EN |
33888e93258fSBjoern A. Zeeb 				  B_AX_TX_KSRCH_ERR_EN);
33898e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_MPDU_TX_ERR_IMR,
33908e93258fSBjoern A. Zeeb 			  imr->mpdu_tx_imr_set);
33918e93258fSBjoern A. Zeeb 
33928e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_MPDU_RX_ERR_IMR,
33938e93258fSBjoern A. Zeeb 			  B_AX_GETPKTID_ERR_INT_EN |
33948e93258fSBjoern A. Zeeb 			  B_AX_MHDRLEN_ERR_INT_EN |
33958e93258fSBjoern A. Zeeb 			  B_AX_RPT_ERR_INT_EN);
33968e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_MPDU_RX_ERR_IMR,
33978e93258fSBjoern A. Zeeb 			  imr->mpdu_rx_imr_set);
33988e93258fSBjoern A. Zeeb }
33998e93258fSBjoern A. Zeeb 
34008e93258fSBjoern A. Zeeb static void rtw89_sta_sch_imr_enable(struct rtw89_dev *rtwdev)
34018e93258fSBjoern A. Zeeb {
34028e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
34038e93258fSBjoern A. Zeeb 
34048e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_STA_SCHEDULER_ERR_IMR,
34058e93258fSBjoern A. Zeeb 			  B_AX_SEARCH_HANG_TIMEOUT_INT_EN |
34068e93258fSBjoern A. Zeeb 			  B_AX_RPT_HANG_TIMEOUT_INT_EN |
34078e93258fSBjoern A. Zeeb 			  B_AX_PLE_B_PKTID_ERR_INT_EN);
34088e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_STA_SCHEDULER_ERR_IMR,
34098e93258fSBjoern A. Zeeb 			  imr->sta_sch_imr_set);
34108e93258fSBjoern A. Zeeb }
34118e93258fSBjoern A. Zeeb 
34128e93258fSBjoern A. Zeeb static void rtw89_txpktctl_imr_enable(struct rtw89_dev *rtwdev)
34138e93258fSBjoern A. Zeeb {
34148e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
34158e93258fSBjoern A. Zeeb 
34168e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, imr->txpktctl_imr_b0_reg,
34178e93258fSBjoern A. Zeeb 			  imr->txpktctl_imr_b0_clr);
34188e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, imr->txpktctl_imr_b0_reg,
34198e93258fSBjoern A. Zeeb 			  imr->txpktctl_imr_b0_set);
34208e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, imr->txpktctl_imr_b1_reg,
34218e93258fSBjoern A. Zeeb 			  imr->txpktctl_imr_b1_clr);
34228e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, imr->txpktctl_imr_b1_reg,
34238e93258fSBjoern A. Zeeb 			  imr->txpktctl_imr_b1_set);
34248e93258fSBjoern A. Zeeb }
34258e93258fSBjoern A. Zeeb 
34268e93258fSBjoern A. Zeeb static void rtw89_wde_imr_enable(struct rtw89_dev *rtwdev)
34278e93258fSBjoern A. Zeeb {
34288e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
34298e93258fSBjoern A. Zeeb 
34308e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_WDE_ERR_IMR, imr->wde_imr_clr);
34318e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_WDE_ERR_IMR, imr->wde_imr_set);
34328e93258fSBjoern A. Zeeb }
34338e93258fSBjoern A. Zeeb 
34348e93258fSBjoern A. Zeeb static void rtw89_ple_imr_enable(struct rtw89_dev *rtwdev)
34358e93258fSBjoern A. Zeeb {
34368e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
34378e93258fSBjoern A. Zeeb 
34388e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_PLE_ERR_IMR, imr->ple_imr_clr);
34398e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_PLE_ERR_IMR, imr->ple_imr_set);
34408e93258fSBjoern A. Zeeb }
34418e93258fSBjoern A. Zeeb 
34428e93258fSBjoern A. Zeeb static void rtw89_pktin_imr_enable(struct rtw89_dev *rtwdev)
34438e93258fSBjoern A. Zeeb {
34448e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_PKTIN_ERR_IMR,
34458e93258fSBjoern A. Zeeb 			  B_AX_PKTIN_GETPKTID_ERR_INT_EN);
34468e93258fSBjoern A. Zeeb }
34478e93258fSBjoern A. Zeeb 
34488e93258fSBjoern A. Zeeb static void rtw89_dispatcher_imr_enable(struct rtw89_dev *rtwdev)
34498e93258fSBjoern A. Zeeb {
34508e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
34518e93258fSBjoern A. Zeeb 
34528e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR,
34538e93258fSBjoern A. Zeeb 			  imr->host_disp_imr_clr);
34548e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR,
34558e93258fSBjoern A. Zeeb 			  imr->host_disp_imr_set);
34568e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR,
34578e93258fSBjoern A. Zeeb 			  imr->cpu_disp_imr_clr);
34588e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR,
34598e93258fSBjoern A. Zeeb 			  imr->cpu_disp_imr_set);
34608e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR,
34618e93258fSBjoern A. Zeeb 			  imr->other_disp_imr_clr);
34628e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR,
34638e93258fSBjoern A. Zeeb 			  imr->other_disp_imr_set);
34648e93258fSBjoern A. Zeeb }
34658e93258fSBjoern A. Zeeb 
34668e93258fSBjoern A. Zeeb static void rtw89_cpuio_imr_enable(struct rtw89_dev *rtwdev)
34678e93258fSBjoern A. Zeeb {
34688e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_CPUIO_ERR_IMR, B_AX_CPUIO_IMR_CLR);
34698e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_CPUIO_ERR_IMR, B_AX_CPUIO_IMR_SET);
34708e93258fSBjoern A. Zeeb }
34718e93258fSBjoern A. Zeeb 
34728e93258fSBjoern A. Zeeb static void rtw89_bbrpt_imr_enable(struct rtw89_dev *rtwdev)
34738e93258fSBjoern A. Zeeb {
34748e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
34758e93258fSBjoern A. Zeeb 
3476e2340276SBjoern A. Zeeb 	rtw89_write32_set(rtwdev, imr->bbrpt_com_err_imr_reg,
34778e93258fSBjoern A. Zeeb 			  B_AX_BBRPT_COM_NULL_PLPKTID_ERR_INT_EN);
34788e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, imr->bbrpt_chinfo_err_imr_reg,
34798e93258fSBjoern A. Zeeb 			  B_AX_BBRPT_CHINFO_IMR_CLR);
34808e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, imr->bbrpt_chinfo_err_imr_reg,
34818e93258fSBjoern A. Zeeb 			  imr->bbrpt_err_imr_set);
34828e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, imr->bbrpt_dfs_err_imr_reg,
34838e93258fSBjoern A. Zeeb 			  B_AX_BBRPT_DFS_TO_ERR_INT_EN);
34848e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_LA_ERRFLAG, B_AX_LA_IMR_DATA_LOSS_ERR);
34858e93258fSBjoern A. Zeeb }
34868e93258fSBjoern A. Zeeb 
34878e93258fSBjoern A. Zeeb static void rtw89_scheduler_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx)
34888e93258fSBjoern A. Zeeb {
34898e93258fSBjoern A. Zeeb 	u32 reg;
34908e93258fSBjoern A. Zeeb 
3491*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_SCHEDULE_ERR_IMR, mac_idx);
34928e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, reg, B_AX_SORT_NON_IDLE_ERR_INT_EN |
34938e93258fSBjoern A. Zeeb 				       B_AX_FSM_TIMEOUT_ERR_INT_EN);
34948e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, B_AX_FSM_TIMEOUT_ERR_INT_EN);
34958e93258fSBjoern A. Zeeb }
34968e93258fSBjoern A. Zeeb 
34978e93258fSBjoern A. Zeeb static void rtw89_ptcl_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx)
34988e93258fSBjoern A. Zeeb {
34998e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
35008e93258fSBjoern A. Zeeb 	u32 reg;
35018e93258fSBjoern A. Zeeb 
3502*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PTCL_IMR0, mac_idx);
35038e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, reg, imr->ptcl_imr_clr);
35048e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, imr->ptcl_imr_set);
35058e93258fSBjoern A. Zeeb }
35068e93258fSBjoern A. Zeeb 
35078e93258fSBjoern A. Zeeb static void rtw89_cdma_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx)
35088e93258fSBjoern A. Zeeb {
35098e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
35108e93258fSBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
35118e93258fSBjoern A. Zeeb 	u32 reg;
35128e93258fSBjoern A. Zeeb 
3513*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, imr->cdma_imr_0_reg, mac_idx);
35148e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, reg, imr->cdma_imr_0_clr);
35158e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, imr->cdma_imr_0_set);
35168e93258fSBjoern A. Zeeb 
35178e93258fSBjoern A. Zeeb 	if (chip_id == RTL8852C) {
3518*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, imr->cdma_imr_1_reg, mac_idx);
35198e93258fSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, reg, imr->cdma_imr_1_clr);
35208e93258fSBjoern A. Zeeb 		rtw89_write32_set(rtwdev, reg, imr->cdma_imr_1_set);
35218e93258fSBjoern A. Zeeb 	}
35228e93258fSBjoern A. Zeeb }
35238e93258fSBjoern A. Zeeb 
35248e93258fSBjoern A. Zeeb static void rtw89_phy_intf_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx)
35258e93258fSBjoern A. Zeeb {
35268e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
35278e93258fSBjoern A. Zeeb 	u32 reg;
35288e93258fSBjoern A. Zeeb 
3529*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, imr->phy_intf_imr_reg, mac_idx);
35308e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, reg, imr->phy_intf_imr_clr);
35318e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, imr->phy_intf_imr_set);
35328e93258fSBjoern A. Zeeb }
35338e93258fSBjoern A. Zeeb 
35348e93258fSBjoern A. Zeeb static void rtw89_rmac_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx)
35358e93258fSBjoern A. Zeeb {
35368e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
35378e93258fSBjoern A. Zeeb 	u32 reg;
35388e93258fSBjoern A. Zeeb 
3539*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, imr->rmac_imr_reg, mac_idx);
35408e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, reg, imr->rmac_imr_clr);
35418e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, imr->rmac_imr_set);
35428e93258fSBjoern A. Zeeb }
35438e93258fSBjoern A. Zeeb 
35448e93258fSBjoern A. Zeeb static void rtw89_tmac_imr_enable(struct rtw89_dev *rtwdev, u8 mac_idx)
35458e93258fSBjoern A. Zeeb {
35468e93258fSBjoern A. Zeeb 	const struct rtw89_imr_info *imr = rtwdev->chip->imr_info;
35478e93258fSBjoern A. Zeeb 	u32 reg;
35488e93258fSBjoern A. Zeeb 
3549*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, imr->tmac_imr_reg, mac_idx);
35508e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, reg, imr->tmac_imr_clr);
35518e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, imr->tmac_imr_set);
35528e93258fSBjoern A. Zeeb }
35538e93258fSBjoern A. Zeeb 
3554*6d67aabdSBjoern A. Zeeb static int enable_imr_ax(struct rtw89_dev *rtwdev, u8 mac_idx,
35558e93258fSBjoern A. Zeeb 			 enum rtw89_mac_hwmod_sel sel)
35568e93258fSBjoern A. Zeeb {
35578e93258fSBjoern A. Zeeb 	int ret;
35588e93258fSBjoern A. Zeeb 
35598e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, sel);
35608e93258fSBjoern A. Zeeb 	if (ret) {
35618e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "MAC%d mac_idx%d is not ready\n",
35628e93258fSBjoern A. Zeeb 			  sel, mac_idx);
35638e93258fSBjoern A. Zeeb 		return ret;
35648e93258fSBjoern A. Zeeb 	}
35658e93258fSBjoern A. Zeeb 
35668e93258fSBjoern A. Zeeb 	if (sel == RTW89_DMAC_SEL) {
35678e93258fSBjoern A. Zeeb 		rtw89_wdrls_imr_enable(rtwdev);
35688e93258fSBjoern A. Zeeb 		rtw89_wsec_imr_enable(rtwdev);
35698e93258fSBjoern A. Zeeb 		rtw89_mpdu_trx_imr_enable(rtwdev);
35708e93258fSBjoern A. Zeeb 		rtw89_sta_sch_imr_enable(rtwdev);
35718e93258fSBjoern A. Zeeb 		rtw89_txpktctl_imr_enable(rtwdev);
35728e93258fSBjoern A. Zeeb 		rtw89_wde_imr_enable(rtwdev);
35738e93258fSBjoern A. Zeeb 		rtw89_ple_imr_enable(rtwdev);
35748e93258fSBjoern A. Zeeb 		rtw89_pktin_imr_enable(rtwdev);
35758e93258fSBjoern A. Zeeb 		rtw89_dispatcher_imr_enable(rtwdev);
35768e93258fSBjoern A. Zeeb 		rtw89_cpuio_imr_enable(rtwdev);
35778e93258fSBjoern A. Zeeb 		rtw89_bbrpt_imr_enable(rtwdev);
35788e93258fSBjoern A. Zeeb 	} else if (sel == RTW89_CMAC_SEL) {
35798e93258fSBjoern A. Zeeb 		rtw89_scheduler_imr_enable(rtwdev, mac_idx);
35808e93258fSBjoern A. Zeeb 		rtw89_ptcl_imr_enable(rtwdev, mac_idx);
35818e93258fSBjoern A. Zeeb 		rtw89_cdma_imr_enable(rtwdev, mac_idx);
35828e93258fSBjoern A. Zeeb 		rtw89_phy_intf_imr_enable(rtwdev, mac_idx);
35838e93258fSBjoern A. Zeeb 		rtw89_rmac_imr_enable(rtwdev, mac_idx);
35848e93258fSBjoern A. Zeeb 		rtw89_tmac_imr_enable(rtwdev, mac_idx);
35858e93258fSBjoern A. Zeeb 	} else {
35868e93258fSBjoern A. Zeeb 		return -EINVAL;
35878e93258fSBjoern A. Zeeb 	}
35888e93258fSBjoern A. Zeeb 
35898e93258fSBjoern A. Zeeb 	return 0;
35908e93258fSBjoern A. Zeeb }
35918e93258fSBjoern A. Zeeb 
3592*6d67aabdSBjoern A. Zeeb static void err_imr_ctrl_ax(struct rtw89_dev *rtwdev, bool en)
35938e93258fSBjoern A. Zeeb {
35948e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_DMAC_ERR_IMR,
35958e93258fSBjoern A. Zeeb 		      en ? DMAC_ERR_IMR_EN : DMAC_ERR_IMR_DIS);
35968e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_CMAC_ERR_IMR,
35978e93258fSBjoern A. Zeeb 		      en ? CMAC0_ERR_IMR_EN : CMAC0_ERR_IMR_DIS);
3598*6d67aabdSBjoern A. Zeeb 	if (!rtw89_is_rtl885xb(rtwdev) && rtwdev->mac.dle_info.c1_rx_qta)
35998e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_CMAC_ERR_IMR_C1,
36008e93258fSBjoern A. Zeeb 			      en ? CMAC1_ERR_IMR_EN : CMAC1_ERR_IMR_DIS);
36018e93258fSBjoern A. Zeeb }
36028e93258fSBjoern A. Zeeb 
3603*6d67aabdSBjoern A. Zeeb static int dbcc_enable_ax(struct rtw89_dev *rtwdev, bool enable)
36048e93258fSBjoern A. Zeeb {
36058e93258fSBjoern A. Zeeb 	int ret = 0;
36068e93258fSBjoern A. Zeeb 
36078e93258fSBjoern A. Zeeb 	if (enable) {
3608*6d67aabdSBjoern A. Zeeb 		ret = band1_enable_ax(rtwdev);
36098e93258fSBjoern A. Zeeb 		if (ret) {
36108e93258fSBjoern A. Zeeb 			rtw89_err(rtwdev, "[ERR] band1_enable %d\n", ret);
36118e93258fSBjoern A. Zeeb 			return ret;
36128e93258fSBjoern A. Zeeb 		}
36138e93258fSBjoern A. Zeeb 
3614*6d67aabdSBjoern A. Zeeb 		ret = enable_imr_ax(rtwdev, RTW89_MAC_1, RTW89_CMAC_SEL);
36158e93258fSBjoern A. Zeeb 		if (ret) {
36168e93258fSBjoern A. Zeeb 			rtw89_err(rtwdev, "[ERR] enable CMAC1 IMR %d\n", ret);
36178e93258fSBjoern A. Zeeb 			return ret;
36188e93258fSBjoern A. Zeeb 		}
36198e93258fSBjoern A. Zeeb 	} else {
36208e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR] disable dbcc is not implemented not\n");
36218e93258fSBjoern A. Zeeb 		return -EINVAL;
36228e93258fSBjoern A. Zeeb 	}
36238e93258fSBjoern A. Zeeb 
36248e93258fSBjoern A. Zeeb 	return 0;
36258e93258fSBjoern A. Zeeb }
36268e93258fSBjoern A. Zeeb 
3627*6d67aabdSBjoern A. Zeeb static int set_host_rpr_ax(struct rtw89_dev *rtwdev)
36288e93258fSBjoern A. Zeeb {
36298e93258fSBjoern A. Zeeb 	if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) {
36308e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, R_AX_WDRLS_CFG,
36318e93258fSBjoern A. Zeeb 				   B_AX_WDRLS_MODE_MASK, RTW89_RPR_MODE_POH);
36328e93258fSBjoern A. Zeeb 		rtw89_write32_set(rtwdev, R_AX_RLSRPT0_CFG0,
36338e93258fSBjoern A. Zeeb 				  B_AX_RLSRPT0_FLTR_MAP_MASK);
36348e93258fSBjoern A. Zeeb 	} else {
36358e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, R_AX_WDRLS_CFG,
36368e93258fSBjoern A. Zeeb 				   B_AX_WDRLS_MODE_MASK, RTW89_RPR_MODE_STF);
36378e93258fSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, R_AX_RLSRPT0_CFG0,
36388e93258fSBjoern A. Zeeb 				  B_AX_RLSRPT0_FLTR_MAP_MASK);
36398e93258fSBjoern A. Zeeb 	}
36408e93258fSBjoern A. Zeeb 
36418e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, R_AX_RLSRPT0_CFG1, B_AX_RLSRPT0_AGGNUM_MASK, 30);
36428e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, R_AX_RLSRPT0_CFG1, B_AX_RLSRPT0_TO_MASK, 255);
36438e93258fSBjoern A. Zeeb 
36448e93258fSBjoern A. Zeeb 	return 0;
36458e93258fSBjoern A. Zeeb }
36468e93258fSBjoern A. Zeeb 
3647*6d67aabdSBjoern A. Zeeb static int trx_init_ax(struct rtw89_dev *rtwdev)
36488e93258fSBjoern A. Zeeb {
3649*6d67aabdSBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
36508e93258fSBjoern A. Zeeb 	enum rtw89_qta_mode qta_mode = rtwdev->mac.qta_mode;
36518e93258fSBjoern A. Zeeb 	int ret;
36528e93258fSBjoern A. Zeeb 
3653*6d67aabdSBjoern A. Zeeb 	ret = dmac_init_ax(rtwdev, 0);
36548e93258fSBjoern A. Zeeb 	if (ret) {
36558e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]DMAC init %d\n", ret);
36568e93258fSBjoern A. Zeeb 		return ret;
36578e93258fSBjoern A. Zeeb 	}
36588e93258fSBjoern A. Zeeb 
3659*6d67aabdSBjoern A. Zeeb 	ret = cmac_init_ax(rtwdev, 0);
36608e93258fSBjoern A. Zeeb 	if (ret) {
36618e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]CMAC%d init %d\n", 0, ret);
36628e93258fSBjoern A. Zeeb 		return ret;
36638e93258fSBjoern A. Zeeb 	}
36648e93258fSBjoern A. Zeeb 
3665*6d67aabdSBjoern A. Zeeb 	if (rtw89_mac_is_qta_dbcc(rtwdev, qta_mode)) {
3666*6d67aabdSBjoern A. Zeeb 		ret = dbcc_enable_ax(rtwdev, true);
36678e93258fSBjoern A. Zeeb 		if (ret) {
36688e93258fSBjoern A. Zeeb 			rtw89_err(rtwdev, "[ERR]dbcc_enable init %d\n", ret);
36698e93258fSBjoern A. Zeeb 			return ret;
36708e93258fSBjoern A. Zeeb 		}
36718e93258fSBjoern A. Zeeb 	}
36728e93258fSBjoern A. Zeeb 
3673*6d67aabdSBjoern A. Zeeb 	ret = enable_imr_ax(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
36748e93258fSBjoern A. Zeeb 	if (ret) {
36758e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR] enable DMAC IMR %d\n", ret);
36768e93258fSBjoern A. Zeeb 		return ret;
36778e93258fSBjoern A. Zeeb 	}
36788e93258fSBjoern A. Zeeb 
3679*6d67aabdSBjoern A. Zeeb 	ret = enable_imr_ax(rtwdev, RTW89_MAC_0, RTW89_CMAC_SEL);
36808e93258fSBjoern A. Zeeb 	if (ret) {
36818e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR] to enable CMAC0 IMR %d\n", ret);
36828e93258fSBjoern A. Zeeb 		return ret;
36838e93258fSBjoern A. Zeeb 	}
36848e93258fSBjoern A. Zeeb 
3685*6d67aabdSBjoern A. Zeeb 	err_imr_ctrl_ax(rtwdev, true);
36868e93258fSBjoern A. Zeeb 
3687*6d67aabdSBjoern A. Zeeb 	ret = set_host_rpr_ax(rtwdev);
36888e93258fSBjoern A. Zeeb 	if (ret) {
36898e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR] set host rpr %d\n", ret);
36908e93258fSBjoern A. Zeeb 		return ret;
36918e93258fSBjoern A. Zeeb 	}
36928e93258fSBjoern A. Zeeb 
3693*6d67aabdSBjoern A. Zeeb 	if (chip_id == RTL8852C)
3694*6d67aabdSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, R_AX_RSP_CHK_SIG,
3695*6d67aabdSBjoern A. Zeeb 				  B_AX_RSP_STATIC_RTS_CHK_SERV_BW_EN);
3696*6d67aabdSBjoern A. Zeeb 
3697*6d67aabdSBjoern A. Zeeb 	return 0;
3698*6d67aabdSBjoern A. Zeeb }
3699*6d67aabdSBjoern A. Zeeb 
3700*6d67aabdSBjoern A. Zeeb static int rtw89_mac_feat_init(struct rtw89_dev *rtwdev)
3701*6d67aabdSBjoern A. Zeeb {
3702*6d67aabdSBjoern A. Zeeb #define BACAM_1024BMP_OCC_ENTRY 4
3703*6d67aabdSBjoern A. Zeeb #define BACAM_MAX_RU_SUPPORT_B0_STA 1
3704*6d67aabdSBjoern A. Zeeb #define BACAM_MAX_RU_SUPPORT_B1_STA 1
3705*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
3706*6d67aabdSBjoern A. Zeeb 	u8 users, offset;
3707*6d67aabdSBjoern A. Zeeb 
3708*6d67aabdSBjoern A. Zeeb 	if (chip->bacam_ver != RTW89_BACAM_V1)
3709*6d67aabdSBjoern A. Zeeb 		return 0;
3710*6d67aabdSBjoern A. Zeeb 
3711*6d67aabdSBjoern A. Zeeb 	offset = 0;
3712*6d67aabdSBjoern A. Zeeb 	users = BACAM_MAX_RU_SUPPORT_B0_STA;
3713*6d67aabdSBjoern A. Zeeb 	rtw89_fw_h2c_init_ba_cam_users(rtwdev, users, offset, RTW89_MAC_0);
3714*6d67aabdSBjoern A. Zeeb 
3715*6d67aabdSBjoern A. Zeeb 	offset += users * BACAM_1024BMP_OCC_ENTRY;
3716*6d67aabdSBjoern A. Zeeb 	users = BACAM_MAX_RU_SUPPORT_B1_STA;
3717*6d67aabdSBjoern A. Zeeb 	rtw89_fw_h2c_init_ba_cam_users(rtwdev, users, offset, RTW89_MAC_1);
3718*6d67aabdSBjoern A. Zeeb 
37198e93258fSBjoern A. Zeeb 	return 0;
37208e93258fSBjoern A. Zeeb }
37218e93258fSBjoern A. Zeeb 
37228e93258fSBjoern A. Zeeb static void rtw89_disable_fw_watchdog(struct rtw89_dev *rtwdev)
37238e93258fSBjoern A. Zeeb {
37248e93258fSBjoern A. Zeeb 	u32 val32;
37258e93258fSBjoern A. Zeeb 
3726*6d67aabdSBjoern A. Zeeb 	if (rtw89_is_rtl885xb(rtwdev)) {
3727e2340276SBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_APB_WRAP_EN);
3728e2340276SBjoern A. Zeeb 		rtw89_write32_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_APB_WRAP_EN);
3729e2340276SBjoern A. Zeeb 		return;
3730e2340276SBjoern A. Zeeb 	}
3731e2340276SBjoern A. Zeeb 
37328e93258fSBjoern A. Zeeb 	rtw89_mac_mem_write(rtwdev, R_AX_WDT_CTRL,
37338e93258fSBjoern A. Zeeb 			    WDT_CTRL_ALL_DIS, RTW89_MAC_MEM_CPU_LOCAL);
37348e93258fSBjoern A. Zeeb 
37358e93258fSBjoern A. Zeeb 	val32 = rtw89_mac_mem_read(rtwdev, R_AX_WDT_STATUS, RTW89_MAC_MEM_CPU_LOCAL);
37368e93258fSBjoern A. Zeeb 	val32 |= B_AX_FS_WDT_INT;
37378e93258fSBjoern A. Zeeb 	val32 &= ~B_AX_FS_WDT_INT_MSK;
37388e93258fSBjoern A. Zeeb 	rtw89_mac_mem_write(rtwdev, R_AX_WDT_STATUS, val32, RTW89_MAC_MEM_CPU_LOCAL);
37398e93258fSBjoern A. Zeeb }
37408e93258fSBjoern A. Zeeb 
3741*6d67aabdSBjoern A. Zeeb static void rtw89_mac_disable_cpu_ax(struct rtw89_dev *rtwdev)
37428e93258fSBjoern A. Zeeb {
37438e93258fSBjoern A. Zeeb 	clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags);
37448e93258fSBjoern A. Zeeb 
37458e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_WCPU_EN);
37468e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_WCPU_FW_CTRL, B_AX_WCPU_FWDL_EN |
37478e93258fSBjoern A. Zeeb 			  B_AX_H2C_PATH_RDY | B_AX_FWDL_PATH_RDY);
37488e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_SYS_CLK_CTRL, B_AX_CPU_CLK_EN);
37498e93258fSBjoern A. Zeeb 
37508e93258fSBjoern A. Zeeb 	rtw89_disable_fw_watchdog(rtwdev);
37518e93258fSBjoern A. Zeeb 
37528e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
37538e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN);
37548e93258fSBjoern A. Zeeb }
37558e93258fSBjoern A. Zeeb 
3756*6d67aabdSBjoern A. Zeeb static int rtw89_mac_enable_cpu_ax(struct rtw89_dev *rtwdev, u8 boot_reason,
3757*6d67aabdSBjoern A. Zeeb 				   bool dlfw, bool include_bb)
37588e93258fSBjoern A. Zeeb {
37598e93258fSBjoern A. Zeeb 	u32 val;
37608e93258fSBjoern A. Zeeb 	int ret;
37618e93258fSBjoern A. Zeeb 
37628e93258fSBjoern A. Zeeb 	if (rtw89_read32(rtwdev, R_AX_PLATFORM_ENABLE) & B_AX_WCPU_EN)
37638e93258fSBjoern A. Zeeb 		return -EFAULT;
37648e93258fSBjoern A. Zeeb 
3765e2340276SBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_UDM1, 0);
3766e2340276SBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_UDM2, 0);
37678e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, 0);
37688e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_HALT_C2H_CTRL, 0);
3769e2340276SBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_HALT_H2C, 0);
3770e2340276SBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_HALT_C2H, 0);
37718e93258fSBjoern A. Zeeb 
37728e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_SYS_CLK_CTRL, B_AX_CPU_CLK_EN);
37738e93258fSBjoern A. Zeeb 
37748e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, R_AX_WCPU_FW_CTRL);
37758e93258fSBjoern A. Zeeb 	val &= ~(B_AX_WCPU_FWDL_EN | B_AX_H2C_PATH_RDY | B_AX_FWDL_PATH_RDY);
37768e93258fSBjoern A. Zeeb 	val = u32_replace_bits(val, RTW89_FWDL_INITIAL_STATE,
37778e93258fSBjoern A. Zeeb 			       B_AX_WCPU_FWDL_STS_MASK);
37788e93258fSBjoern A. Zeeb 
37798e93258fSBjoern A. Zeeb 	if (dlfw)
37808e93258fSBjoern A. Zeeb 		val |= B_AX_WCPU_FWDL_EN;
37818e93258fSBjoern A. Zeeb 
37828e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_WCPU_FW_CTRL, val);
3783e2340276SBjoern A. Zeeb 
3784e2340276SBjoern A. Zeeb 	if (rtwdev->chip->chip_id == RTL8852B)
3785e2340276SBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, R_AX_SEC_CTRL,
3786e2340276SBjoern A. Zeeb 				   B_AX_SEC_IDMEM_SIZE_CONFIG_MASK, 0x2);
3787e2340276SBjoern A. Zeeb 
37888e93258fSBjoern A. Zeeb 	rtw89_write16_mask(rtwdev, R_AX_BOOT_REASON, B_AX_BOOT_REASON_MASK,
37898e93258fSBjoern A. Zeeb 			   boot_reason);
37908e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_WCPU_EN);
37918e93258fSBjoern A. Zeeb 
37928e93258fSBjoern A. Zeeb 	if (!dlfw) {
37938e93258fSBjoern A. Zeeb 		mdelay(5);
37948e93258fSBjoern A. Zeeb 
3795*6d67aabdSBjoern A. Zeeb 		ret = rtw89_fw_check_rdy(rtwdev, RTW89_FWDL_CHECK_FREERTOS_DONE);
37968e93258fSBjoern A. Zeeb 		if (ret)
37978e93258fSBjoern A. Zeeb 			return ret;
37988e93258fSBjoern A. Zeeb 	}
37998e93258fSBjoern A. Zeeb 
38008e93258fSBjoern A. Zeeb 	return 0;
38018e93258fSBjoern A. Zeeb }
38028e93258fSBjoern A. Zeeb 
3803*6d67aabdSBjoern A. Zeeb static void rtw89_mac_hci_func_en_ax(struct rtw89_dev *rtwdev)
38048e93258fSBjoern A. Zeeb {
38058e93258fSBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
38068e93258fSBjoern A. Zeeb 	u32 val;
38078e93258fSBjoern A. Zeeb 
38088e93258fSBjoern A. Zeeb 	if (chip_id == RTL8852C)
38098e93258fSBjoern A. Zeeb 		val = B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_DISPATCHER_EN |
38108e93258fSBjoern A. Zeeb 		      B_AX_PKT_BUF_EN | B_AX_H_AXIDMA_EN;
38118e93258fSBjoern A. Zeeb 	else
38128e93258fSBjoern A. Zeeb 		val = B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_DISPATCHER_EN |
38138e93258fSBjoern A. Zeeb 		      B_AX_PKT_BUF_EN;
38148e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_DMAC_FUNC_EN, val);
3815*6d67aabdSBjoern A. Zeeb }
38168e93258fSBjoern A. Zeeb 
3817*6d67aabdSBjoern A. Zeeb static void rtw89_mac_dmac_func_pre_en_ax(struct rtw89_dev *rtwdev)
3818*6d67aabdSBjoern A. Zeeb {
3819*6d67aabdSBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
3820*6d67aabdSBjoern A. Zeeb 	u32 val;
3821*6d67aabdSBjoern A. Zeeb 
3822*6d67aabdSBjoern A. Zeeb 	if (chip_id == RTL8851B || chip_id == RTL8852BT)
3823e2340276SBjoern A. Zeeb 		val = B_AX_DISPATCHER_CLK_EN | B_AX_AXIDMA_CLK_EN;
3824e2340276SBjoern A. Zeeb 	else
38258e93258fSBjoern A. Zeeb 		val = B_AX_DISPATCHER_CLK_EN;
38268e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_DMAC_CLK_EN, val);
38278e93258fSBjoern A. Zeeb 
38288e93258fSBjoern A. Zeeb 	if (chip_id != RTL8852C)
3829*6d67aabdSBjoern A. Zeeb 		return;
38308e93258fSBjoern A. Zeeb 
38318e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, R_AX_HAXI_INIT_CFG1);
38328e93258fSBjoern A. Zeeb 	val &= ~(B_AX_DMA_MODE_MASK | B_AX_STOP_AXI_MST);
38338e93258fSBjoern A. Zeeb 	val |= FIELD_PREP(B_AX_DMA_MODE_MASK, DMA_MOD_PCIE_1B) |
38348e93258fSBjoern A. Zeeb 	       B_AX_TXHCI_EN_V1 | B_AX_RXHCI_EN_V1;
38358e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_HAXI_INIT_CFG1, val);
38368e93258fSBjoern A. Zeeb 
38378e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_HAXI_DMA_STOP1,
38388e93258fSBjoern A. Zeeb 			  B_AX_STOP_ACH0 | B_AX_STOP_ACH1 | B_AX_STOP_ACH3 |
38398e93258fSBjoern A. Zeeb 			  B_AX_STOP_ACH4 | B_AX_STOP_ACH5 | B_AX_STOP_ACH6 |
38408e93258fSBjoern A. Zeeb 			  B_AX_STOP_ACH7 | B_AX_STOP_CH8 | B_AX_STOP_CH9 |
38418e93258fSBjoern A. Zeeb 			  B_AX_STOP_CH12 | B_AX_STOP_ACH2);
38428e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_HAXI_DMA_STOP2, B_AX_STOP_CH10 | B_AX_STOP_CH11);
38438e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_AXIDMA_EN);
3844*6d67aabdSBjoern A. Zeeb }
38458e93258fSBjoern A. Zeeb 
3846*6d67aabdSBjoern A. Zeeb static int rtw89_mac_dmac_pre_init(struct rtw89_dev *rtwdev)
3847*6d67aabdSBjoern A. Zeeb {
3848*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
3849*6d67aabdSBjoern A. Zeeb 	int ret;
3850*6d67aabdSBjoern A. Zeeb 
3851*6d67aabdSBjoern A. Zeeb 	mac->hci_func_en(rtwdev);
3852*6d67aabdSBjoern A. Zeeb 	mac->dmac_func_pre_en(rtwdev);
3853*6d67aabdSBjoern A. Zeeb 
3854*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_dle_init(rtwdev, RTW89_QTA_DLFW, rtwdev->mac.qta_mode);
38558e93258fSBjoern A. Zeeb 	if (ret) {
38568e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]DLE pre init %d\n", ret);
38578e93258fSBjoern A. Zeeb 		return ret;
38588e93258fSBjoern A. Zeeb 	}
38598e93258fSBjoern A. Zeeb 
3860*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_hfc_init(rtwdev, true, false, true);
38618e93258fSBjoern A. Zeeb 	if (ret) {
38628e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[ERR]HCI FC pre init %d\n", ret);
38638e93258fSBjoern A. Zeeb 		return ret;
38648e93258fSBjoern A. Zeeb 	}
38658e93258fSBjoern A. Zeeb 
38668e93258fSBjoern A. Zeeb 	return ret;
38678e93258fSBjoern A. Zeeb }
38688e93258fSBjoern A. Zeeb 
38698e93258fSBjoern A. Zeeb int rtw89_mac_enable_bb_rf(struct rtw89_dev *rtwdev)
38708e93258fSBjoern A. Zeeb {
38718e93258fSBjoern A. Zeeb 	rtw89_write8_set(rtwdev, R_AX_SYS_FUNC_EN,
38728e93258fSBjoern A. Zeeb 			 B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN);
38738e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL,
38748e93258fSBjoern A. Zeeb 			  B_AX_WLRF1_CTRL_7 | B_AX_WLRF1_CTRL_1 |
38758e93258fSBjoern A. Zeeb 			  B_AX_WLRF_CTRL_7 | B_AX_WLRF_CTRL_1);
38768e93258fSBjoern A. Zeeb 	rtw89_write8_set(rtwdev, R_AX_PHYREG_SET, PHYREG_SET_ALL_CYCLE);
38778e93258fSBjoern A. Zeeb 
38788e93258fSBjoern A. Zeeb 	return 0;
38798e93258fSBjoern A. Zeeb }
38808e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_enable_bb_rf);
38818e93258fSBjoern A. Zeeb 
3882e2340276SBjoern A. Zeeb int rtw89_mac_disable_bb_rf(struct rtw89_dev *rtwdev)
38838e93258fSBjoern A. Zeeb {
38848e93258fSBjoern A. Zeeb 	rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN,
38858e93258fSBjoern A. Zeeb 			 B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN);
38868e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL,
38878e93258fSBjoern A. Zeeb 			  B_AX_WLRF1_CTRL_7 | B_AX_WLRF1_CTRL_1 |
38888e93258fSBjoern A. Zeeb 			  B_AX_WLRF_CTRL_7 | B_AX_WLRF_CTRL_1);
38898e93258fSBjoern A. Zeeb 	rtw89_write8_clr(rtwdev, R_AX_PHYREG_SET, PHYREG_SET_ALL_CYCLE);
3890e2340276SBjoern A. Zeeb 
3891e2340276SBjoern A. Zeeb 	return 0;
38928e93258fSBjoern A. Zeeb }
38938e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_disable_bb_rf);
38948e93258fSBjoern A. Zeeb 
3895*6d67aabdSBjoern A. Zeeb int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb)
38968e93258fSBjoern A. Zeeb {
38978e93258fSBjoern A. Zeeb 	int ret;
38988e93258fSBjoern A. Zeeb 
38998e93258fSBjoern A. Zeeb 	ret = rtw89_mac_power_switch(rtwdev, true);
39008e93258fSBjoern A. Zeeb 	if (ret) {
39018e93258fSBjoern A. Zeeb 		rtw89_mac_power_switch(rtwdev, false);
39028e93258fSBjoern A. Zeeb 		ret = rtw89_mac_power_switch(rtwdev, true);
39038e93258fSBjoern A. Zeeb 		if (ret)
39048e93258fSBjoern A. Zeeb 			return ret;
39058e93258fSBjoern A. Zeeb 	}
39068e93258fSBjoern A. Zeeb 
3907e2340276SBjoern A. Zeeb 	rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
39088e93258fSBjoern A. Zeeb 
3909*6d67aabdSBjoern A. Zeeb 	if (include_bb) {
3910*6d67aabdSBjoern A. Zeeb 		rtw89_chip_bb_preinit(rtwdev, RTW89_PHY_0);
3911*6d67aabdSBjoern A. Zeeb 		if (rtwdev->dbcc_en)
3912*6d67aabdSBjoern A. Zeeb 			rtw89_chip_bb_preinit(rtwdev, RTW89_PHY_1);
3913*6d67aabdSBjoern A. Zeeb 	}
3914*6d67aabdSBjoern A. Zeeb 
39158e93258fSBjoern A. Zeeb 	ret = rtw89_mac_dmac_pre_init(rtwdev);
39168e93258fSBjoern A. Zeeb 	if (ret)
39178e93258fSBjoern A. Zeeb 		return ret;
39188e93258fSBjoern A. Zeeb 
39198e93258fSBjoern A. Zeeb 	if (rtwdev->hci.ops->mac_pre_init) {
39208e93258fSBjoern A. Zeeb 		ret = rtwdev->hci.ops->mac_pre_init(rtwdev);
39218e93258fSBjoern A. Zeeb 		if (ret)
39228e93258fSBjoern A. Zeeb 			return ret;
39238e93258fSBjoern A. Zeeb 	}
39248e93258fSBjoern A. Zeeb 
3925*6d67aabdSBjoern A. Zeeb 	ret = rtw89_fw_download(rtwdev, RTW89_FW_NORMAL, include_bb);
39268e93258fSBjoern A. Zeeb 	if (ret)
39278e93258fSBjoern A. Zeeb 		return ret;
39288e93258fSBjoern A. Zeeb 
39298e93258fSBjoern A. Zeeb 	return 0;
39308e93258fSBjoern A. Zeeb }
39318e93258fSBjoern A. Zeeb 
39328e93258fSBjoern A. Zeeb int rtw89_mac_init(struct rtw89_dev *rtwdev)
39338e93258fSBjoern A. Zeeb {
3934*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
3935*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
3936*6d67aabdSBjoern A. Zeeb 	bool include_bb = !!chip->bbmcu_nr;
39378e93258fSBjoern A. Zeeb 	int ret;
39388e93258fSBjoern A. Zeeb 
3939*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_partial_init(rtwdev, include_bb);
39408e93258fSBjoern A. Zeeb 	if (ret)
39418e93258fSBjoern A. Zeeb 		goto fail;
39428e93258fSBjoern A. Zeeb 
39438e93258fSBjoern A. Zeeb 	ret = rtw89_chip_enable_bb_rf(rtwdev);
39448e93258fSBjoern A. Zeeb 	if (ret)
39458e93258fSBjoern A. Zeeb 		goto fail;
39468e93258fSBjoern A. Zeeb 
3947*6d67aabdSBjoern A. Zeeb 	ret = mac->sys_init(rtwdev);
39488e93258fSBjoern A. Zeeb 	if (ret)
39498e93258fSBjoern A. Zeeb 		goto fail;
39508e93258fSBjoern A. Zeeb 
3951*6d67aabdSBjoern A. Zeeb 	ret = mac->trx_init(rtwdev);
3952*6d67aabdSBjoern A. Zeeb 	if (ret)
3953*6d67aabdSBjoern A. Zeeb 		goto fail;
3954*6d67aabdSBjoern A. Zeeb 
3955*6d67aabdSBjoern A. Zeeb 	ret = rtw89_mac_feat_init(rtwdev);
39568e93258fSBjoern A. Zeeb 	if (ret)
39578e93258fSBjoern A. Zeeb 		goto fail;
39588e93258fSBjoern A. Zeeb 
39598e93258fSBjoern A. Zeeb 	if (rtwdev->hci.ops->mac_post_init) {
39608e93258fSBjoern A. Zeeb 		ret = rtwdev->hci.ops->mac_post_init(rtwdev);
39618e93258fSBjoern A. Zeeb 		if (ret)
39628e93258fSBjoern A. Zeeb 			goto fail;
39638e93258fSBjoern A. Zeeb 	}
39648e93258fSBjoern A. Zeeb 
39658e93258fSBjoern A. Zeeb 	rtw89_fw_send_all_early_h2c(rtwdev);
39668e93258fSBjoern A. Zeeb 	rtw89_fw_h2c_set_ofld_cfg(rtwdev);
39678e93258fSBjoern A. Zeeb 
39688e93258fSBjoern A. Zeeb 	return ret;
39698e93258fSBjoern A. Zeeb fail:
39708e93258fSBjoern A. Zeeb 	rtw89_mac_power_switch(rtwdev, false);
39718e93258fSBjoern A. Zeeb 
39728e93258fSBjoern A. Zeeb 	return ret;
39738e93258fSBjoern A. Zeeb }
39748e93258fSBjoern A. Zeeb 
39758e93258fSBjoern A. Zeeb static void rtw89_mac_dmac_tbl_init(struct rtw89_dev *rtwdev, u8 macid)
39768e93258fSBjoern A. Zeeb {
39778e93258fSBjoern A. Zeeb 	u8 i;
39788e93258fSBjoern A. Zeeb 
3979*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
3980*6d67aabdSBjoern A. Zeeb 		return;
3981*6d67aabdSBjoern A. Zeeb 
39828e93258fSBjoern A. Zeeb 	for (i = 0; i < 4; i++) {
39838e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR,
39848e93258fSBjoern A. Zeeb 			      DMAC_TBL_BASE_ADDR + (macid << 4) + (i << 2));
39858e93258fSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY, 0);
39868e93258fSBjoern A. Zeeb 	}
39878e93258fSBjoern A. Zeeb }
39888e93258fSBjoern A. Zeeb 
39898e93258fSBjoern A. Zeeb static void rtw89_mac_cmac_tbl_init(struct rtw89_dev *rtwdev, u8 macid)
39908e93258fSBjoern A. Zeeb {
3991*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
3992*6d67aabdSBjoern A. Zeeb 		return;
3993*6d67aabdSBjoern A. Zeeb 
39948e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_FILTER_MODEL_ADDR,
39958e93258fSBjoern A. Zeeb 		      CMAC_TBL_BASE_ADDR + macid * CCTL_INFO_SIZE);
39968e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY, 0x4);
39978e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY + 4, 0x400A0004);
39988e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY + 8, 0);
39998e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY + 12, 0);
40008e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY + 16, 0);
40018e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY + 20, 0xE43000B);
40028e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY + 24, 0);
40038e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_INDIR_ACCESS_ENTRY + 28, 0xB8109);
40048e93258fSBjoern A. Zeeb }
40058e93258fSBjoern A. Zeeb 
40068e93258fSBjoern A. Zeeb int rtw89_mac_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause)
40078e93258fSBjoern A. Zeeb {
40088e93258fSBjoern A. Zeeb 	u8 sh =  FIELD_GET(GENMASK(4, 0), macid);
40098e93258fSBjoern A. Zeeb 	u8 grp = macid >> 5;
40108e93258fSBjoern A. Zeeb 	int ret;
40118e93258fSBjoern A. Zeeb 
4012e2340276SBjoern A. Zeeb 	/* If this is called by change_interface() in the case of P2P, it could
4013e2340276SBjoern A. Zeeb 	 * be power-off, so ignore this operation.
4014e2340276SBjoern A. Zeeb 	 */
4015e2340276SBjoern A. Zeeb 	if (test_bit(RTW89_FLAG_CHANGING_INTERFACE, rtwdev->flags) &&
4016e2340276SBjoern A. Zeeb 	    !test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
4017e2340276SBjoern A. Zeeb 		return 0;
4018e2340276SBjoern A. Zeeb 
40198e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_CMAC_SEL);
40208e93258fSBjoern A. Zeeb 	if (ret)
40218e93258fSBjoern A. Zeeb 		return ret;
40228e93258fSBjoern A. Zeeb 
40238e93258fSBjoern A. Zeeb 	rtw89_fw_h2c_macid_pause(rtwdev, sh, grp, pause);
40248e93258fSBjoern A. Zeeb 
40258e93258fSBjoern A. Zeeb 	return 0;
40268e93258fSBjoern A. Zeeb }
40278e93258fSBjoern A. Zeeb 
4028*6d67aabdSBjoern A. Zeeb static const struct rtw89_port_reg rtw89_port_base_ax = {
40298e93258fSBjoern A. Zeeb 	.port_cfg = R_AX_PORT_CFG_P0,
40308e93258fSBjoern A. Zeeb 	.tbtt_prohib = R_AX_TBTT_PROHIB_P0,
40318e93258fSBjoern A. Zeeb 	.bcn_area = R_AX_BCN_AREA_P0,
40328e93258fSBjoern A. Zeeb 	.bcn_early = R_AX_BCNERLYINT_CFG_P0,
40338e93258fSBjoern A. Zeeb 	.tbtt_early = R_AX_TBTTERLYINT_CFG_P0,
40348e93258fSBjoern A. Zeeb 	.tbtt_agg = R_AX_TBTT_AGG_P0,
40358e93258fSBjoern A. Zeeb 	.bcn_space = R_AX_BCN_SPACE_CFG_P0,
40368e93258fSBjoern A. Zeeb 	.bcn_forcetx = R_AX_BCN_FORCETX_P0,
40378e93258fSBjoern A. Zeeb 	.bcn_err_cnt = R_AX_BCN_ERR_CNT_P0,
40388e93258fSBjoern A. Zeeb 	.bcn_err_flag = R_AX_BCN_ERR_FLAG_P0,
40398e93258fSBjoern A. Zeeb 	.dtim_ctrl = R_AX_DTIM_CTRL_P0,
40408e93258fSBjoern A. Zeeb 	.tbtt_shift = R_AX_TBTT_SHIFT_P0,
40418e93258fSBjoern A. Zeeb 	.bcn_cnt_tmr = R_AX_BCN_CNT_TMR_P0,
40428e93258fSBjoern A. Zeeb 	.tsftr_l = R_AX_TSFTR_LOW_P0,
4043*6d67aabdSBjoern A. Zeeb 	.tsftr_h = R_AX_TSFTR_HIGH_P0,
4044*6d67aabdSBjoern A. Zeeb 	.md_tsft = R_AX_MD_TSFT_STMP_CTL,
4045*6d67aabdSBjoern A. Zeeb 	.bss_color = R_AX_PTCL_BSS_COLOR_0,
4046*6d67aabdSBjoern A. Zeeb 	.mbssid = R_AX_MBSSID_CTRL,
4047*6d67aabdSBjoern A. Zeeb 	.mbssid_drop = R_AX_MBSSID_DROP_0,
4048*6d67aabdSBjoern A. Zeeb 	.tsf_sync = R_AX_PORT0_TSF_SYNC,
4049*6d67aabdSBjoern A. Zeeb 	.ptcl_dbg = R_AX_PTCL_DBG,
4050*6d67aabdSBjoern A. Zeeb 	.ptcl_dbg_info = R_AX_PTCL_DBG_INFO,
4051*6d67aabdSBjoern A. Zeeb 	.bcn_drop_all = R_AX_BCN_DROP_ALL0,
4052*6d67aabdSBjoern A. Zeeb 	.hiq_win = {R_AX_P0MB_HGQ_WINDOW_CFG_0, R_AX_PORT_HGQ_WINDOW_CFG,
4053*6d67aabdSBjoern A. Zeeb 		    R_AX_PORT_HGQ_WINDOW_CFG + 1, R_AX_PORT_HGQ_WINDOW_CFG + 2,
4054*6d67aabdSBjoern A. Zeeb 		    R_AX_PORT_HGQ_WINDOW_CFG + 3},
40558e93258fSBjoern A. Zeeb };
40568e93258fSBjoern A. Zeeb 
4057*6d67aabdSBjoern A. Zeeb static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev,
4058*6d67aabdSBjoern A. Zeeb 					struct rtw89_vif *rtwvif, u8 type)
4059*6d67aabdSBjoern A. Zeeb {
4060*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4061*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
4062*6d67aabdSBjoern A. Zeeb 	u8 mask = B_AX_PTCL_DBG_INFO_MASK_BY_PORT(rtwvif->port);
4063*6d67aabdSBjoern A. Zeeb 	u32 reg_info, reg_ctrl;
4064*6d67aabdSBjoern A. Zeeb 	u32 val;
4065*6d67aabdSBjoern A. Zeeb 	int ret;
4066*6d67aabdSBjoern A. Zeeb 
4067*6d67aabdSBjoern A. Zeeb 	reg_info = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg_info, rtwvif->mac_idx);
4068*6d67aabdSBjoern A. Zeeb 	reg_ctrl = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg, rtwvif->mac_idx);
4069*6d67aabdSBjoern A. Zeeb 
4070*6d67aabdSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg_ctrl, B_AX_PTCL_DBG_SEL_MASK, type);
4071*6d67aabdSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg_ctrl, B_AX_PTCL_DBG_EN);
4072*6d67aabdSBjoern A. Zeeb 	fsleep(100);
4073*6d67aabdSBjoern A. Zeeb 
4074*6d67aabdSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read32_mask, val, val == 0, 1000, 100000,
4075*6d67aabdSBjoern A. Zeeb 				true, rtwdev, reg_info, mask);
4076*6d67aabdSBjoern A. Zeeb 	if (ret)
4077*6d67aabdSBjoern A. Zeeb 		rtw89_warn(rtwdev, "Polling beacon packet empty fail\n");
4078*6d67aabdSBjoern A. Zeeb }
4079*6d67aabdSBjoern A. Zeeb 
4080*6d67aabdSBjoern A. Zeeb static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
4081*6d67aabdSBjoern A. Zeeb {
4082*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4083*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
4084*6d67aabdSBjoern A. Zeeb 
4085*6d67aabdSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, p->bcn_drop_all, BIT(rtwvif->port));
4086*6d67aabdSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, 1);
4087*6d67aabdSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, 0);
4088*6d67aabdSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 0);
4089*6d67aabdSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK, 2);
4090*6d67aabdSBjoern A. Zeeb 	rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK, 1);
4091*6d67aabdSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK, 1);
4092*6d67aabdSBjoern A. Zeeb 	rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN);
4093*6d67aabdSBjoern A. Zeeb 
4094*6d67aabdSBjoern A. Zeeb 	rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM0);
4095*6d67aabdSBjoern A. Zeeb 	if (rtwvif->port == RTW89_PORT_0)
4096*6d67aabdSBjoern A. Zeeb 		rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM1);
4097*6d67aabdSBjoern A. Zeeb 
4098*6d67aabdSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, p->bcn_drop_all, BIT(rtwvif->port));
4099*6d67aabdSBjoern A. Zeeb 	rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TBTT_PROHIB_EN);
4100*6d67aabdSBjoern A. Zeeb 	fsleep(2000);
4101*6d67aabdSBjoern A. Zeeb }
4102*6d67aabdSBjoern A. Zeeb 
41038e93258fSBjoern A. Zeeb #define BCN_INTERVAL 100
41048e93258fSBjoern A. Zeeb #define BCN_ERLY_DEF 160
41058e93258fSBjoern A. Zeeb #define BCN_SETUP_DEF 2
41068e93258fSBjoern A. Zeeb #define BCN_HOLD_DEF 200
41078e93258fSBjoern A. Zeeb #define BCN_MASK_DEF 0
41088e93258fSBjoern A. Zeeb #define TBTT_ERLY_DEF 5
41098e93258fSBjoern A. Zeeb #define BCN_SET_UNIT 32
41108e93258fSBjoern A. Zeeb #define BCN_ERLY_SET_DLY (10 * 2)
41118e93258fSBjoern A. Zeeb 
41128e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_func_sw(struct rtw89_dev *rtwdev,
41138e93258fSBjoern A. Zeeb 				       struct rtw89_vif *rtwvif)
41148e93258fSBjoern A. Zeeb {
4115*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4116*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
41178e93258fSBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
4118*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
4119*6d67aabdSBjoern A. Zeeb 	bool need_backup = false;
4120*6d67aabdSBjoern A. Zeeb 	u32 backup_val;
41218e93258fSBjoern A. Zeeb 
41228e93258fSBjoern A. Zeeb 	if (!rtw89_read32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN))
41238e93258fSBjoern A. Zeeb 		return;
41248e93258fSBjoern A. Zeeb 
4125*6d67aabdSBjoern A. Zeeb 	if (chip->chip_id == RTL8852A && rtwvif->port != RTW89_PORT_0) {
4126*6d67aabdSBjoern A. Zeeb 		need_backup = true;
4127*6d67aabdSBjoern A. Zeeb 		backup_val = rtw89_read32_port(rtwdev, rtwvif, p->tbtt_prohib);
4128*6d67aabdSBjoern A. Zeeb 	}
4129*6d67aabdSBjoern A. Zeeb 
4130*6d67aabdSBjoern A. Zeeb 	if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
4131*6d67aabdSBjoern A. Zeeb 		rtw89_mac_bcn_drop(rtwdev, rtwvif);
4132*6d67aabdSBjoern A. Zeeb 
4133*6d67aabdSBjoern A. Zeeb 	if (chip->chip_id == RTL8852A) {
41348e93258fSBjoern A. Zeeb 		rtw89_write32_port_clr(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK);
41358e93258fSBjoern A. Zeeb 		rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 1);
41368e93258fSBjoern A. Zeeb 		rtw89_write16_port_clr(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK);
41378e93258fSBjoern A. Zeeb 		rtw89_write16_port_clr(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK);
4138*6d67aabdSBjoern A. Zeeb 	}
41398e93258fSBjoern A. Zeeb 
41408e93258fSBjoern A. Zeeb 	msleep(vif->bss_conf.beacon_int + 1);
41418e93258fSBjoern A. Zeeb 	rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN |
41428e93258fSBjoern A. Zeeb 							    B_AX_BRK_SETUP);
41438e93258fSBjoern A. Zeeb 	rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSFTR_RST);
41448e93258fSBjoern A. Zeeb 	rtw89_write32_port(rtwdev, rtwvif, p->bcn_cnt_tmr, 0);
4145*6d67aabdSBjoern A. Zeeb 
4146*6d67aabdSBjoern A. Zeeb 	if (need_backup)
4147*6d67aabdSBjoern A. Zeeb 		rtw89_write32_port(rtwdev, rtwvif, p->tbtt_prohib, backup_val);
41488e93258fSBjoern A. Zeeb }
41498e93258fSBjoern A. Zeeb 
41508e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_tx_rpt(struct rtw89_dev *rtwdev,
41518e93258fSBjoern A. Zeeb 				      struct rtw89_vif *rtwvif, bool en)
41528e93258fSBjoern A. Zeeb {
4153*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4154*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
41558e93258fSBjoern A. Zeeb 
41568e93258fSBjoern A. Zeeb 	if (en)
41578e93258fSBjoern A. Zeeb 		rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN);
41588e93258fSBjoern A. Zeeb 	else
41598e93258fSBjoern A. Zeeb 		rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN);
41608e93258fSBjoern A. Zeeb }
41618e93258fSBjoern A. Zeeb 
41628e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_rx_rpt(struct rtw89_dev *rtwdev,
41638e93258fSBjoern A. Zeeb 				      struct rtw89_vif *rtwvif, bool en)
41648e93258fSBjoern A. Zeeb {
4165*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4166*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
41678e93258fSBjoern A. Zeeb 
41688e93258fSBjoern A. Zeeb 	if (en)
41698e93258fSBjoern A. Zeeb 		rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN);
41708e93258fSBjoern A. Zeeb 	else
41718e93258fSBjoern A. Zeeb 		rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN);
41728e93258fSBjoern A. Zeeb }
41738e93258fSBjoern A. Zeeb 
41748e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_net_type(struct rtw89_dev *rtwdev,
41758e93258fSBjoern A. Zeeb 					struct rtw89_vif *rtwvif)
41768e93258fSBjoern A. Zeeb {
4177*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4178*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
41798e93258fSBjoern A. Zeeb 
41808e93258fSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_NET_TYPE_MASK,
41818e93258fSBjoern A. Zeeb 				rtwvif->net_type);
41828e93258fSBjoern A. Zeeb }
41838e93258fSBjoern A. Zeeb 
41848e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_bcn_prct(struct rtw89_dev *rtwdev,
41858e93258fSBjoern A. Zeeb 					struct rtw89_vif *rtwvif)
41868e93258fSBjoern A. Zeeb {
4187*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4188*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
41898e93258fSBjoern A. Zeeb 	bool en = rtwvif->net_type != RTW89_NET_TYPE_NO_LINK;
41908e93258fSBjoern A. Zeeb 	u32 bits = B_AX_TBTT_PROHIB_EN | B_AX_BRK_SETUP;
41918e93258fSBjoern A. Zeeb 
41928e93258fSBjoern A. Zeeb 	if (en)
41938e93258fSBjoern A. Zeeb 		rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bits);
41948e93258fSBjoern A. Zeeb 	else
41958e93258fSBjoern A. Zeeb 		rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bits);
41968e93258fSBjoern A. Zeeb }
41978e93258fSBjoern A. Zeeb 
41988e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_rx_sw(struct rtw89_dev *rtwdev,
41998e93258fSBjoern A. Zeeb 				     struct rtw89_vif *rtwvif)
42008e93258fSBjoern A. Zeeb {
4201*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4202*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
42038e93258fSBjoern A. Zeeb 	bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA ||
42048e93258fSBjoern A. Zeeb 		  rtwvif->net_type == RTW89_NET_TYPE_AD_HOC;
42058e93258fSBjoern A. Zeeb 	u32 bit = B_AX_RX_BSSID_FIT_EN;
42068e93258fSBjoern A. Zeeb 
42078e93258fSBjoern A. Zeeb 	if (en)
42088e93258fSBjoern A. Zeeb 		rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bit);
42098e93258fSBjoern A. Zeeb 	else
42108e93258fSBjoern A. Zeeb 		rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bit);
42118e93258fSBjoern A. Zeeb }
42128e93258fSBjoern A. Zeeb 
4213*6d67aabdSBjoern A. Zeeb void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev,
4214*6d67aabdSBjoern A. Zeeb 				struct rtw89_vif *rtwvif, bool en)
42158e93258fSBjoern A. Zeeb {
4216*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4217*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
42188e93258fSBjoern A. Zeeb 
42198e93258fSBjoern A. Zeeb 	if (en)
42208e93258fSBjoern A. Zeeb 		rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN);
42218e93258fSBjoern A. Zeeb 	else
42228e93258fSBjoern A. Zeeb 		rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN);
42238e93258fSBjoern A. Zeeb }
42248e93258fSBjoern A. Zeeb 
4225*6d67aabdSBjoern A. Zeeb static void rtw89_mac_port_cfg_rx_sync_by_nettype(struct rtw89_dev *rtwdev,
42268e93258fSBjoern A. Zeeb 						  struct rtw89_vif *rtwvif)
42278e93258fSBjoern A. Zeeb {
4228*6d67aabdSBjoern A. Zeeb 	bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA ||
42298e93258fSBjoern A. Zeeb 		  rtwvif->net_type == RTW89_NET_TYPE_AD_HOC;
42308e93258fSBjoern A. Zeeb 
4231*6d67aabdSBjoern A. Zeeb 	rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, en);
4232*6d67aabdSBjoern A. Zeeb }
4233*6d67aabdSBjoern A. Zeeb 
4234*6d67aabdSBjoern A. Zeeb static void rtw89_mac_port_cfg_tx_sw(struct rtw89_dev *rtwdev,
4235*6d67aabdSBjoern A. Zeeb 				     struct rtw89_vif *rtwvif, bool en)
4236*6d67aabdSBjoern A. Zeeb {
4237*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4238*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
4239*6d67aabdSBjoern A. Zeeb 
42408e93258fSBjoern A. Zeeb 	if (en)
42418e93258fSBjoern A. Zeeb 		rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN);
42428e93258fSBjoern A. Zeeb 	else
42438e93258fSBjoern A. Zeeb 		rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN);
42448e93258fSBjoern A. Zeeb }
42458e93258fSBjoern A. Zeeb 
4246*6d67aabdSBjoern A. Zeeb static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev,
4247*6d67aabdSBjoern A. Zeeb 						struct rtw89_vif *rtwvif)
4248*6d67aabdSBjoern A. Zeeb {
4249*6d67aabdSBjoern A. Zeeb 	bool en = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ||
4250*6d67aabdSBjoern A. Zeeb 		  rtwvif->net_type == RTW89_NET_TYPE_AD_HOC;
4251*6d67aabdSBjoern A. Zeeb 
4252*6d67aabdSBjoern A. Zeeb 	rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en);
4253*6d67aabdSBjoern A. Zeeb }
4254*6d67aabdSBjoern A. Zeeb 
4255*6d67aabdSBjoern A. Zeeb void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en)
4256*6d67aabdSBjoern A. Zeeb {
4257*6d67aabdSBjoern A. Zeeb 	struct rtw89_vif *rtwvif;
4258*6d67aabdSBjoern A. Zeeb 
4259*6d67aabdSBjoern A. Zeeb 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
4260*6d67aabdSBjoern A. Zeeb 		if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
4261*6d67aabdSBjoern A. Zeeb 			rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en);
4262*6d67aabdSBjoern A. Zeeb }
4263*6d67aabdSBjoern A. Zeeb 
42648e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev,
42658e93258fSBjoern A. Zeeb 					struct rtw89_vif *rtwvif)
42668e93258fSBjoern A. Zeeb {
4267*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4268*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
42698e93258fSBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
42708e93258fSBjoern A. Zeeb 	u16 bcn_int = vif->bss_conf.beacon_int ? vif->bss_conf.beacon_int : BCN_INTERVAL;
42718e93258fSBjoern A. Zeeb 
42728e93258fSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK,
42738e93258fSBjoern A. Zeeb 				bcn_int);
42748e93258fSBjoern A. Zeeb }
42758e93258fSBjoern A. Zeeb 
42768e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_hiq_win(struct rtw89_dev *rtwdev,
42778e93258fSBjoern A. Zeeb 				       struct rtw89_vif *rtwvif)
42788e93258fSBjoern A. Zeeb {
42798e93258fSBjoern A. Zeeb 	u8 win = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0;
4280*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4281*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
42828e93258fSBjoern A. Zeeb 	u8 port = rtwvif->port;
42838e93258fSBjoern A. Zeeb 	u32 reg;
42848e93258fSBjoern A. Zeeb 
4285*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, p->hiq_win[port], rtwvif->mac_idx);
42868e93258fSBjoern A. Zeeb 	rtw89_write8(rtwdev, reg, win);
42878e93258fSBjoern A. Zeeb }
42888e93258fSBjoern A. Zeeb 
42898e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_hiq_dtim(struct rtw89_dev *rtwdev,
42908e93258fSBjoern A. Zeeb 					struct rtw89_vif *rtwvif)
42918e93258fSBjoern A. Zeeb {
4292*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4293*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
42948e93258fSBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
42958e93258fSBjoern A. Zeeb 	u32 addr;
42968e93258fSBjoern A. Zeeb 
4297*6d67aabdSBjoern A. Zeeb 	addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif->mac_idx);
42988e93258fSBjoern A. Zeeb 	rtw89_write8_set(rtwdev, addr, B_AX_UPD_HGQMD | B_AX_UPD_TIMIE);
42998e93258fSBjoern A. Zeeb 
43008e93258fSBjoern A. Zeeb 	rtw89_write16_port_mask(rtwdev, rtwvif, p->dtim_ctrl, B_AX_DTIM_NUM_MASK,
43018e93258fSBjoern A. Zeeb 				vif->bss_conf.dtim_period);
43028e93258fSBjoern A. Zeeb }
43038e93258fSBjoern A. Zeeb 
43048e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_bcn_setup_time(struct rtw89_dev *rtwdev,
43058e93258fSBjoern A. Zeeb 					      struct rtw89_vif *rtwvif)
43068e93258fSBjoern A. Zeeb {
4307*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4308*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
43098e93258fSBjoern A. Zeeb 
43108e93258fSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib,
43118e93258fSBjoern A. Zeeb 				B_AX_TBTT_SETUP_MASK, BCN_SETUP_DEF);
43128e93258fSBjoern A. Zeeb }
43138e93258fSBjoern A. Zeeb 
43148e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_bcn_hold_time(struct rtw89_dev *rtwdev,
43158e93258fSBjoern A. Zeeb 					     struct rtw89_vif *rtwvif)
43168e93258fSBjoern A. Zeeb {
4317*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4318*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
43198e93258fSBjoern A. Zeeb 
43208e93258fSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib,
43218e93258fSBjoern A. Zeeb 				B_AX_TBTT_HOLD_MASK, BCN_HOLD_DEF);
43228e93258fSBjoern A. Zeeb }
43238e93258fSBjoern A. Zeeb 
43248e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_bcn_mask_area(struct rtw89_dev *rtwdev,
43258e93258fSBjoern A. Zeeb 					     struct rtw89_vif *rtwvif)
43268e93258fSBjoern A. Zeeb {
4327*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4328*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
43298e93258fSBjoern A. Zeeb 
43308e93258fSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area,
43318e93258fSBjoern A. Zeeb 				B_AX_BCN_MSK_AREA_MASK, BCN_MASK_DEF);
43328e93258fSBjoern A. Zeeb }
43338e93258fSBjoern A. Zeeb 
43348e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_tbtt_early(struct rtw89_dev *rtwdev,
43358e93258fSBjoern A. Zeeb 					  struct rtw89_vif *rtwvif)
43368e93258fSBjoern A. Zeeb {
4337*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4338*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
43398e93258fSBjoern A. Zeeb 
43408e93258fSBjoern A. Zeeb 	rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early,
43418e93258fSBjoern A. Zeeb 				B_AX_TBTTERLY_MASK, TBTT_ERLY_DEF);
43428e93258fSBjoern A. Zeeb }
43438e93258fSBjoern A. Zeeb 
43448e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev,
43458e93258fSBjoern A. Zeeb 					 struct rtw89_vif *rtwvif)
43468e93258fSBjoern A. Zeeb {
4347*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4348*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
43498e93258fSBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
43508e93258fSBjoern A. Zeeb 	static const u32 masks[RTW89_PORT_NUM] = {
43518e93258fSBjoern A. Zeeb 		B_AX_BSS_COLOB_AX_PORT_0_MASK, B_AX_BSS_COLOB_AX_PORT_1_MASK,
43528e93258fSBjoern A. Zeeb 		B_AX_BSS_COLOB_AX_PORT_2_MASK, B_AX_BSS_COLOB_AX_PORT_3_MASK,
43538e93258fSBjoern A. Zeeb 		B_AX_BSS_COLOB_AX_PORT_4_MASK,
43548e93258fSBjoern A. Zeeb 	};
43558e93258fSBjoern A. Zeeb 	u8 port = rtwvif->port;
43568e93258fSBjoern A. Zeeb 	u32 reg_base;
43578e93258fSBjoern A. Zeeb 	u32 reg;
43588e93258fSBjoern A. Zeeb 	u8 bss_color;
43598e93258fSBjoern A. Zeeb 
43608e93258fSBjoern A. Zeeb 	bss_color = vif->bss_conf.he_bss_color.color;
4361*6d67aabdSBjoern A. Zeeb 	reg_base = port >= 4 ? p->bss_color + 4 : p->bss_color;
4362*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif->mac_idx);
43638e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, masks[port], bss_color);
43648e93258fSBjoern A. Zeeb }
43658e93258fSBjoern A. Zeeb 
43668e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_mbssid(struct rtw89_dev *rtwdev,
43678e93258fSBjoern A. Zeeb 				      struct rtw89_vif *rtwvif)
43688e93258fSBjoern A. Zeeb {
4369*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4370*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
43718e93258fSBjoern A. Zeeb 	u8 port = rtwvif->port;
43728e93258fSBjoern A. Zeeb 	u32 reg;
43738e93258fSBjoern A. Zeeb 
43748e93258fSBjoern A. Zeeb 	if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
43758e93258fSBjoern A. Zeeb 		return;
43768e93258fSBjoern A. Zeeb 
43778e93258fSBjoern A. Zeeb 	if (port == 0) {
4378*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid, rtwvif->mac_idx);
43798e93258fSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, reg, B_AX_P0MB_ALL_MASK);
43808e93258fSBjoern A. Zeeb 	}
43818e93258fSBjoern A. Zeeb }
43828e93258fSBjoern A. Zeeb 
43838e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev,
43848e93258fSBjoern A. Zeeb 					struct rtw89_vif *rtwvif)
43858e93258fSBjoern A. Zeeb {
4386*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4387*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
43888e93258fSBjoern A. Zeeb 	u8 port = rtwvif->port;
43898e93258fSBjoern A. Zeeb 	u32 reg;
43908e93258fSBjoern A. Zeeb 	u32 val;
43918e93258fSBjoern A. Zeeb 
4392*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid_drop, rtwvif->mac_idx);
43938e93258fSBjoern A. Zeeb 	val = rtw89_read32(rtwdev, reg);
43948e93258fSBjoern A. Zeeb 	val &= ~FIELD_PREP(B_AX_PORT_DROP_4_0_MASK, BIT(port));
43958e93258fSBjoern A. Zeeb 	if (port == 0)
43968e93258fSBjoern A. Zeeb 		val &= ~BIT(0);
43978e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val);
43988e93258fSBjoern A. Zeeb }
43998e93258fSBjoern A. Zeeb 
44008e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_func_en(struct rtw89_dev *rtwdev,
4401e2340276SBjoern A. Zeeb 				       struct rtw89_vif *rtwvif, bool enable)
44028e93258fSBjoern A. Zeeb {
4403*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4404*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
44058e93258fSBjoern A. Zeeb 
4406e2340276SBjoern A. Zeeb 	if (enable)
4407e2340276SBjoern A. Zeeb 		rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg,
4408e2340276SBjoern A. Zeeb 				       B_AX_PORT_FUNC_EN);
4409e2340276SBjoern A. Zeeb 	else
4410e2340276SBjoern A. Zeeb 		rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg,
4411e2340276SBjoern A. Zeeb 				       B_AX_PORT_FUNC_EN);
44128e93258fSBjoern A. Zeeb }
44138e93258fSBjoern A. Zeeb 
44148e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_bcn_early(struct rtw89_dev *rtwdev,
44158e93258fSBjoern A. Zeeb 					 struct rtw89_vif *rtwvif)
44168e93258fSBjoern A. Zeeb {
4417*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4418*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
44198e93258fSBjoern A. Zeeb 
44208e93258fSBjoern A. Zeeb 	rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK,
44218e93258fSBjoern A. Zeeb 				BCN_ERLY_DEF);
44228e93258fSBjoern A. Zeeb }
44238e93258fSBjoern A. Zeeb 
44248e93258fSBjoern A. Zeeb static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev,
44258e93258fSBjoern A. Zeeb 					  struct rtw89_vif *rtwvif)
44268e93258fSBjoern A. Zeeb {
4427*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4428*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
44298e93258fSBjoern A. Zeeb 	u16 val;
44308e93258fSBjoern A. Zeeb 
44318e93258fSBjoern A. Zeeb 	if (rtwdev->chip->chip_id != RTL8852C)
44328e93258fSBjoern A. Zeeb 		return;
44338e93258fSBjoern A. Zeeb 
44348e93258fSBjoern A. Zeeb 	if (rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT &&
44358e93258fSBjoern A. Zeeb 	    rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
44368e93258fSBjoern A. Zeeb 		return;
44378e93258fSBjoern A. Zeeb 
44388e93258fSBjoern A. Zeeb 	val = FIELD_PREP(B_AX_TBTT_SHIFT_OFST_MAG, 1) |
44398e93258fSBjoern A. Zeeb 			 B_AX_TBTT_SHIFT_OFST_SIGN;
44408e93258fSBjoern A. Zeeb 
44418e93258fSBjoern A. Zeeb 	rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_shift,
44428e93258fSBjoern A. Zeeb 				B_AX_TBTT_SHIFT_OFST_MASK, val);
44438e93258fSBjoern A. Zeeb }
44448e93258fSBjoern A. Zeeb 
4445e2340276SBjoern A. Zeeb void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev,
4446e2340276SBjoern A. Zeeb 			     struct rtw89_vif *rtwvif,
4447e2340276SBjoern A. Zeeb 			     struct rtw89_vif *rtwvif_src,
4448e2340276SBjoern A. Zeeb 			     u16 offset_tu)
4449e2340276SBjoern A. Zeeb {
4450*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4451*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
4452e2340276SBjoern A. Zeeb 	u32 val, reg;
4453e2340276SBjoern A. Zeeb 
4454e2340276SBjoern A. Zeeb 	val = RTW89_PORT_OFFSET_TU_TO_32US(offset_tu);
4455*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, p->tsf_sync + rtwvif->port * 4,
4456e2340276SBjoern A. Zeeb 				   rtwvif->mac_idx);
4457e2340276SBjoern A. Zeeb 
4458e2340276SBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_SRC, rtwvif_src->port);
4459e2340276SBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_OFFSET_VAL, val);
4460e2340276SBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, B_AX_SYNC_NOW);
4461e2340276SBjoern A. Zeeb }
4462e2340276SBjoern A. Zeeb 
4463e2340276SBjoern A. Zeeb static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev,
4464e2340276SBjoern A. Zeeb 					 struct rtw89_vif *rtwvif,
4465e2340276SBjoern A. Zeeb 					 struct rtw89_vif *rtwvif_src,
4466e2340276SBjoern A. Zeeb 					 u8 offset, int *n_offset)
4467e2340276SBjoern A. Zeeb {
4468e2340276SBjoern A. Zeeb 	if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif == rtwvif_src)
4469e2340276SBjoern A. Zeeb 		return;
4470e2340276SBjoern A. Zeeb 
4471e2340276SBjoern A. Zeeb 	/* adjust offset randomly to avoid beacon conflict */
4472e2340276SBjoern A. Zeeb 	offset = offset - offset / 4 + get_random_u32() % (offset / 2);
4473e2340276SBjoern A. Zeeb 	rtw89_mac_port_tsf_sync(rtwdev, rtwvif, rtwvif_src,
4474e2340276SBjoern A. Zeeb 				(*n_offset) * offset);
4475e2340276SBjoern A. Zeeb 
4476e2340276SBjoern A. Zeeb 	(*n_offset)++;
4477e2340276SBjoern A. Zeeb }
4478e2340276SBjoern A. Zeeb 
4479e2340276SBjoern A. Zeeb static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev)
4480e2340276SBjoern A. Zeeb {
4481e2340276SBjoern A. Zeeb 	struct rtw89_vif *src = NULL, *tmp;
4482e2340276SBjoern A. Zeeb 	u8 offset = 100, vif_aps = 0;
4483e2340276SBjoern A. Zeeb 	int n_offset = 1;
4484e2340276SBjoern A. Zeeb 
4485e2340276SBjoern A. Zeeb 	rtw89_for_each_rtwvif(rtwdev, tmp) {
4486e2340276SBjoern A. Zeeb 		if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA)
4487e2340276SBjoern A. Zeeb 			src = tmp;
4488e2340276SBjoern A. Zeeb 		if (tmp->net_type == RTW89_NET_TYPE_AP_MODE)
4489e2340276SBjoern A. Zeeb 			vif_aps++;
4490e2340276SBjoern A. Zeeb 	}
4491e2340276SBjoern A. Zeeb 
4492e2340276SBjoern A. Zeeb 	if (vif_aps == 0)
4493e2340276SBjoern A. Zeeb 		return;
4494e2340276SBjoern A. Zeeb 
4495e2340276SBjoern A. Zeeb 	offset /= (vif_aps + 1);
4496e2340276SBjoern A. Zeeb 
4497e2340276SBjoern A. Zeeb 	rtw89_for_each_rtwvif(rtwdev, tmp)
4498e2340276SBjoern A. Zeeb 		rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, &n_offset);
4499e2340276SBjoern A. Zeeb }
4500e2340276SBjoern A. Zeeb 
45018e93258fSBjoern A. Zeeb int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
45028e93258fSBjoern A. Zeeb {
45038e93258fSBjoern A. Zeeb 	int ret;
45048e93258fSBjoern A. Zeeb 
45058e93258fSBjoern A. Zeeb 	ret = rtw89_mac_port_update(rtwdev, rtwvif);
45068e93258fSBjoern A. Zeeb 	if (ret)
45078e93258fSBjoern A. Zeeb 		return ret;
45088e93258fSBjoern A. Zeeb 
45098e93258fSBjoern A. Zeeb 	rtw89_mac_dmac_tbl_init(rtwdev, rtwvif->mac_id);
45108e93258fSBjoern A. Zeeb 	rtw89_mac_cmac_tbl_init(rtwdev, rtwvif->mac_id);
45118e93258fSBjoern A. Zeeb 
45128e93258fSBjoern A. Zeeb 	ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif->mac_id, false);
45138e93258fSBjoern A. Zeeb 	if (ret)
45148e93258fSBjoern A. Zeeb 		return ret;
45158e93258fSBjoern A. Zeeb 
45168e93258fSBjoern A. Zeeb 	ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_CREATE);
45178e93258fSBjoern A. Zeeb 	if (ret)
45188e93258fSBjoern A. Zeeb 		return ret;
45198e93258fSBjoern A. Zeeb 
4520e2340276SBjoern A. Zeeb 	ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
4521e2340276SBjoern A. Zeeb 	if (ret)
4522e2340276SBjoern A. Zeeb 		return ret;
4523e2340276SBjoern A. Zeeb 
45248e93258fSBjoern A. Zeeb 	ret = rtw89_cam_init(rtwdev, rtwvif);
45258e93258fSBjoern A. Zeeb 	if (ret)
45268e93258fSBjoern A. Zeeb 		return ret;
45278e93258fSBjoern A. Zeeb 
45288e93258fSBjoern A. Zeeb 	ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
45298e93258fSBjoern A. Zeeb 	if (ret)
45308e93258fSBjoern A. Zeeb 		return ret;
45318e93258fSBjoern A. Zeeb 
4532*6d67aabdSBjoern A. Zeeb 	ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif, NULL);
4533*6d67aabdSBjoern A. Zeeb 	if (ret)
4534*6d67aabdSBjoern A. Zeeb 		return ret;
4535*6d67aabdSBjoern A. Zeeb 
4536*6d67aabdSBjoern A. Zeeb 	ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif, NULL);
45378e93258fSBjoern A. Zeeb 	if (ret)
45388e93258fSBjoern A. Zeeb 		return ret;
45398e93258fSBjoern A. Zeeb 
45408e93258fSBjoern A. Zeeb 	return 0;
45418e93258fSBjoern A. Zeeb }
45428e93258fSBjoern A. Zeeb 
45438e93258fSBjoern A. Zeeb int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
45448e93258fSBjoern A. Zeeb {
45458e93258fSBjoern A. Zeeb 	int ret;
45468e93258fSBjoern A. Zeeb 
45478e93258fSBjoern A. Zeeb 	ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_REMOVE);
45488e93258fSBjoern A. Zeeb 	if (ret)
45498e93258fSBjoern A. Zeeb 		return ret;
45508e93258fSBjoern A. Zeeb 
45518e93258fSBjoern A. Zeeb 	rtw89_cam_deinit(rtwdev, rtwvif);
45528e93258fSBjoern A. Zeeb 
45538e93258fSBjoern A. Zeeb 	ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL);
45548e93258fSBjoern A. Zeeb 	if (ret)
45558e93258fSBjoern A. Zeeb 		return ret;
45568e93258fSBjoern A. Zeeb 
45578e93258fSBjoern A. Zeeb 	return 0;
45588e93258fSBjoern A. Zeeb }
45598e93258fSBjoern A. Zeeb 
45608e93258fSBjoern A. Zeeb int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
45618e93258fSBjoern A. Zeeb {
45628e93258fSBjoern A. Zeeb 	u8 port = rtwvif->port;
45638e93258fSBjoern A. Zeeb 
45648e93258fSBjoern A. Zeeb 	if (port >= RTW89_PORT_NUM)
45658e93258fSBjoern A. Zeeb 		return -EINVAL;
45668e93258fSBjoern A. Zeeb 
45678e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif);
45688e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_tx_rpt(rtwdev, rtwvif, false);
45698e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_rx_rpt(rtwdev, rtwvif, false);
45708e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_net_type(rtwdev, rtwvif);
45718e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif);
45728e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif);
4573*6d67aabdSBjoern A. Zeeb 	rtw89_mac_port_cfg_rx_sync_by_nettype(rtwdev, rtwvif);
4574*6d67aabdSBjoern A. Zeeb 	rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif);
45758e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif);
45768e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif);
45778e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif);
45788e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif);
45798e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif);
45808e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif);
45818e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif);
45828e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif);
45838e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif);
45848e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif);
45858e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif);
4586e2340276SBjoern A. Zeeb 	rtw89_mac_port_cfg_func_en(rtwdev, rtwvif, true);
4587e2340276SBjoern A. Zeeb 	rtw89_mac_port_tsf_resync_all(rtwdev);
45888e93258fSBjoern A. Zeeb 	fsleep(BCN_ERLY_SET_DLY);
45898e93258fSBjoern A. Zeeb 	rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif);
45908e93258fSBjoern A. Zeeb 
45918e93258fSBjoern A. Zeeb 	return 0;
45928e93258fSBjoern A. Zeeb }
45938e93258fSBjoern A. Zeeb 
4594e2340276SBjoern A. Zeeb int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
4595e2340276SBjoern A. Zeeb 			   u64 *tsf)
4596e2340276SBjoern A. Zeeb {
4597*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4598*6d67aabdSBjoern A. Zeeb 	const struct rtw89_port_reg *p = mac->port_base;
4599e2340276SBjoern A. Zeeb 	u32 tsf_low, tsf_high;
4600e2340276SBjoern A. Zeeb 	int ret;
4601e2340276SBjoern A. Zeeb 
4602e2340276SBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, rtwvif->mac_idx, RTW89_CMAC_SEL);
4603e2340276SBjoern A. Zeeb 	if (ret)
4604e2340276SBjoern A. Zeeb 		return ret;
4605e2340276SBjoern A. Zeeb 
4606e2340276SBjoern A. Zeeb 	tsf_low = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_l);
4607e2340276SBjoern A. Zeeb 	tsf_high = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_h);
4608e2340276SBjoern A. Zeeb 	*tsf = (u64)tsf_high << 32 | tsf_low;
4609e2340276SBjoern A. Zeeb 
4610e2340276SBjoern A. Zeeb 	return 0;
4611e2340276SBjoern A. Zeeb }
4612e2340276SBjoern A. Zeeb 
4613e2340276SBjoern A. Zeeb static void rtw89_mac_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
4614e2340276SBjoern A. Zeeb 						      struct cfg80211_bss *bss,
4615e2340276SBjoern A. Zeeb 						      void *data)
4616e2340276SBjoern A. Zeeb {
4617e2340276SBjoern A. Zeeb 	const struct cfg80211_bss_ies *ies;
4618e2340276SBjoern A. Zeeb 	const struct element *elem;
4619e2340276SBjoern A. Zeeb 	bool *tolerated = data;
4620e2340276SBjoern A. Zeeb 
4621e2340276SBjoern A. Zeeb 	rcu_read_lock();
4622e2340276SBjoern A. Zeeb 	ies = rcu_dereference(bss->ies);
4623e2340276SBjoern A. Zeeb 	elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, ies->data,
4624e2340276SBjoern A. Zeeb 				  ies->len);
4625e2340276SBjoern A. Zeeb 
4626e2340276SBjoern A. Zeeb 	if (!elem || elem->datalen < 10 ||
4627e2340276SBjoern A. Zeeb 	    !(elem->data[10] & WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT))
4628e2340276SBjoern A. Zeeb 		*tolerated = false;
4629e2340276SBjoern A. Zeeb 	rcu_read_unlock();
4630e2340276SBjoern A. Zeeb }
4631e2340276SBjoern A. Zeeb 
4632e2340276SBjoern A. Zeeb void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
4633e2340276SBjoern A. Zeeb 					struct ieee80211_vif *vif)
4634e2340276SBjoern A. Zeeb {
4635e2340276SBjoern A. Zeeb 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
4636*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
4637e2340276SBjoern A. Zeeb 	struct ieee80211_hw *hw = rtwdev->hw;
4638e2340276SBjoern A. Zeeb 	bool tolerated = true;
4639e2340276SBjoern A. Zeeb 	u32 reg;
4640e2340276SBjoern A. Zeeb 
4641e2340276SBjoern A. Zeeb 	if (!vif->bss_conf.he_support || vif->type != NL80211_IFTYPE_STATION)
4642e2340276SBjoern A. Zeeb 		return;
4643e2340276SBjoern A. Zeeb 
4644*6d67aabdSBjoern A. Zeeb 	if (!(vif->bss_conf.chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR))
4645e2340276SBjoern A. Zeeb 		return;
4646e2340276SBjoern A. Zeeb 
4647*6d67aabdSBjoern A. Zeeb 	cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chanreq.oper,
4648e2340276SBjoern A. Zeeb 			  rtw89_mac_check_he_obss_narrow_bw_ru_iter,
4649e2340276SBjoern A. Zeeb 			  &tolerated);
4650e2340276SBjoern A. Zeeb 
4651*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, mac->narrow_bw_ru_dis.addr,
4652*6d67aabdSBjoern A. Zeeb 				   rtwvif->mac_idx);
4653e2340276SBjoern A. Zeeb 	if (tolerated)
4654*6d67aabdSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, reg, mac->narrow_bw_ru_dis.mask);
4655e2340276SBjoern A. Zeeb 	else
4656*6d67aabdSBjoern A. Zeeb 		rtw89_write32_set(rtwdev, reg, mac->narrow_bw_ru_dis.mask);
4657e2340276SBjoern A. Zeeb }
4658e2340276SBjoern A. Zeeb 
4659e2340276SBjoern A. Zeeb void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
4660e2340276SBjoern A. Zeeb {
4661*6d67aabdSBjoern A. Zeeb 	rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif);
4662e2340276SBjoern A. Zeeb }
4663e2340276SBjoern A. Zeeb 
46648e93258fSBjoern A. Zeeb int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
46658e93258fSBjoern A. Zeeb {
46668e93258fSBjoern A. Zeeb 	int ret;
46678e93258fSBjoern A. Zeeb 
4668*6d67aabdSBjoern A. Zeeb 	rtwvif->mac_id = rtw89_acquire_mac_id(rtwdev);
46698e93258fSBjoern A. Zeeb 	if (rtwvif->mac_id == RTW89_MAX_MAC_ID_NUM)
46708e93258fSBjoern A. Zeeb 		return -ENOSPC;
46718e93258fSBjoern A. Zeeb 
46728e93258fSBjoern A. Zeeb 	ret = rtw89_mac_vif_init(rtwdev, rtwvif);
46738e93258fSBjoern A. Zeeb 	if (ret)
46748e93258fSBjoern A. Zeeb 		goto release_mac_id;
46758e93258fSBjoern A. Zeeb 
46768e93258fSBjoern A. Zeeb 	return 0;
46778e93258fSBjoern A. Zeeb 
46788e93258fSBjoern A. Zeeb release_mac_id:
4679*6d67aabdSBjoern A. Zeeb 	rtw89_release_mac_id(rtwdev, rtwvif->mac_id);
46808e93258fSBjoern A. Zeeb 
46818e93258fSBjoern A. Zeeb 	return ret;
46828e93258fSBjoern A. Zeeb }
46838e93258fSBjoern A. Zeeb 
46848e93258fSBjoern A. Zeeb int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
46858e93258fSBjoern A. Zeeb {
46868e93258fSBjoern A. Zeeb 	int ret;
46878e93258fSBjoern A. Zeeb 
46888e93258fSBjoern A. Zeeb 	ret = rtw89_mac_vif_deinit(rtwdev, rtwvif);
4689*6d67aabdSBjoern A. Zeeb 	rtw89_release_mac_id(rtwdev, rtwvif->mac_id);
46908e93258fSBjoern A. Zeeb 
46918e93258fSBjoern A. Zeeb 	return ret;
46928e93258fSBjoern A. Zeeb }
46938e93258fSBjoern A. Zeeb 
46948e93258fSBjoern A. Zeeb static void
46958e93258fSBjoern A. Zeeb rtw89_mac_c2h_macid_pause(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
46968e93258fSBjoern A. Zeeb {
46978e93258fSBjoern A. Zeeb }
46988e93258fSBjoern A. Zeeb 
46998e93258fSBjoern A. Zeeb static bool rtw89_is_op_chan(struct rtw89_dev *rtwdev, u8 band, u8 channel)
47008e93258fSBjoern A. Zeeb {
4701e2340276SBjoern A. Zeeb 	const struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
47028e93258fSBjoern A. Zeeb 
4703e2340276SBjoern A. Zeeb 	return band == op->band_type && channel == op->primary_channel;
47048e93258fSBjoern A. Zeeb }
47058e93258fSBjoern A. Zeeb 
47068e93258fSBjoern A. Zeeb static void
4707*6d67aabdSBjoern A. Zeeb rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
47088e93258fSBjoern A. Zeeb 			   u32 len)
47098e93258fSBjoern A. Zeeb {
4710*6d67aabdSBjoern A. Zeeb 	const struct rtw89_c2h_scanofld *c2h =
4711*6d67aabdSBjoern A. Zeeb 		(const struct rtw89_c2h_scanofld *)skb->data;
47128e93258fSBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
4713e2340276SBjoern A. Zeeb 	struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
47148e93258fSBjoern A. Zeeb 	struct rtw89_chan new;
4715*6d67aabdSBjoern A. Zeeb 	u8 reason, status, tx_fail, band, actual_period, expect_period;
4716*6d67aabdSBjoern A. Zeeb 	u32 last_chan = rtwdev->scan_info.last_chan_idx, report_tsf;
4717*6d67aabdSBjoern A. Zeeb 	u8 mac_idx, sw_def, fw_def;
47188e93258fSBjoern A. Zeeb 	u16 chan;
4719e2340276SBjoern A. Zeeb 	int ret;
4720e2340276SBjoern A. Zeeb 
4721e2340276SBjoern A. Zeeb 	if (!rtwvif)
4722e2340276SBjoern A. Zeeb 		return;
47238e93258fSBjoern A. Zeeb 
4724*6d67aabdSBjoern A. Zeeb 	tx_fail = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_TX_FAIL);
4725*6d67aabdSBjoern A. Zeeb 	status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS);
4726*6d67aabdSBjoern A. Zeeb 	chan = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_PRI_CH);
4727*6d67aabdSBjoern A. Zeeb 	reason = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_RSN);
4728*6d67aabdSBjoern A. Zeeb 	band = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_BAND);
4729*6d67aabdSBjoern A. Zeeb 	actual_period = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_PERIOD);
4730*6d67aabdSBjoern A. Zeeb 	mac_idx = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_MAC_IDX);
4731*6d67aabdSBjoern A. Zeeb 
47328e93258fSBjoern A. Zeeb 
47338e93258fSBjoern A. Zeeb 	if (!(rtwdev->chip->support_bands & BIT(NL80211_BAND_6GHZ)))
47348e93258fSBjoern A. Zeeb 		band = chan > 14 ? RTW89_BAND_5G : RTW89_BAND_2G;
47358e93258fSBjoern A. Zeeb 
47368e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN,
4737*6d67aabdSBjoern A. Zeeb 		    "mac_idx[%d] band: %d, chan: %d, reason: %d, status: %d, tx_fail: %d, actual: %d\n",
4738*6d67aabdSBjoern A. Zeeb 		    mac_idx, band, chan, reason, status, tx_fail, actual_period);
4739*6d67aabdSBjoern A. Zeeb 
4740*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) {
4741*6d67aabdSBjoern A. Zeeb 		sw_def = le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_SW_DEF);
4742*6d67aabdSBjoern A. Zeeb 		expect_period = le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_EXPECT_PERIOD);
4743*6d67aabdSBjoern A. Zeeb 		fw_def = le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_FW_DEF);
4744*6d67aabdSBjoern A. Zeeb 		report_tsf = le32_get_bits(c2h->w7, RTW89_C2H_SCANOFLD_W7_REPORT_TSF);
4745*6d67aabdSBjoern A. Zeeb 
4746*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN,
4747*6d67aabdSBjoern A. Zeeb 			    "sw_def: %d, fw_def: %d, tsf: %x, expect: %d\n",
4748*6d67aabdSBjoern A. Zeeb 			    sw_def, fw_def, report_tsf, expect_period);
4749*6d67aabdSBjoern A. Zeeb 	}
47508e93258fSBjoern A. Zeeb 
47518e93258fSBjoern A. Zeeb 	switch (reason) {
4752*6d67aabdSBjoern A. Zeeb 	case RTW89_SCAN_LEAVE_OP_NOTIFY:
47538e93258fSBjoern A. Zeeb 	case RTW89_SCAN_LEAVE_CH_NOTIFY:
4754*6d67aabdSBjoern A. Zeeb 		if (rtw89_is_op_chan(rtwdev, band, chan)) {
4755*6d67aabdSBjoern A. Zeeb 			rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, false);
47568e93258fSBjoern A. Zeeb 			ieee80211_stop_queues(rtwdev->hw);
4757*6d67aabdSBjoern A. Zeeb 		}
47588e93258fSBjoern A. Zeeb 		return;
47598e93258fSBjoern A. Zeeb 	case RTW89_SCAN_END_SCAN_NOTIFY:
4760*6d67aabdSBjoern A. Zeeb 		if (rtwdev->scan_info.abort)
4761*6d67aabdSBjoern A. Zeeb 			return;
4762*6d67aabdSBjoern A. Zeeb 
4763e2340276SBjoern A. Zeeb 		if (rtwvif && rtwvif->scan_req &&
4764e2340276SBjoern A. Zeeb 		    last_chan < rtwvif->scan_req->n_channels) {
4765e2340276SBjoern A. Zeeb 			ret = rtw89_hw_scan_offload(rtwdev, vif, true);
4766e2340276SBjoern A. Zeeb 			if (ret) {
4767e2340276SBjoern A. Zeeb 				rtw89_hw_scan_abort(rtwdev, vif);
4768e2340276SBjoern A. Zeeb 				rtw89_warn(rtwdev, "HW scan failed: %d\n", ret);
4769e2340276SBjoern A. Zeeb 			}
4770e2340276SBjoern A. Zeeb 		} else {
47718e93258fSBjoern A. Zeeb 			rtw89_hw_scan_complete(rtwdev, vif, false);
4772e2340276SBjoern A. Zeeb 		}
47738e93258fSBjoern A. Zeeb 		break;
4774*6d67aabdSBjoern A. Zeeb 	case RTW89_SCAN_ENTER_OP_NOTIFY:
47758e93258fSBjoern A. Zeeb 	case RTW89_SCAN_ENTER_CH_NOTIFY:
47768e93258fSBjoern A. Zeeb 		if (rtw89_is_op_chan(rtwdev, band, chan)) {
4777e2340276SBjoern A. Zeeb 			rtw89_assign_entity_chan(rtwdev, rtwvif->sub_entity_idx,
4778e2340276SBjoern A. Zeeb 						 &rtwdev->scan_info.op_chan);
4779*6d67aabdSBjoern A. Zeeb 			rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true);
47808e93258fSBjoern A. Zeeb 			ieee80211_wake_queues(rtwdev->hw);
4781e2340276SBjoern A. Zeeb 		} else {
4782e2340276SBjoern A. Zeeb 			rtw89_chan_create(&new, chan, chan, band,
4783e2340276SBjoern A. Zeeb 					  RTW89_CHANNEL_WIDTH_20);
4784e2340276SBjoern A. Zeeb 			rtw89_assign_entity_chan(rtwdev, rtwvif->sub_entity_idx,
4785e2340276SBjoern A. Zeeb 						 &new);
47868e93258fSBjoern A. Zeeb 		}
47878e93258fSBjoern A. Zeeb 		break;
47888e93258fSBjoern A. Zeeb 	default:
47898e93258fSBjoern A. Zeeb 		return;
47908e93258fSBjoern A. Zeeb 	}
47918e93258fSBjoern A. Zeeb }
47928e93258fSBjoern A. Zeeb 
47938e93258fSBjoern A. Zeeb static void
4794e2340276SBjoern A. Zeeb rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
4795e2340276SBjoern A. Zeeb 		       struct sk_buff *skb)
4796e2340276SBjoern A. Zeeb {
4797e2340276SBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif);
4798e2340276SBjoern A. Zeeb 	enum nl80211_cqm_rssi_threshold_event nl_event;
4799e2340276SBjoern A. Zeeb 	const struct rtw89_c2h_mac_bcnfltr_rpt *c2h =
4800e2340276SBjoern A. Zeeb 		(const struct rtw89_c2h_mac_bcnfltr_rpt *)skb->data;
4801e2340276SBjoern A. Zeeb 	u8 type, event, mac_id;
4802e2340276SBjoern A. Zeeb 	s8 sig;
4803e2340276SBjoern A. Zeeb 
4804e2340276SBjoern A. Zeeb 	type = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_TYPE);
4805e2340276SBjoern A. Zeeb 	sig = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_MA) - MAX_RSSI;
4806e2340276SBjoern A. Zeeb 	event = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_EVENT);
4807e2340276SBjoern A. Zeeb 	mac_id = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_MACID);
4808e2340276SBjoern A. Zeeb 
4809e2340276SBjoern A. Zeeb 	if (mac_id != rtwvif->mac_id)
4810e2340276SBjoern A. Zeeb 		return;
4811e2340276SBjoern A. Zeeb 
4812e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_FW,
4813e2340276SBjoern A. Zeeb 		    "C2H bcnfltr rpt macid: %d, type: %d, ma: %d, event: %d\n",
4814e2340276SBjoern A. Zeeb 		    mac_id, type, sig, event);
4815e2340276SBjoern A. Zeeb 
4816e2340276SBjoern A. Zeeb 	switch (type) {
4817e2340276SBjoern A. Zeeb 	case RTW89_BCN_FLTR_BEACON_LOSS:
4818e2340276SBjoern A. Zeeb 		if (!rtwdev->scanning && !rtwvif->offchan)
4819e2340276SBjoern A. Zeeb 			ieee80211_connection_loss(vif);
4820e2340276SBjoern A. Zeeb 		else
4821e2340276SBjoern A. Zeeb 			rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true);
4822e2340276SBjoern A. Zeeb 		return;
4823e2340276SBjoern A. Zeeb 	case RTW89_BCN_FLTR_NOTIFY:
4824e2340276SBjoern A. Zeeb 		nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
4825e2340276SBjoern A. Zeeb 		break;
4826e2340276SBjoern A. Zeeb 	case RTW89_BCN_FLTR_RSSI:
4827e2340276SBjoern A. Zeeb 		if (event == RTW89_BCN_FLTR_RSSI_LOW)
4828e2340276SBjoern A. Zeeb 			nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
4829e2340276SBjoern A. Zeeb 		else if (event == RTW89_BCN_FLTR_RSSI_HIGH)
4830e2340276SBjoern A. Zeeb 			nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
4831e2340276SBjoern A. Zeeb 		else
4832e2340276SBjoern A. Zeeb 			return;
4833e2340276SBjoern A. Zeeb 		break;
4834e2340276SBjoern A. Zeeb 	default:
4835e2340276SBjoern A. Zeeb 		return;
4836e2340276SBjoern A. Zeeb 	}
4837e2340276SBjoern A. Zeeb 
4838e2340276SBjoern A. Zeeb 	ieee80211_cqm_rssi_notify(vif, nl_event, sig, GFP_KERNEL);
4839e2340276SBjoern A. Zeeb }
4840e2340276SBjoern A. Zeeb 
4841e2340276SBjoern A. Zeeb static void
4842e2340276SBjoern A. Zeeb rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
4843e2340276SBjoern A. Zeeb 			   u32 len)
4844e2340276SBjoern A. Zeeb {
4845e2340276SBjoern A. Zeeb 	struct rtw89_vif *rtwvif;
4846e2340276SBjoern A. Zeeb 
4847e2340276SBjoern A. Zeeb 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
4848e2340276SBjoern A. Zeeb 		rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif, c2h);
4849e2340276SBjoern A. Zeeb }
4850e2340276SBjoern A. Zeeb 
4851e2340276SBjoern A. Zeeb static void
48528e93258fSBjoern A. Zeeb rtw89_mac_c2h_rec_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
48538e93258fSBjoern A. Zeeb {
4854e2340276SBjoern A. Zeeb 	/* N.B. This will run in interrupt context. */
4855e2340276SBjoern A. Zeeb 
48568e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_FW,
48578e93258fSBjoern A. Zeeb 		    "C2H rev ack recv, cat: %d, class: %d, func: %d, seq : %d\n",
48588e93258fSBjoern A. Zeeb 		    RTW89_GET_MAC_C2H_REV_ACK_CAT(c2h->data),
48598e93258fSBjoern A. Zeeb 		    RTW89_GET_MAC_C2H_REV_ACK_CLASS(c2h->data),
48608e93258fSBjoern A. Zeeb 		    RTW89_GET_MAC_C2H_REV_ACK_FUNC(c2h->data),
48618e93258fSBjoern A. Zeeb 		    RTW89_GET_MAC_C2H_REV_ACK_H2C_SEQ(c2h->data));
48628e93258fSBjoern A. Zeeb }
48638e93258fSBjoern A. Zeeb 
48648e93258fSBjoern A. Zeeb static void
4865e2340276SBjoern A. Zeeb rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len)
48668e93258fSBjoern A. Zeeb {
4867e2340276SBjoern A. Zeeb 	/* N.B. This will run in interrupt context. */
4868e2340276SBjoern A. Zeeb 	struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait;
4869e2340276SBjoern A. Zeeb 	const struct rtw89_c2h_done_ack *c2h =
4870e2340276SBjoern A. Zeeb 		(const struct rtw89_c2h_done_ack *)skb_c2h->data;
4871e2340276SBjoern A. Zeeb 	u8 h2c_cat = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_CAT);
4872e2340276SBjoern A. Zeeb 	u8 h2c_class = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_CLASS);
4873e2340276SBjoern A. Zeeb 	u8 h2c_func = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_FUNC);
4874e2340276SBjoern A. Zeeb 	u8 h2c_return = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_H2C_RETURN);
4875e2340276SBjoern A. Zeeb 	u8 h2c_seq = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_H2C_SEQ);
4876e2340276SBjoern A. Zeeb 	struct rtw89_completion_data data = {};
4877e2340276SBjoern A. Zeeb 	unsigned int cond;
4878e2340276SBjoern A. Zeeb 
48798e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_FW,
48808e93258fSBjoern A. Zeeb 		    "C2H done ack recv, cat: %d, class: %d, func: %d, ret: %d, seq : %d\n",
4881e2340276SBjoern A. Zeeb 		    h2c_cat, h2c_class, h2c_func, h2c_return, h2c_seq);
4882e2340276SBjoern A. Zeeb 
4883e2340276SBjoern A. Zeeb 	if (h2c_cat != H2C_CAT_MAC)
4884e2340276SBjoern A. Zeeb 		return;
4885e2340276SBjoern A. Zeeb 
4886e2340276SBjoern A. Zeeb 	switch (h2c_class) {
4887e2340276SBjoern A. Zeeb 	default:
4888e2340276SBjoern A. Zeeb 		return;
4889e2340276SBjoern A. Zeeb 	case H2C_CL_MAC_FW_OFLD:
4890e2340276SBjoern A. Zeeb 		switch (h2c_func) {
4891e2340276SBjoern A. Zeeb 		default:
4892e2340276SBjoern A. Zeeb 			return;
4893e2340276SBjoern A. Zeeb 		case H2C_FUNC_ADD_SCANOFLD_CH:
4894*6d67aabdSBjoern A. Zeeb 			cond = RTW89_SCANOFLD_WAIT_COND_ADD_CH;
4895*6d67aabdSBjoern A. Zeeb 			break;
4896e2340276SBjoern A. Zeeb 		case H2C_FUNC_SCANOFLD:
4897*6d67aabdSBjoern A. Zeeb 			cond = RTW89_SCANOFLD_WAIT_COND_START;
4898*6d67aabdSBjoern A. Zeeb 			break;
4899*6d67aabdSBjoern A. Zeeb 		case H2C_FUNC_SCANOFLD_BE:
4900*6d67aabdSBjoern A. Zeeb 			cond = RTW89_SCANOFLD_BE_WAIT_COND_START;
4901e2340276SBjoern A. Zeeb 			break;
4902e2340276SBjoern A. Zeeb 		}
4903e2340276SBjoern A. Zeeb 
4904e2340276SBjoern A. Zeeb 		data.err = !!h2c_return;
4905e2340276SBjoern A. Zeeb 		rtw89_complete_cond(fw_ofld_wait, cond, &data);
4906e2340276SBjoern A. Zeeb 		return;
4907e2340276SBjoern A. Zeeb 	}
49088e93258fSBjoern A. Zeeb }
49098e93258fSBjoern A. Zeeb 
49108e93258fSBjoern A. Zeeb static void
49118e93258fSBjoern A. Zeeb rtw89_mac_c2h_log(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
49128e93258fSBjoern A. Zeeb {
4913e2340276SBjoern A. Zeeb 	rtw89_fw_log_dump(rtwdev, c2h->data, len);
49148e93258fSBjoern A. Zeeb }
49158e93258fSBjoern A. Zeeb 
49168e93258fSBjoern A. Zeeb static void
49178e93258fSBjoern A. Zeeb rtw89_mac_c2h_bcn_cnt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
49188e93258fSBjoern A. Zeeb {
49198e93258fSBjoern A. Zeeb }
49208e93258fSBjoern A. Zeeb 
49218e93258fSBjoern A. Zeeb static void
4922e2340276SBjoern A. Zeeb rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h,
49238e93258fSBjoern A. Zeeb 			   u32 len)
49248e93258fSBjoern A. Zeeb {
4925e2340276SBjoern A. Zeeb 	struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
4926e2340276SBjoern A. Zeeb 	const struct rtw89_c2h_pkt_ofld_rsp *c2h =
4927e2340276SBjoern A. Zeeb 		(const struct rtw89_c2h_pkt_ofld_rsp *)skb_c2h->data;
4928e2340276SBjoern A. Zeeb 	u16 pkt_len = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_LEN);
4929e2340276SBjoern A. Zeeb 	u8 pkt_id = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_ID);
4930e2340276SBjoern A. Zeeb 	u8 pkt_op = le32_get_bits(c2h->w2, RTW89_C2H_PKT_OFLD_RSP_W2_PTK_OP);
4931e2340276SBjoern A. Zeeb 	struct rtw89_completion_data data = {};
4932e2340276SBjoern A. Zeeb 	unsigned int cond;
4933e2340276SBjoern A. Zeeb 
4934e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_FW, "pkt ofld rsp: id %d op %d len %d\n",
4935e2340276SBjoern A. Zeeb 		    pkt_id, pkt_op, pkt_len);
4936e2340276SBjoern A. Zeeb 
4937e2340276SBjoern A. Zeeb 	data.err = !pkt_len;
4938e2340276SBjoern A. Zeeb 	cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(pkt_id, pkt_op);
4939e2340276SBjoern A. Zeeb 
4940e2340276SBjoern A. Zeeb 	rtw89_complete_cond(wait, cond, &data);
4941e2340276SBjoern A. Zeeb }
4942e2340276SBjoern A. Zeeb 
4943e2340276SBjoern A. Zeeb static void
4944e2340276SBjoern A. Zeeb rtw89_mac_c2h_tsf32_toggle_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
4945e2340276SBjoern A. Zeeb 			       u32 len)
4946e2340276SBjoern A. Zeeb {
4947*6d67aabdSBjoern A. Zeeb 	rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_TSF32_TOGGLE_CHANGE);
4948e2340276SBjoern A. Zeeb }
4949e2340276SBjoern A. Zeeb 
4950e2340276SBjoern A. Zeeb static void
4951e2340276SBjoern A. Zeeb rtw89_mac_c2h_mcc_rcv_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
4952e2340276SBjoern A. Zeeb {
4953e2340276SBjoern A. Zeeb 	u8 group = RTW89_GET_MAC_C2H_MCC_RCV_ACK_GROUP(c2h->data);
4954e2340276SBjoern A. Zeeb 	u8 func = RTW89_GET_MAC_C2H_MCC_RCV_ACK_H2C_FUNC(c2h->data);
4955e2340276SBjoern A. Zeeb 
4956e2340276SBjoern A. Zeeb 	switch (func) {
4957e2340276SBjoern A. Zeeb 	case H2C_FUNC_ADD_MCC:
4958e2340276SBjoern A. Zeeb 	case H2C_FUNC_START_MCC:
4959e2340276SBjoern A. Zeeb 	case H2C_FUNC_STOP_MCC:
4960e2340276SBjoern A. Zeeb 	case H2C_FUNC_DEL_MCC_GROUP:
4961e2340276SBjoern A. Zeeb 	case H2C_FUNC_RESET_MCC_GROUP:
4962e2340276SBjoern A. Zeeb 	case H2C_FUNC_MCC_REQ_TSF:
4963e2340276SBjoern A. Zeeb 	case H2C_FUNC_MCC_MACID_BITMAP:
4964e2340276SBjoern A. Zeeb 	case H2C_FUNC_MCC_SYNC:
4965e2340276SBjoern A. Zeeb 	case H2C_FUNC_MCC_SET_DURATION:
4966e2340276SBjoern A. Zeeb 		break;
4967e2340276SBjoern A. Zeeb 	default:
4968e2340276SBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
4969e2340276SBjoern A. Zeeb 			    "invalid MCC C2H RCV ACK: func %d\n", func);
4970e2340276SBjoern A. Zeeb 		return;
4971e2340276SBjoern A. Zeeb 	}
4972e2340276SBjoern A. Zeeb 
4973e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
4974e2340276SBjoern A. Zeeb 		    "MCC C2H RCV ACK: group %d, func %d\n", group, func);
4975e2340276SBjoern A. Zeeb }
4976e2340276SBjoern A. Zeeb 
4977e2340276SBjoern A. Zeeb static void
4978e2340276SBjoern A. Zeeb rtw89_mac_c2h_mcc_req_ack(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
4979e2340276SBjoern A. Zeeb {
4980e2340276SBjoern A. Zeeb 	u8 group = RTW89_GET_MAC_C2H_MCC_REQ_ACK_GROUP(c2h->data);
4981e2340276SBjoern A. Zeeb 	u8 func = RTW89_GET_MAC_C2H_MCC_REQ_ACK_H2C_FUNC(c2h->data);
4982e2340276SBjoern A. Zeeb 	u8 retcode = RTW89_GET_MAC_C2H_MCC_REQ_ACK_H2C_RETURN(c2h->data);
4983e2340276SBjoern A. Zeeb 	struct rtw89_completion_data data = {};
4984e2340276SBjoern A. Zeeb 	unsigned int cond;
4985e2340276SBjoern A. Zeeb 	bool next = false;
4986e2340276SBjoern A. Zeeb 
4987e2340276SBjoern A. Zeeb 	switch (func) {
4988e2340276SBjoern A. Zeeb 	case H2C_FUNC_MCC_REQ_TSF:
4989e2340276SBjoern A. Zeeb 		next = true;
4990e2340276SBjoern A. Zeeb 		break;
4991e2340276SBjoern A. Zeeb 	case H2C_FUNC_MCC_MACID_BITMAP:
4992e2340276SBjoern A. Zeeb 	case H2C_FUNC_MCC_SYNC:
4993e2340276SBjoern A. Zeeb 	case H2C_FUNC_MCC_SET_DURATION:
4994e2340276SBjoern A. Zeeb 		break;
4995e2340276SBjoern A. Zeeb 	case H2C_FUNC_ADD_MCC:
4996e2340276SBjoern A. Zeeb 	case H2C_FUNC_START_MCC:
4997e2340276SBjoern A. Zeeb 	case H2C_FUNC_STOP_MCC:
4998e2340276SBjoern A. Zeeb 	case H2C_FUNC_DEL_MCC_GROUP:
4999e2340276SBjoern A. Zeeb 	case H2C_FUNC_RESET_MCC_GROUP:
5000e2340276SBjoern A. Zeeb 	default:
5001e2340276SBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5002e2340276SBjoern A. Zeeb 			    "invalid MCC C2H REQ ACK: func %d\n", func);
5003e2340276SBjoern A. Zeeb 		return;
5004e2340276SBjoern A. Zeeb 	}
5005e2340276SBjoern A. Zeeb 
5006e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5007e2340276SBjoern A. Zeeb 		    "MCC C2H REQ ACK: group %d, func %d, return code %d\n",
5008e2340276SBjoern A. Zeeb 		    group, func, retcode);
5009e2340276SBjoern A. Zeeb 
5010e2340276SBjoern A. Zeeb 	if (!retcode && next)
5011e2340276SBjoern A. Zeeb 		return;
5012e2340276SBjoern A. Zeeb 
5013e2340276SBjoern A. Zeeb 	data.err = !!retcode;
5014e2340276SBjoern A. Zeeb 	cond = RTW89_MCC_WAIT_COND(group, func);
5015e2340276SBjoern A. Zeeb 	rtw89_complete_cond(&rtwdev->mcc.wait, cond, &data);
5016e2340276SBjoern A. Zeeb }
5017e2340276SBjoern A. Zeeb 
5018e2340276SBjoern A. Zeeb static void
5019e2340276SBjoern A. Zeeb rtw89_mac_c2h_mcc_tsf_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
5020e2340276SBjoern A. Zeeb {
5021e2340276SBjoern A. Zeeb 	u8 group = RTW89_GET_MAC_C2H_MCC_TSF_RPT_GROUP(c2h->data);
5022e2340276SBjoern A. Zeeb 	struct rtw89_completion_data data = {};
5023e2340276SBjoern A. Zeeb 	struct rtw89_mac_mcc_tsf_rpt *rpt;
5024e2340276SBjoern A. Zeeb 	unsigned int cond;
5025e2340276SBjoern A. Zeeb 
5026e2340276SBjoern A. Zeeb 	rpt = (struct rtw89_mac_mcc_tsf_rpt *)data.buf;
5027e2340276SBjoern A. Zeeb 	rpt->macid_x = RTW89_GET_MAC_C2H_MCC_TSF_RPT_MACID_X(c2h->data);
5028e2340276SBjoern A. Zeeb 	rpt->macid_y = RTW89_GET_MAC_C2H_MCC_TSF_RPT_MACID_Y(c2h->data);
5029e2340276SBjoern A. Zeeb 	rpt->tsf_x_low = RTW89_GET_MAC_C2H_MCC_TSF_RPT_TSF_LOW_X(c2h->data);
5030e2340276SBjoern A. Zeeb 	rpt->tsf_x_high = RTW89_GET_MAC_C2H_MCC_TSF_RPT_TSF_HIGH_X(c2h->data);
5031e2340276SBjoern A. Zeeb 	rpt->tsf_y_low = RTW89_GET_MAC_C2H_MCC_TSF_RPT_TSF_LOW_Y(c2h->data);
5032e2340276SBjoern A. Zeeb 	rpt->tsf_y_high = RTW89_GET_MAC_C2H_MCC_TSF_RPT_TSF_HIGH_Y(c2h->data);
5033e2340276SBjoern A. Zeeb 
5034e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5035e2340276SBjoern A. Zeeb #if defined(__linux__)
5036e2340276SBjoern A. Zeeb 		    "MCC C2H TSF RPT: macid %d> %llu, macid %d> %llu\n",
5037e2340276SBjoern A. Zeeb 		    rpt->macid_x, (u64)rpt->tsf_x_high << 32 | rpt->tsf_x_low,
5038e2340276SBjoern A. Zeeb 		    rpt->macid_y, (u64)rpt->tsf_y_high << 32 | rpt->tsf_y_low);
5039e2340276SBjoern A. Zeeb #elif defined(__FreeBSD__)
5040e2340276SBjoern A. Zeeb 		    "MCC C2H TSF RPT: macid %d> %ju, macid %d> %ju\n",
5041e2340276SBjoern A. Zeeb 		    rpt->macid_x, (uintmax_t)rpt->tsf_x_high << 32 | rpt->tsf_x_low,
5042e2340276SBjoern A. Zeeb 		    rpt->macid_y, (uintmax_t)rpt->tsf_y_high << 32 | rpt->tsf_y_low);
5043e2340276SBjoern A. Zeeb #endif
5044e2340276SBjoern A. Zeeb 
5045e2340276SBjoern A. Zeeb 	cond = RTW89_MCC_WAIT_COND(group, H2C_FUNC_MCC_REQ_TSF);
5046e2340276SBjoern A. Zeeb 	rtw89_complete_cond(&rtwdev->mcc.wait, cond, &data);
5047e2340276SBjoern A. Zeeb }
5048e2340276SBjoern A. Zeeb 
5049e2340276SBjoern A. Zeeb static void
5050e2340276SBjoern A. Zeeb rtw89_mac_c2h_mcc_status_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
5051e2340276SBjoern A. Zeeb {
5052e2340276SBjoern A. Zeeb 	u8 group = RTW89_GET_MAC_C2H_MCC_STATUS_RPT_GROUP(c2h->data);
5053e2340276SBjoern A. Zeeb 	u8 macid = RTW89_GET_MAC_C2H_MCC_STATUS_RPT_MACID(c2h->data);
5054e2340276SBjoern A. Zeeb 	u8 status = RTW89_GET_MAC_C2H_MCC_STATUS_RPT_STATUS(c2h->data);
5055e2340276SBjoern A. Zeeb 	u32 tsf_low = RTW89_GET_MAC_C2H_MCC_STATUS_RPT_TSF_LOW(c2h->data);
5056e2340276SBjoern A. Zeeb 	u32 tsf_high = RTW89_GET_MAC_C2H_MCC_STATUS_RPT_TSF_HIGH(c2h->data);
5057e2340276SBjoern A. Zeeb 	struct rtw89_completion_data data = {};
5058e2340276SBjoern A. Zeeb 	unsigned int cond;
5059e2340276SBjoern A. Zeeb 	bool rsp = true;
5060e2340276SBjoern A. Zeeb 	bool err;
5061e2340276SBjoern A. Zeeb 	u8 func;
5062e2340276SBjoern A. Zeeb 
5063e2340276SBjoern A. Zeeb 	switch (status) {
5064e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_ADD_ROLE_OK:
5065e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_ADD_ROLE_FAIL:
5066e2340276SBjoern A. Zeeb 		func = H2C_FUNC_ADD_MCC;
5067e2340276SBjoern A. Zeeb 		err = status == RTW89_MAC_MCC_ADD_ROLE_FAIL;
5068e2340276SBjoern A. Zeeb 		break;
5069e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_START_GROUP_OK:
5070e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_START_GROUP_FAIL:
5071e2340276SBjoern A. Zeeb 		func = H2C_FUNC_START_MCC;
5072e2340276SBjoern A. Zeeb 		err = status == RTW89_MAC_MCC_START_GROUP_FAIL;
5073e2340276SBjoern A. Zeeb 		break;
5074e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_STOP_GROUP_OK:
5075e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_STOP_GROUP_FAIL:
5076e2340276SBjoern A. Zeeb 		func = H2C_FUNC_STOP_MCC;
5077e2340276SBjoern A. Zeeb 		err = status == RTW89_MAC_MCC_STOP_GROUP_FAIL;
5078e2340276SBjoern A. Zeeb 		break;
5079e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_DEL_GROUP_OK:
5080e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_DEL_GROUP_FAIL:
5081e2340276SBjoern A. Zeeb 		func = H2C_FUNC_DEL_MCC_GROUP;
5082e2340276SBjoern A. Zeeb 		err = status == RTW89_MAC_MCC_DEL_GROUP_FAIL;
5083e2340276SBjoern A. Zeeb 		break;
5084e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_RESET_GROUP_OK:
5085e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_RESET_GROUP_FAIL:
5086e2340276SBjoern A. Zeeb 		func = H2C_FUNC_RESET_MCC_GROUP;
5087e2340276SBjoern A. Zeeb 		err = status == RTW89_MAC_MCC_RESET_GROUP_FAIL;
5088e2340276SBjoern A. Zeeb 		break;
5089e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_SWITCH_CH_OK:
5090e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_SWITCH_CH_FAIL:
5091e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_TXNULL0_OK:
5092e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_TXNULL0_FAIL:
5093e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_TXNULL1_OK:
5094e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_TXNULL1_FAIL:
5095e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_SWITCH_EARLY:
5096e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_TBTT:
5097e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_DURATION_START:
5098e2340276SBjoern A. Zeeb 	case RTW89_MAC_MCC_DURATION_END:
5099e2340276SBjoern A. Zeeb 		rsp = false;
5100e2340276SBjoern A. Zeeb 		break;
5101e2340276SBjoern A. Zeeb 	default:
5102e2340276SBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5103e2340276SBjoern A. Zeeb 			    "invalid MCC C2H STS RPT: status %d\n", status);
5104e2340276SBjoern A. Zeeb 		return;
5105e2340276SBjoern A. Zeeb 	}
5106e2340276SBjoern A. Zeeb 
5107e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5108e2340276SBjoern A. Zeeb #if defined(__linux__)
5109e2340276SBjoern A. Zeeb 		    "MCC C2H STS RPT: group %d, macid %d, status %d, tsf %llu\n",
5110e2340276SBjoern A. Zeeb 		     group, macid, status, (u64)tsf_high << 32 | tsf_low);
5111e2340276SBjoern A. Zeeb #elif defined(__FreeBSD__)
5112e2340276SBjoern A. Zeeb 		    "MCC C2H STS RPT: group %d, macid %d, status %d, tsf %ju\n",
5113e2340276SBjoern A. Zeeb 		     group, macid, status, (uintmax_t)tsf_high << 32 | tsf_low);
5114e2340276SBjoern A. Zeeb #endif
5115e2340276SBjoern A. Zeeb 
5116e2340276SBjoern A. Zeeb 	if (!rsp)
5117e2340276SBjoern A. Zeeb 		return;
5118e2340276SBjoern A. Zeeb 
5119e2340276SBjoern A. Zeeb 	data.err = err;
5120e2340276SBjoern A. Zeeb 	cond = RTW89_MCC_WAIT_COND(group, func);
5121e2340276SBjoern A. Zeeb 	rtw89_complete_cond(&rtwdev->mcc.wait, cond, &data);
51228e93258fSBjoern A. Zeeb }
51238e93258fSBjoern A. Zeeb 
5124*6d67aabdSBjoern A. Zeeb static void
5125*6d67aabdSBjoern A. Zeeb rtw89_mac_c2h_mrc_tsf_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
5126*6d67aabdSBjoern A. Zeeb {
5127*6d67aabdSBjoern A. Zeeb 	struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
5128*6d67aabdSBjoern A. Zeeb 	const struct rtw89_c2h_mrc_tsf_rpt *c2h_rpt;
5129*6d67aabdSBjoern A. Zeeb 	struct rtw89_completion_data data = {};
5130*6d67aabdSBjoern A. Zeeb 	struct rtw89_mac_mrc_tsf_rpt *rpt;
5131*6d67aabdSBjoern A. Zeeb 	unsigned int i;
5132*6d67aabdSBjoern A. Zeeb 
5133*6d67aabdSBjoern A. Zeeb 	c2h_rpt = (const struct rtw89_c2h_mrc_tsf_rpt *)c2h->data;
5134*6d67aabdSBjoern A. Zeeb 	rpt = (struct rtw89_mac_mrc_tsf_rpt *)data.buf;
5135*6d67aabdSBjoern A. Zeeb 	rpt->num = min_t(u8, RTW89_MAC_MRC_MAX_REQ_TSF_NUM,
5136*6d67aabdSBjoern A. Zeeb 			 le32_get_bits(c2h_rpt->w2,
5137*6d67aabdSBjoern A. Zeeb 				       RTW89_C2H_MRC_TSF_RPT_W2_REQ_TSF_NUM));
5138*6d67aabdSBjoern A. Zeeb 
5139*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < rpt->num; i++) {
5140*6d67aabdSBjoern A. Zeeb 		u32 tsf_high = le32_to_cpu(c2h_rpt->infos[i].tsf_high);
5141*6d67aabdSBjoern A. Zeeb 		u32 tsf_low = le32_to_cpu(c2h_rpt->infos[i].tsf_low);
5142*6d67aabdSBjoern A. Zeeb 
5143*6d67aabdSBjoern A. Zeeb 		rpt->tsfs[i] = (u64)tsf_high << 32 | tsf_low;
5144*6d67aabdSBjoern A. Zeeb 
5145*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5146*6d67aabdSBjoern A. Zeeb #if defined(__linux__)
5147*6d67aabdSBjoern A. Zeeb 			    "MRC C2H TSF RPT: index %u> %llu\n",
5148*6d67aabdSBjoern A. Zeeb 			    i, rpt->tsfs[i]);
5149*6d67aabdSBjoern A. Zeeb #elif defined(__FreeBSD__)
5150*6d67aabdSBjoern A. Zeeb 			    "MRC C2H TSF RPT: index %u> %ju\n",
5151*6d67aabdSBjoern A. Zeeb 			    i, (uintmax_t)rpt->tsfs[i]);
5152*6d67aabdSBjoern A. Zeeb #endif
5153*6d67aabdSBjoern A. Zeeb 	}
5154*6d67aabdSBjoern A. Zeeb 
5155*6d67aabdSBjoern A. Zeeb 	rtw89_complete_cond(wait, RTW89_MRC_WAIT_COND_REQ_TSF, &data);
5156*6d67aabdSBjoern A. Zeeb }
5157*6d67aabdSBjoern A. Zeeb 
5158*6d67aabdSBjoern A. Zeeb static void
5159*6d67aabdSBjoern A. Zeeb rtw89_mac_c2h_wow_aoac_rpt(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len)
5160*6d67aabdSBjoern A. Zeeb {
5161*6d67aabdSBjoern A. Zeeb 	struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
5162*6d67aabdSBjoern A. Zeeb 	struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt;
5163*6d67aabdSBjoern A. Zeeb 	struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
5164*6d67aabdSBjoern A. Zeeb 	const struct rtw89_c2h_wow_aoac_report *c2h =
5165*6d67aabdSBjoern A. Zeeb 		(const struct rtw89_c2h_wow_aoac_report *)skb->data;
5166*6d67aabdSBjoern A. Zeeb 	struct rtw89_completion_data data = {};
5167*6d67aabdSBjoern A. Zeeb 	unsigned int cond;
5168*6d67aabdSBjoern A. Zeeb 
5169*6d67aabdSBjoern A. Zeeb 	aoac_rpt->rpt_ver = c2h->rpt_ver;
5170*6d67aabdSBjoern A. Zeeb 	aoac_rpt->sec_type = c2h->sec_type;
5171*6d67aabdSBjoern A. Zeeb 	aoac_rpt->key_idx = c2h->key_idx;
5172*6d67aabdSBjoern A. Zeeb 	aoac_rpt->pattern_idx = c2h->pattern_idx;
5173*6d67aabdSBjoern A. Zeeb 	aoac_rpt->rekey_ok = u8_get_bits(c2h->rekey_ok,
5174*6d67aabdSBjoern A. Zeeb 					 RTW89_C2H_WOW_AOAC_RPT_REKEY_IDX);
5175*6d67aabdSBjoern A. Zeeb 	memcpy(aoac_rpt->ptk_tx_iv, c2h->ptk_tx_iv, sizeof(aoac_rpt->ptk_tx_iv));
5176*6d67aabdSBjoern A. Zeeb 	memcpy(aoac_rpt->eapol_key_replay_count, c2h->eapol_key_replay_count,
5177*6d67aabdSBjoern A. Zeeb 	       sizeof(aoac_rpt->eapol_key_replay_count));
5178*6d67aabdSBjoern A. Zeeb 	memcpy(aoac_rpt->gtk, c2h->gtk, sizeof(aoac_rpt->gtk));
5179*6d67aabdSBjoern A. Zeeb 	memcpy(aoac_rpt->ptk_rx_iv, c2h->ptk_rx_iv, sizeof(aoac_rpt->ptk_rx_iv));
5180*6d67aabdSBjoern A. Zeeb 	memcpy(aoac_rpt->gtk_rx_iv, c2h->gtk_rx_iv, sizeof(aoac_rpt->gtk_rx_iv));
5181*6d67aabdSBjoern A. Zeeb 	aoac_rpt->igtk_key_id = le64_to_cpu(c2h->igtk_key_id);
5182*6d67aabdSBjoern A. Zeeb 	aoac_rpt->igtk_ipn = le64_to_cpu(c2h->igtk_ipn);
5183*6d67aabdSBjoern A. Zeeb 	memcpy(aoac_rpt->igtk, c2h->igtk, sizeof(aoac_rpt->igtk));
5184*6d67aabdSBjoern A. Zeeb 
5185*6d67aabdSBjoern A. Zeeb 	cond = RTW89_WOW_WAIT_COND(H2C_FUNC_AOAC_REPORT_REQ);
5186*6d67aabdSBjoern A. Zeeb 	rtw89_complete_cond(wait, cond, &data);
5187*6d67aabdSBjoern A. Zeeb }
5188*6d67aabdSBjoern A. Zeeb 
5189*6d67aabdSBjoern A. Zeeb static void
5190*6d67aabdSBjoern A. Zeeb rtw89_mac_c2h_mrc_status_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
5191*6d67aabdSBjoern A. Zeeb {
5192*6d67aabdSBjoern A. Zeeb 	struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
5193*6d67aabdSBjoern A. Zeeb 	const struct rtw89_c2h_mrc_status_rpt *c2h_rpt;
5194*6d67aabdSBjoern A. Zeeb 	struct rtw89_completion_data data = {};
5195*6d67aabdSBjoern A. Zeeb 	enum rtw89_mac_mrc_status status;
5196*6d67aabdSBjoern A. Zeeb 	unsigned int cond;
5197*6d67aabdSBjoern A. Zeeb 	bool next = false;
5198*6d67aabdSBjoern A. Zeeb 	u32 tsf_high;
5199*6d67aabdSBjoern A. Zeeb 	u32 tsf_low;
5200*6d67aabdSBjoern A. Zeeb 	u8 sch_idx;
5201*6d67aabdSBjoern A. Zeeb 	u8 func;
5202*6d67aabdSBjoern A. Zeeb 
5203*6d67aabdSBjoern A. Zeeb 	c2h_rpt = (const struct rtw89_c2h_mrc_status_rpt *)c2h->data;
5204*6d67aabdSBjoern A. Zeeb 	sch_idx = le32_get_bits(c2h_rpt->w2, RTW89_C2H_MRC_STATUS_RPT_W2_SCH_IDX);
5205*6d67aabdSBjoern A. Zeeb 	status = le32_get_bits(c2h_rpt->w2, RTW89_C2H_MRC_STATUS_RPT_W2_STATUS);
5206*6d67aabdSBjoern A. Zeeb 	tsf_high = le32_to_cpu(c2h_rpt->tsf_high);
5207*6d67aabdSBjoern A. Zeeb 	tsf_low = le32_to_cpu(c2h_rpt->tsf_low);
5208*6d67aabdSBjoern A. Zeeb 
5209*6d67aabdSBjoern A. Zeeb 	switch (status) {
5210*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_START_SCH_OK:
5211*6d67aabdSBjoern A. Zeeb 		func = H2C_FUNC_START_MRC;
5212*6d67aabdSBjoern A. Zeeb 		break;
5213*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_STOP_SCH_OK:
5214*6d67aabdSBjoern A. Zeeb 		/* H2C_FUNC_DEL_MRC without STOP_ONLY, so wait for DEL_SCH_OK */
5215*6d67aabdSBjoern A. Zeeb 		func = H2C_FUNC_DEL_MRC;
5216*6d67aabdSBjoern A. Zeeb 		next = true;
5217*6d67aabdSBjoern A. Zeeb 		break;
5218*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_DEL_SCH_OK:
5219*6d67aabdSBjoern A. Zeeb 		func = H2C_FUNC_DEL_MRC;
5220*6d67aabdSBjoern A. Zeeb 		break;
5221*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_EMPTY_SCH_FAIL:
5222*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5223*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: empty sch fail\n");
5224*6d67aabdSBjoern A. Zeeb 		return;
5225*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_ROLE_NOT_EXIST_FAIL:
5226*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5227*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: role not exist fail\n");
5228*6d67aabdSBjoern A. Zeeb 		return;
5229*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_DATA_NOT_FOUND_FAIL:
5230*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5231*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: data not found fail\n");
5232*6d67aabdSBjoern A. Zeeb 		return;
5233*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_GET_NEXT_SLOT_FAIL:
5234*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5235*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: get next slot fail\n");
5236*6d67aabdSBjoern A. Zeeb 		return;
5237*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_ALT_ROLE_FAIL:
5238*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5239*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: alt role fail\n");
5240*6d67aabdSBjoern A. Zeeb 		return;
5241*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_ADD_PSTIMER_FAIL:
5242*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5243*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: add ps timer fail\n");
5244*6d67aabdSBjoern A. Zeeb 		return;
5245*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_MALLOC_FAIL:
5246*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5247*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: malloc fail\n");
5248*6d67aabdSBjoern A. Zeeb 		return;
5249*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_SWITCH_CH_FAIL:
5250*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5251*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: switch ch fail\n");
5252*6d67aabdSBjoern A. Zeeb 		return;
5253*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_TXNULL0_FAIL:
5254*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5255*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: tx null-0 fail\n");
5256*6d67aabdSBjoern A. Zeeb 		return;
5257*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_MRC_PORT_FUNC_EN_FAIL:
5258*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5259*6d67aabdSBjoern A. Zeeb 			    "MRC C2H STS RPT: port func en fail\n");
5260*6d67aabdSBjoern A. Zeeb 		return;
5261*6d67aabdSBjoern A. Zeeb 	default:
5262*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5263*6d67aabdSBjoern A. Zeeb 			    "invalid MRC C2H STS RPT: status %d\n", status);
5264*6d67aabdSBjoern A. Zeeb 		return;
5265*6d67aabdSBjoern A. Zeeb 	}
5266*6d67aabdSBjoern A. Zeeb 
5267*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
5268*6d67aabdSBjoern A. Zeeb #if defined(__linux__)
5269*6d67aabdSBjoern A. Zeeb 		    "MRC C2H STS RPT: sch_idx %d, status %d, tsf %llu\n",
5270*6d67aabdSBjoern A. Zeeb 		    sch_idx, status, (u64)tsf_high << 32 | tsf_low);
5271*6d67aabdSBjoern A. Zeeb #elif defined(__FreeBSD__)
5272*6d67aabdSBjoern A. Zeeb 		    "MRC C2H STS RPT: sch_idx %d, status %d, tsf %ju\n",
5273*6d67aabdSBjoern A. Zeeb 		    sch_idx, status, (uintmax_t)tsf_high << 32 | tsf_low);
5274*6d67aabdSBjoern A. Zeeb #endif
5275*6d67aabdSBjoern A. Zeeb 
5276*6d67aabdSBjoern A. Zeeb 	if (next)
5277*6d67aabdSBjoern A. Zeeb 		return;
5278*6d67aabdSBjoern A. Zeeb 
5279*6d67aabdSBjoern A. Zeeb 	cond = RTW89_MRC_WAIT_COND(sch_idx, func);
5280*6d67aabdSBjoern A. Zeeb 	rtw89_complete_cond(wait, cond, &data);
5281*6d67aabdSBjoern A. Zeeb }
5282*6d67aabdSBjoern A. Zeeb 
52838e93258fSBjoern A. Zeeb static
52848e93258fSBjoern A. Zeeb void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev,
52858e93258fSBjoern A. Zeeb 					    struct sk_buff *c2h, u32 len) = {
52868e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_EFUSE_DUMP] = NULL,
52878e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_READ_RSP] = NULL,
52888e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_PKT_OFLD_RSP] = rtw89_mac_c2h_pkt_ofld_rsp,
52898e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_BCN_RESEND] = NULL,
52908e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_MACID_PAUSE] = rtw89_mac_c2h_macid_pause,
52918e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_SCANOFLD_RSP] = rtw89_mac_c2h_scanofld_rsp,
5292e2340276SBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_TSF32_TOGL_RPT] = rtw89_mac_c2h_tsf32_toggle_rpt,
5293e2340276SBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_BCNFLTR_RPT] = rtw89_mac_c2h_bcn_fltr_rpt,
52948e93258fSBjoern A. Zeeb };
52958e93258fSBjoern A. Zeeb 
52968e93258fSBjoern A. Zeeb static
52978e93258fSBjoern A. Zeeb void (* const rtw89_mac_c2h_info_handler[])(struct rtw89_dev *rtwdev,
52988e93258fSBjoern A. Zeeb 					    struct sk_buff *c2h, u32 len) = {
52998e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_REC_ACK] = rtw89_mac_c2h_rec_ack,
53008e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_DONE_ACK] = rtw89_mac_c2h_done_ack,
53018e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_C2H_LOG] = rtw89_mac_c2h_log,
53028e93258fSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_BCN_CNT] = rtw89_mac_c2h_bcn_cnt,
53038e93258fSBjoern A. Zeeb };
53048e93258fSBjoern A. Zeeb 
5305e2340276SBjoern A. Zeeb static
5306e2340276SBjoern A. Zeeb void (* const rtw89_mac_c2h_mcc_handler[])(struct rtw89_dev *rtwdev,
5307e2340276SBjoern A. Zeeb 					   struct sk_buff *c2h, u32 len) = {
5308e2340276SBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_MCC_RCV_ACK] = rtw89_mac_c2h_mcc_rcv_ack,
5309e2340276SBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_MCC_REQ_ACK] = rtw89_mac_c2h_mcc_req_ack,
5310e2340276SBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_MCC_TSF_RPT] = rtw89_mac_c2h_mcc_tsf_rpt,
5311e2340276SBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_MCC_STATUS_RPT] = rtw89_mac_c2h_mcc_status_rpt,
5312e2340276SBjoern A. Zeeb };
5313e2340276SBjoern A. Zeeb 
5314*6d67aabdSBjoern A. Zeeb static
5315*6d67aabdSBjoern A. Zeeb void (* const rtw89_mac_c2h_mrc_handler[])(struct rtw89_dev *rtwdev,
5316*6d67aabdSBjoern A. Zeeb 					   struct sk_buff *c2h, u32 len) = {
5317*6d67aabdSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_MRC_TSF_RPT] = rtw89_mac_c2h_mrc_tsf_rpt,
5318*6d67aabdSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_MRC_STATUS_RPT] = rtw89_mac_c2h_mrc_status_rpt,
5319*6d67aabdSBjoern A. Zeeb };
5320*6d67aabdSBjoern A. Zeeb 
5321*6d67aabdSBjoern A. Zeeb static
5322*6d67aabdSBjoern A. Zeeb void (* const rtw89_mac_c2h_wow_handler[])(struct rtw89_dev *rtwdev,
5323*6d67aabdSBjoern A. Zeeb 					   struct sk_buff *c2h, u32 len) = {
5324*6d67aabdSBjoern A. Zeeb 	[RTW89_MAC_C2H_FUNC_AOAC_REPORT] = rtw89_mac_c2h_wow_aoac_rpt,
5325*6d67aabdSBjoern A. Zeeb };
5326*6d67aabdSBjoern A. Zeeb 
5327*6d67aabdSBjoern A. Zeeb static void rtw89_mac_c2h_scanofld_rsp_atomic(struct rtw89_dev *rtwdev,
5328*6d67aabdSBjoern A. Zeeb 					      struct sk_buff *skb)
5329*6d67aabdSBjoern A. Zeeb {
5330*6d67aabdSBjoern A. Zeeb 	const struct rtw89_c2h_scanofld *c2h =
5331*6d67aabdSBjoern A. Zeeb 		(const struct rtw89_c2h_scanofld *)skb->data;
5332*6d67aabdSBjoern A. Zeeb 	struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait;
5333*6d67aabdSBjoern A. Zeeb 	struct rtw89_completion_data data = {};
5334*6d67aabdSBjoern A. Zeeb 	unsigned int cond;
5335*6d67aabdSBjoern A. Zeeb 	u8 status, reason;
5336*6d67aabdSBjoern A. Zeeb 
5337*6d67aabdSBjoern A. Zeeb 	status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS);
5338*6d67aabdSBjoern A. Zeeb 	reason = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_RSN);
5339*6d67aabdSBjoern A. Zeeb 	data.err = status != RTW89_SCAN_STATUS_SUCCESS;
5340*6d67aabdSBjoern A. Zeeb 
5341*6d67aabdSBjoern A. Zeeb 	if (reason == RTW89_SCAN_END_SCAN_NOTIFY) {
5342*6d67aabdSBjoern A. Zeeb 		if (rtwdev->chip->chip_gen == RTW89_CHIP_BE)
5343*6d67aabdSBjoern A. Zeeb 			cond = RTW89_SCANOFLD_BE_WAIT_COND_STOP;
5344*6d67aabdSBjoern A. Zeeb 		else
5345*6d67aabdSBjoern A. Zeeb 			cond = RTW89_SCANOFLD_WAIT_COND_STOP;
5346*6d67aabdSBjoern A. Zeeb 
5347*6d67aabdSBjoern A. Zeeb 		rtw89_complete_cond(fw_ofld_wait, cond, &data);
5348*6d67aabdSBjoern A. Zeeb 	}
5349*6d67aabdSBjoern A. Zeeb }
5350*6d67aabdSBjoern A. Zeeb 
5351*6d67aabdSBjoern A. Zeeb bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
5352*6d67aabdSBjoern A. Zeeb 			      u8 class, u8 func)
5353e2340276SBjoern A. Zeeb {
5354e2340276SBjoern A. Zeeb 	switch (class) {
5355e2340276SBjoern A. Zeeb 	default:
5356e2340276SBjoern A. Zeeb 		return false;
5357e2340276SBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_INFO:
5358e2340276SBjoern A. Zeeb 		switch (func) {
5359e2340276SBjoern A. Zeeb 		default:
5360e2340276SBjoern A. Zeeb 			return false;
5361e2340276SBjoern A. Zeeb 		case RTW89_MAC_C2H_FUNC_REC_ACK:
5362e2340276SBjoern A. Zeeb 		case RTW89_MAC_C2H_FUNC_DONE_ACK:
5363e2340276SBjoern A. Zeeb 			return true;
5364e2340276SBjoern A. Zeeb 		}
5365e2340276SBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_OFLD:
5366e2340276SBjoern A. Zeeb 		switch (func) {
5367e2340276SBjoern A. Zeeb 		default:
5368e2340276SBjoern A. Zeeb 			return false;
5369*6d67aabdSBjoern A. Zeeb 		case RTW89_MAC_C2H_FUNC_SCANOFLD_RSP:
5370*6d67aabdSBjoern A. Zeeb 			rtw89_mac_c2h_scanofld_rsp_atomic(rtwdev, c2h);
5371*6d67aabdSBjoern A. Zeeb 			return false;
5372e2340276SBjoern A. Zeeb 		case RTW89_MAC_C2H_FUNC_PKT_OFLD_RSP:
5373e2340276SBjoern A. Zeeb 			return true;
5374e2340276SBjoern A. Zeeb 		}
5375e2340276SBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_MCC:
5376e2340276SBjoern A. Zeeb 		return true;
5377*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_MRC:
5378*6d67aabdSBjoern A. Zeeb 		return true;
5379*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_WOW:
5380*6d67aabdSBjoern A. Zeeb 		return true;
5381e2340276SBjoern A. Zeeb 	}
5382e2340276SBjoern A. Zeeb }
5383e2340276SBjoern A. Zeeb 
53848e93258fSBjoern A. Zeeb void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
53858e93258fSBjoern A. Zeeb 			  u32 len, u8 class, u8 func)
53868e93258fSBjoern A. Zeeb {
53878e93258fSBjoern A. Zeeb 	void (*handler)(struct rtw89_dev *rtwdev,
53888e93258fSBjoern A. Zeeb 			struct sk_buff *c2h, u32 len) = NULL;
53898e93258fSBjoern A. Zeeb 
53908e93258fSBjoern A. Zeeb 	switch (class) {
53918e93258fSBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_INFO:
53928e93258fSBjoern A. Zeeb 		if (func < RTW89_MAC_C2H_FUNC_INFO_MAX)
53938e93258fSBjoern A. Zeeb 			handler = rtw89_mac_c2h_info_handler[func];
53948e93258fSBjoern A. Zeeb 		break;
53958e93258fSBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_OFLD:
53968e93258fSBjoern A. Zeeb 		if (func < RTW89_MAC_C2H_FUNC_OFLD_MAX)
53978e93258fSBjoern A. Zeeb 			handler = rtw89_mac_c2h_ofld_handler[func];
53988e93258fSBjoern A. Zeeb 		break;
5399e2340276SBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_MCC:
5400e2340276SBjoern A. Zeeb 		if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MCC)
5401e2340276SBjoern A. Zeeb 			handler = rtw89_mac_c2h_mcc_handler[func];
5402e2340276SBjoern A. Zeeb 		break;
5403*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_MRC:
5404*6d67aabdSBjoern A. Zeeb 		if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MRC)
5405*6d67aabdSBjoern A. Zeeb 			handler = rtw89_mac_c2h_mrc_handler[func];
5406*6d67aabdSBjoern A. Zeeb 		break;
5407*6d67aabdSBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_WOW:
5408*6d67aabdSBjoern A. Zeeb 		if (func < NUM_OF_RTW89_MAC_C2H_FUNC_WOW)
5409*6d67aabdSBjoern A. Zeeb 			handler = rtw89_mac_c2h_wow_handler[func];
5410*6d67aabdSBjoern A. Zeeb 		break;
54118e93258fSBjoern A. Zeeb 	case RTW89_MAC_C2H_CLASS_FWDBG:
54128e93258fSBjoern A. Zeeb 		return;
54138e93258fSBjoern A. Zeeb 	default:
54148e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "c2h class %d not support\n", class);
54158e93258fSBjoern A. Zeeb 		return;
54168e93258fSBjoern A. Zeeb 	}
54178e93258fSBjoern A. Zeeb 	if (!handler) {
54188e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "c2h class %d func %d not support\n", class,
54198e93258fSBjoern A. Zeeb 			   func);
54208e93258fSBjoern A. Zeeb 		return;
54218e93258fSBjoern A. Zeeb 	}
54228e93258fSBjoern A. Zeeb 	handler(rtwdev, skb, len);
54238e93258fSBjoern A. Zeeb }
54248e93258fSBjoern A. Zeeb 
5425*6d67aabdSBjoern A. Zeeb static
5426*6d67aabdSBjoern A. Zeeb bool rtw89_mac_get_txpwr_cr_ax(struct rtw89_dev *rtwdev,
54278e93258fSBjoern A. Zeeb 			       enum rtw89_phy_idx phy_idx,
54288e93258fSBjoern A. Zeeb 			       u32 reg_base, u32 *cr)
54298e93258fSBjoern A. Zeeb {
5430*6d67aabdSBjoern A. Zeeb 	enum rtw89_qta_mode mode = rtwdev->mac.qta_mode;
5431*6d67aabdSBjoern A. Zeeb 	u32 addr = rtw89_mac_reg_by_idx(rtwdev, reg_base, phy_idx);
54328e93258fSBjoern A. Zeeb 
5433*6d67aabdSBjoern A. Zeeb 	if (addr < R_AX_PWR_RATE_CTRL || addr > CMAC1_END_ADDR_AX) {
54348e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "[TXPWR] addr=0x%x exceed txpwr cr\n",
54358e93258fSBjoern A. Zeeb 			  addr);
54368e93258fSBjoern A. Zeeb 		goto error;
54378e93258fSBjoern A. Zeeb 	}
54388e93258fSBjoern A. Zeeb 
5439*6d67aabdSBjoern A. Zeeb 	if (addr >= CMAC1_START_ADDR_AX && addr <= CMAC1_END_ADDR_AX)
54408e93258fSBjoern A. Zeeb 		if (mode == RTW89_QTA_SCC) {
54418e93258fSBjoern A. Zeeb 			rtw89_err(rtwdev,
54428e93258fSBjoern A. Zeeb 				  "[TXPWR] addr=0x%x but hw not enable\n",
54438e93258fSBjoern A. Zeeb 				  addr);
54448e93258fSBjoern A. Zeeb 			goto error;
54458e93258fSBjoern A. Zeeb 		}
54468e93258fSBjoern A. Zeeb 
54478e93258fSBjoern A. Zeeb 	*cr = addr;
54488e93258fSBjoern A. Zeeb 	return true;
54498e93258fSBjoern A. Zeeb 
54508e93258fSBjoern A. Zeeb error:
54518e93258fSBjoern A. Zeeb 	rtw89_err(rtwdev, "[TXPWR] check txpwr cr 0x%x(phy%d) fail\n",
54528e93258fSBjoern A. Zeeb 		  addr, phy_idx);
54538e93258fSBjoern A. Zeeb 
54548e93258fSBjoern A. Zeeb 	return false;
54558e93258fSBjoern A. Zeeb }
54568e93258fSBjoern A. Zeeb 
5457*6d67aabdSBjoern A. Zeeb static
5458*6d67aabdSBjoern A. Zeeb int rtw89_mac_cfg_ppdu_status_ax(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
54598e93258fSBjoern A. Zeeb {
5460*6d67aabdSBjoern A. Zeeb 	u32 reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PPDU_STAT, mac_idx);
5461e2340276SBjoern A. Zeeb 	int ret;
54628e93258fSBjoern A. Zeeb 
54638e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
54648e93258fSBjoern A. Zeeb 	if (ret)
54658e93258fSBjoern A. Zeeb 		return ret;
54668e93258fSBjoern A. Zeeb 
54678e93258fSBjoern A. Zeeb 	if (!enable) {
54688e93258fSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, reg, B_AX_PPDU_STAT_RPT_EN);
5469e2340276SBjoern A. Zeeb 		return 0;
54708e93258fSBjoern A. Zeeb 	}
54718e93258fSBjoern A. Zeeb 
54728e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, B_AX_PPDU_STAT_RPT_EN |
54738e93258fSBjoern A. Zeeb 				   B_AX_APP_MAC_INFO_RPT |
54748e93258fSBjoern A. Zeeb 				   B_AX_APP_RX_CNT_RPT | B_AX_APP_PLCP_HDR_RPT |
54758e93258fSBjoern A. Zeeb 				   B_AX_PPDU_STAT_RPT_CRC32);
54768e93258fSBjoern A. Zeeb 	rtw89_write32_mask(rtwdev, R_AX_HW_RPT_FWD, B_AX_FWD_PPDU_STAT_MASK,
54778e93258fSBjoern A. Zeeb 			   RTW89_PRPT_DEST_HOST);
54788e93258fSBjoern A. Zeeb 
5479e2340276SBjoern A. Zeeb 	return 0;
54808e93258fSBjoern A. Zeeb }
54818e93258fSBjoern A. Zeeb 
54828e93258fSBjoern A. Zeeb void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx)
54838e93258fSBjoern A. Zeeb {
54848e93258fSBjoern A. Zeeb #define MAC_AX_TIME_TH_SH  5
54858e93258fSBjoern A. Zeeb #define MAC_AX_LEN_TH_SH   4
54868e93258fSBjoern A. Zeeb #define MAC_AX_TIME_TH_MAX 255
54878e93258fSBjoern A. Zeeb #define MAC_AX_LEN_TH_MAX  255
54888e93258fSBjoern A. Zeeb #define MAC_AX_TIME_TH_DEF 88
54898e93258fSBjoern A. Zeeb #define MAC_AX_LEN_TH_DEF  4080
5490*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
54918e93258fSBjoern A. Zeeb 	struct ieee80211_hw *hw = rtwdev->hw;
54928e93258fSBjoern A. Zeeb 	u32 rts_threshold = hw->wiphy->rts_threshold;
54938e93258fSBjoern A. Zeeb 	u32 time_th, len_th;
54948e93258fSBjoern A. Zeeb 	u32 reg;
54958e93258fSBjoern A. Zeeb 
54968e93258fSBjoern A. Zeeb 	if (rts_threshold == (u32)-1) {
54978e93258fSBjoern A. Zeeb 		time_th = MAC_AX_TIME_TH_DEF;
54988e93258fSBjoern A. Zeeb 		len_th = MAC_AX_LEN_TH_DEF;
54998e93258fSBjoern A. Zeeb 	} else {
55008e93258fSBjoern A. Zeeb 		time_th = MAC_AX_TIME_TH_MAX << MAC_AX_TIME_TH_SH;
55018e93258fSBjoern A. Zeeb 		len_th = rts_threshold;
55028e93258fSBjoern A. Zeeb 	}
55038e93258fSBjoern A. Zeeb 
55048e93258fSBjoern A. Zeeb 	time_th = min_t(u32, time_th >> MAC_AX_TIME_TH_SH, MAC_AX_TIME_TH_MAX);
55058e93258fSBjoern A. Zeeb 	len_th = min_t(u32, len_th >> MAC_AX_LEN_TH_SH, MAC_AX_LEN_TH_MAX);
55068e93258fSBjoern A. Zeeb 
5507*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, mac->agg_len_ht, mac_idx);
55088e93258fSBjoern A. Zeeb 	rtw89_write16_mask(rtwdev, reg, B_AX_RTS_TXTIME_TH_MASK, time_th);
55098e93258fSBjoern A. Zeeb 	rtw89_write16_mask(rtwdev, reg, B_AX_RTS_LEN_TH_MASK, len_th);
55108e93258fSBjoern A. Zeeb }
55118e93258fSBjoern A. Zeeb 
55128e93258fSBjoern A. Zeeb void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop)
55138e93258fSBjoern A. Zeeb {
55148e93258fSBjoern A. Zeeb 	bool empty;
55158e93258fSBjoern A. Zeeb 	int ret;
55168e93258fSBjoern A. Zeeb 
55178e93258fSBjoern A. Zeeb 	if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
55188e93258fSBjoern A. Zeeb 		return;
55198e93258fSBjoern A. Zeeb 
55208e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(dle_is_txq_empty, empty, empty,
55218e93258fSBjoern A. Zeeb 				10000, 200000, false, rtwdev);
55228e93258fSBjoern A. Zeeb 	if (ret && !drop && (rtwdev->total_sta_assoc || rtwdev->scanning))
55238e93258fSBjoern A. Zeeb 		rtw89_info(rtwdev, "timed out to flush queues\n");
55248e93258fSBjoern A. Zeeb }
55258e93258fSBjoern A. Zeeb 
55268e93258fSBjoern A. Zeeb int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex *coex)
55278e93258fSBjoern A. Zeeb {
5528*6d67aabdSBjoern A. Zeeb 	enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
55298e93258fSBjoern A. Zeeb 	u8 val;
55308e93258fSBjoern A. Zeeb 	u16 val16;
55318e93258fSBjoern A. Zeeb 	u32 val32;
55328e93258fSBjoern A. Zeeb 	int ret;
55338e93258fSBjoern A. Zeeb 
55348e93258fSBjoern A. Zeeb 	rtw89_write8_set(rtwdev, R_AX_GPIO_MUXCFG, B_AX_ENBT);
5535*6d67aabdSBjoern A. Zeeb 	if (chip_id != RTL8851B && chip_id != RTL8852BT)
55368e93258fSBjoern A. Zeeb 		rtw89_write8_set(rtwdev, R_AX_BTC_FUNC_EN, B_AX_PTA_WL_TX_EN);
55378e93258fSBjoern A. Zeeb 	rtw89_write8_set(rtwdev, R_AX_BT_COEX_CFG_2 + 1, B_AX_GNT_BT_POLARITY >> 8);
55388e93258fSBjoern A. Zeeb 	rtw89_write8_set(rtwdev, R_AX_CSR_MODE, B_AX_STATIS_BT_EN | B_AX_WL_ACT_MSK);
55398e93258fSBjoern A. Zeeb 	rtw89_write8_set(rtwdev, R_AX_CSR_MODE + 2, B_AX_BT_CNT_RST >> 16);
5540*6d67aabdSBjoern A. Zeeb 	if (chip_id != RTL8851B && chip_id != RTL8852BT)
55418e93258fSBjoern A. Zeeb 		rtw89_write8_clr(rtwdev, R_AX_TRXPTCL_RESP_0 + 3, B_AX_RSP_CHK_BTCCA >> 24);
55428e93258fSBjoern A. Zeeb 
55438e93258fSBjoern A. Zeeb 	val16 = rtw89_read16(rtwdev, R_AX_CCA_CFG_0);
55448e93258fSBjoern A. Zeeb 	val16 = (val16 | B_AX_BTCCA_EN) & ~B_AX_BTCCA_BRK_TXOP_EN;
55458e93258fSBjoern A. Zeeb 	rtw89_write16(rtwdev, R_AX_CCA_CFG_0, val16);
55468e93258fSBjoern A. Zeeb 
55478e93258fSBjoern A. Zeeb 	ret = rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_2, &val32);
55488e93258fSBjoern A. Zeeb 	if (ret) {
55498e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "Read R_AX_LTE_SW_CFG_2 fail!\n");
55508e93258fSBjoern A. Zeeb 		return ret;
55518e93258fSBjoern A. Zeeb 	}
55528e93258fSBjoern A. Zeeb 	val32 = val32 & B_AX_WL_RX_CTRL;
55538e93258fSBjoern A. Zeeb 	ret = rtw89_mac_write_lte(rtwdev, R_AX_LTE_SW_CFG_2, val32);
55548e93258fSBjoern A. Zeeb 	if (ret) {
55558e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "Write R_AX_LTE_SW_CFG_2 fail!\n");
55568e93258fSBjoern A. Zeeb 		return ret;
55578e93258fSBjoern A. Zeeb 	}
55588e93258fSBjoern A. Zeeb 
55598e93258fSBjoern A. Zeeb 	switch (coex->pta_mode) {
55608e93258fSBjoern A. Zeeb 	case RTW89_MAC_AX_COEX_RTK_MODE:
55618e93258fSBjoern A. Zeeb 		val = rtw89_read8(rtwdev, R_AX_GPIO_MUXCFG);
55628e93258fSBjoern A. Zeeb 		val &= ~B_AX_BTMODE_MASK;
55638e93258fSBjoern A. Zeeb 		val |= FIELD_PREP(B_AX_BTMODE_MASK, MAC_AX_BT_MODE_0_3);
55648e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_GPIO_MUXCFG, val);
55658e93258fSBjoern A. Zeeb 
55668e93258fSBjoern A. Zeeb 		val = rtw89_read8(rtwdev, R_AX_TDMA_MODE);
55678e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_TDMA_MODE, val | B_AX_RTK_BT_ENABLE);
55688e93258fSBjoern A. Zeeb 
55698e93258fSBjoern A. Zeeb 		val = rtw89_read8(rtwdev, R_AX_BT_COEX_CFG_5);
55708e93258fSBjoern A. Zeeb 		val &= ~B_AX_BT_RPT_SAMPLE_RATE_MASK;
55718e93258fSBjoern A. Zeeb 		val |= FIELD_PREP(B_AX_BT_RPT_SAMPLE_RATE_MASK, MAC_AX_RTK_RATE);
55728e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_BT_COEX_CFG_5, val);
55738e93258fSBjoern A. Zeeb 		break;
55748e93258fSBjoern A. Zeeb 	case RTW89_MAC_AX_COEX_CSR_MODE:
55758e93258fSBjoern A. Zeeb 		val = rtw89_read8(rtwdev, R_AX_GPIO_MUXCFG);
55768e93258fSBjoern A. Zeeb 		val &= ~B_AX_BTMODE_MASK;
55778e93258fSBjoern A. Zeeb 		val |= FIELD_PREP(B_AX_BTMODE_MASK, MAC_AX_BT_MODE_2);
55788e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_GPIO_MUXCFG, val);
55798e93258fSBjoern A. Zeeb 
55808e93258fSBjoern A. Zeeb 		val16 = rtw89_read16(rtwdev, R_AX_CSR_MODE);
55818e93258fSBjoern A. Zeeb 		val16 &= ~B_AX_BT_PRI_DETECT_TO_MASK;
55828e93258fSBjoern A. Zeeb 		val16 |= FIELD_PREP(B_AX_BT_PRI_DETECT_TO_MASK, MAC_AX_CSR_PRI_TO);
55838e93258fSBjoern A. Zeeb 		val16 &= ~B_AX_BT_TRX_INIT_DETECT_MASK;
55848e93258fSBjoern A. Zeeb 		val16 |= FIELD_PREP(B_AX_BT_TRX_INIT_DETECT_MASK, MAC_AX_CSR_TRX_TO);
55858e93258fSBjoern A. Zeeb 		val16 &= ~B_AX_BT_STAT_DELAY_MASK;
55868e93258fSBjoern A. Zeeb 		val16 |= FIELD_PREP(B_AX_BT_STAT_DELAY_MASK, MAC_AX_CSR_DELAY);
55878e93258fSBjoern A. Zeeb 		val16 |= B_AX_ENHANCED_BT;
55888e93258fSBjoern A. Zeeb 		rtw89_write16(rtwdev, R_AX_CSR_MODE, val16);
55898e93258fSBjoern A. Zeeb 
55908e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_BT_COEX_CFG_2, MAC_AX_CSR_RATE);
55918e93258fSBjoern A. Zeeb 		break;
55928e93258fSBjoern A. Zeeb 	default:
55938e93258fSBjoern A. Zeeb 		return -EINVAL;
55948e93258fSBjoern A. Zeeb 	}
55958e93258fSBjoern A. Zeeb 
55968e93258fSBjoern A. Zeeb 	switch (coex->direction) {
55978e93258fSBjoern A. Zeeb 	case RTW89_MAC_AX_COEX_INNER:
55988e93258fSBjoern A. Zeeb 		val = rtw89_read8(rtwdev, R_AX_GPIO_MUXCFG + 1);
55998e93258fSBjoern A. Zeeb 		val = (val & ~BIT(2)) | BIT(1);
56008e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_GPIO_MUXCFG + 1, val);
56018e93258fSBjoern A. Zeeb 		break;
56028e93258fSBjoern A. Zeeb 	case RTW89_MAC_AX_COEX_OUTPUT:
56038e93258fSBjoern A. Zeeb 		val = rtw89_read8(rtwdev, R_AX_GPIO_MUXCFG + 1);
56048e93258fSBjoern A. Zeeb 		val = val | BIT(1) | BIT(0);
56058e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_GPIO_MUXCFG + 1, val);
56068e93258fSBjoern A. Zeeb 		break;
56078e93258fSBjoern A. Zeeb 	case RTW89_MAC_AX_COEX_INPUT:
56088e93258fSBjoern A. Zeeb 		val = rtw89_read8(rtwdev, R_AX_GPIO_MUXCFG + 1);
56098e93258fSBjoern A. Zeeb 		val = val & ~(BIT(2) | BIT(1));
56108e93258fSBjoern A. Zeeb 		rtw89_write8(rtwdev, R_AX_GPIO_MUXCFG + 1, val);
56118e93258fSBjoern A. Zeeb 		break;
56128e93258fSBjoern A. Zeeb 	default:
56138e93258fSBjoern A. Zeeb 		return -EINVAL;
56148e93258fSBjoern A. Zeeb 	}
56158e93258fSBjoern A. Zeeb 
56168e93258fSBjoern A. Zeeb 	return 0;
56178e93258fSBjoern A. Zeeb }
56188e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_coex_init);
56198e93258fSBjoern A. Zeeb 
56208e93258fSBjoern A. Zeeb int rtw89_mac_coex_init_v1(struct rtw89_dev *rtwdev,
56218e93258fSBjoern A. Zeeb 			   const struct rtw89_mac_ax_coex *coex)
56228e93258fSBjoern A. Zeeb {
56238e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_BTC_CFG,
56248e93258fSBjoern A. Zeeb 			  B_AX_BTC_EN | B_AX_BTG_LNA1_GAIN_SEL);
56258e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, R_AX_BT_CNT_CFG, B_AX_BT_CNT_EN);
56268e93258fSBjoern A. Zeeb 	rtw89_write16_set(rtwdev, R_AX_CCA_CFG_0, B_AX_BTCCA_EN);
56278e93258fSBjoern A. Zeeb 	rtw89_write16_clr(rtwdev, R_AX_CCA_CFG_0, B_AX_BTCCA_BRK_TXOP_EN);
56288e93258fSBjoern A. Zeeb 
56298e93258fSBjoern A. Zeeb 	switch (coex->pta_mode) {
56308e93258fSBjoern A. Zeeb 	case RTW89_MAC_AX_COEX_RTK_MODE:
56318e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, R_AX_BTC_CFG, B_AX_BTC_MODE_MASK,
56328e93258fSBjoern A. Zeeb 				   MAC_AX_RTK_MODE);
56338e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, R_AX_RTK_MODE_CFG_V1,
56348e93258fSBjoern A. Zeeb 				   B_AX_SAMPLE_CLK_MASK, MAC_AX_RTK_RATE);
56358e93258fSBjoern A. Zeeb 		break;
56368e93258fSBjoern A. Zeeb 	case RTW89_MAC_AX_COEX_CSR_MODE:
56378e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, R_AX_BTC_CFG, B_AX_BTC_MODE_MASK,
56388e93258fSBjoern A. Zeeb 				   MAC_AX_CSR_MODE);
56398e93258fSBjoern A. Zeeb 		break;
56408e93258fSBjoern A. Zeeb 	default:
56418e93258fSBjoern A. Zeeb 		return -EINVAL;
56428e93258fSBjoern A. Zeeb 	}
56438e93258fSBjoern A. Zeeb 
56448e93258fSBjoern A. Zeeb 	return 0;
56458e93258fSBjoern A. Zeeb }
56468e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_coex_init_v1);
56478e93258fSBjoern A. Zeeb 
56488e93258fSBjoern A. Zeeb int rtw89_mac_cfg_gnt(struct rtw89_dev *rtwdev,
56498e93258fSBjoern A. Zeeb 		      const struct rtw89_mac_ax_coex_gnt *gnt_cfg)
56508e93258fSBjoern A. Zeeb {
56518e93258fSBjoern A. Zeeb 	u32 val = 0, ret;
56528e93258fSBjoern A. Zeeb 
56538e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[0].gnt_bt)
56548e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_BT_RFC_S0_SW_VAL | B_AX_GNT_BT_BB_S0_SW_VAL;
56558e93258fSBjoern A. Zeeb 
56568e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[0].gnt_bt_sw_en)
56578e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_BT_RFC_S0_SW_CTRL | B_AX_GNT_BT_BB_S0_SW_CTRL;
56588e93258fSBjoern A. Zeeb 
56598e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[0].gnt_wl)
56608e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_WL_RFC_S0_SW_VAL | B_AX_GNT_WL_BB_S0_SW_VAL;
56618e93258fSBjoern A. Zeeb 
56628e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[0].gnt_wl_sw_en)
56638e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_WL_RFC_S0_SW_CTRL | B_AX_GNT_WL_BB_S0_SW_CTRL;
56648e93258fSBjoern A. Zeeb 
56658e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[1].gnt_bt)
56668e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_BT_RFC_S1_SW_VAL | B_AX_GNT_BT_BB_S1_SW_VAL;
56678e93258fSBjoern A. Zeeb 
56688e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[1].gnt_bt_sw_en)
56698e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_BT_RFC_S1_SW_CTRL | B_AX_GNT_BT_BB_S1_SW_CTRL;
56708e93258fSBjoern A. Zeeb 
56718e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[1].gnt_wl)
56728e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_WL_RFC_S1_SW_VAL | B_AX_GNT_WL_BB_S1_SW_VAL;
56738e93258fSBjoern A. Zeeb 
56748e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[1].gnt_wl_sw_en)
56758e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_WL_RFC_S1_SW_CTRL | B_AX_GNT_WL_BB_S1_SW_CTRL;
56768e93258fSBjoern A. Zeeb 
56778e93258fSBjoern A. Zeeb 	ret = rtw89_mac_write_lte(rtwdev, R_AX_LTE_SW_CFG_1, val);
56788e93258fSBjoern A. Zeeb 	if (ret) {
56798e93258fSBjoern A. Zeeb 		rtw89_err(rtwdev, "Write LTE fail!\n");
56808e93258fSBjoern A. Zeeb 		return ret;
56818e93258fSBjoern A. Zeeb 	}
56828e93258fSBjoern A. Zeeb 
56838e93258fSBjoern A. Zeeb 	return 0;
56848e93258fSBjoern A. Zeeb }
56858e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_cfg_gnt);
56868e93258fSBjoern A. Zeeb 
56878e93258fSBjoern A. Zeeb int rtw89_mac_cfg_gnt_v1(struct rtw89_dev *rtwdev,
56888e93258fSBjoern A. Zeeb 			 const struct rtw89_mac_ax_coex_gnt *gnt_cfg)
56898e93258fSBjoern A. Zeeb {
56908e93258fSBjoern A. Zeeb 	u32 val = 0;
56918e93258fSBjoern A. Zeeb 
56928e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[0].gnt_bt)
56938e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_BT_RFC_S0_VAL | B_AX_GNT_BT_RX_VAL |
56948e93258fSBjoern A. Zeeb 		       B_AX_GNT_BT_TX_VAL;
56958e93258fSBjoern A. Zeeb 	else
56968e93258fSBjoern A. Zeeb 		val |= B_AX_WL_ACT_VAL;
56978e93258fSBjoern A. Zeeb 
56988e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[0].gnt_bt_sw_en)
56998e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_BT_RFC_S0_SWCTRL | B_AX_GNT_BT_RX_SWCTRL |
57008e93258fSBjoern A. Zeeb 		       B_AX_GNT_BT_TX_SWCTRL | B_AX_WL_ACT_SWCTRL;
57018e93258fSBjoern A. Zeeb 
57028e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[0].gnt_wl)
57038e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_WL_RFC_S0_VAL | B_AX_GNT_WL_RX_VAL |
57048e93258fSBjoern A. Zeeb 		       B_AX_GNT_WL_TX_VAL | B_AX_GNT_WL_BB_VAL;
57058e93258fSBjoern A. Zeeb 
57068e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[0].gnt_wl_sw_en)
57078e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_WL_RFC_S0_SWCTRL | B_AX_GNT_WL_RX_SWCTRL |
57088e93258fSBjoern A. Zeeb 		       B_AX_GNT_WL_TX_SWCTRL | B_AX_GNT_WL_BB_SWCTRL;
57098e93258fSBjoern A. Zeeb 
57108e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[1].gnt_bt)
57118e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_BT_RFC_S1_VAL | B_AX_GNT_BT_RX_VAL |
57128e93258fSBjoern A. Zeeb 		       B_AX_GNT_BT_TX_VAL;
57138e93258fSBjoern A. Zeeb 	else
57148e93258fSBjoern A. Zeeb 		val |= B_AX_WL_ACT_VAL;
57158e93258fSBjoern A. Zeeb 
57168e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[1].gnt_bt_sw_en)
57178e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_BT_RFC_S1_SWCTRL | B_AX_GNT_BT_RX_SWCTRL |
57188e93258fSBjoern A. Zeeb 		       B_AX_GNT_BT_TX_SWCTRL | B_AX_WL_ACT_SWCTRL;
57198e93258fSBjoern A. Zeeb 
57208e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[1].gnt_wl)
57218e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_WL_RFC_S1_VAL | B_AX_GNT_WL_RX_VAL |
57228e93258fSBjoern A. Zeeb 		       B_AX_GNT_WL_TX_VAL | B_AX_GNT_WL_BB_VAL;
57238e93258fSBjoern A. Zeeb 
57248e93258fSBjoern A. Zeeb 	if (gnt_cfg->band[1].gnt_wl_sw_en)
57258e93258fSBjoern A. Zeeb 		val |= B_AX_GNT_WL_RFC_S1_SWCTRL | B_AX_GNT_WL_RX_SWCTRL |
57268e93258fSBjoern A. Zeeb 		       B_AX_GNT_WL_TX_SWCTRL | B_AX_GNT_WL_BB_SWCTRL;
57278e93258fSBjoern A. Zeeb 
57288e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_GNT_SW_CTRL, val);
57298e93258fSBjoern A. Zeeb 
57308e93258fSBjoern A. Zeeb 	return 0;
57318e93258fSBjoern A. Zeeb }
57328e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_cfg_gnt_v1);
57338e93258fSBjoern A. Zeeb 
5734*6d67aabdSBjoern A. Zeeb static
5735*6d67aabdSBjoern A. Zeeb int rtw89_mac_cfg_plt_ax(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt)
57368e93258fSBjoern A. Zeeb {
57378e93258fSBjoern A. Zeeb 	u32 reg;
57388e93258fSBjoern A. Zeeb 	u16 val;
57398e93258fSBjoern A. Zeeb 	int ret;
57408e93258fSBjoern A. Zeeb 
57418e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, plt->band, RTW89_CMAC_SEL);
57428e93258fSBjoern A. Zeeb 	if (ret)
57438e93258fSBjoern A. Zeeb 		return ret;
57448e93258fSBjoern A. Zeeb 
5745*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BT_PLT, plt->band);
57468e93258fSBjoern A. Zeeb 	val = (plt->tx & RTW89_MAC_AX_PLT_LTE_RX ? B_AX_TX_PLT_GNT_LTE_RX : 0) |
57478e93258fSBjoern A. Zeeb 	      (plt->tx & RTW89_MAC_AX_PLT_GNT_BT_TX ? B_AX_TX_PLT_GNT_BT_TX : 0) |
57488e93258fSBjoern A. Zeeb 	      (plt->tx & RTW89_MAC_AX_PLT_GNT_BT_RX ? B_AX_TX_PLT_GNT_BT_RX : 0) |
57498e93258fSBjoern A. Zeeb 	      (plt->tx & RTW89_MAC_AX_PLT_GNT_WL ? B_AX_TX_PLT_GNT_WL : 0) |
57508e93258fSBjoern A. Zeeb 	      (plt->rx & RTW89_MAC_AX_PLT_LTE_RX ? B_AX_RX_PLT_GNT_LTE_RX : 0) |
57518e93258fSBjoern A. Zeeb 	      (plt->rx & RTW89_MAC_AX_PLT_GNT_BT_TX ? B_AX_RX_PLT_GNT_BT_TX : 0) |
57528e93258fSBjoern A. Zeeb 	      (plt->rx & RTW89_MAC_AX_PLT_GNT_BT_RX ? B_AX_RX_PLT_GNT_BT_RX : 0) |
57538e93258fSBjoern A. Zeeb 	      (plt->rx & RTW89_MAC_AX_PLT_GNT_WL ? B_AX_RX_PLT_GNT_WL : 0) |
57548e93258fSBjoern A. Zeeb 	      B_AX_PLT_EN;
57558e93258fSBjoern A. Zeeb 	rtw89_write16(rtwdev, reg, val);
57568e93258fSBjoern A. Zeeb 
57578e93258fSBjoern A. Zeeb 	return 0;
57588e93258fSBjoern A. Zeeb }
57598e93258fSBjoern A. Zeeb 
57608e93258fSBjoern A. Zeeb void rtw89_mac_cfg_sb(struct rtw89_dev *rtwdev, u32 val)
57618e93258fSBjoern A. Zeeb {
57628e93258fSBjoern A. Zeeb 	u32 fw_sb;
57638e93258fSBjoern A. Zeeb 
57648e93258fSBjoern A. Zeeb 	fw_sb = rtw89_read32(rtwdev, R_AX_SCOREBOARD);
57658e93258fSBjoern A. Zeeb 	fw_sb = FIELD_GET(B_MAC_AX_SB_FW_MASK, fw_sb);
57668e93258fSBjoern A. Zeeb 	fw_sb = fw_sb & ~B_MAC_AX_BTGS1_NOTIFY;
57678e93258fSBjoern A. Zeeb 	if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
57688e93258fSBjoern A. Zeeb 		fw_sb = fw_sb | MAC_AX_NOTIFY_PWR_MAJOR;
57698e93258fSBjoern A. Zeeb 	else
57708e93258fSBjoern A. Zeeb 		fw_sb = fw_sb | MAC_AX_NOTIFY_TP_MAJOR;
57718e93258fSBjoern A. Zeeb 	val = FIELD_GET(B_MAC_AX_SB_DRV_MASK, val);
57728e93258fSBjoern A. Zeeb 	val = B_AX_TOGGLE |
57738e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_MAC_AX_SB_DRV_MASK, val) |
57748e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_MAC_AX_SB_FW_MASK, fw_sb);
57758e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_SCOREBOARD, val);
57768e93258fSBjoern A. Zeeb 	fsleep(1000); /* avoid BT FW loss information */
57778e93258fSBjoern A. Zeeb }
57788e93258fSBjoern A. Zeeb 
57798e93258fSBjoern A. Zeeb u32 rtw89_mac_get_sb(struct rtw89_dev *rtwdev)
57808e93258fSBjoern A. Zeeb {
57818e93258fSBjoern A. Zeeb 	return rtw89_read32(rtwdev, R_AX_SCOREBOARD);
57828e93258fSBjoern A. Zeeb }
57838e93258fSBjoern A. Zeeb 
57848e93258fSBjoern A. Zeeb int rtw89_mac_cfg_ctrl_path(struct rtw89_dev *rtwdev, bool wl)
57858e93258fSBjoern A. Zeeb {
57868e93258fSBjoern A. Zeeb 	u8 val = rtw89_read8(rtwdev, R_AX_SYS_SDIO_CTRL + 3);
57878e93258fSBjoern A. Zeeb 
57888e93258fSBjoern A. Zeeb 	val = wl ? val | BIT(2) : val & ~BIT(2);
57898e93258fSBjoern A. Zeeb 	rtw89_write8(rtwdev, R_AX_SYS_SDIO_CTRL + 3, val);
57908e93258fSBjoern A. Zeeb 
57918e93258fSBjoern A. Zeeb 	return 0;
57928e93258fSBjoern A. Zeeb }
57938e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_cfg_ctrl_path);
57948e93258fSBjoern A. Zeeb 
57958e93258fSBjoern A. Zeeb int rtw89_mac_cfg_ctrl_path_v1(struct rtw89_dev *rtwdev, bool wl)
57968e93258fSBjoern A. Zeeb {
57978e93258fSBjoern A. Zeeb 	struct rtw89_btc *btc = &rtwdev->btc;
57988e93258fSBjoern A. Zeeb 	struct rtw89_btc_dm *dm = &btc->dm;
57998e93258fSBjoern A. Zeeb 	struct rtw89_mac_ax_gnt *g = dm->gnt.band;
58008e93258fSBjoern A. Zeeb 	int i;
58018e93258fSBjoern A. Zeeb 
58028e93258fSBjoern A. Zeeb 	if (wl)
58038e93258fSBjoern A. Zeeb 		return 0;
58048e93258fSBjoern A. Zeeb 
58058e93258fSBjoern A. Zeeb 	for (i = 0; i < RTW89_PHY_MAX; i++) {
58068e93258fSBjoern A. Zeeb 		g[i].gnt_bt_sw_en = 1;
58078e93258fSBjoern A. Zeeb 		g[i].gnt_bt = 1;
58088e93258fSBjoern A. Zeeb 		g[i].gnt_wl_sw_en = 1;
58098e93258fSBjoern A. Zeeb 		g[i].gnt_wl = 0;
58108e93258fSBjoern A. Zeeb 	}
58118e93258fSBjoern A. Zeeb 
58128e93258fSBjoern A. Zeeb 	return rtw89_mac_cfg_gnt_v1(rtwdev, &dm->gnt);
58138e93258fSBjoern A. Zeeb }
58148e93258fSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_cfg_ctrl_path_v1);
58158e93258fSBjoern A. Zeeb 
58168e93258fSBjoern A. Zeeb bool rtw89_mac_get_ctrl_path(struct rtw89_dev *rtwdev)
58178e93258fSBjoern A. Zeeb {
5818e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
5819e2340276SBjoern A. Zeeb 	u8 val = 0;
58208e93258fSBjoern A. Zeeb 
5821*6d67aabdSBjoern A. Zeeb 	if (chip->chip_id == RTL8852C || chip->chip_id == RTL8922A)
5822e2340276SBjoern A. Zeeb 		return false;
5823*6d67aabdSBjoern A. Zeeb 	else if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
5824e2340276SBjoern A. Zeeb 		val = rtw89_read8_mask(rtwdev, R_AX_SYS_SDIO_CTRL + 3,
5825e2340276SBjoern A. Zeeb 				       B_AX_LTE_MUX_CTRL_PATH >> 24);
5826e2340276SBjoern A. Zeeb 
5827e2340276SBjoern A. Zeeb 	return !!val;
58288e93258fSBjoern A. Zeeb }
58298e93258fSBjoern A. Zeeb 
5830*6d67aabdSBjoern A. Zeeb static u16 rtw89_mac_get_plt_cnt_ax(struct rtw89_dev *rtwdev, u8 band)
58318e93258fSBjoern A. Zeeb {
58328e93258fSBjoern A. Zeeb 	u32 reg;
58338e93258fSBjoern A. Zeeb 	u16 cnt;
58348e93258fSBjoern A. Zeeb 
5835*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BT_PLT, band);
58368e93258fSBjoern A. Zeeb 	cnt = rtw89_read32_mask(rtwdev, reg, B_AX_BT_PLT_PKT_CNT_MASK);
58378e93258fSBjoern A. Zeeb 	rtw89_write16_set(rtwdev, reg, B_AX_BT_PLT_RST);
58388e93258fSBjoern A. Zeeb 
58398e93258fSBjoern A. Zeeb 	return cnt;
58408e93258fSBjoern A. Zeeb }
58418e93258fSBjoern A. Zeeb 
5842e2340276SBjoern A. Zeeb static void rtw89_mac_bfee_standby_timer(struct rtw89_dev *rtwdev, u8 mac_idx,
5843e2340276SBjoern A. Zeeb 					 bool keep)
5844e2340276SBjoern A. Zeeb {
5845e2340276SBjoern A. Zeeb 	u32 reg;
5846e2340276SBjoern A. Zeeb 
5847*6d67aabdSBjoern A. Zeeb 	if (rtwdev->chip->chip_gen != RTW89_CHIP_AX)
5848*6d67aabdSBjoern A. Zeeb 		return;
5849*6d67aabdSBjoern A. Zeeb 
5850e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BF, "set bfee standby_timer to %d\n", keep);
5851*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BFMEE_RESP_OPTION, mac_idx);
5852e2340276SBjoern A. Zeeb 	if (keep) {
5853e2340276SBjoern A. Zeeb 		set_bit(RTW89_FLAG_BFEE_TIMER_KEEP, rtwdev->flags);
5854e2340276SBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, reg, B_AX_BFMEE_BFRP_RX_STANDBY_TIMER_MASK,
5855e2340276SBjoern A. Zeeb 				   BFRP_RX_STANDBY_TIMER_KEEP);
5856e2340276SBjoern A. Zeeb 	} else {
5857e2340276SBjoern A. Zeeb 		clear_bit(RTW89_FLAG_BFEE_TIMER_KEEP, rtwdev->flags);
5858e2340276SBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, reg, B_AX_BFMEE_BFRP_RX_STANDBY_TIMER_MASK,
5859e2340276SBjoern A. Zeeb 				   BFRP_RX_STANDBY_TIMER_RELEASE);
5860e2340276SBjoern A. Zeeb 	}
5861e2340276SBjoern A. Zeeb }
5862e2340276SBjoern A. Zeeb 
5863*6d67aabdSBjoern A. Zeeb void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en)
58648e93258fSBjoern A. Zeeb {
5865*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
58668e93258fSBjoern A. Zeeb 	u32 reg;
5867*6d67aabdSBjoern A. Zeeb 	u32 mask = mac->bfee_ctrl.mask;
58688e93258fSBjoern A. Zeeb 
58698e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BF, "set bfee ndpa_en to %d\n", en);
5870*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, mac->bfee_ctrl.addr, mac_idx);
58718e93258fSBjoern A. Zeeb 	if (en) {
58728e93258fSBjoern A. Zeeb 		set_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags);
58738e93258fSBjoern A. Zeeb 		rtw89_write32_set(rtwdev, reg, mask);
58748e93258fSBjoern A. Zeeb 	} else {
58758e93258fSBjoern A. Zeeb 		clear_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags);
58768e93258fSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, reg, mask);
58778e93258fSBjoern A. Zeeb 	}
58788e93258fSBjoern A. Zeeb }
58798e93258fSBjoern A. Zeeb 
5880*6d67aabdSBjoern A. Zeeb static int rtw89_mac_init_bfee_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
58818e93258fSBjoern A. Zeeb {
58828e93258fSBjoern A. Zeeb 	u32 reg;
58838e93258fSBjoern A. Zeeb 	u32 val32;
58848e93258fSBjoern A. Zeeb 	int ret;
58858e93258fSBjoern A. Zeeb 
58868e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
58878e93258fSBjoern A. Zeeb 	if (ret)
58888e93258fSBjoern A. Zeeb 		return ret;
58898e93258fSBjoern A. Zeeb 
58908e93258fSBjoern A. Zeeb 	/* AP mode set tx gid to 63 */
58918e93258fSBjoern A. Zeeb 	/* STA mode set tx gid to 0(default) */
5892*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BFMER_CTRL_0, mac_idx);
58938e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, B_AX_BFMER_NDP_BFEN);
58948e93258fSBjoern A. Zeeb 
5895*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_RRSC, mac_idx);
58968e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, CSI_RRSC_BMAP);
58978e93258fSBjoern A. Zeeb 
5898*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_BFMEE_RESP_OPTION, mac_idx);
5899e2340276SBjoern A. Zeeb 	val32 = FIELD_PREP(B_AX_BFMEE_NDP_RX_STANDBY_TIMER_MASK, NDP_RX_STANDBY_TIMER);
59008e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg, val32);
5901e2340276SBjoern A. Zeeb 	rtw89_mac_bfee_standby_timer(rtwdev, mac_idx, true);
59028e93258fSBjoern A. Zeeb 	rtw89_mac_bfee_ctrl(rtwdev, mac_idx, true);
59038e93258fSBjoern A. Zeeb 
5904*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx);
59058e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL |
59068e93258fSBjoern A. Zeeb 				       B_AX_BFMEE_USE_NSTS |
59078e93258fSBjoern A. Zeeb 				       B_AX_BFMEE_CSI_GID_SEL |
59088e93258fSBjoern A. Zeeb 				       B_AX_BFMEE_CSI_FORCE_RETE_EN);
5909*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_RATE, mac_idx);
59108e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, reg,
59118e93258fSBjoern A. Zeeb 		      u32_encode_bits(CSI_INIT_RATE_HT, B_AX_BFMEE_HT_CSI_RATE_MASK) |
59128e93258fSBjoern A. Zeeb 		      u32_encode_bits(CSI_INIT_RATE_VHT, B_AX_BFMEE_VHT_CSI_RATE_MASK) |
59138e93258fSBjoern A. Zeeb 		      u32_encode_bits(CSI_INIT_RATE_HE, B_AX_BFMEE_HE_CSI_RATE_MASK));
59148e93258fSBjoern A. Zeeb 
5915*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_CSIRPT_OPTION, mac_idx);
59168e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg,
59178e93258fSBjoern A. Zeeb 			  B_AX_CSIPRT_VHTSU_AID_EN | B_AX_CSIPRT_HESU_AID_EN);
59188e93258fSBjoern A. Zeeb 
59198e93258fSBjoern A. Zeeb 	return 0;
59208e93258fSBjoern A. Zeeb }
59218e93258fSBjoern A. Zeeb 
5922*6d67aabdSBjoern A. Zeeb static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev,
59238e93258fSBjoern A. Zeeb 					 struct ieee80211_vif *vif,
59248e93258fSBjoern A. Zeeb 					 struct ieee80211_sta *sta)
59258e93258fSBjoern A. Zeeb {
59268e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
59278e93258fSBjoern A. Zeeb 	u8 mac_idx = rtwvif->mac_idx;
59288e93258fSBjoern A. Zeeb 	u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1;
59298e93258fSBjoern A. Zeeb 	u8 port_sel = rtwvif->port;
59308e93258fSBjoern A. Zeeb 	u8 sound_dim = 3, t;
59318e93258fSBjoern A. Zeeb 	u8 *phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info;
59328e93258fSBjoern A. Zeeb 	u32 reg;
59338e93258fSBjoern A. Zeeb 	u16 val;
59348e93258fSBjoern A. Zeeb 	int ret;
59358e93258fSBjoern A. Zeeb 
59368e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
59378e93258fSBjoern A. Zeeb 	if (ret)
59388e93258fSBjoern A. Zeeb 		return ret;
59398e93258fSBjoern A. Zeeb 
59408e93258fSBjoern A. Zeeb 	if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) ||
59418e93258fSBjoern A. Zeeb 	    (phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) {
59428e93258fSBjoern A. Zeeb 		ldpc_en &= !!(phy_cap[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD);
59438e93258fSBjoern A. Zeeb 		stbc_en &= !!(phy_cap[2] & IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ);
59448e93258fSBjoern A. Zeeb 		t = FIELD_GET(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
59458e93258fSBjoern A. Zeeb 			      phy_cap[5]);
59468e93258fSBjoern A. Zeeb 		sound_dim = min(sound_dim, t);
59478e93258fSBjoern A. Zeeb 	}
59488e93258fSBjoern A. Zeeb 	if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) ||
59498e93258fSBjoern A. Zeeb 	    (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
59508e93258fSBjoern A. Zeeb 		ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
59518e93258fSBjoern A. Zeeb 		stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK);
59528e93258fSBjoern A. Zeeb 		t = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK,
59538e93258fSBjoern A. Zeeb 			      sta->deflink.vht_cap.cap);
59548e93258fSBjoern A. Zeeb 		sound_dim = min(sound_dim, t);
59558e93258fSBjoern A. Zeeb 	}
59568e93258fSBjoern A. Zeeb 	nc = min(nc, sound_dim);
59578e93258fSBjoern A. Zeeb 	nr = min(nr, sound_dim);
59588e93258fSBjoern A. Zeeb 
5959*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx);
59608e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL);
59618e93258fSBjoern A. Zeeb 
59628e93258fSBjoern A. Zeeb 	val = FIELD_PREP(B_AX_BFMEE_CSIINFO0_NC_MASK, nc) |
59638e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_AX_BFMEE_CSIINFO0_NR_MASK, nr) |
59648e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_AX_BFMEE_CSIINFO0_NG_MASK, ng) |
59658e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_AX_BFMEE_CSIINFO0_CB_MASK, cb) |
59668e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_AX_BFMEE_CSIINFO0_CS_MASK, cs) |
59678e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_AX_BFMEE_CSIINFO0_LDPC_EN, ldpc_en) |
59688e93258fSBjoern A. Zeeb 	      FIELD_PREP(B_AX_BFMEE_CSIINFO0_STBC_EN, stbc_en);
59698e93258fSBjoern A. Zeeb 
59708e93258fSBjoern A. Zeeb 	if (port_sel == 0)
5971*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx);
59728e93258fSBjoern A. Zeeb 	else
5973*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_1, mac_idx);
59748e93258fSBjoern A. Zeeb 
59758e93258fSBjoern A. Zeeb 	rtw89_write16(rtwdev, reg, val);
59768e93258fSBjoern A. Zeeb 
59778e93258fSBjoern A. Zeeb 	return 0;
59788e93258fSBjoern A. Zeeb }
59798e93258fSBjoern A. Zeeb 
5980*6d67aabdSBjoern A. Zeeb static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev,
59818e93258fSBjoern A. Zeeb 				 struct ieee80211_vif *vif,
59828e93258fSBjoern A. Zeeb 				 struct ieee80211_sta *sta)
59838e93258fSBjoern A. Zeeb {
59848e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
59858e93258fSBjoern A. Zeeb 	u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M);
59868e93258fSBjoern A. Zeeb 	u32 reg;
59878e93258fSBjoern A. Zeeb 	u8 mac_idx = rtwvif->mac_idx;
59888e93258fSBjoern A. Zeeb 	int ret;
59898e93258fSBjoern A. Zeeb 
59908e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
59918e93258fSBjoern A. Zeeb 	if (ret)
59928e93258fSBjoern A. Zeeb 		return ret;
59938e93258fSBjoern A. Zeeb 
59948e93258fSBjoern A. Zeeb 	if (sta->deflink.he_cap.has_he) {
59958e93258fSBjoern A. Zeeb 		rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) |
59968e93258fSBjoern A. Zeeb 			 BIT(RTW89_MAC_BF_RRSC_HE_MSC3) |
59978e93258fSBjoern A. Zeeb 			 BIT(RTW89_MAC_BF_RRSC_HE_MSC5));
59988e93258fSBjoern A. Zeeb 	}
59998e93258fSBjoern A. Zeeb 	if (sta->deflink.vht_cap.vht_supported) {
60008e93258fSBjoern A. Zeeb 		rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) |
60018e93258fSBjoern A. Zeeb 			 BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) |
60028e93258fSBjoern A. Zeeb 			 BIT(RTW89_MAC_BF_RRSC_VHT_MSC5));
60038e93258fSBjoern A. Zeeb 	}
60048e93258fSBjoern A. Zeeb 	if (sta->deflink.ht_cap.ht_supported) {
60058e93258fSBjoern A. Zeeb 		rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) |
60068e93258fSBjoern A. Zeeb 			 BIT(RTW89_MAC_BF_RRSC_HT_MSC3) |
60078e93258fSBjoern A. Zeeb 			 BIT(RTW89_MAC_BF_RRSC_HT_MSC5));
60088e93258fSBjoern A. Zeeb 	}
6009*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx);
60108e93258fSBjoern A. Zeeb 	rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL);
60118e93258fSBjoern A. Zeeb 	rtw89_write32_clr(rtwdev, reg, B_AX_BFMEE_CSI_FORCE_RETE_EN);
60128e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev,
6013*6d67aabdSBjoern A. Zeeb 		      rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_RRSC, mac_idx),
60148e93258fSBjoern A. Zeeb 		      rrsc);
60158e93258fSBjoern A. Zeeb 
60168e93258fSBjoern A. Zeeb 	return 0;
60178e93258fSBjoern A. Zeeb }
60188e93258fSBjoern A. Zeeb 
6019*6d67aabdSBjoern A. Zeeb static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev,
6020*6d67aabdSBjoern A. Zeeb 				  struct ieee80211_vif *vif,
60218e93258fSBjoern A. Zeeb 				  struct ieee80211_sta *sta)
60228e93258fSBjoern A. Zeeb {
60238e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
60248e93258fSBjoern A. Zeeb 
60258e93258fSBjoern A. Zeeb 	if (rtw89_sta_has_beamformer_cap(sta)) {
60268e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_BF,
60278e93258fSBjoern A. Zeeb 			    "initialize bfee for new association\n");
6028*6d67aabdSBjoern A. Zeeb 		rtw89_mac_init_bfee_ax(rtwdev, rtwvif->mac_idx);
6029*6d67aabdSBjoern A. Zeeb 		rtw89_mac_set_csi_para_reg_ax(rtwdev, vif, sta);
6030*6d67aabdSBjoern A. Zeeb 		rtw89_mac_csi_rrsc_ax(rtwdev, vif, sta);
60318e93258fSBjoern A. Zeeb 	}
60328e93258fSBjoern A. Zeeb }
60338e93258fSBjoern A. Zeeb 
60348e93258fSBjoern A. Zeeb void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
60358e93258fSBjoern A. Zeeb 			   struct ieee80211_sta *sta)
60368e93258fSBjoern A. Zeeb {
60378e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
60388e93258fSBjoern A. Zeeb 
60398e93258fSBjoern A. Zeeb 	rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, false);
60408e93258fSBjoern A. Zeeb }
60418e93258fSBjoern A. Zeeb 
60428e93258fSBjoern A. Zeeb void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
60438e93258fSBjoern A. Zeeb 				struct ieee80211_bss_conf *conf)
60448e93258fSBjoern A. Zeeb {
60458e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
60468e93258fSBjoern A. Zeeb 	u8 mac_idx = rtwvif->mac_idx;
60478e93258fSBjoern A. Zeeb 	__le32 *p;
60488e93258fSBjoern A. Zeeb 
60498e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BF, "update bf GID table\n");
60508e93258fSBjoern A. Zeeb 
60518e93258fSBjoern A. Zeeb 	p = (__le32 *)conf->mu_group.membership;
6052*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev,
6053*6d67aabdSBjoern A. Zeeb 		      rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION_EN0, mac_idx),
60548e93258fSBjoern A. Zeeb 		      le32_to_cpu(p[0]));
6055*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev,
6056*6d67aabdSBjoern A. Zeeb 		      rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION_EN1, mac_idx),
60578e93258fSBjoern A. Zeeb 		      le32_to_cpu(p[1]));
60588e93258fSBjoern A. Zeeb 
60598e93258fSBjoern A. Zeeb 	p = (__le32 *)conf->mu_group.position;
6060*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION0, mac_idx),
60618e93258fSBjoern A. Zeeb 		      le32_to_cpu(p[0]));
6062*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION1, mac_idx),
60638e93258fSBjoern A. Zeeb 		      le32_to_cpu(p[1]));
6064*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION2, mac_idx),
60658e93258fSBjoern A. Zeeb 		      le32_to_cpu(p[2]));
6066*6d67aabdSBjoern A. Zeeb 	rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION3, mac_idx),
60678e93258fSBjoern A. Zeeb 		      le32_to_cpu(p[3]));
60688e93258fSBjoern A. Zeeb }
60698e93258fSBjoern A. Zeeb 
60708e93258fSBjoern A. Zeeb struct rtw89_mac_bf_monitor_iter_data {
60718e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev;
60728e93258fSBjoern A. Zeeb 	struct ieee80211_sta *down_sta;
60738e93258fSBjoern A. Zeeb 	int count;
60748e93258fSBjoern A. Zeeb };
60758e93258fSBjoern A. Zeeb 
60768e93258fSBjoern A. Zeeb static
60778e93258fSBjoern A. Zeeb void rtw89_mac_bf_monitor_calc_iter(void *data, struct ieee80211_sta *sta)
60788e93258fSBjoern A. Zeeb {
60798e93258fSBjoern A. Zeeb 	struct rtw89_mac_bf_monitor_iter_data *iter_data =
60808e93258fSBjoern A. Zeeb 				(struct rtw89_mac_bf_monitor_iter_data *)data;
60818e93258fSBjoern A. Zeeb 	struct ieee80211_sta *down_sta = iter_data->down_sta;
60828e93258fSBjoern A. Zeeb 	int *count = &iter_data->count;
60838e93258fSBjoern A. Zeeb 
60848e93258fSBjoern A. Zeeb 	if (down_sta == sta)
60858e93258fSBjoern A. Zeeb 		return;
60868e93258fSBjoern A. Zeeb 
60878e93258fSBjoern A. Zeeb 	if (rtw89_sta_has_beamformer_cap(sta))
60888e93258fSBjoern A. Zeeb 		(*count)++;
60898e93258fSBjoern A. Zeeb }
60908e93258fSBjoern A. Zeeb 
60918e93258fSBjoern A. Zeeb void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev,
60928e93258fSBjoern A. Zeeb 			       struct ieee80211_sta *sta, bool disconnect)
60938e93258fSBjoern A. Zeeb {
60948e93258fSBjoern A. Zeeb 	struct rtw89_mac_bf_monitor_iter_data data;
60958e93258fSBjoern A. Zeeb 
60968e93258fSBjoern A. Zeeb 	data.rtwdev = rtwdev;
60978e93258fSBjoern A. Zeeb 	data.down_sta = disconnect ? sta : NULL;
60988e93258fSBjoern A. Zeeb 	data.count = 0;
60998e93258fSBjoern A. Zeeb 	ieee80211_iterate_stations_atomic(rtwdev->hw,
61008e93258fSBjoern A. Zeeb 					  rtw89_mac_bf_monitor_calc_iter,
61018e93258fSBjoern A. Zeeb 					  &data);
61028e93258fSBjoern A. Zeeb 
61038e93258fSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_BF, "bfee STA count=%d\n", data.count);
61048e93258fSBjoern A. Zeeb 	if (data.count)
61058e93258fSBjoern A. Zeeb 		set_bit(RTW89_FLAG_BFEE_MON, rtwdev->flags);
61068e93258fSBjoern A. Zeeb 	else
61078e93258fSBjoern A. Zeeb 		clear_bit(RTW89_FLAG_BFEE_MON, rtwdev->flags);
61088e93258fSBjoern A. Zeeb }
61098e93258fSBjoern A. Zeeb 
61108e93258fSBjoern A. Zeeb void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev)
61118e93258fSBjoern A. Zeeb {
61128e93258fSBjoern A. Zeeb 	struct rtw89_traffic_stats *stats = &rtwdev->stats;
61138e93258fSBjoern A. Zeeb 	struct rtw89_vif *rtwvif;
61148e93258fSBjoern A. Zeeb 	bool en = stats->tx_tfc_lv <= stats->rx_tfc_lv;
61158e93258fSBjoern A. Zeeb 	bool old = test_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags);
6116e2340276SBjoern A. Zeeb 	bool keep_timer = true;
6117e2340276SBjoern A. Zeeb 	bool old_keep_timer;
6118e2340276SBjoern A. Zeeb 
6119e2340276SBjoern A. Zeeb 	old_keep_timer = test_bit(RTW89_FLAG_BFEE_TIMER_KEEP, rtwdev->flags);
6120e2340276SBjoern A. Zeeb 
6121e2340276SBjoern A. Zeeb 	if (stats->tx_tfc_lv <= RTW89_TFC_LOW && stats->rx_tfc_lv <= RTW89_TFC_LOW)
6122e2340276SBjoern A. Zeeb 		keep_timer = false;
6123e2340276SBjoern A. Zeeb 
6124e2340276SBjoern A. Zeeb 	if (keep_timer != old_keep_timer) {
6125e2340276SBjoern A. Zeeb 		rtw89_for_each_rtwvif(rtwdev, rtwvif)
6126e2340276SBjoern A. Zeeb 			rtw89_mac_bfee_standby_timer(rtwdev, rtwvif->mac_idx,
6127e2340276SBjoern A. Zeeb 						     keep_timer);
6128e2340276SBjoern A. Zeeb 	}
61298e93258fSBjoern A. Zeeb 
61308e93258fSBjoern A. Zeeb 	if (en == old)
61318e93258fSBjoern A. Zeeb 		return;
61328e93258fSBjoern A. Zeeb 
61338e93258fSBjoern A. Zeeb 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
61348e93258fSBjoern A. Zeeb 		rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, en);
61358e93258fSBjoern A. Zeeb }
61368e93258fSBjoern A. Zeeb 
61378e93258fSBjoern A. Zeeb static int
61388e93258fSBjoern A. Zeeb __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
61398e93258fSBjoern A. Zeeb 			u32 tx_time)
61408e93258fSBjoern A. Zeeb {
61418e93258fSBjoern A. Zeeb #define MAC_AX_DFLT_TX_TIME 5280
61428e93258fSBjoern A. Zeeb 	u8 mac_idx = rtwsta->rtwvif->mac_idx;
61438e93258fSBjoern A. Zeeb 	u32 max_tx_time = tx_time == 0 ? MAC_AX_DFLT_TX_TIME : tx_time;
61448e93258fSBjoern A. Zeeb 	u32 reg;
61458e93258fSBjoern A. Zeeb 	int ret = 0;
61468e93258fSBjoern A. Zeeb 
61478e93258fSBjoern A. Zeeb 	if (rtwsta->cctl_tx_time) {
61488e93258fSBjoern A. Zeeb 		rtwsta->ampdu_max_time = (max_tx_time - 512) >> 9;
61498e93258fSBjoern A. Zeeb 		ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta);
61508e93258fSBjoern A. Zeeb 	} else {
61518e93258fSBjoern A. Zeeb 		ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
61528e93258fSBjoern A. Zeeb 		if (ret) {
61538e93258fSBjoern A. Zeeb 			rtw89_warn(rtwdev, "failed to check cmac in set txtime\n");
61548e93258fSBjoern A. Zeeb 			return ret;
61558e93258fSBjoern A. Zeeb 		}
61568e93258fSBjoern A. Zeeb 
6157*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_AMPDU_AGG_LIMIT, mac_idx);
61588e93258fSBjoern A. Zeeb 		rtw89_write32_mask(rtwdev, reg, B_AX_AMPDU_MAX_TIME_MASK,
61598e93258fSBjoern A. Zeeb 				   max_tx_time >> 5);
61608e93258fSBjoern A. Zeeb 	}
61618e93258fSBjoern A. Zeeb 
61628e93258fSBjoern A. Zeeb 	return ret;
61638e93258fSBjoern A. Zeeb }
61648e93258fSBjoern A. Zeeb 
61658e93258fSBjoern A. Zeeb int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
61668e93258fSBjoern A. Zeeb 			  bool resume, u32 tx_time)
61678e93258fSBjoern A. Zeeb {
61688e93258fSBjoern A. Zeeb 	int ret = 0;
61698e93258fSBjoern A. Zeeb 
61708e93258fSBjoern A. Zeeb 	if (!resume) {
61718e93258fSBjoern A. Zeeb 		rtwsta->cctl_tx_time = true;
61728e93258fSBjoern A. Zeeb 		ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time);
61738e93258fSBjoern A. Zeeb 	} else {
61748e93258fSBjoern A. Zeeb 		ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time);
61758e93258fSBjoern A. Zeeb 		rtwsta->cctl_tx_time = false;
61768e93258fSBjoern A. Zeeb 	}
61778e93258fSBjoern A. Zeeb 
61788e93258fSBjoern A. Zeeb 	return ret;
61798e93258fSBjoern A. Zeeb }
61808e93258fSBjoern A. Zeeb 
61818e93258fSBjoern A. Zeeb int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
61828e93258fSBjoern A. Zeeb 			  u32 *tx_time)
61838e93258fSBjoern A. Zeeb {
61848e93258fSBjoern A. Zeeb 	u8 mac_idx = rtwsta->rtwvif->mac_idx;
61858e93258fSBjoern A. Zeeb 	u32 reg;
61868e93258fSBjoern A. Zeeb 	int ret = 0;
61878e93258fSBjoern A. Zeeb 
61888e93258fSBjoern A. Zeeb 	if (rtwsta->cctl_tx_time) {
61898e93258fSBjoern A. Zeeb 		*tx_time = (rtwsta->ampdu_max_time + 1) << 9;
61908e93258fSBjoern A. Zeeb 	} else {
61918e93258fSBjoern A. Zeeb 		ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
61928e93258fSBjoern A. Zeeb 		if (ret) {
61938e93258fSBjoern A. Zeeb 			rtw89_warn(rtwdev, "failed to check cmac in tx_time\n");
61948e93258fSBjoern A. Zeeb 			return ret;
61958e93258fSBjoern A. Zeeb 		}
61968e93258fSBjoern A. Zeeb 
6197*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_AMPDU_AGG_LIMIT, mac_idx);
61988e93258fSBjoern A. Zeeb 		*tx_time = rtw89_read32_mask(rtwdev, reg, B_AX_AMPDU_MAX_TIME_MASK) << 5;
61998e93258fSBjoern A. Zeeb 	}
62008e93258fSBjoern A. Zeeb 
62018e93258fSBjoern A. Zeeb 	return ret;
62028e93258fSBjoern A. Zeeb }
62038e93258fSBjoern A. Zeeb 
62048e93258fSBjoern A. Zeeb int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev,
62058e93258fSBjoern A. Zeeb 				 struct rtw89_sta *rtwsta,
62068e93258fSBjoern A. Zeeb 				 bool resume, u8 tx_retry)
62078e93258fSBjoern A. Zeeb {
62088e93258fSBjoern A. Zeeb 	int ret = 0;
62098e93258fSBjoern A. Zeeb 
62108e93258fSBjoern A. Zeeb 	rtwsta->data_tx_cnt_lmt = tx_retry;
62118e93258fSBjoern A. Zeeb 
62128e93258fSBjoern A. Zeeb 	if (!resume) {
62138e93258fSBjoern A. Zeeb 		rtwsta->cctl_tx_retry_limit = true;
62148e93258fSBjoern A. Zeeb 		ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta);
62158e93258fSBjoern A. Zeeb 	} else {
62168e93258fSBjoern A. Zeeb 		ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta);
62178e93258fSBjoern A. Zeeb 		rtwsta->cctl_tx_retry_limit = false;
62188e93258fSBjoern A. Zeeb 	}
62198e93258fSBjoern A. Zeeb 
62208e93258fSBjoern A. Zeeb 	return ret;
62218e93258fSBjoern A. Zeeb }
62228e93258fSBjoern A. Zeeb 
62238e93258fSBjoern A. Zeeb int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev,
62248e93258fSBjoern A. Zeeb 				 struct rtw89_sta *rtwsta, u8 *tx_retry)
62258e93258fSBjoern A. Zeeb {
62268e93258fSBjoern A. Zeeb 	u8 mac_idx = rtwsta->rtwvif->mac_idx;
62278e93258fSBjoern A. Zeeb 	u32 reg;
62288e93258fSBjoern A. Zeeb 	int ret = 0;
62298e93258fSBjoern A. Zeeb 
62308e93258fSBjoern A. Zeeb 	if (rtwsta->cctl_tx_retry_limit) {
62318e93258fSBjoern A. Zeeb 		*tx_retry = rtwsta->data_tx_cnt_lmt;
62328e93258fSBjoern A. Zeeb 	} else {
62338e93258fSBjoern A. Zeeb 		ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
62348e93258fSBjoern A. Zeeb 		if (ret) {
62358e93258fSBjoern A. Zeeb 			rtw89_warn(rtwdev, "failed to check cmac in rty_lmt\n");
62368e93258fSBjoern A. Zeeb 			return ret;
62378e93258fSBjoern A. Zeeb 		}
62388e93258fSBjoern A. Zeeb 
6239*6d67aabdSBjoern A. Zeeb 		reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TXCNT, mac_idx);
62408e93258fSBjoern A. Zeeb 		*tx_retry = rtw89_read32_mask(rtwdev, reg, B_AX_L_TXCNT_LMT_MASK);
62418e93258fSBjoern A. Zeeb 	}
62428e93258fSBjoern A. Zeeb 
62438e93258fSBjoern A. Zeeb 	return ret;
62448e93258fSBjoern A. Zeeb }
62458e93258fSBjoern A. Zeeb 
62468e93258fSBjoern A. Zeeb int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev,
62478e93258fSBjoern A. Zeeb 				 struct rtw89_vif *rtwvif, bool en)
62488e93258fSBjoern A. Zeeb {
6249*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
62508e93258fSBjoern A. Zeeb 	u8 mac_idx = rtwvif->mac_idx;
6251*6d67aabdSBjoern A. Zeeb 	u16 set = mac->muedca_ctrl.mask;
62528e93258fSBjoern A. Zeeb 	u32 reg;
62538e93258fSBjoern A. Zeeb 	u32 ret;
62548e93258fSBjoern A. Zeeb 
62558e93258fSBjoern A. Zeeb 	ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
62568e93258fSBjoern A. Zeeb 	if (ret)
62578e93258fSBjoern A. Zeeb 		return ret;
62588e93258fSBjoern A. Zeeb 
6259*6d67aabdSBjoern A. Zeeb 	reg = rtw89_mac_reg_by_idx(rtwdev, mac->muedca_ctrl.addr, mac_idx);
62608e93258fSBjoern A. Zeeb 	if (en)
62618e93258fSBjoern A. Zeeb 		rtw89_write16_set(rtwdev, reg, set);
62628e93258fSBjoern A. Zeeb 	else
62638e93258fSBjoern A. Zeeb 		rtw89_write16_clr(rtwdev, reg, set);
62648e93258fSBjoern A. Zeeb 
62658e93258fSBjoern A. Zeeb 	return 0;
62668e93258fSBjoern A. Zeeb }
62678e93258fSBjoern A. Zeeb 
6268*6d67aabdSBjoern A. Zeeb static
6269*6d67aabdSBjoern A. Zeeb int rtw89_mac_write_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 mask)
62708e93258fSBjoern A. Zeeb {
62718e93258fSBjoern A. Zeeb 	u32 val32;
62728e93258fSBjoern A. Zeeb 	int ret;
62738e93258fSBjoern A. Zeeb 
62748e93258fSBjoern A. Zeeb 	val32 = FIELD_PREP(B_AX_WL_XTAL_SI_ADDR_MASK, offset) |
62758e93258fSBjoern A. Zeeb 		FIELD_PREP(B_AX_WL_XTAL_SI_DATA_MASK, val) |
62768e93258fSBjoern A. Zeeb 		FIELD_PREP(B_AX_WL_XTAL_SI_BITMASK_MASK, mask) |
62778e93258fSBjoern A. Zeeb 		FIELD_PREP(B_AX_WL_XTAL_SI_MODE_MASK, XTAL_SI_NORMAL_WRITE) |
62788e93258fSBjoern A. Zeeb 		FIELD_PREP(B_AX_WL_XTAL_SI_CMD_POLL, 1);
62798e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_WLAN_XTAL_SI_CTRL, val32);
62808e93258fSBjoern A. Zeeb 
62818e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_WL_XTAL_SI_CMD_POLL),
62828e93258fSBjoern A. Zeeb 				50, 50000, false, rtwdev, R_AX_WLAN_XTAL_SI_CTRL);
62838e93258fSBjoern A. Zeeb 	if (ret) {
62848e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "xtal si not ready(W): offset=%x val=%x mask=%x\n",
62858e93258fSBjoern A. Zeeb 			   offset, val, mask);
62868e93258fSBjoern A. Zeeb 		return ret;
62878e93258fSBjoern A. Zeeb 	}
62888e93258fSBjoern A. Zeeb 
62898e93258fSBjoern A. Zeeb 	return 0;
62908e93258fSBjoern A. Zeeb }
62918e93258fSBjoern A. Zeeb 
6292*6d67aabdSBjoern A. Zeeb static
6293*6d67aabdSBjoern A. Zeeb int rtw89_mac_read_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 *val)
62948e93258fSBjoern A. Zeeb {
62958e93258fSBjoern A. Zeeb 	u32 val32;
62968e93258fSBjoern A. Zeeb 	int ret;
62978e93258fSBjoern A. Zeeb 
62988e93258fSBjoern A. Zeeb 	val32 = FIELD_PREP(B_AX_WL_XTAL_SI_ADDR_MASK, offset) |
62998e93258fSBjoern A. Zeeb 		FIELD_PREP(B_AX_WL_XTAL_SI_DATA_MASK, 0x00) |
63008e93258fSBjoern A. Zeeb 		FIELD_PREP(B_AX_WL_XTAL_SI_BITMASK_MASK, 0x00) |
63018e93258fSBjoern A. Zeeb 		FIELD_PREP(B_AX_WL_XTAL_SI_MODE_MASK, XTAL_SI_NORMAL_READ) |
63028e93258fSBjoern A. Zeeb 		FIELD_PREP(B_AX_WL_XTAL_SI_CMD_POLL, 1);
63038e93258fSBjoern A. Zeeb 	rtw89_write32(rtwdev, R_AX_WLAN_XTAL_SI_CTRL, val32);
63048e93258fSBjoern A. Zeeb 
63058e93258fSBjoern A. Zeeb 	ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_WL_XTAL_SI_CMD_POLL),
63068e93258fSBjoern A. Zeeb 				50, 50000, false, rtwdev, R_AX_WLAN_XTAL_SI_CTRL);
63078e93258fSBjoern A. Zeeb 	if (ret) {
63088e93258fSBjoern A. Zeeb 		rtw89_warn(rtwdev, "xtal si not ready(R): offset=%x\n", offset);
63098e93258fSBjoern A. Zeeb 		return ret;
63108e93258fSBjoern A. Zeeb 	}
63118e93258fSBjoern A. Zeeb 
63128e93258fSBjoern A. Zeeb 	*val = rtw89_read8(rtwdev, R_AX_WLAN_XTAL_SI_CTRL + 1);
63138e93258fSBjoern A. Zeeb 
63148e93258fSBjoern A. Zeeb 	return 0;
63158e93258fSBjoern A. Zeeb }
6316e2340276SBjoern A. Zeeb 
6317e2340276SBjoern A. Zeeb static
6318e2340276SBjoern A. Zeeb void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta)
6319e2340276SBjoern A. Zeeb {
6320e2340276SBjoern A. Zeeb 	static const enum rtw89_pkt_drop_sel sels[] = {
6321e2340276SBjoern A. Zeeb 		RTW89_PKT_DROP_SEL_MACID_BE_ONCE,
6322e2340276SBjoern A. Zeeb 		RTW89_PKT_DROP_SEL_MACID_BK_ONCE,
6323e2340276SBjoern A. Zeeb 		RTW89_PKT_DROP_SEL_MACID_VI_ONCE,
6324e2340276SBjoern A. Zeeb 		RTW89_PKT_DROP_SEL_MACID_VO_ONCE,
6325e2340276SBjoern A. Zeeb 	};
6326e2340276SBjoern A. Zeeb 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
6327e2340276SBjoern A. Zeeb 	struct rtw89_pkt_drop_params params = {0};
6328e2340276SBjoern A. Zeeb 	int i;
6329e2340276SBjoern A. Zeeb 
6330e2340276SBjoern A. Zeeb 	params.mac_band = RTW89_MAC_0;
6331e2340276SBjoern A. Zeeb 	params.macid = rtwsta->mac_id;
6332e2340276SBjoern A. Zeeb 	params.port = rtwvif->port;
6333e2340276SBjoern A. Zeeb 	params.mbssid = 0;
6334e2340276SBjoern A. Zeeb 	params.tf_trs = rtwvif->trigger;
6335e2340276SBjoern A. Zeeb 
6336e2340276SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(sels); i++) {
6337e2340276SBjoern A. Zeeb 		params.sel = sels[i];
6338e2340276SBjoern A. Zeeb 		rtw89_fw_h2c_pkt_drop(rtwdev, &params);
6339e2340276SBjoern A. Zeeb 	}
6340e2340276SBjoern A. Zeeb }
6341e2340276SBjoern A. Zeeb 
6342e2340276SBjoern A. Zeeb static void rtw89_mac_pkt_drop_vif_iter(void *data, struct ieee80211_sta *sta)
6343e2340276SBjoern A. Zeeb {
6344e2340276SBjoern A. Zeeb 	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
6345e2340276SBjoern A. Zeeb 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
6346e2340276SBjoern A. Zeeb 	struct rtw89_dev *rtwdev = rtwvif->rtwdev;
6347e2340276SBjoern A. Zeeb 	struct rtw89_vif *target = data;
6348e2340276SBjoern A. Zeeb 
6349e2340276SBjoern A. Zeeb 	if (rtwvif != target)
6350e2340276SBjoern A. Zeeb 		return;
6351e2340276SBjoern A. Zeeb 
6352e2340276SBjoern A. Zeeb 	rtw89_mac_pkt_drop_sta(rtwdev, rtwsta);
6353e2340276SBjoern A. Zeeb }
6354e2340276SBjoern A. Zeeb 
6355e2340276SBjoern A. Zeeb void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
6356e2340276SBjoern A. Zeeb {
6357e2340276SBjoern A. Zeeb 	ieee80211_iterate_stations_atomic(rtwdev->hw,
6358e2340276SBjoern A. Zeeb 					  rtw89_mac_pkt_drop_vif_iter,
6359e2340276SBjoern A. Zeeb 					  rtwvif);
6360e2340276SBjoern A. Zeeb }
6361e2340276SBjoern A. Zeeb 
6362e2340276SBjoern A. Zeeb int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev,
6363e2340276SBjoern A. Zeeb 					enum rtw89_mac_idx band)
6364e2340276SBjoern A. Zeeb {
6365*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
6366e2340276SBjoern A. Zeeb 	struct rtw89_pkt_drop_params params = {0};
6367e2340276SBjoern A. Zeeb 	bool empty;
6368e2340276SBjoern A. Zeeb 	int i, ret = 0, try_cnt = 3;
6369e2340276SBjoern A. Zeeb 
6370e2340276SBjoern A. Zeeb 	params.mac_band = band;
6371e2340276SBjoern A. Zeeb 	params.sel = RTW89_PKT_DROP_SEL_BAND_ONCE;
6372e2340276SBjoern A. Zeeb 
6373e2340276SBjoern A. Zeeb 	for (i = 0; i < try_cnt; i++) {
6374*6d67aabdSBjoern A. Zeeb 		ret = read_poll_timeout(mac->is_txq_empty, empty, empty, 50,
6375e2340276SBjoern A. Zeeb 					50000, false, rtwdev);
6376e2340276SBjoern A. Zeeb 		if (ret && !RTW89_CHK_FW_FEATURE(NO_PACKET_DROP, &rtwdev->fw))
6377e2340276SBjoern A. Zeeb 			rtw89_fw_h2c_pkt_drop(rtwdev, &params);
6378e2340276SBjoern A. Zeeb 		else
6379e2340276SBjoern A. Zeeb 			return 0;
6380e2340276SBjoern A. Zeeb 	}
6381e2340276SBjoern A. Zeeb 	return ret;
6382e2340276SBjoern A. Zeeb }
6383*6d67aabdSBjoern A. Zeeb 
6384*6d67aabdSBjoern A. Zeeb int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable)
6385*6d67aabdSBjoern A. Zeeb {
6386*6d67aabdSBjoern A. Zeeb 	struct rtw89_mac_h2c_info h2c_info = {};
6387*6d67aabdSBjoern A. Zeeb 	struct rtw89_mac_c2h_info c2h_info = {};
6388*6d67aabdSBjoern A. Zeeb 	u32 ret;
6389*6d67aabdSBjoern A. Zeeb 
6390*6d67aabdSBjoern A. Zeeb 	h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_WOW_CPUIO_RX_CTRL;
6391*6d67aabdSBjoern A. Zeeb 	h2c_info.content_len = sizeof(h2c_info.u.hdr);
6392*6d67aabdSBjoern A. Zeeb 	h2c_info.u.hdr.w0 = u32_encode_bits(wow_enable, RTW89_H2CREG_WOW_CPUIO_RX_CTRL_EN);
6393*6d67aabdSBjoern A. Zeeb 
6394*6d67aabdSBjoern A. Zeeb 	ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info);
6395*6d67aabdSBjoern A. Zeeb 	if (ret)
6396*6d67aabdSBjoern A. Zeeb 		return ret;
6397*6d67aabdSBjoern A. Zeeb 
6398*6d67aabdSBjoern A. Zeeb 	if (c2h_info.id != RTW89_FWCMD_C2HREG_FUNC_WOW_CPUIO_RX_ACK)
6399*6d67aabdSBjoern A. Zeeb 		ret = -EINVAL;
6400*6d67aabdSBjoern A. Zeeb 
6401*6d67aabdSBjoern A. Zeeb 	return ret;
6402*6d67aabdSBjoern A. Zeeb }
6403*6d67aabdSBjoern A. Zeeb 
6404*6d67aabdSBjoern A. Zeeb static int rtw89_wow_config_mac_ax(struct rtw89_dev *rtwdev, bool enable_wow)
6405*6d67aabdSBjoern A. Zeeb {
6406*6d67aabdSBjoern A. Zeeb 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
6407*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
6408*6d67aabdSBjoern A. Zeeb 	int ret;
6409*6d67aabdSBjoern A. Zeeb 
6410*6d67aabdSBjoern A. Zeeb 	if (enable_wow) {
6411*6d67aabdSBjoern A. Zeeb 		ret = rtw89_mac_resize_ple_rx_quota(rtwdev, true);
6412*6d67aabdSBjoern A. Zeeb 		if (ret) {
6413*6d67aabdSBjoern A. Zeeb 			rtw89_err(rtwdev, "[ERR]patch rx qta %d\n", ret);
6414*6d67aabdSBjoern A. Zeeb 			return ret;
6415*6d67aabdSBjoern A. Zeeb 		}
6416*6d67aabdSBjoern A. Zeeb 
6417*6d67aabdSBjoern A. Zeeb 		rtw89_write32_set(rtwdev, R_AX_RX_FUNCTION_STOP, B_AX_HDR_RX_STOP);
6418*6d67aabdSBjoern A. Zeeb 		rtw89_mac_cpu_io_rx(rtwdev, enable_wow);
6419*6d67aabdSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, mac->rx_fltr, B_AX_SNIFFER_MODE);
6420*6d67aabdSBjoern A. Zeeb 		rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false);
6421*6d67aabdSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_ACTION_FWD0, 0);
6422*6d67aabdSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_ACTION_FWD1, 0);
6423*6d67aabdSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_TF_FWD, 0);
6424*6d67aabdSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_HW_RPT_FWD, 0);
6425*6d67aabdSBjoern A. Zeeb 
6426*6d67aabdSBjoern A. Zeeb 		if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
6427*6d67aabdSBjoern A. Zeeb 			rtw89_write8(rtwdev, R_BE_DBG_WOW_READY, WOWLAN_NOT_READY);
6428*6d67aabdSBjoern A. Zeeb 		else
6429*6d67aabdSBjoern A. Zeeb 			rtw89_write32_set(rtwdev, R_AX_DBG_WOW,
6430*6d67aabdSBjoern A. Zeeb 					  B_AX_DBG_WOW_CPU_IO_RX_EN);
6431*6d67aabdSBjoern A. Zeeb 	} else {
6432*6d67aabdSBjoern A. Zeeb 		ret = rtw89_mac_resize_ple_rx_quota(rtwdev, false);
6433*6d67aabdSBjoern A. Zeeb 		if (ret) {
6434*6d67aabdSBjoern A. Zeeb 			rtw89_err(rtwdev, "[ERR]patch rx qta %d\n", ret);
6435*6d67aabdSBjoern A. Zeeb 			return ret;
6436*6d67aabdSBjoern A. Zeeb 		}
6437*6d67aabdSBjoern A. Zeeb 
6438*6d67aabdSBjoern A. Zeeb 		rtw89_mac_cpu_io_rx(rtwdev, enable_wow);
6439*6d67aabdSBjoern A. Zeeb 		rtw89_write32_clr(rtwdev, R_AX_RX_FUNCTION_STOP, B_AX_HDR_RX_STOP);
6440*6d67aabdSBjoern A. Zeeb 		rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
6441*6d67aabdSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_ACTION_FWD0, TRXCFG_MPDU_PROC_ACT_FRWD);
6442*6d67aabdSBjoern A. Zeeb 		rtw89_write32(rtwdev, R_AX_TF_FWD, TRXCFG_MPDU_PROC_TF_FRWD);
6443*6d67aabdSBjoern A. Zeeb 	}
6444*6d67aabdSBjoern A. Zeeb 
6445*6d67aabdSBjoern A. Zeeb 	return 0;
6446*6d67aabdSBjoern A. Zeeb }
6447*6d67aabdSBjoern A. Zeeb 
6448*6d67aabdSBjoern A. Zeeb static u8 rtw89_fw_get_rdy_ax(struct rtw89_dev *rtwdev, enum rtw89_fwdl_check_type type)
6449*6d67aabdSBjoern A. Zeeb {
6450*6d67aabdSBjoern A. Zeeb 	u8 val = rtw89_read8(rtwdev, R_AX_WCPU_FW_CTRL);
6451*6d67aabdSBjoern A. Zeeb 
6452*6d67aabdSBjoern A. Zeeb 	return FIELD_GET(B_AX_WCPU_FWDL_STS_MASK, val);
6453*6d67aabdSBjoern A. Zeeb }
6454*6d67aabdSBjoern A. Zeeb 
6455*6d67aabdSBjoern A. Zeeb static
6456*6d67aabdSBjoern A. Zeeb int rtw89_fwdl_check_path_ready_ax(struct rtw89_dev *rtwdev,
6457*6d67aabdSBjoern A. Zeeb 				   bool h2c_or_fwdl)
6458*6d67aabdSBjoern A. Zeeb {
6459*6d67aabdSBjoern A. Zeeb 	u8 check = h2c_or_fwdl ? B_AX_H2C_PATH_RDY : B_AX_FWDL_PATH_RDY;
6460*6d67aabdSBjoern A. Zeeb 	u8 val;
6461*6d67aabdSBjoern A. Zeeb 
6462*6d67aabdSBjoern A. Zeeb 	return read_poll_timeout_atomic(rtw89_read8, val, val & check,
6463*6d67aabdSBjoern A. Zeeb 					1, FWDL_WAIT_CNT, false,
6464*6d67aabdSBjoern A. Zeeb 					rtwdev, R_AX_WCPU_FW_CTRL);
6465*6d67aabdSBjoern A. Zeeb }
6466*6d67aabdSBjoern A. Zeeb 
6467*6d67aabdSBjoern A. Zeeb const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
6468*6d67aabdSBjoern A. Zeeb 	.band1_offset = RTW89_MAC_AX_BAND_REG_OFFSET,
6469*6d67aabdSBjoern A. Zeeb 	.filter_model_addr = R_AX_FILTER_MODEL_ADDR,
6470*6d67aabdSBjoern A. Zeeb 	.indir_access_addr = R_AX_INDIR_ACCESS_ENTRY,
6471*6d67aabdSBjoern A. Zeeb 	.mem_base_addrs = rtw89_mac_mem_base_addrs_ax,
6472*6d67aabdSBjoern A. Zeeb 	.rx_fltr = R_AX_RX_FLTR_OPT,
6473*6d67aabdSBjoern A. Zeeb 	.port_base = &rtw89_port_base_ax,
6474*6d67aabdSBjoern A. Zeeb 	.agg_len_ht = R_AX_AGG_LEN_HT_0,
6475*6d67aabdSBjoern A. Zeeb 	.ps_status = R_AX_PPWRBIT_SETTING,
6476*6d67aabdSBjoern A. Zeeb 
6477*6d67aabdSBjoern A. Zeeb 	.muedca_ctrl = {
6478*6d67aabdSBjoern A. Zeeb 		.addr = R_AX_MUEDCA_EN,
6479*6d67aabdSBjoern A. Zeeb 		.mask = B_AX_MUEDCA_EN_0 | B_AX_SET_MUEDCATIMER_TF_0,
6480*6d67aabdSBjoern A. Zeeb 	},
6481*6d67aabdSBjoern A. Zeeb 	.bfee_ctrl = {
6482*6d67aabdSBjoern A. Zeeb 		.addr = R_AX_BFMEE_RESP_OPTION,
6483*6d67aabdSBjoern A. Zeeb 		.mask = B_AX_BFMEE_HT_NDPA_EN | B_AX_BFMEE_VHT_NDPA_EN |
6484*6d67aabdSBjoern A. Zeeb 			B_AX_BFMEE_HE_NDPA_EN,
6485*6d67aabdSBjoern A. Zeeb 	},
6486*6d67aabdSBjoern A. Zeeb 	.narrow_bw_ru_dis = {
6487*6d67aabdSBjoern A. Zeeb 		.addr = R_AX_RXTRIG_TEST_USER_2,
6488*6d67aabdSBjoern A. Zeeb 		.mask = B_AX_RXTRIG_RU26_DIS,
6489*6d67aabdSBjoern A. Zeeb 	},
6490*6d67aabdSBjoern A. Zeeb 	.wow_ctrl = {.addr = R_AX_WOW_CTRL, .mask = B_AX_WOW_WOWEN,},
6491*6d67aabdSBjoern A. Zeeb 
6492*6d67aabdSBjoern A. Zeeb 	.check_mac_en = rtw89_mac_check_mac_en_ax,
6493*6d67aabdSBjoern A. Zeeb 	.sys_init = sys_init_ax,
6494*6d67aabdSBjoern A. Zeeb 	.trx_init = trx_init_ax,
6495*6d67aabdSBjoern A. Zeeb 	.hci_func_en = rtw89_mac_hci_func_en_ax,
6496*6d67aabdSBjoern A. Zeeb 	.dmac_func_pre_en = rtw89_mac_dmac_func_pre_en_ax,
6497*6d67aabdSBjoern A. Zeeb 	.dle_func_en = dle_func_en_ax,
6498*6d67aabdSBjoern A. Zeeb 	.dle_clk_en = dle_clk_en_ax,
6499*6d67aabdSBjoern A. Zeeb 	.bf_assoc = rtw89_mac_bf_assoc_ax,
6500*6d67aabdSBjoern A. Zeeb 
6501*6d67aabdSBjoern A. Zeeb 	.typ_fltr_opt = rtw89_mac_typ_fltr_opt_ax,
6502*6d67aabdSBjoern A. Zeeb 	.cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_ax,
6503*6d67aabdSBjoern A. Zeeb 
6504*6d67aabdSBjoern A. Zeeb 	.dle_mix_cfg = dle_mix_cfg_ax,
6505*6d67aabdSBjoern A. Zeeb 	.chk_dle_rdy = chk_dle_rdy_ax,
6506*6d67aabdSBjoern A. Zeeb 	.dle_buf_req = dle_buf_req_ax,
6507*6d67aabdSBjoern A. Zeeb 	.hfc_func_en = hfc_func_en_ax,
6508*6d67aabdSBjoern A. Zeeb 	.hfc_h2c_cfg = hfc_h2c_cfg_ax,
6509*6d67aabdSBjoern A. Zeeb 	.hfc_mix_cfg = hfc_mix_cfg_ax,
6510*6d67aabdSBjoern A. Zeeb 	.hfc_get_mix_info = hfc_get_mix_info_ax,
6511*6d67aabdSBjoern A. Zeeb 	.wde_quota_cfg = wde_quota_cfg_ax,
6512*6d67aabdSBjoern A. Zeeb 	.ple_quota_cfg = ple_quota_cfg_ax,
6513*6d67aabdSBjoern A. Zeeb 	.set_cpuio = set_cpuio_ax,
6514*6d67aabdSBjoern A. Zeeb 	.dle_quota_change = dle_quota_change_ax,
6515*6d67aabdSBjoern A. Zeeb 
6516*6d67aabdSBjoern A. Zeeb 	.disable_cpu = rtw89_mac_disable_cpu_ax,
6517*6d67aabdSBjoern A. Zeeb 	.fwdl_enable_wcpu = rtw89_mac_enable_cpu_ax,
6518*6d67aabdSBjoern A. Zeeb 	.fwdl_get_status = rtw89_fw_get_rdy_ax,
6519*6d67aabdSBjoern A. Zeeb 	.fwdl_check_path_ready = rtw89_fwdl_check_path_ready_ax,
6520*6d67aabdSBjoern A. Zeeb 	.parse_efuse_map = rtw89_parse_efuse_map_ax,
6521*6d67aabdSBjoern A. Zeeb 	.parse_phycap_map = rtw89_parse_phycap_map_ax,
6522*6d67aabdSBjoern A. Zeeb 	.cnv_efuse_state = rtw89_cnv_efuse_state_ax,
6523*6d67aabdSBjoern A. Zeeb 
6524*6d67aabdSBjoern A. Zeeb 	.cfg_plt = rtw89_mac_cfg_plt_ax,
6525*6d67aabdSBjoern A. Zeeb 	.get_plt_cnt = rtw89_mac_get_plt_cnt_ax,
6526*6d67aabdSBjoern A. Zeeb 
6527*6d67aabdSBjoern A. Zeeb 	.get_txpwr_cr = rtw89_mac_get_txpwr_cr_ax,
6528*6d67aabdSBjoern A. Zeeb 
6529*6d67aabdSBjoern A. Zeeb 	.write_xtal_si = rtw89_mac_write_xtal_si_ax,
6530*6d67aabdSBjoern A. Zeeb 	.read_xtal_si = rtw89_mac_read_xtal_si_ax,
6531*6d67aabdSBjoern A. Zeeb 
6532*6d67aabdSBjoern A. Zeeb 	.dump_qta_lost = rtw89_mac_dump_qta_lost_ax,
6533*6d67aabdSBjoern A. Zeeb 	.dump_err_status = rtw89_mac_dump_err_status_ax,
6534*6d67aabdSBjoern A. Zeeb 
6535*6d67aabdSBjoern A. Zeeb 	.is_txq_empty = mac_is_txq_empty_ax,
6536*6d67aabdSBjoern A. Zeeb 
6537*6d67aabdSBjoern A. Zeeb 	.add_chan_list = rtw89_hw_scan_add_chan_list,
6538*6d67aabdSBjoern A. Zeeb 	.scan_offload = rtw89_fw_h2c_scan_offload,
6539*6d67aabdSBjoern A. Zeeb 
6540*6d67aabdSBjoern A. Zeeb 	.wow_config_mac = rtw89_wow_config_mac_ax,
6541*6d67aabdSBjoern A. Zeeb };
6542*6d67aabdSBjoern A. Zeeb EXPORT_SYMBOL(rtw89_mac_gen_ax);
6543