// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021, MediaTek Inc.
* Copyright (c) 2021-2022, Intel Corporation.
*
* Authors:
* Amir Hanania <amir.hanania@intel.com>
* Haijun Liu <haijun.liu@mediatek.com>
* Moises Veleta <moises.veleta@intel.com>
* Ricardo Martinez <ricardo.martinez@linux.intel.com>
*
* Contributors:
* Andy Shevchenko <andriy.shevchenko@linux.intel.com>
* Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
* Eliot Lee <eliot.lee@intel.com>
* Sreehari Kancharla <sreehari.kancharla@intel.com>
*/
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/dev_printk.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/types.h>
#include "t7xx_dpmaif.h"
#include "t7xx_reg.h"
#define ioread32_poll_timeout_atomic(addr, val, cond, delay_us, timeout_us) \
readx_poll_timeout_atomic(ioread32, addr, val, cond, delay_us, timeout_us)
static int t7xx_dpmaif_init_intr(struct dpmaif_hw_info *hw_info)
{
struct dpmaif_isr_en_mask *isr_en_msk = &hw_info->isr_en_mask;
u32 value, ul_intr_enable, dl_intr_enable;
int ret;
ul_intr_enable = DP_UL_INT_ERR_MSK | DP_UL_INT_QDONE_MSK;
isr_en_msk->ap_ul_l2intr_en_msk = ul_intr_enable;
iowrite32(DPMAIF_AP_ALL_L2TISAR0_MASK, hw_info->pcie_base + DPMAIF_AP_L2TISAR0);
/* Set interrupt enable mask */
iowrite32(ul_intr_enable, hw_info->pcie_base + DPMAIF_AO_UL_AP_L2TIMCR0);
iowrite32(~ul_intr_enable, hw_info->pcie_base + DPMAIF_AO_UL_AP_L2TIMSR0);
/* Check mask status */
ret = ioread32_poll_timeout_atomic(hw_info->pcie_base + DPMAIF_AO_UL_AP_L2TIMR0,
value, (value & ul_intr_enable) != ul_intr_enable, 0,
DPMAIF_CHECK_INIT_TIMEOUT_US);
if (ret)
return ret;
dl_intr_enable = DP_DL_INT_PITCNT_LEN_ERR | DP_DL_INT_BATCNT_LEN_ERR;
isr_en_msk->ap_dl_l2intr_err_en_msk = dl_intr_enable;
ul_intr_enable = DPMAIF_DL_INT_DLQ0_QDONE | DPMAIF_DL_INT_DLQ0_PITCNT_LEN |
DPMAIF_DL_INT_DLQ1_QDONE | DPMAIF_DL_INT_DLQ1_PITCNT_LEN;
isr_en_msk->ap_ul_l2intr_en_msk = ul_intr_enable;
iowrite32(DPMAIF_AP_APDL_ALL_L2TISAR0_MASK, hw_info->pcie_base + DPMAIF_AP_APDL_L2TISAR0);
/* Set DL ISR PD enable mask */
iowrite32(~ul_intr_enable, hw_info->pcie_base + DPMAIF_AO_UL_APDL_L2TIMSR0);
ret = ioread32_poll_timeout_atomic(hw_info->pcie_base + DPMAIF_AO_UL_APDL_L2TIMR0,
value, (value & ul_intr_enable) != ul_intr_enable, 0,
DPMAIF_CHECK_INIT_TIMEOUT_US);
if (ret)
return ret;
isr_en_msk->ap_udl_ip_busy_en_msk = DPMAIF_UDL_IP_BUSY;
iowrite32(DPMAIF_AP_IP_BUSY_MASK, hw_info->pcie_base + DPMAIF_AP_IP_BUSY);
iowrite32(isr_en_msk->ap_udl_ip_busy_en_msk,
hw_info->pcie_base + DPMAIF_AO_AP_DLUL_IP_BUSY_MASK);
value = ioread32(hw_info->pcie_base + DPMAIF_AO_UL_AP_L1TIMR0);
value |= DPMAIF_DL_INT_Q2APTOP | DPMAIF_DL_INT_Q2TOQ1;
iowrite32(value, hw_info->pcie_base + DPMAIF_AO_UL_AP_L1TIMR0);
iowrite32(DPMA_HPC_ALL_INT_MASK, hw_info->pcie_base + DPMAIF_HPC_INTR_MASK);
return 0;
}
static void t7xx_dpmaif_mask_ulq_intr(struct dpmaif_hw_info *hw_info, unsigned int q_num)
{
struct dpmaif_isr_en_mask *isr_en_msk;
u32 value, ul_int_que_done;
int ret;
isr_en_msk = &hw_info->isr_en_mask;
ul_int_que_done = BIT(q_num + DP_UL_INT_DONE_OFFSET) & DP_UL_INT_QDONE_MSK;
isr_en_msk->ap_ul_l2intr_en_msk &= ~ul_int_que_done;
iowrite32(ul_int_que_done, hw_info->pcie_base + DPMAIF_AO_UL_AP_L2TIMSR0);
ret = ioread32_poll_timeout_atomic(hw_info->pcie_base +