162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2020-2023 Intel Corporation 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/circ_buf.h> 762306a36Sopenharmony_ci#include <linux/highmem.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "ivpu_drv.h" 1062306a36Sopenharmony_ci#include "ivpu_hw_37xx_reg.h" 1162306a36Sopenharmony_ci#include "ivpu_hw_reg_io.h" 1262306a36Sopenharmony_ci#include "ivpu_mmu.h" 1362306a36Sopenharmony_ci#include "ivpu_mmu_context.h" 1462306a36Sopenharmony_ci#include "ivpu_pm.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define IVPU_MMU_IDR0_REF 0x080f3e0f 1762306a36Sopenharmony_ci#define IVPU_MMU_IDR0_REF_SIMICS 0x080f3e1f 1862306a36Sopenharmony_ci#define IVPU_MMU_IDR1_REF 0x0e739d18 1962306a36Sopenharmony_ci#define IVPU_MMU_IDR3_REF 0x0000003c 2062306a36Sopenharmony_ci#define IVPU_MMU_IDR5_REF 0x00040070 2162306a36Sopenharmony_ci#define IVPU_MMU_IDR5_REF_SIMICS 0x00000075 2262306a36Sopenharmony_ci#define IVPU_MMU_IDR5_REF_FPGA 0x00800075 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define IVPU_MMU_CDTAB_ENT_SIZE 64 2562306a36Sopenharmony_ci#define IVPU_MMU_CDTAB_ENT_COUNT_LOG2 8 /* 256 entries */ 2662306a36Sopenharmony_ci#define IVPU_MMU_CDTAB_ENT_COUNT ((u32)1 << IVPU_MMU_CDTAB_ENT_COUNT_LOG2) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define IVPU_MMU_STREAM_ID0 0 2962306a36Sopenharmony_ci#define IVPU_MMU_STREAM_ID3 3 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define IVPU_MMU_STRTAB_ENT_SIZE 64 3262306a36Sopenharmony_ci#define IVPU_MMU_STRTAB_ENT_COUNT 4 3362306a36Sopenharmony_ci#define IVPU_MMU_STRTAB_CFG_LOG2SIZE 2 3462306a36Sopenharmony_ci#define IVPU_MMU_STRTAB_CFG IVPU_MMU_STRTAB_CFG_LOG2SIZE 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define IVPU_MMU_Q_COUNT_LOG2 4 /* 16 entries */ 3762306a36Sopenharmony_ci#define IVPU_MMU_Q_COUNT ((u32)1 << IVPU_MMU_Q_COUNT_LOG2) 3862306a36Sopenharmony_ci#define IVPU_MMU_Q_WRAP_BIT (IVPU_MMU_Q_COUNT << 1) 3962306a36Sopenharmony_ci#define IVPU_MMU_Q_WRAP_MASK (IVPU_MMU_Q_WRAP_BIT - 1) 4062306a36Sopenharmony_ci#define IVPU_MMU_Q_IDX_MASK (IVPU_MMU_Q_COUNT - 1) 4162306a36Sopenharmony_ci#define IVPU_MMU_Q_IDX(val) ((val) & IVPU_MMU_Q_IDX_MASK) 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define IVPU_MMU_CMDQ_CMD_SIZE 16 4462306a36Sopenharmony_ci#define IVPU_MMU_CMDQ_SIZE (IVPU_MMU_Q_COUNT * IVPU_MMU_CMDQ_CMD_SIZE) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define IVPU_MMU_EVTQ_CMD_SIZE 32 4762306a36Sopenharmony_ci#define IVPU_MMU_EVTQ_SIZE (IVPU_MMU_Q_COUNT * IVPU_MMU_EVTQ_CMD_SIZE) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define IVPU_MMU_CMD_OPCODE GENMASK(7, 0) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define IVPU_MMU_CMD_SYNC_0_CS GENMASK(13, 12) 5262306a36Sopenharmony_ci#define IVPU_MMU_CMD_SYNC_0_MSH GENMASK(23, 22) 5362306a36Sopenharmony_ci#define IVPU_MMU_CMD_SYNC_0_MSI_ATTR GENMASK(27, 24) 5462306a36Sopenharmony_ci#define IVPU_MMU_CMD_SYNC_0_MSI_ATTR GENMASK(27, 24) 5562306a36Sopenharmony_ci#define IVPU_MMU_CMD_SYNC_0_MSI_DATA GENMASK(63, 32) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define IVPU_MMU_CMD_CFGI_0_SSEC BIT(10) 5862306a36Sopenharmony_ci#define IVPU_MMU_CMD_CFGI_0_SSV BIT(11) 5962306a36Sopenharmony_ci#define IVPU_MMU_CMD_CFGI_0_SSID GENMASK(31, 12) 6062306a36Sopenharmony_ci#define IVPU_MMU_CMD_CFGI_0_SID GENMASK(63, 32) 6162306a36Sopenharmony_ci#define IVPU_MMU_CMD_CFGI_1_RANGE GENMASK(4, 0) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define IVPU_MMU_CMD_TLBI_0_ASID GENMASK(63, 48) 6462306a36Sopenharmony_ci#define IVPU_MMU_CMD_TLBI_0_VMID GENMASK(47, 32) 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define CMD_PREFETCH_CFG 0x1 6762306a36Sopenharmony_ci#define CMD_CFGI_STE 0x3 6862306a36Sopenharmony_ci#define CMD_CFGI_ALL 0x4 6962306a36Sopenharmony_ci#define CMD_CFGI_CD 0x5 7062306a36Sopenharmony_ci#define CMD_CFGI_CD_ALL 0x6 7162306a36Sopenharmony_ci#define CMD_TLBI_NH_ASID 0x11 7262306a36Sopenharmony_ci#define CMD_TLBI_EL2_ALL 0x20 7362306a36Sopenharmony_ci#define CMD_TLBI_NSNH_ALL 0x30 7462306a36Sopenharmony_ci#define CMD_SYNC 0x46 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_UUT 0x01 7762306a36Sopenharmony_ci#define IVPU_MMU_EVT_C_BAD_STREAMID 0x02 7862306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_STE_FETCH 0x03 7962306a36Sopenharmony_ci#define IVPU_MMU_EVT_C_BAD_STE 0x04 8062306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_BAD_ATS_TREQ 0x05 8162306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_STREAM_DISABLED 0x06 8262306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_TRANSL_FORBIDDEN 0x07 8362306a36Sopenharmony_ci#define IVPU_MMU_EVT_C_BAD_SUBSTREAMID 0x08 8462306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_CD_FETCH 0x09 8562306a36Sopenharmony_ci#define IVPU_MMU_EVT_C_BAD_CD 0x0a 8662306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_WALK_EABT 0x0b 8762306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_TRANSLATION 0x10 8862306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_ADDR_SIZE 0x11 8962306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_ACCESS 0x12 9062306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_PERMISSION 0x13 9162306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_TLB_CONFLICT 0x20 9262306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_CFG_CONFLICT 0x21 9362306a36Sopenharmony_ci#define IVPU_MMU_EVT_E_PAGE_REQUEST 0x24 9462306a36Sopenharmony_ci#define IVPU_MMU_EVT_F_VMS_FETCH 0x25 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#define IVPU_MMU_EVT_OP_MASK GENMASK_ULL(7, 0) 9762306a36Sopenharmony_ci#define IVPU_MMU_EVT_SSID_MASK GENMASK_ULL(31, 12) 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#define IVPU_MMU_Q_BASE_RWA BIT(62) 10062306a36Sopenharmony_ci#define IVPU_MMU_Q_BASE_ADDR_MASK GENMASK_ULL(51, 5) 10162306a36Sopenharmony_ci#define IVPU_MMU_STRTAB_BASE_RA BIT(62) 10262306a36Sopenharmony_ci#define IVPU_MMU_STRTAB_BASE_ADDR_MASK GENMASK_ULL(51, 6) 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#define IVPU_MMU_IRQ_EVTQ_EN BIT(2) 10562306a36Sopenharmony_ci#define IVPU_MMU_IRQ_GERROR_EN BIT(0) 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#define IVPU_MMU_CR0_ATSCHK BIT(4) 10862306a36Sopenharmony_ci#define IVPU_MMU_CR0_CMDQEN BIT(3) 10962306a36Sopenharmony_ci#define IVPU_MMU_CR0_EVTQEN BIT(2) 11062306a36Sopenharmony_ci#define IVPU_MMU_CR0_PRIQEN BIT(1) 11162306a36Sopenharmony_ci#define IVPU_MMU_CR0_SMMUEN BIT(0) 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#define IVPU_MMU_CR1_TABLE_SH GENMASK(11, 10) 11462306a36Sopenharmony_ci#define IVPU_MMU_CR1_TABLE_OC GENMASK(9, 8) 11562306a36Sopenharmony_ci#define IVPU_MMU_CR1_TABLE_IC GENMASK(7, 6) 11662306a36Sopenharmony_ci#define IVPU_MMU_CR1_QUEUE_SH GENMASK(5, 4) 11762306a36Sopenharmony_ci#define IVPU_MMU_CR1_QUEUE_OC GENMASK(3, 2) 11862306a36Sopenharmony_ci#define IVPU_MMU_CR1_QUEUE_IC GENMASK(1, 0) 11962306a36Sopenharmony_ci#define IVPU_MMU_CACHE_NC 0 12062306a36Sopenharmony_ci#define IVPU_MMU_CACHE_WB 1 12162306a36Sopenharmony_ci#define IVPU_MMU_CACHE_WT 2 12262306a36Sopenharmony_ci#define IVPU_MMU_SH_NSH 0 12362306a36Sopenharmony_ci#define IVPU_MMU_SH_OSH 2 12462306a36Sopenharmony_ci#define IVPU_MMU_SH_ISH 3 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci#define IVPU_MMU_CMDQ_OP GENMASK_ULL(7, 0) 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#define IVPU_MMU_CD_0_TCR_T0SZ GENMASK_ULL(5, 0) 12962306a36Sopenharmony_ci#define IVPU_MMU_CD_0_TCR_TG0 GENMASK_ULL(7, 6) 13062306a36Sopenharmony_ci#define IVPU_MMU_CD_0_TCR_IRGN0 GENMASK_ULL(9, 8) 13162306a36Sopenharmony_ci#define IVPU_MMU_CD_0_TCR_ORGN0 GENMASK_ULL(11, 10) 13262306a36Sopenharmony_ci#define IVPU_MMU_CD_0_TCR_SH0 GENMASK_ULL(13, 12) 13362306a36Sopenharmony_ci#define IVPU_MMU_CD_0_TCR_EPD0 BIT_ULL(14) 13462306a36Sopenharmony_ci#define IVPU_MMU_CD_0_TCR_EPD1 BIT_ULL(30) 13562306a36Sopenharmony_ci#define IVPU_MMU_CD_0_ENDI BIT(15) 13662306a36Sopenharmony_ci#define IVPU_MMU_CD_0_V BIT(31) 13762306a36Sopenharmony_ci#define IVPU_MMU_CD_0_TCR_IPS GENMASK_ULL(34, 32) 13862306a36Sopenharmony_ci#define IVPU_MMU_CD_0_TCR_TBI0 BIT_ULL(38) 13962306a36Sopenharmony_ci#define IVPU_MMU_CD_0_AA64 BIT(41) 14062306a36Sopenharmony_ci#define IVPU_MMU_CD_0_S BIT(44) 14162306a36Sopenharmony_ci#define IVPU_MMU_CD_0_R BIT(45) 14262306a36Sopenharmony_ci#define IVPU_MMU_CD_0_A BIT(46) 14362306a36Sopenharmony_ci#define IVPU_MMU_CD_0_ASET BIT(47) 14462306a36Sopenharmony_ci#define IVPU_MMU_CD_0_ASID GENMASK_ULL(63, 48) 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#define IVPU_MMU_T0SZ_48BIT 16 14762306a36Sopenharmony_ci#define IVPU_MMU_T0SZ_38BIT 26 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci#define IVPU_MMU_IPS_48BIT 5 15062306a36Sopenharmony_ci#define IVPU_MMU_IPS_44BIT 4 15162306a36Sopenharmony_ci#define IVPU_MMU_IPS_42BIT 3 15262306a36Sopenharmony_ci#define IVPU_MMU_IPS_40BIT 2 15362306a36Sopenharmony_ci#define IVPU_MMU_IPS_36BIT 1 15462306a36Sopenharmony_ci#define IVPU_MMU_IPS_32BIT 0 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci#define IVPU_MMU_CD_1_TTB0_MASK GENMASK_ULL(51, 4) 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci#define IVPU_MMU_STE_0_S1CDMAX GENMASK_ULL(63, 59) 15962306a36Sopenharmony_ci#define IVPU_MMU_STE_0_S1FMT GENMASK_ULL(5, 4) 16062306a36Sopenharmony_ci#define IVPU_MMU_STE_0_S1FMT_LINEAR 0 16162306a36Sopenharmony_ci#define IVPU_MMU_STE_DWORDS 8 16262306a36Sopenharmony_ci#define IVPU_MMU_STE_0_CFG_S1_TRANS 5 16362306a36Sopenharmony_ci#define IVPU_MMU_STE_0_CFG GENMASK_ULL(3, 1) 16462306a36Sopenharmony_ci#define IVPU_MMU_STE_0_S1CTXPTR_MASK GENMASK_ULL(51, 6) 16562306a36Sopenharmony_ci#define IVPU_MMU_STE_0_V BIT(0) 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci#define IVPU_MMU_STE_1_STRW_NSEL1 0ul 16862306a36Sopenharmony_ci#define IVPU_MMU_STE_1_CONT GENMASK_ULL(16, 13) 16962306a36Sopenharmony_ci#define IVPU_MMU_STE_1_STRW GENMASK_ULL(31, 30) 17062306a36Sopenharmony_ci#define IVPU_MMU_STE_1_PRIVCFG GENMASK_ULL(49, 48) 17162306a36Sopenharmony_ci#define IVPU_MMU_STE_1_PRIVCFG_UNPRIV 2ul 17262306a36Sopenharmony_ci#define IVPU_MMU_STE_1_INSTCFG GENMASK_ULL(51, 50) 17362306a36Sopenharmony_ci#define IVPU_MMU_STE_1_INSTCFG_DATA 2ul 17462306a36Sopenharmony_ci#define IVPU_MMU_STE_1_MEV BIT(19) 17562306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1STALLD BIT(27) 17662306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1C_CACHE_NC 0ul 17762306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1C_CACHE_WBRA 1ul 17862306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1C_CACHE_WT 2ul 17962306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1C_CACHE_WB 3ul 18062306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1CIR GENMASK_ULL(3, 2) 18162306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1COR GENMASK_ULL(5, 4) 18262306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1CSH GENMASK_ULL(7, 6) 18362306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1DSS GENMASK_ULL(1, 0) 18462306a36Sopenharmony_ci#define IVPU_MMU_STE_1_S1DSS_TERMINATE 0x0 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci#define IVPU_MMU_REG_TIMEOUT_US (10 * USEC_PER_MSEC) 18762306a36Sopenharmony_ci#define IVPU_MMU_QUEUE_TIMEOUT_US (100 * USEC_PER_MSEC) 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci#define IVPU_MMU_GERROR_ERR_MASK ((REG_FLD(VPU_37XX_HOST_MMU_GERROR, CMDQ)) | \ 19062306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_MMU_GERROR, EVTQ_ABT)) | \ 19162306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_MMU_GERROR, PRIQ_ABT)) | \ 19262306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_CMDQ_ABT)) | \ 19362306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_EVTQ_ABT)) | \ 19462306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_PRIQ_ABT)) | \ 19562306a36Sopenharmony_ci (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_ABT))) 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic char *ivpu_mmu_event_to_str(u32 cmd) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci switch (cmd) { 20062306a36Sopenharmony_ci case IVPU_MMU_EVT_F_UUT: 20162306a36Sopenharmony_ci return "Unsupported Upstream Transaction"; 20262306a36Sopenharmony_ci case IVPU_MMU_EVT_C_BAD_STREAMID: 20362306a36Sopenharmony_ci return "Transaction StreamID out of range"; 20462306a36Sopenharmony_ci case IVPU_MMU_EVT_F_STE_FETCH: 20562306a36Sopenharmony_ci return "Fetch of STE caused external abort"; 20662306a36Sopenharmony_ci case IVPU_MMU_EVT_C_BAD_STE: 20762306a36Sopenharmony_ci return "Used STE invalid"; 20862306a36Sopenharmony_ci case IVPU_MMU_EVT_F_BAD_ATS_TREQ: 20962306a36Sopenharmony_ci return "Address Request disallowed for a StreamID"; 21062306a36Sopenharmony_ci case IVPU_MMU_EVT_F_STREAM_DISABLED: 21162306a36Sopenharmony_ci return "Transaction marks non-substream disabled"; 21262306a36Sopenharmony_ci case IVPU_MMU_EVT_F_TRANSL_FORBIDDEN: 21362306a36Sopenharmony_ci return "MMU bypass is disallowed for this StreamID"; 21462306a36Sopenharmony_ci case IVPU_MMU_EVT_C_BAD_SUBSTREAMID: 21562306a36Sopenharmony_ci return "Invalid StreamID"; 21662306a36Sopenharmony_ci case IVPU_MMU_EVT_F_CD_FETCH: 21762306a36Sopenharmony_ci return "Fetch of CD caused external abort"; 21862306a36Sopenharmony_ci case IVPU_MMU_EVT_C_BAD_CD: 21962306a36Sopenharmony_ci return "Fetched CD invalid"; 22062306a36Sopenharmony_ci case IVPU_MMU_EVT_F_WALK_EABT: 22162306a36Sopenharmony_ci return " An external abort occurred fetching a TLB"; 22262306a36Sopenharmony_ci case IVPU_MMU_EVT_F_TRANSLATION: 22362306a36Sopenharmony_ci return "Translation fault"; 22462306a36Sopenharmony_ci case IVPU_MMU_EVT_F_ADDR_SIZE: 22562306a36Sopenharmony_ci return " Output address caused address size fault"; 22662306a36Sopenharmony_ci case IVPU_MMU_EVT_F_ACCESS: 22762306a36Sopenharmony_ci return "Access flag fault"; 22862306a36Sopenharmony_ci case IVPU_MMU_EVT_F_PERMISSION: 22962306a36Sopenharmony_ci return "Permission fault occurred on page access"; 23062306a36Sopenharmony_ci case IVPU_MMU_EVT_F_TLB_CONFLICT: 23162306a36Sopenharmony_ci return "A TLB conflict"; 23262306a36Sopenharmony_ci case IVPU_MMU_EVT_F_CFG_CONFLICT: 23362306a36Sopenharmony_ci return "A configuration cache conflict"; 23462306a36Sopenharmony_ci case IVPU_MMU_EVT_E_PAGE_REQUEST: 23562306a36Sopenharmony_ci return "Page request hint from a client device"; 23662306a36Sopenharmony_ci case IVPU_MMU_EVT_F_VMS_FETCH: 23762306a36Sopenharmony_ci return "Fetch of VMS caused external abort"; 23862306a36Sopenharmony_ci default: 23962306a36Sopenharmony_ci return "Unknown CMDQ command"; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic void ivpu_mmu_config_check(struct ivpu_device *vdev) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci u32 val_ref; 24662306a36Sopenharmony_ci u32 val; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if (ivpu_is_simics(vdev)) 24962306a36Sopenharmony_ci val_ref = IVPU_MMU_IDR0_REF_SIMICS; 25062306a36Sopenharmony_ci else 25162306a36Sopenharmony_ci val_ref = IVPU_MMU_IDR0_REF; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci val = REGV_RD32(VPU_37XX_HOST_MMU_IDR0); 25462306a36Sopenharmony_ci if (val != val_ref) 25562306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "IDR0 0x%x != IDR0_REF 0x%x\n", val, val_ref); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci val = REGV_RD32(VPU_37XX_HOST_MMU_IDR1); 25862306a36Sopenharmony_ci if (val != IVPU_MMU_IDR1_REF) 25962306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "IDR1 0x%x != IDR1_REF 0x%x\n", val, IVPU_MMU_IDR1_REF); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci val = REGV_RD32(VPU_37XX_HOST_MMU_IDR3); 26262306a36Sopenharmony_ci if (val != IVPU_MMU_IDR3_REF) 26362306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "IDR3 0x%x != IDR3_REF 0x%x\n", val, IVPU_MMU_IDR3_REF); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (ivpu_is_simics(vdev)) 26662306a36Sopenharmony_ci val_ref = IVPU_MMU_IDR5_REF_SIMICS; 26762306a36Sopenharmony_ci else if (ivpu_is_fpga(vdev)) 26862306a36Sopenharmony_ci val_ref = IVPU_MMU_IDR5_REF_FPGA; 26962306a36Sopenharmony_ci else 27062306a36Sopenharmony_ci val_ref = IVPU_MMU_IDR5_REF; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci val = REGV_RD32(VPU_37XX_HOST_MMU_IDR5); 27362306a36Sopenharmony_ci if (val != val_ref) 27462306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "IDR5 0x%x != IDR5_REF 0x%x\n", val, val_ref); 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic int ivpu_mmu_cdtab_alloc(struct ivpu_device *vdev) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 28062306a36Sopenharmony_ci struct ivpu_mmu_cdtab *cdtab = &mmu->cdtab; 28162306a36Sopenharmony_ci size_t size = IVPU_MMU_CDTAB_ENT_COUNT * IVPU_MMU_CDTAB_ENT_SIZE; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci cdtab->base = dmam_alloc_coherent(vdev->drm.dev, size, &cdtab->dma, GFP_KERNEL); 28462306a36Sopenharmony_ci if (!cdtab->base) 28562306a36Sopenharmony_ci return -ENOMEM; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "CDTAB alloc: dma=%pad size=%zu\n", &cdtab->dma, size); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci return 0; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic int ivpu_mmu_strtab_alloc(struct ivpu_device *vdev) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 29562306a36Sopenharmony_ci struct ivpu_mmu_strtab *strtab = &mmu->strtab; 29662306a36Sopenharmony_ci size_t size = IVPU_MMU_STRTAB_ENT_COUNT * IVPU_MMU_STRTAB_ENT_SIZE; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci strtab->base = dmam_alloc_coherent(vdev->drm.dev, size, &strtab->dma, GFP_KERNEL); 29962306a36Sopenharmony_ci if (!strtab->base) 30062306a36Sopenharmony_ci return -ENOMEM; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci strtab->base_cfg = IVPU_MMU_STRTAB_CFG; 30362306a36Sopenharmony_ci strtab->dma_q = IVPU_MMU_STRTAB_BASE_RA; 30462306a36Sopenharmony_ci strtab->dma_q |= strtab->dma & IVPU_MMU_STRTAB_BASE_ADDR_MASK; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "STRTAB alloc: dma=%pad dma_q=%pad size=%zu\n", 30762306a36Sopenharmony_ci &strtab->dma, &strtab->dma_q, size); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci return 0; 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cistatic int ivpu_mmu_cmdq_alloc(struct ivpu_device *vdev) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 31562306a36Sopenharmony_ci struct ivpu_mmu_queue *q = &mmu->cmdq; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci q->base = dmam_alloc_coherent(vdev->drm.dev, IVPU_MMU_CMDQ_SIZE, &q->dma, GFP_KERNEL); 31862306a36Sopenharmony_ci if (!q->base) 31962306a36Sopenharmony_ci return -ENOMEM; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci q->dma_q = IVPU_MMU_Q_BASE_RWA; 32262306a36Sopenharmony_ci q->dma_q |= q->dma & IVPU_MMU_Q_BASE_ADDR_MASK; 32362306a36Sopenharmony_ci q->dma_q |= IVPU_MMU_Q_COUNT_LOG2; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "CMDQ alloc: dma=%pad dma_q=%pad size=%u\n", 32662306a36Sopenharmony_ci &q->dma, &q->dma_q, IVPU_MMU_CMDQ_SIZE); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci return 0; 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_cistatic int ivpu_mmu_evtq_alloc(struct ivpu_device *vdev) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 33462306a36Sopenharmony_ci struct ivpu_mmu_queue *q = &mmu->evtq; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci q->base = dmam_alloc_coherent(vdev->drm.dev, IVPU_MMU_EVTQ_SIZE, &q->dma, GFP_KERNEL); 33762306a36Sopenharmony_ci if (!q->base) 33862306a36Sopenharmony_ci return -ENOMEM; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci q->dma_q = IVPU_MMU_Q_BASE_RWA; 34162306a36Sopenharmony_ci q->dma_q |= q->dma & IVPU_MMU_Q_BASE_ADDR_MASK; 34262306a36Sopenharmony_ci q->dma_q |= IVPU_MMU_Q_COUNT_LOG2; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "EVTQ alloc: dma=%pad dma_q=%pad size=%u\n", 34562306a36Sopenharmony_ci &q->dma, &q->dma_q, IVPU_MMU_EVTQ_SIZE); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci return 0; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic int ivpu_mmu_structs_alloc(struct ivpu_device *vdev) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci int ret; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci ret = ivpu_mmu_cdtab_alloc(vdev); 35562306a36Sopenharmony_ci if (ret) { 35662306a36Sopenharmony_ci ivpu_err(vdev, "Failed to allocate cdtab: %d\n", ret); 35762306a36Sopenharmony_ci return ret; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci ret = ivpu_mmu_strtab_alloc(vdev); 36162306a36Sopenharmony_ci if (ret) { 36262306a36Sopenharmony_ci ivpu_err(vdev, "Failed to allocate strtab: %d\n", ret); 36362306a36Sopenharmony_ci return ret; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_alloc(vdev); 36762306a36Sopenharmony_ci if (ret) { 36862306a36Sopenharmony_ci ivpu_err(vdev, "Failed to allocate cmdq: %d\n", ret); 36962306a36Sopenharmony_ci return ret; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci ret = ivpu_mmu_evtq_alloc(vdev); 37362306a36Sopenharmony_ci if (ret) 37462306a36Sopenharmony_ci ivpu_err(vdev, "Failed to allocate evtq: %d\n", ret); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci return ret; 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic int ivpu_mmu_reg_write(struct ivpu_device *vdev, u32 reg, u32 val) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci u32 reg_ack = reg + 4; /* ACK register is 4B after base register */ 38262306a36Sopenharmony_ci u32 val_ack; 38362306a36Sopenharmony_ci int ret; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci REGV_WR32(reg, val); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci ret = REGV_POLL(reg_ack, val_ack, (val == val_ack), IVPU_MMU_REG_TIMEOUT_US); 38862306a36Sopenharmony_ci if (ret) 38962306a36Sopenharmony_ci ivpu_err(vdev, "Failed to write register 0x%x\n", reg); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci return ret; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_cistatic int ivpu_mmu_irqs_setup(struct ivpu_device *vdev) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci u32 irq_ctrl = IVPU_MMU_IRQ_EVTQ_EN | IVPU_MMU_IRQ_GERROR_EN; 39762306a36Sopenharmony_ci int ret; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_IRQ_CTRL, 0); 40062306a36Sopenharmony_ci if (ret) 40162306a36Sopenharmony_ci return ret; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci return ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_IRQ_CTRL, irq_ctrl); 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic int ivpu_mmu_cmdq_wait_for_cons(struct ivpu_device *vdev) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci struct ivpu_mmu_queue *cmdq = &vdev->mmu->cmdq; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci return REGV_POLL(VPU_37XX_HOST_MMU_CMDQ_CONS, cmdq->cons, (cmdq->prod == cmdq->cons), 41162306a36Sopenharmony_ci IVPU_MMU_QUEUE_TIMEOUT_US); 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic int ivpu_mmu_cmdq_cmd_write(struct ivpu_device *vdev, const char *name, u64 data0, u64 data1) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci struct ivpu_mmu_queue *q = &vdev->mmu->cmdq; 41762306a36Sopenharmony_ci u64 *queue_buffer = q->base; 41862306a36Sopenharmony_ci int idx = IVPU_MMU_Q_IDX(q->prod) * (IVPU_MMU_CMDQ_CMD_SIZE / sizeof(*queue_buffer)); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci if (!CIRC_SPACE(IVPU_MMU_Q_IDX(q->prod), IVPU_MMU_Q_IDX(q->cons), IVPU_MMU_Q_COUNT)) { 42162306a36Sopenharmony_ci ivpu_err(vdev, "Failed to write MMU CMD %s\n", name); 42262306a36Sopenharmony_ci return -EBUSY; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci queue_buffer[idx] = data0; 42662306a36Sopenharmony_ci queue_buffer[idx + 1] = data1; 42762306a36Sopenharmony_ci q->prod = (q->prod + 1) & IVPU_MMU_Q_WRAP_MASK; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "CMD write: %s data: 0x%llx 0x%llx\n", name, data0, data1); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci return 0; 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistatic int ivpu_mmu_cmdq_sync(struct ivpu_device *vdev) 43562306a36Sopenharmony_ci{ 43662306a36Sopenharmony_ci struct ivpu_mmu_queue *q = &vdev->mmu->cmdq; 43762306a36Sopenharmony_ci u64 val; 43862306a36Sopenharmony_ci int ret; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci val = FIELD_PREP(IVPU_MMU_CMD_OPCODE, CMD_SYNC) | 44162306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CMD_SYNC_0_CS, 0x2) | 44262306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CMD_SYNC_0_MSH, 0x3) | 44362306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CMD_SYNC_0_MSI_ATTR, 0xf); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_cmd_write(vdev, "SYNC", val, 0); 44662306a36Sopenharmony_ci if (ret) 44762306a36Sopenharmony_ci return ret; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci clflush_cache_range(q->base, IVPU_MMU_CMDQ_SIZE); 45062306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_MMU_CMDQ_PROD, q->prod); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_wait_for_cons(vdev); 45362306a36Sopenharmony_ci if (ret) 45462306a36Sopenharmony_ci ivpu_err(vdev, "Timed out waiting for consumer: %d\n", ret); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci return ret; 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic int ivpu_mmu_cmdq_write_cfgi_all(struct ivpu_device *vdev) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci u64 data0 = FIELD_PREP(IVPU_MMU_CMD_OPCODE, CMD_CFGI_ALL); 46262306a36Sopenharmony_ci u64 data1 = FIELD_PREP(IVPU_MMU_CMD_CFGI_1_RANGE, 0x1f); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci return ivpu_mmu_cmdq_cmd_write(vdev, "CFGI_ALL", data0, data1); 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic int ivpu_mmu_cmdq_write_tlbi_nh_asid(struct ivpu_device *vdev, u16 ssid) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci u64 val = FIELD_PREP(IVPU_MMU_CMD_OPCODE, CMD_TLBI_NH_ASID) | 47062306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CMD_TLBI_0_ASID, ssid); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci return ivpu_mmu_cmdq_cmd_write(vdev, "TLBI_NH_ASID", val, 0); 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic int ivpu_mmu_cmdq_write_tlbi_nsnh_all(struct ivpu_device *vdev) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci u64 val = FIELD_PREP(IVPU_MMU_CMD_OPCODE, CMD_TLBI_NSNH_ALL); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci return ivpu_mmu_cmdq_cmd_write(vdev, "TLBI_NSNH_ALL", val, 0); 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic int ivpu_mmu_reset(struct ivpu_device *vdev) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 48562306a36Sopenharmony_ci u32 val; 48662306a36Sopenharmony_ci int ret; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci memset(mmu->cmdq.base, 0, IVPU_MMU_CMDQ_SIZE); 48962306a36Sopenharmony_ci clflush_cache_range(mmu->cmdq.base, IVPU_MMU_CMDQ_SIZE); 49062306a36Sopenharmony_ci mmu->cmdq.prod = 0; 49162306a36Sopenharmony_ci mmu->cmdq.cons = 0; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci memset(mmu->evtq.base, 0, IVPU_MMU_EVTQ_SIZE); 49462306a36Sopenharmony_ci mmu->evtq.prod = 0; 49562306a36Sopenharmony_ci mmu->evtq.cons = 0; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, 0); 49862306a36Sopenharmony_ci if (ret) 49962306a36Sopenharmony_ci return ret; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci val = FIELD_PREP(IVPU_MMU_CR1_TABLE_SH, IVPU_MMU_SH_ISH) | 50262306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CR1_TABLE_OC, IVPU_MMU_CACHE_WB) | 50362306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CR1_TABLE_IC, IVPU_MMU_CACHE_WB) | 50462306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CR1_QUEUE_SH, IVPU_MMU_SH_ISH) | 50562306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CR1_QUEUE_OC, IVPU_MMU_CACHE_WB) | 50662306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CR1_QUEUE_IC, IVPU_MMU_CACHE_WB); 50762306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_MMU_CR1, val); 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci REGV_WR64(VPU_37XX_HOST_MMU_STRTAB_BASE, mmu->strtab.dma_q); 51062306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_MMU_STRTAB_BASE_CFG, mmu->strtab.base_cfg); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci REGV_WR64(VPU_37XX_HOST_MMU_CMDQ_BASE, mmu->cmdq.dma_q); 51362306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_MMU_CMDQ_PROD, 0); 51462306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_MMU_CMDQ_CONS, 0); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci val = IVPU_MMU_CR0_CMDQEN; 51762306a36Sopenharmony_ci ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val); 51862306a36Sopenharmony_ci if (ret) 51962306a36Sopenharmony_ci return ret; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_write_cfgi_all(vdev); 52262306a36Sopenharmony_ci if (ret) 52362306a36Sopenharmony_ci return ret; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_write_tlbi_nsnh_all(vdev); 52662306a36Sopenharmony_ci if (ret) 52762306a36Sopenharmony_ci return ret; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_sync(vdev); 53062306a36Sopenharmony_ci if (ret) 53162306a36Sopenharmony_ci return ret; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci REGV_WR64(VPU_37XX_HOST_MMU_EVTQ_BASE, mmu->evtq.dma_q); 53462306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_MMU_EVTQ_PROD_SEC, 0); 53562306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_MMU_EVTQ_CONS_SEC, 0); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci val |= IVPU_MMU_CR0_EVTQEN; 53862306a36Sopenharmony_ci ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val); 53962306a36Sopenharmony_ci if (ret) 54062306a36Sopenharmony_ci return ret; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci val |= IVPU_MMU_CR0_ATSCHK; 54362306a36Sopenharmony_ci ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val); 54462306a36Sopenharmony_ci if (ret) 54562306a36Sopenharmony_ci return ret; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci ret = ivpu_mmu_irqs_setup(vdev); 54862306a36Sopenharmony_ci if (ret) 54962306a36Sopenharmony_ci return ret; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci val |= IVPU_MMU_CR0_SMMUEN; 55262306a36Sopenharmony_ci return ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val); 55362306a36Sopenharmony_ci} 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_cistatic void ivpu_mmu_strtab_link_cd(struct ivpu_device *vdev, u32 sid) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 55862306a36Sopenharmony_ci struct ivpu_mmu_strtab *strtab = &mmu->strtab; 55962306a36Sopenharmony_ci struct ivpu_mmu_cdtab *cdtab = &mmu->cdtab; 56062306a36Sopenharmony_ci u64 *entry = strtab->base + (sid * IVPU_MMU_STRTAB_ENT_SIZE); 56162306a36Sopenharmony_ci u64 str[2]; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci str[0] = FIELD_PREP(IVPU_MMU_STE_0_CFG, IVPU_MMU_STE_0_CFG_S1_TRANS) | 56462306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_STE_0_S1CDMAX, IVPU_MMU_CDTAB_ENT_COUNT_LOG2) | 56562306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_STE_0_S1FMT, IVPU_MMU_STE_0_S1FMT_LINEAR) | 56662306a36Sopenharmony_ci IVPU_MMU_STE_0_V | 56762306a36Sopenharmony_ci (cdtab->dma & IVPU_MMU_STE_0_S1CTXPTR_MASK); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci str[1] = FIELD_PREP(IVPU_MMU_STE_1_S1DSS, IVPU_MMU_STE_1_S1DSS_TERMINATE) | 57062306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_STE_1_S1CIR, IVPU_MMU_STE_1_S1C_CACHE_NC) | 57162306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_STE_1_S1COR, IVPU_MMU_STE_1_S1C_CACHE_NC) | 57262306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_STE_1_S1CSH, IVPU_MMU_SH_NSH) | 57362306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_STE_1_PRIVCFG, IVPU_MMU_STE_1_PRIVCFG_UNPRIV) | 57462306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_STE_1_INSTCFG, IVPU_MMU_STE_1_INSTCFG_DATA) | 57562306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_STE_1_STRW, IVPU_MMU_STE_1_STRW_NSEL1) | 57662306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_STE_1_CONT, IVPU_MMU_STRTAB_CFG_LOG2SIZE) | 57762306a36Sopenharmony_ci IVPU_MMU_STE_1_MEV | 57862306a36Sopenharmony_ci IVPU_MMU_STE_1_S1STALLD; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci WRITE_ONCE(entry[1], str[1]); 58162306a36Sopenharmony_ci WRITE_ONCE(entry[0], str[0]); 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci clflush_cache_range(entry, IVPU_MMU_STRTAB_ENT_SIZE); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "STRTAB write entry (SSID=%u): 0x%llx, 0x%llx\n", sid, str[0], str[1]); 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_cistatic int ivpu_mmu_strtab_init(struct ivpu_device *vdev) 58962306a36Sopenharmony_ci{ 59062306a36Sopenharmony_ci ivpu_mmu_strtab_link_cd(vdev, IVPU_MMU_STREAM_ID0); 59162306a36Sopenharmony_ci ivpu_mmu_strtab_link_cd(vdev, IVPU_MMU_STREAM_ID3); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci return 0; 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ciint ivpu_mmu_invalidate_tlb(struct ivpu_device *vdev, u16 ssid) 59762306a36Sopenharmony_ci{ 59862306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 59962306a36Sopenharmony_ci int ret = 0; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci mutex_lock(&mmu->lock); 60262306a36Sopenharmony_ci if (!mmu->on) 60362306a36Sopenharmony_ci goto unlock; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_write_tlbi_nh_asid(vdev, ssid); 60662306a36Sopenharmony_ci if (ret) 60762306a36Sopenharmony_ci goto unlock; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_sync(vdev); 61062306a36Sopenharmony_ciunlock: 61162306a36Sopenharmony_ci mutex_unlock(&mmu->lock); 61262306a36Sopenharmony_ci return ret; 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_cistatic int ivpu_mmu_cd_add(struct ivpu_device *vdev, u32 ssid, u64 cd_dma) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 61862306a36Sopenharmony_ci struct ivpu_mmu_cdtab *cdtab = &mmu->cdtab; 61962306a36Sopenharmony_ci u64 *entry; 62062306a36Sopenharmony_ci u64 cd[4]; 62162306a36Sopenharmony_ci int ret = 0; 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci if (ssid > IVPU_MMU_CDTAB_ENT_COUNT) 62462306a36Sopenharmony_ci return -EINVAL; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci entry = cdtab->base + (ssid * IVPU_MMU_CDTAB_ENT_SIZE); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci if (cd_dma != 0) { 62962306a36Sopenharmony_ci cd[0] = FIELD_PREP(IVPU_MMU_CD_0_TCR_T0SZ, IVPU_MMU_T0SZ_48BIT) | 63062306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CD_0_TCR_TG0, 0) | 63162306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CD_0_TCR_IRGN0, 0) | 63262306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CD_0_TCR_ORGN0, 0) | 63362306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CD_0_TCR_SH0, 0) | 63462306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CD_0_TCR_IPS, IVPU_MMU_IPS_48BIT) | 63562306a36Sopenharmony_ci FIELD_PREP(IVPU_MMU_CD_0_ASID, ssid) | 63662306a36Sopenharmony_ci IVPU_MMU_CD_0_TCR_EPD1 | 63762306a36Sopenharmony_ci IVPU_MMU_CD_0_AA64 | 63862306a36Sopenharmony_ci IVPU_MMU_CD_0_R | 63962306a36Sopenharmony_ci IVPU_MMU_CD_0_ASET | 64062306a36Sopenharmony_ci IVPU_MMU_CD_0_V; 64162306a36Sopenharmony_ci cd[1] = cd_dma & IVPU_MMU_CD_1_TTB0_MASK; 64262306a36Sopenharmony_ci cd[2] = 0; 64362306a36Sopenharmony_ci cd[3] = 0x0000000000007444; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci /* For global context generate memory fault on VPU */ 64662306a36Sopenharmony_ci if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) 64762306a36Sopenharmony_ci cd[0] |= IVPU_MMU_CD_0_A; 64862306a36Sopenharmony_ci } else { 64962306a36Sopenharmony_ci memset(cd, 0, sizeof(cd)); 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci WRITE_ONCE(entry[1], cd[1]); 65362306a36Sopenharmony_ci WRITE_ONCE(entry[2], cd[2]); 65462306a36Sopenharmony_ci WRITE_ONCE(entry[3], cd[3]); 65562306a36Sopenharmony_ci WRITE_ONCE(entry[0], cd[0]); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci clflush_cache_range(entry, IVPU_MMU_CDTAB_ENT_SIZE); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "CDTAB %s entry (SSID=%u, dma=%pad): 0x%llx, 0x%llx, 0x%llx, 0x%llx\n", 66062306a36Sopenharmony_ci cd_dma ? "write" : "clear", ssid, &cd_dma, cd[0], cd[1], cd[2], cd[3]); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci mutex_lock(&mmu->lock); 66362306a36Sopenharmony_ci if (!mmu->on) 66462306a36Sopenharmony_ci goto unlock; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_write_cfgi_all(vdev); 66762306a36Sopenharmony_ci if (ret) 66862306a36Sopenharmony_ci goto unlock; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_sync(vdev); 67162306a36Sopenharmony_ciunlock: 67262306a36Sopenharmony_ci mutex_unlock(&mmu->lock); 67362306a36Sopenharmony_ci return ret; 67462306a36Sopenharmony_ci} 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_cistatic int ivpu_mmu_cd_add_gbl(struct ivpu_device *vdev) 67762306a36Sopenharmony_ci{ 67862306a36Sopenharmony_ci int ret; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci ret = ivpu_mmu_cd_add(vdev, 0, vdev->gctx.pgtable.pgd_dma); 68162306a36Sopenharmony_ci if (ret) 68262306a36Sopenharmony_ci ivpu_err(vdev, "Failed to add global CD entry: %d\n", ret); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci return ret; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_cistatic int ivpu_mmu_cd_add_user(struct ivpu_device *vdev, u32 ssid, dma_addr_t cd_dma) 68862306a36Sopenharmony_ci{ 68962306a36Sopenharmony_ci int ret; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci if (ssid == 0) { 69262306a36Sopenharmony_ci ivpu_err(vdev, "Invalid SSID: %u\n", ssid); 69362306a36Sopenharmony_ci return -EINVAL; 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci ret = ivpu_mmu_cd_add(vdev, ssid, cd_dma); 69762306a36Sopenharmony_ci if (ret) 69862306a36Sopenharmony_ci ivpu_err(vdev, "Failed to add CD entry SSID=%u: %d\n", ssid, ret); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci return ret; 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ciint ivpu_mmu_init(struct ivpu_device *vdev) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 70662306a36Sopenharmony_ci int ret; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "Init..\n"); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci drmm_mutex_init(&vdev->drm, &mmu->lock); 71162306a36Sopenharmony_ci ivpu_mmu_config_check(vdev); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci ret = ivpu_mmu_structs_alloc(vdev); 71462306a36Sopenharmony_ci if (ret) 71562306a36Sopenharmony_ci return ret; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci ret = ivpu_mmu_strtab_init(vdev); 71862306a36Sopenharmony_ci if (ret) { 71962306a36Sopenharmony_ci ivpu_err(vdev, "Failed to initialize strtab: %d\n", ret); 72062306a36Sopenharmony_ci return ret; 72162306a36Sopenharmony_ci } 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci ret = ivpu_mmu_cd_add_gbl(vdev); 72462306a36Sopenharmony_ci if (ret) { 72562306a36Sopenharmony_ci ivpu_err(vdev, "Failed to initialize strtab: %d\n", ret); 72662306a36Sopenharmony_ci return ret; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci ret = ivpu_mmu_enable(vdev); 73062306a36Sopenharmony_ci if (ret) { 73162306a36Sopenharmony_ci ivpu_err(vdev, "Failed to resume MMU: %d\n", ret); 73262306a36Sopenharmony_ci return ret; 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci ivpu_dbg(vdev, MMU, "Init done\n"); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci return 0; 73862306a36Sopenharmony_ci} 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ciint ivpu_mmu_enable(struct ivpu_device *vdev) 74162306a36Sopenharmony_ci{ 74262306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 74362306a36Sopenharmony_ci int ret; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci mutex_lock(&mmu->lock); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci mmu->on = true; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci ret = ivpu_mmu_reset(vdev); 75062306a36Sopenharmony_ci if (ret) { 75162306a36Sopenharmony_ci ivpu_err(vdev, "Failed to reset MMU: %d\n", ret); 75262306a36Sopenharmony_ci goto err; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_write_cfgi_all(vdev); 75662306a36Sopenharmony_ci if (ret) 75762306a36Sopenharmony_ci goto err; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_write_tlbi_nsnh_all(vdev); 76062306a36Sopenharmony_ci if (ret) 76162306a36Sopenharmony_ci goto err; 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci ret = ivpu_mmu_cmdq_sync(vdev); 76462306a36Sopenharmony_ci if (ret) 76562306a36Sopenharmony_ci goto err; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci mutex_unlock(&mmu->lock); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci return 0; 77062306a36Sopenharmony_cierr: 77162306a36Sopenharmony_ci mmu->on = false; 77262306a36Sopenharmony_ci mutex_unlock(&mmu->lock); 77362306a36Sopenharmony_ci return ret; 77462306a36Sopenharmony_ci} 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_civoid ivpu_mmu_disable(struct ivpu_device *vdev) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci struct ivpu_mmu_info *mmu = vdev->mmu; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci mutex_lock(&mmu->lock); 78162306a36Sopenharmony_ci mmu->on = false; 78262306a36Sopenharmony_ci mutex_unlock(&mmu->lock); 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic void ivpu_mmu_dump_event(struct ivpu_device *vdev, u32 *event) 78662306a36Sopenharmony_ci{ 78762306a36Sopenharmony_ci u32 ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, event[0]); 78862306a36Sopenharmony_ci u32 op = FIELD_GET(IVPU_MMU_EVT_OP_MASK, event[0]); 78962306a36Sopenharmony_ci u64 fetch_addr = ((u64)event[7]) << 32 | event[6]; 79062306a36Sopenharmony_ci u64 in_addr = ((u64)event[5]) << 32 | event[4]; 79162306a36Sopenharmony_ci u32 sid = event[1]; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci ivpu_err(vdev, "MMU EVTQ: 0x%x (%s) SSID: %d SID: %d, e[2] %08x, e[3] %08x, in addr: 0x%llx, fetch addr: 0x%llx\n", 79462306a36Sopenharmony_ci op, ivpu_mmu_event_to_str(op), ssid, sid, event[2], event[3], in_addr, fetch_addr); 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic u32 *ivpu_mmu_get_event(struct ivpu_device *vdev) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci struct ivpu_mmu_queue *evtq = &vdev->mmu->evtq; 80062306a36Sopenharmony_ci u32 idx = IVPU_MMU_Q_IDX(evtq->cons); 80162306a36Sopenharmony_ci u32 *evt = evtq->base + (idx * IVPU_MMU_EVTQ_CMD_SIZE); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci evtq->prod = REGV_RD32(VPU_37XX_HOST_MMU_EVTQ_PROD_SEC); 80462306a36Sopenharmony_ci if (!CIRC_CNT(IVPU_MMU_Q_IDX(evtq->prod), IVPU_MMU_Q_IDX(evtq->cons), IVPU_MMU_Q_COUNT)) 80562306a36Sopenharmony_ci return NULL; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci evtq->cons = (evtq->cons + 1) & IVPU_MMU_Q_WRAP_MASK; 80862306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_MMU_EVTQ_CONS_SEC, evtq->cons); 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci return evt; 81162306a36Sopenharmony_ci} 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_civoid ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci bool schedule_recovery = false; 81662306a36Sopenharmony_ci u32 *event; 81762306a36Sopenharmony_ci u32 ssid; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci ivpu_dbg(vdev, IRQ, "MMU event queue\n"); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci while ((event = ivpu_mmu_get_event(vdev)) != NULL) { 82262306a36Sopenharmony_ci ivpu_mmu_dump_event(vdev, event); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, event[0]); 82562306a36Sopenharmony_ci if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) 82662306a36Sopenharmony_ci schedule_recovery = true; 82762306a36Sopenharmony_ci else 82862306a36Sopenharmony_ci ivpu_mmu_user_context_mark_invalid(vdev, ssid); 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci if (schedule_recovery) 83262306a36Sopenharmony_ci ivpu_pm_schedule_recovery(vdev); 83362306a36Sopenharmony_ci} 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_civoid ivpu_mmu_irq_gerr_handler(struct ivpu_device *vdev) 83662306a36Sopenharmony_ci{ 83762306a36Sopenharmony_ci u32 gerror_val, gerrorn_val, active; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci ivpu_dbg(vdev, IRQ, "MMU error\n"); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci gerror_val = REGV_RD32(VPU_37XX_HOST_MMU_GERROR); 84262306a36Sopenharmony_ci gerrorn_val = REGV_RD32(VPU_37XX_HOST_MMU_GERRORN); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci active = gerror_val ^ gerrorn_val; 84562306a36Sopenharmony_ci if (!(active & IVPU_MMU_GERROR_ERR_MASK)) 84662306a36Sopenharmony_ci return; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_ABT, active)) 84962306a36Sopenharmony_ci ivpu_warn_ratelimited(vdev, "MMU MSI ABT write aborted\n"); 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_PRIQ_ABT, active)) 85262306a36Sopenharmony_ci ivpu_warn_ratelimited(vdev, "MMU PRIQ MSI ABT write aborted\n"); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_EVTQ_ABT, active)) 85562306a36Sopenharmony_ci ivpu_warn_ratelimited(vdev, "MMU EVTQ MSI ABT write aborted\n"); 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_CMDQ_ABT, active)) 85862306a36Sopenharmony_ci ivpu_warn_ratelimited(vdev, "MMU CMDQ MSI ABT write aborted\n"); 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, PRIQ_ABT, active)) 86162306a36Sopenharmony_ci ivpu_err_ratelimited(vdev, "MMU PRIQ write aborted\n"); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, EVTQ_ABT, active)) 86462306a36Sopenharmony_ci ivpu_err_ratelimited(vdev, "MMU EVTQ write aborted\n"); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, CMDQ, active)) 86762306a36Sopenharmony_ci ivpu_err_ratelimited(vdev, "MMU CMDQ write aborted\n"); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci REGV_WR32(VPU_37XX_HOST_MMU_GERRORN, gerror_val); 87062306a36Sopenharmony_ci} 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ciint ivpu_mmu_set_pgtable(struct ivpu_device *vdev, int ssid, struct ivpu_mmu_pgtable *pgtable) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci return ivpu_mmu_cd_add_user(vdev, ssid, pgtable->pgd_dma); 87562306a36Sopenharmony_ci} 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_civoid ivpu_mmu_clear_pgtable(struct ivpu_device *vdev, int ssid) 87862306a36Sopenharmony_ci{ 87962306a36Sopenharmony_ci ivpu_mmu_cd_add_user(vdev, ssid, 0); /* 0 will clear CD entry */ 88062306a36Sopenharmony_ci} 881