// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2019-2020 Realtek Corporation
*/
#include "cam.h"
#include "chan.h"
#include "debug.h"
#include "efuse.h"
#include "fw.h"
#include "mac.h"
#include "pci.h"
#include "ps.h"
#include "reg.h"
#include "util.h"
static const u32 rtw89_mac_mem_base_addrs_ax[RTW89_MAC_MEM_NUM] = {
[RTW89_MAC_MEM_AXIDMA] = AXIDMA_BASE_ADDR,
[RTW89_MAC_MEM_SHARED_BUF] = SHARED_BUF_BASE_ADDR,
[RTW89_MAC_MEM_DMAC_TBL] = DMAC_TBL_BASE_ADDR,
[RTW89_MAC_MEM_SHCUT_MACHDR] = SHCUT_MACHDR_BASE_ADDR,
[RTW89_MAC_MEM_STA_SCHED] = STA_SCHED_BASE_ADDR,
[RTW89_MAC_MEM_RXPLD_FLTR_CAM] = RXPLD_FLTR_CAM_BASE_ADDR,
[RTW89_MAC_MEM_SECURITY_CAM] = SECURITY_CAM_BASE_ADDR,
[RTW89_MAC_MEM_WOW_CAM] = WOW_CAM_BASE_ADDR,
[RTW89_MAC_MEM_CMAC_TBL] = CMAC_TBL_BASE_ADDR,
[RTW89_MAC_MEM_ADDR_CAM] = ADDR_CAM_BASE_ADDR,
[RTW89_MAC_MEM_BA_CAM] = BA_CAM_BASE_ADDR,
[RTW89_MAC_MEM_BCN_IE_CAM0] = BCN_IE_CAM0_BASE_ADDR,
[RTW89_MAC_MEM_BCN_IE_CAM1] = BCN_IE_CAM1_BASE_ADDR,
[RTW89_MAC_MEM_TXD_FIFO_0] = TXD_FIFO_0_BASE_ADDR,
[RTW89_MAC_MEM_TXD_FIFO_1] = TXD_FIFO_1_BASE_ADDR,
[RTW89_MAC_MEM_TXDATA_FIFO_0] = TXDATA_FIFO_0_BASE_ADDR,
[RTW89_MAC_MEM_TXDATA_FIFO_1] = TXDATA_FIFO_1_BASE_ADDR,
[RTW89_MAC_MEM_CPU_LOCAL] = CPU_LOCAL_BASE_ADDR,
[RTW89_MAC_MEM_BSSID_CAM] = BSSID_CAM_BASE_ADDR,
[RTW89_MAC_MEM_TXD_FIFO_0_V1] = TXD_FIFO_0_BASE_ADDR_V1,
[RTW89_MAC_MEM_TXD_FIFO_1_V1] = TXD_FIFO_1_BASE_ADDR_V1,
};
static void rtw89_mac_mem_write(struct rtw89_dev *rtwdev, u32 offset,
u32 val, enum rtw89_mac_mem_sel sel)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 addr = mac->mem_base_addrs[sel] + offset;
rtw89_write32(rtwdev, mac->filter_model_addr, addr);
rtw89_write32(rtwdev, mac->indir_access_addr, val);
}
static u32 rtw89_mac_mem_read(struct rtw89_dev *rtwdev, u32 offset,
enum rtw89_mac_mem_sel sel)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 addr = mac->mem_base_addrs[sel] + offset;
rtw89_write32(rtwdev, mac->filter_model_addr, addr);
return rtw89_read32(rtwdev, mac->indir_access_addr);
}
static int rtw89_mac_check_mac_en_ax(struct rtw89_dev *rtwdev, u8 mac_idx,
enum rtw89_mac_hwmod_sel sel)
{
u32 val, r_val;
if (sel == RTW89_DMAC_SEL) {
r_val = rtw89_read32(rtwdev, R_AX_DMAC_FUNC_EN);
val = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN);
} else if (sel == RTW89_CMAC_SEL && mac_idx == 0) {
r_val = rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN);
val = B_AX_CMAC_EN;
} else if (sel == RTW89_CMAC_SEL && mac_idx == 1) {
r_val = rtw89_read32(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND);
val = B_AX_CMAC1_FEN;
} else {
return -EINVAL;
}
if (r_val == RTW89_R32_EA || r_val == RTW89_R32_DEAD ||
(val & r_val) != val)
return -EFAULT;
return 0;
}
int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val)
{
u8 lte_ctrl;
int ret;
ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
50, 50000, false , rtwdev, R_AX_LTE_CTRL + 3);
if (ret && !test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
rtw89_err(rtwdev, "[ERR]lte not ready(W)\n" );
rtw89_write32(rtwdev, R_AX_LTE_WDATA, val);
rtw89_write32(rtwdev, R_AX_LTE_CTRL, 0xC00F0000 | offset);
return ret;
}
int rtw89_mac_read_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 *val)
{
u8 lte_ctrl;
int ret;
ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
50, 50000, false , rtwdev, R_AX_LTE_CTRL + 3);
if (ret && !test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
rtw89_err(rtwdev, "[ERR]lte not ready(W)\n" );
rtw89_write32(rtwdev, R_AX_LTE_CTRL, 0x800F0000 | offset);
*val = rtw89_read32(rtwdev, R_AX_LTE_RDATA);
return ret;
}
int rtw89_mac_dle_dfi_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_dfi_ctrl *ctrl)
{
u32 ctrl_reg, data_reg, ctrl_data;
u32 val;
int ret;
switch (ctrl->type) {
case DLE_CTRL_TYPE_WDE:
ctrl_reg = R_AX_WDE_DBG_FUN_INTF_CTL;
data_reg = R_AX_WDE_DBG_FUN_INTF_DATA;
ctrl_data = FIELD_PREP(B_AX_WDE_DFI_TRGSEL_MASK, ctrl->target) |
FIELD_PREP(B_AX_WDE_DFI_ADDR_MASK, ctrl->addr) |
B_AX_WDE_DFI_ACTIVE;
break ;
case DLE_CTRL_TYPE_PLE:
ctrl_reg = R_AX_PLE_DBG_FUN_INTF_CTL;
data_reg = R_AX_PLE_DBG_FUN_INTF_DATA;
ctrl_data = FIELD_PREP(B_AX_PLE_DFI_TRGSEL_MASK, ctrl->target) |
FIELD_PREP(B_AX_PLE_DFI_ADDR_MASK, ctrl->addr) |
B_AX_PLE_DFI_ACTIVE;
break ;
default :
rtw89_warn(rtwdev, "[ERR] dfi ctrl type %d\n" , ctrl->type);
return -EINVAL;
}
rtw89_write32(rtwdev, ctrl_reg, ctrl_data);
ret = read_poll_timeout_atomic(rtw89_read32, val, !(val & B_AX_WDE_DFI_ACTIVE),
1, 1000, false , rtwdev, ctrl_reg);
if (ret) {
rtw89_warn(rtwdev, "[ERR] dle dfi ctrl 0x%X set 0x%X timeout\n" ,
ctrl_reg, ctrl_data);
return ret;
}
ctrl->out_data = rtw89_read32(rtwdev, data_reg);
return 0;
}
int rtw89_mac_dle_dfi_quota_cfg(struct rtw89_dev *rtwdev,
struct rtw89_mac_dle_dfi_quota *quota)
{
struct rtw89_mac_dle_dfi_ctrl ctrl;
int ret;
ctrl.type = quota->dle_type;
ctrl.target = DLE_DFI_TYPE_QUOTA;
ctrl.addr = quota->qtaid;
ret = rtw89_mac_dle_dfi_cfg(rtwdev, &ctrl);
if (ret) {
rtw89_warn(rtwdev, "[ERR] dle dfi quota %d\n" , ret);
return ret;
}
quota->rsv_pgnum = FIELD_GET(B_AX_DLE_RSV_PGNUM, ctrl.out_data);
quota->use_pgnum = FIELD_GET(B_AX_DLE_USE_PGNUM, ctrl.out_data);
return 0;
}
int rtw89_mac_dle_dfi_qempty_cfg(struct rtw89_dev *rtwdev,
struct rtw89_mac_dle_dfi_qempty *qempty)
{
struct rtw89_mac_dle_dfi_ctrl ctrl;
u32 ret;
ctrl.type = qempty->dle_type;
ctrl.target = DLE_DFI_TYPE_QEMPTY;
ctrl.addr = qempty->grpsel;
ret = rtw89_mac_dle_dfi_cfg(rtwdev, &ctrl);
if (ret) {
rtw89_warn(rtwdev, "[ERR] dle dfi qempty %d\n" , ret);
return ret;
}
qempty->qempty = FIELD_GET(B_AX_DLE_QEMPTY_GRP, ctrl.out_data);
return 0;
}
static void dump_err_status_dispatcher_ax(struct rtw89_dev *rtwdev)
{
rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ALWAYS_IMR=0x%08x " ,
rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR));
rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ALWAYS_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR));
rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ALWAYS_IMR=0x%08x " ,
rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR));
rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ALWAYS_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR));
rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ALWAYS_IMR=0x%08x " ,
rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR));
rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ALWAYS_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR));
}
static void rtw89_mac_dump_qta_lost_ax(struct rtw89_dev *rtwdev)
{
struct rtw89_mac_dle_dfi_qempty qempty;
struct rtw89_mac_dle_dfi_quota quota;
struct rtw89_mac_dle_dfi_ctrl ctrl;
u32 val, not_empty, i;
int ret;
qempty.dle_type = DLE_CTRL_TYPE_PLE;
qempty.grpsel = 0;
qempty.qempty = ~(u32)0;
ret = rtw89_mac_dle_dfi_qempty_cfg(rtwdev, &qempty);
if (ret)
rtw89_warn(rtwdev, "%s: query DLE fail\n" , __func__);
else
rtw89_info(rtwdev, "DLE group0 empty: 0x%x\n" , qempty.qempty);
for (not_empty = ~qempty.qempty, i = 0; not_empty != 0; not_empty >>= 1, i++) {
if (!(not_empty & BIT(0)))
continue ;
ctrl.type = DLE_CTRL_TYPE_PLE;
ctrl.target = DLE_DFI_TYPE_QLNKTBL;
ctrl.addr = (QLNKTBL_ADDR_INFO_SEL_0 ? QLNKTBL_ADDR_INFO_SEL : 0) |
u32_encode_bits(i, QLNKTBL_ADDR_TBL_IDX_MASK);
ret = rtw89_mac_dle_dfi_cfg(rtwdev, &ctrl);
if (ret)
rtw89_warn(rtwdev, "%s: query DLE fail\n" , __func__);
else
rtw89_info(rtwdev, "qidx%d pktcnt = %d\n" , i,
u32_get_bits(ctrl.out_data,
QLNKTBL_DATA_SEL1_PKT_CNT_MASK));
}
quota.dle_type = DLE_CTRL_TYPE_PLE;
quota.qtaid = 6;
ret = rtw89_mac_dle_dfi_quota_cfg(rtwdev, "a);
if (ret)
rtw89_warn(rtwdev, "%s: query DLE fail\n" , __func__);
else
rtw89_info(rtwdev, "quota6 rsv/use: 0x%x/0x%x\n" ,
quota.rsv_pgnum, quota.use_pgnum);
val = rtw89_read32(rtwdev, R_AX_PLE_QTA6_CFG);
rtw89_info(rtwdev, "[PLE][CMAC0_RX]min_pgnum=0x%x\n" ,
u32_get_bits(val, B_AX_PLE_Q6_MIN_SIZE_MASK));
rtw89_info(rtwdev, "[PLE][CMAC0_RX]max_pgnum=0x%x\n" ,
u32_get_bits(val, B_AX_PLE_Q6_MAX_SIZE_MASK));
val = rtw89_read32(rtwdev, R_AX_RX_FLTR_OPT);
rtw89_info(rtwdev, "[PLE][CMAC0_RX]B_AX_RX_MPDU_MAX_LEN=0x%x\n" ,
u32_get_bits(val, B_AX_RX_MPDU_MAX_LEN_MASK));
rtw89_info(rtwdev, "R_AX_RSP_CHK_SIG=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RSP_CHK_SIG));
rtw89_info(rtwdev, "R_AX_TRXPTCL_RESP_0=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_TRXPTCL_RESP_0));
rtw89_info(rtwdev, "R_AX_CCA_CONTROL=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_CCA_CONTROL));
if (!rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_1, RTW89_CMAC_SEL)) {
quota.dle_type = DLE_CTRL_TYPE_PLE;
quota.qtaid = 7;
ret = rtw89_mac_dle_dfi_quota_cfg(rtwdev, "a);
if (ret)
rtw89_warn(rtwdev, "%s: query DLE fail\n" , __func__);
else
rtw89_info(rtwdev, "quota7 rsv/use: 0x%x/0x%x\n" ,
quota.rsv_pgnum, quota.use_pgnum);
val = rtw89_read32(rtwdev, R_AX_PLE_QTA7_CFG);
rtw89_info(rtwdev, "[PLE][CMAC1_RX]min_pgnum=0x%x\n" ,
u32_get_bits(val, B_AX_PLE_Q7_MIN_SIZE_MASK));
rtw89_info(rtwdev, "[PLE][CMAC1_RX]max_pgnum=0x%x\n" ,
u32_get_bits(val, B_AX_PLE_Q7_MAX_SIZE_MASK));
val = rtw89_read32(rtwdev, R_AX_RX_FLTR_OPT_C1);
rtw89_info(rtwdev, "[PLE][CMAC1_RX]B_AX_RX_MPDU_MAX_LEN=0x%x\n" ,
u32_get_bits(val, B_AX_RX_MPDU_MAX_LEN_MASK));
rtw89_info(rtwdev, "R_AX_RSP_CHK_SIG_C1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RSP_CHK_SIG_C1));
rtw89_info(rtwdev, "R_AX_TRXPTCL_RESP_0_C1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_TRXPTCL_RESP_0_C1));
rtw89_info(rtwdev, "R_AX_CCA_CONTROL_C1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_CCA_CONTROL_C1));
}
rtw89_info(rtwdev, "R_AX_DLE_EMPTY0=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_DLE_EMPTY0));
rtw89_info(rtwdev, "R_AX_DLE_EMPTY1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_DLE_EMPTY1));
dump_err_status_dispatcher_ax(rtwdev);
}
void rtw89_mac_dump_l0_to_l1(struct rtw89_dev *rtwdev,
enum mac_ax_err_info err)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 dbg, event;
dbg = rtw89_read32(rtwdev, R_AX_SER_DBG_INFO);
event = u32_get_bits(dbg, B_AX_L0_TO_L1_EVENT_MASK);
switch (event) {
case MAC_AX_L0_TO_L1_RX_QTA_LOST:
rtw89_info(rtwdev, "quota lost!\n" );
mac->dump_qta_lost(rtwdev);
break ;
default :
break ;
}
}
void rtw89_mac_dump_dmac_err_status(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
u32 dmac_err;
int i, ret;
ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
if (ret) {
rtw89_warn(rtwdev, "[DMAC] : DMAC not enabled\n" );
return ;
}
dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
rtw89_info(rtwdev, "R_AX_DMAC_ERR_ISR=0x%08x\n" , dmac_err);
rtw89_info(rtwdev, "R_AX_DMAC_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_DMAC_ERR_IMR));
if (dmac_err) {
rtw89_info(rtwdev, "R_AX_WDE_ERR_FLAG_CFG=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WDE_ERR_FLAG_CFG_NUM1));
rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_CFG=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_CFG_NUM1));
if (chip->chip_id == RTL8852C) {
rtw89_info(rtwdev, "R_AX_PLE_ERRFLAG_MSG=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PLE_ERRFLAG_MSG));
rtw89_info(rtwdev, "R_AX_WDE_ERRFLAG_MSG=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WDE_ERRFLAG_MSG));
rtw89_info(rtwdev, "R_AX_PLE_DBGERR_LOCKEN=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PLE_DBGERR_LOCKEN));
rtw89_info(rtwdev, "R_AX_PLE_DBGERR_STS=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PLE_DBGERR_STS));
}
}
if (dmac_err & B_AX_WDRLS_ERR_FLAG) {
rtw89_info(rtwdev, "R_AX_WDRLS_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WDRLS_ERR_IMR));
rtw89_info(rtwdev, "R_AX_WDRLS_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WDRLS_ERR_ISR));
if (chip->chip_id == RTL8852C)
rtw89_info(rtwdev, "R_AX_RPQ_RXBD_IDX=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX_V1));
else
rtw89_info(rtwdev, "R_AX_RPQ_RXBD_IDX=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RPQ_RXBD_IDX));
}
if (dmac_err & B_AX_WSEC_ERR_FLAG) {
if (chip->chip_id == RTL8852C) {
rtw89_info(rtwdev, "R_AX_SEC_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG_IMR));
rtw89_info(rtwdev, "R_AX_SEC_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_ERROR_FLAG));
rtw89_info(rtwdev, "R_AX_SEC_ENG_CTRL=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
rtw89_info(rtwdev, "R_AX_SEC_MPDU_PROC=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
rtw89_info(rtwdev, "R_AX_SEC_CAM_ACCESS=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
rtw89_info(rtwdev, "R_AX_SEC_CAM_RDATA=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
rtw89_info(rtwdev, "R_AX_SEC_DEBUG1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_DEBUG1));
rtw89_info(rtwdev, "R_AX_SEC_TX_DEBUG=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
rtw89_info(rtwdev, "R_AX_SEC_RX_DEBUG=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG));
rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL,
B_AX_DBG_SEL0, 0x8B);
rtw89_write32_mask(rtwdev, R_AX_DBG_CTRL,
B_AX_DBG_SEL1, 0x8B);
rtw89_write32_mask(rtwdev, R_AX_SYS_STATUS1,
B_AX_SEL_0XC0_MASK, 1);
for (i = 0; i < 0x10; i++) {
rtw89_write32_mask(rtwdev, R_AX_SEC_ENG_CTRL,
B_AX_SEC_DBG_PORT_FIELD_MASK, i);
rtw89_info(rtwdev, "sel=%x,R_AX_SEC_DEBUG2=0x%08x\n" ,
i, rtw89_read32(rtwdev, R_AX_SEC_DEBUG2));
}
} else if (chip->chip_id == RTL8922A) {
rtw89_info(rtwdev, "R_BE_SEC_ERROR_FLAG=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_SEC_ERROR_FLAG));
rtw89_info(rtwdev, "R_BE_SEC_ERROR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_SEC_ERROR_IMR));
rtw89_info(rtwdev, "R_BE_SEC_ENG_CTRL=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_SEC_ENG_CTRL));
rtw89_info(rtwdev, "R_BE_SEC_MPDU_PROC=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_SEC_MPDU_PROC));
rtw89_info(rtwdev, "R_BE_SEC_CAM_ACCESS=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_SEC_CAM_ACCESS));
rtw89_info(rtwdev, "R_BE_SEC_CAM_RDATA=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_SEC_CAM_RDATA));
rtw89_info(rtwdev, "R_BE_SEC_DEBUG2=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_SEC_DEBUG2));
} else {
rtw89_info(rtwdev, "R_AX_SEC_ERR_IMR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_DEBUG));
rtw89_info(rtwdev, "R_AX_SEC_ENG_CTRL=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_ENG_CTRL));
rtw89_info(rtwdev, "R_AX_SEC_MPDU_PROC=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_MPDU_PROC));
rtw89_info(rtwdev, "R_AX_SEC_CAM_ACCESS=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_CAM_ACCESS));
rtw89_info(rtwdev, "R_AX_SEC_CAM_RDATA=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_CAM_RDATA));
rtw89_info(rtwdev, "R_AX_SEC_CAM_WDATA=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_CAM_WDATA));
rtw89_info(rtwdev, "R_AX_SEC_TX_DEBUG=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_TX_DEBUG));
rtw89_info(rtwdev, "R_AX_SEC_RX_DEBUG=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_RX_DEBUG));
rtw89_info(rtwdev, "R_AX_SEC_TRX_PKT_CNT=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_TRX_PKT_CNT));
rtw89_info(rtwdev, "R_AX_SEC_TRX_BLK_CNT=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SEC_TRX_BLK_CNT));
}
}
if (dmac_err & B_AX_MPDU_ERR_FLAG) {
rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_IMR));
rtw89_info(rtwdev, "R_AX_MPDU_TX_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_MPDU_TX_ERR_ISR));
rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_IMR));
rtw89_info(rtwdev, "R_AX_MPDU_RX_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_MPDU_RX_ERR_ISR));
}
if (dmac_err & B_AX_STA_SCHEDULER_ERR_FLAG) {
if (chip->chip_id == RTL8922A) {
rtw89_info(rtwdev, "R_BE_INTERRUPT_MASK_REG=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_INTERRUPT_MASK_REG));
rtw89_info(rtwdev, "R_BE_INTERRUPT_STS_REG=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_INTERRUPT_STS_REG));
} else {
rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_IMR));
rtw89_info(rtwdev, "R_AX_STA_SCHEDULER_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_STA_SCHEDULER_ERR_ISR));
}
}
if (dmac_err & B_AX_WDE_DLE_ERR_FLAG) {
rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
rtw89_info(rtwdev, "R_AX_WDE_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR));
}
if (dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) {
if (chip->chip_id == RTL8852C || chip->chip_id == RTL8922A) {
rtw89_info(rtwdev, "R_AX_TXPKTCTL_B0_ERRFLAG_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR));
rtw89_info(rtwdev, "R_AX_TXPKTCTL_B0_ERRFLAG_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR));
rtw89_info(rtwdev, "R_AX_TXPKTCTL_B1_ERRFLAG_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_IMR));
rtw89_info(rtwdev, "R_AX_TXPKTCTL_B1_ERRFLAG_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_TXPKTCTL_B1_ERRFLAG_ISR));
} else {
rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR));
rtw89_info(rtwdev, "R_AX_TXPKTCTL_ERR_IMR_ISR_B1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_TXPKTCTL_ERR_IMR_ISR_B1));
}
}
if (dmac_err & B_AX_PLE_DLE_ERR_FLAG) {
rtw89_info(rtwdev, "R_AX_WDE_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WDE_ERR_IMR));
rtw89_info(rtwdev, "R_AX_WDE_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WDE_ERR_ISR));
rtw89_info(rtwdev, "R_AX_PLE_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PLE_ERR_IMR));
rtw89_info(rtwdev, "R_AX_PLE_ERR_FLAG_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PLE_ERR_FLAG_ISR));
rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_0=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_0));
rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_1));
rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_2=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_2));
rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_0=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_0));
rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_1));
rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_2=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_2));
if (chip->chip_id == RTL8922A) {
rtw89_info(rtwdev, "R_BE_WD_CPUQ_OP_3=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_WD_CPUQ_OP_3));
rtw89_info(rtwdev, "R_BE_WD_CPUQ_OP_STATUS=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_WD_CPUQ_OP_STATUS));
rtw89_info(rtwdev, "R_BE_PLE_CPUQ_OP_3=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_PL_CPUQ_OP_3));
rtw89_info(rtwdev, "R_BE_PL_CPUQ_OP_STATUS=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_PL_CPUQ_OP_STATUS));
} else {
rtw89_info(rtwdev, "R_AX_WD_CPUQ_OP_STATUS=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_WD_CPUQ_OP_STATUS));
rtw89_info(rtwdev, "R_AX_PL_CPUQ_OP_STATUS=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PL_CPUQ_OP_STATUS));
if (chip->chip_id == RTL8852C) {
rtw89_info(rtwdev, "R_AX_RX_CTRL0=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RX_CTRL0));
rtw89_info(rtwdev, "R_AX_RX_CTRL1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RX_CTRL1));
rtw89_info(rtwdev, "R_AX_RX_CTRL2=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RX_CTRL2));
} else {
rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_0=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_0));
rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_1=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_1));
rtw89_info(rtwdev, "R_AX_RXDMA_PKT_INFO_2=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_RXDMA_PKT_INFO_2));
}
}
}
if (dmac_err & B_AX_PKTIN_ERR_FLAG) {
rtw89_info(rtwdev, "R_AX_PKTIN_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PKTIN_ERR_IMR));
rtw89_info(rtwdev, "R_AX_PKTIN_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_PKTIN_ERR_ISR));
}
if (dmac_err & B_AX_DISPATCH_ERR_FLAG) {
if (chip->chip_id == RTL8922A) {
rtw89_info(rtwdev, "R_BE_DISP_HOST_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_DISP_HOST_IMR));
rtw89_info(rtwdev, "R_BE_DISP_ERROR_ISR1=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_DISP_ERROR_ISR1));
rtw89_info(rtwdev, "R_BE_DISP_CPU_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_DISP_CPU_IMR));
rtw89_info(rtwdev, "R_BE_DISP_ERROR_ISR2=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_DISP_ERROR_ISR2));
rtw89_info(rtwdev, "R_BE_DISP_OTHER_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_DISP_OTHER_IMR));
rtw89_info(rtwdev, "R_BE_DISP_ERROR_ISR0=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_DISP_ERROR_ISR0));
} else {
rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_IMR));
rtw89_info(rtwdev, "R_AX_HOST_DISPATCHER_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_HOST_DISPATCHER_ERR_ISR));
rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_IMR));
rtw89_info(rtwdev, "R_AX_CPU_DISPATCHER_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_CPU_DISPATCHER_ERR_ISR));
rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_IMR));
rtw89_info(rtwdev, "R_AX_OTHER_DISPATCHER_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_OTHER_DISPATCHER_ERR_ISR));
}
}
if (dmac_err & B_AX_BBRPT_ERR_FLAG) {
if (chip->chip_id == RTL8852C || chip->chip_id == RTL8922A) {
rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR));
rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_ISR));
rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
} else {
rtw89_info(rtwdev, "R_AX_BBRPT_COM_ERR_IMR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_COM_ERR_IMR_ISR));
rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_ISR));
rtw89_info(rtwdev, "R_AX_BBRPT_CHINFO_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_CHINFO_ERR_IMR));
rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_IMR));
rtw89_info(rtwdev, "R_AX_BBRPT_DFS_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_BBRPT_DFS_ERR_ISR));
}
if (chip->chip_id == RTL8922A) {
rtw89_info(rtwdev, "R_BE_LA_ERRFLAG_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_LA_ERRFLAG_IMR));
rtw89_info(rtwdev, "R_BE_LA_ERRFLAG_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_LA_ERRFLAG_ISR));
}
}
if (dmac_err & B_AX_HAXIDMA_ERR_FLAG) {
if (chip->chip_id == RTL8922A) {
rtw89_info(rtwdev, "R_BE_HAXI_IDCT_MSK=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_HAXI_IDCT_MSK));
rtw89_info(rtwdev, "R_BE_HAXI_IDCT=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_HAXI_IDCT));
} else if (chip->chip_id == RTL8852C) {
rtw89_info(rtwdev, "R_AX_HAXIDMA_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_HAXI_IDCT_MSK));
rtw89_info(rtwdev, "R_AX_HAXIDMA_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_HAXI_IDCT));
}
}
if (dmac_err & B_BE_P_AXIDMA_ERR_INT) {
rtw89_info(rtwdev, "R_BE_PL_AXIDMA_IDCT_MSK=0x%08x\n" ,
rtw89_mac_mem_read(rtwdev, R_BE_PL_AXIDMA_IDCT_MSK,
RTW89_MAC_MEM_AXIDMA));
rtw89_info(rtwdev, "R_BE_PL_AXIDMA_IDCT=0x%08x\n" ,
rtw89_mac_mem_read(rtwdev, R_BE_PL_AXIDMA_IDCT,
RTW89_MAC_MEM_AXIDMA));
}
if (dmac_err & B_BE_MLO_ERR_INT) {
rtw89_info(rtwdev, "R_BE_MLO_ERR_IDCT_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_MLO_ERR_IDCT_IMR));
rtw89_info(rtwdev, "R_BE_PKTIN_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_MLO_ERR_IDCT_ISR));
}
if (dmac_err & B_BE_PLRLS_ERR_INT) {
rtw89_info(rtwdev, "R_BE_PLRLS_ERR_IMR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_PLRLS_ERR_IMR));
rtw89_info(rtwdev, "R_BE_PLRLS_ERR_ISR=0x%08x\n" ,
rtw89_read32(rtwdev, R_BE_PLRLS_ERR_ISR));
}
}
static void rtw89_mac_dump_cmac_err_status_ax(struct rtw89_dev *rtwdev,
u8 band)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
u32 offset = 0;
u32 cmac_err;
int ret;
ret = rtw89_mac_check_mac_en(rtwdev, band, RTW89_CMAC_SEL);
if (ret) {
if (band)
rtw89_warn(rtwdev, "[CMAC] : CMAC1 not enabled\n" );
else
rtw89_warn(rtwdev, "[CMAC] : CMAC0 not enabled\n" );
return ;
}
if (band)
offset = RTW89_MAC_AX_BAND_REG_OFFSET;
cmac_err = rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset);
rtw89_info(rtwdev, "R_AX_CMAC_ERR_ISR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_CMAC_ERR_ISR + offset));
rtw89_info(rtwdev, "R_AX_CMAC_FUNC_EN [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_CMAC_FUNC_EN + offset));
rtw89_info(rtwdev, "R_AX_CK_EN [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_CK_EN + offset));
if (cmac_err & B_AX_SCHEDULE_TOP_ERR_IND) {
rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_IMR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_IMR + offset));
rtw89_info(rtwdev, "R_AX_SCHEDULE_ERR_ISR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_SCHEDULE_ERR_ISR + offset));
}
if (cmac_err & B_AX_PTCL_TOP_ERR_IND) {
rtw89_info(rtwdev, "R_AX_PTCL_IMR0 [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_PTCL_IMR0 + offset));
rtw89_info(rtwdev, "R_AX_PTCL_ISR0 [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_PTCL_ISR0 + offset));
}
if (cmac_err & B_AX_DMA_TOP_ERR_IND) {
if (chip->chip_id == RTL8852C) {
rtw89_info(rtwdev, "R_AX_RX_ERR_FLAG [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG + offset));
rtw89_info(rtwdev, "R_AX_RX_ERR_FLAG_IMR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_RX_ERR_FLAG_IMR + offset));
} else {
rtw89_info(rtwdev, "R_AX_DLE_CTRL [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_DLE_CTRL + offset));
}
}
if (cmac_err & B_AX_DMA_TOP_ERR_IND || cmac_err & B_AX_WMAC_RX_ERR_IND) {
if (chip->chip_id == RTL8852C) {
rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_ISR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_ISR + offset));
rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset));
} else {
rtw89_info(rtwdev, "R_AX_PHYINFO_ERR_IMR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_PHYINFO_ERR_IMR + offset));
}
}
if (cmac_err & B_AX_TXPWR_CTRL_ERR_IND) {
rtw89_info(rtwdev, "R_AX_TXPWR_IMR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_TXPWR_IMR + offset));
rtw89_info(rtwdev, "R_AX_TXPWR_ISR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_TXPWR_ISR + offset));
}
if (cmac_err & B_AX_WMAC_TX_ERR_IND) {
if (chip->chip_id == RTL8852C) {
rtw89_info(rtwdev, "R_AX_TRXPTCL_ERROR_INDICA [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA + offset));
rtw89_info(rtwdev, "R_AX_TRXPTCL_ERROR_INDICA_MASK [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_TRXPTCL_ERROR_INDICA_MASK + offset));
} else {
rtw89_info(rtwdev, "R_AX_TMAC_ERR_IMR_ISR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_TMAC_ERR_IMR_ISR + offset));
}
rtw89_info(rtwdev, "R_AX_DBGSEL_TRXPTCL [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_DBGSEL_TRXPTCL + offset));
}
rtw89_info(rtwdev, "R_AX_CMAC_ERR_IMR [%d]=0x%08x\n" , band,
rtw89_read32(rtwdev, R_AX_CMAC_ERR_IMR + offset));
}
static void rtw89_mac_dump_err_status_ax(struct rtw89_dev *rtwdev,
enum mac_ax_err_info err)
{
if (err != MAC_AX_ERR_L1_ERR_DMAC &&
err != MAC_AX_ERR_L0_PROMOTE_TO_L1 &&
err != MAC_AX_ERR_L0_ERR_CMAC0 &&
err != MAC_AX_ERR_L0_ERR_CMAC1 &&
err != MAC_AX_ERR_RXI300)
return ;
rtw89_info(rtwdev, "--->\nerr=0x%x\n" , err);
rtw89_info(rtwdev, "R_AX_SER_DBG_INFO =0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SER_DBG_INFO));
rtw89_info(rtwdev, "R_AX_SER_DBG_INFO =0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_SER_DBG_INFO));
rtw89_info(rtwdev, "DBG Counter 1 (R_AX_DRV_FW_HSK_4)=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_DRV_FW_HSK_4));
rtw89_info(rtwdev, "DBG Counter 2 (R_AX_DRV_FW_HSK_5)=0x%08x\n" ,
rtw89_read32(rtwdev, R_AX_DRV_FW_HSK_5));
rtw89_mac_dump_dmac_err_status(rtwdev);
rtw89_mac_dump_cmac_err_status_ax(rtwdev, RTW89_MAC_0);
rtw89_mac_dump_cmac_err_status_ax(rtwdev, RTW89_MAC_1);
rtwdev->hci.ops->dump_err_status(rtwdev);
if (err == MAC_AX_ERR_L0_PROMOTE_TO_L1)
rtw89_mac_dump_l0_to_l1(rtwdev, err);
rtw89_info(rtwdev, "<---\n" );
}
static bool rtw89_mac_suppress_log(struct rtw89_dev *rtwdev, u32 err)
{
struct rtw89_ser *ser = &rtwdev->ser;
u32 dmac_err, imr, isr;
int ret;
if (rtwdev->chip->chip_id == RTL8852C) {
ret = rtw89_mac_check_mac_en(rtwdev, 0, RTW89_DMAC_SEL);
if (ret)
return true ;
if (err == MAC_AX_ERR_L1_ERR_DMAC) {
dmac_err = rtw89_read32(rtwdev, R_AX_DMAC_ERR_ISR);
imr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_IMR);
isr = rtw89_read32(rtwdev, R_AX_TXPKTCTL_B0_ERRFLAG_ISR);
if ((dmac_err & B_AX_TXPKTCTRL_ERR_FLAG) &&
((isr & imr) & B_AX_B0_ISR_ERR_CMDPSR_FRZTO)) {
set_bit(RTW89_SER_SUPPRESS_LOG, ser->flags);
return true ;
}
} else if (err == MAC_AX_ERR_L1_RESET_DISABLE_DMAC_DONE) {
if (test_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
return true ;
} else if (err == MAC_AX_ERR_L1_RESET_RECOVERY_DONE) {
if (test_and_clear_bit(RTW89_SER_SUPPRESS_LOG, ser->flags))
return true ;
}
}
return false ;
}
u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
u32 err, err_scnr;
int ret;
ret = read_poll_timeout(rtw89_read32, err, (err != 0), 1000, 100000,
false , rtwdev, R_AX_HALT_C2H_CTRL);
if (ret) {
rtw89_warn(rtwdev, "Polling FW err status fail\n" );
return ret;
}
err = rtw89_read32(rtwdev, R_AX_HALT_C2H);
rtw89_write32(rtwdev, R_AX_HALT_C2H_CTRL, 0);
err_scnr = RTW89_ERROR_SCENARIO(err);
if (err_scnr == RTW89_WCPU_CPU_EXCEPTION)
err = MAC_AX_ERR_CPU_EXCEPTION;
else if (err_scnr == RTW89_WCPU_ASSERTION)
err = MAC_AX_ERR_ASSERTION;
else if (err_scnr == RTW89_RXI300_ERROR)
err = MAC_AX_ERR_RXI300;
if (rtw89_mac_suppress_log(rtwdev, err))
return err;
rtw89_fw_st_dbg_dump(rtwdev);
mac->dump_err_status(rtwdev, err);
return err;
}
EXPORT_SYMBOL(rtw89_mac_get_err_status);
int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err)
{
struct rtw89_ser *ser = &rtwdev->ser;
u32 halt;
int ret = 0;
if (err > MAC_AX_SET_ERR_MAX) {
rtw89_err(rtwdev, "Bad set-err-status value 0x%08x\n" , err);
return -EINVAL;
}
ret = read_poll_timeout(rtw89_read32, halt, (halt == 0x0), 1000,
100000, false , rtwdev, R_AX_HALT_H2C_CTRL);
if (ret) {
rtw89_err(rtwdev, "FW doesn't receive previous msg\n" );
return -EFAULT;
}
rtw89_write32(rtwdev, R_AX_HALT_H2C, err);
if (ser->prehandle_l1 &&
(err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN))
return 0;
rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, B_AX_HALT_H2C_TRIGGER);
return 0;
}
EXPORT_SYMBOL(rtw89_mac_set_err_status);
static int hfc_reset_param(struct rtw89_dev *rtwdev)
{
const struct rtw89_hfc_param_ini *param_ini, *param_inis;
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
u8 qta_mode = rtwdev->mac.dle_info.qta_mode;
param_inis = rtwdev->chip->hfc_param_ini[rtwdev->hci.type];
if (!param_inis)
return -EINVAL;
param_ini = ¶m_inis[qta_mode];
param->en = 0;
if (param_ini->pub_cfg)
param->pub_cfg = *param_ini->pub_cfg;
if (param_ini->prec_cfg)
param->prec_cfg = *param_ini->prec_cfg;
if (param_ini->ch_cfg)
param->ch_cfg = param_ini->ch_cfg;
memset(¶m->ch_info, 0, sizeof (param->ch_info));
memset(¶m->pub_info, 0, sizeof (param->pub_info));
param->mode = param_ini->mode;
return 0;
}
static int hfc_ch_cfg_chk(struct rtw89_dev *rtwdev, u8 ch)
{
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
const struct rtw89_hfc_ch_cfg *ch_cfg = param->ch_cfg;
const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg;
const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg;
if (ch >= RTW89_DMA_CH_NUM)
return -EINVAL;
if ((ch_cfg[ch].min && ch_cfg[ch].min < prec_cfg->ch011_prec) ||
ch_cfg[ch].max > pub_cfg->pub_max)
return -EINVAL;
if (ch_cfg[ch].grp >= grp_num)
return -EINVAL;
return 0;
}
static int hfc_pub_info_chk(struct rtw89_dev *rtwdev)
{
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
const struct rtw89_hfc_pub_cfg *cfg = ¶m->pub_cfg;
struct rtw89_hfc_pub_info *info = ¶m->pub_info;
if (info->g0_used + info->g1_used + info->pub_aval != cfg->pub_max) {
if (rtwdev->chip->chip_id == RTL8852A)
return 0;
else
return -EFAULT;
}
return 0;
}
static int hfc_pub_cfg_chk(struct rtw89_dev *rtwdev)
{
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg;
if (pub_cfg->grp0 + pub_cfg->grp1 != pub_cfg->pub_max)
return -EFAULT;
return 0;
}
static int hfc_ch_ctrl(struct rtw89_dev *rtwdev, u8 ch)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_page_regs *regs = chip->page_regs;
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
const struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg;
int ret = 0;
u32 val = 0;
ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
if (ret)
return ret;
ret = hfc_ch_cfg_chk(rtwdev, ch);
if (ret)
return ret;
if (ch > RTW89_DMA_B1HI)
return -EINVAL;
val = u32_encode_bits(cfg[ch].min, B_AX_MIN_PG_MASK) |
u32_encode_bits(cfg[ch].max, B_AX_MAX_PG_MASK) |
(cfg[ch].grp ? B_AX_GRP : 0);
rtw89_write32(rtwdev, regs->ach_page_ctrl + ch * 4, val);
return 0;
}
static int hfc_upd_ch_info(struct rtw89_dev *rtwdev, u8 ch)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_page_regs *regs = chip->page_regs;
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
struct rtw89_hfc_ch_info *info = param->ch_info;
const struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg;
u32 val;
u32 ret;
ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
if (ret)
return ret;
if (ch > RTW89_DMA_H2C)
return -EINVAL;
val = rtw89_read32(rtwdev, regs->ach_page_info + ch * 4);
info[ch].aval = u32_get_bits(val, B_AX_AVAL_PG_MASK);
if (ch < RTW89_DMA_H2C)
info[ch].used = u32_get_bits(val, B_AX_USE_PG_MASK);
else
info[ch].used = cfg[ch].min - info[ch].aval;
return 0;
}
static int hfc_pub_ctrl(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_page_regs *regs = chip->page_regs;
const struct rtw89_hfc_pub_cfg *cfg = &rtwdev->mac.hfc_param.pub_cfg;
u32 val;
int ret;
ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
if (ret)
return ret;
ret = hfc_pub_cfg_chk(rtwdev);
if (ret)
return ret;
val = u32_encode_bits(cfg->grp0, B_AX_PUBPG_G0_MASK) |
u32_encode_bits(cfg->grp1, B_AX_PUBPG_G1_MASK);
rtw89_write32(rtwdev, regs->pub_page_ctrl1, val);
val = u32_encode_bits(cfg->wp_thrd, B_AX_WP_THRD_MASK);
rtw89_write32(rtwdev, regs->wp_page_ctrl2, val);
return 0;
}
static void hfc_get_mix_info_ax(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_page_regs *regs = chip->page_regs;
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg;
struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg;
struct rtw89_hfc_pub_info *info = ¶m->pub_info;
u32 val;
val = rtw89_read32(rtwdev, regs->pub_page_info1);
info->g0_used = u32_get_bits(val, B_AX_G0_USE_PG_MASK);
info->g1_used = u32_get_bits(val, B_AX_G1_USE_PG_MASK);
val = rtw89_read32(rtwdev, regs->pub_page_info3);
info->g0_aval = u32_get_bits(val, B_AX_G0_AVAL_PG_MASK);
info->g1_aval = u32_get_bits(val, B_AX_G1_AVAL_PG_MASK);
info->pub_aval =
u32_get_bits(rtw89_read32(rtwdev, regs->pub_page_info2),
B_AX_PUB_AVAL_PG_MASK);
info->wp_aval =
u32_get_bits(rtw89_read32(rtwdev, regs->wp_page_info1),
B_AX_WP_AVAL_PG_MASK);
val = rtw89_read32(rtwdev, regs->hci_fc_ctrl);
param->en = val & B_AX_HCI_FC_EN ? 1 : 0;
param->h2c_en = val & B_AX_HCI_FC_CH12_EN ? 1 : 0;
param->mode = u32_get_bits(val, B_AX_HCI_FC_MODE_MASK);
prec_cfg->ch011_full_cond =
u32_get_bits(val, B_AX_HCI_FC_WD_FULL_COND_MASK);
prec_cfg->h2c_full_cond =
u32_get_bits(val, B_AX_HCI_FC_CH12_FULL_COND_MASK);
prec_cfg->wp_ch07_full_cond =
u32_get_bits(val, B_AX_HCI_FC_WP_CH07_FULL_COND_MASK);
prec_cfg->wp_ch811_full_cond =
u32_get_bits(val, B_AX_HCI_FC_WP_CH811_FULL_COND_MASK);
val = rtw89_read32(rtwdev, regs->ch_page_ctrl);
prec_cfg->ch011_prec = u32_get_bits(val, B_AX_PREC_PAGE_CH011_MASK);
prec_cfg->h2c_prec = u32_get_bits(val, B_AX_PREC_PAGE_CH12_MASK);
val = rtw89_read32(rtwdev, regs->pub_page_ctrl2);
pub_cfg->pub_max = u32_get_bits(val, B_AX_PUBPG_ALL_MASK);
val = rtw89_read32(rtwdev, regs->wp_page_ctrl1);
prec_cfg->wp_ch07_prec = u32_get_bits(val, B_AX_PREC_PAGE_WP_CH07_MASK);
prec_cfg->wp_ch811_prec = u32_get_bits(val, B_AX_PREC_PAGE_WP_CH811_MASK);
val = rtw89_read32(rtwdev, regs->wp_page_ctrl2);
pub_cfg->wp_thrd = u32_get_bits(val, B_AX_WP_THRD_MASK);
val = rtw89_read32(rtwdev, regs->pub_page_ctrl1);
pub_cfg->grp0 = u32_get_bits(val, B_AX_PUBPG_G0_MASK);
pub_cfg->grp1 = u32_get_bits(val, B_AX_PUBPG_G1_MASK);
}
static int hfc_upd_mix_info(struct rtw89_dev *rtwdev)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
int ret;
ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
if (ret)
return ret;
mac->hfc_get_mix_info(rtwdev);
ret = hfc_pub_info_chk(rtwdev);
if (param->en && ret)
return ret;
return 0;
}
static void hfc_h2c_cfg_ax(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_page_regs *regs = chip->page_regs;
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg;
u32 val;
val = u32_encode_bits(prec_cfg->h2c_prec, B_AX_PREC_PAGE_CH12_MASK);
rtw89_write32(rtwdev, regs->ch_page_ctrl, val);
rtw89_write32_mask(rtwdev, regs->hci_fc_ctrl,
B_AX_HCI_FC_CH12_FULL_COND_MASK,
prec_cfg->h2c_full_cond);
}
static void hfc_mix_cfg_ax(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_page_regs *regs = chip->page_regs;
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg;
const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg;
u32 val;
val = u32_encode_bits(prec_cfg->ch011_prec, B_AX_PREC_PAGE_CH011_MASK) |
u32_encode_bits(prec_cfg->h2c_prec, B_AX_PREC_PAGE_CH12_MASK);
rtw89_write32(rtwdev, regs->ch_page_ctrl, val);
val = u32_encode_bits(pub_cfg->pub_max, B_AX_PUBPG_ALL_MASK);
rtw89_write32(rtwdev, regs->pub_page_ctrl2, val);
val = u32_encode_bits(prec_cfg->wp_ch07_prec,
B_AX_PREC_PAGE_WP_CH07_MASK) |
u32_encode_bits(prec_cfg->wp_ch811_prec,
B_AX_PREC_PAGE_WP_CH811_MASK);
rtw89_write32(rtwdev, regs->wp_page_ctrl1, val);
val = u32_replace_bits(rtw89_read32(rtwdev, regs->hci_fc_ctrl),
param->mode, B_AX_HCI_FC_MODE_MASK);
val = u32_replace_bits(val, prec_cfg->ch011_full_cond,
B_AX_HCI_FC_WD_FULL_COND_MASK);
val = u32_replace_bits(val, prec_cfg->h2c_full_cond,
B_AX_HCI_FC_CH12_FULL_COND_MASK);
val = u32_replace_bits(val, prec_cfg->wp_ch07_full_cond,
B_AX_HCI_FC_WP_CH07_FULL_COND_MASK);
val = u32_replace_bits(val, prec_cfg->wp_ch811_full_cond,
B_AX_HCI_FC_WP_CH811_FULL_COND_MASK);
rtw89_write32(rtwdev, regs->hci_fc_ctrl, val);
}
static void hfc_func_en_ax(struct rtw89_dev *rtwdev, bool en, bool h2c_en)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_page_regs *regs = chip->page_regs;
struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param;
u32 val;
val = rtw89_read32(rtwdev, regs->hci_fc_ctrl);
param->en = en;
param->h2c_en = h2c_en;
val = en ? (val | B_AX_HCI_FC_EN) : (val & ~B_AX_HCI_FC_EN);
val = h2c_en ? (val | B_AX_HCI_FC_CH12_EN) :
(val & ~B_AX_HCI_FC_CH12_EN);
rtw89_write32(rtwdev, regs->hci_fc_ctrl, val);
}
int rtw89_mac_hfc_init(struct rtw89_dev *rtwdev, bool reset, bool en, bool h2c_en)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_chip_info *chip = rtwdev->chip;
u32 dma_ch_mask = chip->dma_ch_mask;
u8 ch;
u32 ret = 0;
if (reset)
ret = hfc_reset_param(rtwdev);
if (ret)
return ret;
ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL);
if (ret)
return ret;
mac->hfc_func_en(rtwdev, false , false );
if (!en && h2c_en) {
mac->hfc_h2c_cfg(rtwdev);
mac->hfc_func_en(rtwdev, en, h2c_en);
return ret;
}
for (ch = RTW89_DMA_ACH0; ch < RTW89_DMA_H2C; ch++) {
if (dma_ch_mask & BIT(ch))
continue ;
ret = hfc_ch_ctrl(rtwdev, ch);
if (ret)
return ret;
}
ret = hfc_pub_ctrl(rtwdev);
if (ret)
return ret;
mac->hfc_mix_cfg(rtwdev);
if (en || h2c_en) {
mac->hfc_func_en(rtwdev, en, h2c_en);
udelay(10);
}
for (ch = RTW89_DMA_ACH0; ch < RTW89_DMA_H2C; ch++) {
if (dma_ch_mask & BIT(ch))
continue ;
ret = hfc_upd_ch_info(rtwdev, ch);
if (ret)
return ret;
}
ret = hfc_upd_mix_info(rtwdev);
return ret;
}
#define PWR_POLL_CNT 2000
static int pwr_cmd_poll(struct rtw89_dev *rtwdev,
const struct rtw89_pwr_cfg *cfg)
{
u8 val = 0;
int ret;
u32 addr = cfg->base == PWR_INTF_MSK_SDIO ?
cfg->addr | SDIO_LOCAL_BASE_ADDR : cfg->addr;
ret = read_poll_timeout(rtw89_read8, val, !((val ^ cfg->val) & cfg->msk),
1000, 1000 * PWR_POLL_CNT, false , rtwdev, addr);
if (!ret)
return 0;
rtw89_warn(rtwdev, "[ERR] Polling timeout\n" );
rtw89_warn(rtwdev, "[ERR] addr: %X, %X\n" , addr, cfg->addr);
rtw89_warn(rtwdev, "[ERR] val: %X, %X\n" , val, cfg->val);
return -EBUSY;
}
static int rtw89_mac_sub_pwr_seq(struct rtw89_dev *rtwdev, u8 cv_msk,
u8 intf_msk, const struct rtw89_pwr_cfg *cfg)
{
const struct rtw89_pwr_cfg *cur_cfg;
u32 addr;
u8 val;
for (cur_cfg = cfg; cur_cfg->cmd != PWR_CMD_END; cur_cfg++) {
if (!(cur_cfg->intf_msk & intf_msk) ||
!(cur_cfg->cv_msk & cv_msk))
continue ;
switch (cur_cfg->cmd) {
case PWR_CMD_WRITE:
addr = cur_cfg->addr;
if (cur_cfg->base == PWR_BASE_SDIO)
addr |= SDIO_LOCAL_BASE_ADDR;
val = rtw89_read8(rtwdev, addr);
val &= ~(cur_cfg->msk);
val |= (cur_cfg->val & cur_cfg->msk);
rtw89_write8(rtwdev, addr, val);
break ;
case PWR_CMD_POLL:
if (pwr_cmd_poll(rtwdev, cur_cfg))
return -EBUSY;
break ;
case PWR_CMD_DELAY:
if (cur_cfg->val == PWR_DELAY_US)
udelay(cur_cfg->addr);
else
fsleep(cur_cfg->addr * 1000);
break ;
default :
return -EINVAL;
}
}
return 0;
}
static int rtw89_mac_pwr_seq(struct rtw89_dev *rtwdev,
const struct rtw89_pwr_cfg * const *cfg_seq)
{
int ret;
for (; *cfg_seq; cfg_seq++) {
ret = rtw89_mac_sub_pwr_seq(rtwdev, BIT(rtwdev->hal.cv),
PWR_INTF_MSK_PCIE, *cfg_seq);
if (ret)
return -EBUSY;
}
return 0;
}
static enum rtw89_rpwm_req_pwr_state
rtw89_mac_get_req_pwr_state(struct rtw89_dev *rtwdev)
{
enum rtw89_rpwm_req_pwr_state state;
switch (rtwdev->ps_mode) {
case RTW89_PS_MODE_RFOFF:
state = RTW89_MAC_RPWM_REQ_PWR_STATE_BAND0_RFOFF;
break ;
case RTW89_PS_MODE_CLK_GATED:
state = RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED;
break ;
case RTW89_PS_MODE_PWR_GATED:
state = RTW89_MAC_RPWM_REQ_PWR_STATE_PWR_GATED;
break ;
default :
state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;
break ;
}
return state;
}
static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
enum rtw89_rpwm_req_pwr_state req_pwr_state,
bool notify_wake)
{
u16 request;
spin_lock_bh(&rtwdev->rpwm_lock);
request = rtw89_read16(rtwdev, R_AX_RPWM);
request ^= request | PS_RPWM_TOGGLE;
request |= req_pwr_state;
if (notify_wake) {
request |= PS_RPWM_NOTIFY_WAKE;
} else {
rtwdev->mac.rpwm_seq_num = (rtwdev->mac.rpwm_seq_num + 1) &
RPWM_SEQ_NUM_MAX;
request |= FIELD_PREP(PS_RPWM_SEQ_NUM,
rtwdev->mac.rpwm_seq_num);
if (req_pwr_state < RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED)
request |= PS_RPWM_ACK;
}
rtw89_write16(rtwdev, rtwdev->hci.rpwm_addr, request);
spin_unlock_bh(&rtwdev->rpwm_lock);
}
static int rtw89_mac_check_cpwm_state(struct rtw89_dev *rtwdev,
enum rtw89_rpwm_req_pwr_state req_pwr_state)
{
bool request_deep_mode;
bool in_deep_mode;
u8 rpwm_req_num;
u8 cpwm_rsp_seq;
u8 cpwm_seq;
u8 cpwm_status;
if (req_pwr_state >= RTW89_MAC_RPWM_REQ_PWR_STATE_CLK_GATED)
request_deep_mode = true ;
else
request_deep_mode = false ;
if (rtw89_read32_mask(rtwdev, R_AX_LDM, B_AX_EN_32K))
in_deep_mode = true ;
else
in_deep_mode = false ;
if (request_deep_mode != in_deep_mode)
return -EPERM;
if (request_deep_mode)
return 0;
rpwm_req_num = rtwdev->mac.rpwm_seq_num;
cpwm_rsp_seq = rtw89_read16_mask(rtwdev, rtwdev->hci.cpwm_addr,
PS_CPWM_RSP_SEQ_NUM);
if (rpwm_req_num != cpwm_rsp_seq)
return -EPERM;
rtwdev->mac.cpwm_seq_num = (rtwdev->mac.cpwm_seq_num + 1) &
CPWM_SEQ_NUM_MAX;
cpwm_seq = rtw89_read16_mask(rtwdev, rtwdev->hci.cpwm_addr, PS_CPWM_SEQ_NUM);
if (cpwm_seq != rtwdev->mac.cpwm_seq_num)
return -EPERM;
cpwm_status = rtw89_read16_mask(rtwdev, rtwdev->hci.cpwm_addr, PS_CPWM_STATE);
if (cpwm_status != req_pwr_state)
return -EPERM;
return 0;
}
void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
{
enum rtw89_rpwm_req_pwr_state state;
unsigned long delay = enter ? 10 : 150;
int ret;
int i;
if (enter)
state = rtw89_mac_get_req_pwr_state(rtwdev);
else
state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;
for (i = 0; i < RPWM_TRY_CNT; i++) {
rtw89_mac_send_rpwm(rtwdev, state, false );
ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret,
!ret, delay, 15000, false ,
rtwdev, state);
if (!ret)
break ;
if (i == RPWM_TRY_CNT - 1)
rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n" ,
enter ? "entering" : "leaving" );
else
rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
"%d time firmware failed to ack for %s ps mode\n" ,
i + 1, enter ? "entering" : "leaving" );
}
}
void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev)
{
enum rtw89_rpwm_req_pwr_state state;
state = rtw89_mac_get_req_pwr_state(rtwdev);
rtw89_mac_send_rpwm(rtwdev, state, true );
}
static void rtw89_mac_power_switch_boot_mode(struct rtw89_dev *rtwdev)
{
u32 boot_mode;
if (rtwdev->hci.type != RTW89_HCI_TYPE_USB)
return ;
boot_mode = rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);
if (!boot_mode)
return ;
rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC);
rtw89_write32_clr(rtwdev, R_AX_SYS_STATUS1, B_AX_AUTO_WLPON);
rtw89_write32_clr(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);
rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
}
static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
{
#define PWR_ACT 1
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
const struct rtw89_chip_info *chip = rtwdev->chip;
const struct rtw89_pwr_cfg * const *cfg_seq;
int (*cfg_func)(struct rtw89_dev *rtwdev);
int ret;
u8 val;
rtw89_mac_power_switch_boot_mode(rtwdev);
if (on) {
cfg_seq = chip->pwr_on_seq;
cfg_func = chip->ops->pwr_on_func;
} else {
cfg_seq = chip->pwr_off_seq;
cfg_func = chip->ops->pwr_off_func;
}
if (test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags))
__rtw89_leave_ps_mode(rtwdev);
val = rtw89_read32_mask(rtwdev, R_AX_IC_PWR_STATE, B_AX_WLMAC_PWR_STE_MASK);
if (on && val == PWR_ACT) {
rtw89_err(rtwdev, "MAC has already powered on\n" );
return -EBUSY;
}
ret = cfg_func ? cfg_func(rtwdev) : rtw89_mac_pwr_seq(rtwdev, cfg_seq);
if (ret)
return ret;
if (on) {
if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags))
mac->efuse_read_fw_secure(rtwdev);
set_bit(RTW89_FLAG_POWERON, rtwdev->flags);
set_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
set_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_TP_MAJOR);
} else {
clear_bit(RTW89_FLAG_POWERON, rtwdev->flags);
clear_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
clear_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags);
clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags);
rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR);
rtw89_set_entity_state(rtwdev, RTW89_PHY_0, false );
rtw89_set_entity_state(rtwdev, RTW89_PHY_1, false );
}
return 0;
#undef PWR_ACT
}
int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev)
{
int ret;
ret = rtw89_mac_power_switch(rtwdev, true );
if (ret) {
rtw89_mac_power_switch(rtwdev, false );
ret = rtw89_mac_power_switch(rtwdev, true );
if (ret)
return ret;
}
return 0;
}
void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev)
{
rtw89_mac_power_switch(rtwdev, false );
}
static int cmac_func_en_ax(struct rtw89_dev *rtwdev, u8 mac_idx, bool en)
{
u32 func_en = 0;
u32 ck_en = 0;
u32 c1pc_en = 0;
u32 addrl_func_en[] = {R_AX_CMAC_FUNC_EN, R_AX_CMAC_FUNC_EN_C1};
u32 addrl_ck_en[] = {R_AX_CK_EN, R_AX_CK_EN_C1};
func_en = B_AX_CMAC_EN | B_AX_CMAC_TXEN | B_AX_CMAC_RXEN |
B_AX_PHYINTF_EN | B_AX_CMAC_DMA_EN | B_AX_PTCLTOP_EN |
B_AX_SCHEDULER_EN | B_AX_TMAC_EN | B_AX_RMAC_EN |
B_AX_CMAC_CRPRT;
ck_en = B_AX_CMAC_CKEN | B_AX_PHYINTF_CKEN | B_AX_CMAC_DMA_CKEN |
B_AX_PTCLTOP_CKEN | B_AX_SCHEDULER_CKEN | B_AX_TMAC_CKEN |
B_AX_RMAC_CKEN;
c1pc_en = B_AX_R_SYM_WLCMAC1_PC_EN |
B_AX_R_SYM_WLCMAC1_P1_PC_EN |
B_AX_R_SYM_WLCMAC1_P2_PC_EN |
B_AX_R_SYM_WLCMAC1_P3_PC_EN |
B_AX_R_SYM_WLCMAC1_P4_PC_EN;
if (en) {
if (mac_idx == RTW89_MAC_1) {
rtw89_write32_set(rtwdev, R_AX_AFE_CTRL1, c1pc_en);
rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
B_AX_R_SYM_ISO_CMAC12PP);
rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
B_AX_CMAC1_FEN);
}
rtw89_write32_set(rtwdev, addrl_ck_en[mac_idx], ck_en);
rtw89_write32_set(rtwdev, addrl_func_en[mac_idx], func_en);
} else {
rtw89_write32_clr(rtwdev, addrl_func_en[mac_idx], func_en);
rtw89_write32_clr(rtwdev, addrl_ck_en[mac_idx], ck_en);
if (mac_idx == RTW89_MAC_1) {
rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
B_AX_CMAC1_FEN);
rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL_EXTEND,
B_AX_R_SYM_ISO_CMAC12PP);
rtw89_write32_clr(rtwdev, R_AX_AFE_CTRL1, c1pc_en);
}
}
return 0;
}
static int dmac_func_en_ax(struct rtw89_dev *rtwdev)
{
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
u32 val32;
if (chip_id == RTL8852C)
val32 = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN |
B_AX_MAC_SEC_EN | B_AX_DISPATCHER_EN |
B_AX_DLE_CPUIO_EN | B_AX_PKT_IN_EN |
B_AX_DMAC_TBL_EN | B_AX_PKT_BUF_EN |
B_AX_STA_SCH_EN | B_AX_TXPKT_CTRL_EN |
B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN |
B_AX_DMAC_CRPRT | B_AX_H_AXIDMA_EN);
else
val32 = (B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN |
B_AX_MAC_SEC_EN | B_AX_DISPATCHER_EN |
B_AX_DLE_CPUIO_EN | B_AX_PKT_IN_EN |
B_AX_DMAC_TBL_EN | B_AX_PKT_BUF_EN |
B_AX_STA_SCH_EN | B_AX_TXPKT_CTRL_EN |
B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN |
B_AX_DMAC_CRPRT);
rtw89_write32(rtwdev, R_AX_DMAC_FUNC_EN, val32);
val32 = (B_AX_MAC_SEC_CLK_EN | B_AX_DISPATCHER_CLK_EN |
B_AX_DLE_CPUIO_CLK_EN | B_AX_PKT_IN_CLK_EN |
B_AX_STA_SCH_CLK_EN | B_AX_TXPKT_CTRL_CLK_EN |
B_AX_WD_RLS_CLK_EN | B_AX_BBRPT_CLK_EN);
if (chip_id == RTL8852BT)
val32 |= B_AX_AXIDMA_CLK_EN;
rtw89_write32(rtwdev, R_AX_DMAC_CLK_EN, val32);
return 0;
}
static int chip_func_en_ax(struct rtw89_dev *rtwdev)
{
enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev))
rtw89_write32_set(rtwdev, R_AX_SPS_DIG_ON_CTRL0,
B_AX_OCP_L1_MASK);
return 0;
}
static int sys_init_ax(struct rtw89_dev *rtwdev)
{
int ret;
ret = dmac_func_en_ax(rtwdev);
if (ret)
return ret;
ret = cmac_func_en_ax(rtwdev, 0, true );
if (ret)
return ret;
ret = chip_func_en_ax(rtwdev);
if (ret)
return ret;
return ret;
}
const struct rtw89_mac_size_set rtw89_mac_size = {
.hfc_preccfg_pcie = {2, 40, 0, 0, 1, 0, 0, 0},
.hfc_prec_cfg_c0 = {2, 32, 0, 0, 0, 0, 0, 0},
.hfc_prec_cfg_c2 = {0, 256, 0, 0, 0, 0, 0, 0},
/* PCIE 64 */
.wde_size0 = {RTW89_WDE_PG_64, 4095, 1,},
.wde_size0_v1 = {RTW89_WDE_PG_64, 3328, 0, 0,},
/* DLFW */
.wde_size4 = {RTW89_WDE_PG_64, 0, 4096,},
.wde_size4_v1 = {RTW89_WDE_PG_64, 0, 3328, 0,},
/* PCIE 64 */
.wde_size6 = {RTW89_WDE_PG_64, 512, 0,},
/* 8852B PCIE SCC */
.wde_size7 = {RTW89_WDE_PG_64, 510, 2,},
/* DLFW */
.wde_size9 = {RTW89_WDE_PG_64, 0, 1024,},
/* 8852C DLFW */
.wde_size18 = {RTW89_WDE_PG_64, 0, 2048,},
/* 8852C PCIE SCC */
.wde_size19 = {RTW89_WDE_PG_64, 3328, 0,},
.wde_size23 = {RTW89_WDE_PG_64, 1022, 2,},
/* 8852B USB2.0/USB3.0 SCC */
.wde_size25 = {RTW89_WDE_PG_64, 162, 94,},
/* PCIE */
.ple_size0 = {RTW89_PLE_PG_128, 1520, 16,},
.ple_size0_v1 = {RTW89_PLE_PG_128, 2688, 240, 212992,},
.ple_size3_v1 = {RTW89_PLE_PG_128, 2928, 0, 212992,},
/* DLFW */
.ple_size4 = {RTW89_PLE_PG_128, 64, 1472,},
/* PCIE 64 */
.ple_size6 = {RTW89_PLE_PG_128, 496, 16,},
/* DLFW */
.ple_size8 = {RTW89_PLE_PG_128, 64, 960,},
.ple_size9 = {RTW89_PLE_PG_128, 2288, 16,},
/* 8852C DLFW */
.ple_size18 = {RTW89_PLE_PG_128, 2544, 16,},
/* 8852C PCIE SCC */
.ple_size19 = {RTW89_PLE_PG_128, 1904, 16,},
/* 8852B USB2.0 SCC */
.ple_size32 = {RTW89_PLE_PG_128, 620, 20,},
/* 8852B USB3.0 SCC */
.ple_size33 = {RTW89_PLE_PG_128, 632, 8,},
/* PCIE 64 */
.wde_qt0 = {3792, 196, 0, 107,},
.wde_qt0_v1 = {3302, 6, 0, 20,},
/* DLFW */
.wde_qt4 = {0, 0, 0, 0,},
/* PCIE 64 */
.wde_qt6 = {448, 48, 0, 16,},
/* 8852B PCIE SCC */
.wde_qt7 = {446, 48, 0, 16,},
/* 8852C DLFW */
.wde_qt17 = {0, 0, 0, 0,},
/* 8852C PCIE SCC */
.wde_qt18 = {3228, 60, 0, 40,},
.wde_qt23 = {958, 48, 0, 16,},
/* 8852B USB2.0/USB3.0 SCC */
.wde_qt25 = {152, 2, 0, 8,},
.ple_qt0 = {320, 320, 32, 16, 13, 13, 292, 292, 64, 18, 1, 4, 0,},
.ple_qt1 = {320, 320, 32, 16, 1316, 1316, 1595, 1595, 1367, 1321, 1, 1307, 0,},
/* PCIE SCC */
.ple_qt4 = {264, 0, 16, 20, 26, 13, 356, 0, 32, 40, 8,},
/* PCIE SCC */
.ple_qt5 = {264, 0, 32, 20, 64, 13, 1101, 0, 64, 128, 120,},
.ple_qt9 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 1, 0, 0,},
/* DLFW */
.ple_qt13 = {0, 0, 16, 48, 0, 0, 0, 0, 0, 0, 0,},
/* PCIE 64 */
.ple_qt18 = {147, 0, 16, 20, 17, 13, 89, 0, 32, 14, 8, 0,},
/* DLFW 52C */
.ple_qt44 = {0, 0, 16, 256, 0, 0, 0, 0, 0, 0, 0, 0,},
/* DLFW 52C */
.ple_qt45 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 0, 0,},
/* 8852C PCIE SCC */
.ple_qt46 = {525, 0, 16, 20, 13, 13, 178, 0, 32, 62, 8, 16,},
/* 8852C PCIE SCC */
.ple_qt47 = {525, 0, 32, 20, 1034, 13, 1199, 0, 1053, 62, 160, 1037,},
.ple_qt57 = {147, 0, 16, 20, 13, 13, 178, 0, 32, 14, 8, 0,},
/* PCIE 64 */
.ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,},
.ple_qt59 = {147, 0, 32, 20, 1860, 13, 2025, 0, 1879, 14, 24, 0,},
/* USB2.0 52B SCC */
.ple_qt72 = {130, 0, 16, 48, 4, 13, 322, 0, 32, 14, 8, 0, 0,},
/* USB2.0 52B 92K */
.ple_qt73 = {130, 0, 32, 48, 37, 13, 355, 0, 65, 14, 24, 0, 0,},
/* USB3.0 52B 92K */
.ple_qt74 = {286, 0, 16, 48, 4, 13, 178, 0, 32, 14, 8, 0, 0,},
.ple_qt75 = {286, 0, 32, 48, 37, 13, 211, 0, 65, 14, 24, 0, 0,},
/* 8852A PCIE WOW */
.ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,},
/* 8852B PCIE WOW */
.ple_qt_52b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
/* 8852BT PCIE WOW */
.ple_qt_52bt_wow = {147, 0, 32, 20, 1860, 13, 1929, 0, 1879, 14, 24, 0,},
/* 8851B PCIE WOW */
.ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
.ple_rsvd_qt0 = {2, 107, 107, 6, 6, 6, 6, 0, 0, 0,},
.ple_rsvd_qt1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
.rsvd0_size0 = {212992, 0,},
.rsvd1_size0 = {587776, 2048,},
};
EXPORT_SYMBOL(rtw89_mac_size);
static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
enum rtw89_qta_mode mode)
{
struct rtw89_mac_info *mac = &rtwdev->mac;
const struct rtw89_dle_mem *cfg, *cfgs;
cfgs = rtwdev->chip->dle_mem[rtwdev->hci.dle_type];
if (!cfgs)
return NULL;
cfg = &cfgs[mode];
if (cfg->mode != mode) {
rtw89_warn(rtwdev, "qta mode unmatch!\n" );
return NULL;
}
mac->dle_info.rsvd_qt = cfg->rsvd_qt;
mac->dle_info.ple_pg_size = cfg->ple_size->pge_size;
mac->dle_info.ple_free_pg = cfg->ple_size->lnk_pge_num;
mac->dle_info.qta_mode = mode;
mac->dle_info.c0_rx_qta = cfg->ple_min_qt->cma0_dma;
mac->dle_info.c1_rx_qta = cfg->ple_min_qt->cma1_dma;
return cfg;
}
int rtw89_mac_get_dle_rsvd_qt_cfg(struct rtw89_dev *rtwdev,
enum rtw89_mac_dle_rsvd_qt_type type,
struct rtw89_mac_dle_rsvd_qt_cfg *cfg)
{
struct rtw89_dle_info *dle_info = &rtwdev->mac.dle_info;
const struct rtw89_rsvd_quota *rsvd_qt = dle_info->rsvd_qt;
switch (type) {
case DLE_RSVD_QT_MPDU_INFO:
cfg->pktid = dle_info->ple_free_pg;
cfg->pg_num = rsvd_qt->mpdu_info_tbl;
break ;
case DLE_RSVD_QT_B0_CSI:
cfg->pktid = dle_info->ple_free_pg + rsvd_qt->mpdu_info_tbl;
cfg->pg_num = rsvd_qt->b0_csi;
break ;
case DLE_RSVD_QT_B1_CSI:
cfg->pktid = dle_info->ple_free_pg +
rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi;
cfg->pg_num = rsvd_qt->b1_csi;
break ;
case DLE_RSVD_QT_B0_LMR:
cfg->pktid = dle_info->ple_free_pg +
rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi;
cfg->pg_num = rsvd_qt->b0_lmr;
break ;
case DLE_RSVD_QT_B1_LMR:
cfg->pktid = dle_info->ple_free_pg +
rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi +
rsvd_qt->b0_lmr;
cfg->pg_num = rsvd_qt->b1_lmr;
break ;
case DLE_RSVD_QT_B0_FTM:
cfg->pktid = dle_info->ple_free_pg +
rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi +
rsvd_qt->b0_lmr + rsvd_qt->b1_lmr;
cfg->pg_num = rsvd_qt->b0_ftm;
break ;
case DLE_RSVD_QT_B1_FTM:
cfg->pktid = dle_info->ple_free_pg +
rsvd_qt->mpdu_info_tbl + rsvd_qt->b0_csi + rsvd_qt->b1_csi +
rsvd_qt->b0_lmr + rsvd_qt->b1_lmr + rsvd_qt->b0_ftm;
cfg->pg_num = rsvd_qt->b1_ftm;
break ;
default :
return -EINVAL;
}
cfg->size = (u32)cfg->pg_num * dle_info->ple_pg_size;
return 0;
}
static bool mac_is_txq_empty_ax(struct rtw89_dev *rtwdev)
{
struct rtw89_mac_dle_dfi_qempty qempty;
u32 grpnum, qtmp, val32, msk32;
int i, j, ret;
grpnum = rtwdev->chip->wde_qempty_acq_grpnum;
qempty.dle_type = DLE_CTRL_TYPE_WDE;
for (i = 0; i < grpnum; i++) {
qempty.grpsel = i;
ret = rtw89_mac_dle_dfi_qempty_cfg(rtwdev, &qempty);
if (ret) {
rtw89_warn(rtwdev, "dle dfi acq empty %d\n" , ret);
return false ;
}
qtmp = qempty.qempty;
for (j = 0 ; j < QEMP_ACQ_GRP_MACID_NUM; j++) {
val32 = u32_get_bits(qtmp, QEMP_ACQ_GRP_QSEL_MASK);
if (val32 != QEMP_ACQ_GRP_QSEL_MASK)
return false ;
qtmp >>= QEMP_ACQ_GRP_QSEL_SH;
}
}
qempty.grpsel = rtwdev->chip->wde_qempty_mgq_grpsel;
ret = rtw89_mac_dle_dfi_qempty_cfg(rtwdev, &qempty);
if (ret) {
rtw89_warn(rtwdev, "dle dfi mgq empty %d\n" , ret);
return false ;
}
msk32 = B_CMAC0_MGQ_NORMAL | B_CMAC0_MGQ_NO_PWRSAV | B_CMAC0_CPUMGQ;
if ((qempty.qempty & msk32) != msk32)
return false ;
if (rtwdev->dbcc_en) {
msk32 |= B_CMAC1_MGQ_NORMAL | B_CMAC1_MGQ_NO_PWRSAV | B_CMAC1_CPUMGQ;
if ((qempty.qempty & msk32) != msk32)
return false ;
}
msk32 = B_AX_WDE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_WDE_EMPTY_QTA_DMAC_DATA_CPU |
B_AX_PLE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_PLE_EMPTY_QTA_DMAC_H2C |
B_AX_WDE_EMPTY_QUE_OTHERS | B_AX_PLE_EMPTY_QUE_DMAC_MPDU_TX |
B_AX_WDE_EMPTY_QTA_DMAC_CPUIO | B_AX_PLE_EMPTY_QTA_DMAC_CPUIO |
B_AX_WDE_EMPTY_QUE_DMAC_PKTIN | B_AX_WDE_EMPTY_QTA_DMAC_HIF |
B_AX_PLE_EMPTY_QUE_DMAC_SEC_TX | B_AX_WDE_EMPTY_QTA_DMAC_PKTIN |
B_AX_PLE_EMPTY_QTA_DMAC_B0_TXPL | B_AX_PLE_EMPTY_QTA_DMAC_B1_TXPL |
B_AX_PLE_EMPTY_QTA_DMAC_MPDU_TX;
val32 = rtw89_read32(rtwdev, R_AX_DLE_EMPTY0);
return (val32 & msk32) == msk32;
}
static inline u32 dle_used_size(const struct rtw89_dle_mem *cfg)
{
const struct rtw89_dle_size *wde = cfg->wde_size;
const struct rtw89_dle_size *ple = cfg->ple_size;
u32 used;
used = wde->pge_size * (wde->lnk_pge_num + wde->unlnk_pge_num) +
ple->pge_size * (ple->lnk_pge_num + ple->unlnk_pge_num);
if (cfg->rsvd0_size && cfg->rsvd1_size) {
used += cfg->rsvd0_size->size;
used += cfg->rsvd1_size->size;
}
return used;
}
static u32 dle_expected_used_size(struct rtw89_dev *rtwdev,
enum rtw89_qta_mode mode)
{
u32 size = rtwdev->chip->fifo_size;
if (mode == RTW89_QTA_SCC)
size -= rtwdev->chip->dle_scc_rsvd_size;
return size;
}
static void dle_func_en_ax(struct rtw89_dev *rtwdev, bool enable)
{
if (enable)
rtw89_write32_set(rtwdev, R_AX_DMAC_FUNC_EN,
B_AX_DLE_WDE_EN | B_AX_DLE_PLE_EN);
else
rtw89_write32_clr(rtwdev, R_AX_DMAC_FUNC_EN,
B_AX_DLE_WDE_EN | B_AX_DLE_PLE_EN);
}
static void dle_clk_en_ax(struct rtw89_dev *rtwdev, bool enable)
{
u32 val = B_AX_DLE_WDE_CLK_EN | B_AX_DLE_PLE_CLK_EN;
if (enable) {
if (rtwdev->chip->chip_id == RTL8851B)
val |= B_AX_AXIDMA_CLK_EN;
rtw89_write32_set(rtwdev, R_AX_DMAC_CLK_EN, val);
} else {
rtw89_write32_clr(rtwdev, R_AX_DMAC_CLK_EN, val);
}
}
static int dle_mix_cfg_ax(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg)
{
const struct rtw89_dle_size *size_cfg;
u32 val;
u8 bound = 0;
val = rtw89_read32(rtwdev, R_AX_WDE_PKTBUF_CFG);
size_cfg = cfg->wde_size;
switch (size_cfg->pge_size) {
default :
case RTW89_WDE_PG_64:
val = u32_replace_bits(val, S_AX_WDE_PAGE_SEL_64,
B_AX_WDE_PAGE_SEL_MASK);
break ;
case RTW89_WDE_PG_128:
val = u32_replace_bits(val, S_AX_WDE_PAGE_SEL_128,
B_AX_WDE_PAGE_SEL_MASK);
break ;
case RTW89_WDE_PG_256:
rtw89_err(rtwdev, "[ERR]WDE DLE doesn't support 256 byte!\n" );
return -EINVAL;
}
val = u32_replace_bits(val, bound, B_AX_WDE_START_BOUND_MASK);
val = u32_replace_bits(val, size_cfg->lnk_pge_num,
B_AX_WDE_FREE_PAGE_NUM_MASK);
rtw89_write32(rtwdev, R_AX_WDE_PKTBUF_CFG, val);
val = rtw89_read32(rtwdev, R_AX_PLE_PKTBUF_CFG);
bound = (size_cfg->lnk_pge_num + size_cfg->unlnk_pge_num)
* size_cfg->pge_size / DLE_BOUND_UNIT;
size_cfg = cfg->ple_size;
switch (size_cfg->pge_size) {
default :
case RTW89_PLE_PG_64:
rtw89_err(rtwdev, "[ERR]PLE DLE doesn't support 64 byte!\n" );
return -EINVAL;
case RTW89_PLE_PG_128:
val = u32_replace_bits(val, S_AX_PLE_PAGE_SEL_128,
B_AX_PLE_PAGE_SEL_MASK);
break ;
case RTW89_PLE_PG_256:
val = u32_replace_bits(val, S_AX_PLE_PAGE_SEL_256,
B_AX_PLE_PAGE_SEL_MASK);
break ;
}
val = u32_replace_bits(val, bound, B_AX_PLE_START_BOUND_MASK);
val = u32_replace_bits(val, size_cfg->lnk_pge_num,
B_AX_PLE_FREE_PAGE_NUM_MASK);
rtw89_write32(rtwdev, R_AX_PLE_PKTBUF_CFG, val);
return 0;
}
static int chk_dle_rdy_ax(struct rtw89_dev *rtwdev, bool wde_or_ple)
{
u32 reg, mask;
u32 ini;
if (wde_or_ple) {
reg = R_AX_WDE_INI_STATUS;
mask = WDE_MGN_INI_RDY;
} else {
reg = R_AX_PLE_INI_STATUS;
mask = PLE_MGN_INI_RDY;
}
return read_poll_timeout(rtw89_read32, ini, (ini & mask) == mask, 1,
2000, false , rtwdev, reg);
}
#define INVALID_QT_WCPU U16_MAX
#define SET_QUOTA_VAL(_min_x, _max_x, _module, _idx) \
do { \
val = u32_encode_bits(_min_x, B_AX_ ## _module ## _MIN_SIZE_MASK) | \
u32_encode_bits(_max_x, B_AX_ ## _module ## _MAX_SIZE_MASK); \
rtw89_write32(rtwdev, \
R_AX_ ## _module ## _QTA ## _idx ## _CFG, \
val); \
} while (0)
#define SET_QUOTA(_x, _module, _idx) \
SET_QUOTA_VAL(min_cfg->_x, max_cfg->_x, _module, _idx)
static void wde_quota_cfg_ax(struct rtw89_dev *rtwdev,
const struct rtw89_wde_quota *min_cfg,
const struct rtw89_wde_quota *max_cfg,
u16 ext_wde_min_qt_wcpu)
{
u16 min_qt_wcpu = ext_wde_min_qt_wcpu != INVALID_QT_WCPU ?
ext_wde_min_qt_wcpu : min_cfg->wcpu;
u32 val;
SET_QUOTA(hif, WDE, 0);
SET_QUOTA_VAL(min_qt_wcpu, max_cfg->wcpu, WDE, 1);
SET_QUOTA(pkt_in, WDE, 3);
SET_QUOTA(cpu_io, WDE, 4);
}
static void ple_quota_cfg_ax(struct rtw89_dev *rtwdev,
const struct rtw89_ple_quota *min_cfg,
const struct rtw89_ple_quota *max_cfg)
{
u32 val;
SET_QUOTA(cma0_tx, PLE, 0);
SET_QUOTA(cma1_tx, PLE, 1);
SET_QUOTA(c2h, PLE, 2);
SET_QUOTA(h2c, PLE, 3);
SET_QUOTA(wcpu, PLE, 4);
SET_QUOTA(mpdu_proc, PLE, 5);
SET_QUOTA(cma0_dma, PLE, 6);
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=99 H=96 G=97
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland